8 Commits

Author SHA1 Message Date
d3aa1dd0bf v1.3.4 pom 2022-11-18 15:43:53 -05:00
3fca20385e Merge branch 'develop' into stable 2022-11-18 15:41:35 -05:00
63ffd77622 fixed NPE on expressions 2022-11-18 15:40:50 -05:00
ad74bf02a3 v1.3.3 pom 2022-11-18 15:10:57 -05:00
99d9cc8d17 Merge branch 'develop' into stable 2022-11-18 14:01:59 -05:00
4d064916e9 fixed multiple condition translation in process model JSON 2022-11-18 14:01:46 -05:00
c441a61d37 added README 2022-10-10 23:44:14 -04:00
8eae54f753 moved @see javadoc 2022-10-10 22:28:27 -04:00
4 changed files with 384 additions and 24 deletions

348
README.md Normal file
View File

@@ -0,0 +1,348 @@
# APS Model Maven Plugin
This is a maven plugin that APS model management. The use cases include synchronization between disparate APS instances, like the progressive environments you find in most enterprise infrastructures. It will also synchronize APS instances to Git or Git to APS instances.
## Usage
Here is an example configuration for synchronizing an APS instance to the local project so it can be committed to Git.
```xml
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>com.inteligr8</groupId>
<artifactId>aps-model-maven-plugin</artifactId>
<version>...</version>
<configuration>
<activitiAppBaseUrl>http://localhost:8080/activiti-app</activitiAppBaseUrl>
<activitiAppAuthBasicServerId>aps</activitiAppAuthBasicServerId>
<apsAppName>Test App</apsAppName>
</configuration>
<executions>
<execution>
<id>download-unpack-app</id>
<phase>generate-sources</phase>
<goals>
<goal>download-app</goal>
<goal>unpack-app</goal>
</goals>
<configuration>
<normalize>true</normalize>
<diffFriendly>true</diffFriendly>
</configuration>
</execution>
<execution>
<id>translate-app</id>
<phase>compile</phase>
<goals>
<goal>translate-app</goal>
</goals>
<configuration>
<finalDirectory>${basedir}/src/main/aps/app</finalDirectory>
</configuration>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
...
</project>
```
For `BASIC` authentication, you will need to define a `server` in the `settings.xml` as shown in the snippet below.
```xml
<settings ...>
...
<servers>
...
<server>
<id>aps</id>
<username>...</username>
<password>...</password>
</server>
...
</servers>
...
</settings>
```
Here is an example configuration for synchronizing the local project to an APS instance.
```xml
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>com.inteligr8</groupId>
<artifactId>aps-model-maven-plugin</artifactId>
<version>...</version>
<configuration>
<activitiAppBaseUrl>http://localhost:8080/activiti-app</activitiAppBaseUrl>
<activitiAppAuthBasicServerId>aps</activitiAppAuthBasicServerId>
<apsAppName>Test App</apsAppName>
</configuration>
<executions>
<execution>
<id>translate-app</id>
<phase>compile</phase>
<goals>
<goal>translate-app</goal>
</goals>
<configuration>
<unzipDirectory>${basedir}/src/main/aps/app</unzipDirectory>
</configuration>
</execution>
<execution>
<id>pack-app</id>
<phase>package</phase>
<goals>
<goal>pack-app</goal>
</goals>
</execution>
<execution>
<id>upload-app</id>
<phase>install</phase>
<goals>
<goal>upload-app</goal>
</goals>
</execution>
<execution>
<id>publish-app</id>
<phase>deploy</phase>
<goals>
<goal>publish-app</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
...
</project>
```
Here is an example configuration for synchronizing directly from a source to different target APS instance.
```xml
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>com.inteligr8</groupId>
<artifactId>aps-model-maven-plugin</artifactId>
<version>...</version>
<configuration>
<apsAppName>Test App</apsAppName>
</configuration>
<executions>
<execution>
<id>download-unpack-app</id>
<phase>generate-sources</phase>
<goals>
<goal>download-app</goal>
<goal>unpack-app</goal>
</goals>
<configuration>
<activitiAppBaseUrl>http://dev-host:8080/activiti-app</activitiAppBaseUrl>
<activitiAppAuthBasicServerId>aps-dev</activitiAppAuthBasicServerId>
<normalize>true</normalize>
<diffFriendly>true</diffFriendly>
</configuration>
</execution>
<execution>
<id>translate-app</id>
<phase>compile</phase>
<goals>
<goal>translate-app</goal>
</goals>
<configuration>
<activitiAppBaseUrl>http://test-host:8080/activiti-app</activitiAppBaseUrl>
<activitiAppAuthBasicServerId>aps-test</activitiAppAuthBasicServerId>
</configuration>
</execution>
<execution>
<id>pack-app</id>
<phase>package</phase>
<goals>
<goal>pack-app</goal>
</goals>
</execution>
<execution>
<id>upload-publish-app</id>
<phase>deploy</phase>
<goals>
<goal>upload-app</goal>
<goal>publish-app</goal>
</goals>
<configuration>
<activitiAppBaseUrl>http://test-host:8080/activiti-app</activitiAppBaseUrl>
<activitiAppAuthBasicServerId>aps-test</activitiAppAuthBasicServerId>
</configuration>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
...
</project>
```
You will want the Maven project to be of packaging type `pom`.
## Goals
| Goal | Description |
| --------------- | ----------- |
| `aps-info` | Check the connection to APS and output version information. |
| `download-app` | Export and download an APS App as a ZIP file from an APS instance. The latest published version is exported. |
| `upload-app` | Upload and import an APS App from a ZIP file to an APS instance. The APS App is created or updated, but not published. |
| `unpack-app` | Unzip the ZIP file exported from the APS instance. |
| `pack-app` | Zip a previously unpacked APS App in preparation for import to an APS instance. |
| `publish-app` | Publish an existing APS App in an APS instance. |
| `translate-app` | Translate an unpacked APS App. |
| `share-models` | Share applicable models in an APS instance. |
### Goal: `aps-info`
| Configuration Property | Data Type | Required | Default | Description |
| ------------------------------ |:---------:|:--------:| ------- | ----------- |
| `activitiAppBaseUrl` | `string` | | `http://localhost:8080/activiti-app` | The base URL of the APS instance. |
| `activitiAppAuthType` | `string` | | `BASIC` | Either `BASIC` or `OAuth`; case insensitive. |
| `activitiAppAuthBasicServerId` | `string` | | `aps` | The `settings.xml` server ID that provides the credentials for the APS instance when using `BASIC` authentication. |
| `oauthCode` | `string` | *Maybe* | | An authorization code for the identity provider governing the APS instance when using `OAuth` authentication. |
| `oauthClientServerId` | `string` | *Maybe* | | The `settings.xml` server ID that provides the client ID/secret credentials for the identity provider governing the APS instance when using `OAuth` authentication. |
| `oauthServerId` | `string` | *Maybe* | | The `settings.xml` server ID that provides the username/password credentials for the identity provider governing the APS instance when using `OAuth` authentication. |
| `oauthTokenUrl` | `string` | *Maybe* | | The token URL for the identity provider governing the APS instance when using `OAuth` authentication. |
| `skip` | `boolean` | | `false` | |
### Goal: `download-app`
| Configuration Property | Data Type | Required | Default | Description |
| ------------------------------ |:---------:|:--------:| ------- | ----------- |
| `zipDirectory` | `string` | | `target/aps` | The base directory where the ZIP file should be downloaded. |
| `apsAppName` | `string` | Yes | | An APS App name that exists in the APS instance. |
| `activitiAppBaseUrl` | `string` | | `http://localhost:8080/activiti-app` | The base URL of the APS instance. |
| `activitiAppAuthType` | `string` | | `BASIC` | Either `BASIC` or `OAuth`; case insensitive. |
| `activitiAppAuthBasicServerId` | `string` | | `aps` | The `settings.xml` server ID that provides the credentials for the APS instance when using `BASIC` authentication. |
| `oauthCode` | `string` | *Maybe* | | An authorization code for the identity provider governing the APS instance when using `OAuth` authentication. |
| `oauthClientServerId` | `string` | *Maybe* | | The `settings.xml` server ID that provides the client ID/secret credentials for the identity provider governing the APS instance when using `OAuth` authentication. |
| `oauthServerId` | `string` | *Maybe* | | The `settings.xml` server ID that provides the username/password credentials for the identity provider governing the APS instance when using `OAuth` authentication. |
| `oauthTokenUrl` | `string` | *Maybe* | | The token URL for the identity provider governing the APS instance when using `OAuth` authentication. |
| `skip` | `boolean` | | `false` | |
### Goal: `unpack-app`
| Configuration Property | Data Type | Required | Default | Description |
| ------------------------------ |:---------:|:--------:| ------- | ----------- |
| `apsAppName` | `string` | Yes | | The name of the APS App ZIP file, without the `.zip` extension. |
| `zipDirectory` | `string` | | `target/aps` | The base directory where the ZIP file should exist. |
| `unzipDirectory` | `string` | | `target/aps/app` | The base directory where the ZIP file should be unpacked; the APS App name will be another folder within this directory. |
| `reformat` | `boolean` | | `true` | The JSON and XML files should be reformatted for readability and better `diff`/Git support. |
| `normalize` | `boolean` | Yes | | The JSON and XML files should be normalized for better `diff`/Git support. |
| `diffFriendly` | `boolean` | Yes | | The JSON file models should be sorted for better `diff`/Git support. |
| `charsetName` | `string` | | `utf-8` | |
| `skip` | `boolean` | | `false` | |
### Goal: `translate-app`
This goal translates an APS App configuration so all the model and organization IDs reference the specified APS instance. This is the most important functionality provied by this Maven plugin. It allows for the clean synchronization of APS models between environments; forward and backwards.
| Configuration Property | Data Type | Required | Default | Description |
| ------------------------------ |:---------:|:--------:| ------- | ----------- |
| `apsAppName` | `string` | Yes | | The name of the folder in the `unzipDirectory`. |
| `unzipDirectory` | `string` | | `target/aps/app` | The base directory where the unpacked APS App exists. |
| `finalDirectory` | `string` | | `target/aps/app` | The base directory where the translated APS App should exist. If it is the same as `unzipDirectory`, then it is translated in-place. |
| `overwrite` | `boolean` | | `true` | |
| `charsetName` | `string` | | `utf-8` | |
| `activitiAppBaseUrl` | `string` | | `http://localhost:8080/activiti-app` | The base URL of the APS instance. |
| `activitiAppAuthType` | `string` | | `BASIC` | Either `BASIC` or `OAuth`; case insensitive. |
| `activitiAppAuthBasicServerId` | `string` | | `aps` | The `settings.xml` server ID that provides the credentials for the APS instance when using `BASIC` authentication. |
| `oauthCode` | `string` | *Maybe* | | An authorization code for the identity provider governing the APS instance when using `OAuth` authentication. |
| `oauthClientServerId` | `string` | *Maybe* | | The `settings.xml` server ID that provides the client ID/secret credentials for the identity provider governing the APS instance when using `OAuth` authentication. |
| `oauthServerId` | `string` | *Maybe* | | The `settings.xml` server ID that provides the username/password credentials for the identity provider governing the APS instance when using `OAuth` authentication. |
| `oauthTokenUrl` | `string` | *Maybe* | | The token URL for the identity provider governing the APS instance when using `OAuth` authentication. |
| `skip` | `boolean` | | `false` | |
### Goal: `pack-app`
| Configuration Property | Data Type | Required | Default | Description |
| ------------------------------ |:---------:|:--------:| ------- | ----------- |
| `apsAppName` | `string` | Yes | | The name of the folder in the `unzipDirectory`. |
| `unzipDirectory` | `string` | | `target/aps/app` | The base directory where the unpacked APS App is located; the APS App name will be a folder within this directory. |
| `zipDirectory` | `string` | | `target/aps` | The base directory where the new ZIP file should exist. |
| `skip` | `boolean` | | `false` | |
### Goal: `upload-app`
| Configuration Property | Data Type | Required | Default | Description |
| ------------------------------ |:---------:|:--------:| ------- | ----------- |
| `zipDirectory` | `string` | | `target/aps` | The base directory where the ZIP file should be downloaded. |
| `apsAppName` | `string` | Yes | | An APS App name that exists in the APS instance. |
| `publish` | `boolean` | | `false` | Automatically publish after upload. |
| `activitiAppBaseUrl` | `string` | | `http://localhost:8080/activiti-app` | The base URL of the APS instance. |
| `activitiAppAuthType` | `string` | | `BASIC` | Either `BASIC` or `OAuth`; case insensitive. |
| `activitiAppAuthBasicServerId` | `string` | | `aps` | The `settings.xml` server ID that provides the credentials for the APS instance when using `BASIC` authentication. |
| `oauthCode` | `string` | *Maybe* | | An authorization code for the identity provider governing the APS instance when using `OAuth` authentication. |
| `oauthClientServerId` | `string` | *Maybe* | | The `settings.xml` server ID that provides the client ID/secret credentials for the identity provider governing the APS instance when using `OAuth` authentication. |
| `oauthServerId` | `string` | *Maybe* | | The `settings.xml` server ID that provides the username/password credentials for the identity provider governing the APS instance when using `OAuth` authentication. |
| `oauthTokenUrl` | `string` | *Maybe* | | The token URL for the identity provider governing the APS instance when using `OAuth` authentication. |
| `skip` | `boolean` | | `false` | |
### Goal: `publish-app`
| Configuration Property | Data Type | Required | Default | Description |
| ------------------------------ |:---------:|:--------:| ------- | ----------- |
| `apsAppName` | `string` | Yes | | An APS App name that exists in the APS instance. |
| `comment` | `string` | | `Automated by 'aps-model-maven-plugin'` | A comment to apply to the new version of the APS App. |
| `activitiAppBaseUrl` | `string` | | `http://localhost:8080/activiti-app` | The base URL of the APS instance. |
| `activitiAppAuthType` | `string` | | `BASIC` | Either `BASIC` or `OAuth`; case insensitive. |
| `activitiAppAuthBasicServerId` | `string` | | `aps` | The `settings.xml` server ID that provides the credentials for the APS instance when using `BASIC` authentication. |
| `oauthCode` | `string` | *Maybe* | | An authorization code for the identity provider governing the APS instance when using `OAuth` authentication. |
| `oauthClientServerId` | `string` | *Maybe* | | The `settings.xml` server ID that provides the client ID/secret credentials for the identity provider governing the APS instance when using `OAuth` authentication. |
| `oauthServerId` | `string` | *Maybe* | | The `settings.xml` server ID that provides the username/password credentials for the identity provider governing the APS instance when using `OAuth` authentication. |
| `oauthTokenUrl` | `string` | *Maybe* | | The token URL for the identity provider governing the APS instance when using `OAuth` authentication. |
| `skip` | `boolean` | | `false` | |
### Goal: `share-models`
This goal queries the APS instance for all applicable models and shares them based on the configuration. This is very useful in highly collaborative environments. It may be worth having this run on a routine basis in the development environment and on every synchronization to other environments.
| Configuration Property | Data Type | Required | Default | Description |
| ------------------------------ |:---------:|:--------:| ------- | ----------- |
| `modelName` | `string` | | | A single model to share. If the same name is used for two different model types (app and process), then both are shared. If this is left unspecified, all models are shared. |
| `readers` | `string` | | | A comma-delimited list of organizations/groups to target for readonly access to all model types. |
| `editors` | `string` | | | A comma-delimited list of organizations/groups to target for editor access to all model types. |
| `appReaders` | `string` | | | A comma-delimited list of organizations/groups to target for readonly access to only APS App models. This is needed for APS App publishers. |
| `appEditors` | `string` | | | A comma-delimited list of organizations/groups to target for editor access to only APS App models. This is needed for APS App collators. |
| `processReaders` | `string` | | | A comma-delimited list of organizations/groups to target for readonly access to only APS Process models. This is needed for APS App collators. |
| `processEditors` | `string` | | | A comma-delimited list of organizations/groups to target for editor access to only APS Process models. This is needed for APS Process modelers. |
| `formReaders` | `string` | | | A comma-delimited list of organizations/groups to target for readonly access to only APS Form models. This is needed for APS Process modelers. |
| `formEditors` | `string` | | | A comma-delimited list of organizations/groups to target for editor access to only APS Form models. This is needed for APS Form designers. |
| `doRevoke` | `boolean` | | `false` | If `true`, revoke permission to any other groups/users for the applicable models; `false` will leave those permissions intact. |
| `activitiAppBaseUrl` | `string` | | `http://localhost:8080/activiti-app` | The base URL of the APS instance. |
| `activitiAppAuthType` | `string` | | `BASIC` | Either `BASIC` or `OAuth`; case insensitive. |
| `activitiAppAuthBasicServerId` | `string` | | `aps` | The `settings.xml` server ID that provides the credentials for the APS instance when using `BASIC` authentication. |
| `oauthCode` | `string` | *Maybe* | | An authorization code for the identity provider governing the APS instance when using `OAuth` authentication. |
| `oauthClientServerId` | `string` | *Maybe* | | The `settings.xml` server ID that provides the client ID/secret credentials for the identity provider governing the APS instance when using `OAuth` authentication. |
| `oauthServerId` | `string` | *Maybe* | | The `settings.xml` server ID that provides the username/password credentials for the identity provider governing the APS instance when using `OAuth` authentication. |
| `oauthTokenUrl` | `string` | *Maybe* | | The token URL for the identity provider governing the APS instance when using `OAuth` authentication. |
| `skip` | `boolean` | | `false` | |

