...
 
Commits (12)
......@@ -16,6 +16,7 @@
<junit.version>4.8.2</junit.version>
<jackson.version>1.9.10</jackson.version>
<camel.version>2.17.2</camel.version>
<hornetq.version>2.4.0.Final</hornetq.version>
</properties>
<licenses>
......@@ -220,7 +221,7 @@
<dependency>
<groupId>org.apache</groupId>
<artifactId>jackrabbit-ocm</artifactId>
<version>3.0.0</version>
<version>2.0.1-SNAPSHOT</version>
</dependency>
<dependency>
......@@ -273,6 +274,8 @@
<artifactId>commons-pool</artifactId>
<version>1.5.5</version>
</dependency>
<!-- JMS Dependencies -->
<dependency>
<groupId>javax.jms</groupId>
......@@ -280,6 +283,40 @@
<version>2.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hornetq</groupId>
<artifactId>hornetq-core-client</artifactId>
<version>${hornetq.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.hornetq</groupId>
<artifactId>hornetq-jms-client</artifactId>
<version>${hornetq.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.hornetq</groupId>
<artifactId>hornetq-transports</artifactId>
<version>2.0.0.GA</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.jboss.netty</groupId>
<artifactId>netty</artifactId>
<version>3.1.0.GA</version>
</dependency>
<dependency>
<groupId>org.jboss.javaee</groupId>
<artifactId>jboss-jms-api</artifactId>
<version>1.1.0.GA</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
......
This source diff could not be displayed because it is too large. You can view the blob instead.
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -35,6 +36,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* The purpose of the Cluster manager is to manage all the functions that need to be
......@@ -48,6 +50,8 @@ import org.springframework.scheduling.annotation.Scheduled;
* @author peter
*
*/
@Component
public class ClusterManagerImpl implements ClusterManager {
private static final Logger LOG = LoggerFactory.getLogger(ClusterManagerImpl.class);
......
......@@ -31,9 +31,11 @@ import org.apache.jackrabbit.spi.Event;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.jcr.observation.ObservationManager;
@Component
public class JcrObserver {
private static final Logger logger = LoggerFactory.getLogger(JcrObserver.class);
......
......@@ -48,6 +48,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;
/**
* On startup it will recurse all the boards in Gravity to find rules which have timers.
......@@ -62,6 +63,8 @@ import org.springframework.jms.core.JmsTemplate;
* @author peter
*
*/
@Component
public class TimerManager {
private static final Logger LOG = LoggerFactory.getLogger(TimerManager.class);
......
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -27,7 +28,9 @@ import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
@Component
public class VariableInterpreter {
private static final String VARIABLE_TEMPLATE_TOKEN = "#";
......
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
* Gravity Workflow Automation is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* Gravity Workflow Automation is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Gravity Workflow Automation.
* If not, see <http://www.gnu.org/licenses/>.
*/
package nz.net.orcon.kanban.automation.actions;
import java.util.ArrayList;
......@@ -6,8 +27,8 @@ import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.amazonaws.AmazonWebServiceClient;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.cloudfront.AmazonCloudFrontClient;
......@@ -36,6 +57,7 @@ import com.amazonaws.services.identitymanagement.model.ServerCertificateMetadata
import com.amazonaws.services.identitymanagement.model.UploadServerCertificateRequest;
import com.amazonaws.services.identitymanagement.model.UploadServerCertificateResult;
@Component
public class AwsAutomationAction {
@Autowired
......
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -21,6 +22,9 @@
package nz.net.orcon.kanban.automation.actions;
import org.springframework.stereotype.Component;
@Component
public class CreateVariableAction {
......
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -24,7 +25,9 @@ package nz.net.orcon.kanban.automation.actions;
import java.util.Date;
import org.joda.time.DateTime;
import org.springframework.stereotype.Component;
@Component
public class DateTool {
public Date addDays( Date date, String days){
......
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -47,7 +48,9 @@ import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class EmailReceiverAction {
private static final Logger logger = LoggerFactory.getLogger(EmailReceiverAction.class);
......
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -28,7 +29,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.stereotype.Component;
@Component
public class EmailSenderAction {
private static final Logger logger = LoggerFactory.getLogger(EmailSenderAction.class);
......
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -23,7 +24,9 @@ package nz.net.orcon.kanban.automation.actions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class StringUtils {
private static final Logger logger = LoggerFactory.getLogger(StringUtils.class);
......
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -22,10 +23,12 @@
package nz.net.orcon.kanban.automation.actions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import nz.net.orcon.kanban.automation.ClusterManager;
import nz.net.orcon.kanban.controllers.URI;
@Component
public class UniqueIdAction {
@Autowired
......
......@@ -30,9 +30,11 @@ import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import nz.net.orcon.kanban.model.Action;
@Component
public class ExtractPlugin implements Plugin {
private static final Logger logger = LoggerFactory.getLogger(ExtractPlugin.class);
......
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -28,6 +29,7 @@ import java.util.Locale;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import freemarker.template.Configuration;
import freemarker.template.Template;
......@@ -35,6 +37,7 @@ import freemarker.template.Template;
import nz.net.orcon.kanban.controllers.ResourceController;
import nz.net.orcon.kanban.model.Action;
@Component
public class FreemarkerPlugin implements Plugin {
@Autowired
......
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -32,9 +33,11 @@ import java.util.Map.Entry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import nz.net.orcon.kanban.model.Action;
@Component
public class HttpCallPlugin implements Plugin {
protected static final Logger LOG = LoggerFactory.getLogger(HttpCallPlugin.class);
......
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
* Gravity Workflow Automation is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* Gravity Workflow Automation is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Gravity Workflow Automation.
* If not, see <http://www.gnu.org/licenses/>.
*/
package nz.net.orcon.kanban.automation.plugin;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.amazonaws.util.json.Jackson;
import nz.net.orcon.kanban.model.Action;
@Component(value="jsonPlugin")
public class JsonPlugin implements Plugin {
private static final Logger logger = LoggerFactory.getLogger(JsonPlugin.class);
@Override
public Map<String,Object> process( Action action, Map<String,Object> context ) throws Exception{
Object objectToInject = context.get(action.getResource());
if( action.getMethod() !=null && action.getMethod().equals("list")) {
ArrayList response = Jackson.fromJsonString(objectToInject.toString(), ArrayList.class);
context.put(action.getResponse(), response);
logger.debug("JSON List Stored: " + response.toString());
} else if(action.getMethod() !=null && action.getMethod().equals("map")){
HashMap response = Jackson.fromJsonString(objectToInject.toString(), HashMap.class);
context.put(action.getResponse(), response);
logger.debug("JSON Object Stored: " + response.toString());
} else {
String response = Jackson.toJsonString(objectToInject);
context.put(action.getResponse(), response);
logger.debug("JSON Stored: " + response.toString());
}
return context;
}
}
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -25,6 +26,8 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.springframework.stereotype.Component;
import nz.net.orcon.kanban.model.Action;
/**
......@@ -34,6 +37,8 @@ import nz.net.orcon.kanban.model.Action;
*
* @author peter
*/
@Component
public class MapMapperPlugin implements Plugin {
@Override
......
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -24,6 +25,7 @@ package nz.net.orcon.kanban.automation.plugin;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import nz.net.orcon.kanban.controllers.CardController;
import nz.net.orcon.kanban.model.Action;
......@@ -33,6 +35,8 @@ import nz.net.orcon.kanban.model.Action;
*
* @author peter
*/
@Component
public class MovePlugin implements Plugin {
@Autowired
......
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -25,8 +26,11 @@ import java.lang.reflect.Method;
import java.util.Map;
import java.util.Map.Entry;
import org.springframework.stereotype.Component;
import nz.net.orcon.kanban.model.Action;
@Component
public class ObjectMapperPlugin implements Plugin {
@Override
......
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -24,6 +25,7 @@ package nz.net.orcon.kanban.automation.plugin;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import nz.net.orcon.kanban.controllers.CardController;
import nz.net.orcon.kanban.model.Action;
......@@ -36,6 +38,8 @@ import nz.net.orcon.kanban.model.Action;
*
* @author peter
*/
@Component
public class PersistPlugin implements Plugin {
@Autowired
......
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -23,8 +24,11 @@ package nz.net.orcon.kanban.automation.plugin;
import java.util.Map;
import org.springframework.stereotype.Component;
import nz.net.orcon.kanban.model.Action;
@Component
public class PropertyMapperPlugin implements Plugin {
@Override
......
......@@ -34,11 +34,13 @@ import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import nz.net.orcon.kanban.controllers.ListController;
import nz.net.orcon.kanban.controllers.ResourceController;
import nz.net.orcon.kanban.model.Action;
@Component
public class ScriptPlugin implements Plugin{
private static final Logger log = LoggerFactory.getLogger(ScriptPlugin.class);
......
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -28,6 +29,7 @@ import java.util.Map.Entry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import nz.net.orcon.kanban.automation.VariableInterpreter;
import nz.net.orcon.kanban.controllers.BoardsCache;
......@@ -52,6 +54,8 @@ import nz.net.orcon.kanban.model.Phase;
* @author peter
*
*/
@Component
public class SpawnPlugin implements Plugin {
private static final Logger logger = LoggerFactory.getLogger(SpawnPlugin.class);
......
......@@ -26,6 +26,7 @@ import java.util.Map;
import java.util.Map.Entry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import nz.net.orcon.kanban.controllers.ResourceController;
import nz.net.orcon.kanban.model.Action;
......@@ -38,6 +39,7 @@ import nz.net.orcon.kanban.model.Action;
* @author peter
*
*/
@Component
public class TemplatePlugin implements Plugin {
@Autowired
......
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -27,10 +28,12 @@ import java.util.Map;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import nz.net.orcon.kanban.controllers.ResourceController;
import nz.net.orcon.kanban.model.Action;
//@Component
public class VelocityPlugin implements Plugin {
@Autowired
......
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -27,11 +28,13 @@ import java.util.Map.Entry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.thoughtworks.xstream.XStream;
import nz.net.orcon.kanban.model.Action;
@Component(value="xStreamPlugin")
public class XStreamPlugin implements Plugin {
private static final Logger logger = LoggerFactory.getLogger(XStreamPlugin.class);
......
package nz.net.orcon.kanban.controllers;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Resource;
import org.apache.jackrabbit.ocm.manager.ObjectContentManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import nz.net.orcon.kanban.model.Team;
import nz.net.orcon.kanban.model.User;
import nz.net.orcon.kanban.tools.IdentifierTools;
import nz.net.orcon.kanban.tools.ListTools;
import nz.net.orcon.kanban.tools.OcmMapperFactory;
@Controller
@RequestMapping("/bootstrap")
public class BootStrapController {
private static final Logger logger = LoggerFactory.getLogger(BootStrapController.class);
@Resource(name="ocmFactory")
OcmMapperFactory ocmFactory;
@Autowired
TeamCache teamCache;
@Autowired
TeamController teamController;
@Autowired
private ListTools listTools;
@RequestMapping(value = "", method=RequestMethod.GET)
public @ResponseBody boolean bootstrap() throws Exception {
boolean result = true;
ObjectContentManager ocm = ocmFactory.getOcm();
try {
// Determine if there are new users
Map<String, String> userList = listTools.list(String.format(URI.USER_URI,""), "name", ocm.getSession());
logger.info("Users: " + userList.toString());
result = userList.isEmpty();
if(!userList.containsKey("admin")){
User user = new User();
user.setId("admin");
user.setName("admin");
user.setFirstname("Admin");
user.setSurname("");
user.setEmail("");
user.setKey("password");
String newId = IdentifierTools.getIdFromNamedModelClass(user);
user.setPath(String.format(URI.USER_URI, newId.toString()));
user.setKey(null);
ocm.insert(user);
ocm.save();
logger.info("Bootstrapping New User: "+ user.getName());
}
} finally {
ocm.logout();
}
try{
Team team = teamCache.getItem("administrators");
logger.info("Administration Team Exists");
Map<String,String> ownerList = team.getOwners();
if(!ownerList.isEmpty()){
logger.info("Administration Owners: " + ownerList.toString());
}
Map<String,String> memberList = team.getMembers();
if(!memberList.isEmpty()){
logger.info("Administration Owners: " + memberList.toString());
}
result = false;
} catch( Exception e){
Map<String,String> members = new HashMap<String,String>();
members.put("admin", "ADMIN");
Team team = new Team();
team.setName("Administrators");
team.setMembers(members);
team.setOwners(members);
teamController.createTeam(team);
logger.info("Bootstrapping New Administration Team");
}
return result;
}
}
......@@ -108,8 +108,8 @@ public class CardController {
@Autowired
CardListener cardListener;
//@Autowired
//AutomationEngine automationEngine;
@Autowired
AutomationEngine automationEngine;
@Autowired
private NotificationController notificationController;
......@@ -177,9 +177,8 @@ public class CardController {
CardHolder cardHolder = new CardHolder();
cardHolder.setBoardId(boardId);
cardHolder.setCardId(cardId);
//Map<String, Map<String,Boolean>> explain = automationEngine.explain(cardHolder);
//return explain;
return null;
Map<String, Map<String,Boolean>> explain = automationEngine.explain(cardHolder);
return explain;
}
@PreAuthorize("hasPermission(#boardId, 'BOARD', 'READ,WRITE,ADMIN')")
......@@ -284,6 +283,22 @@ public class CardController {
return card;
}
@RequestMapping(value = "/fields/{templateId}", method=RequestMethod.POST)
public @ResponseBody Card createCardFromFields(@PathVariable String boardId,
@PathVariable String phaseId,
@PathVariable String templateId,
@RequestParam(required=false,defaultValue="white") String color,
@RequestBody Map<String,Object> data) throws Exception {
logger.info(data.toString());
Card card = new Card();
card.setTemplate(templateId);
card.setFields(data);
card.setColor(color);
return createCard(boardId, phaseId, card);
}
@PreAuthorize("hasPermission(#boardId, 'BOARD', 'READ,WRITE,ADMIN')")
@RequestMapping(value = "", method=RequestMethod.GET)
public @ResponseBody Map<String,String> getCardList(@PathVariable String boardId,
......
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
* Gravity Workflow Automation is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* Gravity Workflow Automation is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Gravity Workflow Automation.
* If not, see <http://www.gnu.org/licenses/>.
*/
package nz.net.orcon.kanban.controllers;
import java.util.Map;
import javax.annotation.Resource;
import javax.jcr.Node;
import javax.jcr.Session;
import nz.net.orcon.kanban.automation.CacheInvalidationInterface;
import nz.net.orcon.kanban.model.Card;
import nz.net.orcon.kanban.model.Filter;
import nz.net.orcon.kanban.model.PivotData;
import nz.net.orcon.kanban.model.PivotTable;
import nz.net.orcon.kanban.tools.CardTools;
import nz.net.orcon.kanban.tools.IdentifierTools;
import nz.net.orcon.kanban.tools.ListTools;
import nz.net.orcon.kanban.tools.OcmMapperFactory;
import org.apache.commons.lang.StringUtils;
import org.apache.jackrabbit.ocm.manager.ObjectContentManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/board/{boardId}/pivot")
public class PivotTableController {
private static final Logger logger = LoggerFactory.getLogger(PivotTableController.class);
@Resource(name="ocmFactory")
OcmMapperFactory ocmFactory;
@Autowired
CacheInvalidationInterface cacheInvalidationManager;
@Autowired
CardTools cardTools;
@Autowired
private ListTools listTools;
@Autowired
private ListController listController;
@PreAuthorize("hasPermission(#boardId, 'BOARD', 'ADMIN')")
@RequestMapping(value = "", method=RequestMethod.POST)
public @ResponseBody PivotTable createPivot(@PathVariable String boardId,
@RequestBody PivotTable pivot) throws Exception {
if( pivot.getPath()!=null ){
logger.warn("Attempt to update pivot using POST");
throw new Exception("Attempt to Update PivotTable using POST. Use PUT instead");
}
ObjectContentManager ocm = ocmFactory.getOcm();
try {
listTools.ensurePresence(String.format(URI.PIVOT_TABLE_URI, boardId), "pivots", ocm.getSession());
String newId = IdentifierTools.getIdFromNamedModelClass(pivot);
pivot.setPath(String.format(URI.PIVOT_TABLE_URI, boardId, newId.toString()));
ocm.insert(pivot);
ocm.save();
this.cacheInvalidationManager.invalidate(BoardController.BOARD, boardId);
} finally {
ocm.logout();
}
return pivot;
}
@PreAuthorize("hasPermission(#boardId, 'BOARD', 'ADMIN')")
@RequestMapping(value = "/{pivotId}", method=RequestMethod.PUT)
public @ResponseBody PivotTable updatePivot(@PathVariable String boardId,
@PathVariable String pivotId,
@RequestBody PivotTable pivot) throws Exception {
if( pivot.getPath()==null ){
pivot.setPath(String.format(URI.PIVOT_TABLE_URI, boardId, pivotId));
}
ObjectContentManager ocm = ocmFactory.getOcm();
try {
ocm.update(pivot);
ocm.save();
this.cacheInvalidationManager.invalidate(BoardController.BOARD, boardId);
} finally {
ocm.logout();
}
return pivot;
}
@PreAuthorize("hasPermission(#boardId, 'BOARD', 'READ,WRITE,ADMIN')")
@RequestMapping(value = "/{pivotId}", method=RequestMethod.GET)
public @ResponseBody PivotTable getPivot(@PathVariable String boardId,
@PathVariable String pivotId) throws Exception {
ObjectContentManager ocm = ocmFactory.getOcm();
PivotTable pivot = null;
try {
pivot = (PivotTable) ocm.getObject(Filter.class,String.format(URI.PIVOT_TABLE_URI, boardId, pivotId));
if(pivot==null){
throw new ResourceNotFoundException();
}
} finally {
ocm.logout();
}
return pivot;
}
@PreAuthorize("hasPermission(#boardId, 'BOARD', 'READ,WRITE,ADMIN')")
@RequestMapping(value = "", method=RequestMethod.GET)
public @ResponseBody Map<String,String> listPivots(@PathVariable String boardId) throws Exception {
Session session = ocmFactory.getOcm().getSession();
Map<String,String> result = null;
try {
result = listTools.list(String.format(URI.PIVOT_TABLE_URI, boardId,""), "name", session);
} finally {
session.logout();
}
return result;
}
@PreAuthorize("hasPermission(#boardId, 'BOARD', 'ADMIN')")
@RequestMapping(value = "/{pivotId}", method=RequestMethod.DELETE)
public @ResponseBody void deletePivot(@PathVariable String boardId,
@PathVariable String pivotId) throws Exception {
if( StringUtils.isBlank(pivotId)){
return;
}
ObjectContentManager ocm = ocmFactory.getOcm();
try {
Node node = ocm.getSession().getNode(String.format(URI.PIVOT_TABLE_URI, boardId, pivotId));
if(node==null){
throw new ResourceNotFoundException();
}
node.remove();
ocm.save();
this.cacheInvalidationManager.invalidate(BoardController.BOARD, boardId);
} finally {
ocm.logout();
}
}
@PreAuthorize("hasPermission(#boardId, 'BOARD', 'READ,WRITE,ADMIN')")
@RequestMapping(value = "/{pivotId}/execute", method=RequestMethod.GET)
public @ResponseBody Map<String, Map<String,Number>> executePivot(@PathVariable String boardId,
@PathVariable String pivotId)
throws Exception {
PivotData pivotData = new PivotData();
ObjectContentManager ocm = ocmFactory.getOcm();
try {
PivotTable pivot = (PivotTable) ocm.getObject(Filter.class,String.format(URI.PIVOT_TABLE_URI, boardId, pivotId));
if(pivot==null){
throw new ResourceNotFoundException();
}
// Get raw data with applicable filter
Map<String, String> basicQueryResult = listTools.basicQuery(boardId, null, pivot.getFilter(), "id", ocm);
// Construct the Pivot Data
for( String key : basicQueryResult.keySet() ){
Card card = cardTools.getCard(boardId, key, ocm);
String xAxisValue = card.getFields().get(pivot.getxAxis()).toString();
String yAxisValue = card.getFields().get(pivot.getyAxis()).toString();
Object value = card.getFields().get(pivot.getField());
Number n = 1;
if( value!=null || value instanceof Number){
n = (Number) value;
}
pivotData.addData(xAxisValue,yAxisValue, n);
}
} finally {
ocm.logout();
}
return pivotData.getData();
}
}
......@@ -70,6 +70,7 @@ public class TeamController {
@Autowired
SecurityTool securityTool;
@RequestMapping(value = "", method=RequestMethod.POST)
public @ResponseBody Team createTeam(@RequestBody Team team) throws Exception {
if( team.getPath()!=null ){
......@@ -95,7 +96,7 @@ public class TeamController {
return team;
}
//@PreAuthorize("hasPermission(#teamId, 'TEAM', 'READ,WRITE,ADMIN')")
@PreAuthorize("hasPermission(#teamId, 'TEAM', 'READ,WRITE,ADMIN')")
@RequestMapping(value = "/{teamId}", method=RequestMethod.GET)
public @ResponseBody Team getTeam(@PathVariable String teamId) throws Exception {
return teamCache.getItem(teamId);
......@@ -119,6 +120,7 @@ public class TeamController {
return this.teamCache.list();
}
@PreAuthorize("hasPermission(#teamId, 'TEAM', 'ADMIN')")
@RequestMapping(value = "/{teamId}/owners", method=RequestMethod.POST)
public @ResponseBody void addOwners(@PathVariable String teamId, @RequestBody Map<String,String> roles) throws Exception {
......@@ -142,6 +144,7 @@ public class TeamController {
}
}
@PreAuthorize("hasPermission(#teamId, 'TEAM', 'ADMIN')")
@RequestMapping(value = "/{teamId}/members", method=RequestMethod.POST)
public @ResponseBody void addMembers(@PathVariable String teamId, @RequestBody Map<String,String> roles) throws Exception {
......@@ -166,6 +169,7 @@ public class TeamController {
}
}
@PreAuthorize("hasPermission(#teamId, 'TEAM', 'ADMIN')")
@RequestMapping(value = "/{teamId}/members/{member}", method=RequestMethod.DELETE)
public @ResponseBody void deleteMember(@PathVariable String teamId, @PathVariable String member) throws Exception {
......@@ -186,4 +190,26 @@ public class TeamController {
ocm.logout();
}
}
@PreAuthorize("hasPermission(#teamId, 'TEAM', 'ADMIN')")
@RequestMapping(value = "/{teamId}/owners/{owner}", method=RequestMethod.DELETE)
public @ResponseBody void deleteOwner(@PathVariable String teamId, @PathVariable String owner) throws Exception {
ObjectContentManager ocm = ocmFactory.getOcm();
try{
listTools.ensurePresence(String.format( URI.TEAM_URI, teamId), "members", ocm.getSession());
Node node = ocm.getSession().getNode(String.format(URI.TEAM_OWNERS, teamId, owner));
if( node==null){
throw new ResourceNotFoundException();
}
node.remove();
ocm.save();
this.cacheInvalidationManager.invalidate(TEAM, teamId);
} finally {
ocm.logout();
}
}
}
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -45,6 +46,7 @@ public class URI {
public static final String NOTIFICATIONS_TYPE_MAPPING_URI = "/notifications/%s/mapping";
public static final String NOTIFICATIONS_TYPE_ID_URI = "/notifications/%s/%s";
public static final String MOVE_NOTIFICATION_URI = "%s/notifications/%s/%s";
public static final String PIVOT_TABLE_URI = "/board/%s/pivots/%s";
public static final String RESOURCE_URI = "/board/%s/resources/%s";
public static final String RULE_URI = "/board/%s/rules/%s";
public static final String TEAM_URI = "/team/%s";
......
......@@ -63,7 +63,7 @@ public class UserController {
@Resource(name="ocmFactory")
OcmMapperFactory ocmFactory;
@PreAuthorize("hasPermission('admin', 'TEAM', 'ADMIN')")
@PreAuthorize("hasPermission('administrators', 'TEAM', 'ADMIN')")
@RequestMapping(value = "", method=RequestMethod.POST)
public @ResponseBody User createUser(@RequestBody User user) throws Exception {
if( user.getPath()!=null ){
......@@ -77,13 +77,15 @@ public class UserController {
user.setPath(String.format(URI.USER_URI, newId.toString()));
user.setKey(null);
ocm.insert(user);
ocm.save();
ocm.save();
user.setPasswordhash(null);
} finally {
ocm.logout();
}
return user;
}
@PreAuthorize("hasPermission('administrators', 'TEAM', 'ADMIN')")
@RequestMapping(value = "/{userId}", method=RequestMethod.GET)
public @ResponseBody User getUser(@PathVariable String userId) throws Exception {
......@@ -117,7 +119,7 @@ public class UserController {
return taskList;
}
@PreAuthorize("hasPermission('admin', 'TEAM', 'ADMIN')")
@PreAuthorize("hasPermission('administrators', 'TEAM', 'ADMIN')")
@RequestMapping(value = "/{userId}", method=RequestMethod.DELETE)
public @ResponseBody void deleteUser(@PathVariable String userId) throws Exception {
Session session = ocmFactory.getOcm().getSession();
......@@ -129,6 +131,7 @@ public class UserController {
}
}
@PreAuthorize("hasPermission('administrators', 'TEAM', 'ADMIN')")
@RequestMapping(value = "", method=RequestMethod.GET)
public @ResponseBody Map<String,String> listUsers() throws Exception {
......@@ -171,4 +174,5 @@ public class UserController {
}
return false;
}
}
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -22,7 +23,6 @@
package nz.net.orcon.kanban.model;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.apache.jackrabbit.ocm.manager.enumconverter.EnumTypeConverter;
......
package nz.net.orcon.kanban.model;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* PivotData
*
* The purpose of the PivotData Class is to act as a container for data injected into a pivot table.
*
* @author peter
*
*/
public class PivotData {
Set<String> xAxisSet = new HashSet<String>();
Set<String> yAxisSet = new HashSet<String>();
Map<String, Number> values = new HashMap<String,Number>();
public void addData( String xAxis, String yAxis, Number value ){
xAxisSet.add(xAxis);
yAxisSet.add(yAxis);
String elementKey = xAxis + ":" + yAxis;
if( values.containsKey(elementKey) ){
Number newValue = values.get(elementKey).doubleValue() + value.doubleValue();
values.put(elementKey, newValue);
} else {
values.put(elementKey, value);
}
}
public Map<String, Map<String,Number>> getData() {
Map<String, Map<String,Number>> result = new HashMap<String, Map<String, Number>>();
for( String yAxis : yAxisSet){
Map<String,Number> newLine = new HashMap<String,Number>();
for( String xAxis : xAxisSet ){
String elementKey = xAxis + ":" + yAxis;
Number number = values.get(elementKey);
newLine.put(xAxis, number);
}
result.put(yAxis, newLine);
}
return result;
}
}
package nz.net.orcon.kanban.model;
import java.io.Serializable;
import org.apache.jackrabbit.ocm.mapper.impl.annotation.Field;
import org.apache.jackrabbit.ocm.mapper.impl.annotation.Node;
@Node
public class PivotTable extends AbstractNamedModelClass implements Serializable{
private static final long serialVersionUID = -8796432214417007588L;
@Field
private String filter;
@Field
private String xAxis;
@Field
private String yAxis;
@Field
private String field;
@Field
private PivotType type;
public String getFilter() {
return filter;
}
public void setFilter(String filter) {
this.filter = filter;
}
public String getxAxis() {
return xAxis;
}
public void setxAxis(String xAxis) {
this.xAxis = xAxis;
}
public String getyAxis() {
return yAxis;
}
public void setyAxis(String yAxis) {
this.yAxis = yAxis;
}
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
}
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
* Gravity Workflow Automation is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* Gravity Workflow Automation is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Gravity Workflow Automation.
* If not, see <http://www.gnu.org/licenses/>.
*/
package nz.net.orcon.kanban.model;
public enum PivotType {
COUNT,
SUM,
AVERAGE
}
......@@ -29,7 +29,7 @@ import org.apache.jackrabbit.ocm.mapper.impl.annotation.Collection;
import org.apache.jackrabbit.ocm.mapper.impl.annotation.Node;
@Node
public class Team extends AbstractNamedModelClass implements Serializable {
public class Team extends AbstractNamedModelClass implements Serializable, SecurityRoleEntity {
private static final long serialVersionUID = 167163553039753200L;
......@@ -55,4 +55,9 @@ public class Team extends AbstractNamedModelClass implements Serializable {
return members;
}
@Override
public Map<String, String> getRoles() {
return owners;
}
}
......@@ -72,13 +72,19 @@ public class GravityPermissionEvaluator implements PermissionEvaluator {
try {
Map<String,String> roles = getRolesById(targetType, targetId.toString());
if(roles==null){
LOG.warn("No Roles Found for " + authentication.getName());
return false;
}
List<String> permissions = new ArrayList<String>(Arrays.asList(permission.toString().split(",")));
if(LOG.isDebugEnabled()){
LOG.debug("permissions: " + permissions);
}
return isAuthorised(authentication, roles, permissions);
} catch (Exception e){
LOG.warn("Exception running auth: " + e.getMessage());
LOG.warn("Exception running auth: " + e.getClass().getSimpleName() + " " + e.getMessage());
return false;
}
}
......
......@@ -28,7 +28,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import javax.jcr.Node;
......
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2016 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -40,7 +41,6 @@ import org.apache.jackrabbit.ocm.mapper.Mapper;
import org.apache.jackrabbit.ocm.mapper.impl.annotation.AnnotationMapperImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
public class OcmMapperFactory {
......
......@@ -22,7 +22,7 @@
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="variableInterpreter" class="nz.net.orcon.kanban.automation.VariableInterpreter"/>
<!-- <bean id="variableInterpreter" class="nz.net.orcon.kanban.automation.VariableInterpreter"/> -->
<bean id="listTools" class="nz.net.orcon.kanban.tools.ListTools" >
<property name="dateInterpreter" ref="dateInterpreter" />
......@@ -66,54 +66,18 @@
<entry key="cardController" value-ref="cardController" />
<entry key="notificationController" value-ref="notificationController" />
<entry key="phaseController" value-ref="phaseController" />
<entry key="stringify" value-ref="stringify" />
<entry key="stringify" value-ref="stringUtils" />
<entry key="emailSenderAction" value-ref="emailSenderAction" />
<entry key="emailReceiverAction" value-ref="emailReceiverAction" />
<entry key="uniqueIdAction" value-ref="uniqueIdAction" />
<entry key="dateTool" value-ref="dateTool" />
<entry key="createVariableAction" value-ref="createVariableAction" />
<entry key="clusterManager" value-ref="clusterManager" />
<entry key="clusterManager" value-ref="clusterManagerImpl" />
<entry key="awsAutomation" value-ref="awsAutomationAction" />
</map>
</property>
</bean>
<bean id="persistPlugin" class="nz.net.orcon.kanban.automation.plugin.PersistPlugin" />
<bean id="movePlugin" class="nz.net.orcon.kanban.automation.plugin.MovePlugin" />
<bean id="objectMapperPlugin" class="nz.net.orcon.kanban.automation.plugin.ObjectMapperPlugin" />
<bean id="mapMapperPlugin" class="nz.net.orcon.kanban.automation.plugin.MapMapperPlugin" />
<bean id="xStreamPlugin" class="nz.net.orcon.kanban.automation.plugin.XStreamPlugin" />
<bean id="extractPlugin" class="nz.net.orcon.kanban.automation.plugin.ExtractPlugin" />
<bean id="propertyPlugin" class="nz.net.orcon.kanban.automation.plugin.PropertyMapperPlugin" />
<bean id="scriptPlugin" class="nz.net.orcon.kanban.automation.plugin.ScriptPlugin" />
<bean id="spawnPlugin" class="nz.net.orcon.kanban.automation.plugin.SpawnPlugin" />
<bean id="templatePlugin" class="nz.net.orcon.kanban.automation.plugin.TemplatePlugin" />
<bean id="jcrObserver" class="nz.net.orcon.kanban.automation.JcrObserver"/>
<bean id="timerManager" class="nz.net.orcon.kanban.automation.TimerManager"/>
<bean id="emailSenderAction" class="nz.net.orcon.kanban.automation.actions.EmailSenderAction" />
<bean id="uniqueIdAction" class="nz.net.orcon.kanban.automation.actions.UniqueIdAction" />
<bean id="emailReceiverAction" class="nz.net.orcon.kanban.automation.actions.EmailReceiverAction" />
<bean id="dateTool" class="nz.net.orcon.kanban.automation.actions.DateTool" />
<bean id="stringify" class="nz.net.orcon.kanban.automation.actions.StringUtils"/>
<bean id="createVariableAction" class="nz.net.orcon.kanban.automation.actions.CreateVariableAction"/>
<!--
<bean id="bulletinAdvancedEndpoint"
class="nz.net.orcon.kanban.automation.actions.BulletinAdvancedSmsEndpoint">
......@@ -152,11 +116,6 @@
<constructor-arg ref="awsCredential"/>
</bean>
<bean id="awsAutomationAction" class="nz.net.orcon.kanban.automation.actions.AwsAutomationAction"/>
<!-- Cluster Management -->
<bean id="clusterManager" class="nz.net.orcon.kanban.automation.ClusterManagerImpl"/>
<camel:camelContext>
<!-- and then let Camel use those @Component scanned route builders -->
<camel:contextScan/>
......
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<http use-expressions="true" auto-config="true">
<intercept-url pattern="/spring/**" access="isAuthenticated()" />
<http-basic />
<!-- <form-login /> -->
</http>
<beans:bean id="securityTool" class="nz.net.orcon.kanban.security.SecurityToolImpl"/>
<beans:bean id="nullAuthenticationProvider" class="nz.net.orcon.kanban.security.NullAuthenticationProvider"/>
<beans:bean id="jcrAuthenticationProvider" class="nz.net.orcon.kanban.security.JcrAuthenticationProvider"/>
<beans:bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<beans:property name="permissionEvaluator" ref="gravityPermissionEvaluator"/>
</beans:bean>
<beans:bean id="gravityPermissionEvaluator" class="nz.net.orcon.kanban.security.GravityPermissionEvaluator"/>
<global-method-security pre-post-annotations="enabled">
<expression-handler ref="expressionHandler"/>
</global-method-security>
<authentication-manager>
<authentication-provider ref="jcrAuthenticationProvider"/>
</authentication-manager>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<http use-expressions="true" auto-config="true">
<intercept-url pattern="/spring/bootstrap" access="permitAll()" />
<intercept-url pattern="/spring/**" access="isAuthenticated()" />
<http-basic />
<!-- <form-login /> -->
</http>
<beans:bean id="securityTool" class="nz.net.orcon.kanban.security.SecurityToolImpl"/>
<beans:bean id="nullAuthenticationProvider" class="nz.net.orcon.kanban.security.NullAuthenticationProvider"/>
<beans:bean id="jcrAuthenticationProvider" class="nz.net.orcon.kanban.security.JcrAuthenticationProvider"/>
<beans:bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<beans:property name="permissionEvaluator" ref="gravityPermissionEvaluator"/>
</beans:bean>
<beans:bean id="gravityPermissionEvaluator" class="nz.net.orcon.kanban.security.GravityPermissionEvaluator"/>
<global-method-security pre-post-annotations="enabled">
<expression-handler ref="expressionHandler"/>
</global-method-security>
<authentication-manager>
<authentication-provider ref="jcrAuthenticationProvider"/>
</authentication-manager>
</beans:beans>
\ No newline at end of file
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
*
* This file is part of Gravity Workflow Automation.
*
* Gravity Workflow Automation is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* Gravity Workflow Automation is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Gravity Workflow Automation.
* If not, see <http://www.gnu.org/licenses/>.
*/
package nz.net.orcon.kanban.automation.plugin;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;