Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
b75448335e | |||
3d174119d4 | |||
32d4e807a1 | |||
0c9dff2e23 | |||
a345739d2e | |||
0423a9e8ad | |||
cf051cac8a | |||
3a059d5ea9 | |||
496a90e04b | |||
21def1483b | |||
3d353cf6d5 | |||
0541cf502b | |||
89a43457f4 |
41
pom.xml
41
pom.xml
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
<groupId>com.inteligr8.alfresco</groupId>
|
<groupId>com.inteligr8.alfresco</groupId>
|
||||||
<artifactId>aps-model-maven-plugin</artifactId>
|
<artifactId>aps-model-maven-plugin</artifactId>
|
||||||
<version>1.0.0</version>
|
<version>1.2.0</version>
|
||||||
<packaging>maven-plugin</packaging>
|
<packaging>maven-plugin</packaging>
|
||||||
|
|
||||||
<name>A Maven plugin for Alfresco Process Services model portability</name>
|
<name>A Maven plugin for Alfresco Process Services model portability</name>
|
||||||
@@ -34,36 +34,27 @@
|
|||||||
<maven.compiler.target>1.8</maven.compiler.target>
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
<maven.version>3.6.3</maven.version>
|
<maven.version>3.6.3</maven.version>
|
||||||
|
|
||||||
<jersey.version>2.34</jersey.version>
|
<jersey.version>2.35</jersey.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.inteligr8.alfresco</groupId>
|
<groupId>com.inteligr8.alfresco</groupId>
|
||||||
<artifactId>aps-public-rest-api</artifactId>
|
<artifactId>aps-public-rest-api</artifactId>
|
||||||
<version>1.2.0</version>
|
<version>2.0.0</version>
|
||||||
<classifier>aps1</classifier>
|
<classifier>aps1</classifier>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.inteligr8.alfresco</groupId>
|
||||||
|
<artifactId>aps-public-rest-client</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
<classifier>jersey</classifier>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-lang3</artifactId>
|
<artifactId>commons-lang3</artifactId>
|
||||||
<version>3.4</version>
|
<version>3.4</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.glassfish.jersey.ext</groupId>
|
|
||||||
<artifactId>jersey-proxy-client</artifactId>
|
|
||||||
<version>${jersey.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.glassfish.jersey.core</groupId>
|
|
||||||
<artifactId>jersey-client</artifactId>
|
|
||||||
<version>${jersey.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.glassfish.jersey.media</groupId>
|
|
||||||
<artifactId>jersey-media-multipart</artifactId>
|
|
||||||
<version>${jersey.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.glassfish.jersey.inject</groupId>
|
<groupId>org.glassfish.jersey.inject</groupId>
|
||||||
<artifactId>jersey-hk2</artifactId>
|
<artifactId>jersey-hk2</artifactId>
|
||||||
@@ -161,8 +152,13 @@
|
|||||||
<localRepositoryPath>${project.build.directory}/it-repo</localRepositoryPath>
|
<localRepositoryPath>${project.build.directory}/it-repo</localRepositoryPath>
|
||||||
<mavenHome>${env.MAVEN_HOME}</mavenHome>
|
<mavenHome>${env.MAVEN_HOME}</mavenHome>
|
||||||
<debug>true</debug>
|
<debug>true</debug>
|
||||||
|
<skipInvocation>${skipTests}</skipInvocation>
|
||||||
<properties>
|
<properties>
|
||||||
<project.main.basedir>${basedir}</project.main.basedir>
|
<project.main.basedir>${basedir}</project.main.basedir>
|
||||||
|
<aps-model.baseUrl>${aps-model.baseUrl}</aps-model.baseUrl>
|
||||||
|
<aps-model.authType>${aps-model.authType}</aps-model.authType>
|
||||||
|
<aps-model.basicAuth.mavenServerId>${aps-model.basicAuth.mavenServerId}</aps-model.basicAuth.mavenServerId>
|
||||||
|
<aps-model.appName>${aps-model.appName}</aps-model.appName>
|
||||||
</properties>
|
</properties>
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
@@ -184,6 +180,7 @@
|
|||||||
<goals><goal>jar</goal></goals>
|
<goals><goal>jar</goal></goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<show>public</show>
|
<show>public</show>
|
||||||
|
<skip>true</skip>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
@@ -223,6 +220,14 @@
|
|||||||
</build>
|
</build>
|
||||||
</profile>
|
</profile>
|
||||||
</profiles>
|
</profiles>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>inteligr8-releases</id>
|
||||||
|
<name>Inteligr8 Releases</name>
|
||||||
|
<url>https://repos.inteligr8.com/nexus/repository/inteligr8-public</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
<distributionManagement>
|
<distributionManagement>
|
||||||
<repository>
|
<repository>
|
||||||
|
@@ -12,10 +12,6 @@
|
|||||||
|
|
||||||
<name>Deploy App Plugin Tests</name>
|
<name>Deploy App Plugin Tests</name>
|
||||||
|
|
||||||
<properties>
|
|
||||||
<aps.app>FORMS Core</aps.app>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
@@ -24,14 +20,46 @@
|
|||||||
<version>@pom.version@</version>
|
<version>@pom.version@</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>download-app</id>
|
<id>download-unpack-app</id>
|
||||||
<phase>validate</phase>
|
<phase>generate-sources</phase>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>download-app</goal>
|
<goal>download-app</goal>
|
||||||
|
<goal>unpack-app</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<reformat>true</reformat>
|
||||||
|
<normalize>true</normalize>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>translate-app</id>
|
||||||
|
<phase>compile</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>translate-app</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<finalDirectory>${project.build.directory}/aps-dev</finalDirectory>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>pack-app</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>pack-app</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<unzipDirectory>${project.build.directory}/aps-dev</unzipDirectory>
|
||||||
|
<zipDirectory>${project.build.directory}/aps-test</zipDirectory>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>deploy-app</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
<goal>deploy-app</goal>
|
<goal>deploy-app</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<apsAppName>${aps.app}</apsAppName>
|
<zipDirectory>${project.build.directory}/aps-test</zipDirectory>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
|
@@ -12,10 +12,6 @@
|
|||||||
|
|
||||||
<name>Download App Plugin Tests</name>
|
<name>Download App Plugin Tests</name>
|
||||||
|
|
||||||
<properties>
|
|
||||||
<aps.app>FORMS Core</aps.app>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
@@ -25,23 +21,19 @@
|
|||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>download-app</id>
|
<id>download-app</id>
|
||||||
<phase>validate</phase>
|
<phase>generate-sources</phase>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>download-app</goal>
|
<goal>download-app</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
|
||||||
<apsAppName>${aps.app}</apsAppName>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
</execution>
|
||||||
<execution>
|
<execution>
|
||||||
<id>download-app-other</id>
|
<id>download-app-other</id>
|
||||||
<phase>validate</phase>
|
<phase>generate-sources</phase>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>download-app</goal>
|
<goal>download-app</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<apsAppName>${aps.app}</apsAppName>
|
<zipDirectory>${basedir}/src/main/aps</zipDirectory>
|
||||||
<targetDirectory>${basedir}/src/main/app</targetDirectory>
|
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
@@ -57,8 +49,8 @@
|
|||||||
<rules>
|
<rules>
|
||||||
<requireFilesExist>
|
<requireFilesExist>
|
||||||
<files>
|
<files>
|
||||||
<file>${project.build.directory}/app/${aps.app}.zip</file>
|
<file>${project.build.directory}/aps/${aps-model.appName}.zip</file>
|
||||||
<file>${basedir}/src/main/app/${aps.app}.zip</file>
|
<file>${basedir}/src/main/aps/${aps-model.appName}.zip</file>
|
||||||
</files>
|
</files>
|
||||||
</requireFilesExist>
|
</requireFilesExist>
|
||||||
</rules>
|
</rules>
|
||||||
|
@@ -12,10 +12,6 @@
|
|||||||
|
|
||||||
<name>Pack App Plugin Tests</name>
|
<name>Pack App Plugin Tests</name>
|
||||||
|
|
||||||
<properties>
|
|
||||||
<aps.app>FORMS Core</aps.app>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
@@ -25,24 +21,23 @@
|
|||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>download-unpack-app</id>
|
<id>download-unpack-app</id>
|
||||||
<phase>validate</phase>
|
<phase>generate-sources</phase>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>download-app</goal>
|
<goal>download-app</goal>
|
||||||
<goal>unpack-app</goal>
|
<goal>unpack-app</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<apsAppName>${aps.app}</apsAppName>
|
<normalize>true</normalize>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
<execution>
|
<execution>
|
||||||
<id>pack-app</id>
|
<id>pack-app</id>
|
||||||
<phase>validate</phase>
|
<phase>package</phase>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>pack-app</goal>
|
<goal>pack-app</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<apsAppName>${aps.app}</apsAppName>
|
<zipDirectory>${basedir}</zipDirectory>
|
||||||
<targetDirectory>${basedir}/src/main/app</targetDirectory>
|
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
@@ -58,7 +53,7 @@
|
|||||||
<rules>
|
<rules>
|
||||||
<requireFilesExist>
|
<requireFilesExist>
|
||||||
<files>
|
<files>
|
||||||
<file>${basedir}/src/main/app/${aps.app}.zip</file>
|
<file>${basedir}/${aps-model.appName}.zip</file>
|
||||||
</files>
|
</files>
|
||||||
</requireFilesExist>
|
</requireFilesExist>
|
||||||
</rules>
|
</rules>
|
||||||
|
@@ -12,10 +12,6 @@
|
|||||||
|
|
||||||
<name>Translate App Plugin Tests</name>
|
<name>Translate App Plugin Tests</name>
|
||||||
|
|
||||||
<properties>
|
|
||||||
<aps.app>FORMS Core</aps.app>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
@@ -25,24 +21,24 @@
|
|||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>download-unpack-app</id>
|
<id>download-unpack-app</id>
|
||||||
<phase>validate</phase>
|
<phase>generate-sources</phase>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>download-app</goal>
|
<goal>download-app</goal>
|
||||||
<goal>unpack-app</goal>
|
<goal>unpack-app</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<apsAppName>${aps.app}</apsAppName>
|
<normalize>true</normalize>
|
||||||
|
<diffFriendly>true</diffFriendly>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
<execution>
|
<execution>
|
||||||
<id>translate-app</id>
|
<id>translate-app</id>
|
||||||
<phase>validate</phase>
|
<phase>compile</phase>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>translate-app</goal>
|
<goal>translate-app</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<apsAppName>${aps.app}</apsAppName>
|
<finalDirectory>${basedir}/src/main/aps/app</finalDirectory>
|
||||||
<targetDirectory>${basedir}/src/main/app</targetDirectory>
|
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
@@ -58,7 +54,7 @@
|
|||||||
<rules>
|
<rules>
|
||||||
<requireFilesExist>
|
<requireFilesExist>
|
||||||
<files>
|
<files>
|
||||||
<file>${basedir}/src/main/app/${aps.app}/${aps.app}.json</file>
|
<file>${basedir}/src/main/aps/app/${aps-model.appName}/${aps-model.appName}.json</file>
|
||||||
</files>
|
</files>
|
||||||
</requireFilesExist>
|
</requireFilesExist>
|
||||||
</rules>
|
</rules>
|
||||||
|
@@ -12,10 +12,6 @@
|
|||||||
|
|
||||||
<name>Unpack App Plugin Tests</name>
|
<name>Unpack App Plugin Tests</name>
|
||||||
|
|
||||||
<properties>
|
|
||||||
<aps.app>FORMS Core</aps.app>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
@@ -25,24 +21,20 @@
|
|||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>download-unpack-app</id>
|
<id>download-unpack-app</id>
|
||||||
<phase>validate</phase>
|
<phase>generate-sources</phase>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>download-app</goal>
|
<goal>download-app</goal>
|
||||||
<goal>unpack-app</goal>
|
<goal>unpack-app</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
|
||||||
<apsAppName>${aps.app}</apsAppName>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
</execution>
|
||||||
<execution>
|
<execution>
|
||||||
<id>unpack-app</id>
|
<id>unpack-app</id>
|
||||||
<phase>validate</phase>
|
<phase>process-sources</phase>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>unpack-app</goal>
|
<goal>unpack-app</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<apsAppName>${aps.app}</apsAppName>
|
<unzipDirectory>${basedir}/src/main/aps/app</unzipDirectory>
|
||||||
<targetDirectory>${basedir}/src/main/app</targetDirectory>
|
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
@@ -58,8 +50,8 @@
|
|||||||
<rules>
|
<rules>
|
||||||
<requireFilesExist>
|
<requireFilesExist>
|
||||||
<files>
|
<files>
|
||||||
<file>${project.build.directory}/app/${aps.app}/${aps.app}.json</file>
|
<file>${project.build.directory}/aps/app/${aps-model.appName}/${aps-model.appName}.json</file>
|
||||||
<file>${basedir}/src/main/app/${aps.app}/${aps.app}.json</file>
|
<file>${basedir}/src/main/aps/app/${aps-model.appName}/${aps-model.appName}.json</file>
|
||||||
</files>
|
</files>
|
||||||
</requireFilesExist>
|
</requireFilesExist>
|
||||||
</rules>
|
</rules>
|
||||||
|
@@ -1,83 +0,0 @@
|
|||||||
package com.inteligr8.maven.aps.modeling;
|
|
||||||
|
|
||||||
import org.apache.maven.plugin.AbstractMojo;
|
|
||||||
import org.apache.maven.plugins.annotations.Parameter;
|
|
||||||
|
|
||||||
import com.inteligr8.alfresco.activiti.ApsClientConfiguration;
|
|
||||||
import com.inteligr8.alfresco.activiti.ApsClientJerseyImpl;
|
|
||||||
import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl;
|
|
||||||
|
|
||||||
public abstract class ApsAddressibleGoal extends AbstractMojo {
|
|
||||||
|
|
||||||
@Parameter( property = "activitiAppBaseUrl", required = true, defaultValue = "http://localhost:8080/activiti-app" )
|
|
||||||
protected String activitiAppBaseUrl;
|
|
||||||
|
|
||||||
@Parameter( property = "activitiAppAuth", required = true, defaultValue = "BASIC" )
|
|
||||||
protected String activitiAppAuthType;
|
|
||||||
|
|
||||||
@Parameter( property = "activitiAppBasicUsername", required = false, defaultValue = "admin" )
|
|
||||||
protected String activitiAppAuthBasicUsername;
|
|
||||||
|
|
||||||
@Parameter( property = "activitiAppBasicPassword", required = false, defaultValue = "admin" )
|
|
||||||
protected String activitiAppAuthBasicPassword;
|
|
||||||
|
|
||||||
@Parameter( property = "oAuthCode", required = false )
|
|
||||||
protected String oauthCode;
|
|
||||||
|
|
||||||
@Parameter( property = "oAuthClientId", required = false )
|
|
||||||
protected String oauthClientId;
|
|
||||||
|
|
||||||
@Parameter( property = "oAuthClientSecret", required = false )
|
|
||||||
protected String oauthClientSecret;
|
|
||||||
|
|
||||||
@Parameter( property = "oAuthUsername", required = false )
|
|
||||||
protected String oauthUsername;
|
|
||||||
|
|
||||||
@Parameter( property = "oAuthPassword", required = false )
|
|
||||||
protected String oauthPassword;
|
|
||||||
|
|
||||||
@Parameter( property = "oAuthTokenUrl", required = false )
|
|
||||||
protected String oauthTokenUrl;
|
|
||||||
|
|
||||||
private ApsPublicRestApiJerseyImpl api;
|
|
||||||
|
|
||||||
public ApsClientConfiguration getApsClientConfiguration() {
|
|
||||||
ApsClientConfiguration config = new ApsClientConfiguration();
|
|
||||||
config.setBaseUrl(this.activitiAppBaseUrl);
|
|
||||||
switch (this.activitiAppAuthType.toUpperCase()) {
|
|
||||||
case "BASIC":
|
|
||||||
this.getLog().info("Configuring APS with BASIC authentication");
|
|
||||||
this.getLog().debug("Username: " + this.activitiAppAuthBasicUsername);
|
|
||||||
config.setBasicAuthUsername(this.activitiAppAuthBasicUsername);
|
|
||||||
config.setBasicAuthPassword(this.activitiAppAuthBasicPassword);
|
|
||||||
break;
|
|
||||||
case "OAUTH":
|
|
||||||
this.getLog().info("Configuring APS with OAuth authentication");
|
|
||||||
this.getLog().debug("OAuth Code: " + this.oauthCode);
|
|
||||||
this.getLog().debug("OAuth Client ID: " + this.oauthClientId);
|
|
||||||
this.getLog().debug("OAuth Username: " + this.oauthUsername);
|
|
||||||
config.setOAuthAuthCode(this.oauthCode);
|
|
||||||
config.setOAuthTokenUrl(this.oauthTokenUrl);
|
|
||||||
config.setOAuthClientId(this.oauthClientId);
|
|
||||||
config.setOAuthClientSecret(this.oauthClientSecret);
|
|
||||||
config.setOAuthUsername(this.oauthUsername);
|
|
||||||
config.setOAuthPassword(this.oauthPassword);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("The 'activitiAppAuth' configuration must be either 'Basic' or 'OAuth'");
|
|
||||||
}
|
|
||||||
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized ApsPublicRestApiJerseyImpl getApsApi() {
|
|
||||||
if (this.api == null) {
|
|
||||||
ApsClientConfiguration config = this.getApsClientConfiguration();
|
|
||||||
ApsClientJerseyImpl apsClient = new ApsClientJerseyImpl(config);
|
|
||||||
this.api = new ApsPublicRestApiJerseyImpl(apsClient);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.api;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,38 +0,0 @@
|
|||||||
package com.inteligr8.maven.aps.modeling;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl;
|
|
||||||
import com.inteligr8.alfresco.activiti.api.ModelsApi.ModelType;
|
|
||||||
import com.inteligr8.alfresco.activiti.model.Datum;
|
|
||||||
import com.inteligr8.alfresco.activiti.model.ResultListDataRepresentation;
|
|
||||||
import com.inteligr8.alfresco.activiti.model.Tenant;
|
|
||||||
|
|
||||||
public abstract class ApsAppAccessibleGoal extends ApsAddressibleGoal {
|
|
||||||
|
|
||||||
protected Long findTenantId() {
|
|
||||||
List<Tenant> tenants = this.getApsApi().getAdminApi().getTenants();
|
|
||||||
if (tenants == null || tenants.isEmpty())
|
|
||||||
return null;
|
|
||||||
return tenants.iterator().next().getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Long findAppByName(String appName) {
|
|
||||||
ApsPublicRestApiJerseyImpl api = this.getApsApi();
|
|
||||||
|
|
||||||
this.getLog().debug("Searching for APS App with name: " + appName);
|
|
||||||
ResultListDataRepresentation results = api.getModelsApi().get(null, null, ModelType.App.getId(), null);
|
|
||||||
this.getLog().debug("Found " + results.getTotal() + " APS Apps");
|
|
||||||
for (Datum datum : results.getData()) {
|
|
||||||
String name = (String)datum.getAdditionalProperties().get("name");
|
|
||||||
if (name.equals(appName)) {
|
|
||||||
Number id = (Number)datum.getAdditionalProperties().get("id");
|
|
||||||
this.getLog().info("Found APS App ID: " + id);
|
|
||||||
return id == null ? null : id.longValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,10 +0,0 @@
|
|||||||
package com.inteligr8.maven.aps.modeling;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public interface ApsFileTranslator {
|
|
||||||
|
|
||||||
void translateFile(File file, String modelName, Long modelId) throws IOException;
|
|
||||||
|
|
||||||
}
|
|
@@ -1,31 +0,0 @@
|
|||||||
package com.inteligr8.maven.aps.modeling;
|
|
||||||
|
|
||||||
import org.w3c.dom.CDATASection;
|
|
||||||
import org.w3c.dom.Node;
|
|
||||||
|
|
||||||
public class CDATAFlexSection {
|
|
||||||
|
|
||||||
private final Node node;
|
|
||||||
|
|
||||||
public CDATAFlexSection(Node node) {
|
|
||||||
this.node = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getValue() {
|
|
||||||
if (this.node instanceof CDATASection) {
|
|
||||||
return ((CDATASection)this.node).getData();
|
|
||||||
} else {
|
|
||||||
String value = this.node.getTextContent();
|
|
||||||
return value == null ? null : this.node.getTextContent().trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValue(String value) {
|
|
||||||
if (this.node instanceof CDATASection) {
|
|
||||||
((CDATASection)this.node).setData(value);
|
|
||||||
} else {
|
|
||||||
this.node.setTextContent(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,99 +0,0 @@
|
|||||||
package com.inteligr8.maven.aps.modeling;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
|
||||||
import org.apache.maven.execution.MavenSession;
|
|
||||||
import org.apache.maven.plugin.MojoExecutionException;
|
|
||||||
import org.apache.maven.plugin.MojoFailureException;
|
|
||||||
import org.apache.maven.plugins.annotations.Mojo;
|
|
||||||
import org.apache.maven.plugins.annotations.Parameter;
|
|
||||||
import org.apache.maven.project.MavenProject;
|
|
||||||
import org.codehaus.plexus.component.annotations.Component;
|
|
||||||
|
|
||||||
@Mojo( name = "translate-app", threadSafe = true )
|
|
||||||
@Component( role = org.apache.maven.plugin.Mojo.class )
|
|
||||||
public class TranslateAppGoal extends ApsAppAccessibleGoal {
|
|
||||||
|
|
||||||
@Parameter( defaultValue = "${project}", readonly = true )
|
|
||||||
protected MavenProject project;
|
|
||||||
|
|
||||||
@Parameter( defaultValue = "${session}", readonly = true )
|
|
||||||
protected MavenSession session;
|
|
||||||
|
|
||||||
@Parameter( property = "apsAppName", required = true )
|
|
||||||
protected String apsAppName;
|
|
||||||
|
|
||||||
@Parameter( property = "sourceDirectory", required = true, defaultValue = "${project.build.directory}/app" )
|
|
||||||
protected File sourceDirectory;
|
|
||||||
|
|
||||||
@Parameter( property = "targetDirectory", required = false, defaultValue = "${project.build.directory}/app" )
|
|
||||||
protected File targetDirectory;
|
|
||||||
|
|
||||||
@Parameter( property = "overwrite", required = true, defaultValue = "true" )
|
|
||||||
protected boolean overwrite = true;
|
|
||||||
|
|
||||||
@Parameter( property = "charset", required = true, defaultValue = "utf-8" )
|
|
||||||
protected String charsetName = "utf-8";
|
|
||||||
|
|
||||||
@Parameter( property = "skip", required = true, defaultValue = "false" )
|
|
||||||
protected boolean skip = false;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
|
||||||
File apsAppDirectory = this.validateApsAppDirectory();
|
|
||||||
File newApsAppDirectory = this.validateTargetDirectory();
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (!apsAppDirectory.equals(newApsAppDirectory)) {
|
|
||||||
FileUtils.copyDirectory(apsAppDirectory, newApsAppDirectory);
|
|
||||||
apsAppDirectory = newApsAppDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
ApsAppTranslator translator = new ApsAppTranslator(this.apsAppName, apsAppDirectory, this.getApsApi(), true);
|
|
||||||
translator.execute();
|
|
||||||
} catch (IOException ie) {
|
|
||||||
throw new MojoExecutionException("An I/O issue occurred", ie);
|
|
||||||
} catch (IllegalArgumentException iae) {
|
|
||||||
throw new MojoExecutionException("The input is not supported", iae);
|
|
||||||
} catch (IllegalStateException ise) {
|
|
||||||
throw new MojoExecutionException("The state of system is not supported", ise);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected File validateApsAppDirectory() throws MojoExecutionException {
|
|
||||||
if (!this.sourceDirectory.exists())
|
|
||||||
throw new MojoExecutionException("The 'sourceDirectory' does not exist: " + this.sourceDirectory);
|
|
||||||
if (!this.sourceDirectory.isDirectory())
|
|
||||||
throw new MojoExecutionException("The 'sourceDirectory' is not a directory: " + this.sourceDirectory);
|
|
||||||
|
|
||||||
File appDirectory = new File(this.sourceDirectory, this.apsAppName);
|
|
||||||
|
|
||||||
if (!appDirectory.exists())
|
|
||||||
throw new MojoExecutionException("The 'apsAppName' does not exist in the 'apsAppsDirectory': " + appDirectory);
|
|
||||||
if (!appDirectory.isDirectory())
|
|
||||||
throw new MojoExecutionException("The 'apsAppName' is not a directory in the 'apsAppsDirectory': " + appDirectory);
|
|
||||||
|
|
||||||
return appDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected File validateTargetDirectory() throws MojoExecutionException {
|
|
||||||
if (!this.targetDirectory.exists()) {
|
|
||||||
this.targetDirectory.mkdirs();
|
|
||||||
} else if (!this.targetDirectory.isDirectory()) {
|
|
||||||
throw new MojoExecutionException("The 'targetDirectory' is not a directory: " + this.targetDirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
File appDirectory = new File(this.targetDirectory, this.apsAppName);
|
|
||||||
|
|
||||||
if (!appDirectory.exists()) {
|
|
||||||
appDirectory.mkdirs();
|
|
||||||
} else if (!appDirectory.isDirectory()) {
|
|
||||||
throw new MojoExecutionException("The 'apsAppName' is not a directory in the 'targetDirectory': " + appDirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
return appDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -0,0 +1,13 @@
|
|||||||
|
package com.inteligr8.maven.aps.modeling.crawler;
|
||||||
|
|
||||||
|
public interface ApsAppCrawlable {
|
||||||
|
|
||||||
|
ApsFileTransformer getAppJsonTransformer();
|
||||||
|
|
||||||
|
ApsFileTransformer getProcessJsonTransformer();
|
||||||
|
|
||||||
|
ApsFileTransformer getProcessBpmnTransformer();
|
||||||
|
|
||||||
|
ApsFileTransformer getFormJsonTransformer();
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,105 @@
|
|||||||
|
package com.inteligr8.maven.aps.modeling.crawler;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class ApsAppCrawler {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(ApsAppCrawler.class);
|
||||||
|
private final Pattern filenamePattern = Pattern.compile("([^/]+)-([0-9]+)\\.(json|bpmn20\\.xml)");
|
||||||
|
private final String appName;
|
||||||
|
private final File appDirectory;
|
||||||
|
private final File appDescriptor;
|
||||||
|
private final boolean failOnIntegrityViolation;
|
||||||
|
|
||||||
|
public ApsAppCrawler(String apsAppName, File apsAppDirectory, boolean failOnIntegrityViolation) {
|
||||||
|
this.appName = apsAppName;
|
||||||
|
this.appDirectory = apsAppDirectory;
|
||||||
|
this.failOnIntegrityViolation = failOnIntegrityViolation;
|
||||||
|
|
||||||
|
this.appDescriptor = this.validateDescriptor(appDirectory);
|
||||||
|
if (this.logger.isDebugEnabled())
|
||||||
|
this.logger.debug("APS App descriptor found: " + this.appDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected File validateDescriptor(File appDirectory) {
|
||||||
|
File appDescriptor = new File(appDirectory, this.appName + ".json");
|
||||||
|
|
||||||
|
if (!appDescriptor.exists())
|
||||||
|
throw new IllegalStateException("The APS App descriptor could not be found: " + appDescriptor);
|
||||||
|
if (!appDescriptor.isFile())
|
||||||
|
throw new IllegalStateException("The APS App descriptor is not a file: " + appDescriptor);
|
||||||
|
|
||||||
|
return appDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void execute(ApsAppCrawlable crawlable) throws IOException {
|
||||||
|
this.logger.info("Crawling APS App ...");
|
||||||
|
|
||||||
|
Map<String, ApsFileTransformer> processTransformers = new HashMap<>();
|
||||||
|
processTransformers.put("json", crawlable.getProcessJsonTransformer());
|
||||||
|
processTransformers.put("bpmn20.xml", crawlable.getProcessBpmnTransformer());
|
||||||
|
processTransformers.put("bpmn", crawlable.getProcessBpmnTransformer());
|
||||||
|
|
||||||
|
this.transform(crawlable.getAppJsonTransformer(), this.appDescriptor, this.appName, null);
|
||||||
|
this.crawlModels("form-models", crawlable.getFormJsonTransformer());
|
||||||
|
this.crawlModels("bpmn-models", processTransformers);
|
||||||
|
this.crawlModels("bpmn-subprocess-models", crawlable.getProcessJsonTransformer());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void crawlModels(String modelsDirectoryName, ApsFileTransformer transformer) throws IOException {
|
||||||
|
this.crawlModels(modelsDirectoryName, Collections.singletonMap("json", transformer));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void crawlModels(String modelsDirectoryName, Map<String, ApsFileTransformer> transformers) throws IOException {
|
||||||
|
File modelsDirectory = new File(this.appDirectory, modelsDirectoryName);
|
||||||
|
if (!modelsDirectory.exists()) {
|
||||||
|
this.logger.debug("APS model directory doesn't exist; no models to transform: {}", modelsDirectory);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (File modelFile : modelsDirectory.listFiles()) {
|
||||||
|
this.logger.trace("Transforming model: {}", modelFile);
|
||||||
|
|
||||||
|
Matcher matcher = this.filenamePattern.matcher(modelFile.getName());
|
||||||
|
if (!matcher.find()) {
|
||||||
|
this.logger.warn("The '{}' folder has a file with an unexpected filename format; skipping: {}", modelsDirectoryName, modelFile);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String ext = matcher.group(3);
|
||||||
|
ApsFileTransformer transformer = transformers.get(ext.toLowerCase());
|
||||||
|
if (transformer == null) {
|
||||||
|
this.logger.warn("The '{}' folder has a file with an unexpected extension; skipping: {}", modelsDirectoryName, modelFile);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String modelName = matcher.group(1);
|
||||||
|
Long modelId = new Long(matcher.group(2));
|
||||||
|
this.logger.trace("Transforming model {} ID: {}", modelName, modelId);
|
||||||
|
|
||||||
|
this.transform(transformer, modelFile, modelName, modelId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void transform(ApsFileTransformer transformer, File modelFile, String modelName, Long modelId) throws IOException {
|
||||||
|
try {
|
||||||
|
transformer.transformFile(modelFile, modelName, modelId);
|
||||||
|
} catch (IllegalArgumentException | IllegalStateException ie) {
|
||||||
|
if (this.failOnIntegrityViolation) {
|
||||||
|
throw ie;
|
||||||
|
} else {
|
||||||
|
this.logger.warn(ie.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,10 @@
|
|||||||
|
package com.inteligr8.maven.aps.modeling.crawler;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public interface ApsFileTransformer {
|
||||||
|
|
||||||
|
void transformFile(File file, String modelName, Long modelId) throws IOException;
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,99 @@
|
|||||||
|
package com.inteligr8.maven.aps.modeling.goal;
|
||||||
|
|
||||||
|
import org.apache.maven.execution.MavenSession;
|
||||||
|
import org.apache.maven.plugins.annotations.Parameter;
|
||||||
|
import org.apache.maven.settings.Server;
|
||||||
|
|
||||||
|
import com.inteligr8.alfresco.activiti.ApsClientJerseyConfiguration;
|
||||||
|
import com.inteligr8.alfresco.activiti.ApsClientJerseyImpl;
|
||||||
|
import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl;
|
||||||
|
|
||||||
|
public abstract class ApsAddressibleGoal extends DisablableGoal {
|
||||||
|
|
||||||
|
@Parameter( defaultValue = "${session}", readonly = true )
|
||||||
|
protected MavenSession session;
|
||||||
|
|
||||||
|
@Parameter( property = "aps-model.baseUrl", required = true, defaultValue = "http://localhost:8080/activiti-app" )
|
||||||
|
protected String activitiAppBaseUrl;
|
||||||
|
|
||||||
|
@Parameter( property = "aps-model.authType", required = true, defaultValue = "BASIC" )
|
||||||
|
protected String activitiAppAuthType;
|
||||||
|
|
||||||
|
@Parameter( property = "aps-model.basicAuth.mavenServerId", required = true, defaultValue = "aps" )
|
||||||
|
protected String activitiAppAuthBasicServerId;
|
||||||
|
|
||||||
|
@Parameter( property = "aps-model.oauth.code", required = false )
|
||||||
|
protected String oauthCode;
|
||||||
|
|
||||||
|
@Parameter( property = "aps-model.oauth.client.mavenServerId", required = false )
|
||||||
|
protected String oauthClientServerId;
|
||||||
|
|
||||||
|
@Parameter( property = "aps-model.oauth.mavenServerId", required = false )
|
||||||
|
protected String oauthServerId;
|
||||||
|
|
||||||
|
@Parameter( property = "aps-model.oauth.tokenUrl", required = false )
|
||||||
|
protected String oauthTokenUrl;
|
||||||
|
|
||||||
|
private ApsPublicRestApiJerseyImpl api;
|
||||||
|
|
||||||
|
public ApsClientJerseyConfiguration getApsClientConfiguration() {
|
||||||
|
this.getLog().debug("Configuring APS to URL: " + this.activitiAppBaseUrl);
|
||||||
|
ApsClientJerseyConfiguration config = new ApsClientJerseyConfiguration();
|
||||||
|
config.setBaseUrl(this.activitiAppBaseUrl);
|
||||||
|
switch (this.activitiAppAuthType.toUpperCase()) {
|
||||||
|
case "BASIC":
|
||||||
|
this.getLog().info("Configuring APS with BASIC authentication");
|
||||||
|
|
||||||
|
Server creds = this.session.getSettings().getServer(this.activitiAppAuthBasicServerId);
|
||||||
|
if (this.activitiAppAuthBasicServerId != null && creds == null)
|
||||||
|
this.getLog().warn("The Maven configuration has no server '" + this.activitiAppAuthBasicServerId + "'; continuing with default credentials");
|
||||||
|
|
||||||
|
if (creds != null) {
|
||||||
|
this.getLog().debug("Username: " + creds.getUsername());
|
||||||
|
config.setBasicAuthUsername(creds.getUsername());
|
||||||
|
config.setBasicAuthPassword(creds.getPassword());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "OAUTH":
|
||||||
|
this.getLog().info("Configuring APS with OAuth authentication");
|
||||||
|
|
||||||
|
Server clientCreds = this.session.getSettings().getServer(this.oauthClientServerId);
|
||||||
|
Server oauthCreds = this.session.getSettings().getServer(this.oauthServerId);
|
||||||
|
if ((this.oauthClientServerId != null || this.oauthServerId != null) && clientCreds == null && oauthCreds == null)
|
||||||
|
this.getLog().warn("The Maven configuration has no server '" + this.oauthClientServerId + "' or '" + this.oauthServerId + "'; continuing without credentials");
|
||||||
|
|
||||||
|
this.getLog().debug("OAuth Code: " + this.oauthCode);
|
||||||
|
config.setOAuthAuthCode(this.oauthCode);
|
||||||
|
|
||||||
|
if (clientCreds != null) {
|
||||||
|
this.getLog().debug("OAuth Client ID: " + clientCreds.getUsername());
|
||||||
|
config.setOAuthClientId(clientCreds.getUsername());
|
||||||
|
config.setOAuthClientSecret(clientCreds.getPassword());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oauthCreds != null) {
|
||||||
|
this.getLog().debug("OAuth Username: " + oauthCreds.getUsername());
|
||||||
|
config.setOAuthUsername(oauthCreds.getUsername());
|
||||||
|
config.setOAuthPassword(oauthCreds.getPassword());
|
||||||
|
}
|
||||||
|
|
||||||
|
config.setOAuthTokenUrl(this.oauthTokenUrl);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("The 'activitiAppAuthType' configuration must be either 'Basic' or 'OAuth'");
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized ApsPublicRestApiJerseyImpl getApsApi() {
|
||||||
|
if (this.api == null) {
|
||||||
|
ApsClientJerseyConfiguration config = this.getApsClientConfiguration();
|
||||||
|
ApsClientJerseyImpl apsClient = new ApsClientJerseyImpl(config);
|
||||||
|
this.api = new ApsPublicRestApiJerseyImpl(apsClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.api;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,57 @@
|
|||||||
|
package com.inteligr8.maven.aps.modeling.goal;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.maven.plugin.MojoExecutionException;
|
||||||
|
import org.apache.maven.plugins.annotations.Parameter;
|
||||||
|
|
||||||
|
import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl;
|
||||||
|
import com.inteligr8.alfresco.activiti.api.ModelsApi.ModelType;
|
||||||
|
import com.inteligr8.alfresco.activiti.model.Datum;
|
||||||
|
import com.inteligr8.alfresco.activiti.model.ResultListDataRepresentation;
|
||||||
|
import com.inteligr8.alfresco.activiti.model.Tenant;
|
||||||
|
|
||||||
|
public abstract class ApsAppAccessibleGoal extends ApsAddressibleGoal {
|
||||||
|
|
||||||
|
@Parameter( property = "aps-model.appName", required = true )
|
||||||
|
protected String apsAppName;
|
||||||
|
|
||||||
|
protected Long findTenantId() {
|
||||||
|
List<Tenant> tenants = this.getApsApi().getAdminApi().getTenants();
|
||||||
|
if (tenants == null || tenants.isEmpty())
|
||||||
|
return null;
|
||||||
|
return tenants.iterator().next().getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Map<String, Long> findAppNameIds() {
|
||||||
|
ApsPublicRestApiJerseyImpl api = this.getApsApi();
|
||||||
|
|
||||||
|
Map<String, Long> apps = new HashMap<>(16);
|
||||||
|
|
||||||
|
this.getLog().debug("Searching for all APS Apps");
|
||||||
|
ResultListDataRepresentation results = api.getModelsApi().get("everyone", null, ModelType.App.getId(), null);
|
||||||
|
this.getLog().debug("Found " + results.getTotal() + " APS Apps");
|
||||||
|
for (Datum datum : results.getData()) {
|
||||||
|
String name = (String)datum.getAdditionalProperties().get("name");
|
||||||
|
Number id = (Number)datum.getAdditionalProperties().get("id");
|
||||||
|
apps.put(name, id.longValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
return apps;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Long findAppId() throws MojoExecutionException {
|
||||||
|
return this.findAppIdByName(this.apsAppName);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Long findAppIdByName(String appName) throws MojoExecutionException {
|
||||||
|
Map<String, Long> apps = this.findAppNameIds();
|
||||||
|
Long appId = apps.get(this.apsAppName);
|
||||||
|
if (appId == null)
|
||||||
|
throw new MojoExecutionException("The APS App '' could not be found; valid apps: " + apps.keySet());
|
||||||
|
return appId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,10 @@
|
|||||||
|
package com.inteligr8.maven.aps.modeling.goal;
|
||||||
|
|
||||||
|
import org.apache.maven.plugins.annotations.Parameter;
|
||||||
|
|
||||||
|
public abstract class ApsAppGoal extends DisablableGoal {
|
||||||
|
|
||||||
|
@Parameter( property = "aps-model.appName", required = true )
|
||||||
|
protected String apsAppName;
|
||||||
|
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.maven.aps.modeling;
|
package com.inteligr8.maven.aps.modeling.goal;
|
||||||
|
|
||||||
import org.apache.maven.plugin.MojoExecutionException;
|
import org.apache.maven.plugin.MojoExecutionException;
|
||||||
import org.apache.maven.plugin.MojoFailureException;
|
import org.apache.maven.plugin.MojoFailureException;
|
||||||
@@ -12,7 +12,7 @@ import com.inteligr8.alfresco.activiti.model.AppVersion;
|
|||||||
public class ApsInfoGoal extends ApsAddressibleGoal {
|
public class ApsInfoGoal extends ApsAddressibleGoal {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
public void executeEnabled() throws MojoExecutionException, MojoFailureException {
|
||||||
AppVersion version = this.getApsApi()
|
AppVersion version = this.getApsApi()
|
||||||
.getAppVersionApi()
|
.getAppVersionApi()
|
||||||
.get();
|
.get();
|
@@ -1,61 +1,57 @@
|
|||||||
package com.inteligr8.maven.aps.modeling;
|
package com.inteligr8.maven.aps.modeling.goal;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.text.ParseException;
|
||||||
|
|
||||||
import org.apache.maven.plugin.MojoExecutionException;
|
import org.apache.maven.plugin.MojoExecutionException;
|
||||||
import org.apache.maven.plugin.MojoFailureException;
|
import org.apache.maven.plugin.MojoFailureException;
|
||||||
import org.apache.maven.plugins.annotations.Mojo;
|
import org.apache.maven.plugins.annotations.Mojo;
|
||||||
import org.apache.maven.plugins.annotations.Parameter;
|
import org.apache.maven.plugins.annotations.Parameter;
|
||||||
import org.codehaus.plexus.component.annotations.Component;
|
import org.codehaus.plexus.component.annotations.Component;
|
||||||
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
|
||||||
|
|
||||||
import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl;
|
import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl;
|
||||||
import com.inteligr8.alfresco.activiti.model.AppDefinitionUpdateResultRepresentation;
|
import com.inteligr8.alfresco.activiti.model.AppDefinitionUpdateResultRepresentation;
|
||||||
|
import com.inteligr8.alfresco.activiti.model.FileMultipartJersey;
|
||||||
|
|
||||||
@Mojo( name = "deploy-app", threadSafe = true )
|
@Mojo( name = "deploy-app", threadSafe = true )
|
||||||
@Component( role = org.apache.maven.plugin.Mojo.class )
|
@Component( role = org.apache.maven.plugin.Mojo.class )
|
||||||
public class DeployAppGoal extends ApsAppAccessibleGoal {
|
public class DeployAppGoal extends ApsAppAccessibleGoal {
|
||||||
|
|
||||||
@Parameter( property = "apsAppName", required = true )
|
@Parameter( property = "aps-model.upload.directory", required = true, defaultValue = "${project.build.directory}/aps" )
|
||||||
protected String apsAppName;
|
protected File zipDirectory;
|
||||||
|
|
||||||
@Parameter( property = "sourceDirectory", required = true, defaultValue = "${project.build.directory}/app" )
|
|
||||||
protected File sourceDirectory;
|
|
||||||
|
|
||||||
@Parameter( property = "publish", required = true, defaultValue = "false" )
|
@Parameter( property = "publish", required = true, defaultValue = "false" )
|
||||||
protected boolean publish = false;
|
protected boolean publish = false;
|
||||||
|
|
||||||
@Parameter( property = "skip", required = true, defaultValue = "false" )
|
|
||||||
protected boolean skip = false;
|
|
||||||
|
|
||||||
protected final int bufferSize = 128 * 1024;
|
protected final int bufferSize = 128 * 1024;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
public void executeEnabled() throws MojoExecutionException, MojoFailureException {
|
||||||
File sourceFile = this.validateSourceDirectory();
|
File sourceFile = this.validateSourceDirectory();
|
||||||
|
|
||||||
|
Long appId = this.findAppId();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Long appId = this.findAppByName(this.apsAppName);
|
|
||||||
this.uploadApp(appId, sourceFile);
|
this.uploadApp(appId, sourceFile);
|
||||||
} catch (IOException ie) {
|
} catch (IOException ie) {
|
||||||
throw new MojoExecutionException("The downloaded APS App could not be unpacked", ie);
|
throw new MojoExecutionException("The APS App could not be uploaded", ie);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected File validateSourceDirectory() {
|
protected File validateSourceDirectory() {
|
||||||
if (!this.sourceDirectory.exists()) {
|
if (!this.zipDirectory.exists()) {
|
||||||
throw new IllegalStateException("The 'sourceDirectory' does not exist: " + this.sourceDirectory);
|
throw new IllegalStateException("The 'zipDirectory' does not exist: " + this.zipDirectory);
|
||||||
} else if (!this.sourceDirectory.isDirectory()) {
|
} else if (!this.zipDirectory.isDirectory()) {
|
||||||
throw new IllegalStateException("The 'sourceDirectory' is not a directory: " + this.sourceDirectory);
|
throw new IllegalStateException("The 'zipDirectory' is not a directory: " + this.zipDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
File sourceFile = new File(this.sourceDirectory, this.apsAppName + ".zip");
|
File sourceFile = new File(this.zipDirectory, this.apsAppName + ".zip");
|
||||||
|
|
||||||
if (!sourceFile.exists()) {
|
if (!sourceFile.exists()) {
|
||||||
throw new IllegalStateException("The App file does not exists in the 'sourceDirectory': " + sourceFile);
|
throw new IllegalStateException("The App file does not exists in the 'zipDirectory': " + sourceFile);
|
||||||
} else if (!sourceFile.isFile()) {
|
} else if (!sourceFile.isFile()) {
|
||||||
throw new IllegalStateException("The App file is not a file: " + sourceFile);
|
throw new IllegalStateException("The App file is not a file: " + sourceFile);
|
||||||
}
|
}
|
||||||
@@ -66,35 +62,34 @@ public class DeployAppGoal extends ApsAppAccessibleGoal {
|
|||||||
private void uploadApp(Long appId, File appZip) throws IOException, MojoExecutionException {
|
private void uploadApp(Long appId, File appZip) throws IOException, MojoExecutionException {
|
||||||
ApsPublicRestApiJerseyImpl api = this.getApsApi();
|
ApsPublicRestApiJerseyImpl api = this.getApsApi();
|
||||||
|
|
||||||
FormDataContentDisposition cdisposition = FormDataContentDisposition.name("file")
|
|
||||||
.size(appZip.length())
|
|
||||||
.fileName(appZip.getName())
|
|
||||||
.build();
|
|
||||||
|
|
||||||
FileInputStream fistream = new FileInputStream(appZip);
|
FileInputStream fistream = new FileInputStream(appZip);
|
||||||
BufferedInputStream bistream = new BufferedInputStream(fistream, this.bufferSize);
|
BufferedInputStream bistream = new BufferedInputStream(fistream, this.bufferSize);
|
||||||
try {
|
try {
|
||||||
|
FileMultipartJersey multipart = FileMultipartJersey.from(appZip.getName(), bistream);
|
||||||
|
|
||||||
if (appId == null) {
|
if (appId == null) {
|
||||||
if (this.publish) {
|
if (this.publish) {
|
||||||
this.getLog().info("Uploading & publishing new APS App: " + this.apsAppName);
|
this.getLog().info("Uploading & publishing new APS App: " + this.apsAppName);
|
||||||
AppDefinitionUpdateResultRepresentation appDefUpdate = api.getAppDefinitionsJerseyApi().publishApp(bistream, cdisposition);
|
AppDefinitionUpdateResultRepresentation appDefUpdate = api.getAppDefinitionsJerseyApi().publishApp(multipart);
|
||||||
if (Boolean.TRUE.equals(appDefUpdate.getError()))
|
if (Boolean.TRUE.equals(appDefUpdate.getError()))
|
||||||
throw new MojoExecutionException(appDefUpdate.getErrorDescription());
|
throw new MojoExecutionException(appDefUpdate.getErrorDescription());
|
||||||
} else {
|
} else {
|
||||||
this.getLog().info("Uploading new APS App: " + this.apsAppName);
|
this.getLog().info("Uploading new APS App: " + this.apsAppName);
|
||||||
api.getAppDefinitionsJerseyApi().import_(bistream, cdisposition);
|
api.getAppDefinitionsJerseyApi().importApp(multipart, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this.publish) {
|
if (this.publish) {
|
||||||
this.getLog().info("Uploading, versioning, & publishing APS App: " + this.apsAppName);
|
this.getLog().info("Uploading, versioning, & publishing APS App: " + this.apsAppName + " (" + appId + ")");
|
||||||
AppDefinitionUpdateResultRepresentation appDefUpdate = api.getAppDefinitionsJerseyApi().publishApp(appId, bistream, cdisposition);
|
AppDefinitionUpdateResultRepresentation appDefUpdate = api.getAppDefinitionsJerseyApi().publishApp(appId, multipart);
|
||||||
if (Boolean.TRUE.equals(appDefUpdate.getError()))
|
if (Boolean.TRUE.equals(appDefUpdate.getError()))
|
||||||
throw new MojoExecutionException(appDefUpdate.getErrorDescription());
|
throw new MojoExecutionException(appDefUpdate.getErrorDescription());
|
||||||
} else {
|
} else {
|
||||||
this.getLog().info("Uploading & versioning APS App: " + this.apsAppName);
|
this.getLog().info("Uploading & versioning APS App: " + this.apsAppName + " (" + appId + ")");
|
||||||
api.getAppDefinitionsJerseyApi().import_(appId, bistream, cdisposition);
|
api.getAppDefinitionsJerseyApi().importApp(appId, multipart, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (ParseException pe) {
|
||||||
|
throw new MojoExecutionException("The app ZIP could not be wrapped in a multipart", pe);
|
||||||
} finally {
|
} finally {
|
||||||
bistream.close();
|
bistream.close();
|
||||||
}
|
}
|
@@ -0,0 +1,29 @@
|
|||||||
|
package com.inteligr8.maven.aps.modeling.goal;
|
||||||
|
|
||||||
|
import org.apache.maven.plugin.AbstractMojo;
|
||||||
|
import org.apache.maven.plugin.MojoExecutionException;
|
||||||
|
import org.apache.maven.plugin.MojoFailureException;
|
||||||
|
import org.apache.maven.plugins.annotations.Parameter;
|
||||||
|
|
||||||
|
public abstract class DisablableGoal extends AbstractMojo {
|
||||||
|
|
||||||
|
@Parameter( property = "aps-model.skip", required = true, defaultValue = "false" )
|
||||||
|
protected boolean skip = false;
|
||||||
|
|
||||||
|
protected boolean isEnabled() {
|
||||||
|
return !this.skip;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isDisabled() {
|
||||||
|
return this.skip;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void execute() throws MojoExecutionException, MojoFailureException {
|
||||||
|
if (this.isEnabled())
|
||||||
|
this.executeEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void executeEnabled() throws MojoExecutionException, MojoFailureException;
|
||||||
|
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.maven.aps.modeling;
|
package com.inteligr8.maven.aps.modeling.goal;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -16,23 +16,17 @@ import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl;
|
|||||||
@Component( role = org.apache.maven.plugin.Mojo.class )
|
@Component( role = org.apache.maven.plugin.Mojo.class )
|
||||||
public class DownloadAppGoal extends ApsAppAccessibleGoal {
|
public class DownloadAppGoal extends ApsAppAccessibleGoal {
|
||||||
|
|
||||||
@Parameter( property = "apsAppName", required = true )
|
@Parameter( property = "aps-model.download.directory", required = true, defaultValue = "${project.build.directory}/aps" )
|
||||||
protected String apsAppName;
|
protected File zipDirectory;
|
||||||
|
|
||||||
@Parameter( property = "targetDirectory", required = true, defaultValue = "${project.build.directory}/app" )
|
|
||||||
protected File targetDirectory;
|
|
||||||
|
|
||||||
@Parameter( property = "skip", required = true, defaultValue = "false" )
|
|
||||||
protected boolean skip = false;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
public void executeEnabled() throws MojoExecutionException, MojoFailureException {
|
||||||
this.validateTargetDirectory();
|
this.validateTargetDirectory();
|
||||||
|
|
||||||
long appId = this.findAppByName(this.apsAppName);
|
Long appId = this.findAppId();
|
||||||
File appZip = this.downloadApp(appId);
|
File appZip = this.downloadApp(appId);
|
||||||
|
|
||||||
File toAppZip = new File(this.targetDirectory, this.apsAppName + ".zip");
|
File toAppZip = new File(this.zipDirectory, this.apsAppName + ".zip");
|
||||||
if (toAppZip.exists())
|
if (toAppZip.exists())
|
||||||
toAppZip.delete();
|
toAppZip.delete();
|
||||||
|
|
||||||
@@ -44,10 +38,10 @@ public class DownloadAppGoal extends ApsAppAccessibleGoal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void validateTargetDirectory() {
|
protected void validateTargetDirectory() {
|
||||||
if (!this.targetDirectory.exists()) {
|
if (!this.zipDirectory.exists()) {
|
||||||
this.getLog().debug("Creating APS Apps directory: " + this.targetDirectory);
|
this.getLog().debug("Creating APS Apps directory: " + this.zipDirectory);
|
||||||
this.targetDirectory.mkdirs();
|
this.zipDirectory.mkdirs();
|
||||||
} else if (!this.targetDirectory.isDirectory()) {
|
} else if (!this.zipDirectory.isDirectory()) {
|
||||||
throw new IllegalStateException("The 'targetDirectory' refers to a file and not a directory");
|
throw new IllegalStateException("The 'targetDirectory' refers to a file and not a directory");
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.maven.aps.modeling;
|
package com.inteligr8.maven.aps.modeling.goal;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
@@ -12,7 +12,6 @@ import java.util.zip.ZipEntry;
|
|||||||
import java.util.zip.ZipOutputStream;
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.maven.plugin.AbstractMojo;
|
|
||||||
import org.apache.maven.plugin.MojoExecutionException;
|
import org.apache.maven.plugin.MojoExecutionException;
|
||||||
import org.apache.maven.plugin.MojoFailureException;
|
import org.apache.maven.plugin.MojoFailureException;
|
||||||
import org.apache.maven.plugins.annotations.Mojo;
|
import org.apache.maven.plugins.annotations.Mojo;
|
||||||
@@ -21,24 +20,18 @@ import org.codehaus.plexus.component.annotations.Component;
|
|||||||
|
|
||||||
@Mojo( name = "pack-app", threadSafe = true )
|
@Mojo( name = "pack-app", threadSafe = true )
|
||||||
@Component( role = org.apache.maven.plugin.Mojo.class )
|
@Component( role = org.apache.maven.plugin.Mojo.class )
|
||||||
public class PackAppGoal extends AbstractMojo {
|
public class PackAppGoal extends ApsAppGoal {
|
||||||
|
|
||||||
@Parameter( property = "apsAppName", required = true )
|
@Parameter( property = "aps-model.app.directory", required = true, defaultValue = "${project.build.directory}/aps/app" )
|
||||||
protected String apsAppName;
|
protected File unzipDirectory;
|
||||||
|
|
||||||
@Parameter( property = "sourceDirectory", required = true, defaultValue = "${project.build.directory}/app" )
|
|
||||||
protected File sourceDirectory;
|
|
||||||
|
|
||||||
@Parameter( property = "targetDirectory", required = true, defaultValue = "${project.build.directory}/app" )
|
|
||||||
protected File targetDirectory;
|
|
||||||
|
|
||||||
@Parameter( property = "skip", required = true, defaultValue = "false" )
|
@Parameter( property = "aps-model.upload.directory", required = true, defaultValue = "${project.build.directory}/aps" )
|
||||||
protected boolean skip = false;
|
protected File zipDirectory;
|
||||||
|
|
||||||
protected final int bufferSize = 128 * 1024;
|
protected final int bufferSize = 128 * 1024;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
public void executeEnabled() throws MojoExecutionException, MojoFailureException {
|
||||||
this.validateSourceDirectory();
|
this.validateSourceDirectory();
|
||||||
File appDirectory = this.validateAppDirectory();
|
File appDirectory = this.validateAppDirectory();
|
||||||
|
|
||||||
@@ -52,17 +45,17 @@ public class PackAppGoal extends AbstractMojo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void validateSourceDirectory() {
|
protected void validateSourceDirectory() {
|
||||||
if (!this.sourceDirectory.exists()) {
|
if (!this.unzipDirectory.exists()) {
|
||||||
throw new IllegalStateException("The 'sourceDirectory' does not exist: " + this.sourceDirectory);
|
throw new IllegalStateException("The 'unzipDirectory' does not exist: " + this.unzipDirectory);
|
||||||
} else if (!this.sourceDirectory.isDirectory()) {
|
} else if (!this.unzipDirectory.isDirectory()) {
|
||||||
throw new IllegalStateException("The 'sourceDirectory' is not a directory: " + this.sourceDirectory);
|
throw new IllegalStateException("The 'unzipDirectory' is not a directory: " + this.unzipDirectory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected File validateAppDirectory() {
|
protected File validateAppDirectory() {
|
||||||
File appDirectory = new File(this.sourceDirectory, this.apsAppName);
|
File appDirectory = new File(this.unzipDirectory, this.apsAppName);
|
||||||
if (!appDirectory.exists()) {
|
if (!appDirectory.exists()) {
|
||||||
throw new IllegalStateException("The 'apsAppName' does not exist in the source directory: " + this.sourceDirectory);
|
throw new IllegalStateException("The 'apsAppName' does not exist in the source directory: " + this.unzipDirectory);
|
||||||
} else if (!appDirectory.isDirectory()) {
|
} else if (!appDirectory.isDirectory()) {
|
||||||
throw new IllegalStateException("The 'apsAppName' refers to a file and not a directory: " + appDirectory);
|
throw new IllegalStateException("The 'apsAppName' refers to a file and not a directory: " + appDirectory);
|
||||||
}
|
}
|
||||||
@@ -71,19 +64,19 @@ public class PackAppGoal extends AbstractMojo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected File validateTargetDirectory() {
|
protected File validateTargetDirectory() {
|
||||||
if (!this.targetDirectory.exists()) {
|
if (!this.zipDirectory.exists()) {
|
||||||
this.getLog().debug("The 'targetDirectory' does not exist; creating: " + this.targetDirectory);
|
this.getLog().debug("The 'zipDirectory' does not exist; creating: " + this.zipDirectory);
|
||||||
this.targetDirectory.mkdirs();
|
this.zipDirectory.mkdirs();
|
||||||
} else if (!this.targetDirectory.isDirectory()) {
|
} else if (!this.zipDirectory.isDirectory()) {
|
||||||
throw new IllegalStateException("The 'targetDirectory' is not a directory: " + this.targetDirectory);
|
throw new IllegalStateException("The 'zipDirectory' is not a directory: " + this.zipDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
File targetFile = new File(this.targetDirectory, this.apsAppName + ".zip");
|
File targetFile = new File(this.zipDirectory, this.apsAppName + ".zip");
|
||||||
|
|
||||||
if (targetFile.isDirectory()) {
|
if (targetFile.isDirectory()) {
|
||||||
throw new IllegalStateException("The App file is not a file: " + targetFile);
|
throw new IllegalStateException("The App file is not a file: " + targetFile);
|
||||||
} else if (targetFile.exists()) {
|
} else if (targetFile.exists()) {
|
||||||
this.getLog().debug("The App file in the 'targetDirectory' exists; deleting: " + targetFile);
|
this.getLog().debug("The App file in the 'zipDirectory' exists; deleting: " + targetFile);
|
||||||
targetFile.delete();
|
targetFile.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,6 +92,7 @@ public class PackAppGoal extends AbstractMojo {
|
|||||||
ZipOutputStream zostream = new ZipOutputStream(bostream);
|
ZipOutputStream zostream = new ZipOutputStream(bostream);
|
||||||
try {
|
try {
|
||||||
this.zipDirectory(appDirectory, null, zostream);
|
this.zipDirectory(appDirectory, null, zostream);
|
||||||
|
zostream.flush();
|
||||||
} finally {
|
} finally {
|
||||||
zostream.close();
|
zostream.close();
|
||||||
}
|
}
|
||||||
@@ -125,7 +119,8 @@ public class PackAppGoal extends AbstractMojo {
|
|||||||
|
|
||||||
this.getLog().debug("Packing APS file: " + path);
|
this.getLog().debug("Packing APS file: " + path);
|
||||||
|
|
||||||
ZipEntry zentry = new ZipEntry(path.toString());
|
// Activit App processing requires forward slashes (WOW)
|
||||||
|
ZipEntry zentry = new ZipEntry(path.toString().replace('\\', '/'));
|
||||||
zostream.putNextEntry(zentry);
|
zostream.putNextEntry(zentry);
|
||||||
try {
|
try {
|
||||||
FileInputStream fistream = new FileInputStream(file);
|
FileInputStream fistream = new FileInputStream(file);
|
@@ -0,0 +1,91 @@
|
|||||||
|
package com.inteligr8.maven.aps.modeling.goal;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.apache.maven.plugin.MojoExecutionException;
|
||||||
|
import org.apache.maven.plugin.MojoFailureException;
|
||||||
|
import org.apache.maven.plugins.annotations.Mojo;
|
||||||
|
import org.apache.maven.plugins.annotations.Parameter;
|
||||||
|
import org.codehaus.plexus.component.annotations.Component;
|
||||||
|
|
||||||
|
import com.inteligr8.maven.aps.modeling.crawler.ApsAppCrawler;
|
||||||
|
import com.inteligr8.maven.aps.modeling.translator.ApsAppTranslator;
|
||||||
|
|
||||||
|
@Mojo( name = "translate-app", threadSafe = true )
|
||||||
|
@Component( role = org.apache.maven.plugin.Mojo.class )
|
||||||
|
public class TranslateAppGoal extends ApsAppAccessibleGoal {
|
||||||
|
|
||||||
|
@Parameter( property = "aps-model.app.directory", required = true, defaultValue = "${project.build.directory}/aps/app" )
|
||||||
|
protected File unzipDirectory;
|
||||||
|
|
||||||
|
@Parameter( property = "aps-model.translatedApp.directory", required = false, defaultValue = "${project.build.directory}/aps/app" )
|
||||||
|
protected File finalDirectory;
|
||||||
|
|
||||||
|
@Parameter( property = "aps-model.translate.overwrite", required = true, defaultValue = "true" )
|
||||||
|
protected boolean overwrite = true;
|
||||||
|
|
||||||
|
@Parameter( property = "aps-model.translate.charset", required = true, defaultValue = "utf-8" )
|
||||||
|
protected String charsetName = "utf-8";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void executeEnabled() throws MojoExecutionException, MojoFailureException {
|
||||||
|
File apsAppDirectory = this.validateApsAppDirectory();
|
||||||
|
File newApsAppDirectory = this.validateTargetDirectory();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!apsAppDirectory.equals(newApsAppDirectory)) {
|
||||||
|
FileUtils.copyDirectory(apsAppDirectory, newApsAppDirectory);
|
||||||
|
apsAppDirectory = newApsAppDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
ApsAppTranslator translator = new ApsAppTranslator(apsAppDirectory, this.getApsApi());
|
||||||
|
translator.buildIndexes();
|
||||||
|
|
||||||
|
ApsAppCrawler crawler = new ApsAppCrawler(this.apsAppName, apsAppDirectory, true);
|
||||||
|
crawler.execute(translator);
|
||||||
|
} catch (IOException ie) {
|
||||||
|
throw new MojoExecutionException("An I/O issue occurred", ie);
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
throw new MojoExecutionException("The input is not supported", iae);
|
||||||
|
} catch (IllegalStateException ise) {
|
||||||
|
throw new MojoExecutionException("The state of system is not supported", ise);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected File validateApsAppDirectory() throws MojoExecutionException {
|
||||||
|
if (!this.unzipDirectory.exists())
|
||||||
|
throw new MojoExecutionException("The 'unzipDirectory' does not exist: " + this.unzipDirectory);
|
||||||
|
if (!this.unzipDirectory.isDirectory())
|
||||||
|
throw new MojoExecutionException("The 'unzipDirectory' is not a directory: " + this.unzipDirectory);
|
||||||
|
|
||||||
|
File appDirectory = new File(this.unzipDirectory, this.apsAppName);
|
||||||
|
|
||||||
|
if (!appDirectory.exists())
|
||||||
|
throw new MojoExecutionException("The 'apsAppName' does not exist in the 'unzipDirectory': " + appDirectory);
|
||||||
|
if (!appDirectory.isDirectory())
|
||||||
|
throw new MojoExecutionException("The 'apsAppName' is not a directory in the 'unzipDirectory': " + appDirectory);
|
||||||
|
|
||||||
|
return appDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected File validateTargetDirectory() throws MojoExecutionException {
|
||||||
|
if (!this.finalDirectory.exists()) {
|
||||||
|
this.finalDirectory.mkdirs();
|
||||||
|
} else if (!this.finalDirectory.isDirectory()) {
|
||||||
|
throw new MojoExecutionException("The 'finalDirectory' is not a directory: " + this.finalDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
File appDirectory = new File(this.finalDirectory, this.apsAppName);
|
||||||
|
|
||||||
|
if (!appDirectory.exists()) {
|
||||||
|
appDirectory.mkdirs();
|
||||||
|
} else if (!appDirectory.isDirectory()) {
|
||||||
|
throw new MojoExecutionException("The 'apsAppName' is not a directory in the 'finalDirectory': " + appDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
return appDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.maven.aps.modeling;
|
package com.inteligr8.maven.aps.modeling.goal;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
@@ -10,43 +10,53 @@ import java.io.InputStream;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
import javax.xml.transform.TransformerException;
|
import javax.xml.transform.TransformerException;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.maven.plugin.AbstractMojo;
|
|
||||||
import org.apache.maven.plugin.MojoExecutionException;
|
import org.apache.maven.plugin.MojoExecutionException;
|
||||||
import org.apache.maven.plugin.MojoFailureException;
|
import org.apache.maven.plugin.MojoFailureException;
|
||||||
import org.apache.maven.plugins.annotations.Mojo;
|
import org.apache.maven.plugins.annotations.Mojo;
|
||||||
import org.apache.maven.plugins.annotations.Parameter;
|
import org.apache.maven.plugins.annotations.Parameter;
|
||||||
import org.codehaus.plexus.component.annotations.Component;
|
import org.codehaus.plexus.component.annotations.Component;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
import com.inteligr8.maven.aps.modeling.crawler.ApsAppCrawler;
|
||||||
|
import com.inteligr8.maven.aps.modeling.normalizer.ApsAppNormalizer;
|
||||||
|
import com.inteligr8.maven.aps.modeling.util.ModelUtil;
|
||||||
|
|
||||||
@Mojo( name = "unpack-app", threadSafe = true )
|
@Mojo( name = "unpack-app", threadSafe = true )
|
||||||
@Component( role = org.apache.maven.plugin.Mojo.class )
|
@Component( role = org.apache.maven.plugin.Mojo.class )
|
||||||
public class UnpackAppGoal extends AbstractMojo {
|
public class UnpackAppGoal extends ApsAppGoal {
|
||||||
|
|
||||||
@Parameter( property = "apsAppName", required = true )
|
@Parameter( property = "aps-model.download.directory", required = true, defaultValue = "${project.build.directory}/aps" )
|
||||||
protected String apsAppName;
|
protected File zipDirectory;
|
||||||
|
|
||||||
@Parameter( property = "sourceDirectory", required = true, defaultValue = "${project.build.directory}/app" )
|
@Parameter( property = "aps-model.app.directory", required = true, defaultValue = "${project.build.directory}/aps/app" )
|
||||||
protected File sourceDirectory;
|
protected File unzipDirectory;
|
||||||
|
|
||||||
@Parameter( property = "targetDirectory", required = true, defaultValue = "${project.build.directory}/app" )
|
|
||||||
protected File targetDirectory;
|
|
||||||
|
|
||||||
@Parameter( property = "charset", required = true, defaultValue = "utf-8" )
|
@Parameter( property = "aps-model.reformat", required = true, defaultValue = "true" )
|
||||||
|
protected boolean reformat = true;
|
||||||
|
|
||||||
|
@Parameter( property = "aps-model.normalize" )
|
||||||
|
protected boolean normalize;
|
||||||
|
|
||||||
|
@Parameter( property = "aps-model.normalize.diffFriendly" )
|
||||||
|
protected boolean diffFriendly;
|
||||||
|
|
||||||
|
@Parameter( property = "aps-model.charset", required = true, defaultValue = "utf-8" )
|
||||||
protected String charsetName = "utf-8";
|
protected String charsetName = "utf-8";
|
||||||
|
|
||||||
@Parameter( property = "skip", required = true, defaultValue = "false" )
|
|
||||||
protected boolean skip = false;
|
|
||||||
|
|
||||||
private final int bufferSize = 128 * 1024;
|
private final int bufferSize = 128 * 1024;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
public void executeEnabled() throws MojoExecutionException, MojoFailureException {
|
||||||
|
this.validate();
|
||||||
|
|
||||||
File sourceFile = this.validateSourceDirectory();
|
File sourceFile = this.validateSourceDirectory();
|
||||||
|
|
||||||
this.validateTargetDirectory();
|
this.validateTargetDirectory();
|
||||||
@@ -60,20 +70,37 @@ public class UnpackAppGoal extends AbstractMojo {
|
|||||||
throw new MojoExecutionException("The downloaded APS App could not be unpacked", ie);
|
throw new MojoExecutionException("The downloaded APS App could not be unpacked", ie);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.normalizeFiles(appDirectory);
|
if (this.reformat)
|
||||||
|
this.reformatFiles(appDirectory);
|
||||||
|
if (this.normalize) {
|
||||||
|
try {
|
||||||
|
ApsAppNormalizer normalizer = new ApsAppNormalizer(this.diffFriendly);
|
||||||
|
ApsAppCrawler crawler = new ApsAppCrawler(this.apsAppName, appDirectory, true);
|
||||||
|
crawler.execute(normalizer);
|
||||||
|
} catch (IOException ie) {
|
||||||
|
throw new MojoExecutionException("An I/O issue occurred", ie);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void validate() {
|
||||||
|
if (this.normalize && !this.reformat) {
|
||||||
|
this.getLog().warn("The reformat option is disabled, but normalization is enabled; enabling reformat anyway");
|
||||||
|
this.reformat = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected File validateSourceDirectory() {
|
protected File validateSourceDirectory() {
|
||||||
if (!this.sourceDirectory.exists()) {
|
if (!this.zipDirectory.exists()) {
|
||||||
throw new IllegalStateException("The 'sourceDirectory' does not exist: " + this.sourceDirectory);
|
throw new IllegalStateException("The 'zipDirectory' does not exist: " + this.zipDirectory);
|
||||||
} else if (!this.sourceDirectory.isDirectory()) {
|
} else if (!this.zipDirectory.isDirectory()) {
|
||||||
throw new IllegalStateException("The 'sourceDirectory' is not a directory: " + this.sourceDirectory);
|
throw new IllegalStateException("The 'zipDirectory' is not a directory: " + this.zipDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
File sourceFile = new File(this.sourceDirectory, this.apsAppName + ".zip");
|
File sourceFile = new File(this.zipDirectory, this.apsAppName + ".zip");
|
||||||
|
|
||||||
if (!sourceFile.exists()) {
|
if (!sourceFile.exists()) {
|
||||||
throw new IllegalStateException("The App file does not exists in the 'sourceDirectory': " + sourceFile);
|
throw new IllegalStateException("The App file does not exists in the 'zipDirectory': " + sourceFile);
|
||||||
} else if (!sourceFile.isFile()) {
|
} else if (!sourceFile.isFile()) {
|
||||||
throw new IllegalStateException("The App file is not a file: " + sourceFile);
|
throw new IllegalStateException("The App file is not a file: " + sourceFile);
|
||||||
}
|
}
|
||||||
@@ -82,16 +109,16 @@ public class UnpackAppGoal extends AbstractMojo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void validateTargetDirectory() {
|
protected void validateTargetDirectory() {
|
||||||
if (!this.targetDirectory.exists()) {
|
if (!this.unzipDirectory.exists()) {
|
||||||
this.getLog().debug("Creating APS Apps directory: " + this.targetDirectory);
|
this.getLog().debug("Creating unzip directory: " + this.unzipDirectory);
|
||||||
this.targetDirectory.mkdirs();
|
this.unzipDirectory.mkdirs();
|
||||||
} else if (!this.targetDirectory.isDirectory()) {
|
} else if (!this.unzipDirectory.isDirectory()) {
|
||||||
throw new IllegalStateException("The 'apsAppsDirectory' refers to a file and not a directory: " + this.targetDirectory);
|
throw new IllegalStateException("The 'unzipDirectory' refers to a file and not a directory: " + this.unzipDirectory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected File validateAppDirectory() {
|
protected File validateAppDirectory() {
|
||||||
File appDirectory = new File(this.targetDirectory, this.apsAppName);
|
File appDirectory = new File(this.unzipDirectory, this.apsAppName);
|
||||||
if (!appDirectory.exists()) {
|
if (!appDirectory.exists()) {
|
||||||
this.getLog().debug("Creating APS App directory: " + appDirectory);
|
this.getLog().debug("Creating APS App directory: " + appDirectory);
|
||||||
appDirectory.mkdirs();
|
appDirectory.mkdirs();
|
||||||
@@ -149,21 +176,25 @@ public class UnpackAppGoal extends AbstractMojo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void normalizeFiles(File directory) throws MojoFailureException {
|
private void reformatFiles(File directory) throws MojoFailureException {
|
||||||
for (File file : directory.listFiles()) {
|
for (File file : directory.listFiles()) {
|
||||||
if (file.isDirectory()) {
|
if (file.isDirectory()) {
|
||||||
this.normalizeFiles(file);
|
this.reformatFiles(file);
|
||||||
} else {
|
} else {
|
||||||
String ext = this.getFileExtension(file);
|
String ext = this.getFileExtension(file);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
switch (ext) {
|
switch (ext) {
|
||||||
case "json":
|
case "json":
|
||||||
ModelUtil.getInstance().json(file);
|
this.getLog().debug("Reformatting file: " + file);
|
||||||
|
Map<String, Object> json = ModelUtil.getInstance().readJsonAsMap(file);
|
||||||
|
ModelUtil.getInstance().writeJson(json, file, false);
|
||||||
break;
|
break;
|
||||||
case "xml":
|
case "xml":
|
||||||
case "bpmn":
|
case "bpmn":
|
||||||
ModelUtil.getInstance().xml(file);
|
this.getLog().debug("Reformatting file: " + file);
|
||||||
|
Document xml = ModelUtil.getInstance().readXml(file);
|
||||||
|
ModelUtil.getInstance().writeXml(xml, file);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
file.delete();
|
file.delete();
|
@@ -0,0 +1,53 @@
|
|||||||
|
package com.inteligr8.maven.aps.modeling.normalizer;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import com.inteligr8.maven.aps.modeling.util.ApsModelArrayNodeSorter;
|
||||||
|
import com.inteligr8.maven.aps.modeling.util.ModelUtil;
|
||||||
|
|
||||||
|
public class ApsAppJsonNormalizer implements ApsFileNormalizer {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(ApsAppJsonNormalizer.class);
|
||||||
|
|
||||||
|
private final boolean enableSorting;
|
||||||
|
|
||||||
|
public ApsAppJsonNormalizer(boolean enableSorting) {
|
||||||
|
this.enableSorting = enableSorting;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transformFile(File file, String modelName, Long modelId) throws IOException {
|
||||||
|
this.logger.debug("Normalizing App JSON file: {}", file);
|
||||||
|
|
||||||
|
boolean changed = false;
|
||||||
|
JsonNode descriptor = ModelUtil.getInstance().readJson(file);
|
||||||
|
ArrayNode jsonModels = (ArrayNode)descriptor.get("definition").get("models");
|
||||||
|
|
||||||
|
// remove system-level and non-functional fields from models
|
||||||
|
for (JsonNode _jsonModel : jsonModels) {
|
||||||
|
ObjectNode jsonModel = (ObjectNode)_jsonModel;
|
||||||
|
|
||||||
|
int fields = jsonModel.size();
|
||||||
|
jsonModel.remove(Arrays.asList("lastUpdated"));
|
||||||
|
// jsonModel.remove(Arrays.asList("createdBy", "createdByFullName", "lastUpdatedBy", "lastUpdatedByFullName", "lastUpdated"));
|
||||||
|
if (jsonModel.size() < fields)
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort the models for better 'diff' support
|
||||||
|
if (this.enableSorting)
|
||||||
|
changed = ApsModelArrayNodeSorter.getInstance().sort(jsonModels, "name") || changed;
|
||||||
|
|
||||||
|
if (changed)
|
||||||
|
ModelUtil.getInstance().writeJson(descriptor, file, this.enableSorting);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,34 @@
|
|||||||
|
package com.inteligr8.maven.aps.modeling.normalizer;
|
||||||
|
|
||||||
|
import com.inteligr8.maven.aps.modeling.crawler.ApsAppCrawlable;
|
||||||
|
import com.inteligr8.maven.aps.modeling.crawler.ApsFileTransformer;
|
||||||
|
|
||||||
|
public class ApsAppNormalizer implements ApsAppCrawlable {
|
||||||
|
|
||||||
|
private final boolean enableSorting;
|
||||||
|
|
||||||
|
public ApsAppNormalizer(boolean enableSorting) {
|
||||||
|
this.enableSorting = enableSorting;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApsFileTransformer getAppJsonTransformer() {
|
||||||
|
return new ApsAppJsonNormalizer(this.enableSorting);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApsFileTransformer getFormJsonTransformer() {
|
||||||
|
return new ApsFormJsonNormalizer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApsFileTransformer getProcessJsonTransformer() {
|
||||||
|
return new ApsProcessJsonNormalizer(this.enableSorting);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApsFileTransformer getProcessBpmnTransformer() {
|
||||||
|
return new ApsProcessBpmnNormalizer();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,7 @@
|
|||||||
|
package com.inteligr8.maven.aps.modeling.normalizer;
|
||||||
|
|
||||||
|
import com.inteligr8.maven.aps.modeling.crawler.ApsFileTransformer;
|
||||||
|
|
||||||
|
public interface ApsFileNormalizer extends ApsFileTransformer {
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,19 @@
|
|||||||
|
package com.inteligr8.maven.aps.modeling.normalizer;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class ApsFormJsonNormalizer implements ApsFileNormalizer {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(ApsFormJsonNormalizer.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transformFile(File file, String modelName, Long modelId) throws IOException {
|
||||||
|
this.logger.debug("Normalizing Form JSON file: {}", file);
|
||||||
|
this.logger.trace("Nothing to normalize: {}", file);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,52 @@
|
|||||||
|
package com.inteligr8.maven.aps.modeling.normalizer;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.xml.transform.TransformerException;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.w3c.dom.Attr;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
import com.inteligr8.maven.aps.modeling.util.ModelUtil;
|
||||||
|
|
||||||
|
public class ApsProcessBpmnNormalizer implements ApsFileNormalizer {
|
||||||
|
|
||||||
|
private static final String NAMESPACE_ACTIVITI_MODELER = "http://activiti.com/modeler";
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(ApsProcessBpmnNormalizer.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transformFile(File file, String modelName, Long modelId) throws IOException {
|
||||||
|
this.logger.debug("Normalizing Process BPMN file: {}", file);
|
||||||
|
|
||||||
|
boolean changed = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Document bpmn = ModelUtil.getInstance().readXml(file);
|
||||||
|
Element definitionsElement = bpmn.getDocumentElement();
|
||||||
|
|
||||||
|
changed = this.removeAttributeIfSet(definitionsElement, NAMESPACE_ACTIVITI_MODELER, "exportDateTime") || changed;
|
||||||
|
changed = this.removeAttributeIfSet(definitionsElement, NAMESPACE_ACTIVITI_MODELER, "modelLastUpdated") || changed;
|
||||||
|
|
||||||
|
if (changed)
|
||||||
|
ModelUtil.getInstance().writeXml(bpmn, file);
|
||||||
|
} catch (TransformerException | SAXException e) {
|
||||||
|
throw new IllegalStateException("An XML issue occurred", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean removeAttributeIfSet(Element element, String attrNamespace, String attrName) {
|
||||||
|
Attr attr = element.getAttributeNodeNS(attrNamespace, attrName);
|
||||||
|
if (attr == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
element.removeAttributeNode(attr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,50 @@
|
|||||||
|
package com.inteligr8.maven.aps.modeling.normalizer;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import com.inteligr8.maven.aps.modeling.util.ApsModelArrayNodeSorter;
|
||||||
|
import com.inteligr8.maven.aps.modeling.util.ModelUtil;
|
||||||
|
|
||||||
|
public class ApsProcessJsonNormalizer implements ApsFileNormalizer {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(ApsProcessJsonNormalizer.class);
|
||||||
|
|
||||||
|
private final boolean enableSorting;
|
||||||
|
|
||||||
|
public ApsProcessJsonNormalizer(boolean enableSorting) {
|
||||||
|
this.enableSorting = enableSorting;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transformFile(File file, String modelName, Long modelId) throws IOException {
|
||||||
|
this.logger.debug("Normalizing Process JSON file: {}", file);
|
||||||
|
|
||||||
|
if (!this.enableSorting)
|
||||||
|
return;
|
||||||
|
|
||||||
|
boolean changed = false;
|
||||||
|
|
||||||
|
ObjectNode jsonDescriptor = ModelUtil.getInstance().readJson(file, ObjectNode.class);
|
||||||
|
ArrayNode jsonChildShapes = this.getChildShapes(jsonDescriptor);
|
||||||
|
|
||||||
|
changed = ApsModelArrayNodeSorter.getInstance().sort(jsonChildShapes, "resourceId") || changed;
|
||||||
|
|
||||||
|
if (changed)
|
||||||
|
ModelUtil.getInstance().writeJson(jsonDescriptor, file, this.enableSorting);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArrayNode getChildShapes(ObjectNode jsonDescriptor) {
|
||||||
|
JsonNode jsonChildShapes = jsonDescriptor.get("childShapes");
|
||||||
|
if (jsonChildShapes == null)
|
||||||
|
jsonChildShapes = jsonDescriptor.get("editorJson").get("childShapes");
|
||||||
|
return (ArrayNode)jsonChildShapes;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.maven.aps.modeling;
|
package com.inteligr8.maven.aps.modeling.translator;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -9,33 +9,35 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import com.inteligr8.alfresco.activiti.model.Group;
|
import com.inteligr8.alfresco.activiti.ApsPublicRestApi;
|
||||||
|
import com.inteligr8.alfresco.activiti.model.GroupLight;
|
||||||
|
import com.inteligr8.maven.aps.modeling.util.Index;
|
||||||
|
import com.inteligr8.maven.aps.modeling.util.ModelUtil;
|
||||||
|
|
||||||
public class ApsAppJsonTranslator implements ApsFileTranslator {
|
public class ApsAppJsonTranslator extends ApsOrganizationHandler implements ApsFileTranslator {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(ApsAppJsonTranslator.class);
|
private final Logger logger = LoggerFactory.getLogger(ApsAppJsonTranslator.class);
|
||||||
|
private final Map<String, GroupLight> apsOrgIndex;
|
||||||
private Map<String, Group> apsOrgIndex;
|
private final Index<Long, String> apsProcessIndex;
|
||||||
private Index<Long, String> apsProcessIndex;
|
private final Index<Long, String> fileProcessIndex;
|
||||||
private Index<Long, String> fileProcessIndex;
|
|
||||||
|
|
||||||
public ApsAppJsonTranslator(
|
public ApsAppJsonTranslator(
|
||||||
Map<String, Group> apsOrgIndex,
|
ApsPublicRestApi api,
|
||||||
|
Map<String, GroupLight> apsOrgIndex,
|
||||||
Index<Long, String> apsProcessIndex,
|
Index<Long, String> apsProcessIndex,
|
||||||
Index<Long, String> fileProcessIndex) {
|
Index<Long, String> fileProcessIndex) {
|
||||||
|
super(api, apsOrgIndex);
|
||||||
this.apsOrgIndex = apsOrgIndex;
|
this.apsOrgIndex = apsOrgIndex;
|
||||||
this.apsProcessIndex = apsProcessIndex;
|
this.apsProcessIndex = apsProcessIndex;
|
||||||
|
|
||||||
this.fileProcessIndex = fileProcessIndex;
|
this.fileProcessIndex = fileProcessIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translateFile(File file, String modelName, Long modelId) throws IOException {
|
public void translateFile(File file, String modelName, Long modelId) throws IOException {
|
||||||
this.logger.debug("Translating JSON file: {}", file);
|
this.logger.debug("Translating JSON file: {}", file);
|
||||||
|
|
||||||
JsonNode descriptor = ModelUtil.getInstance().readJson(file);
|
|
||||||
|
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
|
JsonNode descriptor = ModelUtil.getInstance().readJson(file);
|
||||||
|
|
||||||
for (JsonNode _jsonModel : descriptor.get("definition").get("models")) {
|
for (JsonNode _jsonModel : descriptor.get("definition").get("models")) {
|
||||||
ObjectNode jsonModel = (ObjectNode)_jsonModel;
|
ObjectNode jsonModel = (ObjectNode)_jsonModel;
|
||||||
@@ -64,6 +66,15 @@ public class ApsAppJsonTranslator implements ApsFileTranslator {
|
|||||||
this.logger.trace("The process '{}' ID does not change; leaving unchanged", fileProcessName);
|
this.logger.trace("The process '{}' ID does not change; leaving unchanged", fileProcessName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (jsonModel.has("version")) {
|
||||||
|
jsonModel.put("version", 0);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
// int fields = jsonModel.size();
|
||||||
|
// jsonModel.remove(Arrays.asList("version"));
|
||||||
|
// if (jsonModel.size() < fields)
|
||||||
|
// changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (JsonNode _jsonIdentityInfo : descriptor.get("definition").get("publishIdentityInfo")) {
|
for (JsonNode _jsonIdentityInfo : descriptor.get("definition").get("publishIdentityInfo")) {
|
||||||
@@ -74,23 +85,37 @@ public class ApsAppJsonTranslator implements ApsFileTranslator {
|
|||||||
|
|
||||||
if (this.apsOrgIndex.containsKey(fileOrgName)) {
|
if (this.apsOrgIndex.containsKey(fileOrgName)) {
|
||||||
long fileOrgId = jsonGroup.get("id").asLong();
|
long fileOrgId = jsonGroup.get("id").asLong();
|
||||||
long apsOrgId = this.apsOrgIndex.get(fileOrgName).getId();
|
GroupLight apsOrg = this.apsOrgIndex.get(fileOrgName);
|
||||||
|
|
||||||
if (fileOrgId != apsOrgId) {
|
if (apsOrg == null) {
|
||||||
this.logger.debug("The organziation '{}' exists in APS with ID {}; changing descriptor", fileOrgName, apsOrgId);
|
this.logger.debug("The organization '{}' does not exist in APS; adding to APS", fileOrgName);
|
||||||
jsonGroup.put("id", apsOrgId);
|
long apsGroupId = this.createOrganization(fileOrgName);
|
||||||
|
jsonGroup.put("id", apsGroupId);
|
||||||
|
changed = true;
|
||||||
|
} else if (fileOrgId != apsOrg.getId()) {
|
||||||
|
this.logger.debug("The organization '{}' exists in APS with ID {}; changing descriptor", fileOrgName, apsOrg.getId());
|
||||||
|
jsonGroup.put("id", apsOrg.getId());
|
||||||
changed = true;
|
changed = true;
|
||||||
} else {
|
} else {
|
||||||
this.logger.trace("The organization '{}' ID does not change; leaving unchanged", fileOrgName);
|
this.logger.trace("The organization '{}' ID does not change; leaving unchanged", fileOrgName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (jsonGroup.has("parentGroupId")) {
|
||||||
|
jsonGroup.put("parentGroupId", 0);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
// if (jsonGroup.has("parentGroupId")) {
|
||||||
|
// jsonGroup.remove("parentGroupId");
|
||||||
|
// changed = true;
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
this.logger.warn("The organziation '{}' does not exist in APS", fileOrgName);
|
this.logger.warn("The organization '{}' does not exist in APS", fileOrgName);
|
||||||
// FIXME create the organization
|
// FIXME create the organization
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
ModelUtil.getInstance().writeJson(descriptor, file);
|
ModelUtil.getInstance().writeJson(descriptor, file, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -1,8 +1,7 @@
|
|||||||
package com.inteligr8.maven.aps.modeling;
|
package com.inteligr8.maven.aps.modeling.translator;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -13,110 +12,127 @@ import java.util.regex.Pattern;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.inteligr8.alfresco.activiti.ApsPublicRestApi;
|
||||||
import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl;
|
import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl;
|
||||||
import com.inteligr8.alfresco.activiti.api.ModelsApi.ModelType;
|
import com.inteligr8.alfresco.activiti.api.ModelsApi.ModelType;
|
||||||
import com.inteligr8.alfresco.activiti.model.Datum;
|
import com.inteligr8.alfresco.activiti.model.Datum;
|
||||||
import com.inteligr8.alfresco.activiti.model.Group;
|
import com.inteligr8.alfresco.activiti.model.GroupLight;
|
||||||
import com.inteligr8.alfresco.activiti.model.ResultListDataRepresentation;
|
import com.inteligr8.alfresco.activiti.model.ResultListDataRepresentation;
|
||||||
import com.inteligr8.alfresco.activiti.model.Tenant;
|
import com.inteligr8.alfresco.activiti.model.Tenant;
|
||||||
|
import com.inteligr8.maven.aps.modeling.crawler.ApsAppCrawlable;
|
||||||
|
import com.inteligr8.maven.aps.modeling.crawler.ApsFileTransformer;
|
||||||
|
import com.inteligr8.maven.aps.modeling.util.Index;
|
||||||
|
|
||||||
public class ApsAppTranslator {
|
public class ApsAppTranslator implements ApsAppCrawlable {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(ApsAppTranslator.class);
|
private final Logger logger = LoggerFactory.getLogger(ApsAppTranslator.class);
|
||||||
private final Pattern filenamePattern = Pattern.compile("([^/]+)-([0-9]+)\\.(json|bpmn20\\.xml)");
|
private final Pattern filenamePattern = Pattern.compile("([^/]+)-([0-9]+)\\.(json|bpmn20\\.xml)");
|
||||||
private final ApsPublicRestApiJerseyImpl api;
|
private final ApsPublicRestApi api;
|
||||||
private final String appName;
|
|
||||||
private final File appDirectory;
|
private final File appDirectory;
|
||||||
private final File appDescriptor;
|
|
||||||
private final boolean failOnIntegrityViolation;
|
|
||||||
|
|
||||||
private Map<String, Group> apsOrgIndex;
|
private boolean indexesBuilt = false;
|
||||||
|
private Map<String, GroupLight> apsOrgIndex;
|
||||||
private Index<Long, String> apsFormIndex;
|
private Index<Long, String> apsFormIndex;
|
||||||
private Index<Long, String> apsProcessIndex;
|
private Index<Long, String> apsProcessIndex;
|
||||||
private Index<Long, String> fileFormIndex;
|
private Index<Long, String> fileFormIndex;
|
||||||
private Index<Long, String> fileProcessIndex;
|
private Index<Long, String> fileProcessIndex;
|
||||||
private Index<Long, String> fileSubprocessIndex;
|
private Index<Long, String> fileSubprocessIndex;
|
||||||
|
|
||||||
public ApsAppTranslator(String apsAppName, File apsAppDirectory, ApsPublicRestApiJerseyImpl api, boolean failOnIntegrityViolation) {
|
public ApsAppTranslator(File apsAppDirectory, ApsPublicRestApiJerseyImpl api) {
|
||||||
this.api = api;
|
this.api = api;
|
||||||
this.appName = apsAppName;
|
|
||||||
this.appDirectory = apsAppDirectory;
|
this.appDirectory = apsAppDirectory;
|
||||||
this.failOnIntegrityViolation = failOnIntegrityViolation;
|
|
||||||
|
|
||||||
this.appDescriptor = this.validateDescriptor(appDirectory);
|
|
||||||
if (this.logger.isDebugEnabled())
|
|
||||||
this.logger.debug("APS App descriptor found: " + this.appDescriptor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected File validateDescriptor(File appDirectory) {
|
public synchronized void buildIndexes() throws IOException {
|
||||||
File appDescriptor = new File(appDirectory, this.appName + ".json");
|
if (this.indexesBuilt)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!appDescriptor.exists())
|
|
||||||
throw new IllegalStateException("The APS App descriptor could not be found: " + appDescriptor);
|
|
||||||
if (!appDescriptor.isFile())
|
|
||||||
throw new IllegalStateException("The APS App descriptor is not a file: " + appDescriptor);
|
|
||||||
|
|
||||||
return appDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void execute() throws IOException {
|
|
||||||
this.buildIndexes();
|
|
||||||
this.translate();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void buildIndexes() throws IOException {
|
|
||||||
this.logger.info("Building indexes ...");
|
this.logger.info("Building indexes ...");
|
||||||
|
|
||||||
long tenantId = this.findTenantId();
|
long tenantId = this.findTenantId();
|
||||||
this.logger.debug("APS App tenant ID: {}", tenantId);
|
this.logger.debug("APS App tenant ID: {}", tenantId);
|
||||||
|
|
||||||
this.apsOrgIndex = this.buildApsGroupMap(tenantId);
|
this.apsOrgIndex = this.buildApsGroupMap(tenantId);
|
||||||
this.logger.debug("APS App organizations: {}", this.apsOrgIndex);
|
this.logLarge("APS App organizations: {}", this.apsOrgIndex);
|
||||||
|
|
||||||
this.apsProcessIndex = this.buildApsModelIndex(ModelType.Process);
|
this.apsProcessIndex = this.buildApsModelIndex(ModelType.Process);
|
||||||
this.logger.debug("APS process models: {}", this.apsProcessIndex);
|
this.logLarge("APS process models: {}", this.apsProcessIndex);
|
||||||
|
|
||||||
this.apsFormIndex = this.buildApsModelIndex(ModelType.Form);
|
this.apsFormIndex = this.buildApsModelIndex(ModelType.Form);
|
||||||
this.logger.debug("APS form models: {}", this.apsFormIndex);
|
this.logLarge("APS form models: {}", this.apsFormIndex);
|
||||||
|
|
||||||
this.fileFormIndex = this.buildFileIndex("form-models", this.apsFormIndex, true);
|
this.fileFormIndex = this.buildFileIndex("form-models", this.apsFormIndex, true);
|
||||||
this.logger.debug("File form models: {}", this.fileFormIndex);
|
this.logLarge("File form models: {}", this.fileFormIndex);
|
||||||
|
|
||||||
this.fileProcessIndex = this.buildFileIndex("bpmn-models", this.apsProcessIndex, true);
|
this.fileProcessIndex = this.buildFileIndex("bpmn-models", this.apsProcessIndex, true);
|
||||||
this.logger.debug("File process models: {}", this.fileProcessIndex);
|
this.logLarge("File process models: {}", this.fileProcessIndex);
|
||||||
|
|
||||||
this.fileSubprocessIndex = this.buildFileIndex("bpmn-subprocess-models", this.apsProcessIndex, true);
|
this.fileSubprocessIndex = this.buildFileIndex("bpmn-subprocess-models", this.apsProcessIndex, true);
|
||||||
this.logger.debug("File subprocess models: {}", this.fileSubprocessIndex);
|
this.logLarge("File subprocess models: {}", this.fileSubprocessIndex);
|
||||||
|
|
||||||
|
this.indexesBuilt = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void translate() throws IOException {
|
private <K, V> void logLarge(String message, Map<K, V> map) {
|
||||||
this.logger.info("Translating models ...");
|
if (this.logger.isTraceEnabled()) {
|
||||||
|
this.logger.trace(message, map);
|
||||||
|
} else {
|
||||||
|
this.logger.debug(message, map.keySet());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 getAppJsonTransformer() {
|
||||||
|
if (!this.indexesBuilt)
|
||||||
|
throw new IllegalStateException("The indexes are never built");
|
||||||
|
|
||||||
ApsFileTranslator descriptorTranslator = new ApsAppJsonTranslator(
|
return new ApsAppJsonTranslator(
|
||||||
|
this.api,
|
||||||
this.apsOrgIndex,
|
this.apsOrgIndex,
|
||||||
this.apsProcessIndex,
|
this.apsProcessIndex,
|
||||||
this.fileProcessIndex);
|
this.fileProcessIndex);
|
||||||
ApsFileTranslator formTranslator = new ApsFormJsonTranslator(
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApsFileTransformer getFormJsonTransformer() {
|
||||||
|
if (!this.indexesBuilt)
|
||||||
|
throw new IllegalStateException("The indexes are never built");
|
||||||
|
|
||||||
|
return new ApsFormJsonTranslator(
|
||||||
this.apsFormIndex);
|
this.apsFormIndex);
|
||||||
ApsFileTranslator processTranslator = new ApsProcessJsonTranslator(
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApsFileTransformer getProcessJsonTransformer() {
|
||||||
|
if (!this.indexesBuilt)
|
||||||
|
throw new IllegalStateException("The indexes are never built");
|
||||||
|
|
||||||
|
return new ApsProcessJsonTranslator(
|
||||||
|
this.api,
|
||||||
this.apsProcessIndex,
|
this.apsProcessIndex,
|
||||||
this.apsOrgIndex,
|
this.apsOrgIndex,
|
||||||
this.apsFormIndex);
|
this.apsFormIndex);
|
||||||
ApsFileTranslator bpmnTranslator = new ApsProcessBpmnTranslator(
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApsFileTransformer getProcessBpmnTransformer() {
|
||||||
|
if (!this.indexesBuilt)
|
||||||
|
throw new IllegalStateException("The indexes are never built");
|
||||||
|
|
||||||
|
return new ApsProcessBpmnTranslator(
|
||||||
|
this.api,
|
||||||
this.apsProcessIndex,
|
this.apsProcessIndex,
|
||||||
this.apsOrgIndex,
|
this.apsOrgIndex,
|
||||||
this.apsFormIndex,
|
this.apsFormIndex,
|
||||||
this.fileFormIndex);
|
this.fileFormIndex);
|
||||||
|
|
||||||
Map<String, ApsFileTranslator> processTranslators = new HashMap<>();
|
|
||||||
processTranslators.put("json", processTranslator);
|
|
||||||
processTranslators.put("bpmn20.xml", bpmnTranslator);
|
|
||||||
processTranslators.put("bpmn", bpmnTranslator);
|
|
||||||
|
|
||||||
this.translate(descriptorTranslator, this.appDescriptor, this.appName, null);
|
|
||||||
this.translateModels("form-models", formTranslator);
|
|
||||||
this.translateModels("bpmn-models", processTranslators);
|
|
||||||
this.translateModels("bpmn-subprocess-models", processTranslator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Long findTenantId() {
|
protected Long findTenantId() {
|
||||||
@@ -124,17 +140,18 @@ public class ApsAppTranslator {
|
|||||||
return (tenants == null || tenants.isEmpty()) ? null : tenants.iterator().next().getId();
|
return (tenants == null || tenants.isEmpty()) ? null : tenants.iterator().next().getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Map<String, Group> buildApsGroupMap(long tenantId) {
|
protected Map<String, GroupLight> buildApsGroupMap(long tenantId) {
|
||||||
List<Group> groups = this.api.getAdminApi().getGroups(tenantId, true, true);
|
List<GroupLight> groups = this.api.getAdminApi().getGroups(tenantId, true, true);
|
||||||
|
|
||||||
Map<String, Group> map = new HashMap<>(groups.size());
|
Map<String, GroupLight> map = new HashMap<>(groups.size());
|
||||||
for (Group group : groups)
|
for (GroupLight group : groups)
|
||||||
map.put(group.getName(), group);
|
map.put(group.getName(), group);
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Index<Long, String> buildApsModelIndex(ModelType modelType) {
|
protected Index<Long, String> buildApsModelIndex(ModelType modelType) {
|
||||||
ResultListDataRepresentation results = this.api.getModelsApi().get(null, null, modelType.getId(), null);
|
ResultListDataRepresentation results = this.api.getModelsApi().get("everyone", null, modelType.getId(), null);
|
||||||
|
this.logger.debug("APS {} models found: {} out of {}", modelType, results.getSize(), results.getTotal());
|
||||||
|
|
||||||
Index<Long, String> map = new Index<>(results.getSize().intValue(), false);
|
Index<Long, String> map = new Index<>(results.getSize().intValue(), false);
|
||||||
|
|
||||||
@@ -143,11 +160,13 @@ public class ApsAppTranslator {
|
|||||||
Number defId = (Number)datum.getAdditionalProperties().get("id");
|
Number defId = (Number)datum.getAdditionalProperties().get("id");
|
||||||
String defName = (String)datum.getAdditionalProperties().get("name");
|
String defName = (String)datum.getAdditionalProperties().get("name");
|
||||||
map.put(defId.longValue(), defName);
|
map.put(defId.longValue(), defName);
|
||||||
|
|
||||||
|
// FIXME add paging support
|
||||||
}
|
}
|
||||||
} catch (IllegalArgumentException iae) {
|
} catch (IllegalArgumentException iae) {
|
||||||
throw new IllegalStateException("This goal does not support the current state of APS", iae);
|
throw new IllegalStateException("This goal does not support the current state of APS", iae);
|
||||||
}
|
}
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,77 +176,50 @@ public class ApsAppTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected Index<Long, String> buildFileIndex(File modelDirectory, Index<Long, String> apsModelIndex, boolean renameFiles) {
|
protected Index<Long, String> buildFileIndex(File modelDirectory, Index<Long, String> apsModelIndex, boolean renameFiles) {
|
||||||
if (!modelDirectory.exists())
|
if (!modelDirectory.exists()) {
|
||||||
|
this.logger.debug("APS model directory doesn't exist; creating empty index: {}", modelDirectory);
|
||||||
return new Index<>(0, false);
|
return new Index<>(0, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (!modelDirectory.isDirectory())
|
if (!modelDirectory.isDirectory())
|
||||||
throw new IllegalStateException("The APS model directory is actually a file: " + modelDirectory);
|
throw new IllegalStateException("The APS model directory is actually a file: " + modelDirectory);
|
||||||
|
|
||||||
Index<Long, String> fileModelIndex = new Index<>(apsModelIndex.size(), false);
|
Index<Long, String> fileModelIndex = new Index<>(apsModelIndex.size(), false);
|
||||||
|
|
||||||
for (File modelFile : modelDirectory.listFiles()) {
|
for (File modelFile : modelDirectory.listFiles()) {
|
||||||
|
this.logger.trace("Building index for model file: {}", modelFile);
|
||||||
|
|
||||||
Matcher matcher = this.filenamePattern.matcher(modelFile.getName());
|
Matcher matcher = this.filenamePattern.matcher(modelFile.getName());
|
||||||
String modelName = matcher.replaceFirst("$1");
|
String modelName = matcher.replaceFirst("$1");
|
||||||
String modelIdStr = matcher.replaceFirst("$2");
|
String modelIdStr = matcher.replaceFirst("$2");
|
||||||
String modelExt = matcher.replaceFirst("$3");
|
String modelExt = matcher.replaceFirst("$3");
|
||||||
long fileModelId = Long.parseLong(modelIdStr);
|
long fileModelId = Long.parseLong(modelIdStr);
|
||||||
|
this.logger.trace("Building index for model {} ID: {}", modelName, fileModelId);
|
||||||
|
|
||||||
fileModelIndex.put(fileModelId, modelName);
|
fileModelIndex.put(fileModelId, modelName);
|
||||||
|
|
||||||
Set<Long> apsModelIds = apsModelIndex.getKeys(modelName);
|
Set<Long> apsModelIds = apsModelIndex.getKeys(modelName);
|
||||||
|
if (apsModelIds == null || apsModelIds.isEmpty()) {
|
||||||
|
this.logger.debug("The model file '{}' has no corresponding model in APS; treating as new", modelFile.getName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (apsModelIds.size() > 1)
|
if (apsModelIds.size() > 1)
|
||||||
throw new IllegalStateException("An APS " + modelDirectory.getName() + " name was used multiple times: " + modelName);
|
throw new IllegalStateException("An APS " + modelDirectory.getName() + " name was used multiple times: " + modelName);
|
||||||
|
|
||||||
if (renameFiles && !apsModelIds.isEmpty()) {
|
if (renameFiles) {
|
||||||
Long apsModelId = apsModelIds.iterator().next();
|
Long apsModelId = apsModelIds.iterator().next();
|
||||||
if (apsModelId != fileModelId) {
|
if (apsModelId != fileModelId) {
|
||||||
this.logger.debug("Renaming form model from '" + modelFile.getName() + "' to match APS form ID: " + apsModelId);
|
this.logger.debug("Renaming form model from '" + modelFile.getName() + "' to match APS form ID: " + apsModelId);
|
||||||
File newModelFile = new File(modelFile.getParentFile(), modelName + "-" + apsModelId + "." + modelExt);
|
File newModelFile = new File(modelFile.getParentFile(), modelName + "-" + apsModelId + "." + modelExt);
|
||||||
modelFile.renameTo(newModelFile);
|
modelFile.renameTo(newModelFile);
|
||||||
} else {
|
} else {
|
||||||
this.logger.debug("The APS model '{}' and corresponding model file have matching IDs", modelName);
|
this.logger.debug("The APS model '{}' and corresponding model file '{}' have matching IDs", modelName, modelFile.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fileModelIndex;
|
return fileModelIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void translateModels(String modelsDirectoryName, ApsFileTranslator translator) throws IOException {
|
|
||||||
this.translateModels(modelsDirectoryName, Collections.singletonMap("json", translator));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void translateModels(String modelsDirectoryName, Map<String, ApsFileTranslator> translators) throws IOException {
|
|
||||||
File modelsDirectory = new File(this.appDirectory, modelsDirectoryName);
|
|
||||||
for (File modelFile : modelsDirectory.listFiles()) {
|
|
||||||
Matcher matcher = this.filenamePattern.matcher(modelFile.getName());
|
|
||||||
if (!matcher.find()) {
|
|
||||||
this.logger.warn("The '{}' folder has a file with an unexpected filename format; skipping: {}", modelsDirectoryName, modelFile);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
String ext = matcher.group(3);
|
|
||||||
ApsFileTranslator translator = translators.get(ext.toLowerCase());
|
|
||||||
if (translator == null) {
|
|
||||||
this.logger.warn("The '{}' folder has a file with an unexpected extension; skipping: {}", modelsDirectoryName, modelFile);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
String modelName = matcher.group(1);
|
|
||||||
Long modelId = new Long(matcher.group(2));
|
|
||||||
this.translate(translator, modelFile, modelName, modelId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void translate(ApsFileTranslator translator, File modelFile, String modelName, Long modelId) throws IOException {
|
|
||||||
try {
|
|
||||||
translator.translateFile(modelFile, modelName, modelId);
|
|
||||||
} catch (IllegalArgumentException | IllegalStateException ie) {
|
|
||||||
if (this.failOnIntegrityViolation) {
|
|
||||||
throw ie;
|
|
||||||
} else {
|
|
||||||
this.logger.warn(ie.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@@ -0,0 +1,17 @@
|
|||||||
|
package com.inteligr8.maven.aps.modeling.translator;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import com.inteligr8.maven.aps.modeling.crawler.ApsFileTransformer;
|
||||||
|
|
||||||
|
public interface ApsFileTranslator extends ApsFileTransformer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void transformFile(File file, String modelName, Long modelId) throws IOException {
|
||||||
|
this.translateFile(file, modelName, modelId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void translateFile(File file, String modelName, Long modelId) throws IOException;
|
||||||
|
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.maven.aps.modeling;
|
package com.inteligr8.maven.aps.modeling.translator;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -8,6 +8,8 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import com.inteligr8.maven.aps.modeling.util.Index;
|
||||||
|
import com.inteligr8.maven.aps.modeling.util.ModelUtil;
|
||||||
|
|
||||||
public class ApsFormJsonTranslator implements ApsFileTranslator {
|
public class ApsFormJsonTranslator implements ApsFileTranslator {
|
||||||
|
|
||||||
@@ -44,7 +46,7 @@ public class ApsFormJsonTranslator implements ApsFileTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
ModelUtil.getInstance().writeJson(jsonDescriptor, file);
|
ModelUtil.getInstance().writeJson(jsonDescriptor, file, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -0,0 +1,35 @@
|
|||||||
|
package com.inteligr8.maven.aps.modeling.translator;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.inteligr8.alfresco.activiti.ApsPublicRestApi;
|
||||||
|
import com.inteligr8.alfresco.activiti.model.Group;
|
||||||
|
import com.inteligr8.alfresco.activiti.model.GroupLight;
|
||||||
|
|
||||||
|
public class ApsOrganizationHandler {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(ApsOrganizationHandler.class);
|
||||||
|
private final ApsPublicRestApi api;
|
||||||
|
private final Map<String, GroupLight> apsOrgIndex;
|
||||||
|
|
||||||
|
public ApsOrganizationHandler(
|
||||||
|
ApsPublicRestApi api,
|
||||||
|
Map<String, GroupLight> apsOrgIndex) {
|
||||||
|
this.api = api;
|
||||||
|
this.apsOrgIndex = apsOrgIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected long createOrganization(String groupName) {
|
||||||
|
this.logger.info("Creating organization '{}' in APS", groupName);
|
||||||
|
|
||||||
|
GroupLight group = this.api.getAdminApi().createGroup(new Group()
|
||||||
|
.withName(groupName)
|
||||||
|
.withType(1L)); // an organization, not capability
|
||||||
|
this.apsOrgIndex.put(groupName, group);
|
||||||
|
return group.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.maven.aps.modeling;
|
package com.inteligr8.maven.aps.modeling.translator;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -16,34 +16,38 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.w3c.dom.Attr;
|
import org.w3c.dom.Attr;
|
||||||
import org.w3c.dom.CDATASection;
|
import org.w3c.dom.CharacterData;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
import com.inteligr8.alfresco.activiti.model.Group;
|
import com.inteligr8.alfresco.activiti.ApsPublicRestApi;
|
||||||
|
import com.inteligr8.alfresco.activiti.model.GroupLight;
|
||||||
|
import com.inteligr8.maven.aps.modeling.util.Index;
|
||||||
|
import com.inteligr8.maven.aps.modeling.util.ModelUtil;
|
||||||
|
|
||||||
public class ApsProcessBpmnTranslator implements ApsFileTranslator {
|
public class ApsProcessBpmnTranslator extends ApsOrganizationHandler implements ApsFileTranslator {
|
||||||
|
|
||||||
private static final String NAMESPACE_ACTIVITI = "http://activiti.org/bpmn";
|
private static final String NAMESPACE_ACTIVITI = "http://activiti.org/bpmn";
|
||||||
private static final String NAMESPACE_ACTIVITI_MODELER = "http://activiti.com/modeler";
|
private static final String NAMESPACE_ACTIVITI_MODELER = "http://activiti.com/modeler";
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(ApsProcessBpmnTranslator.class);
|
private final Logger logger = LoggerFactory.getLogger(ApsProcessBpmnTranslator.class);
|
||||||
private final Index<Long, String> apsIndex;
|
private final Index<Long, String> apsIndex;
|
||||||
private final Map<String, Group> apsOrgIndex;
|
private final Map<String, GroupLight> apsOrgIndex;
|
||||||
private final Index<Long, String> apsFormIndex;
|
private final Index<Long, String> apsFormIndex;
|
||||||
private final Index<Long, String> fileFormIndex;
|
private final Index<Long, String> fileFormIndex;
|
||||||
|
|
||||||
public ApsProcessBpmnTranslator(
|
public ApsProcessBpmnTranslator(
|
||||||
|
ApsPublicRestApi api,
|
||||||
Index<Long, String> apsProcessIndex,
|
Index<Long, String> apsProcessIndex,
|
||||||
Map<String, Group> apsOrgIndex,
|
Map<String, GroupLight> apsOrgIndex,
|
||||||
Index<Long, String> apsFormIndex,
|
Index<Long, String> apsFormIndex,
|
||||||
Index<Long, String> fileFormIndex) {
|
Index<Long, String> fileFormIndex) {
|
||||||
|
super(api, apsOrgIndex);
|
||||||
this.apsIndex = apsProcessIndex;
|
this.apsIndex = apsProcessIndex;
|
||||||
this.apsOrgIndex = apsOrgIndex;
|
this.apsOrgIndex = apsOrgIndex;
|
||||||
this.apsFormIndex = apsFormIndex;
|
this.apsFormIndex = apsFormIndex;
|
||||||
|
|
||||||
this.fileFormIndex = fileFormIndex;
|
this.fileFormIndex = fileFormIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +76,7 @@ public class ApsProcessBpmnTranslator implements ApsFileTranslator {
|
|||||||
changed = this.translateTaskForm(formKeyElement) || changed;
|
changed = this.translateTaskForm(formKeyElement) || changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeList subprocessElements = ModelUtil.getInstance().xpath(definitionsElement, "//subProcess");
|
NodeList subprocessElements = ModelUtil.getInstance().xpath(definitionsElement, "//tns:subProcess");
|
||||||
for (int n = 0; n < subprocessElements.getLength(); n++) {
|
for (int n = 0; n < subprocessElements.getLength(); n++) {
|
||||||
Element subprocessElement = (Element)subprocessElements.item(n);
|
Element subprocessElement = (Element)subprocessElements.item(n);
|
||||||
changed = this.translateSubprocess(subprocessElement) || changed;
|
changed = this.translateSubprocess(subprocessElement) || changed;
|
||||||
@@ -84,9 +88,9 @@ public class ApsProcessBpmnTranslator implements ApsFileTranslator {
|
|||||||
changed = this.translateConditionDefinition(conditionDefinitionElement) || changed;
|
changed = this.translateConditionDefinition(conditionDefinitionElement) || changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeList conditionExpressions = ModelUtil.getInstance().xpath(definitionsElement, "//conditionExpression/text()");
|
NodeList conditionExpressions = ModelUtil.getInstance().xpath(definitionsElement, "//tns:conditionExpression/text()");
|
||||||
for (int n = 0; n < conditionExpressions.getLength(); n++) {
|
for (int n = 0; n < conditionExpressions.getLength(); n++) {
|
||||||
CDATASection conditionExpression = (CDATASection)conditionExpressions.item(n);
|
CharacterData conditionExpression = (CharacterData)conditionExpressions.item(n);
|
||||||
changed = this.translateConditionExpression(conditionExpression) || changed;
|
changed = this.translateConditionExpression(conditionExpression) || changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,10 +104,10 @@ public class ApsProcessBpmnTranslator implements ApsFileTranslator {
|
|||||||
private boolean translateRootElement(Element definitionsElement, Long apsProcessId) {
|
private boolean translateRootElement(Element definitionsElement, Long apsProcessId) {
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
|
|
||||||
changed = this.setAttributeIfSet(definitionsElement, NAMESPACE_ACTIVITI_MODELER, "modelId", apsProcessId) || changed;
|
if (apsProcessId != null)
|
||||||
|
changed = this.setAttributeIfSet(definitionsElement, NAMESPACE_ACTIVITI_MODELER, "modelId", apsProcessId) || changed;
|
||||||
changed = this.removeAttributeIfSet(definitionsElement, NAMESPACE_ACTIVITI_MODELER, "modelVersion") || changed;
|
changed = this.removeAttributeIfSet(definitionsElement, NAMESPACE_ACTIVITI_MODELER, "modelVersion") || changed;
|
||||||
changed = this.removeAttributeIfSet(definitionsElement, NAMESPACE_ACTIVITI_MODELER, "exportDateTime") || changed;
|
//changed = this.setAttributeIfSet(definitionsElement, NAMESPACE_ACTIVITI_MODELER, "modelVersion", "0") || changed;
|
||||||
changed = this.removeAttributeIfSet(definitionsElement, NAMESPACE_ACTIVITI_MODELER, "modelLastUpdated") || changed;
|
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
@@ -139,22 +143,26 @@ public class ApsProcessBpmnTranslator implements ApsFileTranslator {
|
|||||||
String groupName = groupNameElement.getTextContent().trim();
|
String groupName = groupNameElement.getTextContent().trim();
|
||||||
this.logger.trace("Found '{}' candidate group in the APS Process BPMN model", groupName);
|
this.logger.trace("Found '{}' candidate group in the APS Process BPMN model", groupName);
|
||||||
|
|
||||||
if (this.apsOrgIndex.containsKey(groupName)) {
|
GroupLight apsOrg = this.apsOrgIndex.get(groupName);
|
||||||
long apsOrgId = this.apsOrgIndex.get(groupName).getId();
|
long apsOrgId = 0L;
|
||||||
groupIdsList.add(apsOrgId);
|
if (apsOrg == null) {
|
||||||
|
this.logger.debug("The organization '{}' does not exist in APS; creating it ...", groupName);
|
||||||
if (apsOrgId != orgId) {
|
apsOrgId = this.createOrganization(groupName);
|
||||||
this.logger.debug("The organization '{}' exists in APS with ID {}; changing model", groupName, apsOrgId);
|
|
||||||
groupNameElement = (Element)groupNameElement.getOwnerDocument().renameNode(groupNameElement,
|
|
||||||
groupNameElement.getNamespaceURI(), "group-info-name-" + apsOrgId);
|
|
||||||
changed = true;
|
|
||||||
} else {
|
|
||||||
this.logger.trace("The organization '{}' ID does not change; leaving unchanged", groupName);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// FIXME automatically add the group?
|
apsOrgId = apsOrg.getId();
|
||||||
this.logger.debug("The organization '{}' does not exist in APS; leaving unchanged", groupName);
|
}
|
||||||
groupIdsList.add(orgId);
|
|
||||||
|
if (apsOrgId != orgId) {
|
||||||
|
this.logger.debug("The organization '{}' exists in APS with ID {}; changing model", groupName, apsOrgId);
|
||||||
|
groupNameElement = (Element)groupNameElement.getOwnerDocument().renameNode(groupNameElement,
|
||||||
|
groupNameElement.getNamespaceURI(), "modeler:group-info-name-" + apsOrgId);
|
||||||
|
|
||||||
|
groupIdsList.add(apsOrgId);
|
||||||
|
changed = true;
|
||||||
|
} else {
|
||||||
|
this.logger.trace("The organization '{}' ID does not change; leaving unchanged", groupName);
|
||||||
|
|
||||||
|
groupIdsList.add(apsOrgId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,17 +206,17 @@ public class ApsProcessBpmnTranslator implements ApsFileTranslator {
|
|||||||
this.logger.trace("The form '{}' key does not change; leaving unchanged", formRefName);
|
this.logger.trace("The form '{}' key does not change; leaving unchanged", formRefName);
|
||||||
}
|
}
|
||||||
|
|
||||||
CDATAFlexSection formRefIdData = (CDATAFlexSection)ModelUtil.getInstance().xpath(
|
CharacterData formRefIdData = (CharacterData)ModelUtil.getInstance().xpath(
|
||||||
taskElement,
|
taskElement,
|
||||||
"tns:extensionElements/modeler:form-reference-id",
|
"tns:extensionElements/modeler:form-reference-id",
|
||||||
ModelUtil.CDATA_FLEX);
|
ModelUtil.CDATA_FLEX);
|
||||||
if (formRefIdData == null)
|
if (formRefIdData == null)
|
||||||
throw new IllegalStateException("A form was detected in the task, but no form reference ID was found: " + taskElement.getAttribute("id"));
|
throw new IllegalStateException("A form was detected in the task, but no form reference ID was found: " + taskElement.getAttribute("id"));
|
||||||
|
|
||||||
long formRefId = Long.parseLong(formRefIdData.getValue());
|
long formRefId = Long.parseLong(formRefIdData.getData());
|
||||||
if (apsFormId != formRefId) {
|
if (apsFormId != formRefId) {
|
||||||
this.logger.debug("The form '{}' reference exists in APS with ID {}; changing model", formRefName, apsFormId);
|
this.logger.debug("The form '{}' reference exists in APS with ID {}; changing model", formRefName, apsFormId);
|
||||||
formRefIdData.setValue(apsFormId.toString());
|
formRefIdData.setData(apsFormId.toString());
|
||||||
changed = true;
|
changed = true;
|
||||||
} else {
|
} else {
|
||||||
this.logger.trace("The form '{}' reference ID does not change; leaving unchanged", formRefName);
|
this.logger.trace("The form '{}' reference ID does not change; leaving unchanged", formRefName);
|
||||||
@@ -242,14 +250,14 @@ public class ApsProcessBpmnTranslator implements ApsFileTranslator {
|
|||||||
|
|
||||||
this.logger.trace("Found ID {} for the subprocess '{}' in the APS Process BPMN model", apsProcessId, subprocessName);
|
this.logger.trace("Found ID {} for the subprocess '{}' in the APS Process BPMN model", apsProcessId, subprocessName);
|
||||||
|
|
||||||
CDATAFlexSection subprocessIdData = (CDATAFlexSection)ModelUtil.getInstance().xpath(
|
CharacterData subprocessIdData = (CharacterData)ModelUtil.getInstance().xpath(
|
||||||
subprocessElement,
|
subprocessElement,
|
||||||
"tns:extensionElements/modeler:subprocess-id",
|
"tns:extensionElements/modeler:subprocess-id",
|
||||||
ModelUtil.CDATA_FLEX);
|
ModelUtil.CDATA_FLEX);
|
||||||
long subprocessId = Long.parseLong(subprocessIdData.getValue());
|
long subprocessId = Long.parseLong(subprocessIdData.getData());
|
||||||
if (apsProcessId != subprocessId) {
|
if (apsProcessId != subprocessId) {
|
||||||
this.logger.debug("The process '{}' exists in APS with ID {}; changing model", subprocessName, apsProcessId);
|
this.logger.debug("The process '{}' exists in APS with ID {}; changing model", subprocessName, apsProcessId);
|
||||||
subprocessIdData.setValue(apsProcessId.toString());
|
subprocessIdData.setData(apsProcessId.toString());
|
||||||
changed = true;
|
changed = true;
|
||||||
} else {
|
} else {
|
||||||
this.logger.trace("The process '{}' ID does not change; leaving unchanged", subprocessName);
|
this.logger.trace("The process '{}' ID does not change; leaving unchanged", subprocessName);
|
||||||
@@ -282,28 +290,42 @@ public class ApsProcessBpmnTranslator implements ApsFileTranslator {
|
|||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean translateConditionExpression(CDATASection conditionExpressionCdata) throws XPathExpressionException {
|
private boolean translateConditionExpression(CharacterData conditionExpressionCdata) throws XPathExpressionException {
|
||||||
this.logger.trace("Translating condition expression for outcome form elements: {}", conditionExpressionCdata.getParentNode().getParentNode().getAttributes().getNamedItem("id"));
|
this.logger.trace("Translating condition expression for outcome form elements: {}", conditionExpressionCdata.getParentNode().getParentNode().getAttributes().getNamedItem("id"));
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
|
|
||||||
String conditionExpression = conditionExpressionCdata.getData();
|
String conditionExpression = conditionExpressionCdata.getData();
|
||||||
Pattern formOutcomeInExpressionPattern = Pattern.compile("[^A-Za-z0-9]form([0-9]+)outcome[^A-Za-z0-9]");
|
StringBuilder newce = new StringBuilder();
|
||||||
|
int pos = 0;
|
||||||
|
|
||||||
|
Pattern formOutcomeInExpressionPattern = Pattern.compile("form([0-9]+)outcome");
|
||||||
Matcher matcher = formOutcomeInExpressionPattern.matcher(conditionExpression);
|
Matcher matcher = formOutcomeInExpressionPattern.matcher(conditionExpression);
|
||||||
while (matcher.find()) {
|
while (matcher.find()) {
|
||||||
|
newce.append(conditionExpression.substring(pos, matcher.start(1)));
|
||||||
|
|
||||||
long formId = Long.parseLong(matcher.group(1));
|
long formId = Long.parseLong(matcher.group(1));
|
||||||
String formName = this.fileFormIndex.getValue(formId);
|
String formName = this.fileFormIndex.getValue(formId);
|
||||||
if (formName == null) {
|
if (formName == null) {
|
||||||
this.logger.warn("The form ID '{}' does not exist in the form model files; ignoring", formId);
|
this.logger.warn("The form ID '{}' does not exist in the form model files; ignoring", formId);
|
||||||
|
newce.append(formId);
|
||||||
} else {
|
} else {
|
||||||
Long apsFormId = this.apsFormIndex.getFirstKey(formName);
|
Long apsFormId = this.apsFormIndex.getFirstKey(formName);
|
||||||
if (apsFormId == null) {
|
if (apsFormId == null) {
|
||||||
this.logger.warn("The form '{}' does not exist in APS; leaving unchanged", formName);
|
this.logger.warn("The form '{}' does not exist in APS; leaving unchanged", formName);
|
||||||
|
newce.append(formId);
|
||||||
} else {
|
} else {
|
||||||
conditionExpressionCdata.setData(apsFormId.toString());
|
newce.append(apsFormId);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pos = matcher.end(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newce.append(conditionExpression.substring(pos));
|
||||||
|
|
||||||
|
if (changed)
|
||||||
|
conditionExpressionCdata.setData(newce.toString());
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.maven.aps.modeling;
|
package com.inteligr8.maven.aps.modeling.translator;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -10,19 +10,24 @@ import org.slf4j.LoggerFactory;
|
|||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import com.inteligr8.alfresco.activiti.model.Group;
|
import com.inteligr8.alfresco.activiti.ApsPublicRestApi;
|
||||||
|
import com.inteligr8.alfresco.activiti.model.GroupLight;
|
||||||
|
import com.inteligr8.maven.aps.modeling.util.Index;
|
||||||
|
import com.inteligr8.maven.aps.modeling.util.ModelUtil;
|
||||||
|
|
||||||
public class ApsProcessJsonTranslator implements ApsFileTranslator {
|
public class ApsProcessJsonTranslator extends ApsOrganizationHandler implements ApsFileTranslator {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(ApsProcessJsonTranslator.class);
|
private final Logger logger = LoggerFactory.getLogger(ApsProcessJsonTranslator.class);
|
||||||
private final Index<Long, String> apsIndex;
|
private final Index<Long, String> apsIndex;
|
||||||
private final Map<String, Group> apsOrgIndex;
|
private final Map<String, GroupLight> apsOrgIndex;
|
||||||
private final Index<Long, String> apsFormIndex;
|
private final Index<Long, String> apsFormIndex;
|
||||||
|
|
||||||
public ApsProcessJsonTranslator(
|
public ApsProcessJsonTranslator(
|
||||||
|
ApsPublicRestApi api,
|
||||||
Index<Long, String> apsProcessIndex,
|
Index<Long, String> apsProcessIndex,
|
||||||
Map<String, Group> apsOrgIndex,
|
Map<String, GroupLight> apsOrgIndex,
|
||||||
Index<Long, String> apsFormIndex) {
|
Index<Long, String> apsFormIndex) {
|
||||||
|
super(api, apsOrgIndex);
|
||||||
this.apsIndex = apsProcessIndex;
|
this.apsIndex = apsProcessIndex;
|
||||||
this.apsOrgIndex = apsOrgIndex;
|
this.apsOrgIndex = apsOrgIndex;
|
||||||
this.apsFormIndex = apsFormIndex;
|
this.apsFormIndex = apsFormIndex;
|
||||||
@@ -43,17 +48,32 @@ public class ApsProcessJsonTranslator implements ApsFileTranslator {
|
|||||||
changed = this.translateSubprocesses(jsonDescriptor) || changed;
|
changed = this.translateSubprocesses(jsonDescriptor) || changed;
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
ModelUtil.getInstance().writeJson(jsonDescriptor, file);
|
ModelUtil.getInstance().writeJson(jsonDescriptor, file, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean translateResourceId(ObjectNode jsonDescriptor, Long apsProcessId) {
|
private boolean translateResourceId(ObjectNode jsonDescriptor, Long apsProcessId) {
|
||||||
|
if (apsProcessId == null) {
|
||||||
|
this.logger.trace("The process is not in APS; treating as new");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectNode resourceIdParentJson = jsonDescriptor;
|
||||||
|
|
||||||
JsonNode jsonResourceId = jsonDescriptor.get("resourceId");
|
JsonNode jsonResourceId = jsonDescriptor.get("resourceId");
|
||||||
|
if (jsonResourceId == null || jsonResourceId.isNull()) {
|
||||||
|
JsonNode jsonEditorJson = jsonDescriptor.get("editorJson");
|
||||||
|
if (jsonEditorJson != null && jsonEditorJson.isObject()) {
|
||||||
|
resourceIdParentJson = (ObjectNode)jsonEditorJson;
|
||||||
|
jsonResourceId = jsonEditorJson.get("resourceId");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (jsonResourceId == null || jsonResourceId.isNull()) {
|
if (jsonResourceId == null || jsonResourceId.isNull()) {
|
||||||
this.logger.trace("The process 'resourceId' is not defined; leaving unchanged", apsProcessId);
|
this.logger.trace("The process 'resourceId' is not defined; leaving unchanged", apsProcessId);
|
||||||
return false;
|
return false;
|
||||||
} else if (jsonResourceId.asLong() != apsProcessId) {
|
} else if (jsonResourceId.asLong() != apsProcessId) {
|
||||||
this.logger.debug("The process is found in APS with ID {}; changing 'resourceId' in descriptor", apsProcessId);
|
this.logger.debug("The process is found in APS with ID {}; changing 'resourceId' in descriptor", apsProcessId);
|
||||||
jsonDescriptor.put("resourceId", apsProcessId);
|
resourceIdParentJson.put("resourceId", apsProcessId);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
this.logger.trace("The process ID {} does not change; leaving unchanged", apsProcessId);
|
this.logger.trace("The process ID {} does not change; leaving unchanged", apsProcessId);
|
||||||
@@ -90,10 +110,16 @@ public class ApsProcessJsonTranslator implements ApsFileTranslator {
|
|||||||
|
|
||||||
if (this.apsOrgIndex.containsKey(fileOrgName)) {
|
if (this.apsOrgIndex.containsKey(fileOrgName)) {
|
||||||
long fileOrgId = jsonCandidateGroup.get("id").asLong();
|
long fileOrgId = jsonCandidateGroup.get("id").asLong();
|
||||||
long apsOrgId = this.apsOrgIndex.get(fileOrgName).getId();
|
GroupLight apsOrg = this.apsOrgIndex.get(fileOrgName);
|
||||||
if (apsOrgId != fileOrgId) {
|
|
||||||
this.logger.debug("The organization '{}' exists in APS with ID {}; changing descriptor", fileOrgName, apsOrgId);
|
if (apsOrg == null) {
|
||||||
jsonCandidateGroup.put("id", apsOrgId);
|
this.logger.debug("The organization '{}' does not exist in APS; adding to APS", fileOrgName);
|
||||||
|
long apsGroupId = this.createOrganization(fileOrgName);
|
||||||
|
jsonCandidateGroup.put("id", apsGroupId);
|
||||||
|
return true;
|
||||||
|
} else if (apsOrg.getId() != fileOrgId) {
|
||||||
|
this.logger.debug("The organization '{}' exists in APS with ID {}; changing descriptor", fileOrgName, apsOrg.getId());
|
||||||
|
jsonCandidateGroup.put("id", apsOrg.getId());
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
this.logger.trace("The organization '{}' ID does not change; leaving unchanged", fileOrgName);
|
this.logger.trace("The organization '{}' ID does not change; leaving unchanged", fileOrgName);
|
||||||
@@ -113,8 +139,8 @@ public class ApsProcessJsonTranslator implements ApsFileTranslator {
|
|||||||
|
|
||||||
for (JsonNode jsonChildShape : this.getChildShapes(jsonDescriptor)) {
|
for (JsonNode jsonChildShape : this.getChildShapes(jsonDescriptor)) {
|
||||||
try {
|
try {
|
||||||
JsonNode jsonConditionalSequenceFlow = (JsonNode)jsonChildShape.get("properties").get("conditionalsequenceflow");
|
JsonNode jsonConditionalSequenceFlow = (JsonNode)jsonChildShape.get("properties").get("conditionsequenceflow");
|
||||||
changed = this.translateConditionalSequenceFlow(jsonConditionalSequenceFlow) || changed;
|
changed = this.translateConditionSequenceFlow(jsonConditionalSequenceFlow) || changed;
|
||||||
|
|
||||||
JsonNode jsonFormRef = (JsonNode)jsonChildShape.get("properties").get("formreference");
|
JsonNode jsonFormRef = (JsonNode)jsonChildShape.get("properties").get("formreference");
|
||||||
changed = this.translateReference(jsonFormRef, this.apsFormIndex) || changed;
|
changed = this.translateReference(jsonFormRef, this.apsFormIndex) || changed;
|
||||||
@@ -126,7 +152,7 @@ public class ApsProcessJsonTranslator implements ApsFileTranslator {
|
|||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean translateConditionalSequenceFlow(JsonNode jsonConditionalSequenceFlow) {
|
private boolean translateConditionSequenceFlow(JsonNode jsonConditionalSequenceFlow) {
|
||||||
if (jsonConditionalSequenceFlow == null || !jsonConditionalSequenceFlow.isObject())
|
if (jsonConditionalSequenceFlow == null || !jsonConditionalSequenceFlow.isObject())
|
||||||
return false;
|
return false;
|
||||||
|
|
@@ -0,0 +1,22 @@
|
|||||||
|
package com.inteligr8.maven.aps.modeling.util;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
|
||||||
|
public class ApsModelArrayNodeSorter extends ArrayNodeObjectSorter {
|
||||||
|
|
||||||
|
private static ApsModelArrayNodeSorter INSTANCE = new ApsModelArrayNodeSorter();
|
||||||
|
|
||||||
|
public static ApsModelArrayNodeSorter getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected ApsModelArrayNodeSorter() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean sort(ArrayNode arrayNode, String jsonObjectFieldName) {
|
||||||
|
return this.sort(arrayNode, new ObjectNodeComparator(jsonObjectFieldName));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,23 @@
|
|||||||
|
package com.inteligr8.maven.aps.modeling.util;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ApsModelListMapSorter extends ListMapSorter<String, Object> {
|
||||||
|
|
||||||
|
private static ApsModelListMapSorter INSTANCE = new ApsModelListMapSorter();
|
||||||
|
|
||||||
|
public static ApsModelListMapSorter getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected ApsModelListMapSorter() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean sort(List<Map<String, Object>> jsonArrayAsMap, String jsonObjectFieldName) {
|
||||||
|
return this.sort(jsonArrayAsMap, new MapComparator<String, Object>(jsonObjectFieldName));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,82 @@
|
|||||||
|
package com.inteligr8.maven.aps.modeling.util;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
|
||||||
|
public class ArrayNodeObjectSorter {
|
||||||
|
|
||||||
|
private static ArrayNodeObjectSorter INSTANCE = new ArrayNodeObjectSorter();
|
||||||
|
|
||||||
|
public static ArrayNodeObjectSorter getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected ArrayNodeObjectSorter() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean sort(ArrayNode arrayNode, Comparator<JsonNode> comparator) {
|
||||||
|
if (arrayNode.isEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
boolean sorted = false;
|
||||||
|
boolean changed = false;
|
||||||
|
int index = 0;
|
||||||
|
JsonNode node = arrayNode.get(index);
|
||||||
|
|
||||||
|
// simple bubble sort
|
||||||
|
while (!sorted) {
|
||||||
|
sorted = true;
|
||||||
|
int nextIndex = index + 1;
|
||||||
|
|
||||||
|
// forward bubble
|
||||||
|
while (nextIndex < arrayNode.size()) {
|
||||||
|
JsonNode nextNode = arrayNode.get(nextIndex);
|
||||||
|
int c = comparator.compare(node, nextNode);
|
||||||
|
|
||||||
|
if (c == 0) {
|
||||||
|
node = nextNode;
|
||||||
|
} else if (c < 0) {
|
||||||
|
node = nextNode;
|
||||||
|
} else {
|
||||||
|
arrayNode.insert(index, arrayNode.remove(nextIndex));
|
||||||
|
sorted = false;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = nextIndex;
|
||||||
|
nextIndex = index + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sorted)
|
||||||
|
break;
|
||||||
|
sorted = true;
|
||||||
|
nextIndex = index - 1;
|
||||||
|
|
||||||
|
// reverse bubble
|
||||||
|
while (nextIndex >= 0) {
|
||||||
|
JsonNode nextNode = arrayNode.get(nextIndex);
|
||||||
|
int c = comparator.compare(nextNode, node);
|
||||||
|
|
||||||
|
if (c == 0) {
|
||||||
|
node = nextNode;
|
||||||
|
} else if (c < 0) {
|
||||||
|
node = nextNode;
|
||||||
|
} else {
|
||||||
|
arrayNode.insert(nextIndex, arrayNode.remove(index));
|
||||||
|
sorted = false;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = nextIndex;
|
||||||
|
nextIndex = index - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.maven.aps.modeling;
|
package com.inteligr8.maven.aps.modeling.util;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -33,6 +33,14 @@ public class Index<K, V> {
|
|||||||
return this.forwardMap.get(key);
|
return this.forwardMap.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<K> keySet() {
|
||||||
|
return this.forwardMap.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<V> valueSet() {
|
||||||
|
return this.reverseMap.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
public Set<K> getKeys(V value) {
|
public Set<K> getKeys(V value) {
|
||||||
return this.reverseMap.get(value);
|
return this.reverseMap.get(value);
|
||||||
}
|
}
|
@@ -0,0 +1,70 @@
|
|||||||
|
package com.inteligr8.maven.aps.modeling.util;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ListMapSorter<K, V> {
|
||||||
|
|
||||||
|
public boolean sort(List<Map<K, V>> listOfMaps, Comparator<Map<K, V>> comparator) {
|
||||||
|
if (listOfMaps.isEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
boolean sorted = false;
|
||||||
|
boolean changed = false;
|
||||||
|
int index = 0;
|
||||||
|
Map<K, V> map = listOfMaps.get(index);
|
||||||
|
|
||||||
|
// simple bubble sort
|
||||||
|
while (!sorted) {
|
||||||
|
sorted = true;
|
||||||
|
int nextIndex = index + 1;
|
||||||
|
|
||||||
|
// forward bubble
|
||||||
|
while (nextIndex < listOfMaps.size()) {
|
||||||
|
Map<K, V> nextMap = listOfMaps.get(nextIndex);
|
||||||
|
int c = comparator.compare(map, nextMap);
|
||||||
|
|
||||||
|
if (c == 0) {
|
||||||
|
map = nextMap;
|
||||||
|
} else if (c < 0) {
|
||||||
|
map = nextMap;
|
||||||
|
} else {
|
||||||
|
listOfMaps.add(index, listOfMaps.remove(nextIndex));
|
||||||
|
sorted = false;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = nextIndex;
|
||||||
|
nextIndex = index + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sorted)
|
||||||
|
break;
|
||||||
|
sorted = true;
|
||||||
|
nextIndex = index - 1;
|
||||||
|
|
||||||
|
// reverse bubble
|
||||||
|
while (nextIndex >= 0) {
|
||||||
|
Map<K, V> nextMap = listOfMaps.get(nextIndex);
|
||||||
|
int c = comparator.compare(nextMap, map);
|
||||||
|
|
||||||
|
if (c == 0) {
|
||||||
|
map = nextMap;
|
||||||
|
} else if (c < 0) {
|
||||||
|
map = nextMap;
|
||||||
|
} else {
|
||||||
|
listOfMaps.add(nextIndex, listOfMaps.remove(index));
|
||||||
|
sorted = false;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = nextIndex;
|
||||||
|
nextIndex = index - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,49 @@
|
|||||||
|
package com.inteligr8.maven.aps.modeling.util;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class MapComparator<K, V> implements Comparator<Map<K, V>> {
|
||||||
|
|
||||||
|
//private final Logger logger = LoggerFactory.getLogger(ArrayOfObjectNodeComparator.class);
|
||||||
|
private final List<K> keys;
|
||||||
|
|
||||||
|
public MapComparator(@SuppressWarnings("unchecked") K... keys) {
|
||||||
|
this(Arrays.asList(keys));
|
||||||
|
}
|
||||||
|
|
||||||
|
public MapComparator(List<K> keys) {
|
||||||
|
this.keys = keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(Map<K, V> m1, Map<K, V> m2) {
|
||||||
|
for (K key : keys) {
|
||||||
|
V value1 = m1.get(key);
|
||||||
|
V value2 = m2.get(key);
|
||||||
|
|
||||||
|
if (value1 == null && value2 == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (value1 == null)
|
||||||
|
return 1;
|
||||||
|
if (value2 == null)
|
||||||
|
return -1;
|
||||||
|
if (!value1.getClass().equals(value2.getClass()))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (value1 instanceof Boolean) {
|
||||||
|
return Boolean.compare((Boolean)value1, (Boolean)value2);
|
||||||
|
} if (value1 instanceof Number) {
|
||||||
|
return Double.compare(((Number)value1).doubleValue(), ((Number)value2).doubleValue());
|
||||||
|
} if (value1 instanceof String) {
|
||||||
|
return ((String)value1).compareTo((String)value2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.maven.aps.modeling;
|
package com.inteligr8.maven.aps.modeling.util;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
@@ -8,6 +8,8 @@ import java.io.FileOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.xml.namespace.QName;
|
import javax.xml.namespace.QName;
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
@@ -25,7 +27,7 @@ import javax.xml.xpath.XPathConstants;
|
|||||||
import javax.xml.xpath.XPathExpressionException;
|
import javax.xml.xpath.XPathExpressionException;
|
||||||
import javax.xml.xpath.XPathFactory;
|
import javax.xml.xpath.XPathFactory;
|
||||||
|
|
||||||
import org.w3c.dom.CDATASection;
|
import org.w3c.dom.CharacterData;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
import org.w3c.dom.Node;
|
import org.w3c.dom.Node;
|
||||||
@@ -36,10 +38,10 @@ import com.fasterxml.jackson.databind.JsonNode;
|
|||||||
import com.fasterxml.jackson.databind.MapperFeature;
|
import com.fasterxml.jackson.databind.MapperFeature;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
|
import com.inteligr8.maven.aps.modeling.xml.DomNamespaceContext;
|
||||||
|
|
||||||
public class ModelUtil {
|
public class ModelUtil {
|
||||||
|
|
||||||
public final static QName CDATA = QName.valueOf("inteligr8:xml:cdata");
|
|
||||||
public final static QName CDATA_FLEX = QName.valueOf("inteligr8:xml:cdata_or_element");
|
public final static QName CDATA_FLEX = QName.valueOf("inteligr8:xml:cdata_or_element");
|
||||||
private final static ModelUtil INSTANCE = new ModelUtil();
|
private final static ModelUtil INSTANCE = new ModelUtil();
|
||||||
|
|
||||||
@@ -50,6 +52,7 @@ public class ModelUtil {
|
|||||||
|
|
||||||
|
|
||||||
private final ObjectMapper om = new ObjectMapper();
|
private final ObjectMapper om = new ObjectMapper();
|
||||||
|
private final ObjectMapper omsorted = new ObjectMapper();
|
||||||
private final DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
|
private final DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
|
||||||
private final DocumentBuilder docBuilder;
|
private final DocumentBuilder docBuilder;
|
||||||
private final XPathFactory xpathfactory = XPathFactory.newInstance();
|
private final XPathFactory xpathfactory = XPathFactory.newInstance();
|
||||||
@@ -77,41 +80,28 @@ public class ModelUtil {
|
|||||||
|
|
||||||
// makes Git handling a whole lot better
|
// makes Git handling a whole lot better
|
||||||
this.om.enable(SerializationFeature.INDENT_OUTPUT);
|
this.om.enable(SerializationFeature.INDENT_OUTPUT);
|
||||||
// makes Git handling better between environment nuances
|
this.omsorted.enable(SerializationFeature.INDENT_OUTPUT);
|
||||||
this.om.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
|
|
||||||
this.om.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void json(File inplaceFile) throws IOException {
|
|
||||||
JsonNode json;
|
|
||||||
|
|
||||||
FileInputStream fistream = new FileInputStream(inplaceFile);
|
|
||||||
BufferedInputStream bistream = new BufferedInputStream(fistream, this.bufferSize);
|
|
||||||
try {
|
|
||||||
json = this.readJson(bistream);
|
|
||||||
} finally {
|
|
||||||
bistream.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
FileOutputStream fostream = new FileOutputStream(inplaceFile);
|
// makes Git handling better between environment nuances
|
||||||
BufferedOutputStream bostream = new BufferedOutputStream(fostream, this.bufferSize);
|
this.omsorted.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
|
||||||
try {
|
this.omsorted.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
|
||||||
this.writeJson(json, bostream);
|
|
||||||
} finally {
|
|
||||||
bostream.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void json(File sourceFile, File targetFile) throws IOException {
|
|
||||||
|
|
||||||
|
public void json(File inplaceFile, boolean enableSorting) throws IOException {
|
||||||
|
JsonNode json = this.readJson(inplaceFile);
|
||||||
|
this.writeJson(json, inplaceFile, enableSorting);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void json(File sourceFile, File targetFile, boolean enableSorting) throws IOException {
|
||||||
FileInputStream fistream = new FileInputStream(sourceFile);
|
FileInputStream fistream = new FileInputStream(sourceFile);
|
||||||
BufferedInputStream bistream = new BufferedInputStream(fistream, this.bufferSize);
|
BufferedInputStream bistream = new BufferedInputStream(fistream, this.bufferSize);
|
||||||
try {
|
try {
|
||||||
FileOutputStream fostream = new FileOutputStream(targetFile);
|
FileOutputStream fostream = new FileOutputStream(targetFile);
|
||||||
BufferedOutputStream bostream = new BufferedOutputStream(fostream, this.bufferSize);
|
BufferedOutputStream bostream = new BufferedOutputStream(fostream, this.bufferSize);
|
||||||
try {
|
try {
|
||||||
this.json(bistream, bostream);
|
this.json(bistream, bostream, enableSorting);
|
||||||
} finally {
|
} finally {
|
||||||
bostream.close();
|
bostream.close();
|
||||||
}
|
}
|
||||||
@@ -120,17 +110,17 @@ public class ModelUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void json(InputStream istream, OutputStream ostream) throws IOException {
|
public void json(InputStream istream, OutputStream ostream, boolean enableSorting) throws IOException {
|
||||||
// FIXME stream it for lower memory/IO usage
|
// FIXME stream it for lower memory/IO usage
|
||||||
JsonNode json = this.readJson(istream);
|
JsonNode json = this.readJson(istream);
|
||||||
this.writeJson(json, ostream);
|
this.writeJson(json, ostream, enableSorting);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JsonNode readJson(File file) throws IOException {
|
public JsonNode readJson(File file) throws IOException {
|
||||||
return this.readJson(file, JsonNode.class);
|
return this.readJson(file, JsonNode.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends JsonNode> T readJson(File file, Class<T> type) throws IOException {
|
public <T> T readJson(File file, Class<T> type) throws IOException {
|
||||||
FileInputStream fistream = new FileInputStream(file);
|
FileInputStream fistream = new FileInputStream(file);
|
||||||
BufferedInputStream bistream = new BufferedInputStream(fistream, this.bufferSize);
|
BufferedInputStream bistream = new BufferedInputStream(fistream, this.bufferSize);
|
||||||
try {
|
try {
|
||||||
@@ -140,26 +130,78 @@ public class ModelUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <T> List<T> readJsonAsList(File file) throws IOException {
|
||||||
|
FileInputStream fistream = new FileInputStream(file);
|
||||||
|
BufferedInputStream bistream = new BufferedInputStream(fistream, this.bufferSize);
|
||||||
|
try {
|
||||||
|
return this.readJsonAsList(bistream);
|
||||||
|
} finally {
|
||||||
|
bistream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> readJsonAsMap(File file) throws IOException {
|
||||||
|
FileInputStream fistream = new FileInputStream(file);
|
||||||
|
BufferedInputStream bistream = new BufferedInputStream(fistream, this.bufferSize);
|
||||||
|
try {
|
||||||
|
return this.readJsonAsMap(bistream);
|
||||||
|
} finally {
|
||||||
|
bistream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public JsonNode readJson(InputStream istream) throws IOException {
|
public JsonNode readJson(InputStream istream) throws IOException {
|
||||||
return this.om.readTree(istream);
|
return this.om.readTree(istream);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends JsonNode> T readJson(InputStream istream, Class<T> type) throws IOException {
|
public <T> T readJson(InputStream istream, Class<T> type) throws IOException {
|
||||||
return this.om.readValue(istream, type);
|
return this.om.readValue(istream, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeJson(JsonNode json, File file) throws IOException {
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> List<T> readJsonAsList(InputStream istream) throws IOException {
|
||||||
|
return this.om.readValue(istream, List.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Map<String, Object> readJsonAsMap(InputStream istream) throws IOException {
|
||||||
|
return this.om.readValue(istream, Map.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeJson(JsonNode json, File file, boolean enableSorting) throws IOException {
|
||||||
FileOutputStream fostream = new FileOutputStream(file);
|
FileOutputStream fostream = new FileOutputStream(file);
|
||||||
BufferedOutputStream bostream = new BufferedOutputStream(fostream, this.bufferSize);
|
BufferedOutputStream bostream = new BufferedOutputStream(fostream, this.bufferSize);
|
||||||
try {
|
try {
|
||||||
this.writeJson(json, bostream);
|
this.writeJson(json, bostream, enableSorting);
|
||||||
} finally {
|
} finally {
|
||||||
bostream.close();
|
bostream.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeJson(JsonNode json, OutputStream ostream) throws IOException {
|
public void writeJson(Map<String, Object> map, File file, boolean enableSorting) throws IOException {
|
||||||
this.om.writeValue(ostream, json);
|
FileOutputStream fostream = new FileOutputStream(file);
|
||||||
|
BufferedOutputStream bostream = new BufferedOutputStream(fostream, this.bufferSize);
|
||||||
|
try {
|
||||||
|
this.writeJson(map, bostream, enableSorting);
|
||||||
|
} finally {
|
||||||
|
bostream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeJson(JsonNode json, OutputStream ostream, boolean enableSorting) throws IOException {
|
||||||
|
if (enableSorting) {
|
||||||
|
this.omsorted.writeValue(ostream, json);
|
||||||
|
} else {
|
||||||
|
this.om.writeValue(ostream, json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeJson(Map<String, Object> map, OutputStream ostream, boolean enableSorting) throws IOException {
|
||||||
|
if (enableSorting) {
|
||||||
|
this.omsorted.writeValue(ostream, map);
|
||||||
|
} else {
|
||||||
|
this.om.writeValue(ostream, map);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -244,22 +286,23 @@ public class ModelUtil {
|
|||||||
XPath xpath = this.xpathfactory.newXPath();
|
XPath xpath = this.xpathfactory.newXPath();
|
||||||
xpath.setNamespaceContext(new DomNamespaceContext(node));
|
xpath.setNamespaceContext(new DomNamespaceContext(node));
|
||||||
|
|
||||||
boolean isFlex = returnType.equals(ModelUtil.CDATA_FLEX);
|
if (returnType.equals(ModelUtil.CDATA_FLEX)) {
|
||||||
|
|
||||||
if (returnType.equals(ModelUtil.CDATA) || isFlex) {
|
|
||||||
NodeList nodes = (NodeList)xpath.evaluate(xpathExpr, node, XPathConstants.NODESET);
|
NodeList nodes = (NodeList)xpath.evaluate(xpathExpr, node, XPathConstants.NODESET);
|
||||||
Node anode = this.getFirstCDataSectionOrLastElement(nodes);
|
Node anode = this.getFirstCDataSectionOrLastElement(nodes);
|
||||||
if (anode instanceof CDATASection) {
|
if (anode instanceof CharacterData) {
|
||||||
// nothing special
|
// nothing special
|
||||||
} else if (anode instanceof Element) {
|
} else if (anode instanceof Element) {
|
||||||
Node anode2 = this.getFirstCDataSectionOrLastElement(anode.getChildNodes());
|
Node anode2 = this.getFirstCDataSectionOrLastElement(anode.getChildNodes());
|
||||||
if (anode2 != null)
|
if (anode2 == null)
|
||||||
return anode = anode2;
|
return null;
|
||||||
|
if (!(anode2 instanceof CharacterData))
|
||||||
|
throw new IllegalStateException();
|
||||||
|
anode = anode2;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return isFlex ? new CDATAFlexSection(anode) : anode;
|
return anode;
|
||||||
} else {
|
} else {
|
||||||
return xpath.evaluate(xpathExpr, node, returnType);
|
return xpath.evaluate(xpathExpr, node, returnType);
|
||||||
}
|
}
|
||||||
@@ -270,8 +313,8 @@ public class ModelUtil {
|
|||||||
|
|
||||||
for (int n = 0; n < nodes.getLength(); n++) {
|
for (int n = 0; n < nodes.getLength(); n++) {
|
||||||
Node anode = nodes.item(n);
|
Node anode = nodes.item(n);
|
||||||
if (anode.getNodeType() == Node.CDATA_SECTION_NODE) {
|
if (anode instanceof CharacterData) {
|
||||||
return (CDATASection)anode;
|
return (CharacterData)anode;
|
||||||
} else if (anode.getNodeType() == Node.ELEMENT_NODE) {
|
} else if (anode.getNodeType() == Node.ELEMENT_NODE) {
|
||||||
element = (Element)anode;
|
element = (Element)anode;
|
||||||
}
|
}
|
@@ -0,0 +1,58 @@
|
|||||||
|
package com.inteligr8.maven.aps.modeling.util;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
|
||||||
|
public class ObjectNodeComparator implements Comparator<JsonNode> {
|
||||||
|
|
||||||
|
//private final Logger logger = LoggerFactory.getLogger(ArrayOfObjectNodeComparator.class);
|
||||||
|
private final List<String> objectFieldNames;
|
||||||
|
|
||||||
|
public ObjectNodeComparator(String... objectFieldNames) {
|
||||||
|
this(Arrays.asList(objectFieldNames));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectNodeComparator(List<String> objectFieldNames) {
|
||||||
|
this.objectFieldNames = objectFieldNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(JsonNode o1, JsonNode o2) {
|
||||||
|
if (!o1.isObject())
|
||||||
|
return -1;
|
||||||
|
if (!o2.isObject())
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
for (String objectFieldName : objectFieldNames) {
|
||||||
|
JsonNode value1 = o1.get(objectFieldName);
|
||||||
|
JsonNode value2 = o2.get(objectFieldName);
|
||||||
|
|
||||||
|
if (value1 == null && value2 == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (value1 == null)
|
||||||
|
return 1;
|
||||||
|
if (value2 == null)
|
||||||
|
return -1;
|
||||||
|
if (!value1.getNodeType().equals(value2.getNodeType()))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (value1.getNodeType()) {
|
||||||
|
case BOOLEAN:
|
||||||
|
return Boolean.compare(value1.asBoolean(), value2.asBoolean());
|
||||||
|
case NUMBER:
|
||||||
|
return Double.compare(value1.asDouble(), value2.asDouble());
|
||||||
|
case STRING:
|
||||||
|
return value1.asText().compareTo(value2.asText());
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
package com.inteligr8.maven.aps.modeling;
|
package com.inteligr8.maven.aps.modeling.xml;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
@@ -1,9 +1,14 @@
|
|||||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||||
<xsl:output indent="yes"/>
|
<xsl:output indent="yes" />
|
||||||
<xsl:strip-space elements="*"/>
|
<xsl:strip-space elements="*"/>
|
||||||
<xsl:template match="@*|node()">
|
<xsl:template match="@*|node()">
|
||||||
<xsl:copy>
|
<xsl:copy>
|
||||||
<xsl:apply-templates select="@*|node()"/>
|
<xsl:apply-templates select="@*|node()"/>
|
||||||
</xsl:copy>
|
</xsl:copy>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
<xsl:template match="text()">
|
||||||
|
<xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text>
|
||||||
|
<xsl:value-of select="." disable-output-escaping="yes" />
|
||||||
|
<xsl:text disable-output-escaping="yes">]]></xsl:text>
|
||||||
|
</xsl:template>
|
||||||
</xsl:stylesheet>
|
</xsl:stylesheet>
|
||||||
|
Reference in New Issue
Block a user