Compare commits
27 Commits
Author | SHA1 | Date | |
---|---|---|---|
2d89466813 | |||
a856f9580b | |||
9e62c994ec | |||
6041898be3 | |||
0b9473465e | |||
a65a6df1f8 | |||
98c01db50d | |||
b974bc8f5c | |||
ceb448c382 | |||
8bb15894e8 | |||
c7e0d48908 | |||
8b478e35d7 | |||
bd5b218509 | |||
1d5fa40209 | |||
ab0c27eab1 | |||
55d85814ab | |||
c2f96d36f6 | |||
05fc9e7db9 | |||
78b7fc2ec9 | |||
d3aa1dd0bf | |||
3fca20385e | |||
63ffd77622 | |||
ad74bf02a3 | |||
99d9cc8d17 | |||
4d064916e9 | |||
c441a61d37 | |||
8eae54f753 |
348
README.md
Normal file
348
README.md
Normal 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` | |
|
||||
|
8
pom.xml
8
pom.xml
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>com.inteligr8.alfresco</groupId>
|
||||
<artifactId>aps-model-maven-plugin</artifactId>
|
||||
<version>1.3.2</version>
|
||||
<version>1.4.1</version>
|
||||
<packaging>maven-plugin</packaging>
|
||||
|
||||
<name>A Maven plugin for Alfresco Process Services model portability</name>
|
||||
@@ -44,19 +44,19 @@
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<maven.version>3.6.3</maven.version>
|
||||
|
||||
<jersey.version>2.35</jersey.version>
|
||||
<jersey.version>2.39.1</jersey.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.inteligr8.alfresco</groupId>
|
||||
<artifactId>aps-public-rest-api</artifactId>
|
||||
<version>2.0.3-aps1</version>
|
||||
<version>2.0.17</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.inteligr8.alfresco</groupId>
|
||||
<artifactId>aps-public-rest-client</artifactId>
|
||||
<version>2.0.2-jersey</version>
|
||||
<version>2.0.5-jersey</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
|
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.inteligr8.maven.aps.modeling.crawler;
|
||||
|
||||
/**
|
||||
* An interface for APS template export transformation implementations.
|
||||
*
|
||||
* An APS template is a JSON file.
|
||||
*
|
||||
* @author brian@inteligr8.com
|
||||
*/
|
||||
public interface ApsTemplateCrawlable {
|
||||
|
||||
/**
|
||||
* @return A file transformer for APS template JSON files.
|
||||
*/
|
||||
ApsFileTransformer getTemplateJsonTransformer();
|
||||
|
||||
}
|
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.inteligr8.maven.aps.modeling.crawler;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
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 ApsTemplateCrawler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ApsTemplateCrawler.class);
|
||||
private final File templateDirectory;
|
||||
private final boolean failOnIntegrityViolation;
|
||||
|
||||
/**
|
||||
* @param apsTemplateDirectory A directory to the APS template files.
|
||||
* @param failOnIntegrityViolation true to fail on file integrity issues; false to log warnings.
|
||||
*/
|
||||
public ApsTemplateCrawler(File apsTemplateDirectory, boolean failOnIntegrityViolation) {
|
||||
this.templateDirectory = apsTemplateDirectory;
|
||||
this.failOnIntegrityViolation = failOnIntegrityViolation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param crawlable A crawlable implementation; the callback for potential transformations.
|
||||
* @throws IOException A file access exception occurred.
|
||||
*/
|
||||
public void execute(ApsTemplateCrawlable crawlable) throws IOException {
|
||||
this.logger.info("Crawling APS templates ...");
|
||||
|
||||
this.crawlTemplates(crawlable.getTemplateJsonTransformer());
|
||||
}
|
||||
|
||||
protected void crawlTemplates(ApsFileTransformer transformer) throws IOException {
|
||||
for (File templateFile : this.templateDirectory.listFiles()) {
|
||||
if (!templateFile.getName().endsWith(".json"))
|
||||
continue;
|
||||
|
||||
this.logger.trace("Transforming template: {}", templateFile);
|
||||
|
||||
try {
|
||||
transformer.transformFile(templateFile, null, null);
|
||||
} catch (IllegalArgumentException | IllegalStateException ie) {
|
||||
if (this.failOnIntegrityViolation) {
|
||||
throw ie;
|
||||
} else {
|
||||
this.logger.warn(ie.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -14,6 +14,8 @@
|
||||
*/
|
||||
package com.inteligr8.maven.aps.modeling.goal;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.execution.MavenSession;
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
import org.apache.maven.settings.Server;
|
||||
@@ -21,6 +23,7 @@ import org.apache.maven.settings.Server;
|
||||
import com.inteligr8.alfresco.activiti.ApsClientJerseyConfiguration;
|
||||
import com.inteligr8.alfresco.activiti.ApsClientJerseyImpl;
|
||||
import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl;
|
||||
import com.inteligr8.alfresco.activiti.model.Tenant;
|
||||
|
||||
/**
|
||||
* This class adds APS addressbility to extending goals.
|
||||
@@ -117,6 +120,8 @@ public abstract class ApsAddressibleGoal extends DisablableGoal {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method constructs and caches the APS API accessor.
|
||||
*
|
||||
* @return An APS API instance.
|
||||
*/
|
||||
public synchronized ApsPublicRestApiJerseyImpl getApsApi() {
|
||||
@@ -128,5 +133,20 @@ public abstract class ApsAddressibleGoal extends DisablableGoal {
|
||||
|
||||
return this.api;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<Tenant> tenants = this.getApsApi().getAdminApi().getTenants();
|
||||
if (tenants == null || tenants.isEmpty())
|
||||
return null;
|
||||
return tenants.iterator().next().getId();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -21,9 +21,11 @@ import java.util.Map;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
|
||||
import com.inteligr8.activiti.model.Datum;
|
||||
import com.inteligr8.activiti.model.ResultList;
|
||||
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.ModelRepresentation;
|
||||
import com.inteligr8.alfresco.activiti.model.ResultListDataRepresentation;
|
||||
import com.inteligr8.alfresco.activiti.model.Tenant;
|
||||
|
||||
@@ -36,7 +38,7 @@ import com.inteligr8.alfresco.activiti.model.Tenant;
|
||||
*
|
||||
* @author brian@inteligr8.com
|
||||
*/
|
||||
public abstract class ApsAppAccessibleGoal extends ApsAddressibleGoal {
|
||||
public abstract class ApsAppAddressibleGoal extends ApsAddressibleGoal {
|
||||
|
||||
@Parameter( property = "aps-model.appName", required = true )
|
||||
protected String apsAppName;
|
||||
@@ -58,24 +60,23 @@ public abstract class ApsAppAccessibleGoal extends ApsAddressibleGoal {
|
||||
|
||||
/**
|
||||
* This method makes the appropriate service calls to find all the APS
|
||||
* Apps, returning them as a map of names to IDs.
|
||||
* Apps, returning them as a map of names to models.
|
||||
*
|
||||
* This method does not cache the result.
|
||||
*
|
||||
* @return A map of APS App names to their respective IDs; may be empty; never null.
|
||||
* @return A map of APS App names to their model; may be empty; never null.
|
||||
*/
|
||||
protected Map<String, Long> findAppNameIds() {
|
||||
protected Map<String, ModelRepresentation> buildAppNameMap() {
|
||||
ApsPublicRestApiJerseyImpl api = this.getApsApi();
|
||||
|
||||
Map<String, Long> apps = new HashMap<>(16);
|
||||
Map<String, ModelRepresentation> apps = new HashMap<>(16);
|
||||
|
||||
this.getLog().debug("Searching for all APS Apps");
|
||||
ResultListDataRepresentation results = api.getModelsApi().get("everyone", null, ModelType.App.getId(), null);
|
||||
ResultList<ModelRepresentation> results = api.getModelsApi().get("everyone", null, ModelType.App.getId(), null);
|
||||
this.getLog().debug("Found " + results.getTotal() + " APS Apps");
|
||||
for (Datum datum : results.getData()) {
|
||||
String name = (String)datum.getAdditionalProperties().get("name");
|
||||
Number id = (Number)datum.getAdditionalProperties().get("id");
|
||||
apps.put(name, id.longValue());
|
||||
for (ModelRepresentation model : results.getData()) {
|
||||
String name = model.getName();
|
||||
apps.put(name, model);
|
||||
}
|
||||
|
||||
return apps;
|
||||
@@ -88,11 +89,11 @@ public abstract class ApsAppAccessibleGoal extends ApsAddressibleGoal {
|
||||
* 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.
|
||||
* @return An APS App model; 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);
|
||||
protected ModelRepresentation findAppModel(boolean failOnNotFound) throws MojoExecutionException {
|
||||
return this.findAppModelByName(this.apsAppName, failOnNotFound);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,15 +104,15 @@ public abstract class ApsAppAccessibleGoal extends ApsAddressibleGoal {
|
||||
*
|
||||
* @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.
|
||||
* @return An APS App model; null if not found.
|
||||
* @throws MojoExecutionException The APS App could not be found.
|
||||
*/
|
||||
protected Long findAppIdByName(String appName, boolean failOnNotFound) throws MojoExecutionException {
|
||||
Map<String, Long> apps = this.findAppNameIds();
|
||||
Long appId = apps.get(this.apsAppName);
|
||||
if (failOnNotFound && appId == null)
|
||||
protected ModelRepresentation findAppModelByName(String appName, boolean failOnNotFound) throws MojoExecutionException {
|
||||
Map<String, ModelRepresentation> apps = this.buildAppNameMap();
|
||||
ModelRepresentation appModel = apps.get(this.apsAppName);
|
||||
if (failOnNotFound && appModel == null)
|
||||
throw new MojoExecutionException("The APS App '" + this.apsAppName + "' could not be found; valid apps: " + apps.keySet());
|
||||
return appId;
|
||||
return appModel;
|
||||
}
|
||||
|
||||
}
|
@@ -26,12 +26,13 @@ import org.apache.maven.plugins.annotations.Mojo;
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
import org.codehaus.plexus.component.annotations.Component;
|
||||
|
||||
import com.inteligr8.activiti.model.Datum;
|
||||
import com.inteligr8.activiti.model.ResultList;
|
||||
import com.inteligr8.alfresco.activiti.api.ModelsApi;
|
||||
import com.inteligr8.alfresco.activiti.model.Datum;
|
||||
import com.inteligr8.alfresco.activiti.model.GroupLight;
|
||||
import com.inteligr8.alfresco.activiti.model.ModelRepresentation;
|
||||
import com.inteligr8.alfresco.activiti.model.PermissionLevel;
|
||||
import com.inteligr8.alfresco.activiti.model.PermissionLight;
|
||||
import com.inteligr8.alfresco.activiti.model.ResultList;
|
||||
import com.inteligr8.alfresco.activiti.model.ResultListDataRepresentation;
|
||||
import com.inteligr8.alfresco.activiti.model.ShareInfoRequest;
|
||||
import com.inteligr8.alfresco.activiti.model.SharePermission;
|
||||
@@ -108,14 +109,12 @@ public class ApsShareGoal extends ApsAddressibleGoal {
|
||||
}
|
||||
|
||||
private void shareModels(ModelsApi.ModelType modelType, Set<String> readers, Set<String> editors) {
|
||||
ResultListDataRepresentation models = this.getApsApi().getModelsApi().get(null, null, modelType.getId(), null);
|
||||
ResultList<ModelRepresentation> models = this.getApsApi().getModelsApi().get(null, null, modelType.getId(), null);
|
||||
if (models.getData() == null)
|
||||
return;
|
||||
|
||||
for (Datum datum : models.getData()) {
|
||||
Number modelId = (Number)datum.getAdditionalProperties().get("id");
|
||||
String modelName = (String)datum.getAdditionalProperties().get("name");
|
||||
if (this.modelName != null && !this.modelName.equals(modelName))
|
||||
for (ModelRepresentation model : models.getData()) {
|
||||
if (this.modelName != null && !this.modelName.equals(model.getName()))
|
||||
continue;
|
||||
|
||||
Set<String> groupsAddressed = new HashSet<>();
|
||||
@@ -123,7 +122,7 @@ public class ApsShareGoal extends ApsAddressibleGoal {
|
||||
Set<String> editorsUnaddressed = new HashSet<>(editors);
|
||||
ShareInfoRequest changeRequest = new ShareInfoRequest();
|
||||
|
||||
ResultList<SharePermission> shares = this.getApsApi().getShareApi().getShareInfo(modelId.toString());
|
||||
ResultList<SharePermission> shares = this.getApsApi().getShareApi().getShareInfo(model.getId().toString());
|
||||
if (shares.getData() != null) {
|
||||
for (SharePermission share : shares.getData()) {
|
||||
if (share.getGroup() != null) {
|
||||
@@ -145,7 +144,7 @@ public class ApsShareGoal extends ApsAddressibleGoal {
|
||||
|
||||
if (!changeRequest.getAdded().isEmpty() || !changeRequest.getUpdated().isEmpty() || !changeRequest.getRemoved().isEmpty()) {
|
||||
this.getLog().info("Sharing model: " + modelType + " => '" + modelName + "'");
|
||||
this.getApsApi().getShareApi().setShareInfo(modelId.toString(), changeRequest);
|
||||
this.getApsApi().getShareApi().setShareInfo(model.getId().toString(), changeRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.inteligr8.maven.aps.modeling.goal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
|
||||
import com.inteligr8.activiti.model.ResultList;
|
||||
import com.inteligr8.alfresco.activiti.model.BaseTemplateLight;
|
||||
import com.inteligr8.alfresco.activiti.model.DocumentTemplateLight;
|
||||
import com.inteligr8.alfresco.activiti.model.EmailTemplateLight;
|
||||
|
||||
/**
|
||||
* 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 ApsTemplateAddressibleGoal extends ApsAddressibleGoal {
|
||||
|
||||
public enum TemplateType {
|
||||
SystemEmail,
|
||||
CustomEmail,
|
||||
Document
|
||||
}
|
||||
|
||||
@Parameter( property = "aps-model.documentTemplateNames", defaultValue = ".*" )
|
||||
protected String apsDocumentTemplateNames;
|
||||
@Parameter( property = "aps-model.systemEmailTemplateNames", defaultValue = ".*" )
|
||||
protected String apsSystemEmailTemplateNames;
|
||||
@Parameter( property = "aps-model.customEmailTemplateNames", defaultValue = ".*" )
|
||||
protected String apsCustomEmailTemplateNames;
|
||||
|
||||
protected Map<TemplateType, Map<String, ? extends BaseTemplateLight>> findTemplates() {
|
||||
Long tenantId = this.findTenantId();
|
||||
return this.findTemplates(tenantId);
|
||||
}
|
||||
|
||||
protected Map<TemplateType, Map<String, ? extends BaseTemplateLight>> findTemplates(Long tenantId) {
|
||||
Map<TemplateType, Map<String, ? extends BaseTemplateLight>> templates = new HashMap<>(32);
|
||||
|
||||
Map<String, ? extends BaseTemplateLight> systemEmailTemplateNames = this.findSystemEmailTemplates(tenantId);
|
||||
if (systemEmailTemplateNames != null && !systemEmailTemplateNames.isEmpty())
|
||||
templates.put(TemplateType.SystemEmail, systemEmailTemplateNames);
|
||||
|
||||
Map<String, ? extends BaseTemplateLight> customEmailTemplateNames = this.findCustomEmailTemplates(tenantId);
|
||||
if (customEmailTemplateNames != null && !customEmailTemplateNames.isEmpty())
|
||||
templates.put(TemplateType.CustomEmail, customEmailTemplateNames);
|
||||
|
||||
Map<String, ? extends BaseTemplateLight> docTemplateNames = this.findDocumentTemplates(tenantId);
|
||||
if (docTemplateNames != null && !docTemplateNames.isEmpty())
|
||||
templates.put(TemplateType.Document, docTemplateNames);
|
||||
|
||||
return templates;
|
||||
}
|
||||
|
||||
protected Map<String, ? extends BaseTemplateLight> findSystemEmailTemplates(Long tenantId) {
|
||||
this.getLog().debug("Searching for all APS System Email Templates");
|
||||
|
||||
List<Pattern> matchingPatterns = this.buildPatterns(this.apsSystemEmailTemplateNames);
|
||||
Map<String, EmailTemplateLight> map = new HashMap<>();
|
||||
|
||||
ResultList<EmailTemplateLight> templates = this.getApsApi().getTemplatesApi().getSystemEmailTemplates(tenantId);
|
||||
for (EmailTemplateLight template : templates.getData()) {
|
||||
for (Pattern pattern : matchingPatterns) {
|
||||
if (pattern.matcher(template.getName()).matches())
|
||||
map.put(template.getName(), template);
|
||||
}
|
||||
}
|
||||
|
||||
this.getLog().debug("Found APS System Email Templates: " + map.size());
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
protected Map<String, ? extends BaseTemplateLight> findCustomEmailTemplates(Long tenantId) {
|
||||
this.getLog().debug("Searching for all APS Custom Email Templates");
|
||||
|
||||
List<Pattern> matchingPatterns = this.buildPatterns(this.apsCustomEmailTemplateNames);
|
||||
Map<String, EmailTemplateLight> map = new HashMap<>();
|
||||
int pageSize = 50;
|
||||
int page = 1;
|
||||
|
||||
ResultList<EmailTemplateLight> templates = this.getApsApi().getTemplatesApi().getCustomEmailTemplates(null, (page-1) * pageSize, pageSize, "sort_by_name_asc", tenantId);
|
||||
while (!templates.getData().isEmpty()) {
|
||||
for (EmailTemplateLight template : templates.getData()) {
|
||||
for (Pattern pattern : matchingPatterns) {
|
||||
if (pattern.matcher(template.getName()).matches())
|
||||
map.put(template.getName(), template);
|
||||
}
|
||||
}
|
||||
|
||||
page++;
|
||||
templates = this.getApsApi().getTemplatesApi().getCustomEmailTemplates(null, (page-1) * pageSize, pageSize, "sort_by_name_asc", tenantId);
|
||||
}
|
||||
|
||||
this.getLog().debug("Found APS Custom Email Templates: " + map.size());
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
protected Map<String, ? extends BaseTemplateLight> findDocumentTemplates(Long tenantId) {
|
||||
List<Pattern> matchingPatterns = this.buildPatterns(this.apsDocumentTemplateNames);
|
||||
Map<String, DocumentTemplateLight> map = new HashMap<>();
|
||||
int pageSize = 50;
|
||||
int page = 1;
|
||||
|
||||
ResultList<DocumentTemplateLight> templates = this.getApsApi().getTemplatesApi().getDocumentTemplates(null, (page-1) * pageSize, pageSize, "sort_by_name_asc", tenantId);
|
||||
while (!templates.getData().isEmpty()) {
|
||||
for (DocumentTemplateLight template : templates.getData()) {
|
||||
for (Pattern pattern : matchingPatterns) {
|
||||
if (pattern.matcher(template.getName()).matches())
|
||||
map.put(template.getName(), template);
|
||||
}
|
||||
}
|
||||
|
||||
page++;
|
||||
templates = this.getApsApi().getTemplatesApi().getDocumentTemplates(null, (page-1) * pageSize, pageSize, "sort_by_name_asc", tenantId);
|
||||
}
|
||||
|
||||
this.getLog().debug("Found APS Document Templates: " + map.size());
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
private List<Pattern> buildPatterns(String regexes) {
|
||||
if (regexes == null)
|
||||
return Collections.emptyList();
|
||||
|
||||
List<Pattern> patterns = new LinkedList<>();
|
||||
|
||||
for (String regex : regexes.split(",")) {
|
||||
regex = regex.trim();
|
||||
if (regex.length() > 0)
|
||||
patterns.add(Pattern.compile(regex));
|
||||
}
|
||||
|
||||
return patterns;
|
||||
}
|
||||
|
||||
}
|
@@ -37,7 +37,7 @@ import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl;
|
||||
*/
|
||||
@Mojo( name = "download-app", threadSafe = true )
|
||||
@Component( role = org.apache.maven.plugin.Mojo.class )
|
||||
public class DownloadAppGoal extends ApsAppAccessibleGoal {
|
||||
public class DownloadAppGoal extends ApsAppAddressibleGoal {
|
||||
|
||||
@Parameter( property = "aps-model.download.directory", required = true, defaultValue = "${project.build.directory}/aps" )
|
||||
protected File zipDirectory;
|
||||
@@ -46,7 +46,7 @@ public class DownloadAppGoal extends ApsAppAccessibleGoal {
|
||||
public void executeEnabled() throws MojoExecutionException, MojoFailureException {
|
||||
this.validateTargetDirectory();
|
||||
|
||||
Long appId = this.findAppId(true);
|
||||
Long appId = this.findAppModel(true).getId();
|
||||
File appZip = this.downloadApp(appId);
|
||||
|
||||
File toAppZip = new File(this.zipDirectory, this.apsAppName + ".zip");
|
||||
@@ -65,7 +65,7 @@ public class DownloadAppGoal extends ApsAppAccessibleGoal {
|
||||
this.getLog().debug("Creating APS Apps directory: " + this.zipDirectory);
|
||||
this.zipDirectory.mkdirs();
|
||||
} else if (!this.zipDirectory.isDirectory()) {
|
||||
throw new IllegalStateException("The 'targetDirectory' refers to a file and not a directory");
|
||||
throw new IllegalStateException("The 'zipDirectory' refers to a file and not a directory");
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.inteligr8.maven.aps.modeling.goal;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.apache.maven.plugins.annotations.Mojo;
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
import org.codehaus.plexus.component.annotations.Component;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import com.inteligr8.alfresco.activiti.model.BaseTemplateLight;
|
||||
import com.inteligr8.alfresco.activiti.model.DocumentTemplateLight;
|
||||
import com.inteligr8.alfresco.activiti.model.EmailTemplate;
|
||||
import com.inteligr8.maven.aps.modeling.normalizer.ApsTemplateJsonNormalizer;
|
||||
import com.inteligr8.maven.aps.modeling.util.ModelUtil;
|
||||
|
||||
/**
|
||||
* A class that implements an APS service download goal.
|
||||
*
|
||||
* This goal will simply download the APS templates with the specified names
|
||||
* from the specified APS service.
|
||||
*
|
||||
* @author brian@inteligr8.com
|
||||
*/
|
||||
@Mojo( name = "download-template", threadSafe = true )
|
||||
@Component( role = org.apache.maven.plugin.Mojo.class )
|
||||
public class DownloadTemplateGoal extends ApsTemplateAddressibleGoal {
|
||||
|
||||
@Parameter( property = "aps-model.download.directory", required = true, defaultValue = "${project.build.directory}/aps" )
|
||||
protected File templateDirectory;
|
||||
|
||||
@Parameter( property = "aps-model.normalize" )
|
||||
protected boolean normalize;
|
||||
|
||||
@Parameter( property = "aps-model.normalize.diffFriendly" )
|
||||
protected boolean diffFriendly;
|
||||
|
||||
@Override
|
||||
public void executeEnabled() throws MojoExecutionException, MojoFailureException {
|
||||
this.validateTargetDirectory();
|
||||
|
||||
Long tenantId = this.findTenantId();
|
||||
|
||||
try {
|
||||
Map<TemplateType, Map<String, ? extends BaseTemplateLight>> templates = this.findTemplates(tenantId);
|
||||
for (TemplateType ttype : templates.keySet()) {
|
||||
this.getLog().info("Downloading " + templates.get(ttype).size() + " " + ttype + " templates");
|
||||
|
||||
for (Entry<String, ? extends BaseTemplateLight> template : templates.get(ttype).entrySet()) {
|
||||
switch (ttype) {
|
||||
case Document:
|
||||
File dfilebin = new File(this.templateDirectory, template.getValue().getName());
|
||||
|
||||
Response response = this.getApsApi().getTemplatesApi().getDocumentTemplate(
|
||||
template.getValue().getId(),
|
||||
System.currentTimeMillis());
|
||||
try {
|
||||
if (response.getStatus() / 100 == 2) {
|
||||
InputStream istream = (InputStream) response.getEntity();
|
||||
try {
|
||||
FileUtils.copyInputStreamToFile(istream, dfilebin);
|
||||
} finally {
|
||||
istream.close();
|
||||
}
|
||||
} else {
|
||||
this.getLog().warn("The document template could not be downloaded; skipping: " + template.getValue().getName());
|
||||
continue;
|
||||
}
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
|
||||
ObjectNode djson = ModelUtil.getInstance().readPojo(template.getValue());
|
||||
File dfile = new File(this.templateDirectory, template.getValue().getName() + ".dt.json");
|
||||
ModelUtil.getInstance().writeJson(djson, dfile, this.diffFriendly);
|
||||
if (this.normalize)
|
||||
new ApsTemplateJsonNormalizer(this.diffFriendly).normalizeFile(dfile, null);
|
||||
|
||||
break;
|
||||
case CustomEmail:
|
||||
EmailTemplate etemplate = this.getApsApi().getTemplatesApi().getCustomEmailTemplate(template.getValue().getId(), tenantId);
|
||||
ObjectNode ejson = ModelUtil.getInstance().readPojo(etemplate);
|
||||
File efile = new File(this.templateDirectory, template.getValue().getName() + ".cet.json");
|
||||
ModelUtil.getInstance().writeJson(ejson, efile, this.diffFriendly);
|
||||
if (this.normalize)
|
||||
new ApsTemplateJsonNormalizer(this.diffFriendly).normalizeFile(efile, null);
|
||||
|
||||
break;
|
||||
case SystemEmail:
|
||||
EmailTemplate stemplate = this.getApsApi().getTemplatesApi().getSystemEmailTemplate(template.getValue().getName(), tenantId);
|
||||
ObjectNode sjson = ModelUtil.getInstance().readPojo(stemplate);
|
||||
File sfile = new File(this.templateDirectory, template.getValue().getName() + ".set.json");
|
||||
ModelUtil.getInstance().writeJson(sjson, sfile, this.diffFriendly);
|
||||
if (this.normalize)
|
||||
new ApsTemplateJsonNormalizer(this.diffFriendly).normalizeFile(sfile, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException ie) {
|
||||
throw new MojoExecutionException("The downloaded APS templates could not be saved", ie);
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateTargetDirectory() {
|
||||
if (!this.templateDirectory.exists()) {
|
||||
this.getLog().debug("Creating APS template directory: " + this.templateDirectory);
|
||||
this.templateDirectory.mkdirs();
|
||||
} else if (!this.templateDirectory.isDirectory()) {
|
||||
throw new IllegalStateException("The 'templateDirectory' refers to a file and not a directory");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -35,14 +35,17 @@ import com.inteligr8.alfresco.activiti.model.AppDefinitionPublishRepresentation;
|
||||
*/
|
||||
@Mojo( name = "publish-app", threadSafe = true )
|
||||
@Component( role = org.apache.maven.plugin.Mojo.class )
|
||||
public class PublishAppGoal extends ApsAppAccessibleGoal {
|
||||
public class PublishAppGoal extends ApsAppAddressibleGoal {
|
||||
|
||||
@Parameter( property = "aps-model.publish.comment", required = true, defaultValue = "Automated by 'aps-model-maven-plugin'" )
|
||||
protected String comment;
|
||||
|
||||
@Parameter( property = "aps-model.dryRun", required = true, defaultValue = "false" )
|
||||
protected boolean dryRun;
|
||||
|
||||
@Override
|
||||
public void executeEnabled() throws MojoExecutionException, MojoFailureException {
|
||||
Long appId = this.findAppId(false);
|
||||
Long appId = this.findAppModel(false).getId();
|
||||
|
||||
try {
|
||||
this.publishApp(appId);
|
||||
@@ -56,7 +59,12 @@ public class PublishAppGoal extends ApsAppAccessibleGoal {
|
||||
|
||||
AppDefinitionPublishRepresentation appDefPublish = new AppDefinitionPublishRepresentation();
|
||||
appDefPublish.setComment(this.comment);
|
||||
api.getAppDefinitionsApi().publish(appId, appDefPublish);
|
||||
if (this.dryRun) {
|
||||
this.getLog().info("[DRYRUN]: Publishing app: " + appId);
|
||||
} else {
|
||||
this.getLog().info("Publishing app: " + appId);
|
||||
api.getAppDefinitionsApi().publish(appId, appDefPublish);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -33,7 +33,7 @@ import com.inteligr8.maven.aps.modeling.translator.ApsAppTranslator;
|
||||
* 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.
|
||||
* of those model 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
|
||||
@@ -43,7 +43,7 @@ import com.inteligr8.maven.aps.modeling.translator.ApsAppTranslator;
|
||||
*/
|
||||
@Mojo( name = "translate-app", threadSafe = true )
|
||||
@Component( role = org.apache.maven.plugin.Mojo.class )
|
||||
public class TranslateAppGoal extends ApsAppAccessibleGoal {
|
||||
public class TranslateAppGoal extends ApsAppAddressibleGoal {
|
||||
|
||||
@Parameter( property = "aps-model.app.directory", required = true, defaultValue = "${project.build.directory}/aps/app" )
|
||||
protected File unzipDirectory;
|
||||
|
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.inteligr8.maven.aps.modeling.goal;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.apache.maven.plugins.annotations.Mojo;
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
import org.codehaus.plexus.component.annotations.Component;
|
||||
|
||||
import com.inteligr8.maven.aps.modeling.crawler.ApsTemplateCrawler;
|
||||
import com.inteligr8.maven.aps.modeling.translator.ApsTemplateTranslator;
|
||||
|
||||
/**
|
||||
* A class that implements an APS template translation goal.
|
||||
*
|
||||
* This goal will translate all the JSON template files to match the
|
||||
* environment referenced by the specified APS service. This relies on all APS
|
||||
* templates having unique names. The names of those templates are used to
|
||||
* remap IDs between environments.
|
||||
*
|
||||
* @author brian@inteligr8.com
|
||||
*/
|
||||
@Mojo( name = "translate-template", threadSafe = true )
|
||||
@Component( role = org.apache.maven.plugin.Mojo.class )
|
||||
public class TranslateTemplateGoal extends ApsAddressibleGoal {
|
||||
|
||||
@Parameter( property = "aps-model.template.directory", required = true, defaultValue = "${project.build.directory}/aps" )
|
||||
protected File templateDirectory;
|
||||
|
||||
@Parameter( property = "aps-model.translatedTemplate.directory", required = false, defaultValue = "${project.build.directory}/aps" )
|
||||
protected File finalDirectory;
|
||||
|
||||
@Parameter( property = "aps-model.translate.overwrite", required = true, defaultValue = "true" )
|
||||
protected boolean overwrite = true;
|
||||
|
||||
@Parameter( property = "aps-model.translate.charset", required = true, defaultValue = "utf-8" )
|
||||
protected String charsetName = "utf-8";
|
||||
|
||||
@Override
|
||||
public void executeEnabled() throws MojoExecutionException, MojoFailureException {
|
||||
this.validateApsTemplateDirectory();
|
||||
this.validateTargetDirectory();
|
||||
|
||||
try {
|
||||
if (!this.templateDirectory.equals(this.finalDirectory)) {
|
||||
FileUtils.copyDirectory(this.templateDirectory, this.finalDirectory);
|
||||
}
|
||||
|
||||
ApsTemplateTranslator translator = new ApsTemplateTranslator(this.getApsApi());
|
||||
translator.buildIndexes();
|
||||
|
||||
ApsTemplateCrawler crawler = new ApsTemplateCrawler(this.finalDirectory, true);
|
||||
crawler.execute(translator);
|
||||
} catch (IOException ie) {
|
||||
throw new MojoExecutionException("An I/O issue occurred", ie);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
throw new MojoExecutionException("The input is not supported", iae);
|
||||
} catch (IllegalStateException ise) {
|
||||
throw new MojoExecutionException("The state of system is not supported", ise);
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateApsTemplateDirectory() throws MojoExecutionException {
|
||||
if (!this.templateDirectory.exists())
|
||||
throw new MojoExecutionException("The 'templateDirectory' does not exist: " + this.templateDirectory);
|
||||
if (!this.templateDirectory.isDirectory())
|
||||
throw new MojoExecutionException("The 'templateDirectory' is not a directory: " + this.templateDirectory);
|
||||
}
|
||||
|
||||
protected void validateTargetDirectory() throws MojoExecutionException {
|
||||
if (!this.finalDirectory.exists()) {
|
||||
this.finalDirectory.mkdirs();
|
||||
} else if (!this.finalDirectory.isDirectory()) {
|
||||
throw new MojoExecutionException("The 'finalDirectory' is not a directory: " + this.finalDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -29,6 +29,7 @@ import org.codehaus.plexus.component.annotations.Component;
|
||||
import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl;
|
||||
import com.inteligr8.alfresco.activiti.model.AppDefinitionUpdateResultRepresentation;
|
||||
import com.inteligr8.alfresco.activiti.model.FileMultipartJersey;
|
||||
import com.inteligr8.alfresco.activiti.model.ModelRepresentation;
|
||||
|
||||
/**
|
||||
* A class that implements an APS service upload goal.
|
||||
@@ -42,13 +43,16 @@ import com.inteligr8.alfresco.activiti.model.FileMultipartJersey;
|
||||
*/
|
||||
@Mojo( name = "upload-app", threadSafe = true )
|
||||
@Component( role = org.apache.maven.plugin.Mojo.class )
|
||||
public class UploadAppGoal extends ApsAppAccessibleGoal {
|
||||
public class UploadAppGoal extends ApsAppAddressibleGoal {
|
||||
|
||||
@Parameter( property = "aps-model.upload.directory", required = true, defaultValue = "${project.build.directory}/aps" )
|
||||
protected File zipDirectory;
|
||||
|
||||
@Parameter( property = "publish", required = true, defaultValue = "false" )
|
||||
protected boolean publish = false;
|
||||
|
||||
@Parameter( property = "aps-model.dryRun", required = true, defaultValue = "false" )
|
||||
protected boolean dryRun;
|
||||
|
||||
protected final int bufferSize = 128 * 1024;
|
||||
|
||||
@@ -56,10 +60,10 @@ public class UploadAppGoal extends ApsAppAccessibleGoal {
|
||||
public void executeEnabled() throws MojoExecutionException, MojoFailureException {
|
||||
File sourceFile = this.validateSourceDirectory();
|
||||
|
||||
Long appId = this.findAppId(false);
|
||||
ModelRepresentation appModel = this.findAppModel(false);
|
||||
|
||||
try {
|
||||
this.uploadApp(appId, sourceFile);
|
||||
this.uploadApp(appModel, sourceFile);
|
||||
} catch (IOException ie) {
|
||||
throw new MojoExecutionException("The APS App could not be uploaded", ie);
|
||||
}
|
||||
@@ -83,7 +87,7 @@ public class UploadAppGoal extends ApsAppAccessibleGoal {
|
||||
return sourceFile;
|
||||
}
|
||||
|
||||
private void uploadApp(Long appId, File appZip) throws IOException, MojoExecutionException {
|
||||
private void uploadApp(ModelRepresentation appModel, File appZip) throws IOException, MojoExecutionException {
|
||||
ApsPublicRestApiJerseyImpl api = this.getApsApi();
|
||||
|
||||
FileInputStream fistream = new FileInputStream(appZip);
|
||||
@@ -91,25 +95,41 @@ public class UploadAppGoal extends ApsAppAccessibleGoal {
|
||||
try {
|
||||
FileMultipartJersey multipart = FileMultipartJersey.from(appZip.getName(), bistream);
|
||||
|
||||
if (appId == null) {
|
||||
if (appModel == null) {
|
||||
if (this.publish) {
|
||||
this.getLog().info("Uploading & publishing new APS App: " + this.apsAppName);
|
||||
AppDefinitionUpdateResultRepresentation appDefUpdate = api.getAppDefinitionsJerseyApi().publishApp(multipart);
|
||||
if (Boolean.TRUE.equals(appDefUpdate.getError()))
|
||||
throw new MojoExecutionException(appDefUpdate.getErrorDescription());
|
||||
if (this.dryRun) {
|
||||
this.getLog().info("[DRYRUN]: Uploading & publishing new APS App: " + this.apsAppName);
|
||||
} else {
|
||||
this.getLog().info("Uploading & publishing new APS App: " + this.apsAppName);
|
||||
AppDefinitionUpdateResultRepresentation appDefUpdate = api.getAppDefinitionsJerseyApi().publishApp(multipart);
|
||||
if (Boolean.TRUE.equals(appDefUpdate.getError()))
|
||||
throw new MojoExecutionException(appDefUpdate.getErrorDescription());
|
||||
}
|
||||
} else {
|
||||
this.getLog().info("Uploading new APS App: " + this.apsAppName);
|
||||
api.getAppDefinitionsJerseyApi().importApp(multipart, true);
|
||||
if (this.dryRun) {
|
||||
this.getLog().info("[DRYRUN]: Uploading new APS App: " + this.apsAppName);
|
||||
} else {
|
||||
this.getLog().info("Uploading new APS App: " + this.apsAppName);
|
||||
api.getAppDefinitionsJerseyApi().importApp(multipart, true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (this.publish) {
|
||||
this.getLog().info("Uploading, versioning, & publishing APS App: " + this.apsAppName + " (" + appId + ")");
|
||||
AppDefinitionUpdateResultRepresentation appDefUpdate = api.getAppDefinitionsJerseyApi().publishApp(appId, multipart);
|
||||
if (Boolean.TRUE.equals(appDefUpdate.getError()))
|
||||
throw new MojoExecutionException(appDefUpdate.getErrorDescription());
|
||||
if (this.dryRun) {
|
||||
this.getLog().info("[DRYRUN]: Uploading, versioning, & publishing APS App: " + this.apsAppName + " (" + appModel.getId() + ")");
|
||||
} else {
|
||||
this.getLog().info("Uploading, versioning, & publishing APS App: " + this.apsAppName + " (" + appModel.getId() + ")");
|
||||
AppDefinitionUpdateResultRepresentation appDefUpdate = api.getAppDefinitionsJerseyApi().publishApp(appModel.getId(), multipart);
|
||||
if (Boolean.TRUE.equals(appDefUpdate.getError()))
|
||||
throw new MojoExecutionException(appDefUpdate.getErrorDescription());
|
||||
}
|
||||
} else {
|
||||
this.getLog().info("Uploading & versioning APS App: " + this.apsAppName + " (" + appId + ")");
|
||||
api.getAppDefinitionsJerseyApi().importApp(appId, multipart, true);
|
||||
if (this.dryRun) {
|
||||
this.getLog().info("[DRYRUN]: Uploading & versioning APS App: " + this.apsAppName + " (" + appModel.getId() + ")");
|
||||
} else {
|
||||
this.getLog().info("Uploading & versioning APS App: " + this.apsAppName + " (" + appModel.getId() + ")");
|
||||
api.getAppDefinitionsJerseyApi().importApp(appModel.getId(), multipart, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ParseException pe) {
|
||||
|
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.inteligr8.maven.aps.modeling.goal;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.apache.maven.plugins.annotations.Mojo;
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
import org.codehaus.plexus.component.annotations.Component;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.inteligr8.alfresco.activiti.model.DocumentTemplateLight;
|
||||
import com.inteligr8.alfresco.activiti.model.EmailTemplate;
|
||||
import com.inteligr8.alfresco.activiti.model.EmailTemplateLight;
|
||||
import com.inteligr8.alfresco.activiti.model.FileMultipartJersey;
|
||||
import com.inteligr8.maven.aps.modeling.util.ModelUtil;
|
||||
|
||||
/**
|
||||
* A class that implements an APS service upload goal.
|
||||
*
|
||||
* This goal will simply upload the APS templates within the specified template
|
||||
* directory to the specified APS service. Any IDs specified in the uploaded
|
||||
* templates must match existing IDs for them to properly version. That is the
|
||||
* main purpose of this plugin and can be achieved using the
|
||||
* 'translate-template' goal.
|
||||
*
|
||||
* @author brian@inteligr8.com
|
||||
*/
|
||||
@Mojo( name = "upload-template", threadSafe = true )
|
||||
@Component( role = org.apache.maven.plugin.Mojo.class )
|
||||
public class UploadTemplateGoal extends ApsAddressibleGoal {
|
||||
|
||||
@Parameter( property = "aps-model.upload.directory", required = true, defaultValue = "${project.build.directory}/aps" )
|
||||
protected File templateDirectory;
|
||||
|
||||
@Parameter( required = true, defaultValue = "false" )
|
||||
protected boolean alwaysOverwrite;
|
||||
|
||||
@Parameter( property = "aps-model.dryRun", required = true, defaultValue = "false" )
|
||||
protected boolean dryRun;
|
||||
|
||||
protected final int bufferSize = 128 * 1024;
|
||||
|
||||
@Override
|
||||
public void executeEnabled() throws MojoExecutionException, MojoFailureException {
|
||||
this.validateSourceDirectory();
|
||||
|
||||
Long tenantId = this.findTenantId();
|
||||
|
||||
for (File file : this.templateDirectory.listFiles()) {
|
||||
if (!file.getName().endsWith(".json")) {
|
||||
this.getLog().debug("Ignoring file: " + file.getName());
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
if (file.getName().endsWith(".dt.json")) {
|
||||
DocumentTemplateLight template = ModelUtil.getInstance().writePojo(ModelUtil.getInstance().readJsonAsMap(file), DocumentTemplateLight.class);
|
||||
if (!this.alwaysOverwrite && template.getId() != null && template.getCreated() != null) {
|
||||
DocumentTemplateLight serverSideTemplate = this.getApsApi().getTemplatesApi().getDocumentTemplate(template.getId());
|
||||
if (serverSideTemplate != null && !serverSideTemplate.getCreated().isBefore(template.getCreated())) {
|
||||
this.getLog().debug("Document template unchanged; not updating: " + template.getId());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
File dfile = new File(file.getParent(), file.getName().substring(0, file.getName().length() - ".dt.json".length()));
|
||||
if (!dfile.exists())
|
||||
throw new FileNotFoundException("The file, '" + dfile.getName() + "' was expected and not found");
|
||||
|
||||
FileInputStream fistream = new FileInputStream(dfile);
|
||||
BufferedInputStream bistream = new BufferedInputStream(fistream, this.bufferSize);
|
||||
try {
|
||||
FileMultipartJersey multipart = FileMultipartJersey.from(dfile.getName(), bistream);
|
||||
if (template.getId() == null) {
|
||||
if (this.dryRun) {
|
||||
this.getLog().info("[DRYRUN]: Creating document template: " + template.getName());
|
||||
} else {
|
||||
this.getLog().info("Creating document template: " + template.getName());
|
||||
this.getApsApi().getTemplatesJerseyApi().createDocumentTemplate(tenantId, multipart);
|
||||
}
|
||||
} else {
|
||||
if (this.dryRun) {
|
||||
this.getLog().info("[DRYRUN]: Updating document template: " + template.getName());
|
||||
} else {
|
||||
this.getLog().info("Updating document template: " + template.getName());
|
||||
this.getApsApi().getTemplatesJerseyApi().updateDocumentTemplate(template.getId(), tenantId, multipart);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
bistream.close();
|
||||
fistream.close();
|
||||
}
|
||||
} else if (file.getName().endsWith(".cet.json")) {
|
||||
EmailTemplate template = ModelUtil.getInstance().writePojo(ModelUtil.getInstance().readJsonAsMap(file), EmailTemplate.class);
|
||||
if (!this.alwaysOverwrite && template.getId() != null && template.getCreated() != null) {
|
||||
EmailTemplate serverSideTemplate = this.getApsApi().getTemplatesApi().getCustomEmailTemplate(template.getId(), tenantId);
|
||||
if (serverSideTemplate != null && !serverSideTemplate.getCreated().isBefore(template.getCreated())) {
|
||||
this.getLog().debug("Custom email template unchanged; not updating: " + template.getId());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (template.getId() == null) {
|
||||
if (this.dryRun) {
|
||||
this.getLog().info("[DRYRUN]: Creating custom email template: " + template.getName());
|
||||
} else {
|
||||
this.getLog().info("Creating custom email template: " + template.getName());
|
||||
this.getApsApi().getTemplatesJerseyApi().createCustomEmailTemplate(template);
|
||||
}
|
||||
} else {
|
||||
if (this.dryRun) {
|
||||
this.getLog().info("[DRYRUN]: Updating custom email template: " + template.getName());
|
||||
} else {
|
||||
this.getLog().info("Updating custom email template: " + template.getName());
|
||||
this.getApsApi().getTemplatesJerseyApi().updateCustomEmailTemplate(template.getId(), template);
|
||||
}
|
||||
}
|
||||
} else if (file.getName().endsWith(".set.json")) {
|
||||
EmailTemplate template = ModelUtil.getInstance().writePojo(ModelUtil.getInstance().readJsonAsMap(file), EmailTemplate.class);
|
||||
if (!this.alwaysOverwrite) {
|
||||
EmailTemplate serverSideTemplate = this.getApsApi().getTemplatesApi().getSystemEmailTemplate(template.getName(), tenantId);
|
||||
if (serverSideTemplate != null && template.getTemplate().equals(serverSideTemplate.getTemplate())) {
|
||||
this.getLog().debug("System email template unchanged; not updating: " + template.getName());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.dryRun) {
|
||||
this.getLog().info("[DRYRUN]: Updating system email template: " + template.getName());
|
||||
} else {
|
||||
this.getLog().info("Updating system email template: " + template.getName());
|
||||
this.getApsApi().getTemplatesJerseyApi().updateSystemEmailTemplate(template.getName(), template);
|
||||
}
|
||||
}
|
||||
} catch (JsonProcessingException jpe) {
|
||||
throw new MojoExecutionException("The APS templates JSON files could not be parsed", jpe);
|
||||
} catch (IOException ie) {
|
||||
throw new MojoExecutionException("The APS templates could not be uploaded", ie);
|
||||
} catch (ParseException pe) {
|
||||
throw new MojoFailureException("This should never happen", pe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateSourceDirectory() {
|
||||
if (!this.templateDirectory.exists()) {
|
||||
throw new IllegalStateException("The 'templateDirectory' does not exist: " + this.templateDirectory);
|
||||
} else if (!this.templateDirectory.isDirectory()) {
|
||||
throw new IllegalStateException("The 'templateDirectory' is not a directory: " + this.templateDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.inteligr8.maven.aps.modeling.normalizer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import com.inteligr8.maven.aps.modeling.util.ModelUtil;
|
||||
|
||||
/**
|
||||
* This class implements an APS template JSON configuration file normalizer.
|
||||
*
|
||||
* This will remove the 'createdBy' of each defined template.
|
||||
*
|
||||
* @author brian@inteligr8.com
|
||||
*/
|
||||
public class ApsTemplateJsonNormalizer implements ApsFileNormalizer {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ApsTemplateJsonNormalizer.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 ApsTemplateJsonNormalizer(boolean enableSorting) {
|
||||
this.enableSorting = enableSorting;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void normalizeFile(File file, String _unused) throws IOException {
|
||||
this.logger.debug("Normalizing template JSON file: {}", file);
|
||||
|
||||
ObjectNode templateJson = (ObjectNode) ModelUtil.getInstance().readJson(file);
|
||||
boolean changed = this.transformModel(templateJson);
|
||||
|
||||
if (changed)
|
||||
ModelUtil.getInstance().writeJson(templateJson, file, this.enableSorting);
|
||||
}
|
||||
|
||||
private boolean transformModel(ObjectNode jsonModel) {
|
||||
this.logger.trace("Removing excess template meta-data: {}", jsonModel.get("name"));
|
||||
|
||||
int fields = jsonModel.size();
|
||||
jsonModel.remove(Arrays.asList("createdBy"));
|
||||
return jsonModel.size() < fields;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.inteligr8.maven.aps.modeling.normalizer;
|
||||
|
||||
import com.inteligr8.maven.aps.modeling.crawler.ApsFileTransformer;
|
||||
import com.inteligr8.maven.aps.modeling.crawler.ApsTemplateCrawlable;
|
||||
|
||||
/**
|
||||
* This class defines an APS template normalizer.
|
||||
*
|
||||
* @author brian@inteligr8.com
|
||||
*/
|
||||
public class ApsTemplateNormalizer implements ApsTemplateCrawlable {
|
||||
|
||||
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 template configurations to Git, you will
|
||||
* want to enable sorting.
|
||||
*
|
||||
* @param enableSorting true to re-order JSON objects; false to keep as-is.
|
||||
*/
|
||||
public ApsTemplateNormalizer(boolean enableSorting) {
|
||||
this.enableSorting = enableSorting;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApsFileTransformer getTemplateJsonTransformer() {
|
||||
return new ApsTemplateJsonNormalizer(this.enableSorting);
|
||||
}
|
||||
|
||||
}
|
@@ -26,10 +26,12 @@ import java.util.regex.Pattern;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.inteligr8.activiti.model.Datum;
|
||||
import com.inteligr8.activiti.model.ResultList;
|
||||
import com.inteligr8.alfresco.activiti.ApsPublicRestApi;
|
||||
import com.inteligr8.alfresco.activiti.api.ModelsApi.ModelType;
|
||||
import com.inteligr8.alfresco.activiti.model.Datum;
|
||||
import com.inteligr8.alfresco.activiti.model.GroupLight;
|
||||
import com.inteligr8.alfresco.activiti.model.ModelRepresentation;
|
||||
import com.inteligr8.alfresco.activiti.model.ResultListDataRepresentation;
|
||||
import com.inteligr8.alfresco.activiti.model.Tenant;
|
||||
import com.inteligr8.maven.aps.modeling.crawler.ApsAppCrawlable;
|
||||
@@ -196,17 +198,15 @@ public class ApsAppTranslator implements ApsAppCrawlable {
|
||||
return map;
|
||||
}
|
||||
|
||||
protected Index<Long, String> buildApsModelIndex(ModelType modelType) {
|
||||
ResultListDataRepresentation results = this.api.getModelsApi().get("everyone", null, modelType.getId(), null);
|
||||
protected Index<Long, String> buildApsModelIndex(ModelType modelType) {
|
||||
ResultList<ModelRepresentation> results = this.api.getModelsApi().get("everyone", null, modelType.getId(), null);
|
||||
this.logger.debug("APS {} models found: {} out of {}", modelType, results.getSize(), results.getTotal());
|
||||
|
||||
Index<Long, String> map = new Index<>(results.getSize().intValue(), false);
|
||||
|
||||
try {
|
||||
for (Datum datum : results.getData()) {
|
||||
Number defId = (Number)datum.getAdditionalProperties().get("id");
|
||||
String defName = (String)datum.getAdditionalProperties().get("name");
|
||||
map.put(defId.longValue(), defName);
|
||||
for (ModelRepresentation model : results.getData()) {
|
||||
map.put(model.getId(), model.getName());
|
||||
|
||||
// FIXME add paging support
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.inteligr8.maven.aps.modeling.translator;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
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 template JSON configuration file translator.
|
||||
*
|
||||
* @author brian@inteligr8.com
|
||||
*/
|
||||
public class ApsTemplateJsonTranslator implements ApsFileTranslator {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ApsTemplateJsonTranslator.class);
|
||||
private final Index<Long, String> apsDocumentTemplateIndex;
|
||||
private final Index<Long, String> apsCustomEmailTemplateIndex;
|
||||
|
||||
/**
|
||||
* This constructor initializes the default translator.
|
||||
*/
|
||||
public ApsTemplateJsonTranslator(
|
||||
Index<Long, String> apsDocumentTemplateIndex,
|
||||
Index<Long, String> apsCustomEmailTemplateIndex) {
|
||||
this.apsDocumentTemplateIndex = apsDocumentTemplateIndex;
|
||||
this.apsCustomEmailTemplateIndex = apsCustomEmailTemplateIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translateFile(File file, String _unsued1, Long _unused2) throws IOException {
|
||||
this.logger.debug("Translating JSON file: {}", file);
|
||||
|
||||
boolean changed = false;
|
||||
|
||||
ObjectNode json = (ObjectNode) ModelUtil.getInstance().readJson(file);
|
||||
|
||||
boolean isDocumentTemplate = json.get("mimeType") != null;
|
||||
String templateName = json.get("name").asText();
|
||||
this.logger.trace("Found template name '{}' in APS template file: {}", templateName, file);
|
||||
|
||||
Long oldTemplateId = null;
|
||||
if (json.hasNonNull("id")) {
|
||||
oldTemplateId = json.get("id").asLong();
|
||||
this.logger.trace("Found template ID '{}' in APS template file: {}", oldTemplateId, file);
|
||||
}
|
||||
|
||||
Long newTemplateId = null;
|
||||
if (isDocumentTemplate) {
|
||||
newTemplateId = this.apsDocumentTemplateIndex.getFirstKey(templateName);
|
||||
} else {
|
||||
newTemplateId = this.apsCustomEmailTemplateIndex.getFirstKey(templateName);
|
||||
}
|
||||
|
||||
if (newTemplateId == null) {
|
||||
// new template; remove the key completely
|
||||
json.remove("id");
|
||||
changed = true;
|
||||
} else if (newTemplateId.equals(oldTemplateId)) {
|
||||
// unchanged; nothing to do
|
||||
} else {
|
||||
json.put("id", newTemplateId);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
ModelUtil.getInstance().writeJson(json, file, false);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.inteligr8.maven.aps.modeling.translator;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.inteligr8.activiti.model.ResultList;
|
||||
import com.inteligr8.alfresco.activiti.ApsPublicRestApi;
|
||||
import com.inteligr8.alfresco.activiti.model.BaseTemplateLight;
|
||||
import com.inteligr8.alfresco.activiti.model.Tenant;
|
||||
import com.inteligr8.maven.aps.modeling.crawler.ApsFileTransformer;
|
||||
import com.inteligr8.maven.aps.modeling.crawler.ApsTemplateCrawlable;
|
||||
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 ApsTemplateTranslator implements ApsTemplateCrawlable {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ApsTemplateTranslator.class);
|
||||
private final ApsPublicRestApi api;
|
||||
|
||||
private boolean indexesBuilt = false;
|
||||
private Index<Long, String> apsDocumentTemplateIndex;
|
||||
private Index<Long, String> apsCustomEmailTemplateIndex;
|
||||
|
||||
public ApsTemplateTranslator(ApsPublicRestApi api) {
|
||||
this.api = api;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
this.logger.info("Building indexes ...");
|
||||
|
||||
long tenantId = this.findTenantId();
|
||||
this.logger.debug("APS tenant ID: {}", tenantId);
|
||||
|
||||
this.apsDocumentTemplateIndex = this.buildApsDocumentTemplateIndex(tenantId);
|
||||
this.logLarge("APS document templates: {}", this.apsDocumentTemplateIndex);
|
||||
|
||||
this.apsCustomEmailTemplateIndex = this.buildApsCustomEmailTemplateIndex(tenantId);
|
||||
this.logLarge("APS custom email templates: {}", this.apsCustomEmailTemplateIndex);
|
||||
|
||||
this.indexesBuilt = true;
|
||||
}
|
||||
|
||||
private <K, V> void logLarge(String message, Index<K, V> index) {
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace(message, index);
|
||||
} else {
|
||||
this.logger.debug(message, index.valueSet());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApsFileTransformer getTemplateJsonTransformer() {
|
||||
if (!this.indexesBuilt)
|
||||
throw new IllegalStateException("The indexes are never built");
|
||||
|
||||
return new ApsTemplateJsonTranslator(
|
||||
this.apsDocumentTemplateIndex,
|
||||
this.apsCustomEmailTemplateIndex);
|
||||
}
|
||||
|
||||
protected Long findTenantId() {
|
||||
List<Tenant> tenants = this.api.getAdminApi().getTenants();
|
||||
return (tenants == null || tenants.isEmpty()) ? null : tenants.iterator().next().getId();
|
||||
}
|
||||
|
||||
protected Index<Long, String> buildApsDocumentTemplateIndex(Long tenantId) {
|
||||
int perPage = 50;
|
||||
int page = 1;
|
||||
|
||||
ResultList<? extends BaseTemplateLight> templates = this.api.getTemplatesApi().getDocumentTemplates(null, (page-1)*perPage, perPage, "sort_by_name_asc", tenantId);
|
||||
Index<Long, String> index = new Index<>(templates.getTotal() / 2, false);
|
||||
|
||||
while (!templates.getData().isEmpty()) {
|
||||
this.logger.debug("APS document templates found: {}-{} out of {}", templates.getStart(), (templates.getStart() + templates.getSize()), templates.getTotal());
|
||||
|
||||
for (BaseTemplateLight template : templates.getData())
|
||||
index.put(template.getId(), template.getName());
|
||||
|
||||
page++;
|
||||
templates = this.api.getTemplatesApi().getDocumentTemplates(null, (page-1)*perPage, perPage, "sort_by_name_asc", tenantId);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
protected Index<Long, String> buildApsCustomEmailTemplateIndex(Long tenantId) {
|
||||
int perPage = 50;
|
||||
int page = 1;
|
||||
|
||||
ResultList<? extends BaseTemplateLight> templates = this.api.getTemplatesApi().getCustomEmailTemplates(null, (page-1)*perPage, perPage, "sort_by_name_asc", tenantId);
|
||||
Index<Long, String> index = new Index<>(templates.getTotal() / 2, false);
|
||||
|
||||
while (!templates.getData().isEmpty()) {
|
||||
this.logger.debug("APS document templates found: {}-{} out of {}", templates.getStart(), (templates.getStart() + templates.getSize()), templates.getTotal());
|
||||
|
||||
for (BaseTemplateLight template : templates.getData())
|
||||
index.put(template.getId(), template.getName());
|
||||
|
||||
page++;
|
||||
templates = this.api.getTemplatesApi().getCustomEmailTemplates(null, (page-1)*perPage, perPage, "sort_by_name_asc", tenantId);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
}
|
@@ -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));
|
||||
|
@@ -35,6 +35,8 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
* `allowDuplicateValues` to `false`.
|
||||
*
|
||||
* @author brian@inteligr8.com
|
||||
* @param <K> An index key type.
|
||||
* @param <V> An index value type.
|
||||
*/
|
||||
public class Index<K, V> {
|
||||
|
||||
|
@@ -28,6 +28,8 @@ import java.util.Map;
|
||||
* any sorted list.
|
||||
*
|
||||
* @author brian@inteligr8.com
|
||||
* @param <K> An map key type.
|
||||
* @param <V> An map value type.
|
||||
*/
|
||||
public class MapComparator<K, V> implements Comparator<Map<K, V>> {
|
||||
|
||||
|
@@ -52,6 +52,8 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.MapperFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import com.inteligr8.maven.aps.modeling.xml.DomNamespaceContext;
|
||||
|
||||
/**
|
||||
@@ -73,8 +75,8 @@ public class ModelUtil {
|
||||
|
||||
|
||||
|
||||
private final ObjectMapper om = new ObjectMapper();
|
||||
private final ObjectMapper omsorted = new ObjectMapper();
|
||||
private final ObjectMapper om = new ObjectMapper().registerModule(new JavaTimeModule());
|
||||
private final ObjectMapper omsorted = new ObjectMapper().registerModule(new JavaTimeModule());
|
||||
private final DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
|
||||
private final DocumentBuilder docBuilder;
|
||||
private final XPathFactory xpathfactory = XPathFactory.newInstance();
|
||||
@@ -296,6 +298,27 @@ public class ModelUtil {
|
||||
public Map<String, Object> readJsonAsMap(InputStream istream) throws IOException {
|
||||
return this.om.readValue(istream, Map.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method reads/parses a Java POJO.
|
||||
*
|
||||
* @param o A Java POJO.
|
||||
* @return A JSON node (array, object, or value).
|
||||
*/
|
||||
public ObjectNode readPojo(Object o) {
|
||||
return this.om.convertValue(o, ObjectNode.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method reads/parses a Java POJO.
|
||||
*
|
||||
* @param o A Java POJO.
|
||||
* @return A Java POJO as a map.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, Object> readPojoAsMap(Object o) {
|
||||
return this.om.convertValue(o, Map.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method formats/writes JSON to the specified file.
|
||||
@@ -384,6 +407,19 @@ public class ModelUtil {
|
||||
this.om.writeValue(ostream, map);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method formats/writes a Java POJO of the specified type using the
|
||||
* specified map.
|
||||
*
|
||||
* @param <T> The class of the type to create.
|
||||
* @param map A Java map.
|
||||
* @param type A Java class to create.
|
||||
* @return A Java POJO instance.
|
||||
*/
|
||||
public <T> T writePojo(Map<String, Object> map, Class<T> type) {
|
||||
return this.om.convertValue(map, type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user