From 99d76df7085b94ebdf059bfb39f355f813f8997a Mon Sep 17 00:00:00 2001 From: Brian Long Date: Mon, 10 Oct 2022 22:14:02 -0400 Subject: [PATCH] added docs; logging; prep for maven central --- pom.xml | 185 +++++++----- .../aps/modeling/crawler/ApsAppCrawlable.java | 35 +++ .../aps/modeling/crawler/ApsAppCrawler.java | 44 ++- .../modeling/crawler/ApsFileTransformer.java | 29 ++ .../aps/modeling/goal/ApsAddressibleGoal.java | 33 +++ .../modeling/goal/ApsAppAccessibleGoal.java | 60 ++++ .../maven/aps/modeling/goal/ApsAppGoal.java | 19 ++ .../maven/aps/modeling/goal/ApsInfoGoal.java | 23 ++ .../maven/aps/modeling/goal/ApsShareGoal.java | 25 ++ .../aps/modeling/goal/DisablableGoal.java | 26 ++ .../aps/modeling/goal/DownloadAppGoal.java | 23 ++ .../maven/aps/modeling/goal/PackAppGoal.java | 23 ++ .../aps/modeling/goal/PublishAppGoal.java | 22 ++ .../aps/modeling/goal/TranslateAppGoal.java | 28 ++ .../aps/modeling/goal/UnpackAppGoal.java | 23 ++ .../aps/modeling/goal/UploadAppGoal.java | 24 ++ .../normalizer/ApsAppJsonNormalizer.java | 32 +++ .../modeling/normalizer/ApsAppNormalizer.java | 42 +++ .../normalizer/ApsFileNormalizer.java | 26 ++ .../normalizer/ApsFormJsonNormalizer.java | 21 ++ .../normalizer/ApsProcessBpmnNormalizer.java | 22 ++ .../normalizer/ApsProcessJsonNormalizer.java | 36 ++- .../translator/ApsAppJsonTranslator.java | 60 +++- .../modeling/translator/ApsAppTranslator.java | 53 +++- .../translator/ApsFileTranslator.java | 31 ++ .../translator/ApsFormJsonTranslator.java | 26 ++ .../translator/ApsOrganizationHandler.java | 23 ++ .../translator/ApsProcessBpmnTranslator.java | 36 +++ .../translator/ApsProcessJsonTranslator.java | 55 +++- .../maven/aps/modeling/util/Index.java | 80 ++++++ .../aps/modeling/util/MapComparator.java | 40 +++ .../maven/aps/modeling/util/ModelUtil.java | 270 +++++++++++++++++- .../modeling/util/ObjectNodeComparator.java | 48 +++- .../aps/modeling/xml/DomNamespaceContext.java | 29 ++ 34 files changed, 1447 insertions(+), 105 deletions(-) diff --git a/pom.xml b/pom.xml index 15b7d40..05d44ec 100644 --- a/pom.xml +++ b/pom.xml @@ -1,8 +1,7 @@ - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 com.inteligr8.alfresco @@ -11,8 +10,19 @@ maven-plugin A Maven plugin for Alfresco Process Services model portability + Generate Alfresco Module Packages (AMP) files in a way simialr to WAR files + https://bitbucket.org/inteligr8/amp-maven-plugin + + + + GNU GENERAL PUBLIC LICENSE, Version 3, 29 June 2007 + https://www.gnu.org/licenses/lgpl-3.0.txt + + + scm:git:https://bitbucket.org/inteligr8/aps-model-maven-plugin.git + scm:git:git@bitbucket.org:inteligr8/aps-model-maven-plugin.git https://bitbucket.org/inteligr8/aps-model-maven-plugin @@ -41,14 +51,12 @@ com.inteligr8.alfresco aps-public-rest-api - 2.0.1 - aps1 + 2.0.3-aps1 com.inteligr8.alfresco aps-public-rest-client - 2.0.1 - jersey + 2.0.2-jersey org.apache.commons @@ -109,10 +117,36 @@ + + + + maven-invoker-plugin + 3.2.2 + + ${basedir}/src/it + ${project.build.directory}/it + ${project.build.directory}/it-repo + ${env.MAVEN_HOME} + true + ${skipTests} + + ${basedir} + ${aps-model.baseUrl} + ${aps-model.authType} + ${aps-model.basicAuth.mavenServerId} + ${aps-model.appName} + ${aps-model.share.editors} + ${aps-model.share.readers} + ${aps-model.share.app.editors} + + + + + maven-plugin-plugin - 3.6.0 + 3.6.1 aps-model @@ -143,55 +177,29 @@ - - maven-invoker-plugin - 3.2.2 - - ${basedir}/src/it - ${project.build.directory}/it - ${project.build.directory}/it-repo - ${env.MAVEN_HOME} - true - ${skipTests} - - ${basedir} - ${aps-model.baseUrl} - ${aps-model.authType} - ${aps-model.basicAuth.mavenServerId} - ${aps-model.appName} - ${aps-model.share.editors} - ${aps-model.share.readers} - ${aps-model.share.app.editors} - - - - - run-its - - install - run - - - - - - maven-javadoc-plugin - - - javadoc - package - jar - - public - true - - - - - + + + run-its + + + + maven-invoker-plugin + + + run-its + + install + run + + + + + + + run-it-1 @@ -203,10 +211,9 @@ maven-invoker-plugin - 3.2.2 - run-its + run-it-1 install run @@ -222,22 +229,56 @@ + + ossrh-release + + + + maven-source-plugin + + + source + package + jar-no-fork + + + + + maven-javadoc-plugin + + + javadoc + package + jar + + public + + + + + + maven-gpg-plugin + + + sign + verify + sign + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.13 + true + + ossrh + https://s01.oss.sonatype.org/ + true + + + + + - - - - inteligr8-releases - Inteligr8 Releases - https://repos.inteligr8.com/nexus/repository/inteligr8-public - - - - - - inteligr8-releases - Inteligr8 Releases - https://repos.inteligr8.com/nexus/repository/inteligr8-public - - - 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 index 390da7f..0c53a3d 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/crawler/ApsAppCrawlable.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/crawler/ApsAppCrawlable.java @@ -1,13 +1,48 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.crawler; +/** + * An interface for APS App export transformation implementations. + * + * An APS App export is a ZIP file that always contains an APS App JSON file. + * It may also contain many process XML/JSON files, form JSON files, thumbnail + * images, and more. + * + * @author brian@inteligr8.com + */ public interface ApsAppCrawlable { + /** + * @return A file transformer for APS App JSON files. + */ ApsFileTransformer getAppJsonTransformer(); + /** + * @return A file transformer for APS Process JSON files. + */ ApsFileTransformer getProcessJsonTransformer(); + /** + * @return A file transformer for APS Process BPMN (XML) files. + */ ApsFileTransformer getProcessBpmnTransformer(); + /** + * @return A file transformer for APS Form JSON files. + */ 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 index 9639572..bdc9629 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/crawler/ApsAppCrawler.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/crawler/ApsAppCrawler.java @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.crawler; import java.io.File; @@ -11,6 +25,12 @@ import java.util.regex.Pattern; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * A class that implements a APS App export crawler. The crawler does not + * directly perform any transformations. Those are handled through a callback. + * + * @author brian@inteligr8.com + */ public class ApsAppCrawler { private final Logger logger = LoggerFactory.getLogger(ApsAppCrawler.class); @@ -20,27 +40,39 @@ public class ApsAppCrawler { private final File appDescriptor; private final boolean failOnIntegrityViolation; + /** + * @param apsAppName A name for the APS App. + * @param apsAppDirectory A directory to the unpacked APS App export. + * @param failOnIntegrityViolation true to fail on file integrity issues; false to log warnings. + */ public ApsAppCrawler(String apsAppName, File apsAppDirectory, boolean failOnIntegrityViolation) { this.appName = apsAppName; this.appDirectory = apsAppDirectory; this.failOnIntegrityViolation = failOnIntegrityViolation; - this.appDescriptor = this.validateDescriptor(appDirectory); + this.appDescriptor = this.validateDescriptor(); 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"); + /** + * @return A file handle to the root APS App JSON (configuration) file. + */ + protected File validateDescriptor() { + File appDescriptor = new File(this.appDirectory, this.appName + ".json"); if (!appDescriptor.exists()) - throw new IllegalStateException("The APS App descriptor could not be found: " + appDescriptor); + throw new IllegalStateException("The APS App descriptor could not be found: " + this.appDescriptor); if (!appDescriptor.isFile()) - throw new IllegalStateException("The APS App descriptor is not a file: " + appDescriptor); + throw new IllegalStateException("The APS App descriptor is not a file: " + this.appDescriptor); return appDescriptor; } + /** + * @param crawlable A crawlable implementation; the callback for potential transformations. + * @throws IOException A file access exception occurred. + */ public void execute(ApsAppCrawlable crawlable) throws IOException { this.logger.info("Crawling APS App ..."); @@ -83,7 +115,7 @@ public class ApsAppCrawler { } String modelName = matcher.group(1); - Long modelId = new Long(matcher.group(2)); + Long modelId = Long.valueOf(matcher.group(2)); this.logger.trace("Transforming model {} ID: {}", modelName, modelId); this.transform(transformer, modelFile, modelName, modelId); 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 index 8e9ac56..937da1e 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/crawler/ApsFileTransformer.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/crawler/ApsFileTransformer.java @@ -1,10 +1,39 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.crawler; import java.io.File; import java.io.IOException; +/** + * This interface provides a common method for transforming various files in an + * exported APS App. + * + * @author brian@inteligr8.com + */ public interface ApsFileTransformer { + /** + * This method transforms the specified file which should be referred to + * with the specified name and ID. + * + * @param file A model file. + * @param modelName The target model name. + * @param modelId The target model ID. + * @throws IOException An I/O related exception has occurred during transformation. + */ 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 index 896fca5..dfac7bc 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,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.goal; import org.apache.maven.execution.MavenSession; @@ -8,6 +22,14 @@ import com.inteligr8.alfresco.activiti.ApsClientJerseyConfiguration; import com.inteligr8.alfresco.activiti.ApsClientJerseyImpl; import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl; +/** + * This class adds APS addressbility to extending goals. + * + * This is a common need for several goals in this library, as most of those + * goals will need to call an APS service to perform their work. + * + * @author brian@inteligr8.com + */ public abstract class ApsAddressibleGoal extends DisablableGoal { @Parameter( defaultValue = "${session}", readonly = true ) @@ -36,6 +58,14 @@ public abstract class ApsAddressibleGoal extends DisablableGoal { private ApsPublicRestApiJerseyImpl api; + /** + * Retrieves an APS client configuration. + * + * The configuration is built based on the properties injected into this + * class. It supports either `BASIC` or `OAuth` based authentication. + * + * @return An APS client configuration. + */ public ApsClientJerseyConfiguration getApsClientConfiguration() { this.getLog().debug("Configuring APS to URL: " + this.activitiAppBaseUrl); ApsClientJerseyConfiguration config = new ApsClientJerseyConfiguration(); @@ -86,6 +116,9 @@ public abstract class ApsAddressibleGoal extends DisablableGoal { return config; } + /** + * @return An APS API instance. + */ public synchronized ApsPublicRestApiJerseyImpl getApsApi() { if (this.api == null) { ApsClientJerseyConfiguration config = this.getApsClientConfiguration(); 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 index 2f0692e..b83abc8 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsAppAccessibleGoal.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsAppAccessibleGoal.java @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.goal; import java.util.HashMap; @@ -13,11 +27,28 @@ import com.inteligr8.alfresco.activiti.model.Datum; import com.inteligr8.alfresco.activiti.model.ResultListDataRepresentation; import com.inteligr8.alfresco.activiti.model.Tenant; +/** + * This class adds the APS App name to APS addressibility to extending goals. + * + * Only use this class if your goal needs both the APS name and an APS service + * client. You can use `ApsAppGoal` or `ApsAddressibleGoal` if you only need + * one of those capabilities. + * + * @author brian@inteligr8.com + */ public abstract class ApsAppAccessibleGoal extends ApsAddressibleGoal { @Parameter( property = "aps-model.appName", required = true ) protected String apsAppName; + /** + * This method makes the appropriate service calls to find the first APS + * tenant ID from the configured APS service. + * + * This method does not cache the result. + * + * @return An APS tenant ID; null only if there are no tenants. + */ protected Long findTenantId() { List tenants = this.getApsApi().getAdminApi().getTenants(); if (tenants == null || tenants.isEmpty()) @@ -25,6 +56,14 @@ public abstract class ApsAppAccessibleGoal extends ApsAddressibleGoal { return tenants.iterator().next().getId(); } + /** + * This method makes the appropriate service calls to find all the APS + * Apps, returning them as a map of names to IDs. + * + * This method does not cache the result. + * + * @return A map of APS App names to their respective IDs; may be empty; never null. + */ protected Map findAppNameIds() { ApsPublicRestApiJerseyImpl api = this.getApsApi(); @@ -42,10 +81,31 @@ public abstract class ApsAppAccessibleGoal extends ApsAddressibleGoal { return apps; } + /** + * This method makes the appropriate service calls to find the APS App by + * the configured APS App name. + * + * This method does not cache the result. + * + * @param failOnNotFound true to fail if not found; false to return null. + * @return An APS App ID; null if not found. + * @throws MojoExecutionException The APS App could not be found. + */ protected Long findAppId(boolean failOnNotFound) throws MojoExecutionException { return this.findAppIdByName(this.apsAppName, failOnNotFound); } + /** + * This method makes the appropriate service calls to find an APS App by + * the specified APS App name. + * + * This method does not cache the result. + * + * @param apsName An APS App name. + * @param failOnNotFound true to fail if not found; false to return null. + * @return An APS App ID; null if not found. + * @throws MojoExecutionException The APS App could not be found. + */ protected Long findAppIdByName(String appName, boolean failOnNotFound) throws MojoExecutionException { Map apps = this.findAppNameIds(); Long appId = apps.get(this.apsAppName); 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 index e60b081..534bd48 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsAppGoal.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsAppGoal.java @@ -1,7 +1,26 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.goal; import org.apache.maven.plugins.annotations.Parameter; +/** + * This class adds the APS App name to extending goals. + * + * @author brian@inteligr8.com + */ public abstract class ApsAppGoal extends DisablableGoal { @Parameter( property = "aps-model.appName", required = true ) diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsInfoGoal.java b/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsInfoGoal.java index d3764d5..b0dbd22 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsInfoGoal.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsInfoGoal.java @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.goal; import org.apache.maven.plugin.MojoExecutionException; @@ -7,6 +21,15 @@ import org.codehaus.plexus.component.annotations.Component; import com.inteligr8.alfresco.activiti.model.AppVersion; +/** + * A class that implements an APS service information goal. + * + * This goal will simply output the APS edition and version to the Maven output + * at the `INFO` level. It is a great way to test your connection + * configuration and network accessibility of the service. + * + * @author brian@inteligr8.com + */ @Mojo( name = "aps-info", threadSafe = true ) @Component( role = org.apache.maven.plugin.Mojo.class ) public class ApsInfoGoal extends ApsAddressibleGoal { diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsShareGoal.java b/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsShareGoal.java index 544d337..a2993dd 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsShareGoal.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/ApsShareGoal.java @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.goal; import java.util.Arrays; @@ -24,6 +38,17 @@ import com.inteligr8.alfresco.activiti.model.SharePermission; import com.inteligr8.alfresco.activiti.model.Tenant; import com.inteligr8.maven.aps.modeling.util.Index; +/** + * A class that implements a way to 'share' APS models. + * + * All APS models are automatically owned by the person that creates them. The + * model is then not viewable or editable by anyone else, except for APS + * administrators. This class provides a way to automatically 'share' the + * synchronized models to groups or individual users. The 'share' may have + * readonly or editing capabilities, as configured. + * + * @author brian@inteligr8.com + */ @Mojo( name = "share-models", threadSafe = true ) @Component( role = org.apache.maven.plugin.Mojo.class ) public class ApsShareGoal extends ApsAddressibleGoal { 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 index ba1c368..efa8071 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/goal/DisablableGoal.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/DisablableGoal.java @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.goal; import org.apache.maven.plugin.AbstractMojo; @@ -5,6 +19,10 @@ import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Parameter; +/** + * This class adds enable/disable capability to any goal. It uses the standard + * 'skip' terminology. + */ public abstract class DisablableGoal extends AbstractMojo { @Parameter( property = "aps-model.skip", required = true, defaultValue = "false" ) @@ -24,6 +42,14 @@ public abstract class DisablableGoal extends AbstractMojo { this.executeEnabled(); } + /** + * Identical to the `AbstractMojo.execute()` method, but it is only called + * when this is enabled. + * + * @throws MojoExecutionException The goal failed to execute. + * @throws MojoFailureException The goal failed whiling executing. + * @see org.apache.maven.plugin.AbstractMojo.execute() + */ public abstract void executeEnabled() throws MojoExecutionException, MojoFailureException; } diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/goal/DownloadAppGoal.java b/src/main/java/com/inteligr8/maven/aps/modeling/goal/DownloadAppGoal.java index 579efc6..d37f73b 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/goal/DownloadAppGoal.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/DownloadAppGoal.java @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.goal; import java.io.File; @@ -12,6 +26,15 @@ import org.codehaus.plexus.component.annotations.Component; import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl; +/** + * A class that implements an APS service download goal. + * + * This goal will simply download the APS App with the specified name from the + * specified APS service. The downloaded APS App will remain packed (zipped). + * If a file exists with a conflicting name, it will be overwritten. + * + * @author brian@inteligr8.com + */ @Mojo( name = "download-app", threadSafe = true ) @Component( role = org.apache.maven.plugin.Mojo.class ) public class DownloadAppGoal extends ApsAppAccessibleGoal { 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 69bf6c1..59e0f0c 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 @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.goal; import java.io.BufferedInputStream; @@ -18,6 +32,15 @@ import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.codehaus.plexus.component.annotations.Component; +/** + * A class that implements an APS App packaging goal. + * + * This goal will simply pack (zip) a folder containing an APS App file + * structure. If a file exists with a conflicting name, it will be + * overwritten. + * + * @author brian@inteligr8.com + */ @Mojo( name = "pack-app", threadSafe = true ) @Component( role = org.apache.maven.plugin.Mojo.class ) public class PackAppGoal extends ApsAppGoal { diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/goal/PublishAppGoal.java b/src/main/java/com/inteligr8/maven/aps/modeling/goal/PublishAppGoal.java index fb06bc0..5541a17 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/goal/PublishAppGoal.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/PublishAppGoal.java @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.goal; import java.io.IOException; @@ -11,6 +25,14 @@ import org.codehaus.plexus.component.annotations.Component; import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl; import com.inteligr8.alfresco.activiti.model.AppDefinitionPublishRepresentation; +/** + * A class that implements an APS Service publish goal. + * + * This goal will simply attempt to publish an existing APS App using the APS + * Service. It is typically used in conjuection with the `upload-app` goal. + * + * @author brian@inteligr8.com + */ @Mojo( name = "publish-app", threadSafe = true ) @Component( role = org.apache.maven.plugin.Mojo.class ) public class PublishAppGoal extends ApsAppAccessibleGoal { 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 126a899..e305016 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 @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.goal; import java.io.File; @@ -13,6 +27,20 @@ import org.codehaus.plexus.component.annotations.Component; import com.inteligr8.maven.aps.modeling.crawler.ApsAppCrawler; import com.inteligr8.maven.aps.modeling.translator.ApsAppTranslator; +/** + * A class that implements an APS App translation goal. + * + * This goal will translate all the JSON and XML files in an APS App to match + * the environment referenced by the specified APS App. This relies on all APS + * model elements (apps, processes, and forms) to have unique names. The names + * of those mdoel elements are used to remap IDs between environments. + * + * APS does not enforce a unique name constraint. But it is good practice to + * avoid using the same name anyhow. This plugin will just make you do it. It + * will error if a duplicate is detected. + * + * @author brian@inteligr8.com + */ @Mojo( name = "translate-app", threadSafe = true ) @Component( role = org.apache.maven.plugin.Mojo.class ) public class TranslateAppGoal extends ApsAppAccessibleGoal { 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 062e68e..27a49be 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 @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.goal; import java.io.BufferedInputStream; @@ -29,6 +43,15 @@ import com.inteligr8.maven.aps.modeling.crawler.ApsAppCrawler; import com.inteligr8.maven.aps.modeling.normalizer.ApsAppNormalizer; import com.inteligr8.maven.aps.modeling.util.ModelUtil; +/** + * A class that implements an APS App unpackaging goal. + * + * This goal will simply unpack (unzip) an APS App export into a folder. If a + * folder of the APS App name already exists, it will be cleared before the + * export is unpacked into it. + * + * @author brian@inteligr8.com + */ @Mojo( name = "unpack-app", threadSafe = true ) @Component( role = org.apache.maven.plugin.Mojo.class ) public class UnpackAppGoal extends ApsAppGoal { diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/goal/UploadAppGoal.java b/src/main/java/com/inteligr8/maven/aps/modeling/goal/UploadAppGoal.java index 3d0b1db..9396a6a 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/goal/UploadAppGoal.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/goal/UploadAppGoal.java @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.goal; import java.io.BufferedInputStream; @@ -16,6 +30,16 @@ import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl; import com.inteligr8.alfresco.activiti.model.AppDefinitionUpdateResultRepresentation; import com.inteligr8.alfresco.activiti.model.FileMultipartJersey; +/** + * A class that implements an APS service upload goal. + * + * This goal will simply upload an APS App package with the specified name to + * the specified APS service. Any IDs specified in the uploaded package must + * match existing IDs for them to properly version. That is the main purpose + * of this plugin and can be achieved using the 'translate-app' goal. + * + * @author brian@inteligr8.com + */ @Mojo( name = "upload-app", threadSafe = true ) @Component( role = org.apache.maven.plugin.Mojo.class ) public class UploadAppGoal extends ApsAppAccessibleGoal { 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 a7277e7..f5c7db3 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 @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.normalizer; import java.io.File; @@ -13,12 +27,30 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.inteligr8.maven.aps.modeling.util.ApsModelArrayNodeSorter; import com.inteligr8.maven.aps.modeling.util.ModelUtil; +/** + * This class implements an APS App JSON configuration file normalizer. + * + * This will remove the 'lastUpdated' date of each defined process model. It + * will also order the process 'models' by their respective 'name' values. + * + * @author brian@inteligr8.com + */ public class ApsAppJsonNormalizer implements ApsFileNormalizer { private final Logger logger = LoggerFactory.getLogger(ApsAppJsonNormalizer.class); private final boolean enableSorting; + /** + * This constructor initializes the default normalizer with or without + * sorting. + * + * The sorting feature is available for a better "diff" experience. If + * you intend to commit the APS App configurations to Git, you will want to + * enable sorting. + * + * @param enableSorting true to re-order JSON objects; false to keep as-is. + */ public ApsAppJsonNormalizer(boolean enableSorting) { this.enableSorting = 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 index 6e607db..0f1b4d6 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsAppNormalizer.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsAppNormalizer.java @@ -1,12 +1,54 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.normalizer; import com.inteligr8.maven.aps.modeling.crawler.ApsAppCrawlable; import com.inteligr8.maven.aps.modeling.crawler.ApsFileTransformer; +/** + * This class defines an APS App package normalizer. + * + * An APS App package is a ZIP file that contains multiple files in a + * predictable folder hierachy with predictable file names. It is effectively + * an APS App interchange format specification. + * + * A package must have at least a single configuration file at the root of the + * ZIP package in the JSON format. It must be named the APS App name. That + * file will then reference all the model elements contained in the ZIP. Any + * model elements not referenced will simply be ignored by APS and by this + * plugin. + * + * This class has methods that provide normalizer for all the various model + * elements in an APS App package. + * + * @author brian@inteligr8.com + */ public class ApsAppNormalizer implements ApsAppCrawlable { private final boolean enableSorting; + /** + * This constructor initializes the default normalizer with or without + * sorting. + * + * The sorting feature is available for a better "diff" experience. If + * you intend to commit the APS App configurations to Git, you will want to + * enable sorting. + * + * @param enableSorting true to re-order JSON objects; false to keep as-is. + */ public ApsAppNormalizer(boolean enableSorting) { this.enableSorting = enableSorting; } 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 index 9ff8d1f..844787c 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsFileNormalizer.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsFileNormalizer.java @@ -1,7 +1,33 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.normalizer; +import java.io.File; +import java.io.IOException; + import com.inteligr8.maven.aps.modeling.crawler.ApsFileTransformer; +/** + * This interface defines an APS file normalizer. + * + * Normalization is the transformation of something from one state to a target + * (normalized) state. In this context, a configuration is being normalized to + * be diff-friendly. That principally means the removal of dates. In theory, + * two normalized files will always match unless something of real substance + * has changed. + */ 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 index 5a96d51..5fc1778 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsFormJsonNormalizer.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsFormJsonNormalizer.java @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.normalizer; import java.io.File; @@ -6,6 +20,13 @@ import java.io.IOException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * This class implements an APS Form JSON configuration file normalizer. + * + * This does nothing but log at this time. + * + * @author brian@inteligr8.com + */ public class ApsFormJsonNormalizer implements ApsFileNormalizer { private final Logger logger = LoggerFactory.getLogger(ApsFormJsonNormalizer.class); 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 index 9120c45..da0d3ef 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsProcessBpmnNormalizer.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/normalizer/ApsProcessBpmnNormalizer.java @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.normalizer; import java.io.File; @@ -14,6 +28,14 @@ import org.xml.sax.SAXException; import com.inteligr8.maven.aps.modeling.util.ModelUtil; +/** + * This class implements an APS Process BPMN/XML configuration file normalizer. + * + * This will remove the 'exportDateTime' and 'modelLastUpdated' dates and + * 'modelVersion' of the process model. + * + * @author brian@inteligr8.com + */ public class ApsProcessBpmnNormalizer implements ApsFileNormalizer { private static final String NAMESPACE_ACTIVITI_MODELER = "http://activiti.com/modeler"; 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 cc0e1ac..ea9aca2 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 @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.normalizer; import java.io.File; @@ -12,12 +26,30 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.inteligr8.maven.aps.modeling.util.ApsModelArrayNodeSorter; import com.inteligr8.maven.aps.modeling.util.ModelUtil; +/** + * This class implements an APS Process JSON configuration file normalizer. + * + * This will do nothing unless sorting is enabled. With sorting, it will order + * the 'childShapes' by their respective 'resourceId' values. + * + * @author brian@inteligr8.com + */ public class ApsProcessJsonNormalizer implements ApsFileNormalizer { private final Logger logger = LoggerFactory.getLogger(ApsProcessJsonNormalizer.class); private final boolean enableSorting; + /** + * This constructor initializes the default normalizer with or without + * sorting. + * + * The sorting feature is available for a better "diff" experience. If + * you intend to commit the APS App configurations to Git, you will want to + * enable sorting. + * + * @param enableSorting true to re-order JSON objects; false to keep as-is. + */ public ApsProcessJsonNormalizer(boolean enableSorting) { this.enableSorting = enableSorting; } @@ -33,8 +65,10 @@ public class ApsProcessJsonNormalizer implements ApsFileNormalizer { ObjectNode jsonDescriptor = ModelUtil.getInstance().readJson(file, ObjectNode.class); ArrayNode jsonChildShapes = this.getChildShapes(jsonDescriptor); + this.logger.trace("Found Process shapes: {}: {}", modelName, jsonChildShapes.size()); - changed = ApsModelArrayNodeSorter.getInstance().sort(jsonChildShapes, "resourceId") || changed; + changed = ArrayNodeObjectSorter.getInstance().sort(jsonChildShapes, "resourceId") || changed; + this.logger.trace("Sorted Process shapes: {}: {}", modelName, changed); if (changed) ModelUtil.getInstance().writeJson(jsonDescriptor, file, this.enableSorting); 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 8982aab..64ea976 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 @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.translator; import java.io.File; @@ -15,6 +29,19 @@ import com.inteligr8.alfresco.activiti.model.GroupLight; import com.inteligr8.maven.aps.modeling.util.Index; import com.inteligr8.maven.aps.modeling.util.ModelUtil; +/** + * This class implements an APS App JSON configuration file translator. + * + * This will translate the IDs of all the APS App, Processes, and Organizations + * referenced in the APS App descriptor. + * + * Caution: in lieu of implementing APS User translation, APS User identity + * references are simply removed. Using APS Users in your APS models is bad + * practice. Use APS Organizations, even if that user is the only member of + * the group. + * + * @author brian@inteligr8.com + */ public class ApsAppJsonTranslator extends ApsOrganizationHandler implements ApsFileTranslator { private final Logger logger = LoggerFactory.getLogger(ApsAppJsonTranslator.class); @@ -22,35 +49,45 @@ public class ApsAppJsonTranslator extends ApsOrganizationHandler implements ApsF private final Index apsProcessIndex; private final Index fileProcessIndex; + /** + * This constructor initializes the default translator. + * + * @param api An APS API reference. + * @param apsProcessIndex A map of process IDs to process names as defined in the APS Service. + * @param apsOrgIndex A map of organizations (groups) to organization meta-data as defined in the APS Service. + * @param fileProcessIndex A map of process IDs to process names as used in the local process files. + */ public ApsAppJsonTranslator( ApsPublicRestApi api, - Map apsOrgIndex, Index apsProcessIndex, + Map apsOrgIndex, Index fileProcessIndex) { super(api, apsOrgIndex); - this.apsOrgIndex = apsOrgIndex; this.apsProcessIndex = apsProcessIndex; + this.apsOrgIndex = apsOrgIndex; this.fileProcessIndex = fileProcessIndex; } @Override - public void translateFile(File file, String modelName, Long modelId) throws IOException { + public void translateFile(File file, String appName, Long appId) throws IOException { this.logger.debug("Translating JSON file: {}", file); boolean changed = false; - JsonNode descriptor = ModelUtil.getInstance().readJson(file); + + JsonNode jsonDescriptor = ModelUtil.getInstance().readJson(file); - changed = this.translateModels(descriptor) || changed; - changed = this.translateIdentities(descriptor) || changed; + changed = this.translateModels(jsonDescriptor, appName) || changed; + changed = this.translateIdentities(jsonDescriptor, appName) || changed; if (changed) - ModelUtil.getInstance().writeJson(descriptor, file, false); + ModelUtil.getInstance().writeJson(jsonDescriptor, file, false); } - private boolean translateModels(JsonNode descriptor) { + private boolean translateModels(JsonNode jsonDescriptor, String appName) { + this.logger.trace("Translating processes in App: {}", appName); boolean changed = false; - for (JsonNode _jsonModel : descriptor.get("definition").get("models")) { + for (JsonNode _jsonModel : jsonDescriptor.get("definition").get("models")) { ObjectNode jsonModel = (ObjectNode)_jsonModel; String fileProcessName = jsonModel.get("name").asText(); @@ -91,10 +128,11 @@ public class ApsAppJsonTranslator extends ApsOrganizationHandler implements ApsF return changed; } - private boolean translateIdentities(JsonNode descriptor) { + private boolean translateIdentities(JsonNode jsonDescriptor, String appName) { + this.logger.trace("Translating identities in App: {}", appName); boolean changed = false; - Iterator i = descriptor.get("definition").get("publishIdentityInfo").iterator(); + Iterator i = jsonDescriptor.get("definition").get("publishIdentityInfo").iterator(); while (i.hasNext()) { JsonNode jsonIdentityInfo = i.next(); diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsAppTranslator.java b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsAppTranslator.java index 6fe46d3..e206885 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsAppTranslator.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsAppTranslator.java @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.translator; import java.io.File; @@ -13,7 +27,6 @@ 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.GroupLight; @@ -23,6 +36,24 @@ import com.inteligr8.maven.aps.modeling.crawler.ApsAppCrawlable; import com.inteligr8.maven.aps.modeling.crawler.ApsFileTransformer; import com.inteligr8.maven.aps.modeling.util.Index; +/** + * This class defines an APS App package translator. + * + * An APS App package is a ZIP file that contains multiple files in a + * predictable folder hierachy with predictable file names. It is effectively + * an APS App interchange format specification. + * + * A package must have at least a single configuration file at the root of the + * ZIP package in the JSON format. It must be named the APS App name. That + * file will then reference all the model elements contained in the ZIP. Any + * model elements not referenced will simply be ignored by APS and by this + * plugin. + * + * This class has methods that provide translator for all the various model + * elements in an APS App package. + * + * @author brian@inteligr8.com + */ public class ApsAppTranslator implements ApsAppCrawlable { private final Logger logger = LoggerFactory.getLogger(ApsAppTranslator.class); @@ -38,11 +69,27 @@ public class ApsAppTranslator implements ApsAppCrawlable { private Index fileProcessIndex; private Index fileSubprocessIndex; - public ApsAppTranslator(File apsAppDirectory, ApsPublicRestApiJerseyImpl api) { + /** + * This constructor initializes the default translator. + * + * The specified directory and a reference to the APS Service are both + * required. This way the configuration file can be cross-referenced with + * the APS App IDs on the target APS instance. + * + * @param apsAppDirectory The directory of the unpacked APS package. + * @param api An APS API reference. + */ + public ApsAppTranslator(File apsAppDirectory, ApsPublicRestApi api) { this.api = api; this.appDirectory = apsAppDirectory; } + /** + * This method initializes the data required from the APS Service for the + * function of this class. + * + * @throws IOException A network I/O related issue occurred. + */ public synchronized void buildIndexes() throws IOException { if (this.indexesBuilt) return; @@ -96,8 +143,8 @@ public class ApsAppTranslator implements ApsAppCrawlable { return new ApsAppJsonTranslator( this.api, - this.apsOrgIndex, this.apsProcessIndex, + this.apsOrgIndex, this.fileProcessIndex); } 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 index f542e56..9ecc985 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsFileTranslator.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsFileTranslator.java @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.translator; import java.io.File; @@ -5,6 +19,14 @@ import java.io.IOException; import com.inteligr8.maven.aps.modeling.crawler.ApsFileTransformer; +/** + * This interface defines an APS file translator. + * + * Translation is the transformation of something from one state to a target + * state. In this context, a configuration is being translated to be import + * friendly for the target APS Service. That principally means the update + * of APS model IDs. + */ public interface ApsFileTranslator extends ApsFileTransformer { @Override @@ -12,6 +34,15 @@ public interface ApsFileTranslator extends ApsFileTransformer { this.translateFile(file, modelName, modelId); } + /** + * This method translates the specified file which should be referred to + * with the specified name and ID. + * + * @param file A model file. + * @param modelName The target model name. + * @param modelId The target model ID. + * @throws IOException An I/O related exception has occurred during translation. + */ void translateFile(File file, String modelName, Long modelId) throws IOException; } 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 eb46762..d0175f7 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 @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.translator; import java.io.File; @@ -11,11 +25,23 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.inteligr8.maven.aps.modeling.util.Index; import com.inteligr8.maven.aps.modeling.util.ModelUtil; +/** + * This class implements an APS Form JSON configuration file translator. + * + * This will translate the form ID embedded into APS Form descriptor. + * + * @author brian@inteligr8.com + */ public class ApsFormJsonTranslator implements ApsFileTranslator { private final Logger logger = LoggerFactory.getLogger(ApsFormJsonTranslator.class); private final Index apsIndex; + /** + * This constructor initializes the default translator. + * + * @param apsFormIndex A map of form IDs to form names as defined in the APS Service. + */ public ApsFormJsonTranslator(Index apsFormIndex) { this.apsIndex = apsFormIndex; } diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsOrganizationHandler.java b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsOrganizationHandler.java index f28fe09..3116baa 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsOrganizationHandler.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/translator/ApsOrganizationHandler.java @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.translator; import java.util.Map; @@ -9,12 +23,21 @@ import com.inteligr8.alfresco.activiti.ApsPublicRestApi; import com.inteligr8.alfresco.activiti.model.Group; import com.inteligr8.alfresco.activiti.model.GroupLight; +/** + * This class provides APS Organization support. + * + * @author brian@inteligr8.com. + */ public class ApsOrganizationHandler { private final Logger logger = LoggerFactory.getLogger(ApsOrganizationHandler.class); private final ApsPublicRestApi api; private final Map apsOrgIndex; + /** + * @param api An APS API reference. + * @param apsOrgIndex A map of organization IDs to organization meta-data defined in the APS service. + */ public ApsOrganizationHandler( ApsPublicRestApi api, Map apsOrgIndex) { 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 5e7083a..f662949 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 @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.translator; import java.io.File; @@ -27,6 +41,19 @@ import com.inteligr8.alfresco.activiti.model.GroupLight; import com.inteligr8.maven.aps.modeling.util.Index; import com.inteligr8.maven.aps.modeling.util.ModelUtil; +/** + * This class implements an APS Process BPMN/XML configuration file translator. + * + * This will translate the IDs of all the APS Process, Organizations, and + * Forms referenced in the APS Process BPMN. + * + * Caution: in lieu of implementing APS User translation, APS User identity + * references are simply removed. Using APS Users in your APS models is bad + * practice. Use APS Organizations, even if that user is the only member of + * the group. + * + * @author brian@inteligr8.com + */ public class ApsProcessBpmnTranslator extends ApsOrganizationHandler implements ApsFileTranslator { private static final String NAMESPACE_ACTIVITI = "http://activiti.org/bpmn"; @@ -38,6 +65,15 @@ public class ApsProcessBpmnTranslator extends ApsOrganizationHandler implements private final Index apsFormIndex; private final Index fileFormIndex; + /** + * This constructor initializes the default translator. + * + * @param api An APS API reference. + * @param apsProcessIndex A map of process IDs to process names as defined in the APS Service. + * @param apsOrgIndex A map of organizations (groups) to organization meta-data as defined in the APS Service. + * @param apsFormIndex A map of form IDs to form names as defined in the APS Service. + * @param fileFormIndex A map of form IDS to form names as used in the local form files. + */ public ApsProcessBpmnTranslator( ApsPublicRestApi api, Index apsProcessIndex, 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 ef527de..37090a4 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 @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.translator; import java.io.File; @@ -15,6 +29,19 @@ import com.inteligr8.alfresco.activiti.model.GroupLight; import com.inteligr8.maven.aps.modeling.util.Index; import com.inteligr8.maven.aps.modeling.util.ModelUtil; +/** + * This class implements an APS Process JSON configuration file translator. + * + * This will translate the IDs of all the APS Process, Organizations, and + * Forms referenced in the APS Process descriptor. + * + * Caution: in lieu of implementing APS User translation, APS User identity + * references are simply removed. Using APS Users in your APS models is bad + * practice. Use APS Organizations, even if that user is the only member of + * the group. + * + * @author brian@inteligr8.com + */ public class ApsProcessJsonTranslator extends ApsOrganizationHandler implements ApsFileTranslator { private final Logger logger = LoggerFactory.getLogger(ApsProcessJsonTranslator.class); @@ -22,6 +49,14 @@ public class ApsProcessJsonTranslator extends ApsOrganizationHandler implements private final Map apsOrgIndex; private final Index apsFormIndex; + /** + * This constructor initializes the default translator. + * + * @param api An APS API reference. + * @param apsProcessIndex A map of process IDs to process names as defined in the APS Service. + * @param apsOrgIndex A map of organizations (groups) to organization meta-data as defined in the APS Service. + * @param apsFormIndex A map of form IDs to form names as defined in the APS Service. + */ public ApsProcessJsonTranslator( ApsPublicRestApi api, Index apsProcessIndex, @@ -42,21 +77,22 @@ public class ApsProcessJsonTranslator extends ApsOrganizationHandler implements ObjectNode jsonDescriptor = ModelUtil.getInstance().readJson(file, ObjectNode.class); - changed = this.translateResourceId(jsonDescriptor, apsProcessId) || changed; - changed = this.translateOrganizations(jsonDescriptor) || changed; - changed = this.translateForms(jsonDescriptor) || changed; - changed = this.translateSubprocesses(jsonDescriptor) || changed; + changed = this.translateResourceId(jsonDescriptor, processName, apsProcessId) || changed; + changed = this.translateOrganizations(jsonDescriptor, processName) || changed; + changed = this.translateForms(jsonDescriptor, processName) || changed; + changed = this.translateSubprocesses(jsonDescriptor, processName) || changed; if (changed) ModelUtil.getInstance().writeJson(jsonDescriptor, file, false); } - private boolean translateResourceId(ObjectNode jsonDescriptor, Long apsProcessId) { + private boolean translateResourceId(ObjectNode jsonDescriptor, String processName, Long apsProcessId) { if (apsProcessId == null) { this.logger.trace("The process is not in APS; treating as new"); return false; } + this.logger.trace("Translating resource ID in process: {}", processName); ObjectNode resourceIdParentJson = jsonDescriptor; JsonNode jsonResourceId = jsonDescriptor.get("resourceId"); @@ -83,7 +119,8 @@ public class ApsProcessJsonTranslator extends ApsOrganizationHandler implements - private boolean translateOrganizations(ObjectNode jsonDescriptor) { + private boolean translateOrganizations(ObjectNode jsonDescriptor, String processName) { + this.logger.trace("Translating organizations in process: {}", processName); boolean changed = false; for (JsonNode jsonChildShape : this.getChildShapes(jsonDescriptor)) { @@ -134,7 +171,8 @@ public class ApsProcessJsonTranslator extends ApsOrganizationHandler implements - private boolean translateForms(ObjectNode jsonDescriptor) { + private boolean translateForms(ObjectNode jsonDescriptor, String processName) { + this.logger.trace("Translating forms in process: {}", processName); boolean changed = false; for (JsonNode jsonChildShape : this.getChildShapes(jsonDescriptor)) { @@ -168,7 +206,8 @@ public class ApsProcessJsonTranslator extends ApsOrganizationHandler implements - private boolean translateSubprocesses(ObjectNode jsonDescriptor) { + private boolean translateSubprocesses(ObjectNode jsonDescriptor, String processName) { + this.logger.trace("Translating subprocesses in process: {}", processName); boolean changed = false; for (JsonNode jsonChildShape : this.getChildShapes(jsonDescriptor)) { diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/util/Index.java b/src/main/java/com/inteligr8/maven/aps/modeling/util/Index.java index 631e37f..2089be8 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/util/Index.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/util/Index.java @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.util; import java.util.HashMap; @@ -9,55 +23,114 @@ import java.util.Set; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +/** + * A class that implements bi-directional map for forward and reverse indexing + * and lookups. + * + * The index is considered to be many-to-1. So the forward index appears as + * 1-to-1 (one key to one value) and the reverse index appears as 1-to-many + * (one value to many keys). + * + * If the index should be considered to be 1-to-1, then set + * `allowDuplicateValues` to `false`. + * + * @author brian@inteligr8.com + */ public class Index { private final Map forwardMap; private final Map> reverseMap; private final boolean allowDuplicateValues; + /** + * This constructor defines a new index with some meta-data. + * + * The capacity is not strictly enforced. It should be accurate for + * performance reasons. + * + * @param initialCapacity A capacity, as you would specify in an ArrayList or HashMap. + * @param allowDuplicateValues true to allow multiple keys to have the same value; false to throw an IllegalArgumentException. + */ public Index(int initialCapacity, boolean allowDuplicateValues) { this.forwardMap = new HashMap(initialCapacity); this.reverseMap = new HashMap>(initialCapacity); this.allowDuplicateValues = allowDuplicateValues; } + /** + * @param key An index key. + * @return true if it exists; false otherwise. + */ public boolean containsKey(K key) { return this.forwardMap.containsKey(key); } + /** + * @param value An indexed value. + * @return true if it exists; false otherwise. + */ public boolean containsValue(V value) { return this.reverseMap.containsKey(value); } + /** + * @param key An index key. + * @return The value; null if key not indexed. + */ public V getValue(K key) { return this.forwardMap.get(key); } + /** + * @return A set of all keys; may be empty; never null. + */ public Set keySet() { return this.forwardMap.keySet(); } + /** + * @return A set of all values; may be empty; never null. + */ public Set valueSet() { return this.reverseMap.keySet(); } + /** + * @param value An indexed value. + * @return A set of keys; never empty; null if value not indexed. + */ public Set getKeys(V value) { return this.reverseMap.get(value); } + /** + * @param value An indexed value. + * @return The key; null if value not indexed. + */ public K getFirstKey(V value) { Set keys = this.reverseMap.get(value); return (keys == null || keys.isEmpty()) ? null : keys.iterator().next(); } + /** + * @return The number of keys in the index. + */ public int size() { return this.forwardMap.size(); } + /** + * @return Interable access to the entries of the forward index. + */ public Iterable> entries() { return this.forwardMap.entrySet(); } + /** + * @param key An index key. + * @param value A value to index to the specified key. + * @return true if the key already existed and was overwritten; false otherwise. + */ public synchronized boolean put(K key, V value) { boolean overwrote = false; @@ -81,6 +154,10 @@ public class Index { return overwrote; } + /** + * @param key An index key. + * @return true if the key and its value were removed; false otherwise. + */ public synchronized boolean remove(K key) { V oldValue = this.forwardMap.remove(key); if (oldValue == null) @@ -91,6 +168,9 @@ public class Index { return true; } + /** + * This method clears/resets the index. + */ public synchronized void clear() { this.forwardMap.clear(); this.reverseMap.clear(); diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/util/MapComparator.java b/src/main/java/com/inteligr8/maven/aps/modeling/util/MapComparator.java index b5ebec1..09abeba 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/util/MapComparator.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/util/MapComparator.java @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.util; import java.util.Arrays; @@ -5,15 +19,41 @@ import java.util.Comparator; import java.util.List; import java.util.Map; +/** + * This class implements a comparator for the value of map keys. + * + * If key values are considered equal, fallback keys are supported. Any map + * without the key or not null value will be considered "greater than" ones + * that have values for the specified key. This will move them to the end of + * any sorted list. + * + * @author brian@inteligr8.com + */ public class MapComparator implements Comparator> { //private final Logger logger = LoggerFactory.getLogger(ArrayOfObjectNodeComparator.class); private final List keys; + /** + * An array-based constructor. + * + * The class will sort on the values of these map keys, with a priority in + * the specified order. + * + * @param keys An array of keys. + */ public MapComparator(@SuppressWarnings("unchecked") K... keys) { this(Arrays.asList(keys)); } + /** + * A list-based constructor. + * + * The class will sort on the values of these map keys, with a priority in + * the specified order. + * + * @param keys A list of keys. + */ public MapComparator(List keys) { this.keys = keys; } 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 65f7739..1b2a28a 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 @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.util; import java.io.BufferedInputStream; @@ -40,11 +54,19 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.inteligr8.maven.aps.modeling.xml.DomNamespaceContext; +/** + * This singleton class provides JSON and XML I/O tools and consistent formatting. + * + * @author brian@inteligr8.com + */ public class ModelUtil { public final static QName CDATA_FLEX = QName.valueOf("inteligr8:xml:cdata_or_element"); private final static ModelUtil INSTANCE = new ModelUtil(); + /** + * @return A singleton instance of this class. + */ public static ModelUtil getInstance() { return INSTANCE; } @@ -89,11 +111,42 @@ public class ModelUtil { + /** + * This method reads/parses JSON and immediately formats/writes JSON back + * to the specified file. + * + * You many optionally enable the sorting of elements. Sorting makes the + * files more diff-friendly. The algorithm will sort JSON objects by keys. + * JSON array values will not be sorted. + * + * This method will load the full set of JSON objects into memory. + * + * @param inplaceFile A file handle to an existing valid JSON file. + * @param enableSorting true to sort; false to leave as-is. + * @throws IOException A file I/O issue occurred. + */ public void json(File inplaceFile, boolean enableSorting) throws IOException { JsonNode json = this.readJson(inplaceFile); this.writeJson(json, inplaceFile, enableSorting); } + /** + * This method reads/parses JSON from the specified source file and + * immediately formats/writes JSON to the specified target file. + * + * If the specified target file already exists, it will be overwritten. + * + * You many optionally enable the sorting of elements. Sorting makes the + * files more diff-friendly. The algorithm will sort JSON objects by keys. + * JSON array values will not be sorted. + * + * This method will load the full set of JSON objects into memory. + * + * @param sourceFile A file handle to an existing valid JSON file. + * @param targetFile A file handle for the target JSON file. + * @param enableSorting true to sort; false to leave as-is. + * @throws IOException A file I/O issue occurred. + */ public void json(File sourceFile, File targetFile, boolean enableSorting) throws IOException { FileInputStream fistream = new FileInputStream(sourceFile); BufferedInputStream bistream = new BufferedInputStream(fistream, this.bufferSize); @@ -110,16 +163,45 @@ public class ModelUtil { } } + /** + * This method reads/parses JSON from the specified source stream and + * immediately formats/writes JSON to the specified target stream. + * + * You many optionally enable the sorting of elements. Sorting makes the + * files more diff-friendly. The algorithm will sort JSON objects by keys. + * JSON array values will not be sorted. + * + * This method will load the full set of JSON objects into memory. + * + * @param istream An input stream to valid JSON. + * @param ostream An output stream. + * @param enableSorting true to sort; false to leave as-is. + * @throws IOException A stream I/O issue occurred. + */ 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, enableSorting); } + /** + * This method reads/parses JSON from the specified file. + * + * @param file A file handle to an existing valid JSON file. + * @return A JSON node (array, object, or value). + * @throws IOException A file I/O issue occurred. + */ public JsonNode readJson(File file) throws IOException { return this.readJson(file, JsonNode.class); } + /** + * This method reads/parses JSON from the specified file. + * + * @param file A file handle to an existing valid JSON file. + * @param type A type parse the JSON into (using the Jackson parser). + * @return An instance of the specified type. + * @throws IOException A file I/O issue occurred. + */ public T readJson(File file, Class type) throws IOException { FileInputStream fistream = new FileInputStream(file); BufferedInputStream bistream = new BufferedInputStream(fistream, this.bufferSize); @@ -130,6 +212,13 @@ public class ModelUtil { } } + /** + * This method reads/parses JSON from the specified file. + * + * @param file A file handle to an existing valid JSON file. + * @return A JSON array as a list. + * @throws IOException A file I/O issue occurred. + */ public List readJsonAsList(File file) throws IOException { FileInputStream fistream = new FileInputStream(file); BufferedInputStream bistream = new BufferedInputStream(fistream, this.bufferSize); @@ -140,6 +229,13 @@ public class ModelUtil { } } + /** + * This method reads/parses JSON from the specified file. + * + * @param file A file handle to an existing valid JSON file. + * @return A JSON object as a map. + * @throws IOException A file I/O issue occurred. + */ public Map readJsonAsMap(File file) throws IOException { FileInputStream fistream = new FileInputStream(file); BufferedInputStream bistream = new BufferedInputStream(fistream, this.bufferSize); @@ -150,24 +246,67 @@ public class ModelUtil { } } + /** + * This method reads/parses JSON from the specified stream. + * + * @param istream An input stream to valid JSON. + * @return A JSON node (array, object, or value). + * @throws IOException A stream I/O issue occurred. + */ public JsonNode readJson(InputStream istream) throws IOException { return this.om.readTree(istream); } + /** + * This method reads/parses JSON from the specified stream. + * + * @param istream An input stream to valid JSON. + * @param type A type parse the JSON into (using the Jackson parser). + * @return An instance of the specified type. + * @throws IOException A stream I/O issue occurred. + */ public T readJson(InputStream istream, Class type) throws IOException { return this.om.readValue(istream, type); } + /** + * This method reads/parses JSON from the specified stream. + * + * @param istream An input stream to valid JSON. + * @return A JSON array as a list. + * @throws IOException A stream I/O issue occurred. + */ @SuppressWarnings("unchecked") public List readJsonAsList(InputStream istream) throws IOException { return this.om.readValue(istream, List.class); } + /** + * This method reads/parses JSON from the specified stream. + * + * @param istream An input stream to valid JSON. + * @return A JSON object as a map. + * @throws IOException A stream I/O issue occurred. + */ @SuppressWarnings("unchecked") public Map readJsonAsMap(InputStream istream) throws IOException { return this.om.readValue(istream, Map.class); } + /** + * This method formats/writes JSON to the specified file. + * + * If the specified file already exists, it will be overwritten. + * + * You many optionally enable the sorting of elements. Sorting makes the + * files more diff-friendly. The algorithm will sort JSON objects by keys. + * JSON array values will not be sorted. + * + * @param json A JSON node (array, object, or value). + * @param file A file handle. + * @param enableSorting true to sort; false to leave as-is. + * @throws IOException A file I/O issue occurred. + */ public void writeJson(JsonNode json, File file, boolean enableSorting) throws IOException { FileOutputStream fostream = new FileOutputStream(file); BufferedOutputStream bostream = new BufferedOutputStream(fostream, this.bufferSize); @@ -178,6 +317,20 @@ public class ModelUtil { } } + /** + * This method formats/writes JSON to the specified file. + * + * If the specified file already exists, it will be overwritten. + * + * You many optionally enable the sorting of elements. Sorting makes the + * files more diff-friendly. The algorithm will sort JSON objects by keys. + * JSON array values will not be sorted. + * + * @param map A Java map. + * @param file A file handle. + * @param enableSorting true to sort; false to leave as-is. + * @throws IOException A file I/O issue occurred. + */ public void writeJson(Map map, File file, boolean enableSorting) throws IOException { FileOutputStream fostream = new FileOutputStream(file); BufferedOutputStream bostream = new BufferedOutputStream(fostream, this.bufferSize); @@ -188,6 +341,18 @@ public class ModelUtil { } } + /** + * This method formats/writes JSON to the specified file. + * + * You many optionally enable the sorting of elements. Sorting makes the + * files more diff-friendly. The algorithm will sort JSON objects by keys. + * JSON array values will not be sorted. + * + * @param json A JSON node (array, object, or value). + * @param ostream An output stream. + * @param enableSorting true to sort; false to leave as-is. + * @throws IOException A file I/O issue occurred. + */ public void writeJson(JsonNode json, OutputStream ostream, boolean enableSorting) throws IOException { if (enableSorting) { this.omsorted.writeValue(ostream, json); @@ -196,6 +361,18 @@ public class ModelUtil { } } + /** + * This method formats/writes JSON to the specified file. + * + * You many optionally enable the sorting of elements. Sorting makes the + * files more diff-friendly. The algorithm will sort JSON objects by keys. + * JSON array values will not be sorted. + * + * @param map A Java map. + * @param ostream An output stream. + * @param enableSorting true to sort; false to leave as-is. + * @throws IOException A file I/O issue occurred. + */ public void writeJson(Map map, OutputStream ostream, boolean enableSorting) throws IOException { if (enableSorting) { this.omsorted.writeValue(ostream, map); @@ -206,6 +383,17 @@ public class ModelUtil { + /** + * This method reads/parses XML and immediately formats/writes XML back to + * the specified file. + * + * This method will load the full DOM of XML into memory. + * + * @param inplaceFile A file handle to an existing valid XML file. + * @throws IOException A file I/O issue occurred. + * @throws SAXException The file is not valid XML. + * @throws TransformerException An unknown XML transformation issue occurred. + */ public void xml(File inplaceFile) throws IOException, SAXException, TransformerException { Document xml; @@ -226,6 +414,20 @@ public class ModelUtil { } } + /** + * This method reads/parses XML from the specified source file and + * immediately formats/writes XML to to the specified target file. + * + * If the specified target file already exists, it will be overwritten. + * + * This method will load the full DOM of XML into memory. + * + * @param sourceFile A file handle to an existing valid XML file. + * @param targetFile A file handle. + * @throws IOException A file I/O issue occurred. + * @throws SAXException The file is not valid XML. + * @throws TransformerException An unknown XML transformation issue occurred. + */ public void xml(File sourceFile, File targetFile) throws IOException, SAXException, TransformerException { FileInputStream fistream = new FileInputStream(sourceFile); BufferedInputStream bistream = new BufferedInputStream(fistream, this.bufferSize); @@ -242,12 +444,31 @@ public class ModelUtil { } } + /** + * This method reads/parses XML from the specified source stream and + * immediately formats/writes XML to to the specified target stream. + * + * This method will load the full DOM of XML into memory. + * + * @param sourceFile A file handle to an existing valid XML file. + * @param targetFile A file handle. + * @throws IOException A file I/O issue occurred. + * @throws SAXException The file is not valid XML. + * @throws TransformerException An unknown XML transformation issue occurred. + */ public void xml(InputStream istream, OutputStream ostream) throws IOException, SAXException, TransformerException { - // FIXME stream it for lower memory/IO usage Document doc = this.readXml(istream); this.writeXml(doc, ostream); } + /** + * This method reads/parses XML from the specified file. + * + * @param file A file handle to an existing valid XML file. + * @return An XML DOM Document object. + * @throws IOException A file I/O issue occurred. + * @throws SAXException The file is not valid XML. + */ public Document readXml(File file) throws IOException, SAXException { FileInputStream fistream = new FileInputStream(file); BufferedInputStream bistream = new BufferedInputStream(fistream, this.bufferSize); @@ -258,10 +479,28 @@ public class ModelUtil { } } + /** + * This method reads/parses XML from the specified stream. + * + * @param istream An input stream to valid XML. + * @return An XML DOM Document object. + * @throws IOException A stream I/O issue occurred. + * @throws SAXException The stream is not valid XML. + */ public Document readXml(InputStream istream) throws IOException, SAXException { return this.docBuilder.parse(istream); } + /** + * This method formats/writes XML to the specified file. + * + * If the specified file already exists, it will be overwritten. + * + * @param xml An XML element. + * @param file A file handle. + * @throws IOException A file I/O issue occurred. + * @throws TransformerException An unknown XML transformation issue occurred. + */ public void writeXml(Node xml, File file) throws IOException, TransformerException { FileOutputStream fostream = new FileOutputStream(file); BufferedOutputStream bostream = new BufferedOutputStream(fostream, this.bufferSize); @@ -272,16 +511,43 @@ public class ModelUtil { } } + /** + * This method formats/writes XML to the specified stream. + * + * @param xml An XML element. + * @param ostream An output stream. + * @throws IOException A stream I/O issue occurred. + * @throws TransformerException An unknown XML transformation issue occurred. + */ public void writeXml(Node xml, OutputStream ostream) throws IOException, TransformerException { DOMSource source = new DOMSource(xml); StreamResult result = new StreamResult(ostream); this.transformer.transform(source, result); } + + + /** + * This method searches the DOM using an XPath expression. + * + * @param node An XML node. + * @param xpathExpr An XPath expression. + * @return An XML DOM list of nodes object; null if no result. + * @throws XPathExpressionException An unknown XPath issue occurred. + */ public NodeList xpath(Node node, String xpathExpr) throws XPathExpressionException { return (NodeList)this.xpath(node, xpathExpr, XPathConstants.NODESET); } + /** + * This method searches the DOM using an XPath expression. + * + * @param node An XML node. + * @param xpathExpr An XPath expression. + * @param returnType An XPath return type: see XPathConstants. + * @return An XML DOM list of nodes object; null if no result. + * @throws XPathExpressionException An unknown XPath issue occurred. + */ public Object xpath(Node node, String xpathExpr, QName returnType) throws XPathExpressionException { XPath xpath = this.xpathfactory.newXPath(); xpath.setNamespaceContext(new DomNamespaceContext(node)); diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/util/ObjectNodeComparator.java b/src/main/java/com/inteligr8/maven/aps/modeling/util/ObjectNodeComparator.java index 729639c..7485767 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/util/ObjectNodeComparator.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/util/ObjectNodeComparator.java @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.util; import java.util.Arrays; @@ -6,15 +20,45 @@ import java.util.List; import com.fasterxml.jackson.databind.JsonNode; +/** + * This class implements a comparator for the value of JSON object fields. + * + * If field values are considered equal, fallback fields are supported. Any + * object without the field in question will be considered "greater than" ones + * that have the specified field. This will move them to the end of any sorted + * list. + * + * If a JSON value or array is encountered instead of a JSON object, then it is + * treated exactly like a JSON object without the specified field. It will be + * considered "greater than" and move to the end of any sorted list. + * + * @author brian@inteligr8.com + */ public class ObjectNodeComparator implements Comparator { //private final Logger logger = LoggerFactory.getLogger(ArrayOfObjectNodeComparator.class); private final List objectFieldNames; + /** + * An array-based constructor. + * + * The class will sort on the values of these JSON object field names, with + * a priority in the specified order. + * + * @param objectFieldNames An array of JSON object field names. + */ public ObjectNodeComparator(String... objectFieldNames) { this(Arrays.asList(objectFieldNames)); } + /** + * A list-based constructor. + * + * The class will sort on the values of these JSON object field names, with + * a priority in the specified order. + * + * @param objectFieldNames A list of JSON object field names. + */ public ObjectNodeComparator(List objectFieldNames) { this.objectFieldNames = objectFieldNames; } @@ -22,9 +66,9 @@ public class ObjectNodeComparator implements Comparator { @Override public int compare(JsonNode o1, JsonNode o2) { if (!o1.isObject()) - return -1; - if (!o2.isObject()) return 1; + if (!o2.isObject()) + return -1; for (String objectFieldName : objectFieldNames) { JsonNode value1 = o1.get(objectFieldName); diff --git a/src/main/java/com/inteligr8/maven/aps/modeling/xml/DomNamespaceContext.java b/src/main/java/com/inteligr8/maven/aps/modeling/xml/DomNamespaceContext.java index 4c9872d..bcd90e6 100644 --- a/src/main/java/com/inteligr8/maven/aps/modeling/xml/DomNamespaceContext.java +++ b/src/main/java/com/inteligr8/maven/aps/modeling/xml/DomNamespaceContext.java @@ -1,3 +1,17 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ package com.inteligr8.maven.aps.modeling.xml; import java.util.Collections; @@ -9,6 +23,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Node; +/** + * This class implements namespace handling for DOM processing. + */ public class DomNamespaceContext implements NamespaceContext { private final Logger logger = LoggerFactory.getLogger(DomNamespaceContext.class); @@ -16,10 +33,22 @@ public class DomNamespaceContext implements NamespaceContext { private final String defaultNamespacePrefix; private final String defaultNamespace; + /** + * The constructor using just a DOM node. The default namespace prefix is + * assumed to be 'tns'. + * + * @param node A DOM node. + */ public DomNamespaceContext(Node node) { this(node, "tns"); } + /** + * The constructor using just a DOM node. + * + * @param node A DOM node. + * @param defaultNamespacePrefix A DOM namespace prefix. + */ public DomNamespaceContext(Node node, String defaultNamespacePrefix) { this.node = node; this.defaultNamespacePrefix = defaultNamespacePrefix;