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>
|
||||
<artifactId>aps-model-maven-plugin</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>1.2.0</version>
|
||||
<packaging>maven-plugin</packaging>
|
||||
|
||||
<name>A Maven plugin for Alfresco Process Services model portability</name>
|
||||
@@ -34,36 +34,27 @@
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<maven.version>3.6.3</maven.version>
|
||||
|
||||
<jersey.version>2.34</jersey.version>
|
||||
<jersey.version>2.35</jersey.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.inteligr8.alfresco</groupId>
|
||||
<artifactId>aps-public-rest-api</artifactId>
|
||||
<version>1.2.0</version>
|
||||
<version>2.0.0</version>
|
||||
<classifier>aps1</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.inteligr8.alfresco</groupId>
|
||||
<artifactId>aps-public-rest-client</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<classifier>jersey</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.4</version>
|
||||
</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>
|
||||
<groupId>org.glassfish.jersey.inject</groupId>
|
||||
<artifactId>jersey-hk2</artifactId>
|
||||
@@ -161,8 +152,13 @@
|
||||
<localRepositoryPath>${project.build.directory}/it-repo</localRepositoryPath>
|
||||
<mavenHome>${env.MAVEN_HOME}</mavenHome>
|
||||
<debug>true</debug>
|
||||
<skipInvocation>${skipTests}</skipInvocation>
|
||||
<properties>
|
||||
<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>
|
||||
</configuration>
|
||||
<executions>
|
||||
@@ -184,6 +180,7 @@
|
||||
<goals><goal>jar</goal></goals>
|
||||
<configuration>
|
||||
<show>public</show>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
@@ -223,6 +220,14 @@
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>inteligr8-releases</id>
|
||||
<name>Inteligr8 Releases</name>
|
||||
<url>https://repos.inteligr8.com/nexus/repository/inteligr8-public</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
|
@@ -12,10 +12,6 @@
|
||||
|
||||
<name>Deploy App Plugin Tests</name>
|
||||
|
||||
<properties>
|
||||
<aps.app>FORMS Core</aps.app>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
@@ -24,14 +20,46 @@
|
||||
<version>@pom.version@</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>download-app</id>
|
||||
<phase>validate</phase>
|
||||
<id>download-unpack-app</id>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<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>
|
||||
</goals>
|
||||
<configuration>
|
||||
<apsAppName>${aps.app}</apsAppName>
|
||||
<zipDirectory>${project.build.directory}/aps-test</zipDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
|
@@ -12,10 +12,6 @@
|
||||
|
||||
<name>Download App Plugin Tests</name>
|
||||
|
||||
<properties>
|
||||
<aps.app>FORMS Core</aps.app>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
@@ -25,23 +21,19 @@
|
||||
<executions>
|
||||
<execution>
|
||||
<id>download-app</id>
|
||||
<phase>validate</phase>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>download-app</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<apsAppName>${aps.app}</apsAppName>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>download-app-other</id>
|
||||
<phase>validate</phase>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>download-app</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<apsAppName>${aps.app}</apsAppName>
|
||||
<targetDirectory>${basedir}/src/main/app</targetDirectory>
|
||||
<zipDirectory>${basedir}/src/main/aps</zipDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
@@ -57,8 +49,8 @@
|
||||
<rules>
|
||||
<requireFilesExist>
|
||||
<files>
|
||||
<file>${project.build.directory}/app/${aps.app}.zip</file>
|
||||
<file>${basedir}/src/main/app/${aps.app}.zip</file>
|
||||
<file>${project.build.directory}/aps/${aps-model.appName}.zip</file>
|
||||
<file>${basedir}/src/main/aps/${aps-model.appName}.zip</file>
|
||||
</files>
|
||||
</requireFilesExist>
|
||||
</rules>
|
||||
|
@@ -12,10 +12,6 @@
|
||||
|
||||
<name>Pack App Plugin Tests</name>
|
||||
|
||||
<properties>
|
||||
<aps.app>FORMS Core</aps.app>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
@@ -25,24 +21,23 @@
|
||||
<executions>
|
||||
<execution>
|
||||
<id>download-unpack-app</id>
|
||||
<phase>validate</phase>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>download-app</goal>
|
||||
<goal>unpack-app</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<apsAppName>${aps.app}</apsAppName>
|
||||
<normalize>true</normalize>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>pack-app</id>
|
||||
<phase>validate</phase>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>pack-app</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<apsAppName>${aps.app}</apsAppName>
|
||||
<targetDirectory>${basedir}/src/main/app</targetDirectory>
|
||||
<zipDirectory>${basedir}</zipDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
@@ -58,7 +53,7 @@
|
||||
<rules>
|
||||
<requireFilesExist>
|
||||
<files>
|
||||
<file>${basedir}/src/main/app/${aps.app}.zip</file>
|
||||
<file>${basedir}/${aps-model.appName}.zip</file>
|
||||
</files>
|
||||
</requireFilesExist>
|
||||
</rules>
|
||||
|
@@ -12,10 +12,6 @@
|
||||
|
||||
<name>Translate App Plugin Tests</name>
|
||||
|
||||
<properties>
|
||||
<aps.app>FORMS Core</aps.app>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
@@ -25,24 +21,24 @@
|
||||
<executions>
|
||||
<execution>
|
||||
<id>download-unpack-app</id>
|
||||
<phase>validate</phase>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>download-app</goal>
|
||||
<goal>unpack-app</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<apsAppName>${aps.app}</apsAppName>
|
||||
<normalize>true</normalize>
|
||||
<diffFriendly>true</diffFriendly>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>translate-app</id>
|
||||
<phase>validate</phase>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>translate-app</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<apsAppName>${aps.app}</apsAppName>
|
||||
<targetDirectory>${basedir}/src/main/app</targetDirectory>
|
||||
<finalDirectory>${basedir}/src/main/aps/app</finalDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
@@ -58,7 +54,7 @@
|
||||
<rules>
|
||||
<requireFilesExist>
|
||||
<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>
|
||||
</requireFilesExist>
|
||||
</rules>
|
||||
|
@@ -12,10 +12,6 @@
|
||||
|
||||
<name>Unpack App Plugin Tests</name>
|
||||
|
||||
<properties>
|
||||
<aps.app>FORMS Core</aps.app>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
@@ -25,24 +21,20 @@
|
||||
<executions>
|
||||
<execution>
|
||||
<id>download-unpack-app</id>
|
||||
<phase>validate</phase>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>download-app</goal>
|
||||
<goal>unpack-app</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<apsAppName>${aps.app}</apsAppName>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>unpack-app</id>
|
||||
<phase>validate</phase>
|
||||
<phase>process-sources</phase>
|
||||
<goals>
|
||||
<goal>unpack-app</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<apsAppName>${aps.app}</apsAppName>
|
||||
<targetDirectory>${basedir}/src/main/app</targetDirectory>
|
||||
<unzipDirectory>${basedir}/src/main/aps/app</unzipDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
@@ -58,8 +50,8 @@
|
||||
<rules>
|
||||
<requireFilesExist>
|
||||
<files>
|
||||
<file>${project.build.directory}/app/${aps.app}/${aps.app}.json</file>
|
||||
<file>${basedir}/src/main/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/aps/app/${aps-model.appName}/${aps-model.appName}.json</file>
|
||||
</files>
|
||||
</requireFilesExist>
|
||||
</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.MojoFailureException;
|
||||
@@ -12,7 +12,7 @@ import com.inteligr8.alfresco.activiti.model.AppVersion;
|
||||
public class ApsInfoGoal extends ApsAddressibleGoal {
|
||||
|
||||
@Override
|
||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
||||
public void executeEnabled() throws MojoExecutionException, MojoFailureException {
|
||||
AppVersion version = this.getApsApi()
|
||||
.getAppVersionApi()
|
||||
.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.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.apache.maven.plugins.annotations.Mojo;
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
import org.codehaus.plexus.component.annotations.Component;
|
||||
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
||||
|
||||
import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl;
|
||||
import com.inteligr8.alfresco.activiti.model.AppDefinitionUpdateResultRepresentation;
|
||||
import com.inteligr8.alfresco.activiti.model.FileMultipartJersey;
|
||||
|
||||
@Mojo( name = "deploy-app", threadSafe = true )
|
||||
@Component( role = org.apache.maven.plugin.Mojo.class )
|
||||
public class DeployAppGoal extends ApsAppAccessibleGoal {
|
||||
|
||||
@Parameter( property = "apsAppName", required = true )
|
||||
protected String apsAppName;
|
||||
|
||||
@Parameter( property = "sourceDirectory", required = true, defaultValue = "${project.build.directory}/app" )
|
||||
protected File sourceDirectory;
|
||||
@Parameter( property = "aps-model.upload.directory", required = true, defaultValue = "${project.build.directory}/aps" )
|
||||
protected File zipDirectory;
|
||||
|
||||
@Parameter( property = "publish", required = true, defaultValue = "false" )
|
||||
protected boolean publish = false;
|
||||
|
||||
@Parameter( property = "skip", required = true, defaultValue = "false" )
|
||||
protected boolean skip = false;
|
||||
|
||||
protected final int bufferSize = 128 * 1024;
|
||||
|
||||
@Override
|
||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
||||
public void executeEnabled() throws MojoExecutionException, MojoFailureException {
|
||||
File sourceFile = this.validateSourceDirectory();
|
||||
|
||||
Long appId = this.findAppId();
|
||||
|
||||
try {
|
||||
Long appId = this.findAppByName(this.apsAppName);
|
||||
this.uploadApp(appId, sourceFile);
|
||||
} catch (IOException ie) {
|
||||
throw new MojoExecutionException("The downloaded APS App could not be unpacked", ie);
|
||||
throw new MojoExecutionException("The APS App could not be uploaded", ie);
|
||||
}
|
||||
}
|
||||
|
||||
protected File validateSourceDirectory() {
|
||||
if (!this.sourceDirectory.exists()) {
|
||||
throw new IllegalStateException("The 'sourceDirectory' does not exist: " + this.sourceDirectory);
|
||||
} else if (!this.sourceDirectory.isDirectory()) {
|
||||
throw new IllegalStateException("The 'sourceDirectory' is not a directory: " + this.sourceDirectory);
|
||||
if (!this.zipDirectory.exists()) {
|
||||
throw new IllegalStateException("The 'zipDirectory' does not exist: " + this.zipDirectory);
|
||||
} else if (!this.zipDirectory.isDirectory()) {
|
||||
throw new IllegalStateException("The 'zipDirectory' is not a directory: " + this.zipDirectory);
|
||||
}
|
||||
|
||||
File sourceFile = new File(this.sourceDirectory, this.apsAppName + ".zip");
|
||||
File sourceFile = new File(this.zipDirectory, this.apsAppName + ".zip");
|
||||
|
||||
if (!sourceFile.exists()) {
|
||||
throw new IllegalStateException("The App file does not exists in the 'sourceDirectory': " + sourceFile);
|
||||
throw new IllegalStateException("The App file does not exists in the 'zipDirectory': " + sourceFile);
|
||||
} else if (!sourceFile.isFile()) {
|
||||
throw new IllegalStateException("The App file is not a file: " + sourceFile);
|
||||
}
|
||||
@@ -66,35 +62,34 @@ public class DeployAppGoal extends ApsAppAccessibleGoal {
|
||||
private void uploadApp(Long appId, File appZip) throws IOException, MojoExecutionException {
|
||||
ApsPublicRestApiJerseyImpl api = this.getApsApi();
|
||||
|
||||
FormDataContentDisposition cdisposition = FormDataContentDisposition.name("file")
|
||||
.size(appZip.length())
|
||||
.fileName(appZip.getName())
|
||||
.build();
|
||||
|
||||
FileInputStream fistream = new FileInputStream(appZip);
|
||||
BufferedInputStream bistream = new BufferedInputStream(fistream, this.bufferSize);
|
||||
try {
|
||||
FileMultipartJersey multipart = FileMultipartJersey.from(appZip.getName(), bistream);
|
||||
|
||||
if (appId == null) {
|
||||
if (this.publish) {
|
||||
this.getLog().info("Uploading & publishing new APS App: " + this.apsAppName);
|
||||
AppDefinitionUpdateResultRepresentation appDefUpdate = api.getAppDefinitionsJerseyApi().publishApp(bistream, cdisposition);
|
||||
AppDefinitionUpdateResultRepresentation appDefUpdate = api.getAppDefinitionsJerseyApi().publishApp(multipart);
|
||||
if (Boolean.TRUE.equals(appDefUpdate.getError()))
|
||||
throw new MojoExecutionException(appDefUpdate.getErrorDescription());
|
||||
} else {
|
||||
this.getLog().info("Uploading new APS App: " + this.apsAppName);
|
||||
api.getAppDefinitionsJerseyApi().import_(bistream, cdisposition);
|
||||
api.getAppDefinitionsJerseyApi().importApp(multipart, true);
|
||||
}
|
||||
} else {
|
||||
if (this.publish) {
|
||||
this.getLog().info("Uploading, versioning, & publishing APS App: " + this.apsAppName);
|
||||
AppDefinitionUpdateResultRepresentation appDefUpdate = api.getAppDefinitionsJerseyApi().publishApp(appId, bistream, cdisposition);
|
||||
this.getLog().info("Uploading, versioning, & publishing APS App: " + this.apsAppName + " (" + appId + ")");
|
||||
AppDefinitionUpdateResultRepresentation appDefUpdate = api.getAppDefinitionsJerseyApi().publishApp(appId, multipart);
|
||||
if (Boolean.TRUE.equals(appDefUpdate.getError()))
|
||||
throw new MojoExecutionException(appDefUpdate.getErrorDescription());
|
||||
} else {
|
||||
this.getLog().info("Uploading & versioning APS App: " + this.apsAppName);
|
||||
api.getAppDefinitionsJerseyApi().import_(appId, bistream, cdisposition);
|
||||
this.getLog().info("Uploading & versioning APS App: " + this.apsAppName + " (" + appId + ")");
|
||||
api.getAppDefinitionsJerseyApi().importApp(appId, multipart, true);
|
||||
}
|
||||
}
|
||||
} catch (ParseException pe) {
|
||||
throw new MojoExecutionException("The app ZIP could not be wrapped in a multipart", pe);
|
||||
} finally {
|
||||
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.IOException;
|
||||
@@ -16,23 +16,17 @@ import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl;
|
||||
@Component( role = org.apache.maven.plugin.Mojo.class )
|
||||
public class DownloadAppGoal extends ApsAppAccessibleGoal {
|
||||
|
||||
@Parameter( property = "apsAppName", required = true )
|
||||
protected String apsAppName;
|
||||
|
||||
@Parameter( property = "targetDirectory", required = true, defaultValue = "${project.build.directory}/app" )
|
||||
protected File targetDirectory;
|
||||
|
||||
@Parameter( property = "skip", required = true, defaultValue = "false" )
|
||||
protected boolean skip = false;
|
||||
@Parameter( property = "aps-model.download.directory", required = true, defaultValue = "${project.build.directory}/aps" )
|
||||
protected File zipDirectory;
|
||||
|
||||
@Override
|
||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
||||
public void executeEnabled() throws MojoExecutionException, MojoFailureException {
|
||||
this.validateTargetDirectory();
|
||||
|
||||
long appId = this.findAppByName(this.apsAppName);
|
||||
Long appId = this.findAppId();
|
||||
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())
|
||||
toAppZip.delete();
|
||||
|
||||
@@ -44,10 +38,10 @@ public class DownloadAppGoal extends ApsAppAccessibleGoal {
|
||||
}
|
||||
|
||||
protected void validateTargetDirectory() {
|
||||
if (!this.targetDirectory.exists()) {
|
||||
this.getLog().debug("Creating APS Apps directory: " + this.targetDirectory);
|
||||
this.targetDirectory.mkdirs();
|
||||
} else if (!this.targetDirectory.isDirectory()) {
|
||||
if (!this.zipDirectory.exists()) {
|
||||
this.getLog().debug("Creating APS Apps directory: " + this.zipDirectory);
|
||||
this.zipDirectory.mkdirs();
|
||||
} else if (!this.zipDirectory.isDirectory()) {
|
||||
throw new IllegalStateException("The 'targetDirectory' refers to a file and not a directory");
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package com.inteligr8.maven.aps.modeling;
|
||||
package com.inteligr8.maven.aps.modeling.goal;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
@@ -12,7 +12,6 @@ import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.maven.plugin.AbstractMojo;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.apache.maven.plugins.annotations.Mojo;
|
||||
@@ -21,24 +20,18 @@ import org.codehaus.plexus.component.annotations.Component;
|
||||
|
||||
@Mojo( name = "pack-app", threadSafe = true )
|
||||
@Component( role = org.apache.maven.plugin.Mojo.class )
|
||||
public class PackAppGoal extends AbstractMojo {
|
||||
public class PackAppGoal extends ApsAppGoal {
|
||||
|
||||
@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 = true, defaultValue = "${project.build.directory}/app" )
|
||||
protected File targetDirectory;
|
||||
@Parameter( property = "aps-model.app.directory", required = true, defaultValue = "${project.build.directory}/aps/app" )
|
||||
protected File unzipDirectory;
|
||||
|
||||
@Parameter( property = "skip", required = true, defaultValue = "false" )
|
||||
protected boolean skip = false;
|
||||
@Parameter( property = "aps-model.upload.directory", required = true, defaultValue = "${project.build.directory}/aps" )
|
||||
protected File zipDirectory;
|
||||
|
||||
protected final int bufferSize = 128 * 1024;
|
||||
|
||||
@Override
|
||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
||||
public void executeEnabled() throws MojoExecutionException, MojoFailureException {
|
||||
this.validateSourceDirectory();
|
||||
File appDirectory = this.validateAppDirectory();
|
||||
|
||||
@@ -52,17 +45,17 @@ public class PackAppGoal extends AbstractMojo {
|
||||
}
|
||||
|
||||
protected void validateSourceDirectory() {
|
||||
if (!this.sourceDirectory.exists()) {
|
||||
throw new IllegalStateException("The 'sourceDirectory' does not exist: " + this.sourceDirectory);
|
||||
} else if (!this.sourceDirectory.isDirectory()) {
|
||||
throw new IllegalStateException("The 'sourceDirectory' is not a directory: " + this.sourceDirectory);
|
||||
if (!this.unzipDirectory.exists()) {
|
||||
throw new IllegalStateException("The 'unzipDirectory' does not exist: " + this.unzipDirectory);
|
||||
} else if (!this.unzipDirectory.isDirectory()) {
|
||||
throw new IllegalStateException("The 'unzipDirectory' is not a directory: " + this.unzipDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
protected File validateAppDirectory() {
|
||||
File appDirectory = new File(this.sourceDirectory, this.apsAppName);
|
||||
File appDirectory = new File(this.unzipDirectory, this.apsAppName);
|
||||
if (!appDirectory.exists()) {
|
||||
throw new IllegalStateException("The 'apsAppName' does not exist in the source directory: " + this.sourceDirectory);
|
||||
throw new IllegalStateException("The 'apsAppName' does not exist in the source directory: " + this.unzipDirectory);
|
||||
} else if (!appDirectory.isDirectory()) {
|
||||
throw new IllegalStateException("The 'apsAppName' refers to a file and not a directory: " + appDirectory);
|
||||
}
|
||||
@@ -71,19 +64,19 @@ public class PackAppGoal extends AbstractMojo {
|
||||
}
|
||||
|
||||
protected File validateTargetDirectory() {
|
||||
if (!this.targetDirectory.exists()) {
|
||||
this.getLog().debug("The 'targetDirectory' does not exist; creating: " + this.targetDirectory);
|
||||
this.targetDirectory.mkdirs();
|
||||
} else if (!this.targetDirectory.isDirectory()) {
|
||||
throw new IllegalStateException("The 'targetDirectory' is not a directory: " + this.targetDirectory);
|
||||
if (!this.zipDirectory.exists()) {
|
||||
this.getLog().debug("The 'zipDirectory' does not exist; creating: " + this.zipDirectory);
|
||||
this.zipDirectory.mkdirs();
|
||||
} else if (!this.zipDirectory.isDirectory()) {
|
||||
throw new IllegalStateException("The 'zipDirectory' is not a directory: " + this.zipDirectory);
|
||||
}
|
||||
|
||||
File targetFile = new File(this.targetDirectory, this.apsAppName + ".zip");
|
||||
File targetFile = new File(this.zipDirectory, this.apsAppName + ".zip");
|
||||
|
||||
if (targetFile.isDirectory()) {
|
||||
throw new IllegalStateException("The App file is not a file: " + targetFile);
|
||||
} else if (targetFile.exists()) {
|
||||
this.getLog().debug("The App file in the 'targetDirectory' exists; deleting: " + targetFile);
|
||||
this.getLog().debug("The App file in the 'zipDirectory' exists; deleting: " + targetFile);
|
||||
targetFile.delete();
|
||||
}
|
||||
|
||||
@@ -99,6 +92,7 @@ public class PackAppGoal extends AbstractMojo {
|
||||
ZipOutputStream zostream = new ZipOutputStream(bostream);
|
||||
try {
|
||||
this.zipDirectory(appDirectory, null, zostream);
|
||||
zostream.flush();
|
||||
} finally {
|
||||
zostream.close();
|
||||
}
|
||||
@@ -125,7 +119,8 @@ public class PackAppGoal extends AbstractMojo {
|
||||
|
||||
this.getLog().debug("Packing APS file: " + path);
|
||||
|
||||
ZipEntry zentry = new ZipEntry(path.toString());
|
||||
// Activit App processing requires forward slashes (WOW)
|
||||
ZipEntry zentry = new ZipEntry(path.toString().replace('\\', '/'));
|
||||
zostream.putNextEntry(zentry);
|
||||
try {
|
||||
FileInputStream fistream = new FileInputStream(file);
|
@@ -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.BufferedOutputStream;
|
||||
@@ -10,43 +10,53 @@ import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.maven.plugin.AbstractMojo;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.apache.maven.plugins.annotations.Mojo;
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
import org.codehaus.plexus.component.annotations.Component;
|
||||
import org.w3c.dom.Document;
|
||||
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 )
|
||||
@Component( role = org.apache.maven.plugin.Mojo.class )
|
||||
public class UnpackAppGoal extends AbstractMojo {
|
||||
public class UnpackAppGoal extends ApsAppGoal {
|
||||
|
||||
@Parameter( property = "apsAppName", required = true )
|
||||
protected String apsAppName;
|
||||
@Parameter( property = "aps-model.download.directory", required = true, defaultValue = "${project.build.directory}/aps" )
|
||||
protected File zipDirectory;
|
||||
|
||||
@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 = "aps-model.app.directory", required = true, defaultValue = "${project.build.directory}/aps/app" )
|
||||
protected File unzipDirectory;
|
||||
|
||||
@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";
|
||||
|
||||
@Parameter( property = "skip", required = true, defaultValue = "false" )
|
||||
protected boolean skip = false;
|
||||
|
||||
private final int bufferSize = 128 * 1024;
|
||||
|
||||
@Override
|
||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
||||
public void executeEnabled() throws MojoExecutionException, MojoFailureException {
|
||||
this.validate();
|
||||
|
||||
File sourceFile = this.validateSourceDirectory();
|
||||
|
||||
this.validateTargetDirectory();
|
||||
@@ -60,20 +70,37 @@ public class UnpackAppGoal extends AbstractMojo {
|
||||
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() {
|
||||
if (!this.sourceDirectory.exists()) {
|
||||
throw new IllegalStateException("The 'sourceDirectory' does not exist: " + this.sourceDirectory);
|
||||
} else if (!this.sourceDirectory.isDirectory()) {
|
||||
throw new IllegalStateException("The 'sourceDirectory' is not a directory: " + this.sourceDirectory);
|
||||
if (!this.zipDirectory.exists()) {
|
||||
throw new IllegalStateException("The 'zipDirectory' does not exist: " + this.zipDirectory);
|
||||
} else if (!this.zipDirectory.isDirectory()) {
|
||||
throw new IllegalStateException("The 'zipDirectory' is not a directory: " + this.zipDirectory);
|
||||
}
|
||||
|
||||
File sourceFile = new File(this.sourceDirectory, this.apsAppName + ".zip");
|
||||
File sourceFile = new File(this.zipDirectory, this.apsAppName + ".zip");
|
||||
|
||||
if (!sourceFile.exists()) {
|
||||
throw new IllegalStateException("The App file does not exists in the 'sourceDirectory': " + sourceFile);
|
||||
throw new IllegalStateException("The App file does not exists in the 'zipDirectory': " + sourceFile);
|
||||
} else if (!sourceFile.isFile()) {
|
||||
throw new IllegalStateException("The App file is not a file: " + sourceFile);
|
||||
}
|
||||
@@ -82,16 +109,16 @@ public class UnpackAppGoal extends AbstractMojo {
|
||||
}
|
||||
|
||||
protected void validateTargetDirectory() {
|
||||
if (!this.targetDirectory.exists()) {
|
||||
this.getLog().debug("Creating APS Apps directory: " + this.targetDirectory);
|
||||
this.targetDirectory.mkdirs();
|
||||
} else if (!this.targetDirectory.isDirectory()) {
|
||||
throw new IllegalStateException("The 'apsAppsDirectory' refers to a file and not a directory: " + this.targetDirectory);
|
||||
if (!this.unzipDirectory.exists()) {
|
||||
this.getLog().debug("Creating unzip directory: " + this.unzipDirectory);
|
||||
this.unzipDirectory.mkdirs();
|
||||
} else if (!this.unzipDirectory.isDirectory()) {
|
||||
throw new IllegalStateException("The 'unzipDirectory' refers to a file and not a directory: " + this.unzipDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
protected File validateAppDirectory() {
|
||||
File appDirectory = new File(this.targetDirectory, this.apsAppName);
|
||||
File appDirectory = new File(this.unzipDirectory, this.apsAppName);
|
||||
if (!appDirectory.exists()) {
|
||||
this.getLog().debug("Creating APS App directory: " + appDirectory);
|
||||
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()) {
|
||||
if (file.isDirectory()) {
|
||||
this.normalizeFiles(file);
|
||||
this.reformatFiles(file);
|
||||
} else {
|
||||
String ext = this.getFileExtension(file);
|
||||
|
||||
try {
|
||||
switch (ext) {
|
||||
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;
|
||||
case "xml":
|
||||
case "bpmn":
|
||||
ModelUtil.getInstance().xml(file);
|
||||
this.getLog().debug("Reformatting file: " + file);
|
||||
Document xml = ModelUtil.getInstance().readXml(file);
|
||||
ModelUtil.getInstance().writeXml(xml, file);
|
||||
break;
|
||||
default:
|
||||
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.IOException;
|
||||
@@ -9,33 +9,35 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
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 Map<String, Group> apsOrgIndex;
|
||||
private Index<Long, String> apsProcessIndex;
|
||||
private Index<Long, String> fileProcessIndex;
|
||||
private final Map<String, GroupLight> apsOrgIndex;
|
||||
private final Index<Long, String> apsProcessIndex;
|
||||
private final Index<Long, String> fileProcessIndex;
|
||||
|
||||
public ApsAppJsonTranslator(
|
||||
Map<String, Group> apsOrgIndex,
|
||||
ApsPublicRestApi api,
|
||||
Map<String, GroupLight> apsOrgIndex,
|
||||
Index<Long, String> apsProcessIndex,
|
||||
Index<Long, String> fileProcessIndex) {
|
||||
super(api, apsOrgIndex);
|
||||
this.apsOrgIndex = apsOrgIndex;
|
||||
this.apsProcessIndex = apsProcessIndex;
|
||||
|
||||
this.fileProcessIndex = fileProcessIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translateFile(File file, String modelName, Long modelId) throws IOException {
|
||||
this.logger.debug("Translating JSON file: {}", file);
|
||||
|
||||
JsonNode descriptor = ModelUtil.getInstance().readJson(file);
|
||||
|
||||
|
||||
boolean changed = false;
|
||||
JsonNode descriptor = ModelUtil.getInstance().readJson(file);
|
||||
|
||||
for (JsonNode _jsonModel : descriptor.get("definition").get("models")) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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")) {
|
||||
@@ -74,23 +85,37 @@ public class ApsAppJsonTranslator implements ApsFileTranslator {
|
||||
|
||||
if (this.apsOrgIndex.containsKey(fileOrgName)) {
|
||||
long fileOrgId = jsonGroup.get("id").asLong();
|
||||
long apsOrgId = this.apsOrgIndex.get(fileOrgName).getId();
|
||||
GroupLight apsOrg = this.apsOrgIndex.get(fileOrgName);
|
||||
|
||||
if (fileOrgId != apsOrgId) {
|
||||
this.logger.debug("The organziation '{}' exists in APS with ID {}; changing descriptor", fileOrgName, apsOrgId);
|
||||
jsonGroup.put("id", apsOrgId);
|
||||
if (apsOrg == null) {
|
||||
this.logger.debug("The organization '{}' does not exist in APS; adding to APS", fileOrgName);
|
||||
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;
|
||||
} else {
|
||||
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 {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -13,110 +12,127 @@ import java.util.regex.Pattern;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.inteligr8.alfresco.activiti.ApsPublicRestApi;
|
||||
import com.inteligr8.alfresco.activiti.ApsPublicRestApiJerseyImpl;
|
||||
import com.inteligr8.alfresco.activiti.api.ModelsApi.ModelType;
|
||||
import com.inteligr8.alfresco.activiti.model.Datum;
|
||||
import com.inteligr8.alfresco.activiti.model.Group;
|
||||
import com.inteligr8.alfresco.activiti.model.GroupLight;
|
||||
import com.inteligr8.alfresco.activiti.model.ResultListDataRepresentation;
|
||||
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 Pattern filenamePattern = Pattern.compile("([^/]+)-([0-9]+)\\.(json|bpmn20\\.xml)");
|
||||
private final ApsPublicRestApiJerseyImpl api;
|
||||
private final String appName;
|
||||
private final ApsPublicRestApi api;
|
||||
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> apsProcessIndex;
|
||||
private Index<Long, String> fileFormIndex;
|
||||
private Index<Long, String> fileProcessIndex;
|
||||
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.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");
|
||||
public synchronized void buildIndexes() throws IOException {
|
||||
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 ...");
|
||||
|
||||
long tenantId = this.findTenantId();
|
||||
this.logger.debug("APS App tenant ID: {}", 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.logger.debug("APS process models: {}", this.apsProcessIndex);
|
||||
this.logLarge("APS process models: {}", this.apsProcessIndex);
|
||||
|
||||
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.logger.debug("File form models: {}", this.fileFormIndex);
|
||||
this.logLarge("File form models: {}", this.fileFormIndex);
|
||||
|
||||
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.logger.debug("File subprocess models: {}", this.fileSubprocessIndex);
|
||||
this.logLarge("File subprocess models: {}", this.fileSubprocessIndex);
|
||||
|
||||
this.indexesBuilt = true;
|
||||
}
|
||||
|
||||
protected void translate() throws IOException {
|
||||
this.logger.info("Translating models ...");
|
||||
private <K, V> void logLarge(String message, Map<K, V> map) {
|
||||
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.apsProcessIndex,
|
||||
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);
|
||||
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.apsOrgIndex,
|
||||
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.apsOrgIndex,
|
||||
this.apsFormIndex,
|
||||
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() {
|
||||
@@ -124,17 +140,18 @@ public class ApsAppTranslator {
|
||||
return (tenants == null || tenants.isEmpty()) ? null : tenants.iterator().next().getId();
|
||||
}
|
||||
|
||||
protected Map<String, Group> buildApsGroupMap(long tenantId) {
|
||||
List<Group> groups = this.api.getAdminApi().getGroups(tenantId, true, true);
|
||||
protected Map<String, GroupLight> buildApsGroupMap(long tenantId) {
|
||||
List<GroupLight> groups = this.api.getAdminApi().getGroups(tenantId, true, true);
|
||||
|
||||
Map<String, Group> map = new HashMap<>(groups.size());
|
||||
for (Group group : groups)
|
||||
Map<String, GroupLight> map = new HashMap<>(groups.size());
|
||||
for (GroupLight group : groups)
|
||||
map.put(group.getName(), group);
|
||||
return map;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -143,11 +160,13 @@ public class ApsAppTranslator {
|
||||
Number defId = (Number)datum.getAdditionalProperties().get("id");
|
||||
String defName = (String)datum.getAdditionalProperties().get("name");
|
||||
map.put(defId.longValue(), defName);
|
||||
|
||||
// FIXME add paging support
|
||||
}
|
||||
} catch (IllegalArgumentException iae) {
|
||||
throw new IllegalStateException("This goal does not support the current state of APS", iae);
|
||||
}
|
||||
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -157,77 +176,50 @@ public class ApsAppTranslator {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (!modelDirectory.isDirectory())
|
||||
throw new IllegalStateException("The APS model directory is actually a file: " + modelDirectory);
|
||||
|
||||
Index<Long, String> fileModelIndex = new Index<>(apsModelIndex.size(), false);
|
||||
|
||||
for (File modelFile : modelDirectory.listFiles()) {
|
||||
this.logger.trace("Building index for model file: {}", modelFile);
|
||||
|
||||
Matcher matcher = this.filenamePattern.matcher(modelFile.getName());
|
||||
String modelName = matcher.replaceFirst("$1");
|
||||
String modelIdStr = matcher.replaceFirst("$2");
|
||||
String modelExt = matcher.replaceFirst("$3");
|
||||
long fileModelId = Long.parseLong(modelIdStr);
|
||||
this.logger.trace("Building index for model {} ID: {}", modelName, fileModelId);
|
||||
|
||||
fileModelIndex.put(fileModelId, 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)
|
||||
throw new IllegalStateException("An APS " + modelDirectory.getName() + " name was used multiple times: " + modelName);
|
||||
|
||||
if (renameFiles && !apsModelIds.isEmpty()) {
|
||||
if (renameFiles) {
|
||||
Long apsModelId = apsModelIds.iterator().next();
|
||||
if (apsModelId != fileModelId) {
|
||||
this.logger.debug("Renaming form model from '" + modelFile.getName() + "' to match APS form ID: " + apsModelId);
|
||||
File newModelFile = new File(modelFile.getParentFile(), modelName + "-" + apsModelId + "." + modelExt);
|
||||
modelFile.renameTo(newModelFile);
|
||||
} 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;
|
||||
}
|
||||
|
||||
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.IOException;
|
||||
@@ -8,6 +8,8 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
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 {
|
||||
|
||||
@@ -44,7 +46,7 @@ public class ApsFormJsonTranslator implements ApsFileTranslator {
|
||||
}
|
||||
|
||||
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.IOException;
|
||||
@@ -16,34 +16,38 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.CDATASection;
|
||||
import org.w3c.dom.CharacterData;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
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_MODELER = "http://activiti.com/modeler";
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ApsProcessBpmnTranslator.class);
|
||||
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> fileFormIndex;
|
||||
|
||||
public ApsProcessBpmnTranslator(
|
||||
ApsPublicRestApi api,
|
||||
Index<Long, String> apsProcessIndex,
|
||||
Map<String, Group> apsOrgIndex,
|
||||
Map<String, GroupLight> apsOrgIndex,
|
||||
Index<Long, String> apsFormIndex,
|
||||
Index<Long, String> fileFormIndex) {
|
||||
super(api, apsOrgIndex);
|
||||
this.apsIndex = apsProcessIndex;
|
||||
this.apsOrgIndex = apsOrgIndex;
|
||||
this.apsFormIndex = apsFormIndex;
|
||||
|
||||
this.fileFormIndex = fileFormIndex;
|
||||
}
|
||||
|
||||
@@ -72,7 +76,7 @@ public class ApsProcessBpmnTranslator implements ApsFileTranslator {
|
||||
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++) {
|
||||
Element subprocessElement = (Element)subprocessElements.item(n);
|
||||
changed = this.translateSubprocess(subprocessElement) || changed;
|
||||
@@ -84,9 +88,9 @@ public class ApsProcessBpmnTranslator implements ApsFileTranslator {
|
||||
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++) {
|
||||
CDATASection conditionExpression = (CDATASection)conditionExpressions.item(n);
|
||||
CharacterData conditionExpression = (CharacterData)conditionExpressions.item(n);
|
||||
changed = this.translateConditionExpression(conditionExpression) || changed;
|
||||
}
|
||||
|
||||
@@ -100,10 +104,10 @@ public class ApsProcessBpmnTranslator implements ApsFileTranslator {
|
||||
private boolean translateRootElement(Element definitionsElement, Long apsProcessId) {
|
||||
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, "exportDateTime") || changed;
|
||||
changed = this.removeAttributeIfSet(definitionsElement, NAMESPACE_ACTIVITI_MODELER, "modelLastUpdated") || changed;
|
||||
//changed = this.setAttributeIfSet(definitionsElement, NAMESPACE_ACTIVITI_MODELER, "modelVersion", "0") || changed;
|
||||
|
||||
return changed;
|
||||
}
|
||||
@@ -139,22 +143,26 @@ public class ApsProcessBpmnTranslator implements ApsFileTranslator {
|
||||
String groupName = groupNameElement.getTextContent().trim();
|
||||
this.logger.trace("Found '{}' candidate group in the APS Process BPMN model", groupName);
|
||||
|
||||
if (this.apsOrgIndex.containsKey(groupName)) {
|
||||
long apsOrgId = this.apsOrgIndex.get(groupName).getId();
|
||||
groupIdsList.add(apsOrgId);
|
||||
|
||||
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(), "group-info-name-" + apsOrgId);
|
||||
changed = true;
|
||||
} else {
|
||||
this.logger.trace("The organization '{}' ID does not change; leaving unchanged", groupName);
|
||||
}
|
||||
GroupLight apsOrg = this.apsOrgIndex.get(groupName);
|
||||
long apsOrgId = 0L;
|
||||
if (apsOrg == null) {
|
||||
this.logger.debug("The organization '{}' does not exist in APS; creating it ...", groupName);
|
||||
apsOrgId = this.createOrganization(groupName);
|
||||
} else {
|
||||
// FIXME automatically add the group?
|
||||
this.logger.debug("The organization '{}' does not exist in APS; leaving unchanged", groupName);
|
||||
groupIdsList.add(orgId);
|
||||
apsOrgId = apsOrg.getId();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
CDATAFlexSection formRefIdData = (CDATAFlexSection)ModelUtil.getInstance().xpath(
|
||||
CharacterData formRefIdData = (CharacterData)ModelUtil.getInstance().xpath(
|
||||
taskElement,
|
||||
"tns:extensionElements/modeler:form-reference-id",
|
||||
ModelUtil.CDATA_FLEX);
|
||||
if (formRefIdData == null)
|
||||
throw new IllegalStateException("A form was detected in the task, but no form reference ID was found: " + taskElement.getAttribute("id"));
|
||||
|
||||
long formRefId = Long.parseLong(formRefIdData.getValue());
|
||||
long formRefId = Long.parseLong(formRefIdData.getData());
|
||||
if (apsFormId != formRefId) {
|
||||
this.logger.debug("The form '{}' reference exists in APS with ID {}; changing model", formRefName, apsFormId);
|
||||
formRefIdData.setValue(apsFormId.toString());
|
||||
formRefIdData.setData(apsFormId.toString());
|
||||
changed = true;
|
||||
} else {
|
||||
this.logger.trace("The form '{}' reference ID does not change; leaving unchanged", formRefName);
|
||||
@@ -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);
|
||||
|
||||
CDATAFlexSection subprocessIdData = (CDATAFlexSection)ModelUtil.getInstance().xpath(
|
||||
CharacterData subprocessIdData = (CharacterData)ModelUtil.getInstance().xpath(
|
||||
subprocessElement,
|
||||
"tns:extensionElements/modeler:subprocess-id",
|
||||
ModelUtil.CDATA_FLEX);
|
||||
long subprocessId = Long.parseLong(subprocessIdData.getValue());
|
||||
long subprocessId = Long.parseLong(subprocessIdData.getData());
|
||||
if (apsProcessId != subprocessId) {
|
||||
this.logger.debug("The process '{}' exists in APS with ID {}; changing model", subprocessName, apsProcessId);
|
||||
subprocessIdData.setValue(apsProcessId.toString());
|
||||
subprocessIdData.setData(apsProcessId.toString());
|
||||
changed = true;
|
||||
} else {
|
||||
this.logger.trace("The process '{}' ID does not change; leaving unchanged", subprocessName);
|
||||
@@ -282,28 +290,42 @@ public class ApsProcessBpmnTranslator implements ApsFileTranslator {
|
||||
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"));
|
||||
boolean changed = false;
|
||||
|
||||
String conditionExpression = conditionExpressionCdata.getData();
|
||||
Pattern formOutcomeInExpressionPattern = Pattern.compile("[^A-Za-z0-9]form([0-9]+)outcome[^A-Za-z0-9]");
|
||||
StringBuilder newce = new StringBuilder();
|
||||
int pos = 0;
|
||||
|
||||
Pattern formOutcomeInExpressionPattern = Pattern.compile("form([0-9]+)outcome");
|
||||
Matcher matcher = formOutcomeInExpressionPattern.matcher(conditionExpression);
|
||||
while (matcher.find()) {
|
||||
newce.append(conditionExpression.substring(pos, matcher.start(1)));
|
||||
|
||||
long formId = Long.parseLong(matcher.group(1));
|
||||
String formName = this.fileFormIndex.getValue(formId);
|
||||
if (formName == null) {
|
||||
this.logger.warn("The form ID '{}' does not exist in the form model files; ignoring", formId);
|
||||
newce.append(formId);
|
||||
} else {
|
||||
Long apsFormId = this.apsFormIndex.getFirstKey(formName);
|
||||
if (apsFormId == null) {
|
||||
this.logger.warn("The form '{}' does not exist in APS; leaving unchanged", formName);
|
||||
newce.append(formId);
|
||||
} else {
|
||||
conditionExpressionCdata.setData(apsFormId.toString());
|
||||
newce.append(apsFormId);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
pos = matcher.end(1);
|
||||
}
|
||||
|
||||
newce.append(conditionExpression.substring(pos));
|
||||
|
||||
if (changed)
|
||||
conditionExpressionCdata.setData(newce.toString());
|
||||
|
||||
return changed;
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package com.inteligr8.maven.aps.modeling;
|
||||
package com.inteligr8.maven.aps.modeling.translator;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -10,19 +10,24 @@ 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.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 Index<Long, String> apsIndex;
|
||||
private final Map<String, Group> apsOrgIndex;
|
||||
private final Map<String, GroupLight> apsOrgIndex;
|
||||
private final Index<Long, String> apsFormIndex;
|
||||
|
||||
public ApsProcessJsonTranslator(
|
||||
ApsPublicRestApi api,
|
||||
Index<Long, String> apsProcessIndex,
|
||||
Map<String, Group> apsOrgIndex,
|
||||
Map<String, GroupLight> apsOrgIndex,
|
||||
Index<Long, String> apsFormIndex) {
|
||||
super(api, apsOrgIndex);
|
||||
this.apsIndex = apsProcessIndex;
|
||||
this.apsOrgIndex = apsOrgIndex;
|
||||
this.apsFormIndex = apsFormIndex;
|
||||
@@ -43,17 +48,32 @@ public class ApsProcessJsonTranslator implements ApsFileTranslator {
|
||||
changed = this.translateSubprocesses(jsonDescriptor) || changed;
|
||||
|
||||
if (changed)
|
||||
ModelUtil.getInstance().writeJson(jsonDescriptor, file);
|
||||
ModelUtil.getInstance().writeJson(jsonDescriptor, file, false);
|
||||
}
|
||||
|
||||
private boolean translateResourceId(ObjectNode jsonDescriptor, Long apsProcessId) {
|
||||
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");
|
||||
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()) {
|
||||
this.logger.trace("The process 'resourceId' is not defined; leaving unchanged", apsProcessId);
|
||||
return false;
|
||||
} else if (jsonResourceId.asLong() != 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;
|
||||
} else {
|
||||
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)) {
|
||||
long fileOrgId = jsonCandidateGroup.get("id").asLong();
|
||||
long apsOrgId = this.apsOrgIndex.get(fileOrgName).getId();
|
||||
if (apsOrgId != fileOrgId) {
|
||||
this.logger.debug("The organization '{}' exists in APS with ID {}; changing descriptor", fileOrgName, apsOrgId);
|
||||
jsonCandidateGroup.put("id", apsOrgId);
|
||||
GroupLight apsOrg = this.apsOrgIndex.get(fileOrgName);
|
||||
|
||||
if (apsOrg == null) {
|
||||
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;
|
||||
} else {
|
||||
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)) {
|
||||
try {
|
||||
JsonNode jsonConditionalSequenceFlow = (JsonNode)jsonChildShape.get("properties").get("conditionalsequenceflow");
|
||||
changed = this.translateConditionalSequenceFlow(jsonConditionalSequenceFlow) || changed;
|
||||
JsonNode jsonConditionalSequenceFlow = (JsonNode)jsonChildShape.get("properties").get("conditionsequenceflow");
|
||||
changed = this.translateConditionSequenceFlow(jsonConditionalSequenceFlow) || changed;
|
||||
|
||||
JsonNode jsonFormRef = (JsonNode)jsonChildShape.get("properties").get("formreference");
|
||||
changed = this.translateReference(jsonFormRef, this.apsFormIndex) || changed;
|
||||
@@ -126,7 +152,7 @@ public class ApsProcessJsonTranslator implements ApsFileTranslator {
|
||||
return changed;
|
||||
}
|
||||
|
||||
private boolean translateConditionalSequenceFlow(JsonNode jsonConditionalSequenceFlow) {
|
||||
private boolean translateConditionSequenceFlow(JsonNode jsonConditionalSequenceFlow) {
|
||||
if (jsonConditionalSequenceFlow == null || !jsonConditionalSequenceFlow.isObject())
|
||||
return false;
|
||||
|
@@ -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.HashSet;
|
||||
@@ -33,6 +33,14 @@ public class Index<K, V> {
|
||||
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) {
|
||||
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.BufferedOutputStream;
|
||||
@@ -8,6 +8,8 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
@@ -25,7 +27,7 @@ import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
|
||||
import org.w3c.dom.CDATASection;
|
||||
import org.w3c.dom.CharacterData;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
@@ -36,10 +38,10 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.MapperFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.inteligr8.maven.aps.modeling.xml.DomNamespaceContext;
|
||||
|
||||
public class ModelUtil {
|
||||
|
||||
public final static QName CDATA = QName.valueOf("inteligr8:xml:cdata");
|
||||
public final static QName CDATA_FLEX = QName.valueOf("inteligr8:xml:cdata_or_element");
|
||||
private final static ModelUtil INSTANCE = new ModelUtil();
|
||||
|
||||
@@ -50,6 +52,7 @@ public class ModelUtil {
|
||||
|
||||
|
||||
private final ObjectMapper om = new ObjectMapper();
|
||||
private final ObjectMapper omsorted = new ObjectMapper();
|
||||
private final DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
|
||||
private final DocumentBuilder docBuilder;
|
||||
private final XPathFactory xpathfactory = XPathFactory.newInstance();
|
||||
@@ -77,41 +80,28 @@ public class ModelUtil {
|
||||
|
||||
// makes Git handling a whole lot better
|
||||
this.om.enable(SerializationFeature.INDENT_OUTPUT);
|
||||
// makes Git handling better between environment nuances
|
||||
this.om.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
|
||||
this.om.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
this.omsorted.enable(SerializationFeature.INDENT_OUTPUT);
|
||||
|
||||
FileOutputStream fostream = new FileOutputStream(inplaceFile);
|
||||
BufferedOutputStream bostream = new BufferedOutputStream(fostream, this.bufferSize);
|
||||
try {
|
||||
this.writeJson(json, bostream);
|
||||
} finally {
|
||||
bostream.close();
|
||||
}
|
||||
// makes Git handling better between environment nuances
|
||||
this.omsorted.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
|
||||
this.omsorted.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
|
||||
}
|
||||
|
||||
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);
|
||||
BufferedInputStream bistream = new BufferedInputStream(fistream, this.bufferSize);
|
||||
try {
|
||||
FileOutputStream fostream = new FileOutputStream(targetFile);
|
||||
BufferedOutputStream bostream = new BufferedOutputStream(fostream, this.bufferSize);
|
||||
try {
|
||||
this.json(bistream, bostream);
|
||||
this.json(bistream, bostream, enableSorting);
|
||||
} finally {
|
||||
bostream.close();
|
||||
}
|
||||
@@ -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
|
||||
JsonNode json = this.readJson(istream);
|
||||
this.writeJson(json, ostream);
|
||||
this.writeJson(json, ostream, enableSorting);
|
||||
}
|
||||
|
||||
public JsonNode readJson(File file) throws IOException {
|
||||
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);
|
||||
BufferedInputStream bistream = new BufferedInputStream(fistream, this.bufferSize);
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
BufferedOutputStream bostream = new BufferedOutputStream(fostream, this.bufferSize);
|
||||
try {
|
||||
this.writeJson(json, bostream);
|
||||
this.writeJson(json, bostream, enableSorting);
|
||||
} finally {
|
||||
bostream.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void writeJson(JsonNode json, OutputStream ostream) throws IOException {
|
||||
this.om.writeValue(ostream, json);
|
||||
public void writeJson(Map<String, Object> map, File file, boolean enableSorting) throws IOException {
|
||||
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.setNamespaceContext(new DomNamespaceContext(node));
|
||||
|
||||
boolean isFlex = returnType.equals(ModelUtil.CDATA_FLEX);
|
||||
|
||||
if (returnType.equals(ModelUtil.CDATA) || isFlex) {
|
||||
if (returnType.equals(ModelUtil.CDATA_FLEX)) {
|
||||
NodeList nodes = (NodeList)xpath.evaluate(xpathExpr, node, XPathConstants.NODESET);
|
||||
Node anode = this.getFirstCDataSectionOrLastElement(nodes);
|
||||
if (anode instanceof CDATASection) {
|
||||
if (anode instanceof CharacterData) {
|
||||
// nothing special
|
||||
} else if (anode instanceof Element) {
|
||||
Node anode2 = this.getFirstCDataSectionOrLastElement(anode.getChildNodes());
|
||||
if (anode2 != null)
|
||||
return anode = anode2;
|
||||
if (anode2 == null)
|
||||
return null;
|
||||
if (!(anode2 instanceof CharacterData))
|
||||
throw new IllegalStateException();
|
||||
anode = anode2;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return isFlex ? new CDATAFlexSection(anode) : anode;
|
||||
return anode;
|
||||
} else {
|
||||
return xpath.evaluate(xpathExpr, node, returnType);
|
||||
}
|
||||
@@ -270,8 +313,8 @@ public class ModelUtil {
|
||||
|
||||
for (int n = 0; n < nodes.getLength(); n++) {
|
||||
Node anode = nodes.item(n);
|
||||
if (anode.getNodeType() == Node.CDATA_SECTION_NODE) {
|
||||
return (CDATASection)anode;
|
||||
if (anode instanceof CharacterData) {
|
||||
return (CharacterData)anode;
|
||||
} else if (anode.getNodeType() == Node.ELEMENT_NODE) {
|
||||
element = (Element)anode;
|
||||
}
|
@@ -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.Iterator;
|
@@ -1,9 +1,14 @@
|
||||
<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:template match="@*|node()">
|
||||
<xsl:copy>
|
||||
<xsl:apply-templates select="@*|node()"/>
|
||||
</xsl:copy>
|
||||
</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>
|
||||
|
Reference in New Issue
Block a user