diff --git a/pom.xml b/pom.xml
index 2afd360..acca7e2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -41,7 +41,7 @@
com.inteligr8.alfresco
aps-public-rest-api
- 1.2.0
+ 1.2.1
aps1
@@ -184,6 +184,7 @@
jar
public
+ true
@@ -212,6 +213,12 @@
run
+
+ ${aps-model.baseUrl}
+ ${aps-model.authType}
+ ${aps-model.basicAuth.mavenServerId}
+ ${aps-model.appName}
+
${run-it}/pom.xml
@@ -223,6 +230,14 @@
+
+
+
+ inteligr8-releases
+ Inteligr8 Releases
+ https://repos.inteligr8.com/nexus/repository/inteligr8-public
+
+
diff --git a/src/it/deploy-app/pom.xml b/src/it/deploy-app/pom.xml
index d995edd..8f24f58 100644
--- a/src/it/deploy-app/pom.xml
+++ b/src/it/deploy-app/pom.xml
@@ -12,10 +12,6 @@
Deploy App Plugin Tests
-
- FORMS Core
-
-
@@ -24,14 +20,46 @@
@pom.version@
- download-app
- validate
+ download-unpack-app
+ generate-sources
download-app
+ unpack-app
+
+
+ true
+ true
+
+
+
+ translate-app
+ compile
+
+ translate-app
+
+
+ ${project.build.directory}/aps-dev
+
+
+
+ pack-app
+ package
+
+ pack-app
+
+
+ ${project.build.directory}/aps-dev
+ ${project.build.directory}/aps-test
+
+
+
+ deploy-app
+ package
+
deploy-app
- ${aps.app}
+ ${project.build.directory}/aps-test
diff --git a/src/it/download-app/pom.xml b/src/it/download-app/pom.xml
index 6f4c9dd..b191c07 100644
--- a/src/it/download-app/pom.xml
+++ b/src/it/download-app/pom.xml
@@ -12,10 +12,6 @@
Download App Plugin Tests
-
- FORMS Core
-
-
@@ -25,23 +21,19 @@
download-app
- validate
+ generate-sources
download-app
-
- ${aps.app}
-
download-app-other
- validate
+ generate-sources
download-app
- ${aps.app}
- ${basedir}/src/main/app
+ ${basedir}/src/main/aps
@@ -57,8 +49,8 @@
- ${project.build.directory}/app/${aps.app}.zip
- ${basedir}/src/main/app/${aps.app}.zip
+ ${project.build.directory}/aps/${aps-model.appName}.zip
+ ${basedir}/src/main/aps/${aps-model.appName}.zip
diff --git a/src/it/pack-app/pom.xml b/src/it/pack-app/pom.xml
index 5d2a52b..5d26679 100644
--- a/src/it/pack-app/pom.xml
+++ b/src/it/pack-app/pom.xml
@@ -12,10 +12,6 @@
Pack App Plugin Tests
-
- FORMS Core
-
-
@@ -25,24 +21,23 @@
download-unpack-app
- validate
+ generate-sources
download-app
unpack-app
- ${aps.app}
+ true
pack-app
- validate
+ package
pack-app
- ${aps.app}
- ${basedir}/src/main/app
+ ${basedir}
@@ -58,7 +53,7 @@
- ${basedir}/src/main/app/${aps.app}.zip
+ ${basedir}/${aps-model.appName}.zip
diff --git a/src/it/translate-app/pom.xml b/src/it/translate-app/pom.xml
index 0d70c2a..5c38c84 100644
--- a/src/it/translate-app/pom.xml
+++ b/src/it/translate-app/pom.xml
@@ -12,10 +12,6 @@
Translate App Plugin Tests
-
- FORMS Core
-
-
@@ -25,24 +21,24 @@
download-unpack-app
- validate
+ generate-sources
download-app
unpack-app
- ${aps.app}
+ true
+ true
translate-app
- validate
+ compile
translate-app
- ${aps.app}
- ${basedir}/src/main/app
+ ${basedir}/src/main/aps/app
@@ -58,7 +54,7 @@
- ${basedir}/src/main/app/${aps.app}/${aps.app}.json
+ ${basedir}/src/main/aps/app/${aps-model.appName}/${aps-model.appName}.json
diff --git a/src/it/unpack-app/pom.xml b/src/it/unpack-app/pom.xml
index 085b737..7dcc93a 100644
--- a/src/it/unpack-app/pom.xml
+++ b/src/it/unpack-app/pom.xml
@@ -12,10 +12,6 @@
Unpack App Plugin Tests
-
- FORMS Core
-
-
@@ -25,24 +21,20 @@
download-unpack-app
- validate
+ generate-sources
download-app
unpack-app
-
- ${aps.app}
-
unpack-app
- validate
+ process-sources
unpack-app
- ${aps.app}
- ${basedir}/src/main/app
+ ${basedir}/src/main/aps/app
@@ -58,8 +50,8 @@
- ${project.build.directory}/app/${aps.app}/${aps.app}.json
- ${basedir}/src/main/app/${aps.app}/${aps.app}.json
+ ${project.build.directory}/aps/app/${aps-model.appName}/${aps-model.appName}.json
+ ${basedir}/src/main/aps/app/${aps-model.appName}/${aps-model.appName}.json
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/ApsAddressibleGoal.java b/src/main/java/com/inteligr8/maven/aps/modeling/ApsAddressibleGoal.java
deleted file mode 100644
index 5da59ff..0000000
--- a/src/main/java/com/inteligr8/maven/aps/modeling/ApsAddressibleGoal.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.inteligr8.maven.aps.modeling;
-
-import org.apache.maven.plugin.AbstractMojo;
-import org.apache.maven.plugins.annotations.Parameter;
-
-import com.inteligr8.alfresco.activiti.ApsClientConfiguration;
-import com.inteligr8.alfresco.activiti.ApsClientJerseyImpl;
-import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl;
-
-public abstract class ApsAddressibleGoal extends AbstractMojo {
-
- @Parameter( property = "activitiAppBaseUrl", required = true, defaultValue = "http://localhost:8080/activiti-app" )
- protected String activitiAppBaseUrl;
-
- @Parameter( property = "activitiAppAuth", required = true, defaultValue = "BASIC" )
- protected String activitiAppAuthType;
-
- @Parameter( property = "activitiAppBasicUsername", required = false, defaultValue = "admin" )
- protected String activitiAppAuthBasicUsername;
-
- @Parameter( property = "activitiAppBasicPassword", required = false, defaultValue = "admin" )
- protected String activitiAppAuthBasicPassword;
-
- @Parameter( property = "oAuthCode", required = false )
- protected String oauthCode;
-
- @Parameter( property = "oAuthClientId", required = false )
- protected String oauthClientId;
-
- @Parameter( property = "oAuthClientSecret", required = false )
- protected String oauthClientSecret;
-
- @Parameter( property = "oAuthUsername", required = false )
- protected String oauthUsername;
-
- @Parameter( property = "oAuthPassword", required = false )
- protected String oauthPassword;
-
- @Parameter( property = "oAuthTokenUrl", required = false )
- protected String oauthTokenUrl;
-
- private ApsPublicRestApiJerseyImpl api;
-
- public ApsClientConfiguration getApsClientConfiguration() {
- ApsClientConfiguration config = new ApsClientConfiguration();
- config.setBaseUrl(this.activitiAppBaseUrl);
- switch (this.activitiAppAuthType.toUpperCase()) {
- case "BASIC":
- this.getLog().info("Configuring APS with BASIC authentication");
- this.getLog().debug("Username: " + this.activitiAppAuthBasicUsername);
- config.setBasicAuthUsername(this.activitiAppAuthBasicUsername);
- config.setBasicAuthPassword(this.activitiAppAuthBasicPassword);
- break;
- case "OAUTH":
- this.getLog().info("Configuring APS with OAuth authentication");
- this.getLog().debug("OAuth Code: " + this.oauthCode);
- this.getLog().debug("OAuth Client ID: " + this.oauthClientId);
- this.getLog().debug("OAuth Username: " + this.oauthUsername);
- config.setOAuthAuthCode(this.oauthCode);
- config.setOAuthTokenUrl(this.oauthTokenUrl);
- config.setOAuthClientId(this.oauthClientId);
- config.setOAuthClientSecret(this.oauthClientSecret);
- config.setOAuthUsername(this.oauthUsername);
- config.setOAuthPassword(this.oauthPassword);
- break;
- default:
- throw new IllegalArgumentException("The 'activitiAppAuth' configuration must be either 'Basic' or 'OAuth'");
- }
-
- return config;
- }
-
- public synchronized ApsPublicRestApiJerseyImpl getApsApi() {
- if (this.api == null) {
- ApsClientConfiguration config = this.getApsClientConfiguration();
- ApsClientJerseyImpl apsClient = new ApsClientJerseyImpl(config);
- this.api = new ApsPublicRestApiJerseyImpl(apsClient);
- }
-
- return this.api;
- }
-
-}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/ApsAppAccessibleGoal.java b/src/main/java/com/inteligr8/maven/aps/modeling/ApsAppAccessibleGoal.java
deleted file mode 100644
index d59ff31..0000000
--- a/src/main/java/com/inteligr8/maven/aps/modeling/ApsAppAccessibleGoal.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.inteligr8.maven.aps.modeling;
-
-import java.util.List;
-
-import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl;
-import com.inteligr8.alfresco.activiti.api.ModelsApi.ModelType;
-import com.inteligr8.alfresco.activiti.model.Datum;
-import com.inteligr8.alfresco.activiti.model.ResultListDataRepresentation;
-import com.inteligr8.alfresco.activiti.model.Tenant;
-
-public abstract class ApsAppAccessibleGoal extends ApsAddressibleGoal {
-
- protected Long findTenantId() {
- List tenants = this.getApsApi().getAdminApi().getTenants();
- if (tenants == null || tenants.isEmpty())
- return null;
- return tenants.iterator().next().getId();
- }
-
- protected Long findAppByName(String appName) {
- ApsPublicRestApiJerseyImpl api = this.getApsApi();
-
- this.getLog().debug("Searching for APS App with name: " + appName);
- ResultListDataRepresentation results = api.getModelsApi().get(null, null, ModelType.App.getId(), null);
- this.getLog().debug("Found " + results.getTotal() + " APS Apps");
- for (Datum datum : results.getData()) {
- String name = (String)datum.getAdditionalProperties().get("name");
- if (name.equals(appName)) {
- Number id = (Number)datum.getAdditionalProperties().get("id");
- this.getLog().info("Found APS App ID: " + id);
- return id == null ? null : id.longValue();
- }
- }
-
- return null;
- }
-
-}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/ApsFileTranslator.java b/src/main/java/com/inteligr8/maven/aps/modeling/ApsFileTranslator.java
deleted file mode 100644
index 80d4862..0000000
--- a/src/main/java/com/inteligr8/maven/aps/modeling/ApsFileTranslator.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.inteligr8.maven.aps.modeling;
-
-import java.io.File;
-import java.io.IOException;
-
-public interface ApsFileTranslator {
-
- void translateFile(File file, String modelName, Long modelId) throws IOException;
-
-}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/CDATAFlexSection.java b/src/main/java/com/inteligr8/maven/aps/modeling/CDATAFlexSection.java
deleted file mode 100644
index 195b7ba..0000000
--- a/src/main/java/com/inteligr8/maven/aps/modeling/CDATAFlexSection.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.inteligr8.maven.aps.modeling;
-
-import org.w3c.dom.CDATASection;
-import org.w3c.dom.Node;
-
-public class CDATAFlexSection {
-
- private final Node node;
-
- public CDATAFlexSection(Node node) {
- this.node = node;
- }
-
- public String getValue() {
- if (this.node instanceof CDATASection) {
- return ((CDATASection)this.node).getData();
- } else {
- String value = this.node.getTextContent();
- return value == null ? null : this.node.getTextContent().trim();
- }
- }
-
- public void setValue(String value) {
- if (this.node instanceof CDATASection) {
- ((CDATASection)this.node).setData(value);
- } else {
- this.node.setTextContent(value);
- }
- }
-
-}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/TranslateAppGoal.java b/src/main/java/com/inteligr8/maven/aps/modeling/TranslateAppGoal.java
deleted file mode 100644
index faa79ba..0000000
--- a/src/main/java/com/inteligr8/maven/aps/modeling/TranslateAppGoal.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package com.inteligr8.maven.aps.modeling;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.maven.execution.MavenSession;
-import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.MojoFailureException;
-import org.apache.maven.plugins.annotations.Mojo;
-import org.apache.maven.plugins.annotations.Parameter;
-import org.apache.maven.project.MavenProject;
-import org.codehaus.plexus.component.annotations.Component;
-
-@Mojo( name = "translate-app", threadSafe = true )
-@Component( role = org.apache.maven.plugin.Mojo.class )
-public class TranslateAppGoal extends ApsAppAccessibleGoal {
-
- @Parameter( defaultValue = "${project}", readonly = true )
- protected MavenProject project;
-
- @Parameter( defaultValue = "${session}", readonly = true )
- protected MavenSession session;
-
- @Parameter( property = "apsAppName", required = true )
- protected String apsAppName;
-
- @Parameter( property = "sourceDirectory", required = true, defaultValue = "${project.build.directory}/app" )
- protected File sourceDirectory;
-
- @Parameter( property = "targetDirectory", required = false, defaultValue = "${project.build.directory}/app" )
- protected File targetDirectory;
-
- @Parameter( property = "overwrite", required = true, defaultValue = "true" )
- protected boolean overwrite = true;
-
- @Parameter( property = "charset", required = true, defaultValue = "utf-8" )
- protected String charsetName = "utf-8";
-
- @Parameter( property = "skip", required = true, defaultValue = "false" )
- protected boolean skip = false;
-
- @Override
- public void execute() throws MojoExecutionException, MojoFailureException {
- File apsAppDirectory = this.validateApsAppDirectory();
- File newApsAppDirectory = this.validateTargetDirectory();
-
- try {
- if (!apsAppDirectory.equals(newApsAppDirectory)) {
- FileUtils.copyDirectory(apsAppDirectory, newApsAppDirectory);
- apsAppDirectory = newApsAppDirectory;
- }
-
- ApsAppTranslator translator = new ApsAppTranslator(this.apsAppName, apsAppDirectory, this.getApsApi(), true);
- translator.execute();
- } catch (IOException ie) {
- throw new MojoExecutionException("An I/O issue occurred", ie);
- } catch (IllegalArgumentException iae) {
- throw new MojoExecutionException("The input is not supported", iae);
- } catch (IllegalStateException ise) {
- throw new MojoExecutionException("The state of system is not supported", ise);
- }
- }
-
- protected File validateApsAppDirectory() throws MojoExecutionException {
- if (!this.sourceDirectory.exists())
- throw new MojoExecutionException("The 'sourceDirectory' does not exist: " + this.sourceDirectory);
- if (!this.sourceDirectory.isDirectory())
- throw new MojoExecutionException("The 'sourceDirectory' is not a directory: " + this.sourceDirectory);
-
- File appDirectory = new File(this.sourceDirectory, this.apsAppName);
-
- if (!appDirectory.exists())
- throw new MojoExecutionException("The 'apsAppName' does not exist in the 'apsAppsDirectory': " + appDirectory);
- if (!appDirectory.isDirectory())
- throw new MojoExecutionException("The 'apsAppName' is not a directory in the 'apsAppsDirectory': " + appDirectory);
-
- return appDirectory;
- }
-
- protected File validateTargetDirectory() throws MojoExecutionException {
- if (!this.targetDirectory.exists()) {
- this.targetDirectory.mkdirs();
- } else if (!this.targetDirectory.isDirectory()) {
- throw new MojoExecutionException("The 'targetDirectory' is not a directory: " + this.targetDirectory);
- }
-
- File appDirectory = new File(this.targetDirectory, this.apsAppName);
-
- if (!appDirectory.exists()) {
- appDirectory.mkdirs();
- } else if (!appDirectory.isDirectory()) {
- throw new MojoExecutionException("The 'apsAppName' is not a directory in the 'targetDirectory': " + appDirectory);
- }
-
- return appDirectory;
- }
-
-}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/crawler/ApsAppCrawlable.java b/src/main/java/com/inteligr8/maven/aps/modeling/crawler/ApsAppCrawlable.java
new file mode 100644
index 0000000..390da7f
--- /dev/null
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/crawler/ApsAppCrawlable.java
@@ -0,0 +1,13 @@
+package com.inteligr8.maven.aps.modeling.crawler;
+
+public interface ApsAppCrawlable {
+
+ ApsFileTransformer getAppJsonTransformer();
+
+ ApsFileTransformer getProcessJsonTransformer();
+
+ ApsFileTransformer getProcessBpmnTransformer();
+
+ ApsFileTransformer getFormJsonTransformer();
+
+}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/crawler/ApsAppCrawler.java b/src/main/java/com/inteligr8/maven/aps/modeling/crawler/ApsAppCrawler.java
new file mode 100644
index 0000000..9639572
--- /dev/null
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/crawler/ApsAppCrawler.java
@@ -0,0 +1,105 @@
+package com.inteligr8.maven.aps.modeling.crawler;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ApsAppCrawler {
+
+ private final Logger logger = LoggerFactory.getLogger(ApsAppCrawler.class);
+ private final Pattern filenamePattern = Pattern.compile("([^/]+)-([0-9]+)\\.(json|bpmn20\\.xml)");
+ private final String appName;
+ private final File appDirectory;
+ private final File appDescriptor;
+ private final boolean failOnIntegrityViolation;
+
+ public ApsAppCrawler(String apsAppName, File apsAppDirectory, boolean failOnIntegrityViolation) {
+ this.appName = apsAppName;
+ this.appDirectory = apsAppDirectory;
+ this.failOnIntegrityViolation = failOnIntegrityViolation;
+
+ this.appDescriptor = this.validateDescriptor(appDirectory);
+ if (this.logger.isDebugEnabled())
+ this.logger.debug("APS App descriptor found: " + this.appDescriptor);
+ }
+
+ protected File validateDescriptor(File appDirectory) {
+ File appDescriptor = new File(appDirectory, this.appName + ".json");
+
+ if (!appDescriptor.exists())
+ throw new IllegalStateException("The APS App descriptor could not be found: " + appDescriptor);
+ if (!appDescriptor.isFile())
+ throw new IllegalStateException("The APS App descriptor is not a file: " + appDescriptor);
+
+ return appDescriptor;
+ }
+
+ public void execute(ApsAppCrawlable crawlable) throws IOException {
+ this.logger.info("Crawling APS App ...");
+
+ Map processTransformers = new HashMap<>();
+ processTransformers.put("json", crawlable.getProcessJsonTransformer());
+ processTransformers.put("bpmn20.xml", crawlable.getProcessBpmnTransformer());
+ processTransformers.put("bpmn", crawlable.getProcessBpmnTransformer());
+
+ this.transform(crawlable.getAppJsonTransformer(), this.appDescriptor, this.appName, null);
+ this.crawlModels("form-models", crawlable.getFormJsonTransformer());
+ this.crawlModels("bpmn-models", processTransformers);
+ this.crawlModels("bpmn-subprocess-models", crawlable.getProcessJsonTransformer());
+ }
+
+ protected void crawlModels(String modelsDirectoryName, ApsFileTransformer transformer) throws IOException {
+ this.crawlModels(modelsDirectoryName, Collections.singletonMap("json", transformer));
+ }
+
+ protected void crawlModels(String modelsDirectoryName, Map transformers) throws IOException {
+ File modelsDirectory = new File(this.appDirectory, modelsDirectoryName);
+ if (!modelsDirectory.exists()) {
+ this.logger.debug("APS model directory doesn't exist; no models to transform: {}", modelsDirectory);
+ return;
+ }
+
+ for (File modelFile : modelsDirectory.listFiles()) {
+ this.logger.trace("Transforming model: {}", modelFile);
+
+ Matcher matcher = this.filenamePattern.matcher(modelFile.getName());
+ if (!matcher.find()) {
+ this.logger.warn("The '{}' folder has a file with an unexpected filename format; skipping: {}", modelsDirectoryName, modelFile);
+ continue;
+ }
+
+ String ext = matcher.group(3);
+ ApsFileTransformer transformer = transformers.get(ext.toLowerCase());
+ if (transformer == null) {
+ this.logger.warn("The '{}' folder has a file with an unexpected extension; skipping: {}", modelsDirectoryName, modelFile);
+ continue;
+ }
+
+ String modelName = matcher.group(1);
+ Long modelId = new Long(matcher.group(2));
+ this.logger.trace("Transforming model {} ID: {}", modelName, modelId);
+
+ this.transform(transformer, modelFile, modelName, modelId);
+ }
+ }
+
+ private void transform(ApsFileTransformer transformer, File modelFile, String modelName, Long modelId) throws IOException {
+ try {
+ transformer.transformFile(modelFile, modelName, modelId);
+ } catch (IllegalArgumentException | IllegalStateException ie) {
+ if (this.failOnIntegrityViolation) {
+ throw ie;
+ } else {
+ this.logger.warn(ie.getMessage());
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/crawler/ApsFileTransformer.java b/src/main/java/com/inteligr8/maven/aps/modeling/crawler/ApsFileTransformer.java
new file mode 100644
index 0000000..8e9ac56
--- /dev/null
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/crawler/ApsFileTransformer.java
@@ -0,0 +1,10 @@
+package com.inteligr8.maven.aps.modeling.crawler;
+
+import java.io.File;
+import java.io.IOException;
+
+public interface ApsFileTransformer {
+
+ void transformFile(File file, String modelName, Long modelId) throws IOException;
+
+}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsAddressibleGoal.java b/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsAddressibleGoal.java
new file mode 100644
index 0000000..6393015
--- /dev/null
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsAddressibleGoal.java
@@ -0,0 +1,99 @@
+package com.inteligr8.maven.aps.modeling.goal;
+
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.settings.Server;
+
+import com.inteligr8.alfresco.activiti.ApsClientConfiguration;
+import com.inteligr8.alfresco.activiti.ApsClientJerseyImpl;
+import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl;
+
+public abstract class ApsAddressibleGoal extends DisablableGoal {
+
+ @Parameter( defaultValue = "${session}", readonly = true )
+ protected MavenSession session;
+
+ @Parameter( property = "aps-model.baseUrl", required = true, defaultValue = "http://localhost:8080/activiti-app" )
+ protected String activitiAppBaseUrl;
+
+ @Parameter( property = "aps-model.authType", required = true, defaultValue = "BASIC" )
+ protected String activitiAppAuthType;
+
+ @Parameter( property = "aps-model.basicAuth.mavenServerId", required = true, defaultValue = "aps" )
+ protected String activitiAppAuthBasicServerId;
+
+ @Parameter( property = "aps-model.oauth.code", required = false )
+ protected String oauthCode;
+
+ @Parameter( property = "aps-model.oauth.client.mavenServerId", required = false )
+ protected String oauthClientServerId;
+
+ @Parameter( property = "aps-model.oauth.mavenServerId", required = false )
+ protected String oauthServerId;
+
+ @Parameter( property = "aps-model.oauth.tokenUrl", required = false )
+ protected String oauthTokenUrl;
+
+ private ApsPublicRestApiJerseyImpl api;
+
+ public ApsClientConfiguration getApsClientConfiguration() {
+ this.getLog().debug("Configuring APS to URL: " + this.activitiAppBaseUrl);
+ ApsClientConfiguration config = new ApsClientConfiguration();
+ config.setBaseUrl(this.activitiAppBaseUrl);
+ switch (this.activitiAppAuthType.toUpperCase()) {
+ case "BASIC":
+ this.getLog().info("Configuring APS with BASIC authentication");
+
+ Server creds = this.session.getSettings().getServer(this.activitiAppAuthBasicServerId);
+ if (this.activitiAppAuthBasicServerId != null && creds == null)
+ this.getLog().warn("The Maven configuration has no server '" + this.activitiAppAuthBasicServerId + "'; continuing with default credentials");
+
+ if (creds != null) {
+ this.getLog().debug("Username: " + creds.getUsername());
+ config.setBasicAuthUsername(creds.getUsername());
+ config.setBasicAuthPassword(creds.getPassword());
+ }
+ break;
+ case "OAUTH":
+ this.getLog().info("Configuring APS with OAuth authentication");
+
+ Server clientCreds = this.session.getSettings().getServer(this.oauthClientServerId);
+ Server oauthCreds = this.session.getSettings().getServer(this.oauthServerId);
+ if ((this.oauthClientServerId != null || this.oauthServerId != null) && clientCreds == null && oauthCreds == null)
+ this.getLog().warn("The Maven configuration has no server '" + this.oauthClientServerId + "' or '" + this.oauthServerId + "'; continuing without credentials");
+
+ this.getLog().debug("OAuth Code: " + this.oauthCode);
+ config.setOAuthAuthCode(this.oauthCode);
+
+ if (clientCreds != null) {
+ this.getLog().debug("OAuth Client ID: " + clientCreds.getUsername());
+ config.setOAuthClientId(clientCreds.getUsername());
+ config.setOAuthClientSecret(clientCreds.getPassword());
+ }
+
+ if (oauthCreds != null) {
+ this.getLog().debug("OAuth Username: " + oauthCreds.getUsername());
+ config.setOAuthUsername(oauthCreds.getUsername());
+ config.setOAuthPassword(oauthCreds.getPassword());
+ }
+
+ config.setOAuthTokenUrl(this.oauthTokenUrl);
+ break;
+ default:
+ throw new IllegalArgumentException("The 'activitiAppAuthType' configuration must be either 'Basic' or 'OAuth'");
+ }
+
+ return config;
+ }
+
+ public synchronized ApsPublicRestApiJerseyImpl getApsApi() {
+ if (this.api == null) {
+ ApsClientConfiguration config = this.getApsClientConfiguration();
+ ApsClientJerseyImpl apsClient = new ApsClientJerseyImpl(config);
+ this.api = new ApsPublicRestApiJerseyImpl(apsClient);
+ }
+
+ return this.api;
+ }
+
+}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsAppAccessibleGoal.java b/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsAppAccessibleGoal.java
new file mode 100644
index 0000000..489852a
--- /dev/null
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsAppAccessibleGoal.java
@@ -0,0 +1,57 @@
+package com.inteligr8.maven.aps.modeling.goal;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugins.annotations.Parameter;
+
+import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl;
+import com.inteligr8.alfresco.activiti.api.ModelsApi.ModelType;
+import com.inteligr8.alfresco.activiti.model.Datum;
+import com.inteligr8.alfresco.activiti.model.ResultListDataRepresentation;
+import com.inteligr8.alfresco.activiti.model.Tenant;
+
+public abstract class ApsAppAccessibleGoal extends ApsAddressibleGoal {
+
+ @Parameter( property = "aps-model.appName", required = true )
+ protected String apsAppName;
+
+ protected Long findTenantId() {
+ List tenants = this.getApsApi().getAdminApi().getTenants();
+ if (tenants == null || tenants.isEmpty())
+ return null;
+ return tenants.iterator().next().getId();
+ }
+
+ protected Map findAppNameIds() {
+ ApsPublicRestApiJerseyImpl api = this.getApsApi();
+
+ Map apps = new HashMap<>(16);
+
+ this.getLog().debug("Searching for all APS Apps");
+ ResultListDataRepresentation results = api.getModelsApi().get("everyone", null, ModelType.App.getId(), null);
+ this.getLog().debug("Found " + results.getTotal() + " APS Apps");
+ for (Datum datum : results.getData()) {
+ String name = (String)datum.getAdditionalProperties().get("name");
+ Number id = (Number)datum.getAdditionalProperties().get("id");
+ apps.put(name, id.longValue());
+ }
+
+ return apps;
+ }
+
+ protected Long findAppId() throws MojoExecutionException {
+ return this.findAppIdByName(this.apsAppName);
+ }
+
+ protected Long findAppIdByName(String appName) throws MojoExecutionException {
+ Map apps = this.findAppNameIds();
+ Long appId = apps.get(this.apsAppName);
+ if (appId == null)
+ throw new MojoExecutionException("The APS App '' could not be found; valid apps: " + apps.keySet());
+ return appId;
+ }
+
+}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsAppGoal.java b/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsAppGoal.java
new file mode 100644
index 0000000..e60b081
--- /dev/null
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsAppGoal.java
@@ -0,0 +1,10 @@
+package com.inteligr8.maven.aps.modeling.goal;
+
+import org.apache.maven.plugins.annotations.Parameter;
+
+public abstract class ApsAppGoal extends DisablableGoal {
+
+ @Parameter( property = "aps-model.appName", required = true )
+ protected String apsAppName;
+
+}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/ApsInfoGoal.java b/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsInfoGoal.java
similarity index 85%
rename from src/main/java/com/inteligr8/maven/aps/modeling/ApsInfoGoal.java
rename to src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsInfoGoal.java
index 07b8d01..d3764d5 100644
--- a/src/main/java/com/inteligr8/maven/aps/modeling/ApsInfoGoal.java
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsInfoGoal.java
@@ -1,4 +1,4 @@
-package com.inteligr8.maven.aps.modeling;
+package com.inteligr8.maven.aps.modeling.goal;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
@@ -12,7 +12,7 @@ import com.inteligr8.alfresco.activiti.model.AppVersion;
public class ApsInfoGoal extends ApsAddressibleGoal {
@Override
- public void execute() throws MojoExecutionException, MojoFailureException {
+ public void executeEnabled() throws MojoExecutionException, MojoFailureException {
AppVersion version = this.getApsApi()
.getAppVersionApi()
.get();
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/DeployAppGoal.java b/src/main/java/com/inteligr8/maven/aps/modeling/goal/DeployAppGoal.java
similarity index 61%
rename from src/main/java/com/inteligr8/maven/aps/modeling/DeployAppGoal.java
rename to src/main/java/com/inteligr8/maven/aps/modeling/goal/DeployAppGoal.java
index 07eee07..2f8540e 100644
--- a/src/main/java/com/inteligr8/maven/aps/modeling/DeployAppGoal.java
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/DeployAppGoal.java
@@ -1,16 +1,19 @@
-package com.inteligr8.maven.aps.modeling;
+package com.inteligr8.maven.aps.modeling.goal;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
+import javax.ws.rs.core.MediaType;
+
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.codehaus.plexus.component.annotations.Component;
-import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
+import org.glassfish.jersey.media.multipart.FormDataMultiPart;
+import org.glassfish.jersey.media.multipart.file.StreamDataBodyPart;
import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl;
import com.inteligr8.alfresco.activiti.model.AppDefinitionUpdateResultRepresentation;
@@ -19,43 +22,39 @@ import com.inteligr8.alfresco.activiti.model.AppDefinitionUpdateResultRepresenta
@Component( role = org.apache.maven.plugin.Mojo.class )
public class DeployAppGoal extends ApsAppAccessibleGoal {
- @Parameter( property = "apsAppName", required = true )
- protected String apsAppName;
-
- @Parameter( property = "sourceDirectory", required = true, defaultValue = "${project.build.directory}/app" )
- protected File sourceDirectory;
+ @Parameter( property = "aps-model.upload.directory", required = true, defaultValue = "${project.build.directory}/aps" )
+ protected File zipDirectory;
@Parameter( property = "publish", required = true, defaultValue = "false" )
protected boolean publish = false;
- @Parameter( property = "skip", required = true, defaultValue = "false" )
- protected boolean skip = false;
-
protected final int bufferSize = 128 * 1024;
+ private final MediaType zipMediaType = MediaType.valueOf("application/zip");
@Override
- public void execute() throws MojoExecutionException, MojoFailureException {
+ public void executeEnabled() throws MojoExecutionException, MojoFailureException {
File sourceFile = this.validateSourceDirectory();
+ Long appId = this.findAppId();
+
try {
- Long appId = this.findAppByName(this.apsAppName);
this.uploadApp(appId, sourceFile);
} catch (IOException ie) {
- throw new MojoExecutionException("The downloaded APS App could not be unpacked", ie);
+ throw new MojoExecutionException("The APS App could not be uploaded", ie);
}
}
protected File validateSourceDirectory() {
- if (!this.sourceDirectory.exists()) {
- throw new IllegalStateException("The 'sourceDirectory' does not exist: " + this.sourceDirectory);
- } else if (!this.sourceDirectory.isDirectory()) {
- throw new IllegalStateException("The 'sourceDirectory' is not a directory: " + this.sourceDirectory);
+ if (!this.zipDirectory.exists()) {
+ throw new IllegalStateException("The 'zipDirectory' does not exist: " + this.zipDirectory);
+ } else if (!this.zipDirectory.isDirectory()) {
+ throw new IllegalStateException("The 'zipDirectory' is not a directory: " + this.zipDirectory);
}
- File sourceFile = new File(this.sourceDirectory, this.apsAppName + ".zip");
+ File sourceFile = new File(this.zipDirectory, this.apsAppName + ".zip");
if (!sourceFile.exists()) {
- throw new IllegalStateException("The App file does not exists in the 'sourceDirectory': " + sourceFile);
+ throw new IllegalStateException("The App file does not exists in the 'zipDirectory': " + sourceFile);
} else if (!sourceFile.isFile()) {
throw new IllegalStateException("The App file is not a file: " + sourceFile);
}
@@ -66,33 +65,31 @@ public class DeployAppGoal extends ApsAppAccessibleGoal {
private void uploadApp(Long appId, File appZip) throws IOException, MojoExecutionException {
ApsPublicRestApiJerseyImpl api = this.getApsApi();
- FormDataContentDisposition cdisposition = FormDataContentDisposition.name("file")
- .size(appZip.length())
- .fileName(appZip.getName())
- .build();
-
FileInputStream fistream = new FileInputStream(appZip);
BufferedInputStream bistream = new BufferedInputStream(fistream, this.bufferSize);
try {
+ FormDataMultiPart multipart = new FormDataMultiPart();
+ multipart.bodyPart(new StreamDataBodyPart("file", bistream, appZip.getName(), this.zipMediaType));
+
if (appId == null) {
if (this.publish) {
this.getLog().info("Uploading & publishing new APS App: " + this.apsAppName);
- AppDefinitionUpdateResultRepresentation appDefUpdate = api.getAppDefinitionsJerseyApi().publishApp(bistream, cdisposition);
+ AppDefinitionUpdateResultRepresentation appDefUpdate = api.getAppDefinitionsJerseyApi().publishApp(multipart);
if (Boolean.TRUE.equals(appDefUpdate.getError()))
throw new MojoExecutionException(appDefUpdate.getErrorDescription());
} else {
this.getLog().info("Uploading new APS App: " + this.apsAppName);
- api.getAppDefinitionsJerseyApi().import_(bistream, cdisposition);
+ api.getAppDefinitionsJerseyApi().importApp(multipart, true);
}
} else {
if (this.publish) {
- this.getLog().info("Uploading, versioning, & publishing APS App: " + this.apsAppName);
- AppDefinitionUpdateResultRepresentation appDefUpdate = api.getAppDefinitionsJerseyApi().publishApp(appId, bistream, cdisposition);
+ this.getLog().info("Uploading, versioning, & publishing APS App: " + this.apsAppName + " (" + appId + ")");
+ AppDefinitionUpdateResultRepresentation appDefUpdate = api.getAppDefinitionsJerseyApi().publishApp(appId, multipart);
if (Boolean.TRUE.equals(appDefUpdate.getError()))
throw new MojoExecutionException(appDefUpdate.getErrorDescription());
} else {
- this.getLog().info("Uploading & versioning APS App: " + this.apsAppName);
- api.getAppDefinitionsJerseyApi().import_(appId, bistream, cdisposition);
+ this.getLog().info("Uploading & versioning APS App: " + this.apsAppName + " (" + appId + ")");
+ api.getAppDefinitionsJerseyApi().importApp(appId, multipart, true);
}
}
} finally {
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/goal/DisablableGoal.java b/src/main/java/com/inteligr8/maven/aps/modeling/goal/DisablableGoal.java
new file mode 100644
index 0000000..ba1c368
--- /dev/null
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/DisablableGoal.java
@@ -0,0 +1,29 @@
+package com.inteligr8.maven.aps.modeling.goal;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.Parameter;
+
+public abstract class DisablableGoal extends AbstractMojo {
+
+ @Parameter( property = "aps-model.skip", required = true, defaultValue = "false" )
+ protected boolean skip = false;
+
+ protected boolean isEnabled() {
+ return !this.skip;
+ }
+
+ protected boolean isDisabled() {
+ return this.skip;
+ }
+
+ @Override
+ public final void execute() throws MojoExecutionException, MojoFailureException {
+ if (this.isEnabled())
+ this.executeEnabled();
+ }
+
+ public abstract void executeEnabled() throws MojoExecutionException, MojoFailureException;
+
+}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/DownloadAppGoal.java b/src/main/java/com/inteligr8/maven/aps/modeling/goal/DownloadAppGoal.java
similarity index 61%
rename from src/main/java/com/inteligr8/maven/aps/modeling/DownloadAppGoal.java
rename to src/main/java/com/inteligr8/maven/aps/modeling/goal/DownloadAppGoal.java
index ce95e70..3b7001b 100644
--- a/src/main/java/com/inteligr8/maven/aps/modeling/DownloadAppGoal.java
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/DownloadAppGoal.java
@@ -1,4 +1,4 @@
-package com.inteligr8.maven.aps.modeling;
+package com.inteligr8.maven.aps.modeling.goal;
import java.io.File;
import java.io.IOException;
@@ -16,23 +16,17 @@ import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl;
@Component( role = org.apache.maven.plugin.Mojo.class )
public class DownloadAppGoal extends ApsAppAccessibleGoal {
- @Parameter( property = "apsAppName", required = true )
- protected String apsAppName;
-
- @Parameter( property = "targetDirectory", required = true, defaultValue = "${project.build.directory}/app" )
- protected File targetDirectory;
-
- @Parameter( property = "skip", required = true, defaultValue = "false" )
- protected boolean skip = false;
+ @Parameter( property = "aps-model.download.directory", required = true, defaultValue = "${project.build.directory}/aps" )
+ protected File zipDirectory;
@Override
- public void execute() throws MojoExecutionException, MojoFailureException {
+ public void executeEnabled() throws MojoExecutionException, MojoFailureException {
this.validateTargetDirectory();
- long appId = this.findAppByName(this.apsAppName);
+ Long appId = this.findAppId();
File appZip = this.downloadApp(appId);
- File toAppZip = new File(this.targetDirectory, this.apsAppName + ".zip");
+ File toAppZip = new File(this.zipDirectory, this.apsAppName + ".zip");
if (toAppZip.exists())
toAppZip.delete();
@@ -44,10 +38,10 @@ public class DownloadAppGoal extends ApsAppAccessibleGoal {
}
protected void validateTargetDirectory() {
- if (!this.targetDirectory.exists()) {
- this.getLog().debug("Creating APS Apps directory: " + this.targetDirectory);
- this.targetDirectory.mkdirs();
- } else if (!this.targetDirectory.isDirectory()) {
+ if (!this.zipDirectory.exists()) {
+ this.getLog().debug("Creating APS Apps directory: " + this.zipDirectory);
+ this.zipDirectory.mkdirs();
+ } else if (!this.zipDirectory.isDirectory()) {
throw new IllegalStateException("The 'targetDirectory' refers to a file and not a directory");
}
}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/PackAppGoal.java b/src/main/java/com/inteligr8/maven/aps/modeling/goal/PackAppGoal.java
similarity index 65%
rename from src/main/java/com/inteligr8/maven/aps/modeling/PackAppGoal.java
rename to src/main/java/com/inteligr8/maven/aps/modeling/goal/PackAppGoal.java
index fb24f77..69bf6c1 100644
--- a/src/main/java/com/inteligr8/maven/aps/modeling/PackAppGoal.java
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/PackAppGoal.java
@@ -1,4 +1,4 @@
-package com.inteligr8.maven.aps.modeling;
+package com.inteligr8.maven.aps.modeling.goal;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
@@ -12,7 +12,6 @@ import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.commons.io.IOUtils;
-import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
@@ -21,24 +20,18 @@ import org.codehaus.plexus.component.annotations.Component;
@Mojo( name = "pack-app", threadSafe = true )
@Component( role = org.apache.maven.plugin.Mojo.class )
-public class PackAppGoal extends AbstractMojo {
+public class PackAppGoal extends ApsAppGoal {
- @Parameter( property = "apsAppName", required = true )
- protected String apsAppName;
-
- @Parameter( property = "sourceDirectory", required = true, defaultValue = "${project.build.directory}/app" )
- protected File sourceDirectory;
-
- @Parameter( property = "targetDirectory", required = true, defaultValue = "${project.build.directory}/app" )
- protected File targetDirectory;
+ @Parameter( property = "aps-model.app.directory", required = true, defaultValue = "${project.build.directory}/aps/app" )
+ protected File unzipDirectory;
- @Parameter( property = "skip", required = true, defaultValue = "false" )
- protected boolean skip = false;
+ @Parameter( property = "aps-model.upload.directory", required = true, defaultValue = "${project.build.directory}/aps" )
+ protected File zipDirectory;
protected final int bufferSize = 128 * 1024;
@Override
- public void execute() throws MojoExecutionException, MojoFailureException {
+ public void executeEnabled() throws MojoExecutionException, MojoFailureException {
this.validateSourceDirectory();
File appDirectory = this.validateAppDirectory();
@@ -52,17 +45,17 @@ public class PackAppGoal extends AbstractMojo {
}
protected void validateSourceDirectory() {
- if (!this.sourceDirectory.exists()) {
- throw new IllegalStateException("The 'sourceDirectory' does not exist: " + this.sourceDirectory);
- } else if (!this.sourceDirectory.isDirectory()) {
- throw new IllegalStateException("The 'sourceDirectory' is not a directory: " + this.sourceDirectory);
+ if (!this.unzipDirectory.exists()) {
+ throw new IllegalStateException("The 'unzipDirectory' does not exist: " + this.unzipDirectory);
+ } else if (!this.unzipDirectory.isDirectory()) {
+ throw new IllegalStateException("The 'unzipDirectory' is not a directory: " + this.unzipDirectory);
}
}
protected File validateAppDirectory() {
- File appDirectory = new File(this.sourceDirectory, this.apsAppName);
+ File appDirectory = new File(this.unzipDirectory, this.apsAppName);
if (!appDirectory.exists()) {
- throw new IllegalStateException("The 'apsAppName' does not exist in the source directory: " + this.sourceDirectory);
+ throw new IllegalStateException("The 'apsAppName' does not exist in the source directory: " + this.unzipDirectory);
} else if (!appDirectory.isDirectory()) {
throw new IllegalStateException("The 'apsAppName' refers to a file and not a directory: " + appDirectory);
}
@@ -71,19 +64,19 @@ public class PackAppGoal extends AbstractMojo {
}
protected File validateTargetDirectory() {
- if (!this.targetDirectory.exists()) {
- this.getLog().debug("The 'targetDirectory' does not exist; creating: " + this.targetDirectory);
- this.targetDirectory.mkdirs();
- } else if (!this.targetDirectory.isDirectory()) {
- throw new IllegalStateException("The 'targetDirectory' is not a directory: " + this.targetDirectory);
+ if (!this.zipDirectory.exists()) {
+ this.getLog().debug("The 'zipDirectory' does not exist; creating: " + this.zipDirectory);
+ this.zipDirectory.mkdirs();
+ } else if (!this.zipDirectory.isDirectory()) {
+ throw new IllegalStateException("The 'zipDirectory' is not a directory: " + this.zipDirectory);
}
- File targetFile = new File(this.targetDirectory, this.apsAppName + ".zip");
+ File targetFile = new File(this.zipDirectory, this.apsAppName + ".zip");
if (targetFile.isDirectory()) {
throw new IllegalStateException("The App file is not a file: " + targetFile);
} else if (targetFile.exists()) {
- this.getLog().debug("The App file in the 'targetDirectory' exists; deleting: " + targetFile);
+ this.getLog().debug("The App file in the 'zipDirectory' exists; deleting: " + targetFile);
targetFile.delete();
}
@@ -99,6 +92,7 @@ public class PackAppGoal extends AbstractMojo {
ZipOutputStream zostream = new ZipOutputStream(bostream);
try {
this.zipDirectory(appDirectory, null, zostream);
+ zostream.flush();
} finally {
zostream.close();
}
@@ -125,7 +119,8 @@ public class PackAppGoal extends AbstractMojo {
this.getLog().debug("Packing APS file: " + path);
- ZipEntry zentry = new ZipEntry(path.toString());
+ // Activit App processing requires forward slashes (WOW)
+ ZipEntry zentry = new ZipEntry(path.toString().replace('\\', '/'));
zostream.putNextEntry(zentry);
try {
FileInputStream fistream = new FileInputStream(file);
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/goal/TranslateAppGoal.java b/src/main/java/com/inteligr8/maven/aps/modeling/goal/TranslateAppGoal.java
new file mode 100644
index 0000000..126a899
--- /dev/null
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/TranslateAppGoal.java
@@ -0,0 +1,91 @@
+package com.inteligr8.maven.aps.modeling.goal;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.codehaus.plexus.component.annotations.Component;
+
+import com.inteligr8.maven.aps.modeling.crawler.ApsAppCrawler;
+import com.inteligr8.maven.aps.modeling.translator.ApsAppTranslator;
+
+@Mojo( name = "translate-app", threadSafe = true )
+@Component( role = org.apache.maven.plugin.Mojo.class )
+public class TranslateAppGoal extends ApsAppAccessibleGoal {
+
+ @Parameter( property = "aps-model.app.directory", required = true, defaultValue = "${project.build.directory}/aps/app" )
+ protected File unzipDirectory;
+
+ @Parameter( property = "aps-model.translatedApp.directory", required = false, defaultValue = "${project.build.directory}/aps/app" )
+ protected File finalDirectory;
+
+ @Parameter( property = "aps-model.translate.overwrite", required = true, defaultValue = "true" )
+ protected boolean overwrite = true;
+
+ @Parameter( property = "aps-model.translate.charset", required = true, defaultValue = "utf-8" )
+ protected String charsetName = "utf-8";
+
+ @Override
+ public void executeEnabled() throws MojoExecutionException, MojoFailureException {
+ File apsAppDirectory = this.validateApsAppDirectory();
+ File newApsAppDirectory = this.validateTargetDirectory();
+
+ try {
+ if (!apsAppDirectory.equals(newApsAppDirectory)) {
+ FileUtils.copyDirectory(apsAppDirectory, newApsAppDirectory);
+ apsAppDirectory = newApsAppDirectory;
+ }
+
+ ApsAppTranslator translator = new ApsAppTranslator(apsAppDirectory, this.getApsApi());
+ translator.buildIndexes();
+
+ ApsAppCrawler crawler = new ApsAppCrawler(this.apsAppName, apsAppDirectory, true);
+ crawler.execute(translator);
+ } catch (IOException ie) {
+ throw new MojoExecutionException("An I/O issue occurred", ie);
+ } catch (IllegalArgumentException iae) {
+ throw new MojoExecutionException("The input is not supported", iae);
+ } catch (IllegalStateException ise) {
+ throw new MojoExecutionException("The state of system is not supported", ise);
+ }
+ }
+
+ protected File validateApsAppDirectory() throws MojoExecutionException {
+ if (!this.unzipDirectory.exists())
+ throw new MojoExecutionException("The 'unzipDirectory' does not exist: " + this.unzipDirectory);
+ if (!this.unzipDirectory.isDirectory())
+ throw new MojoExecutionException("The 'unzipDirectory' is not a directory: " + this.unzipDirectory);
+
+ File appDirectory = new File(this.unzipDirectory, this.apsAppName);
+
+ if (!appDirectory.exists())
+ throw new MojoExecutionException("The 'apsAppName' does not exist in the 'unzipDirectory': " + appDirectory);
+ if (!appDirectory.isDirectory())
+ throw new MojoExecutionException("The 'apsAppName' is not a directory in the 'unzipDirectory': " + appDirectory);
+
+ return appDirectory;
+ }
+
+ protected File validateTargetDirectory() throws MojoExecutionException {
+ if (!this.finalDirectory.exists()) {
+ this.finalDirectory.mkdirs();
+ } else if (!this.finalDirectory.isDirectory()) {
+ throw new MojoExecutionException("The 'finalDirectory' is not a directory: " + this.finalDirectory);
+ }
+
+ File appDirectory = new File(this.finalDirectory, this.apsAppName);
+
+ if (!appDirectory.exists()) {
+ appDirectory.mkdirs();
+ } else if (!appDirectory.isDirectory()) {
+ throw new MojoExecutionException("The 'apsAppName' is not a directory in the 'finalDirectory': " + appDirectory);
+ }
+
+ return appDirectory;
+ }
+
+}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/UnpackAppGoal.java b/src/main/java/com/inteligr8/maven/aps/modeling/goal/UnpackAppGoal.java
similarity index 58%
rename from src/main/java/com/inteligr8/maven/aps/modeling/UnpackAppGoal.java
rename to src/main/java/com/inteligr8/maven/aps/modeling/goal/UnpackAppGoal.java
index ed755e0..062e68e 100644
--- a/src/main/java/com/inteligr8/maven/aps/modeling/UnpackAppGoal.java
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/UnpackAppGoal.java
@@ -1,4 +1,4 @@
-package com.inteligr8.maven.aps.modeling;
+package com.inteligr8.maven.aps.modeling.goal;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
@@ -10,43 +10,53 @@ import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.xml.transform.TransformerException;
import org.apache.commons.io.IOUtils;
-import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.codehaus.plexus.component.annotations.Component;
+import org.w3c.dom.Document;
import org.xml.sax.SAXException;
+import com.inteligr8.maven.aps.modeling.crawler.ApsAppCrawler;
+import com.inteligr8.maven.aps.modeling.normalizer.ApsAppNormalizer;
+import com.inteligr8.maven.aps.modeling.util.ModelUtil;
+
@Mojo( name = "unpack-app", threadSafe = true )
@Component( role = org.apache.maven.plugin.Mojo.class )
-public class UnpackAppGoal extends AbstractMojo {
+public class UnpackAppGoal extends ApsAppGoal {
- @Parameter( property = "apsAppName", required = true )
- protected String apsAppName;
+ @Parameter( property = "aps-model.download.directory", required = true, defaultValue = "${project.build.directory}/aps" )
+ protected File zipDirectory;
- @Parameter( property = "sourceDirectory", required = true, defaultValue = "${project.build.directory}/app" )
- protected File sourceDirectory;
-
- @Parameter( property = "targetDirectory", required = true, defaultValue = "${project.build.directory}/app" )
- protected File targetDirectory;
+ @Parameter( property = "aps-model.app.directory", required = true, defaultValue = "${project.build.directory}/aps/app" )
+ protected File unzipDirectory;
- @Parameter( property = "charset", required = true, defaultValue = "utf-8" )
+ @Parameter( property = "aps-model.reformat", required = true, defaultValue = "true" )
+ protected boolean reformat = true;
+
+ @Parameter( property = "aps-model.normalize" )
+ protected boolean normalize;
+
+ @Parameter( property = "aps-model.normalize.diffFriendly" )
+ protected boolean diffFriendly;
+
+ @Parameter( property = "aps-model.charset", required = true, defaultValue = "utf-8" )
protected String charsetName = "utf-8";
- @Parameter( property = "skip", required = true, defaultValue = "false" )
- protected boolean skip = false;
-
private final int bufferSize = 128 * 1024;
@Override
- public void execute() throws MojoExecutionException, MojoFailureException {
+ public void executeEnabled() throws MojoExecutionException, MojoFailureException {
+ this.validate();
+
File sourceFile = this.validateSourceDirectory();
this.validateTargetDirectory();
@@ -60,20 +70,37 @@ public class UnpackAppGoal extends AbstractMojo {
throw new MojoExecutionException("The downloaded APS App could not be unpacked", ie);
}
- this.normalizeFiles(appDirectory);
+ if (this.reformat)
+ this.reformatFiles(appDirectory);
+ if (this.normalize) {
+ try {
+ ApsAppNormalizer normalizer = new ApsAppNormalizer(this.diffFriendly);
+ ApsAppCrawler crawler = new ApsAppCrawler(this.apsAppName, appDirectory, true);
+ crawler.execute(normalizer);
+ } catch (IOException ie) {
+ throw new MojoExecutionException("An I/O issue occurred", ie);
+ }
+ }
+ }
+
+ protected void validate() {
+ if (this.normalize && !this.reformat) {
+ this.getLog().warn("The reformat option is disabled, but normalization is enabled; enabling reformat anyway");
+ this.reformat = true;
+ }
}
protected File validateSourceDirectory() {
- if (!this.sourceDirectory.exists()) {
- throw new IllegalStateException("The 'sourceDirectory' does not exist: " + this.sourceDirectory);
- } else if (!this.sourceDirectory.isDirectory()) {
- throw new IllegalStateException("The 'sourceDirectory' is not a directory: " + this.sourceDirectory);
+ if (!this.zipDirectory.exists()) {
+ throw new IllegalStateException("The 'zipDirectory' does not exist: " + this.zipDirectory);
+ } else if (!this.zipDirectory.isDirectory()) {
+ throw new IllegalStateException("The 'zipDirectory' is not a directory: " + this.zipDirectory);
}
- File sourceFile = new File(this.sourceDirectory, this.apsAppName + ".zip");
+ File sourceFile = new File(this.zipDirectory, this.apsAppName + ".zip");
if (!sourceFile.exists()) {
- throw new IllegalStateException("The App file does not exists in the 'sourceDirectory': " + sourceFile);
+ throw new IllegalStateException("The App file does not exists in the 'zipDirectory': " + sourceFile);
} else if (!sourceFile.isFile()) {
throw new IllegalStateException("The App file is not a file: " + sourceFile);
}
@@ -82,16 +109,16 @@ public class UnpackAppGoal extends AbstractMojo {
}
protected void validateTargetDirectory() {
- if (!this.targetDirectory.exists()) {
- this.getLog().debug("Creating APS Apps directory: " + this.targetDirectory);
- this.targetDirectory.mkdirs();
- } else if (!this.targetDirectory.isDirectory()) {
- throw new IllegalStateException("The 'apsAppsDirectory' refers to a file and not a directory: " + this.targetDirectory);
+ if (!this.unzipDirectory.exists()) {
+ this.getLog().debug("Creating unzip directory: " + this.unzipDirectory);
+ this.unzipDirectory.mkdirs();
+ } else if (!this.unzipDirectory.isDirectory()) {
+ throw new IllegalStateException("The 'unzipDirectory' refers to a file and not a directory: " + this.unzipDirectory);
}
}
protected File validateAppDirectory() {
- File appDirectory = new File(this.targetDirectory, this.apsAppName);
+ File appDirectory = new File(this.unzipDirectory, this.apsAppName);
if (!appDirectory.exists()) {
this.getLog().debug("Creating APS App directory: " + appDirectory);
appDirectory.mkdirs();
@@ -149,21 +176,25 @@ public class UnpackAppGoal extends AbstractMojo {
}
}
- private void normalizeFiles(File directory) throws MojoFailureException {
+ private void reformatFiles(File directory) throws MojoFailureException {
for (File file : directory.listFiles()) {
if (file.isDirectory()) {
- this.normalizeFiles(file);
+ this.reformatFiles(file);
} else {
String ext = this.getFileExtension(file);
try {
switch (ext) {
case "json":
- ModelUtil.getInstance().json(file);
+ this.getLog().debug("Reformatting file: " + file);
+ Map json = ModelUtil.getInstance().readJsonAsMap(file);
+ ModelUtil.getInstance().writeJson(json, file, false);
break;
case "xml":
case "bpmn":
- ModelUtil.getInstance().xml(file);
+ this.getLog().debug("Reformatting file: " + file);
+ Document xml = ModelUtil.getInstance().readXml(file);
+ ModelUtil.getInstance().writeXml(xml, file);
break;
default:
file.delete();
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsAppJsonNormalizer.java b/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsAppJsonNormalizer.java
new file mode 100644
index 0000000..a7277e7
--- /dev/null
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsAppJsonNormalizer.java
@@ -0,0 +1,53 @@
+package com.inteligr8.maven.aps.modeling.normalizer;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.inteligr8.maven.aps.modeling.util.ApsModelArrayNodeSorter;
+import com.inteligr8.maven.aps.modeling.util.ModelUtil;
+
+public class ApsAppJsonNormalizer implements ApsFileNormalizer {
+
+ private final Logger logger = LoggerFactory.getLogger(ApsAppJsonNormalizer.class);
+
+ private final boolean enableSorting;
+
+ public ApsAppJsonNormalizer(boolean enableSorting) {
+ this.enableSorting = enableSorting;
+ }
+
+ @Override
+ public void transformFile(File file, String modelName, Long modelId) throws IOException {
+ this.logger.debug("Normalizing App JSON file: {}", file);
+
+ boolean changed = false;
+ JsonNode descriptor = ModelUtil.getInstance().readJson(file);
+ ArrayNode jsonModels = (ArrayNode)descriptor.get("definition").get("models");
+
+ // remove system-level and non-functional fields from models
+ for (JsonNode _jsonModel : jsonModels) {
+ ObjectNode jsonModel = (ObjectNode)_jsonModel;
+
+ int fields = jsonModel.size();
+ jsonModel.remove(Arrays.asList("lastUpdated"));
+// jsonModel.remove(Arrays.asList("createdBy", "createdByFullName", "lastUpdatedBy", "lastUpdatedByFullName", "lastUpdated"));
+ if (jsonModel.size() < fields)
+ changed = true;
+ }
+
+ // sort the models for better 'diff' support
+ if (this.enableSorting)
+ changed = ApsModelArrayNodeSorter.getInstance().sort(jsonModels, "name") || changed;
+
+ if (changed)
+ ModelUtil.getInstance().writeJson(descriptor, file, this.enableSorting);
+ }
+
+}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsAppNormalizer.java b/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsAppNormalizer.java
new file mode 100644
index 0000000..6e607db
--- /dev/null
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsAppNormalizer.java
@@ -0,0 +1,34 @@
+package com.inteligr8.maven.aps.modeling.normalizer;
+
+import com.inteligr8.maven.aps.modeling.crawler.ApsAppCrawlable;
+import com.inteligr8.maven.aps.modeling.crawler.ApsFileTransformer;
+
+public class ApsAppNormalizer implements ApsAppCrawlable {
+
+ private final boolean enableSorting;
+
+ public ApsAppNormalizer(boolean enableSorting) {
+ this.enableSorting = enableSorting;
+ }
+
+ @Override
+ public ApsFileTransformer getAppJsonTransformer() {
+ return new ApsAppJsonNormalizer(this.enableSorting);
+ }
+
+ @Override
+ public ApsFileTransformer getFormJsonTransformer() {
+ return new ApsFormJsonNormalizer();
+ }
+
+ @Override
+ public ApsFileTransformer getProcessJsonTransformer() {
+ return new ApsProcessJsonNormalizer(this.enableSorting);
+ }
+
+ @Override
+ public ApsFileTransformer getProcessBpmnTransformer() {
+ return new ApsProcessBpmnNormalizer();
+ }
+
+}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsFileNormalizer.java b/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsFileNormalizer.java
new file mode 100644
index 0000000..9ff8d1f
--- /dev/null
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsFileNormalizer.java
@@ -0,0 +1,7 @@
+package com.inteligr8.maven.aps.modeling.normalizer;
+
+import com.inteligr8.maven.aps.modeling.crawler.ApsFileTransformer;
+
+public interface ApsFileNormalizer extends ApsFileTransformer {
+
+}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsFormJsonNormalizer.java b/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsFormJsonNormalizer.java
new file mode 100644
index 0000000..5a96d51
--- /dev/null
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsFormJsonNormalizer.java
@@ -0,0 +1,19 @@
+package com.inteligr8.maven.aps.modeling.normalizer;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ApsFormJsonNormalizer implements ApsFileNormalizer {
+
+ private final Logger logger = LoggerFactory.getLogger(ApsFormJsonNormalizer.class);
+
+ @Override
+ public void transformFile(File file, String modelName, Long modelId) throws IOException {
+ this.logger.debug("Normalizing Form JSON file: {}", file);
+ this.logger.trace("Nothing to normalize: {}", file);
+ }
+
+}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsProcessBpmnNormalizer.java b/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsProcessBpmnNormalizer.java
new file mode 100644
index 0000000..9120c45
--- /dev/null
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsProcessBpmnNormalizer.java
@@ -0,0 +1,52 @@
+package com.inteligr8.maven.aps.modeling.normalizer;
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.xml.transform.TransformerException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+import com.inteligr8.maven.aps.modeling.util.ModelUtil;
+
+public class ApsProcessBpmnNormalizer implements ApsFileNormalizer {
+
+ private static final String NAMESPACE_ACTIVITI_MODELER = "http://activiti.com/modeler";
+
+ private final Logger logger = LoggerFactory.getLogger(ApsProcessBpmnNormalizer.class);
+
+ @Override
+ public void transformFile(File file, String modelName, Long modelId) throws IOException {
+ this.logger.debug("Normalizing Process BPMN file: {}", file);
+
+ boolean changed = false;
+
+ try {
+ Document bpmn = ModelUtil.getInstance().readXml(file);
+ Element definitionsElement = bpmn.getDocumentElement();
+
+ changed = this.removeAttributeIfSet(definitionsElement, NAMESPACE_ACTIVITI_MODELER, "exportDateTime") || changed;
+ changed = this.removeAttributeIfSet(definitionsElement, NAMESPACE_ACTIVITI_MODELER, "modelLastUpdated") || changed;
+
+ if (changed)
+ ModelUtil.getInstance().writeXml(bpmn, file);
+ } catch (TransformerException | SAXException e) {
+ throw new IllegalStateException("An XML issue occurred", e);
+ }
+ }
+
+ private boolean removeAttributeIfSet(Element element, String attrNamespace, String attrName) {
+ Attr attr = element.getAttributeNodeNS(attrNamespace, attrName);
+ if (attr == null)
+ return false;
+
+ element.removeAttributeNode(attr);
+ return true;
+ }
+
+}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsProcessJsonNormalizer.java b/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsProcessJsonNormalizer.java
new file mode 100644
index 0000000..cc0e1ac
--- /dev/null
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsProcessJsonNormalizer.java
@@ -0,0 +1,50 @@
+package com.inteligr8.maven.aps.modeling.normalizer;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.inteligr8.maven.aps.modeling.util.ApsModelArrayNodeSorter;
+import com.inteligr8.maven.aps.modeling.util.ModelUtil;
+
+public class ApsProcessJsonNormalizer implements ApsFileNormalizer {
+
+ private final Logger logger = LoggerFactory.getLogger(ApsProcessJsonNormalizer.class);
+
+ private final boolean enableSorting;
+
+ public ApsProcessJsonNormalizer(boolean enableSorting) {
+ this.enableSorting = enableSorting;
+ }
+
+ @Override
+ public void transformFile(File file, String modelName, Long modelId) throws IOException {
+ this.logger.debug("Normalizing Process JSON file: {}", file);
+
+ if (!this.enableSorting)
+ return;
+
+ boolean changed = false;
+
+ ObjectNode jsonDescriptor = ModelUtil.getInstance().readJson(file, ObjectNode.class);
+ ArrayNode jsonChildShapes = this.getChildShapes(jsonDescriptor);
+
+ changed = ApsModelArrayNodeSorter.getInstance().sort(jsonChildShapes, "resourceId") || changed;
+
+ if (changed)
+ ModelUtil.getInstance().writeJson(jsonDescriptor, file, this.enableSorting);
+ }
+
+ private ArrayNode getChildShapes(ObjectNode jsonDescriptor) {
+ JsonNode jsonChildShapes = jsonDescriptor.get("childShapes");
+ if (jsonChildShapes == null)
+ jsonChildShapes = jsonDescriptor.get("editorJson").get("childShapes");
+ return (ArrayNode)jsonChildShapes;
+ }
+
+}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/ApsAppJsonTranslator.java b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsAppJsonTranslator.java
similarity index 80%
rename from src/main/java/com/inteligr8/maven/aps/modeling/ApsAppJsonTranslator.java
rename to src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsAppJsonTranslator.java
index 6b947a5..95eccca 100644
--- a/src/main/java/com/inteligr8/maven/aps/modeling/ApsAppJsonTranslator.java
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsAppJsonTranslator.java
@@ -1,4 +1,4 @@
-package com.inteligr8.maven.aps.modeling;
+package com.inteligr8.maven.aps.modeling.translator;
import java.io.File;
import java.io.IOException;
@@ -10,6 +10,8 @@ import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.inteligr8.alfresco.activiti.model.Group;
+import com.inteligr8.maven.aps.modeling.util.Index;
+import com.inteligr8.maven.aps.modeling.util.ModelUtil;
public class ApsAppJsonTranslator implements ApsFileTranslator {
@@ -32,10 +34,9 @@ public class ApsAppJsonTranslator implements ApsFileTranslator {
@Override
public void translateFile(File file, String modelName, Long modelId) throws IOException {
this.logger.debug("Translating JSON file: {}", file);
-
- JsonNode descriptor = ModelUtil.getInstance().readJson(file);
-
+
boolean changed = false;
+ JsonNode descriptor = ModelUtil.getInstance().readJson(file);
for (JsonNode _jsonModel : descriptor.get("definition").get("models")) {
ObjectNode jsonModel = (ObjectNode)_jsonModel;
@@ -64,6 +65,15 @@ public class ApsAppJsonTranslator implements ApsFileTranslator {
this.logger.trace("The process '{}' ID does not change; leaving unchanged", fileProcessName);
}
}
+
+ if (jsonModel.has("version")) {
+ jsonModel.put("version", 0);
+ changed = true;
+ }
+// int fields = jsonModel.size();
+// jsonModel.remove(Arrays.asList("version"));
+// if (jsonModel.size() < fields)
+// changed = true;
}
for (JsonNode _jsonIdentityInfo : descriptor.get("definition").get("publishIdentityInfo")) {
@@ -77,20 +87,29 @@ public class ApsAppJsonTranslator implements ApsFileTranslator {
long apsOrgId = this.apsOrgIndex.get(fileOrgName).getId();
if (fileOrgId != apsOrgId) {
- this.logger.debug("The organziation '{}' exists in APS with ID {}; changing descriptor", fileOrgName, apsOrgId);
+ this.logger.debug("The organization '{}' exists in APS with ID {}; changing descriptor", fileOrgName, apsOrgId);
jsonGroup.put("id", apsOrgId);
changed = true;
} else {
this.logger.trace("The organization '{}' ID does not change; leaving unchanged", fileOrgName);
}
+
+ if (jsonGroup.has("parentGroupId")) {
+ jsonGroup.put("parentGroupId", 0);
+ changed = true;
+ }
+// if (jsonGroup.has("parentGroupId")) {
+// jsonGroup.remove("parentGroupId");
+// changed = true;
+// }
} else {
- this.logger.warn("The organziation '{}' does not exist in APS", fileOrgName);
+ this.logger.warn("The organization '{}' does not exist in APS", fileOrgName);
// FIXME create the organization
}
}
if (changed)
- ModelUtil.getInstance().writeJson(descriptor, file);
+ ModelUtil.getInstance().writeJson(descriptor, file, false);
}
}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/ApsAppTranslator.java b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsAppTranslator.java
similarity index 54%
rename from src/main/java/com/inteligr8/maven/aps/modeling/ApsAppTranslator.java
rename to src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsAppTranslator.java
index 424d94e..3c0c363 100644
--- a/src/main/java/com/inteligr8/maven/aps/modeling/ApsAppTranslator.java
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsAppTranslator.java
@@ -1,8 +1,7 @@
-package com.inteligr8.maven.aps.modeling;
+package com.inteligr8.maven.aps.modeling.translator;
import java.io.File;
import java.io.IOException;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -13,23 +12,25 @@ import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.inteligr8.alfresco.activiti.ApsPublicRestApi;
import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl;
import com.inteligr8.alfresco.activiti.api.ModelsApi.ModelType;
import com.inteligr8.alfresco.activiti.model.Datum;
import com.inteligr8.alfresco.activiti.model.Group;
import com.inteligr8.alfresco.activiti.model.ResultListDataRepresentation;
import com.inteligr8.alfresco.activiti.model.Tenant;
+import com.inteligr8.maven.aps.modeling.crawler.ApsAppCrawlable;
+import com.inteligr8.maven.aps.modeling.crawler.ApsFileTransformer;
+import com.inteligr8.maven.aps.modeling.util.Index;
-public class ApsAppTranslator {
+public class ApsAppTranslator implements ApsAppCrawlable {
private final Logger logger = LoggerFactory.getLogger(ApsAppTranslator.class);
private final Pattern filenamePattern = Pattern.compile("([^/]+)-([0-9]+)\\.(json|bpmn20\\.xml)");
- private final ApsPublicRestApiJerseyImpl api;
- private final String appName;
+ private final ApsPublicRestApi api;
private final File appDirectory;
- private final File appDescriptor;
- private final boolean failOnIntegrityViolation;
+ private boolean indexesBuilt = false;
private Map apsOrgIndex;
private Index apsFormIndex;
private Index apsProcessIndex;
@@ -37,86 +38,98 @@ public class ApsAppTranslator {
private Index fileProcessIndex;
private Index fileSubprocessIndex;
- public ApsAppTranslator(String apsAppName, File apsAppDirectory, ApsPublicRestApiJerseyImpl api, boolean failOnIntegrityViolation) {
+ public ApsAppTranslator(File apsAppDirectory, ApsPublicRestApiJerseyImpl api) {
this.api = api;
- this.appName = apsAppName;
this.appDirectory = apsAppDirectory;
- this.failOnIntegrityViolation = failOnIntegrityViolation;
-
- this.appDescriptor = this.validateDescriptor(appDirectory);
- if (this.logger.isDebugEnabled())
- this.logger.debug("APS App descriptor found: " + this.appDescriptor);
}
- protected File validateDescriptor(File appDirectory) {
- File appDescriptor = new File(appDirectory, this.appName + ".json");
+ public synchronized void buildIndexes() throws IOException {
+ if (this.indexesBuilt)
+ return;
- if (!appDescriptor.exists())
- throw new IllegalStateException("The APS App descriptor could not be found: " + appDescriptor);
- if (!appDescriptor.isFile())
- throw new IllegalStateException("The APS App descriptor is not a file: " + appDescriptor);
-
- return appDescriptor;
- }
-
- public void execute() throws IOException {
- this.buildIndexes();
- this.translate();
- }
-
- protected void buildIndexes() throws IOException {
this.logger.info("Building indexes ...");
long tenantId = this.findTenantId();
this.logger.debug("APS App tenant ID: {}", tenantId);
this.apsOrgIndex = this.buildApsGroupMap(tenantId);
- this.logger.debug("APS App organizations: {}", this.apsOrgIndex);
+ this.logLarge("APS App organizations: {}", this.apsOrgIndex);
this.apsProcessIndex = this.buildApsModelIndex(ModelType.Process);
- this.logger.debug("APS process models: {}", this.apsProcessIndex);
+ this.logLarge("APS process models: {}", this.apsProcessIndex);
this.apsFormIndex = this.buildApsModelIndex(ModelType.Form);
- this.logger.debug("APS form models: {}", this.apsFormIndex);
+ this.logLarge("APS form models: {}", this.apsFormIndex);
this.fileFormIndex = this.buildFileIndex("form-models", this.apsFormIndex, true);
- this.logger.debug("File form models: {}", this.fileFormIndex);
+ this.logLarge("File form models: {}", this.fileFormIndex);
this.fileProcessIndex = this.buildFileIndex("bpmn-models", this.apsProcessIndex, true);
- this.logger.debug("File process models: {}", this.fileProcessIndex);
+ this.logLarge("File process models: {}", this.fileProcessIndex);
this.fileSubprocessIndex = this.buildFileIndex("bpmn-subprocess-models", this.apsProcessIndex, true);
- this.logger.debug("File subprocess models: {}", this.fileSubprocessIndex);
+ this.logLarge("File subprocess models: {}", this.fileSubprocessIndex);
+
+ this.indexesBuilt = true;
}
- protected void translate() throws IOException {
- this.logger.info("Translating models ...");
+ private void logLarge(String message, Map map) {
+ if (this.logger.isTraceEnabled()) {
+ this.logger.trace(message, map);
+ } else {
+ this.logger.debug(message, map.keySet());
+ }
+ }
+
+ private void logLarge(String message, Index index) {
+ if (this.logger.isTraceEnabled()) {
+ this.logger.trace(message, index);
+ } else {
+ this.logger.debug(message, index.valueSet());
+ }
+ }
+
+ @Override
+ public ApsFileTransformer getAppJsonTransformer() {
+ if (!this.indexesBuilt)
+ throw new IllegalStateException("The indexes are never built");
- ApsFileTranslator descriptorTranslator = new ApsAppJsonTranslator(
+ return new ApsAppJsonTranslator(
this.apsOrgIndex,
this.apsProcessIndex,
this.fileProcessIndex);
- ApsFileTranslator formTranslator = new ApsFormJsonTranslator(
+ }
+
+ @Override
+ public ApsFileTransformer getFormJsonTransformer() {
+ if (!this.indexesBuilt)
+ throw new IllegalStateException("The indexes are never built");
+
+ return new ApsFormJsonTranslator(
this.apsFormIndex);
- ApsFileTranslator processTranslator = new ApsProcessJsonTranslator(
+ }
+
+ @Override
+ public ApsFileTransformer getProcessJsonTransformer() {
+ if (!this.indexesBuilt)
+ throw new IllegalStateException("The indexes are never built");
+
+ return new ApsProcessJsonTranslator(
this.apsProcessIndex,
this.apsOrgIndex,
this.apsFormIndex);
- ApsFileTranslator bpmnTranslator = new ApsProcessBpmnTranslator(
+ }
+
+ @Override
+ public ApsFileTransformer getProcessBpmnTransformer() {
+ if (!this.indexesBuilt)
+ throw new IllegalStateException("The indexes are never built");
+
+ return new ApsProcessBpmnTranslator(
this.apsProcessIndex,
this.apsOrgIndex,
this.apsFormIndex,
this.fileFormIndex);
-
- Map processTranslators = new HashMap<>();
- processTranslators.put("json", processTranslator);
- processTranslators.put("bpmn20.xml", bpmnTranslator);
- processTranslators.put("bpmn", bpmnTranslator);
-
- this.translate(descriptorTranslator, this.appDescriptor, this.appName, null);
- this.translateModels("form-models", formTranslator);
- this.translateModels("bpmn-models", processTranslators);
- this.translateModels("bpmn-subprocess-models", processTranslator);
}
protected Long findTenantId() {
@@ -134,7 +147,8 @@ public class ApsAppTranslator {
}
protected Index buildApsModelIndex(ModelType modelType) {
- ResultListDataRepresentation results = this.api.getModelsApi().get(null, null, modelType.getId(), null);
+ ResultListDataRepresentation results = this.api.getModelsApi().get("everyone", null, modelType.getId(), null);
+ this.logger.debug("APS {} models found: {} out of {}", modelType, results.getSize(), results.getTotal());
Index map = new Index<>(results.getSize().intValue(), false);
@@ -143,11 +157,13 @@ public class ApsAppTranslator {
Number defId = (Number)datum.getAdditionalProperties().get("id");
String defName = (String)datum.getAdditionalProperties().get("name");
map.put(defId.longValue(), defName);
+
+ // FIXME add paging support
}
} catch (IllegalArgumentException iae) {
throw new IllegalStateException("This goal does not support the current state of APS", iae);
}
-
+
return map;
}
@@ -157,77 +173,50 @@ public class ApsAppTranslator {
}
protected Index buildFileIndex(File modelDirectory, Index apsModelIndex, boolean renameFiles) {
- if (!modelDirectory.exists())
+ if (!modelDirectory.exists()) {
+ this.logger.debug("APS model directory doesn't exist; creating empty index: {}", modelDirectory);
return new Index<>(0, false);
+ }
+
if (!modelDirectory.isDirectory())
throw new IllegalStateException("The APS model directory is actually a file: " + modelDirectory);
Index fileModelIndex = new Index<>(apsModelIndex.size(), false);
for (File modelFile : modelDirectory.listFiles()) {
+ this.logger.trace("Building index for model file: {}", modelFile);
+
Matcher matcher = this.filenamePattern.matcher(modelFile.getName());
String modelName = matcher.replaceFirst("$1");
String modelIdStr = matcher.replaceFirst("$2");
String modelExt = matcher.replaceFirst("$3");
long fileModelId = Long.parseLong(modelIdStr);
+ this.logger.trace("Building index for model {} ID: {}", modelName, fileModelId);
fileModelIndex.put(fileModelId, modelName);
Set apsModelIds = apsModelIndex.getKeys(modelName);
+ if (apsModelIds == null || apsModelIds.isEmpty()) {
+ this.logger.debug("The model file '{}' has no corresponding model in APS; treating as new", modelFile.getName());
+ continue;
+ }
+
if (apsModelIds.size() > 1)
throw new IllegalStateException("An APS " + modelDirectory.getName() + " name was used multiple times: " + modelName);
- if (renameFiles && !apsModelIds.isEmpty()) {
+ if (renameFiles) {
Long apsModelId = apsModelIds.iterator().next();
if (apsModelId != fileModelId) {
this.logger.debug("Renaming form model from '" + modelFile.getName() + "' to match APS form ID: " + apsModelId);
File newModelFile = new File(modelFile.getParentFile(), modelName + "-" + apsModelId + "." + modelExt);
modelFile.renameTo(newModelFile);
} else {
- this.logger.debug("The APS model '{}' and corresponding model file have matching IDs", modelName);
+ this.logger.debug("The APS model '{}' and corresponding model file '{}' have matching IDs", modelName, modelFile.getName());
}
}
}
return fileModelIndex;
}
-
- protected void translateModels(String modelsDirectoryName, ApsFileTranslator translator) throws IOException {
- this.translateModels(modelsDirectoryName, Collections.singletonMap("json", translator));
- }
-
- protected void translateModels(String modelsDirectoryName, Map translators) throws IOException {
- File modelsDirectory = new File(this.appDirectory, modelsDirectoryName);
- for (File modelFile : modelsDirectory.listFiles()) {
- Matcher matcher = this.filenamePattern.matcher(modelFile.getName());
- if (!matcher.find()) {
- this.logger.warn("The '{}' folder has a file with an unexpected filename format; skipping: {}", modelsDirectoryName, modelFile);
- continue;
- }
-
- String ext = matcher.group(3);
- ApsFileTranslator translator = translators.get(ext.toLowerCase());
- if (translator == null) {
- this.logger.warn("The '{}' folder has a file with an unexpected extension; skipping: {}", modelsDirectoryName, modelFile);
- continue;
- }
-
- String modelName = matcher.group(1);
- Long modelId = new Long(matcher.group(2));
- this.translate(translator, modelFile, modelName, modelId);
- }
- }
-
- private void translate(ApsFileTranslator translator, File modelFile, String modelName, Long modelId) throws IOException {
- try {
- translator.translateFile(modelFile, modelName, modelId);
- } catch (IllegalArgumentException | IllegalStateException ie) {
- if (this.failOnIntegrityViolation) {
- throw ie;
- } else {
- this.logger.warn(ie.getMessage());
- }
- }
- }
}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsFileTranslator.java b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsFileTranslator.java
new file mode 100644
index 0000000..f542e56
--- /dev/null
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsFileTranslator.java
@@ -0,0 +1,17 @@
+package com.inteligr8.maven.aps.modeling.translator;
+
+import java.io.File;
+import java.io.IOException;
+
+import com.inteligr8.maven.aps.modeling.crawler.ApsFileTransformer;
+
+public interface ApsFileTranslator extends ApsFileTransformer {
+
+ @Override
+ default void transformFile(File file, String modelName, Long modelId) throws IOException {
+ this.translateFile(file, modelName, modelId);
+ }
+
+ void translateFile(File file, String modelName, Long modelId) throws IOException;
+
+}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/ApsFormJsonTranslator.java b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsFormJsonTranslator.java
similarity index 87%
rename from src/main/java/com/inteligr8/maven/aps/modeling/ApsFormJsonTranslator.java
rename to src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsFormJsonTranslator.java
index 1d9228a..eb46762 100644
--- a/src/main/java/com/inteligr8/maven/aps/modeling/ApsFormJsonTranslator.java
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsFormJsonTranslator.java
@@ -1,4 +1,4 @@
-package com.inteligr8.maven.aps.modeling;
+package com.inteligr8.maven.aps.modeling.translator;
import java.io.File;
import java.io.IOException;
@@ -8,6 +8,8 @@ import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.inteligr8.maven.aps.modeling.util.Index;
+import com.inteligr8.maven.aps.modeling.util.ModelUtil;
public class ApsFormJsonTranslator implements ApsFileTranslator {
@@ -44,7 +46,7 @@ public class ApsFormJsonTranslator implements ApsFileTranslator {
}
if (changed)
- ModelUtil.getInstance().writeJson(jsonDescriptor, file);
+ ModelUtil.getInstance().writeJson(jsonDescriptor, file, false);
}
}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/ApsProcessBpmnTranslator.java b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsProcessBpmnTranslator.java
similarity index 87%
rename from src/main/java/com/inteligr8/maven/aps/modeling/ApsProcessBpmnTranslator.java
rename to src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsProcessBpmnTranslator.java
index 61966ca..456f74a 100644
--- a/src/main/java/com/inteligr8/maven/aps/modeling/ApsProcessBpmnTranslator.java
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsProcessBpmnTranslator.java
@@ -1,4 +1,4 @@
-package com.inteligr8.maven.aps.modeling;
+package com.inteligr8.maven.aps.modeling.translator;
import java.io.File;
import java.io.IOException;
@@ -16,13 +16,15 @@ import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Attr;
-import org.w3c.dom.CDATASection;
+import org.w3c.dom.CharacterData;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import com.inteligr8.alfresco.activiti.model.Group;
+import com.inteligr8.maven.aps.modeling.util.Index;
+import com.inteligr8.maven.aps.modeling.util.ModelUtil;
public class ApsProcessBpmnTranslator implements ApsFileTranslator {
@@ -72,7 +74,7 @@ public class ApsProcessBpmnTranslator implements ApsFileTranslator {
changed = this.translateTaskForm(formKeyElement) || changed;
}
- NodeList subprocessElements = ModelUtil.getInstance().xpath(definitionsElement, "//subProcess");
+ NodeList subprocessElements = ModelUtil.getInstance().xpath(definitionsElement, "//tns:subProcess");
for (int n = 0; n < subprocessElements.getLength(); n++) {
Element subprocessElement = (Element)subprocessElements.item(n);
changed = this.translateSubprocess(subprocessElement) || changed;
@@ -84,9 +86,9 @@ public class ApsProcessBpmnTranslator implements ApsFileTranslator {
changed = this.translateConditionDefinition(conditionDefinitionElement) || changed;
}
- NodeList conditionExpressions = ModelUtil.getInstance().xpath(definitionsElement, "//conditionExpression/text()");
+ NodeList conditionExpressions = ModelUtil.getInstance().xpath(definitionsElement, "//tns:conditionExpression/text()");
for (int n = 0; n < conditionExpressions.getLength(); n++) {
- CDATASection conditionExpression = (CDATASection)conditionExpressions.item(n);
+ CharacterData conditionExpression = (CharacterData)conditionExpressions.item(n);
changed = this.translateConditionExpression(conditionExpression) || changed;
}
@@ -100,10 +102,10 @@ public class ApsProcessBpmnTranslator implements ApsFileTranslator {
private boolean translateRootElement(Element definitionsElement, Long apsProcessId) {
boolean changed = false;
- changed = this.setAttributeIfSet(definitionsElement, NAMESPACE_ACTIVITI_MODELER, "modelId", apsProcessId) || changed;
+ if (apsProcessId != null)
+ changed = this.setAttributeIfSet(definitionsElement, NAMESPACE_ACTIVITI_MODELER, "modelId", apsProcessId) || changed;
changed = this.removeAttributeIfSet(definitionsElement, NAMESPACE_ACTIVITI_MODELER, "modelVersion") || changed;
- changed = this.removeAttributeIfSet(definitionsElement, NAMESPACE_ACTIVITI_MODELER, "exportDateTime") || changed;
- changed = this.removeAttributeIfSet(definitionsElement, NAMESPACE_ACTIVITI_MODELER, "modelLastUpdated") || changed;
+ //changed = this.setAttributeIfSet(definitionsElement, NAMESPACE_ACTIVITI_MODELER, "modelVersion", "0") || changed;
return changed;
}
@@ -146,7 +148,7 @@ public class ApsProcessBpmnTranslator implements ApsFileTranslator {
if (apsOrgId != orgId) {
this.logger.debug("The organization '{}' exists in APS with ID {}; changing model", groupName, apsOrgId);
groupNameElement = (Element)groupNameElement.getOwnerDocument().renameNode(groupNameElement,
- groupNameElement.getNamespaceURI(), "group-info-name-" + apsOrgId);
+ groupNameElement.getNamespaceURI(), "modeler:group-info-name-" + apsOrgId);
changed = true;
} else {
this.logger.trace("The organization '{}' ID does not change; leaving unchanged", groupName);
@@ -198,17 +200,17 @@ public class ApsProcessBpmnTranslator implements ApsFileTranslator {
this.logger.trace("The form '{}' key does not change; leaving unchanged", formRefName);
}
- CDATAFlexSection formRefIdData = (CDATAFlexSection)ModelUtil.getInstance().xpath(
+ CharacterData formRefIdData = (CharacterData)ModelUtil.getInstance().xpath(
taskElement,
"tns:extensionElements/modeler:form-reference-id",
ModelUtil.CDATA_FLEX);
if (formRefIdData == null)
throw new IllegalStateException("A form was detected in the task, but no form reference ID was found: " + taskElement.getAttribute("id"));
- long formRefId = Long.parseLong(formRefIdData.getValue());
+ long formRefId = Long.parseLong(formRefIdData.getData());
if (apsFormId != formRefId) {
this.logger.debug("The form '{}' reference exists in APS with ID {}; changing model", formRefName, apsFormId);
- formRefIdData.setValue(apsFormId.toString());
+ formRefIdData.setData(apsFormId.toString());
changed = true;
} else {
this.logger.trace("The form '{}' reference ID does not change; leaving unchanged", formRefName);
@@ -242,14 +244,14 @@ public class ApsProcessBpmnTranslator implements ApsFileTranslator {
this.logger.trace("Found ID {} for the subprocess '{}' in the APS Process BPMN model", apsProcessId, subprocessName);
- CDATAFlexSection subprocessIdData = (CDATAFlexSection)ModelUtil.getInstance().xpath(
+ CharacterData subprocessIdData = (CharacterData)ModelUtil.getInstance().xpath(
subprocessElement,
"tns:extensionElements/modeler:subprocess-id",
ModelUtil.CDATA_FLEX);
- long subprocessId = Long.parseLong(subprocessIdData.getValue());
+ long subprocessId = Long.parseLong(subprocessIdData.getData());
if (apsProcessId != subprocessId) {
this.logger.debug("The process '{}' exists in APS with ID {}; changing model", subprocessName, apsProcessId);
- subprocessIdData.setValue(apsProcessId.toString());
+ subprocessIdData.setData(apsProcessId.toString());
changed = true;
} else {
this.logger.trace("The process '{}' ID does not change; leaving unchanged", subprocessName);
@@ -282,28 +284,42 @@ public class ApsProcessBpmnTranslator implements ApsFileTranslator {
return changed;
}
- private boolean translateConditionExpression(CDATASection conditionExpressionCdata) throws XPathExpressionException {
+ private boolean translateConditionExpression(CharacterData conditionExpressionCdata) throws XPathExpressionException {
this.logger.trace("Translating condition expression for outcome form elements: {}", conditionExpressionCdata.getParentNode().getParentNode().getAttributes().getNamedItem("id"));
boolean changed = false;
String conditionExpression = conditionExpressionCdata.getData();
- Pattern formOutcomeInExpressionPattern = Pattern.compile("[^A-Za-z0-9]form([0-9]+)outcome[^A-Za-z0-9]");
+ StringBuilder newce = new StringBuilder();
+ int pos = 0;
+
+ Pattern formOutcomeInExpressionPattern = Pattern.compile("form([0-9]+)outcome");
Matcher matcher = formOutcomeInExpressionPattern.matcher(conditionExpression);
while (matcher.find()) {
+ newce.append(conditionExpression.substring(pos, matcher.start(1)));
+
long formId = Long.parseLong(matcher.group(1));
String formName = this.fileFormIndex.getValue(formId);
if (formName == null) {
this.logger.warn("The form ID '{}' does not exist in the form model files; ignoring", formId);
+ newce.append(formId);
} else {
Long apsFormId = this.apsFormIndex.getFirstKey(formName);
if (apsFormId == null) {
this.logger.warn("The form '{}' does not exist in APS; leaving unchanged", formName);
+ newce.append(formId);
} else {
- conditionExpressionCdata.setData(apsFormId.toString());
+ newce.append(apsFormId);
changed = true;
}
}
+
+ pos = matcher.end(1);
}
+
+ newce.append(conditionExpression.substring(pos));
+
+ if (changed)
+ conditionExpressionCdata.setData(newce.toString());
return changed;
}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/ApsProcessJsonTranslator.java b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsProcessJsonTranslator.java
similarity index 87%
rename from src/main/java/com/inteligr8/maven/aps/modeling/ApsProcessJsonTranslator.java
rename to src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsProcessJsonTranslator.java
index f61b020..9c0175e 100644
--- a/src/main/java/com/inteligr8/maven/aps/modeling/ApsProcessJsonTranslator.java
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsProcessJsonTranslator.java
@@ -1,4 +1,4 @@
-package com.inteligr8.maven.aps.modeling;
+package com.inteligr8.maven.aps.modeling.translator;
import java.io.File;
import java.io.IOException;
@@ -11,6 +11,8 @@ import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.inteligr8.alfresco.activiti.model.Group;
+import com.inteligr8.maven.aps.modeling.util.Index;
+import com.inteligr8.maven.aps.modeling.util.ModelUtil;
public class ApsProcessJsonTranslator implements ApsFileTranslator {
@@ -43,17 +45,32 @@ public class ApsProcessJsonTranslator implements ApsFileTranslator {
changed = this.translateSubprocesses(jsonDescriptor) || changed;
if (changed)
- ModelUtil.getInstance().writeJson(jsonDescriptor, file);
+ ModelUtil.getInstance().writeJson(jsonDescriptor, file, false);
}
private boolean translateResourceId(ObjectNode jsonDescriptor, Long apsProcessId) {
+ if (apsProcessId == null) {
+ this.logger.trace("The process is not in APS; treating as new");
+ return false;
+ }
+
+ ObjectNode resourceIdParentJson = jsonDescriptor;
+
JsonNode jsonResourceId = jsonDescriptor.get("resourceId");
+ if (jsonResourceId == null || jsonResourceId.isNull()) {
+ JsonNode jsonEditorJson = jsonDescriptor.get("editorJson");
+ if (jsonEditorJson != null && jsonEditorJson.isObject()) {
+ resourceIdParentJson = (ObjectNode)jsonEditorJson;
+ jsonResourceId = jsonEditorJson.get("resourceId");
+ }
+ }
+
if (jsonResourceId == null || jsonResourceId.isNull()) {
this.logger.trace("The process 'resourceId' is not defined; leaving unchanged", apsProcessId);
return false;
} else if (jsonResourceId.asLong() != apsProcessId) {
this.logger.debug("The process is found in APS with ID {}; changing 'resourceId' in descriptor", apsProcessId);
- jsonDescriptor.put("resourceId", apsProcessId);
+ resourceIdParentJson.put("resourceId", apsProcessId);
return true;
} else {
this.logger.trace("The process ID {} does not change; leaving unchanged", apsProcessId);
@@ -113,8 +130,8 @@ public class ApsProcessJsonTranslator implements ApsFileTranslator {
for (JsonNode jsonChildShape : this.getChildShapes(jsonDescriptor)) {
try {
- JsonNode jsonConditionalSequenceFlow = (JsonNode)jsonChildShape.get("properties").get("conditionalsequenceflow");
- changed = this.translateConditionalSequenceFlow(jsonConditionalSequenceFlow) || changed;
+ JsonNode jsonConditionalSequenceFlow = (JsonNode)jsonChildShape.get("properties").get("conditionsequenceflow");
+ changed = this.translateConditionSequenceFlow(jsonConditionalSequenceFlow) || changed;
JsonNode jsonFormRef = (JsonNode)jsonChildShape.get("properties").get("formreference");
changed = this.translateReference(jsonFormRef, this.apsFormIndex) || changed;
@@ -126,7 +143,7 @@ public class ApsProcessJsonTranslator implements ApsFileTranslator {
return changed;
}
- private boolean translateConditionalSequenceFlow(JsonNode jsonConditionalSequenceFlow) {
+ private boolean translateConditionSequenceFlow(JsonNode jsonConditionalSequenceFlow) {
if (jsonConditionalSequenceFlow == null || !jsonConditionalSequenceFlow.isObject())
return false;
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/util/ApsModelArrayNodeSorter.java b/src/main/java/com/inteligr8/maven/aps/modeling/util/ApsModelArrayNodeSorter.java
new file mode 100644
index 0000000..11c49c3
--- /dev/null
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/util/ApsModelArrayNodeSorter.java
@@ -0,0 +1,22 @@
+package com.inteligr8.maven.aps.modeling.util;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+
+public class ApsModelArrayNodeSorter extends ArrayNodeObjectSorter {
+
+ private static ApsModelArrayNodeSorter INSTANCE = new ApsModelArrayNodeSorter();
+
+ public static ApsModelArrayNodeSorter getInstance() {
+ return INSTANCE;
+ }
+
+
+
+ protected ApsModelArrayNodeSorter() {
+ }
+
+ public boolean sort(ArrayNode arrayNode, String jsonObjectFieldName) {
+ return this.sort(arrayNode, new ObjectNodeComparator(jsonObjectFieldName));
+ }
+
+}
diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/util/ApsModelListMapSorter.java b/src/main/java/com/inteligr8/maven/aps/modeling/util/ApsModelListMapSorter.java
new file mode 100644
index 0000000..212a048
--- /dev/null
+++ b/src/main/java/com/inteligr8/maven/aps/modeling/util/ApsModelListMapSorter.java
@@ -0,0 +1,23 @@
+package com.inteligr8.maven.aps.modeling.util;
+
+import java.util.List;
+import java.util.Map;
+
+public class ApsModelListMapSorter extends ListMapSorter {
+
+ private static ApsModelListMapSorter INSTANCE = new ApsModelListMapSorter();
+
+ public static ApsModelListMapSorter getInstance() {
+ return INSTANCE;
+ }
+
+
+
+ protected ApsModelListMapSorter() {
+ }
+
+ public boolean sort(List