From 3d353cf6d5a068a5a5ad10c8281b8edb018c3c8b Mon Sep 17 00:00:00 2001 From: Brian Long Date: Mon, 28 Mar 2022 20:05:46 +0100 Subject: [PATCH] finished, tested and fixed initial impl --- pom.xml | 5 +- src/it/deploy-app/pom.xml | 42 ++++++++++-- src/it/download-app/pom.xml | 4 +- src/it/pack-app/pom.xml | 11 ++-- src/it/translate-app/pom.xml | 4 +- src/it/unpack-app/pom.xml | 4 +- .../aps/modeling/goal/ApsAddressibleGoal.java | 64 +++++++++++------- .../aps/modeling/goal/DeployAppGoal.java | 44 +++++++------ .../maven/aps/modeling/goal/PackAppGoal.java | 40 +++++------ .../aps/modeling/goal/TranslateAppGoal.java | 8 --- .../aps/modeling/goal/UnpackAppGoal.java | 2 +- .../normalizer/ApsAppJsonNormalizer.java | 7 +- .../normalizer/ApsProcessJsonNormalizer.java | 2 +- .../translator/ApsAppJsonTranslator.java | 21 ++++-- .../translator/ApsFormJsonTranslator.java | 2 +- .../translator/ApsProcessBpmnTranslator.java | 32 ++++++--- .../translator/ApsProcessJsonTranslator.java | 8 +-- .../maven/aps/modeling/util/ModelUtil.java | 66 +++++++++++-------- .../aps/modeling/xml/CDATAFlexSection.java | 31 --------- src/main/resources/bpmn.xslt | 7 +- 20 files changed, 223 insertions(+), 181 deletions(-) delete mode 100644 src/main/java/com/inteligr8/maven/aps/modeling/xml/CDATAFlexSection.java diff --git a/pom.xml b/pom.xml index ce55cfa..f0236b6 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 @@ -216,8 +216,7 @@ ${aps-model.baseUrl} ${aps-model.authType} - ${aps-model.basicAuth.username} - ${aps-model.basicAuth.password} + ${aps-model.basicAuth.mavenServerId} ${aps-model.appName} 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 e3d8f43..b191c07 100644 --- a/src/it/download-app/pom.xml +++ b/src/it/download-app/pom.xml @@ -21,14 +21,14 @@ download-app - validate + generate-sources download-app download-app-other - validate + generate-sources download-app diff --git a/src/it/pack-app/pom.xml b/src/it/pack-app/pom.xml index 9913626..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,7 +21,7 @@ download-unpack-app - validate + generate-sources download-app unpack-app @@ -36,11 +32,12 @@ pack-app - validate + package pack-app + ${basedir} @@ -56,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 5f83a40..5c38c84 100644 --- a/src/it/translate-app/pom.xml +++ b/src/it/translate-app/pom.xml @@ -21,7 +21,7 @@ download-unpack-app - validate + generate-sources download-app unpack-app @@ -33,7 +33,7 @@ translate-app - validate + compile translate-app diff --git a/src/it/unpack-app/pom.xml b/src/it/unpack-app/pom.xml index df47b5b..7dcc93a 100644 --- a/src/it/unpack-app/pom.xml +++ b/src/it/unpack-app/pom.xml @@ -21,7 +21,7 @@ download-unpack-app - validate + generate-sources download-app unpack-app @@ -29,7 +29,7 @@ unpack-app - validate + process-sources unpack-app 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 index 5141963..6393015 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsAddressibleGoal.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsAddressibleGoal.java @@ -1,6 +1,8 @@ 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; @@ -8,32 +10,26 @@ 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.username", required = false, defaultValue = "admin@app.activiti.com" ) - protected String activitiAppAuthBasicUsername; - - @Parameter( property = "aps-model.basicAuth.password", required = false, defaultValue = "admin" ) - protected String activitiAppAuthBasicPassword; + @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.clientId", required = false ) - protected String oauthClientId; + @Parameter( property = "aps-model.oauth.client.mavenServerId", required = false ) + protected String oauthClientServerId; - @Parameter( property = "aps-model.oauth.clientSecret", required = false ) - protected String oauthClientSecret; - - @Parameter( property = "aps-model.oauth.username", required = false ) - protected String oauthUsername; - - @Parameter( property = "aps-model.oauth.password", required = false ) - protected String oauthPassword; + @Parameter( property = "aps-model.oauth.mavenServerId", required = false ) + protected String oauthServerId; @Parameter( property = "aps-model.oauth.tokenUrl", required = false ) protected String oauthTokenUrl; @@ -47,21 +43,41 @@ public abstract class ApsAddressibleGoal extends DisablableGoal { 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); + + 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); - this.getLog().debug("OAuth Client ID: " + this.oauthClientId); - this.getLog().debug("OAuth Username: " + this.oauthUsername); 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); - config.setOAuthClientId(this.oauthClientId); - config.setOAuthClientSecret(this.oauthClientSecret); - config.setOAuthUsername(this.oauthUsername); - config.setOAuthPassword(this.oauthPassword); break; default: throw new IllegalArgumentException("The 'activitiAppAuthType' configuration must be either 'Basic' or 'OAuth'"); diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/goal/DeployAppGoal.java b/src/main/java/com/inteligr8/maven/aps/modeling/goal/DeployAppGoal.java index 1a7d87e..2f8540e 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/goal/DeployAppGoal.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/DeployAppGoal.java @@ -5,12 +5,15 @@ 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,13 +22,14 @@ import com.inteligr8.alfresco.activiti.model.AppDefinitionUpdateResultRepresenta @Component( role = org.apache.maven.plugin.Mojo.class ) public class DeployAppGoal extends ApsAppAccessibleGoal { - @Parameter( property = "sourceDirectory", required = true, defaultValue = "${project.build.directory}/aps/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; protected final int bufferSize = 128 * 1024; + private final MediaType zipMediaType = MediaType.valueOf("application/zip"); @Override public void executeEnabled() throws MojoExecutionException, MojoFailureException { @@ -36,21 +40,21 @@ public class DeployAppGoal extends ApsAppAccessibleGoal { try { 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); } @@ -61,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/PackAppGoal.java b/src/main/java/com/inteligr8/maven/aps/modeling/goal/PackAppGoal.java index 2db4965..69bf6c1 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/goal/PackAppGoal.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/PackAppGoal.java @@ -22,11 +22,11 @@ import org.codehaus.plexus.component.annotations.Component; @Component( role = org.apache.maven.plugin.Mojo.class ) public class PackAppGoal extends ApsAppGoal { - @Parameter( property = "sourceDirectory", required = true, defaultValue = "${project.build.directory}/aps/app" ) - protected File sourceDirectory; - - @Parameter( property = "targetDirectory", required = true, defaultValue = "${project.build.directory}/aps/app" ) - protected File targetDirectory; + @Parameter( property = "aps-model.app.directory", required = true, defaultValue = "${project.build.directory}/aps/app" ) + protected File unzipDirectory; + + @Parameter( property = "aps-model.upload.directory", required = true, defaultValue = "${project.build.directory}/aps" ) + protected File zipDirectory; protected final int bufferSize = 128 * 1024; @@ -45,17 +45,17 @@ public class PackAppGoal extends ApsAppGoal { } 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); } @@ -64,19 +64,19 @@ public class PackAppGoal extends ApsAppGoal { } 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(); } @@ -92,6 +92,7 @@ public class PackAppGoal extends ApsAppGoal { ZipOutputStream zostream = new ZipOutputStream(bostream); try { this.zipDirectory(appDirectory, null, zostream); + zostream.flush(); } finally { zostream.close(); } @@ -118,7 +119,8 @@ public class PackAppGoal extends ApsAppGoal { 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 index e33ebc6..126a899 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/goal/TranslateAppGoal.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/TranslateAppGoal.java @@ -4,12 +4,10 @@ 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; import com.inteligr8.maven.aps.modeling.crawler.ApsAppCrawler; @@ -19,12 +17,6 @@ import com.inteligr8.maven.aps.modeling.translator.ApsAppTranslator; @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 = "aps-model.app.directory", required = true, defaultValue = "${project.build.directory}/aps/app" ) protected File unzipDirectory; diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/goal/UnpackAppGoal.java b/src/main/java/com/inteligr8/maven/aps/modeling/goal/UnpackAppGoal.java index f47571c..062e68e 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/goal/UnpackAppGoal.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/UnpackAppGoal.java @@ -188,7 +188,7 @@ public class UnpackAppGoal extends ApsAppGoal { case "json": this.getLog().debug("Reformatting file: " + file); Map json = ModelUtil.getInstance().readJsonAsMap(file); - ModelUtil.getInstance().writeJson(json, file); + ModelUtil.getInstance().writeJson(json, file, false); break; case "xml": case "bpmn": 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 index 27efb01..a7277e7 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsAppJsonNormalizer.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsAppJsonNormalizer.java @@ -36,17 +36,18 @@ public class ApsAppJsonNormalizer implements ApsFileNormalizer { ObjectNode jsonModel = (ObjectNode)_jsonModel; int fields = jsonModel.size(); - jsonModel.remove(Arrays.asList("createdBy", "createdByFullName", "lastUpdatedBy", "lastUpdatedByFullName", "lastUpdated")); + 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) - ApsModelArrayNodeSorter.getInstance().sort(jsonModels, "name"); + changed = ApsModelArrayNodeSorter.getInstance().sort(jsonModels, "name") || changed; if (changed) - ModelUtil.getInstance().writeJson(descriptor, file); + ModelUtil.getInstance().writeJson(descriptor, file, this.enableSorting); } } 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 index 46d903f..cc0e1ac 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsProcessJsonNormalizer.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsProcessJsonNormalizer.java @@ -37,7 +37,7 @@ public class ApsProcessJsonNormalizer implements ApsFileNormalizer { changed = ApsModelArrayNodeSorter.getInstance().sort(jsonChildShapes, "resourceId") || changed; if (changed) - ModelUtil.getInstance().writeJson(jsonDescriptor, file); + ModelUtil.getInstance().writeJson(jsonDescriptor, file, this.enableSorting); } private ArrayNode getChildShapes(ObjectNode jsonDescriptor) { diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsAppJsonTranslator.java b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsAppJsonTranslator.java index 0e581eb..95eccca 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsAppJsonTranslator.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsAppJsonTranslator.java @@ -2,7 +2,6 @@ package com.inteligr8.maven.aps.modeling.translator; import java.io.File; import java.io.IOException; -import java.util.Arrays; import java.util.Map; import org.slf4j.Logger; @@ -67,10 +66,14 @@ public class ApsAppJsonTranslator implements ApsFileTranslator { } } - int fields = jsonModel.size(); - jsonModel.remove(Arrays.asList("version")); - if (jsonModel.size() < fields) + 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")) { @@ -90,11 +93,15 @@ public class ApsAppJsonTranslator implements ApsFileTranslator { } else { this.logger.trace("The organization '{}' ID does not change; leaving unchanged", fileOrgName); } - + if (jsonGroup.has("parentGroupId")) { - jsonGroup.remove("parentGroupName"); + jsonGroup.put("parentGroupId", 0); changed = true; } +// if (jsonGroup.has("parentGroupId")) { +// jsonGroup.remove("parentGroupId"); +// changed = true; +// } } else { this.logger.warn("The organization '{}' does not exist in APS", fileOrgName); // FIXME create the organization @@ -102,7 +109,7 @@ public class ApsAppJsonTranslator implements ApsFileTranslator { } if (changed) - ModelUtil.getInstance().writeJson(descriptor, file); + ModelUtil.getInstance().writeJson(descriptor, file, false); } } diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsFormJsonTranslator.java b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsFormJsonTranslator.java index 91b853a..eb46762 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsFormJsonTranslator.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsFormJsonTranslator.java @@ -46,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/translator/ApsProcessBpmnTranslator.java b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsProcessBpmnTranslator.java index 783bc44..456f74a 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsProcessBpmnTranslator.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsProcessBpmnTranslator.java @@ -25,7 +25,6 @@ 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; -import com.inteligr8.maven.aps.modeling.xml.CDATAFlexSection; public class ApsProcessBpmnTranslator implements ApsFileTranslator { @@ -106,6 +105,7 @@ public class ApsProcessBpmnTranslator implements ApsFileTranslator { if (apsProcessId != null) changed = this.setAttributeIfSet(definitionsElement, NAMESPACE_ACTIVITI_MODELER, "modelId", apsProcessId) || changed; changed = this.removeAttributeIfSet(definitionsElement, NAMESPACE_ACTIVITI_MODELER, "modelVersion") || changed; + //changed = this.setAttributeIfSet(definitionsElement, NAMESPACE_ACTIVITI_MODELER, "modelVersion", "0") || changed; return changed; } @@ -200,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); @@ -244,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); @@ -289,23 +289,37 @@ public class ApsProcessBpmnTranslator implements ApsFileTranslator { 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/translator/ApsProcessJsonTranslator.java b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsProcessJsonTranslator.java index ec6a60e..9c0175e 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsProcessJsonTranslator.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsProcessJsonTranslator.java @@ -45,7 +45,7 @@ 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) { @@ -130,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; @@ -143,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/ModelUtil.java b/src/main/java/com/inteligr8/maven/aps/modeling/util/ModelUtil.java index 38bed1d..65f7739 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/util/ModelUtil.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/util/ModelUtil.java @@ -27,7 +27,7 @@ import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; -import org.w3c.dom.CDATASection; +import org.w3c.dom.CharacterData; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -38,12 +38,10 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; -import com.inteligr8.maven.aps.modeling.xml.CDATAFlexSection; import com.inteligr8.maven.aps.modeling.xml.DomNamespaceContext; public class ModelUtil { - public final static QName CDATA = QName.valueOf("inteligr8:xml:cdata"); public final static QName CDATA_FLEX = QName.valueOf("inteligr8:xml:cdata_or_element"); private final static ModelUtil INSTANCE = new ModelUtil(); @@ -54,6 +52,7 @@ public class ModelUtil { private final ObjectMapper om = new ObjectMapper(); + private final ObjectMapper omsorted = new ObjectMapper(); private final DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance(); private final DocumentBuilder docBuilder; private final XPathFactory xpathfactory = XPathFactory.newInstance(); @@ -81,26 +80,28 @@ public class ModelUtil { // makes Git handling a whole lot better this.om.enable(SerializationFeature.INDENT_OUTPUT); + this.omsorted.enable(SerializationFeature.INDENT_OUTPUT); + // makes Git handling better between environment nuances - this.om.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY); - this.om.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS); + this.omsorted.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY); + this.omsorted.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS); } - public void json(File inplaceFile) throws IOException { + public void json(File inplaceFile, boolean enableSorting) throws IOException { JsonNode json = this.readJson(inplaceFile); - this.writeJson(json, inplaceFile); + this.writeJson(json, inplaceFile, enableSorting); } - public void json(File sourceFile, File targetFile) throws IOException { + public void json(File sourceFile, File targetFile, boolean enableSorting) throws IOException { FileInputStream fistream = new FileInputStream(sourceFile); BufferedInputStream bistream = new BufferedInputStream(fistream, this.bufferSize); try { FileOutputStream fostream = new FileOutputStream(targetFile); BufferedOutputStream bostream = new BufferedOutputStream(fostream, this.bufferSize); try { - this.json(bistream, bostream); + this.json(bistream, bostream, enableSorting); } finally { bostream.close(); } @@ -109,10 +110,10 @@ public class ModelUtil { } } - public void json(InputStream istream, OutputStream ostream) throws IOException { + public void json(InputStream istream, OutputStream ostream, boolean enableSorting) throws IOException { // FIXME stream it for lower memory/IO usage JsonNode json = this.readJson(istream); - this.writeJson(json, ostream); + this.writeJson(json, ostream, enableSorting); } public JsonNode readJson(File file) throws IOException { @@ -167,32 +168,40 @@ public class ModelUtil { return this.om.readValue(istream, Map.class); } - public void writeJson(JsonNode json, File file) throws IOException { + public void writeJson(JsonNode json, File file, boolean enableSorting) throws IOException { FileOutputStream fostream = new FileOutputStream(file); BufferedOutputStream bostream = new BufferedOutputStream(fostream, this.bufferSize); try { - this.writeJson(json, bostream); + this.writeJson(json, bostream, enableSorting); } finally { bostream.close(); } } - public void writeJson(Map map, File file) throws IOException { + public void writeJson(Map map, File file, boolean enableSorting) throws IOException { FileOutputStream fostream = new FileOutputStream(file); BufferedOutputStream bostream = new BufferedOutputStream(fostream, this.bufferSize); try { - this.writeJson(map, bostream); + this.writeJson(map, bostream, enableSorting); } finally { bostream.close(); } } - public void writeJson(JsonNode json, OutputStream ostream) throws IOException { - this.om.writeValue(ostream, json); + public void writeJson(JsonNode json, OutputStream ostream, boolean enableSorting) throws IOException { + if (enableSorting) { + this.omsorted.writeValue(ostream, json); + } else { + this.om.writeValue(ostream, json); + } } - public void writeJson(Map map, OutputStream ostream) throws IOException { - this.om.writeValue(ostream, map); + public void writeJson(Map map, OutputStream ostream, boolean enableSorting) throws IOException { + if (enableSorting) { + this.omsorted.writeValue(ostream, map); + } else { + this.om.writeValue(ostream, map); + } } @@ -277,22 +286,23 @@ public class ModelUtil { XPath xpath = this.xpathfactory.newXPath(); xpath.setNamespaceContext(new DomNamespaceContext(node)); - boolean isFlex = returnType.equals(ModelUtil.CDATA_FLEX); - - if (returnType.equals(ModelUtil.CDATA) || isFlex) { + if (returnType.equals(ModelUtil.CDATA_FLEX)) { NodeList nodes = (NodeList)xpath.evaluate(xpathExpr, node, XPathConstants.NODESET); Node anode = this.getFirstCDataSectionOrLastElement(nodes); - if (anode instanceof CDATASection) { + if (anode instanceof CharacterData) { // nothing special } else if (anode instanceof Element) { Node anode2 = this.getFirstCDataSectionOrLastElement(anode.getChildNodes()); - if (anode2 != null) - return anode = anode2; + if (anode2 == null) + return null; + if (!(anode2 instanceof CharacterData)) + throw new IllegalStateException(); + anode = anode2; } else { return null; } - return isFlex ? new CDATAFlexSection(anode) : anode; + return anode; } else { return xpath.evaluate(xpathExpr, node, returnType); } @@ -303,8 +313,8 @@ public class ModelUtil { for (int n = 0; n < nodes.getLength(); n++) { Node anode = nodes.item(n); - if (anode.getNodeType() == Node.CDATA_SECTION_NODE) { - return (CDATASection)anode; + if (anode instanceof CharacterData) { + return (CharacterData)anode; } else if (anode.getNodeType() == Node.ELEMENT_NODE) { element = (Element)anode; } diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/xml/CDATAFlexSection.java b/src/main/java/com/inteligr8/maven/aps/modeling/xml/CDATAFlexSection.java deleted file mode 100644 index c0f5397..0000000 --- a/src/main/java/com/inteligr8/maven/aps/modeling/xml/CDATAFlexSection.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.inteligr8.maven.aps.modeling.xml; - -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/resources/bpmn.xslt b/src/main/resources/bpmn.xslt index 9659319..05b3f84 100644 --- a/src/main/resources/bpmn.xslt +++ b/src/main/resources/bpmn.xslt @@ -1,9 +1,14 @@ - + + + <![CDATA[ + + ]]> +