View File

@@ -6,7 +6,7 @@
<groupId>com.inteligr8.alfresco</groupId>
<artifactId>aps-model-maven-plugin</artifactId>
<version>1.3.2</version>
<version>1.3.4</version>
<packaging>maven-plugin</packaging>
<name>A Maven plugin for Alfresco Process Services model portability</name>

View File

@@ -195,13 +195,18 @@ public class ApsProcessJsonTranslator extends ApsOrganizationHandler implements
return false;
this.logger.trace("Found a conditional sequence flow in the APS Process descriptor");
ObjectNode expression = (ObjectNode)jsonConditionalSequenceFlow.get("expression");
boolean changed = false;
changed = this.translateNamedId(expression, this.apsFormIndex, "outcomeForm") || changed;
changed = this.translateNamedId(expression, this.apsFormIndex, "rightOutcomeForm") || changed;
return changed;
boolean changed = false;
ObjectNode expression = (ObjectNode)jsonConditionalSequenceFlow.get("expression");
while (expression != null) {
changed = this.translateNamedId(expression, this.apsFormIndex, "outcomeForm") || changed;
changed = this.translateNamedId(expression, this.apsFormIndex, "rightOutcomeForm") || changed;
expression = (ObjectNode)expression.get("nextCondition");
}
return changed;
}
@@ -236,24 +241,30 @@ public class ApsProcessJsonTranslator extends ApsOrganizationHandler implements
String idField = prefix == null ? "id" : prefix + "Id";
ObjectNode jsonRef = (ObjectNode)_jsonRef;
String modelName = jsonRef.get(nameField).asText();
this.logger.trace("Found model '{}' in the APS Process descriptor", modelName);
if (apsIndex.containsValue(modelName)) {
long modelId = jsonRef.get(idField).asLong();
long apsModelId = apsIndex.getFirstKey(modelName);
if (apsModelId != modelId) {
this.logger.debug("The model '{}' exists in APS with ID {}; leaving unchanged", modelName, apsModelId);
jsonRef.put(idField, apsModelId);
return true;
} else {
this.logger.trace("The model '{}' ID does not change; leaving unchanged", modelName);
}
} else {
this.logger.debug("The model '{}' does not exists in APS; leaving unchanged", modelName);
JsonNode jsonName = jsonRef.get(nameField);
if (jsonName == null) {
this.logger.trace("The expression does not have an APS model name field ({})", nameField);
return false;
}
return false;
String modelName = jsonName.asText();
this.logger.trace("Found model '{}' in the APS Process descriptor", modelName);
if (!apsIndex.containsValue(modelName)) {
this.logger.debug("The model '{}' does not exists in APS; leaving unchanged", modelName);
return false;
}
JsonNode jsonId = jsonRef.get(idField);
long modelId = jsonId == null ? -1L : jsonId.asLong();
long apsModelId = apsIndex.getFirstKey(modelName);
if (apsModelId != modelId) {
this.logger.debug("The model '{}' exists in APS with ID {}", modelName, apsModelId);
jsonRef.put(idField, apsModelId);
return true;
} else {
this.logger.trace("The model '{}' ID does not change; leaving unchanged", modelName);
return false;
}
}

View File

@@ -48,10 +48,11 @@ public class ArrayNodeObjectSorter {
* standard comparison. If it doesn't have a value, then it will sort to
* the end of the array.
*
* @see ObjectNodeComparator
*
* @param arrayNode A JSON array of JSON objects.
* @param jsonObjectFieldName A field in the JSON object elements.
* @return true if any elements were moved/sorted; false if unchanged.
* @see com.inteligr8.maven.aps.modeling.util.ObjectNodeComparator
*/
public boolean sort(ArrayNode arrayNode, String jsonObjectFieldName) {
return this.sort(arrayNode, new ObjectNodeComparator(jsonObjectFieldName));