TSK-925: copied taskana-simplehistory to history folder

This commit is contained in:
Mustapha Zorgati 2019-10-21 04:52:06 +02:00
parent e68c9bae1b
commit 37bcc03c37
49 changed files with 5700 additions and 0 deletions

248
history/pom.xml Normal file
View File

@ -0,0 +1,248 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>pro.taskana.simplehistory</groupId>
<artifactId>taskana-simplehistory-parent</artifactId>
<version>1.1.5-SNAPSHOT</version>
<packaging>pom</packaging>
<name>${project.groupId}:${project.artifactId}</name>
<description>The taskana history events plugin parent and bom module.</description>
<url>http://taskana.pro</url>
<parent>
<groupId>pro.taskana</groupId>
<artifactId>taskana-parent</artifactId>
<relativePath>../</relativePath>
<version>1.1.5-SNAPSHOT</version>
</parent>
<modules>
<module>taskana-simplehistory-provider</module>
<module>taskana-simplehistory-rest-spring</module>
<module>taskana-simplehistory-spring-test</module>
<module>taskana-simplehistory-rest-spring-example</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring.version>5.0.5.RELEASE</spring.version>
<spring.boot.version>2.0.2.RELEASE</spring.boot.version>
<version.h2>1.4.197</version.h2>
<version.junit>4.12</version.junit>
</properties>
<developers>
<developer>
<name>Holger Hagen</name>
<email>holger.hagen@novatec-gmbh.de</email>
<organization>NovaTec Consulting GmbH</organization>
<organizationUrl>https://www.novatec-gmbh.de</organizationUrl>
</developer>
</developers>
<scm>
<url>http://github.com/taskana/TaskanaSimpleHistory/tree/master</url>
<connection>scm:git:git://github.com/taskana/TaskanaSimpleHistory.git</connection>
<developerConnection>scm:git:ssh://github.com:taskana/TaskanaSimpleHistory.git</developerConnection>
</scm>
<licenses>
<license>
<name>The Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
<profiles>
<profile>
<id>snapshot</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.8</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>false</autoReleaseAfterClose>
</configuration>
</plugin>
</plugins>
</build>
<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
</profile>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.8</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>false</autoReleaseAfterClose>
</configuration>
</plugin>
</plugins>
</build>
<distributionManagement>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
</profile>
</profiles>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<versionRange>[1.0.0,)</versionRange>
<goals>
<goal>check</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore/>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.17</version>
<executions>
<execution>
<id>validate</id>
<phase>validate</phase>
<configuration>
<configLocation>../qa/checkstyle/checkstyle.xml</configLocation>
<encoding>UTF-8</encoding>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
<failOnViolation>true</failOnViolation>
<includeTestSourceDirectory>true</includeTestSourceDirectory>
</configuration>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<showWarnings>true</showWarnings>
<compilerArgs>
<arg>-Xlint:all</arg>
</compilerArgs>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<!-- necessary so that the taskana-snapshots are fetched from sonatype-->
<repositories>
<repository>
<id>snapshots-repo</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
</project>

View File

@ -0,0 +1,223 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>taskana-simplehistory-provider</artifactId>
<name>${project.groupId}:${project.artifactId}</name>
<description>The taskana history events plugin to include in your project.</description>
<url>http://taskana.pro</url>
<parent>
<groupId>pro.taskana.simplehistory</groupId>
<artifactId>taskana-simplehistory-parent</artifactId>
<version>1.1.5-SNAPSHOT</version>
</parent>
<licenses>
<license>
<name>The Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
<developers>
<developer>
<name>Holger Hagen</name>
<email>holger.hagen@novatec-gmbh.de</email>
<organization>NovaTec Consulting GmbH</organization>
<organizationUrl>https://www.novatec-gmbh.de</organizationUrl>
</developer>
</developers>
<scm>
<connection>scm:git:git://github.com/taskana/TaskanaSimpleHistory.git</connection>
<developerConnection>scm:git:ssh://github.com:taskana/TaskanaSimpleHistory.git</developerConnection>
<url>http://github.com/taskana/TaskanaSimpleHistory/tree/master</url>
</scm>
<profiles>
<profile>
<id>snapshot</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.8</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>false</autoReleaseAfterClose>
</configuration>
</plugin>
</plugins>
</build>
<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
</profile>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.8</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>false</autoReleaseAfterClose>
</configuration>
</plugin>
</plugins>
</build>
<distributionManagement>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<showWarnings>true</showWarnings>
<compilerArgs>
<arg>-Xlint:all</arg>
</compilerArgs>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>pro.taskana</groupId>
<artifactId>taskana-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.22</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${version.junit}</version>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.6.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.6.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${version.h2}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,15 @@
package pro.taskana.simplehistory;
import pro.taskana.history.api.TaskanaHistory;
/**
* The TaskanaHistoryEngine represents an overall set of all needed services.
*/
public interface TaskanaHistoryEngine {
/**
* The TaskanaHistory can be used for operations on all history events.
*
* @return the HistoryService
*/
TaskanaHistory getTaskanaHistoryService();
}

View File

@ -0,0 +1,81 @@
package pro.taskana.simplehistory.configuration;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Create the schema for the taskana history.
*/
public class DbSchemaCreator {
private static final Logger LOGGER = LoggerFactory.getLogger(DbSchemaCreator.class);
private static final String DB_SCHEMA = "/sql/taskana-history-schema.sql";
private DataSource dataSource;
private String schemaName;
private StringWriter outWriter = new StringWriter();
private PrintWriter logWriter = new PrintWriter(outWriter);
private StringWriter errorWriter = new StringWriter();
private PrintWriter errorLogWriter = new PrintWriter(errorWriter);
public DbSchemaCreator(DataSource dataSource, String schema) throws SQLException {
this.dataSource = dataSource;
this.schemaName = schema;
run();
}
/**
* Run all db scripts.
*
* @throws SQLException
* will be thrown if there will be some incorrect SQL statements invoked.
*/
public void run() throws SQLException {
Connection connection = dataSource.getConnection();
connection.setSchema(schemaName);
ScriptRunner runner = new ScriptRunner(connection);
runner.setStopOnError(true);
runner.setLogWriter(logWriter);
runner.setErrorLogWriter(errorLogWriter);
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(this.getClass()
.getResourceAsStream(DB_SCHEMA)));
runner.runScript(getSqlWithSchemaNameParsed(reader));
} finally {
runner.closeConnection();
}
LOGGER.debug(outWriter.toString());
if (!errorWriter.toString().trim().isEmpty()) {
LOGGER.error(errorWriter.toString());
}
}
private StringReader getSqlWithSchemaNameParsed(BufferedReader reader) {
StringBuffer content = new StringBuffer();
try {
String line = "";
while (line != null) {
line = reader.readLine();
if (line != null) {
content.append(line.replaceAll("%schemaName%", schemaName) + System.lineSeparator());
}
}
} catch (IOException e) {
e.printStackTrace();
LOGGER.error("SchemaName sql parsing failed for schemaName {}", schemaName);
}
return new StringReader(content.toString());
}
}

View File

@ -0,0 +1,14 @@
package pro.taskana.simplehistory.impl;
import pro.taskana.history.api.TaskanaHistoryEvent;
/**
* This entity contains the most important information about a history event.
*/
public class HistoryEventImpl extends TaskanaHistoryEvent {
public HistoryEventImpl() {
super();
}
}

View File

@ -0,0 +1,643 @@
package pro.taskana.simplehistory.impl;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pro.taskana.TimeInterval;
import pro.taskana.exceptions.InvalidArgumentException;
import pro.taskana.simplehistory.impl.mappings.HistoryQueryMapper;
import pro.taskana.simplehistory.query.HistoryQuery;
import pro.taskana.simplehistory.query.HistoryQueryColumnName;
/**
* Implementation for generating dynamic sql.
*/
public class HistoryQueryImpl implements HistoryQuery {
private static final Logger LOGGER = LoggerFactory.getLogger(HistoryQueryImpl.class);
private TaskanaHistoryEngineImpl taskanaHistoryEngine;
private HistoryQueryMapper historyQueryMapper;
private HistoryQueryColumnName columnName;
private List<String> orderBy;
private List<String> orderColumns;
private int maxRows; // limit for rows. used to make list(offset, limit) and single() more efficient.
private String[] idIn;
private String[] businessProcessIdIn;
private String[] parentBusinessProcessIdIn;
private String[] taskIdIn;
private String[] eventTypeIn;
private TimeInterval[] createdIn;
private String[] userIdIn;
private String[] domainIn;
private String[] workbasketKeyIn;
private String[] porCompanyIn;
private String[] porSystemIn;
private String[] porInstanceIn;
private String[] porTypeIn;
private String[] porValueIn;
private String[] taskClassificationKeyIn;
private String[] taskClassificationCategoryIn;
private String[] attachmentClassificationKeyIn;
private String[] commentIn;
private String[] oldValueIn;
private String[] newValueIn;
private String[] custom1In;
private String[] custom2In;
private String[] custom3In;
private String[] custom4In;
private String[] oldDataIn;
private String[] newDataIn;
private String[] businessProcessIdLike;
private String[] parentBusinessProcessIdLike;
private String[] taskIdLike;
private String[] eventTypeLike;
private String[] userIdLike;
private String[] domainLike;
private String[] workbasketKeyLike;
private String[] porCompanyLike;
private String[] porSystemLike;
private String[] porInstanceLike;
private String[] porTypeLike;
private String[] porValueLike;
private String[] taskClassificationKeyLike;
private String[] taskClassificationCategoryLike;
private String[] attachmentClassificationKeyLike;
private String[] commentLike;
private String[] oldValueLike;
private String[] newValueLike;
private String[] custom1Like;
private String[] custom2Like;
private String[] custom3Like;
private String[] custom4Like;
private String[] oldDataLike;
private String[] newDataLike;
public HistoryQueryImpl(TaskanaHistoryEngineImpl taskanaHistoryEngineImpl, HistoryQueryMapper historyQueryMapper) {
this.taskanaHistoryEngine = taskanaHistoryEngineImpl;
this.historyQueryMapper = historyQueryMapper;
this.orderBy = new ArrayList<>();
this.orderColumns = new ArrayList<>();
this.maxRows = -1;
}
@Override
public HistoryQuery idIn(String... idIn) {
this.idIn = toUpperCopy(idIn);
return this;
}
@Override
public HistoryQuery businessProcessIdIn(String... businessProcessId) {
this.businessProcessIdIn = toUpperCopy(businessProcessId);
return this;
}
@Override
public HistoryQuery parentBusinessProcessIdIn(String... parentBusinessProcessId) {
this.parentBusinessProcessIdIn = toUpperCopy(parentBusinessProcessId);
return this;
}
@Override
public HistoryQuery taskIdIn(String... taskId) {
this.taskIdIn = toUpperCopy(taskId);
return this;
}
@Override
public HistoryQuery eventTypeIn(String... eventType) {
this.eventTypeIn = toUpperCopy(eventType);
return this;
}
@Override
public HistoryQuery createdWithin(TimeInterval... createdIn) {
this.createdIn = createdIn;
return this;
}
@Override
public HistoryQuery userIdIn(String... userId) {
this.userIdIn = toUpperCopy(userId);
return this;
}
@Override
public HistoryQuery domainIn(String... domain) {
this.domainIn = toUpperCopy(domain);
return this;
}
@Override
public HistoryQuery workbasketKeyIn(String... workbasketKey) {
this.workbasketKeyIn = toUpperCopy(workbasketKey);
return this;
}
@Override
public HistoryQuery porCompanyIn(String... porCompany) {
this.porCompanyIn = toUpperCopy(porCompany);
return this;
}
@Override
public HistoryQuery porSystemIn(String... porSystem) {
this.porSystemIn = toUpperCopy(porSystem);
return this;
}
@Override
public HistoryQuery porInstanceIn(String... porInstance) {
this.porInstanceIn = toUpperCopy(porInstance);
return this;
}
@Override
public HistoryQuery porTypeIn(String... porType) {
this.porTypeIn = toUpperCopy(porType);
return this;
}
@Override
public HistoryQuery porValueIn(String... porValue) {
this.porValueIn = toUpperCopy(porValue);
return this;
}
@Override
public HistoryQuery taskClassificationKeyIn(String... taskClassificationKey) {
this.taskClassificationKeyIn = toUpperCopy(taskClassificationKey);
return this;
}
@Override
public HistoryQuery taskClassificationCategoryIn(String... taskClassificationCategory) {
this.taskClassificationCategoryIn = toUpperCopy(taskClassificationCategory);
return this;
}
@Override
public HistoryQuery attachmentClassificationKeyIn(String... attachmentClassificationKey) {
this.attachmentClassificationKeyIn = toUpperCopy(attachmentClassificationKey);
return this;
}
@Override
public HistoryQuery commentIn(String... commentIn) {
this.commentIn = toUpperCopy(commentIn);
return this;
}
@Override
public HistoryQuery oldValueIn(String... oldValueIn) {
this.oldValueIn = toUpperCopy(oldValueIn);
return this;
}
@Override
public HistoryQuery newValueIn(String... newValueIn) {
this.newValueIn = toUpperCopy(newValueIn);
return this;
}
@Override
public HistoryQuery custom1In(String... custom1) {
this.custom1In = toUpperCopy(custom1);
return this;
}
@Override
public HistoryQuery custom2In(String... custom2) {
this.custom2In = toUpperCopy(custom2);
return this;
}
@Override
public HistoryQuery custom3In(String... custom3) {
this.custom3In = toUpperCopy(custom3);
return this;
}
@Override
public HistoryQuery custom4In(String... custom4) {
this.custom4In = toUpperCopy(custom4);
return this;
}
@Override
public HistoryQuery oldDataIn(String... oldDataIn) {
this.oldDataIn = toUpperCopy(oldDataIn);
return this;
}
@Override
public HistoryQuery newDataIn(String... newDataIn) {
this.newDataIn = toUpperCopy(newDataIn);
return this;
}
@Override
public HistoryQuery businessProcessIdLike(String... businessProcessId) {
this.businessProcessIdLike = toUpperCopy(businessProcessId);
return this;
}
@Override
public HistoryQuery parentBusinessProcessIdLike(String... parentBusinessProcessId) {
this.parentBusinessProcessIdLike = toUpperCopy(parentBusinessProcessId);
return this;
}
@Override
public HistoryQuery taskIdLike(String... taskId) {
this.taskIdLike = toUpperCopy(taskId);
return this;
}
@Override
public HistoryQuery eventTypeLike(String... eventType) {
this.eventTypeLike = toUpperCopy(eventType);
return this;
}
@Override
public HistoryQuery userIdLike(String... userId) {
this.userIdLike = toUpperCopy(userId);
return this;
}
@Override
public HistoryQuery domainLike(String... domain) {
this.domainLike = toUpperCopy(domain);
return this;
}
@Override
public HistoryQuery workbasketKeyLike(String... workbasketKey) {
this.workbasketKeyLike = toUpperCopy(workbasketKey);
return this;
}
@Override
public HistoryQuery porCompanyLike(String... porCompany) {
this.porCompanyLike = toUpperCopy(porCompany);
return this;
}
@Override
public HistoryQuery porSystemLike(String... porSystem) {
this.porSystemLike = toUpperCopy(porSystem);
return this;
}
@Override
public HistoryQuery porInstanceLike(String... porInstance) {
this.porInstanceLike = toUpperCopy(porInstance);
return this;
}
@Override
public HistoryQuery porTypeLike(String... porType) {
this.porTypeLike = toUpperCopy(porType);
return this;
}
@Override
public HistoryQuery porValueLike(String... porValue) {
this.porValueLike = toUpperCopy(porValue);
return this;
}
@Override
public HistoryQuery taskClassificationKeyLike(String... taskClassificationKey) {
this.taskClassificationKeyLike = toUpperCopy(taskClassificationKey);
return this;
}
@Override
public HistoryQuery taskClassificationCategoryLike(String... taskClassificationCategory) {
this.taskClassificationCategoryLike = toUpperCopy(taskClassificationCategory);
return this;
}
@Override
public HistoryQuery attachmentClassificationKeyLike(String... attachmentClassificationKey) {
this.attachmentClassificationKeyLike = toUpperCopy(attachmentClassificationKey);
return this;
}
@Override
public HistoryQuery commentLike(String... comment) {
this.commentLike = toUpperCopy(comment);
return this;
}
@Override
public HistoryQuery oldValueLike(String... oldValue) {
this.oldValueLike = toUpperCopy(oldValue);
return this;
}
@Override
public HistoryQuery newValueLike(String... newValue) {
this.newValueLike = toUpperCopy(newValue);
return this;
}
@Override
public HistoryQuery custom1Like(String... custom1) {
this.custom1Like = toUpperCopy(custom1);
return this;
}
@Override
public HistoryQuery custom2Like(String... custom2) {
this.custom2Like = toUpperCopy(custom2);
return this;
}
@Override
public HistoryQuery custom3Like(String... custom3) {
this.custom3Like = toUpperCopy(custom3);
return this;
}
@Override
public HistoryQuery custom4Like(String... custom4) {
this.custom4Like = toUpperCopy(custom4);
return this;
}
@Override
public HistoryQuery oldDataLike(String... oldData) {
this.oldDataLike = toUpperCopy(oldData);
return this;
}
@Override
public HistoryQuery newDataLike(String... newData) {
this.newDataLike = toUpperCopy(newData);
return this;
}
@Override
public HistoryQuery orderByBusinessProcessId(SortDirection sortDirection) {
return addOrderCriteria("BUSINESS_PROCESS_ID", sortDirection);
}
@Override
public HistoryQuery orderByParentBusinessProcessId(SortDirection sortDirection) {
return addOrderCriteria("PARENT_BUSINESS_PROCESS_ID", sortDirection);
}
@Override
public HistoryQuery orderByTaskId(SortDirection sortDirection) {
return addOrderCriteria("TASK_ID", sortDirection);
}
@Override
public HistoryQuery orderByEventType(SortDirection sortDirection) {
return addOrderCriteria("EVENT_TYPE", sortDirection);
}
@Override
public HistoryQuery orderByCreated(SortDirection sortDirection) {
return addOrderCriteria("CREATED", sortDirection);
}
@Override
public HistoryQuery orderByUserId(SortDirection sortDirection) {
return addOrderCriteria("USER_ID", sortDirection);
}
@Override
public HistoryQuery orderByDomain(SortDirection sortDirection) {
return addOrderCriteria("DOMAIN", sortDirection);
}
@Override
public HistoryQuery orderByWorkbasketKey(SortDirection sortDirection) {
return addOrderCriteria("WORKBASKET_KEY", sortDirection);
}
@Override
public HistoryQuery orderByPorCompany(SortDirection sortDirection) {
return addOrderCriteria("POR_COMPANY", sortDirection);
}
@Override
public HistoryQuery orderByPorSystem(SortDirection sortDirection) {
return addOrderCriteria("POR_SYSTEM", sortDirection);
}
@Override
public HistoryQuery orderByPorInstance(SortDirection sortDirection) {
return addOrderCriteria("POR_INSTANCE", sortDirection);
}
@Override
public HistoryQuery orderByPorType(SortDirection sortDirection) {
return addOrderCriteria("POR_TYPE", sortDirection);
}
@Override
public HistoryQuery orderByPorValue(SortDirection sortDirection) {
return addOrderCriteria("POR_VALUE", sortDirection);
}
@Override
public HistoryQuery orderByTaskClassificationKey(SortDirection sortDirection) {
return addOrderCriteria("TASK_CLASSIFICATION_KEY", sortDirection);
}
@Override
public HistoryQuery orderByTaskClassificationCategory(SortDirection sortDirection) {
return addOrderCriteria("TASK_CLASSIFICATION_CATEGORY", sortDirection);
}
@Override
public HistoryQuery orderByAttachmentClassificationKey(SortDirection sortDirection) {
return addOrderCriteria("ATTACHMENT_CLASSIFICATION_KEY", sortDirection);
}
@Override
public HistoryQuery orderByComment(SortDirection sortDirection) {
return addOrderCriteria("COMMENT", sortDirection);
}
@Override
public HistoryQuery orderByOldValue(SortDirection sortDirection) {
return addOrderCriteria("OLD_VALUE", sortDirection);
}
@Override
public HistoryQuery orderByNewValue(SortDirection sortDirection) {
return addOrderCriteria("NEW_VALUE", sortDirection);
}
@Override
public HistoryQuery orderByOldData(SortDirection sortDirection) {
return addOrderCriteria("OLD_DATA", sortDirection);
}
@Override
public HistoryQuery orderByNewData(SortDirection sortDirection) {
return addOrderCriteria("NEW_DATA", sortDirection);
}
@Override
public HistoryQuery orderByCustomAttribute(int num, SortDirection sortDirection)
throws InvalidArgumentException {
switch (num) {
case 1:
return addOrderCriteria("CUSTOM_1", sortDirection);
case 2:
return addOrderCriteria("CUSTOM_2", sortDirection);
case 3:
return addOrderCriteria("CUSTOM_3", sortDirection);
case 4:
return addOrderCriteria("CUSTOM_4", sortDirection);
default:
throw new InvalidArgumentException("Custom number has to be between 1 and 4, but this is: " + num);
}
}
@Override
public List<HistoryEventImpl> list() {
LOGGER.debug("entry to list(), this = {}", this);
List<HistoryEventImpl> result = new ArrayList<>();
try {
taskanaHistoryEngine.openConnection();
result = historyQueryMapper.queryHistoryEvent(this);
LOGGER.debug("transaction was successful. Result: {}", result.toString());
return result;
} catch (SQLException e) {
LOGGER.error("Method openConnection() could not open a connection to the database.",
e.getCause());
return result;
} catch (NullPointerException npe) {
LOGGER.error("No History Event found.");
return result;
} finally {
taskanaHistoryEngine.returnConnection();
}
}
@Override
public List<HistoryEventImpl> list(int offset, int limit) {
LOGGER.debug("entry to list({},{}), this = {}", offset, limit, this);
List<HistoryEventImpl> result = new ArrayList<>();
try {
taskanaHistoryEngine.openConnection();
this.maxRows = offset + limit;
result = historyQueryMapper.queryHistoryEvent(this);
LOGGER.debug("transaction was successful. Result: {}", result.toString());
limit = Math.min(result.size() - offset, limit);
if (result.size() > offset) {
return result.subList(offset, offset + limit);
} else {
return new ArrayList<>();
}
} catch (SQLException e) {
LOGGER.error("Method openConnection() could not open a connection to the database.",
e.getCause());
return result;
} catch (NullPointerException npe) {
LOGGER.error("No History Event found.");
return result;
} finally {
taskanaHistoryEngine.returnConnection();
this.maxRows = -1;
}
}
@Override
public List<String> listValues(HistoryQueryColumnName dbColumnName, SortDirection sortDirection) {
LOGGER.debug("entry to listValues() of column {} with sortDirection {}, this {}", dbColumnName, sortDirection,
this);
List<String> result = new ArrayList<>();
this.columnName = dbColumnName;
List<String> cacheOrderBy = this.orderBy;
this.orderBy.clear();
this.addOrderCriteria(columnName.toString(), sortDirection);
try {
taskanaHistoryEngine.openConnection();
result = historyQueryMapper.queryHistoryColumnValues(this);
LOGGER.debug("transaction was successful. Result: {}", result.toString());
return result;
} catch (SQLException e) {
LOGGER.error("Method openConnection() could not open a connection to the database.",
e.getCause());
return result;
} catch (NullPointerException npe) {
LOGGER.error("No History Event found.");
return result;
} finally {
this.orderBy = cacheOrderBy;
this.columnName = null;
this.orderColumns.remove(orderColumns.size() - 1);
taskanaHistoryEngine.returnConnection();
}
}
@Override
public HistoryEventImpl single() {
LOGGER.debug("entry to list(), this = {}", this);
HistoryEventImpl result = new HistoryEventImpl();
try {
taskanaHistoryEngine.openConnection();
this.maxRows = 1;
result = historyQueryMapper.queryHistoryEvent(this).get(0);
LOGGER.debug("transaction was successful. Result: {}", result.toString());
return result;
} catch (SQLException e) {
LOGGER.error("Method openConnection() could not open a connection to the database.",
e.getCause());
return result;
} catch (NullPointerException npe) {
LOGGER.error("No History Event found.");
return result;
} finally {
taskanaHistoryEngine.returnConnection();
this.maxRows = -1;
}
}
@Override
public long count() {
LOGGER.debug("entry to count(), this = {}", this);
try {
taskanaHistoryEngine.openConnection();
long result = historyQueryMapper.countHistoryEvent(this);
LOGGER.debug("transaction was successful. Result: {}", result);
return result;
} catch (SQLException e) {
LOGGER.error("Method openConnection() could not open a connection to the database.",
e.getCause());
return -1;
} catch (NullPointerException npe) {
LOGGER.error("No History Event found.");
return -1;
} finally {
taskanaHistoryEngine.returnConnection();
}
}
private HistoryQueryImpl addOrderCriteria(String columnName, SortDirection sortDirection) {
String orderByDirection = " " + (sortDirection == null ? SortDirection.ASCENDING : sortDirection);
orderBy.add(columnName.toString() + orderByDirection);
orderColumns.add(columnName.toString());
return this;
}
}

View File

@ -0,0 +1,63 @@
package pro.taskana.simplehistory.impl;
import java.sql.SQLException;
import java.time.Instant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pro.taskana.configuration.TaskanaEngineConfiguration;
import pro.taskana.history.api.TaskanaHistory;
import pro.taskana.history.api.TaskanaHistoryEvent;
import pro.taskana.simplehistory.impl.mappings.HistoryEventMapper;
import pro.taskana.simplehistory.impl.mappings.HistoryQueryMapper;
import pro.taskana.simplehistory.query.HistoryQuery;
/**
* This is the implementation of TaskanaHistory.
*/
public class SimpleHistoryServiceImpl implements TaskanaHistory {
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleHistoryServiceImpl.class);
private TaskanaHistoryEngineImpl taskanaHistoryEngine;
private HistoryEventMapper historyEventMapper;
private HistoryQueryMapper historyQueryMapper;
@Override
public void initialize(TaskanaEngineConfiguration taskanaEngineConfiguration) {
try {
this.taskanaHistoryEngine = TaskanaHistoryEngineImpl.createTaskanaEngine(taskanaEngineConfiguration);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Simple history service implementation initialized with schemaName: {} ",
taskanaEngineConfiguration.getSchemaName());
}
} catch (SQLException e) {
LOGGER.error("There was an error creating Taskana history engine", e);
e.printStackTrace();
}
this.historyEventMapper = this.taskanaHistoryEngine.getSqlSession().getMapper(HistoryEventMapper.class);
this.historyQueryMapper = this.taskanaHistoryEngine.getSqlSession().getMapper(HistoryQueryMapper.class);
}
@Override
public void create(TaskanaHistoryEvent event) {
try {
taskanaHistoryEngine.openConnection();
if (event.getCreated() == null) {
Instant now = Instant.now();
event.setCreated(now);
}
historyEventMapper.insert(event);
} catch (SQLException e) {
e.printStackTrace();
} finally {
taskanaHistoryEngine.returnConnection();
LOGGER.debug("exit from create(TaskanaHistoryEvent event). Returning object = {}.", event);
}
}
public HistoryQuery createHistoryQuery() {
return new HistoryQueryImpl(taskanaHistoryEngine, historyQueryMapper);
}
}

View File

@ -0,0 +1,179 @@
package pro.taskana.simplehistory.impl;
import java.sql.SQLException;
import java.util.ArrayDeque;
import java.util.Deque;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.session.SqlSessionManager;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.apache.ibatis.transaction.managed.ManagedTransactionFactory;
import pro.taskana.configuration.TaskanaEngineConfiguration;
import pro.taskana.history.api.TaskanaHistory;
import pro.taskana.simplehistory.TaskanaHistoryEngine;
import pro.taskana.simplehistory.configuration.DbSchemaCreator;
import pro.taskana.simplehistory.impl.mappings.HistoryEventMapper;
import pro.taskana.simplehistory.impl.mappings.HistoryQueryMapper;
/**
* This is the implementation of TaskanaHistoryEngine.
*/
public class TaskanaHistoryEngineImpl implements TaskanaHistoryEngine {
private static final String DEFAULT = "default";
TaskanaEngineConfiguration taskanaEngineConfiguration;
protected SqlSessionManager sessionManager;
protected TransactionFactory transactionFactory;
protected java.sql.Connection connection = null;
protected DbSchemaCreator dbSchemaCreator;
protected static ThreadLocal<Deque<SqlSessionManager>> sessionStack = new ThreadLocal<>();
protected TaskanaHistory taskanaHistoryService;
protected TaskanaHistoryEngineImpl(TaskanaEngineConfiguration taskanaEngineConfiguration) throws SQLException {
this.taskanaEngineConfiguration = taskanaEngineConfiguration;
createTransactionFactory(this.taskanaEngineConfiguration.getUseManagedTransactions());
this.sessionManager = createSqlSessionManager();
dbSchemaCreator = new DbSchemaCreator(taskanaEngineConfiguration.getDatasource(),
taskanaEngineConfiguration.getSchemaName());
}
public static TaskanaHistoryEngineImpl createTaskanaEngine(
TaskanaEngineConfiguration taskanaEngineConfiguration) throws SQLException {
return new TaskanaHistoryEngineImpl(taskanaEngineConfiguration);
}
@Override
public TaskanaHistory getTaskanaHistoryService() {
if (taskanaHistoryService == null) {
SimpleHistoryServiceImpl historyService = new SimpleHistoryServiceImpl();
historyService.initialize(taskanaEngineConfiguration);
this.taskanaHistoryService = historyService;
}
return this.taskanaHistoryService;
}
/**
* Open the connection to the database. to be called at the begin of each Api call that accesses the database
*
* @throws SQLException
* thrown if the connection could not be opened.
*/
void openConnection() throws SQLException {
initSqlSession();
this.sessionManager.getConnection().setSchema(taskanaEngineConfiguration.getSchemaName());
}
/**
* Returns the database connection into the pool. In the case of nested calls, simply pops the latest session from
* the session stack. Closes the connection if the session stack is empty. In mode AUTOCOMMIT commits before the
* connection is closed. To be called at the end of each Api call that accesses the database
*/
void returnConnection() {
popSessionFromStack();
if (getSessionStack().isEmpty()
&& this.sessionManager != null && this.sessionManager.isManagedSessionStarted()) {
try {
this.sessionManager.commit();
} catch (Exception e) {
}
this.sessionManager.close();
}
}
/**
* Initializes the SqlSessionManager.
*/
void initSqlSession() {
this.sessionManager.startManagedSession();
}
/**
* retrieve the SqlSession used by taskana.
*
* @return the myBatis SqlSession object used by taskana
*/
SqlSession getSqlSession() {
return this.sessionManager;
}
/**
* creates the MyBatis transaction factory.
*
* @param useManagedTransactions
* true if TASKANA should use a ManagedTransactionFactory.
*/
private void createTransactionFactory(boolean useManagedTransactions) {
if (useManagedTransactions) {
this.transactionFactory = new ManagedTransactionFactory();
} else {
this.transactionFactory = new JdbcTransactionFactory();
}
}
protected SqlSessionManager createSqlSessionManager() {
Environment environment = new Environment(DEFAULT, this.transactionFactory,
taskanaEngineConfiguration.getDatasource());
Configuration configuration = new Configuration(environment);
// add mappers
configuration.addMapper(HistoryEventMapper.class);
configuration.addMapper(HistoryQueryMapper.class);
SqlSessionFactory localSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
return SqlSessionManager.newInstance(localSessionFactory);
}
protected static void pushSessionToStack(SqlSessionManager session) {
getSessionStack().push(session);
}
protected static void popSessionFromStack() {
Deque<SqlSessionManager> stack = getSessionStack();
if (!stack.isEmpty()) {
stack.pop();
}
}
/**
* With sessionStack, we maintain a Stack of SqlSessionManager objects on a per thread basis. SqlSessionManager is
* the MyBatis object that wraps database connections. The purpose of this stack is to keep track of nested calls.
* Each external API call is wrapped into taskanaEngineImpl.openConnection(); .....
* taskanaEngineImpl.returnConnection(); calls. In order to avoid duplicate opening / closing of connections, we use
* the sessionStack in the following way: Each time, an openConnection call is received, we push the current
* sessionManager onto the stack. On the first call to openConnection, we call sessionManager.startManagedSession()
* to open a database connection. On each call to returnConnection() we pop one instance of sessionManager from the
* stack. When the stack becomes empty, we close the database connection by calling sessionManager.close()
*
* @return Stack of SqlSessionManager
*/
protected static Deque<SqlSessionManager> getSessionStack() {
Deque<SqlSessionManager> stack = sessionStack.get();
if (stack == null) {
stack = new ArrayDeque<>();
sessionStack.set(stack);
}
return stack;
}
protected static SqlSessionManager getSessionFromStack() {
Deque<SqlSessionManager> stack = getSessionStack();
if (stack.isEmpty()) {
return null;
}
return stack.peek();
}
}

View File

@ -0,0 +1,28 @@
package pro.taskana.simplehistory.impl.mappings;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import pro.taskana.history.api.TaskanaHistoryEvent;
/**
* This class is the mybatis mapping of workbaskets.
*/
public interface HistoryEventMapper {
@Insert(
"<script>INSERT INTO HISTORY_EVENTS (BUSINESS_PROCESS_ID, PARENT_BUSINESS_PROCESS_ID, TASK_ID,"
+ " EVENT_TYPE, CREATED, USER_ID, DOMAIN, WORKBASKET_KEY, POR_COMPANY, POR_SYSTEM, POR_INSTANCE,"
+ " POR_TYPE, POR_VALUE, TASK_CLASSIFICATION_KEY, TASK_CLASSIFICATION_CATEGORY, ATTACHMENT_CLASSIFICATION_KEY, "
+ " COMMENT, OLD_VALUE, NEW_VALUE, CUSTOM_1, CUSTOM_2, CUSTOM_3, CUSTOM_4, OLD_DATA, NEW_DATA)"
+ " VALUES ( #{historyEvent.businessProcessId}, #{historyEvent.parentBusinessProcessId}, #{historyEvent.taskId},"
+ " #{historyEvent.eventType}, #{historyEvent.created}, #{historyEvent.userId}, #{historyEvent.domain}, #{historyEvent.workbasketKey},"
+ " #{historyEvent.porCompany}, #{historyEvent.porSystem}, #{historyEvent.porInstance}, #{historyEvent.porType},"
+ " #{historyEvent.porValue}, #{historyEvent.taskClassificationKey}, #{historyEvent.taskClassificationCategory},"
+ " #{historyEvent.attachmentClassificationKey}, #{historyEvent.comment}, #{historyEvent.oldValue}, #{historyEvent.newValue},"
+ " #{historyEvent.custom1}, #{historyEvent.custom2}, #{historyEvent.custom3}, #{historyEvent.custom4},"
+ " #{historyEvent.oldData}, #{historyEvent.newData}) "
+ "</script>")
void insert(@Param("historyEvent") TaskanaHistoryEvent historyEvent);
}

View File

@ -0,0 +1,229 @@
package pro.taskana.simplehistory.impl.mappings;
import java.util.List;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import pro.taskana.simplehistory.impl.HistoryEventImpl;
import pro.taskana.simplehistory.impl.HistoryQueryImpl;
/**
* This class is the mybatis mapping of historyQueries.
*/
public interface HistoryQueryMapper {
@Select(
"<script>"
+ "SELECT ID, BUSINESS_PROCESS_ID, PARENT_BUSINESS_PROCESS_ID, TASK_ID, EVENT_TYPE, CREATED, USER_ID, DOMAIN, WORKBASKET_KEY, "
+ "POR_COMPANY, POR_SYSTEM, POR_INSTANCE, POR_TYPE, POR_VALUE, TASK_CLASSIFICATION_KEY, TASK_CLASSIFICATION_CATEGORY,"
+ "ATTACHMENT_CLASSIFICATION_KEY, COMMENT, OLD_VALUE, NEW_VALUE, CUSTOM_1, CUSTOM_2, CUSTOM_3, CUSTOM_4, OLD_DATA, NEW_DATA "
+ "FROM HISTORY_EVENTS"
+ "<where>"
// IN-Queries
+ "<if test='idIn != null'>AND UPPER(ID) IN (<foreach item='item' collection='idIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='businessProcessIdIn != null'>AND UPPER(BUSINESS_PROCESS_ID) IN (<foreach item='item' collection='businessProcessIdIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='parentBusinessProcessIdIn != null'>AND UPPER(PARENT_BUSINESS_PROCESS_ID) IN (<foreach item='item' collection='parentBusinessProcessIdIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='taskIdIn != null'>AND UPPER(TASK_ID) IN (<foreach item='item' collection='taskIdIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='eventTypeIn != null'>AND UPPER(EVENT_TYPE) IN (<foreach item='item' collection='eventTypeIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='createdIn !=null'> AND ( <foreach item='item' collection='createdIn' separator=',' > ( <if test='item.begin!=null'> CREATED &gt;= #{item.begin} </if> <if test='item.begin!=null and item.end!=null'> AND </if><if test='item.end!=null'> CREATED &lt;=#{item.end} </if>)</foreach>)</if> "
+ "<if test='userIdIn != null'>AND UPPER(USER_ID) IN (<foreach item='item' collection='userIdIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='domainIn != null'>AND UPPER(DOMAIN) IN (<foreach item='item' collection='domainIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='workbasketKeyIn != null'>AND UPPER(WORKBASKET_KEY) IN (<foreach item='item' collection='workbasketKeyIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='porCompanyIn != null'>AND UPPER(POR_COMPANY) IN (<foreach item='item' collection='porCompanyIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='porSystemIn != null'>AND UPPER(POR_SYSTEM) IN (<foreach item='item' collection='porSystemIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='porInstanceIn != null'>AND UPPER(POR_INSTANCE) IN (<foreach item='item' collection='porInstanceIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='porTypeIn != null'>AND UPPER(POR_TYPE) IN (<foreach item='item' collection='porTypeIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='porValueIn != null'>AND UPPER(POR_VALUE) IN (<foreach item='item' collection='porValueIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='taskClassificationKeyIn != null'>AND UPPER(TASK_CLASSIFICATION_KEY) IN (<foreach item='item' collection='taskClassificationKeyIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='taskClassificationCategoryIn != null'>AND UPPER(TASK_CLASSIFICATION_CATEGORY) IN (<foreach item='item' collection='taskClassificationCategoryIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='attachmentClassificationKeyIn != null'>AND UPPER(ATTACHMENT_CLASSIFICATION_KEY) IN (<foreach item='item' collection='attachmentClassificationKeyIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='commentIn != null'>AND UPPER(COMMENT) IN (<foreach item='item' collection='commentIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='oldValueIn != null'>AND UPPER(OLD_VALUE) IN (<foreach item='item' collection='oldValueIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='newValueIn != null'>AND UPPER(NEW_VALUE) IN (<foreach item='item' collection='newValueIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='custom1In != null'>AND UPPER(CUSTOM_1) IN (<foreach item='item' collection='custom1In' separator=',' >#{item}</foreach>)</if> "
+ "<if test='custom2In != null'>AND UPPER(CUSTOM_2) IN (<foreach item='item' collection='custom2In' separator=',' >#{item}</foreach>)</if> "
+ "<if test='custom3In != null'>AND UPPER(CUSTOM_3) IN (<foreach item='item' collection='custom3In' separator=',' >#{item}</foreach>)</if> "
+ "<if test='custom4In != null'>AND UPPER(CUSTOM_4) IN (<foreach item='item' collection='custom4In' separator=',' >#{item}</foreach>)</if> "
+ "<if test='oldDataIn != null'>AND UPPER(OLD_DATA) IN (<foreach item='item' collection='oldDataIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='newDataIn != null'>AND UPPER(NEW_DATA) IN (<foreach item='item' collection='newDataIn' separator=',' >#{item}</foreach>)</if> "
// LIKE-Queries
+ "<if test='businessProcessIdLike != null'>AND (<foreach item='item' collection='businessProcessIdLike' separator='OR' > UPPER(BUSINESS_PROCESS_ID) LIKE #{item} </foreach>)</if> "
+ "<if test='parentBusinessProcessIdLike != null'>AND (<foreach item='item' collection='parentBusinessProcessIdLike' separator=' OR ' >UPPER(PARENT_BUSINESS_PROCESS_ID) LIKE #{item}</foreach>)</if> "
+ "<if test='taskIdLike != null'>AND (<foreach item='item' collection='taskIdLike' separator=' OR ' >UPPER(TASK_ID) LIKE #{item}</foreach>)</if> "
+ "<if test='eventTypeLike != null'>AND (<foreach item='item' collection='eventTypeLike' separator=' OR ' >UPPER(EVENT_TYPE) LIKE #{item}</foreach>)</if> "
+ "<if test='userIdLike != null'>AND (<foreach item='item' collection='userIdLike' separator=' OR ' >UPPER(USER_ID) LIKE #{item}</foreach>)</if> "
+ "<if test='domainLike != null'>AND (<foreach item='item' collection='domainLike' separator=' OR ' >UPPER(DOMAIN) LIKE #{item}</foreach>)</if> "
+ "<if test='workbasketKeyLike != null'>AND (<foreach item='item' collection='workbasketKeyLike' separator=' OR ' >UPPER(WORKBASKET_KEY) LIKE #{item}</foreach>)</if> "
+ "<if test='porCompanyLike != null'>AND (<foreach item='item' collection='porCompanyLike' separator=' OR ' >UPPER(POR_COMPANY) LIKE #{item}</foreach>)</if> "
+ "<if test='porSystemLike != null'>AND (<foreach item='item' collection='porSystemLike' separator=' OR ' >UPPER(POR_SYSTEM) LIKE #{item}</foreach>)</if> "
+ "<if test='porInstanceLike != null'>AND (<foreach item='item' collection='porInstanceLike' separator=' OR ' >UPPER(POR_INSTANCE) LIKE #{item}</foreach>)</if> "
+ "<if test='porTypeLike != null'>AND (<foreach item='item' collection='porTypeLike' separator=' OR ' >UPPER(POR_TYPE) LIKE #{item}</foreach>)</if> "
+ "<if test='porValueLike != null'>AND (<foreach item='item' collection='porValueLike' separator=' OR ' >UPPER(POR_VALUE) LIKE #{item}</foreach>)</if> "
+ "<if test='taskClassificationKeyLike != null'>AND (<foreach item='item' collection='taskClassificationKeyLike' separator=' OR ' >UPPER(TASK_CLASSIFICATION_KEY) LIKE #{item}</foreach>)</if> "
+ "<if test='taskClassificationCategoryLike != null'>AND (<foreach item='item' collection='taskClassificationCategoryLike' separator=' OR ' >UPPER(TASK_CLASSIFICATION_CATEGORY) LIKE #{item}</foreach>)</if> "
+ "<if test='attachmentClassificationKeyLike != null'>AND (<foreach item='item' collection='attachmentClassificationKeyLike' separator=' OR ' >UPPER(ATTACHMENT_CLASSIFICATION_KEY) LIKE #{item}</foreach>)</if> "
+ "<if test='commentLike != null'>AND (<foreach item='item' collection='commentLike' separator=' OR ' >UPPER(COMMENT) LIKE #{item}</foreach>)</if> "
+ "<if test='oldValueLike != null'>AND (<foreach item='item' collection='oldValueLike' separator=' OR ' >UPPER(OLD_VALUE) LIKE #{item}</foreach>)</if> "
+ "<if test='newValueLike != null'>AND (<foreach item='item' collection='newValueLike' separator=' OR ' >UPPER(NEW_VALUE) LIKE #{item}</foreach>)</if> "
+ "<if test='custom1Like != null'>AND (<foreach item='item' collection='custom1Like' separator=' OR ' >UPPER(CUSTOM_1) LIKE #{item}</foreach>)</if> "
+ "<if test='custom2Like != null'>AND (<foreach item='item' collection='custom2Like' separator=' OR ' >UPPER(CUSTOM_2) LIKE #{item}</foreach>)</if> "
+ "<if test='custom3Like != null'>AND (<foreach item='item' collection='custom3Like' separator=' OR ' >UPPER(CUSTOM_3) LIKE #{item}</foreach>)</if> "
+ "<if test='custom4Like != null'>AND (<foreach item='item' collection='custom4Like' separator=' OR ' >UPPER(CUSTOM_4) LIKE #{item}</foreach>)</if> "
+ "<if test='oldDataLike != null'>AND (<foreach item='item' collection='oldDataLike' separator=' OR ' >UPPER(OLD_DATA) LIKE #{item}</foreach>)</if> "
+ "<if test='newDataLike != null'>AND (<foreach item='item' collection='newDataLike' separator=' OR ' >UPPER(NEW_DATA) LIKE #{item}</foreach>)</if> "
+ "</where>"
+ "<if test='!orderBy.isEmpty()'>ORDER BY <foreach item='item' collection='orderBy' separator=',' >${item}</foreach></if> "
+ "<if test='maxRows > 0'> FETCH FIRST #{maxRows} ROWS ONLY </if>"
+ "</script>")
@Results(value = {
@Result(property = "id", column = "ID"),
@Result(property = "businessProcessId", column = "BUSINESS_PROCESS_ID"),
@Result(property = "parentBusinessProcessId", column = "PARENT_BUSINESS_PROCESS_ID"),
@Result(property = "taskId", column = "TASK_ID"),
@Result(property = "eventType", column = "EVENT_TYPE"),
@Result(property = "created", column = "CREATED"),
@Result(property = "userId", column = "USER_ID"),
@Result(property = "domain", column = "DOMAIN"),
@Result(property = "workbasketKey", column = "WORKBASKET_KEY"),
@Result(property = "porCompany", column = "POR_COMPANY"),
@Result(property = "porSystem", column = "POR_SYSTEM"),
@Result(property = "porInstance", column = "POR_INSTANCE"),
@Result(property = "porType", column = "POR_TYPE"),
@Result(property = "porValue", column = "POR_VALUE"),
@Result(property = "taskClassificationKey", column = "TASK_CLASSIFICATION_KEY"),
@Result(property = "taskClassificationCategory", column = "TASK_CLASSIFICATION_CATEGORY"),
@Result(property = "attachmentClassificationKey", column = "ATTACHMENT_CLASSIFICATION_KEY"),
@Result(property = "comment", column = "COMMENT"),
@Result(property = "oldValue", column = "OLD_VALUE"),
@Result(property = "newValue", column = "NEW_VALUE"),
@Result(property = "custom1", column = "CUSTOM_1"),
@Result(property = "custom2", column = "CUSTOM_2"),
@Result(property = "custom3", column = "CUSTOM_3"),
@Result(property = "custom4", column = "CUSTOM_4"),
@Result(property = "oldData", column = "OLD_DATA"),
@Result(property = "newData", column = "NEW_DATA")
})
List<HistoryEventImpl> queryHistoryEvent(HistoryQueryImpl historyEventQuery);
@Select(
"<script>"
+ "SELECT COUNT(ID) "
+ "FROM HISTORY_EVENTS"
+ "<where>"
// IN-Queries
+ "<if test='businessProcessIdIn != null'>AND UPPER(BUSINESS_PROCESS_ID) IN (<foreach item='item' collection='businessProcessIdIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='parentBusinessProcessIdIn != null'>AND UPPER(PARENT_BUSINESS_PROCESS_ID) IN (<foreach item='item' collection='parentBusinessProcessIdIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='taskIdIn != null'>AND UPPER(TASK_ID) IN (<foreach item='item' collection='taskIdIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='eventTypeIn != null'>AND UPPER(EVENT_TYPE) IN (<foreach item='item' collection='eventTypeIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='createdIn !=null'> AND ( <foreach item='item' collection='createdIn' separator=',' > ( <if test='item.begin!=null'> CREATED &gt;= #{item.begin} </if> <if test='item.begin!=null and item.end!=null'> AND </if><if test='item.end!=null'> CREATED &lt;=#{item.end} </if>)</foreach>)</if> "
+ "<if test='userIdIn != null'>AND UPPER(USER_ID) IN (<foreach item='item' collection='userIdIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='domainIn != null'>AND UPPER(DOMAIN) IN (<foreach item='item' collection='domainIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='workbasketKeyIn != null'>AND UPPER(WORKBASKET_KEY) IN (<foreach item='item' collection='workbasketKeyIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='porCompanyIn != null'>AND UPPER(POR_COMPANY) IN (<foreach item='item' collection='porCompanyIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='porSystemIn != null'>AND UPPER(POR_SYSTEM) IN (<foreach item='item' collection='porSystemIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='porInstanceIn != null'>AND UPPER(POR_INSTANCE) IN (<foreach item='item' collection='porInstanceIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='porTypeIn != null'>AND UPPER(POR_TYPE) IN (<foreach item='item' collection='porTypeIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='porValueIn != null'>AND UPPER(POR_VALUE) IN (<foreach item='item' collection='porValueIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='taskClassificationKeyIn != null'>AND UPPER(TASK_CLASSIFICATION_KEY) IN (<foreach item='item' collection='taskClassificationKeyIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='taskClassificationCategoryIn != null'>AND UPPER(TASK_CLASSIFICATION_CATEGORY) IN (<foreach item='item' collection='taskClassificationCategoryIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='attachmentClassificationKeyIn != null'>AND UPPER(ATTACHMENT_CLASSIFICATION_KEY) IN (<foreach item='item' collection='attachmentClassificationKeyIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='commentIn != null'>AND UPPER(COMMENT) IN (<foreach item='item' collection='commentIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='oldValueIn != null'>AND UPPER(OLD_VALUE) IN (<foreach item='item' collection='oldValueIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='newValueIn != null'>AND UPPER(NEW_VALUE) IN (<foreach item='item' collection='newValueIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='custom1In != null'>AND UPPER(CUSTOM_1) IN (<foreach item='item' collection='custom1In' separator=',' >#{item}</foreach>)</if> "
+ "<if test='custom2In != null'>AND UPPER(CUSTOM_2) IN (<foreach item='item' collection='custom2In' separator=',' >#{item}</foreach>)</if> "
+ "<if test='custom3In != null'>AND UPPER(CUSTOM_3) IN (<foreach item='item' collection='custom3In' separator=',' >#{item}</foreach>)</if> "
+ "<if test='custom4In != null'>AND UPPER(CUSTOM_4) IN (<foreach item='item' collection='custom4In' separator=',' >#{item}</foreach>)</if> "
+ "<if test='oldDataIn != null'>AND UPPER(OLD_DATA) IN (<foreach item='item' collection='oldDataIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='newDataIn != null'>AND UPPER(NEW_DATA) IN (<foreach item='item' collection='newDataIn' separator=',' >#{item}</foreach>)</if> "
// LIKE-Queries
+ "<if test='businessProcessIdLike != null'>AND (<foreach item='item' collection='businessProcessIdLike' separator='OR' > UPPER(BUSINESS_PROCESS_ID) LIKE #{item} </foreach>)</if> "
+ "<if test='parentBusinessProcessIdLike != null'>AND (<foreach item='item' collection='parentBusinessProcessIdLike' separator=' OR ' >UPPER(PARENT_BUSINESS_PROCESS_ID) LIKE #{item}</foreach>)</if> "
+ "<if test='taskIdLike != null'>AND (<foreach item='item' collection='taskIdLike' separator=' OR ' >UPPER(TASK_ID) LIKE #{item}</foreach>)</if> "
+ "<if test='eventTypeLike != null'>AND (<foreach item='item' collection='eventTypeLike' separator=' OR ' >UPPER(EVENT_TYPE) LIKE #{item}</foreach>)</if> "
+ "<if test='userIdLike != null'>AND (<foreach item='item' collection='userIdLike' separator=' OR ' >UPPER(USER_ID) LIKE #{item}</foreach>)</if> "
+ "<if test='domainLike != null'>AND (<foreach item='item' collection='domainLike' separator=' OR ' >UPPER(DOMAIN) LIKE #{item}</foreach>)</if> "
+ "<if test='workbasketKeyLike != null'>AND (<foreach item='item' collection='workbasketKeyLike' separator=' OR ' >UPPER(WORKBASKET_KEY) LIKE #{item}</foreach>)</if> "
+ "<if test='porCompanyLike != null'>AND (<foreach item='item' collection='porCompanyLike' separator=' OR ' >UPPER(POR_COMPANY) LIKE #{item}</foreach>)</if> "
+ "<if test='porSystemLike != null'>AND (<foreach item='item' collection='porSystemLike' separator=' OR ' >UPPER(POR_SYSTEM) LIKE #{item}</foreach>)</if> "
+ "<if test='porInstanceLike != null'>AND (<foreach item='item' collection='porInstanceLike' separator=' OR ' >UPPER(POR_INSTANCE) LIKE #{item}</foreach>)</if> "
+ "<if test='porTypeLike != null'>AND (<foreach item='item' collection='porTypeLike' separator=' OR ' >UPPER(POR_TYPE) LIKE #{item}</foreach>)</if> "
+ "<if test='porValueLike != null'>AND (<foreach item='item' collection='porValueLike' separator=' OR ' >UPPER(POR_VALUE) LIKE #{item}</foreach>)</if> "
+ "<if test='taskClassificationKeyLike != null'>AND (<foreach item='item' collection='taskClassificationKeyLike' separator=' OR ' >UPPER(TASK_CLASSIFICATION_KEY) LIKE #{item}</foreach>)</if> "
+ "<if test='taskClassificationCategoryLike != null'>AND (<foreach item='item' collection='taskClassificationCategoryLike' separator=' OR ' >UPPER(TASK_CLASSIFICATION_CATEGORY) LIKE #{item}</foreach>)</if> "
+ "<if test='attachmentClassificationKeyLike != null'>AND (<foreach item='item' collection='attachmentClassificationKeyLike' separator=' OR ' >UPPER(ATTACHMENT_CLASSIFICATION_KEY) LIKE #{item}</foreach>)</if> "
+ "<if test='commentLike != null'>AND (<foreach item='item' collection='commentLike' separator=' OR ' >UPPER(COMMENT) LIKE #{item}</foreach>)</if> "
+ "<if test='oldValueLike != null'>AND (<foreach item='item' collection='oldValueLike' separator=' OR ' >UPPER(OLD_VALUE) LIKE #{item}</foreach>)</if> "
+ "<if test='newValueLike != null'>AND (<foreach item='item' collection='newValueLike' separator=' OR ' >UPPER(NEW_VALUE) LIKE #{item}</foreach>)</if> "
+ "<if test='custom1Like != null'>AND (<foreach item='item' collection='custom1Like' separator=' OR ' >UPPER(CUSTOM_1) LIKE #{item}</foreach>)</if> "
+ "<if test='custom2Like != null'>AND (<foreach item='item' collection='custom2Like' separator=' OR ' >UPPER(CUSTOM_2) LIKE #{item}</foreach>)</if> "
+ "<if test='custom3Like != null'>AND (<foreach item='item' collection='custom3Like' separator=' OR ' >UPPER(CUSTOM_3) LIKE #{item}</foreach>)</if> "
+ "<if test='custom4Like != null'>AND (<foreach item='item' collection='custom4Like' separator=' OR ' >UPPER(CUSTOM_4) LIKE #{item}</foreach>)</if> "
+ "<if test='oldDataLike != null'>AND (<foreach item='item' collection='oldDataLike' separator=' OR ' >UPPER(OLD_DATA) LIKE #{item}</foreach>)</if> "
+ "<if test='newDataLike != null'>AND (<foreach item='item' collection='newDataLike' separator=' OR ' >UPPER(NEW_DATA) LIKE #{item}</foreach>)</if> "
+ "</where>"
+ "</script>")
long countHistoryEvent(HistoryQueryImpl historyEventQuery);
@Select("<script>SELECT DISTINCT ${columnName} "
+ "FROM HISTORY_EVENTS"
+ "<where>"
// IN-Queries
+ "<if test='idIn != null'>AND UPPER(ID) IN (<foreach item='item' collection='idIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='businessProcessIdIn != null'>AND UPPER(BUSINESS_PROCESS_ID) IN (<foreach item='item' collection='businessProcessIdIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='parentBusinessProcessIdIn != null'>AND UPPER(PARENT_BUSINESS_PROCESS_ID) IN (<foreach item='item' collection='parentBusinessProcessIdIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='taskIdIn != null'>AND UPPER(TASK_ID) IN (<foreach item='item' collection='taskIdIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='eventTypeIn != null'>AND UPPER(EVENT_TYPE) IN (<foreach item='item' collection='eventTypeIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='createdIn !=null'> AND ( <foreach item='item' collection='createdIn' separator=',' > ( <if test='item.begin!=null'> CREATED &gt;= #{item.begin} </if> <if test='item.begin!=null and item.end!=null'> AND </if><if test='item.end!=null'> CREATED &lt;=#{item.end} </if>)</foreach>)</if> "
+ "<if test='userIdIn != null'>AND UPPER(USER_ID) IN (<foreach item='item' collection='userIdIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='domainIn != null'>AND UPPER(DOMAIN) IN (<foreach item='item' collection='domainIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='workbasketKeyIn != null'>AND UPPER(WORKBASKET_KEY) IN (<foreach item='item' collection='workbasketKeyIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='porCompanyIn != null'>AND UPPER(POR_COMPANY) IN (<foreach item='item' collection='porCompanyIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='porSystemIn != null'>AND UPPER(POR_SYSTEM) IN (<foreach item='item' collection='porSystemIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='porInstanceIn != null'>AND UPPER(POR_INSTANCE) IN (<foreach item='item' collection='porInstanceIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='porTypeIn != null'>AND UPPER(POR_TYPE) IN (<foreach item='item' collection='porTypeIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='porValueIn != null'>AND UPPER(POR_VALUE) IN (<foreach item='item' collection='porValueIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='taskClassificationKeyIn != null'>AND UPPER(TASK_CLASSIFICATION_KEY) IN (<foreach item='item' collection='taskClassificationKeyIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='taskClassificationCategoryIn != null'>AND UPPER(TASK_CLASSIFICATION_CATEGORY) IN (<foreach item='item' collection='taskClassificationCategoryIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='attachmentClassificationKeyIn != null'>AND UPPER(ATTACHMENT_CLASSIFICATION_KEY) IN (<foreach item='item' collection='attachmentClassificationKeyIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='commentIn != null'>AND UPPER(COMMENT) IN (<foreach item='item' collection='commentIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='oldValueIn != null'>AND UPPER(OLD_VALUE) IN (<foreach item='item' collection='oldValueIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='newValueIn != null'>AND UPPER(NEW_VALUE) IN (<foreach item='item' collection='newValueIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='custom1In != null'>AND UPPER(CUSTOM_1) IN (<foreach item='item' collection='custom1In' separator=',' >#{item}</foreach>)</if> "
+ "<if test='custom2In != null'>AND UPPER(CUSTOM_2) IN (<foreach item='item' collection='custom2In' separator=',' >#{item}</foreach>)</if> "
+ "<if test='custom3In != null'>AND UPPER(CUSTOM_3) IN (<foreach item='item' collection='custom3In' separator=',' >#{item}</foreach>)</if> "
+ "<if test='custom4In != null'>AND UPPER(CUSTOM_4) IN (<foreach item='item' collection='custom4In' separator=',' >#{item}</foreach>)</if> "
+ "<if test='oldDataIn != null'>AND UPPER(OLD_DATA) IN (<foreach item='item' collection='oldDataIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='newDataIn != null'>AND UPPER(NEW_DATA) IN (<foreach item='item' collection='newDataIn' separator=',' >#{item}</foreach>)</if> "
// LIKE-Queries
+ "<if test='businessProcessIdLike != null'>AND (<foreach item='item' collection='businessProcessIdLike' separator='OR' > UPPER(BUSINESS_PROCESS_ID) LIKE #{item} </foreach>)</if> "
+ "<if test='parentBusinessProcessIdLike != null'>AND (<foreach item='item' collection='parentBusinessProcessIdLike' separator=' OR ' >UPPER(PARENT_BUSINESS_PROCESS_ID) LIKE #{item}</foreach>)</if> "
+ "<if test='taskIdLike != null'>AND (<foreach item='item' collection='taskIdLike' separator=' OR ' >UPPER(TASK_ID) LIKE #{item}</foreach>)</if> "
+ "<if test='eventTypeLike != null'>AND (<foreach item='item' collection='eventTypeLike' separator=' OR ' >UPPER(EVENT_TYPE) LIKE #{item}</foreach>)</if> "
+ "<if test='userIdLike != null'>AND (<foreach item='item' collection='userIdLike' separator=' OR ' >UPPER(USER_ID) LIKE #{item}</foreach>)</if> "
+ "<if test='domainLike != null'>AND (<foreach item='item' collection='domainLike' separator=' OR ' >UPPER(DOMAIN) LIKE #{item}</foreach>)</if> "
+ "<if test='workbasketKeyLike != null'>AND (<foreach item='item' collection='workbasketKeyLike' separator=' OR ' >UPPER(WORKBASKET_KEY) LIKE #{item}</foreach>)</if> "
+ "<if test='porCompanyLike != null'>AND (<foreach item='item' collection='porCompanyLike' separator=' OR ' >UPPER(POR_COMPANY) LIKE #{item}</foreach>)</if> "
+ "<if test='porSystemLike != null'>AND (<foreach item='item' collection='porSystemLike' separator=' OR ' >UPPER(POR_SYSTEM) LIKE #{item}</foreach>)</if> "
+ "<if test='porInstanceLike != null'>AND (<foreach item='item' collection='porInstanceLike' separator=' OR ' >UPPER(POR_INSTANCE) LIKE #{item}</foreach>)</if> "
+ "<if test='porTypeLike != null'>AND (<foreach item='item' collection='porTypeLike' separator=' OR ' >UPPER(POR_TYPE) LIKE #{item}</foreach>)</if> "
+ "<if test='porValueLike != null'>AND (<foreach item='item' collection='porValueLike' separator=' OR ' >UPPER(POR_VALUE) LIKE #{item}</foreach>)</if> "
+ "<if test='taskClassificationKeyLike != null'>AND (<foreach item='item' collection='taskClassificationKeyLike' separator=' OR ' >UPPER(TASK_CLASSIFICATION_KEY) LIKE #{item}</foreach>)</if> "
+ "<if test='taskClassificationCategoryLike != null'>AND (<foreach item='item' collection='taskClassificationCategoryLike' separator=' OR ' >UPPER(TASK_CLASSIFICATION_CATEGORY) LIKE #{item}</foreach>)</if> "
+ "<if test='attachmentClassificationKeyLike != null'>AND (<foreach item='item' collection='attachmentClassificationKeyLike' separator=' OR ' >UPPER(ATTACHMENT_CLASSIFICATION_KEY) LIKE #{item}</foreach>)</if> "
+ "<if test='commentLike != null'>AND (<foreach item='item' collection='commentLike' separator=' OR ' >UPPER(COMMENT) LIKE #{item}</foreach>)</if> "
+ "<if test='oldValueLike != null'>AND (<foreach item='item' collection='oldValueLike' separator=' OR ' >UPPER(OLD_VALUE) LIKE #{item}</foreach>)</if> "
+ "<if test='newValueLike != null'>AND (<foreach item='item' collection='newValueLike' separator=' OR ' >UPPER(NEW_VALUE) LIKE #{item}</foreach>)</if> "
+ "<if test='custom1Like != null'>AND (<foreach item='item' collection='custom1Like' separator=' OR ' >UPPER(CUSTOM_1) LIKE #{item}</foreach>)</if> "
+ "<if test='custom2Like != null'>AND (<foreach item='item' collection='custom2Like' separator=' OR ' >UPPER(CUSTOM_2) LIKE #{item}</foreach>)</if> "
+ "<if test='custom3Like != null'>AND (<foreach item='item' collection='custom3Like' separator=' OR ' >UPPER(CUSTOM_3) LIKE #{item}</foreach>)</if> "
+ "<if test='custom4Like != null'>AND (<foreach item='item' collection='custom4Like' separator=' OR ' >UPPER(CUSTOM_4) LIKE #{item}</foreach>)</if> "
+ "<if test='oldDataLike != null'>AND (<foreach item='item' collection='oldDataLike' separator=' OR ' >UPPER(OLD_DATA) LIKE #{item}</foreach>)</if> "
+ "<if test='newDataLike != null'>AND (<foreach item='item' collection='newDataLike' separator=' OR ' >UPPER(NEW_DATA) LIKE #{item}</foreach>)</if> "
+ "</where>"
+ "<if test='!orderBy.isEmpty()'>ORDER BY <foreach item='item' collection='orderBy' separator=',' >${item}</foreach></if> "
+ "</script>")
List<String> queryHistoryColumnValues(HistoryQueryImpl historyQuery);
}

View File

@ -0,0 +1,710 @@
package pro.taskana.simplehistory.query;
import pro.taskana.BaseQuery;
import pro.taskana.TimeInterval;
import pro.taskana.exceptions.InvalidArgumentException;
import pro.taskana.simplehistory.impl.HistoryEventImpl;
/**
* HistoryQuery for generating dynamic sql.
*/
public interface HistoryQuery extends BaseQuery<HistoryEventImpl, HistoryQueryColumnName> {
/**
* Add your Id to your query.
*
* @param idIn
* as String
* @return the query
*/
HistoryQuery idIn(String... idIn);
/**
* Add your businessProcessId to your query.
*
* @param businessProcessId
* as String
* @return the query
*/
HistoryQuery businessProcessIdIn(String... businessProcessId);
/**
* Add your parentBusinessProcessId to your query.
*
* @param parentBusinessProcessId
* as String
* @return the query
*/
HistoryQuery parentBusinessProcessIdIn(String... parentBusinessProcessId);
/**
* Add your taskId to your query.
*
* @param taskId
* as String
* @return the query
*/
HistoryQuery taskIdIn(String... taskId);
/**
* Add your eventType to your query.
*
* @param eventType
* as String
* @return the query
*/
HistoryQuery eventTypeIn(String... eventType);
/**
* Add your created TimeInterval to your query.
*
* @param createdWithin
* the {@link TimeInterval} within which the searched-for classifications were created.
* @return the query
*/
HistoryQuery createdWithin(TimeInterval... createdWithin);
/**
* Add your userId to your query.
*
* @param userId
* as String
* @return the query
*/
HistoryQuery userIdIn(String... userId);
/**
* Add your domain to your query.
*
* @param domain
* as String
* @return the query
*/
HistoryQuery domainIn(String... domain);
/**
* Add your workbasketKey to your query.
*
* @param workbasketKey
* as String
* @return the query
*/
HistoryQuery workbasketKeyIn(String... workbasketKey);
/**
* Add your porCompany to your query.
*
* @param porCompany
* as String
* @return the query
*/
HistoryQuery porCompanyIn(String... porCompany);
/**
* Add your porSystem to your query.
*
* @param porSystem
* as String
* @return the query
*/
HistoryQuery porSystemIn(String... porSystem);
/**
* Add your porInstance to your query.
*
* @param porInstance
* as String
* @return the query
*/
HistoryQuery porInstanceIn(String... porInstance);
/**
* Add your porType to your query.
*
* @param porType
* as String
* @return the query
*/
HistoryQuery porTypeIn(String... porType);
/**
* Add your porValue to your query.
*
* @param porValue
* as String
* @return the query
*/
HistoryQuery porValueIn(String... porValue);
/**
* Add your taskClassificationKey to your query.
*
* @param taskClassificationKey
* as String
* @return the query
*/
HistoryQuery taskClassificationKeyIn(String... taskClassificationKey);
/**
* Add your taskClassificationCategory to your query.
*
* @param taskClassificationCategory
* as String
* @return the query
*/
HistoryQuery taskClassificationCategoryIn(String... taskClassificationCategory);
/**
* Add your attachmentClassificationKey to your query.
*
* @param attachmentClassificationKey
* as String
* @return the query
*/
HistoryQuery attachmentClassificationKeyIn(String... attachmentClassificationKey);
/**
* Add your comment to your query.
*
* @param comment
* as String
* @return the query
*/
HistoryQuery commentIn(String... comment);
/**
* Add your oldValue to your query.
*
* @param oldValue
* as String
* @return the query
*/
HistoryQuery oldValueIn(String... oldValue);
/**
* Add your newValue to your query.
*
* @param newValue
* as String
* @return the query
*/
HistoryQuery newValueIn(String... newValue);
/**
* Add your custom1 to your query.
*
* @param custom1
* as String
* @return the query
*/
HistoryQuery custom1In(String... custom1);
/**
* Add your custom2 to your query.
*
* @param custom2
* as String
* @return the query
*/
HistoryQuery custom2In(String... custom2);
/**
* Add your custom3 to your query.
*
* @param custom3
* as String
* @return the query
*/
HistoryQuery custom3In(String... custom3);
/**
* Add your custom4 to your query.
*
* @param custom4
* as String
* @return the query
*/
HistoryQuery custom4In(String... custom4);
/**
* Add your oldData to your query.
*
* @param oldData
* as String
* @return the query
*/
HistoryQuery oldDataIn(String... oldData);
/**
* Add your newData to your query.
*
* @param newData
* as String
* @return the query
*/
HistoryQuery newDataIn(String... newData);
/**
* Add your businessProcessId to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param businessProcessId
* as String
* @return the query
*/
HistoryQuery businessProcessIdLike(String... businessProcessId);
/**
* Add your parentBusinessProcessId to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param parentBusinessProcessId
* as String
* @return the query
*/
HistoryQuery parentBusinessProcessIdLike(String... parentBusinessProcessId);
/**
* Add your taskId to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param taskId
* as String
* @return the query
*/
HistoryQuery taskIdLike(String... taskId);
/**
* Add your eventType to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param eventType
* as String
* @return the query
*/
HistoryQuery eventTypeLike(String... eventType);
/**
* Add your userId to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param userId
* as String
* @return the query
*/
HistoryQuery userIdLike(String... userId);
/**
* Add your domain to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param domain
* as String
* @return the query
*/
HistoryQuery domainLike(String... domain);
/**
* Add your workbasketKey to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param workbasketKey
* as String
* @return the query
*/
HistoryQuery workbasketKeyLike(String... workbasketKey);
/**
* Add your porCompany to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param porCompany
* as String
* @return the query
*/
HistoryQuery porCompanyLike(String... porCompany);
/**
* Add your porSystem to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param porSystem
* as String
* @return the query
*/
HistoryQuery porSystemLike(String... porSystem);
/**
* Add your porInstance to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param porInstance
* as String
* @return the query
*/
HistoryQuery porInstanceLike(String... porInstance);
/**
* Add your porType to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param porType
* as String
* @return the query
*/
HistoryQuery porTypeLike(String... porType);
/**
* Add your porValue to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param porValue
* as String
* @return the query
*/
HistoryQuery porValueLike(String... porValue);
/**
* Add your taskClassificationKey to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param taskClassificationKey
* as String
* @return the query
*/
HistoryQuery taskClassificationKeyLike(String... taskClassificationKey);
/**
* Add your taskClassificationCategory to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param taskClassificationCategory
* as String
* @return the query
*/
HistoryQuery taskClassificationCategoryLike(String... taskClassificationCategory);
/**
* Add your attachmentClassificationKey to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param attachmentClassificationKey
* as String
* @return the query
*/
HistoryQuery attachmentClassificationKeyLike(String... attachmentClassificationKey);
/**
* Add your comment to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param comment
* as String
* @return the query
*/
HistoryQuery commentLike(String... comment);
/**
* Add your oldValue to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param oldValue
* as String
* @return the query
*/
HistoryQuery oldValueLike(String... oldValue);
/**
* Add your newValue to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param newValue
* as String
* @return the query
*/
HistoryQuery newValueLike(String... newValue);
/**
* Add your custom1 to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param custom1
* as String
* @return the query
*/
HistoryQuery custom1Like(String... custom1);
/**
* Add your custom2 to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param custom2
* as String
* @return the query
*/
HistoryQuery custom2Like(String... custom2);
/**
* Add your custom3 to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param custom3
* as String
* @return the query
*/
HistoryQuery custom3Like(String... custom3);
/**
* Add your custom4 to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param custom4
* as String
* @return the query
*/
HistoryQuery custom4Like(String... custom4);
/**
* Add your oldData to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param oldData
* as String
* @return the query
*/
HistoryQuery oldDataLike(String... oldData);
/**
* Add your newData to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % then it
* will be transmitted to the database.
*
* @param newData
* as String
* @return the query
*/
HistoryQuery newDataLike(String... newData);
/**
* Sort the query result by businessProcessId.
*
* @param sortDirection
* Determines whether the result is sorted in ascending or descending order. If sortDirection is null,
* the result is sorted in ascending order
* @return the query
*/
HistoryQuery orderByBusinessProcessId(SortDirection sortDirection);
/**
* Sort the query result by parentBusinessProcessId.
*
* @param sortDirection
* Determines whether the result is sorted in ascending or descending order. If sortDirection is null,
* the result is sorted in ascending order
* @return the query
*/
HistoryQuery orderByParentBusinessProcessId(SortDirection sortDirection);
/**
* Sort the query result by taskId.
*
* @param sortDirection
* Determines whether the result is sorted in ascending or descending order. If sortDirection is null,
* the result is sorted in ascending order
* @return the query
*/
HistoryQuery orderByTaskId(SortDirection sortDirection);
/**
* Sort the query result by eventType.
*
* @param sortDirection
* Determines whether the result is sorted in ascending or descending order. If sortDirection is null,
* the result is sorted in ascending order
* @return the query
*/
HistoryQuery orderByEventType(SortDirection sortDirection);
/**
* Sort the query result by created.
*
* @param sortDirection
* Determines whether the result is sorted in ascending or descending order. If sortDirection is null,
* the result is sorted in ascending order
* @return the query
*/
HistoryQuery orderByCreated(SortDirection sortDirection);
/**
* Sort the query result by userId.
*
* @param sortDirection
* Determines whether the result is sorted in ascending or descending order. If sortDirection is null,
* the result is sorted in ascending order
* @return the query
*/
HistoryQuery orderByUserId(SortDirection sortDirection);
/**
* Sort the query result by Domain.
*
* @param sortDirection
* Determines whether the result is sorted in ascending or descending order. If sortDirection is null,
* the result is sorted in ascending order
* @return the query
*/
HistoryQuery orderByDomain(SortDirection sortDirection);
/**
* Sort the query result by WorkbasketKey.
*
* @param sortDirection
* Determines whether the result is sorted in ascending or descending order. If sortDirection is null,
* the result is sorted in ascending order
* @return the query
*/
HistoryQuery orderByWorkbasketKey(SortDirection sortDirection);
/**
* Sort the query result by porCompany.
*
* @param sortDirection
* Determines whether the result is sorted in ascending or descending order. If sortDirection is null,
* the result is sorted in ascending order
* @return the query
*/
HistoryQuery orderByPorCompany(SortDirection sortDirection);
/**
* Sort the query result by porSystem.
*
* @param sortDirection
* Determines whether the result is sorted in ascending or descending order. If sortDirection is null,
* the result is sorted in ascending order
* @return the query
*/
HistoryQuery orderByPorSystem(SortDirection sortDirection);
/**
* Sort the query result by porInstance.
*
* @param sortDirection
* Determines whether the result is sorted in ascending or descending order. If sortDirection is null,
* the result is sorted in ascending order
* @return the query
*/
HistoryQuery orderByPorInstance(SortDirection sortDirection);
/**
* Sort the query result by porType.
*
* @param sortDirection
* Determines whether the result is sorted in ascending or descending order. If sortDirection is null,
* the result is sorted in ascending order
* @return the query
*/
HistoryQuery orderByPorType(SortDirection sortDirection);
/**
* Sort the query result by porValue.
*
* @param sortDirection
* Determines whether the result is sorted in ascending or descending order. If sortDirection is null,
* the result is sorted in ascending order
* @return the query
*/
HistoryQuery orderByPorValue(SortDirection sortDirection);
/**
* Sort the query result by taskClassificationKey.
*
* @param sortDirection
* Determines whether the result is sorted in ascending or descending order. If sortDirection is null,
* the result is sorted in ascending order
* @return the query
*/
HistoryQuery orderByTaskClassificationKey(SortDirection sortDirection);
/**
* Sort the query result by taskClassificationCategory.
*
* @param sortDirection
* Determines whether the result is sorted in ascending or descending order. If sortDirection is null,
* the result is sorted in ascending order
* @return the query
*/
HistoryQuery orderByTaskClassificationCategory(SortDirection sortDirection);
/**
* Sort the query result by attachmentClassificationKey.
*
* @param sortDirection
* Determines whether the result is sorted in ascending or descending order. If sortDirection is null,
* the result is sorted in ascending order
* @return the query
*/
HistoryQuery orderByAttachmentClassificationKey(SortDirection sortDirection);
/**
* Sort the query result by comment.
*
* @param sortDirection
* Determines whether the result is sorted in ascending or descending order. If sortDirection is null,
* the result is sorted in ascending order
* @return the query
*/
HistoryQuery orderByComment(SortDirection sortDirection);
/**
* Sort the query result by oldValue.
*
* @param sortDirection
* Determines whether the result is sorted in ascending or descending order. If sortDirection is null,
* the result is sorted in ascending order
* @return the query
*/
HistoryQuery orderByOldValue(SortDirection sortDirection);
/**
* Sort the query result by newValue.
*
* @param sortDirection
* Determines whether the result is sorted in ascending or descending order. If sortDirection is null,
* the result is sorted in ascending order
* @return the query
*/
HistoryQuery orderByNewValue(SortDirection sortDirection);
/**
* Sort the query result by oldData.
*
* @param sortDirection
* Determines whether the result is sorted in ascending or descending order. If sortDirection is null,
* the result is sorted in ascending order
* @return the query
*/
HistoryQuery orderByOldData(SortDirection sortDirection);
/**
* Sort the query result by newData.
*
* @param sortDirection
* Determines whether the result is sorted in ascending or descending order. If sortDirection is null,
* the result is sorted in ascending order
* @return the query
*/
HistoryQuery orderByNewData(SortDirection sortDirection);
/**
* Sort the query result by a custom.
*
* @param num
* the number of the custom as String (eg "4")
* @param sortDirection
* Determines whether the result is sorted in ascending or descending order. If sortDirection is null,
* the result is sorted in ascending order
* @return the query
* @throws InvalidArgumentException
* when the number of the custom is incorrect.
*/
HistoryQuery orderByCustomAttribute(int num, SortDirection sortDirection) throws InvalidArgumentException;
}

View File

@ -0,0 +1,48 @@
package pro.taskana.simplehistory.query;
import pro.taskana.QueryColumnName;
/**
* Enum containing the column names for @see pro.taskana.simplehistory.mappings.HistoryQueryMapper#queryHistoryColumnValues(pro.taskana.simplehistory.impl.HistoryQueryImpl).
*
* @author bv
*/
public enum HistoryQueryColumnName implements QueryColumnName {
ID("id"),
BUSINESS_PROCESS_ID("business_process_id"),
PARENT_BUSINESS_PROCESS_ID("parent_business_process_id"),
TASK_ID("task_id"),
EVENT_TYPE("event_type"),
CREATED("created"),
USER_ID("user_id"),
DOMAIN("domain"),
WORKBASKET_KEY("workbasket_key"),
POR_COMPANY("por_company"),
POR_SYSTEM("por_system"),
POR_INSTANCE("por_instance"),
POR_TYPE("por_type"),
POR_VALUE("por_value"),
TASK_CLASSIFICATION_KEY("task_classification_key"),
TASK_CLASSIFICATION_CATEGORY("task_classification_category"),
ATTACHMENT_CLASSIFICATION_KEY("attachment_classification_key"),
COMMENT("comment"),
OLD_VALUE("old_value"),
NEW_VALUE("new_value"),
CUSTOM_1("custom_1"),
CUSTOM_2("custom_2"),
CUSTOM_3("custom_3"),
CUSTOM_4("custom_4"),
OLD_DATA("old_data"),
NEW_DATA("new_data"),
TYPE("type");
private String name;
HistoryQueryColumnName(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}

View File

@ -0,0 +1 @@
pro.taskana.simplehistory.impl.SimpleHistoryServiceImpl

View File

@ -0,0 +1,33 @@
CREATE SCHEMA IF NOT EXISTS %schemaName%;
SET SCHEMA %schemaName%;
CREATE TABLE IF NOT EXISTS HISTORY_EVENTS (
ID BIGINT NOT NULL AUTO_INCREMENT,
BUSINESS_PROCESS_ID VARCHAR(128) NULL,
PARENT_BUSINESS_PROCESS_ID VARCHAR(128) NULL,
TASK_ID VARCHAR(40) NULL,
EVENT_TYPE VARCHAR(32) NULL,
CREATED TIMESTAMP NULL,
USER_ID VARCHAR(32) NULL,
DOMAIN VARCHAR(32) NULL,
WORKBASKET_KEY VARCHAR(64) NULL,
POR_COMPANY VARCHAR(32) NULL,
POR_SYSTEM VARCHAR(32) NULL,
POR_INSTANCE VARCHAR(32) NULL,
POR_TYPE VARCHAR(32) NULL,
POR_VALUE VARCHAR(128) NULL,
TASK_CLASSIFICATION_KEY VARCHAR(32) NULL,
TASK_CLASSIFICATION_CATEGORY VARCHAR(32) NULL,
ATTACHMENT_CLASSIFICATION_KEY VARCHAR(32) NULL,
COMMENT VARCHAR(4096) NULL,
OLD_VALUE VARCHAR(255) NULL,
NEW_VALUE VARCHAR(255) NULL,
CUSTOM_1 VARCHAR(128) NULL,
CUSTOM_2 VARCHAR(128) NULL,
CUSTOM_3 VARCHAR(128) NULL,
CUSTOM_4 VARCHAR(128) NULL,
OLD_DATA VARCHAR(4096) NULL,
NEW_DATA VARCHAR(4096) NULL,
PRIMARY KEY (ID)
);

View File

@ -0,0 +1,240 @@
package acceptance;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.ibatis.datasource.pooled.PooledDataSource;
import org.junit.BeforeClass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import configuration.DBWriter;
import pro.taskana.configuration.TaskanaEngineConfiguration;
import pro.taskana.simplehistory.impl.HistoryEventImpl;
import pro.taskana.simplehistory.impl.SimpleHistoryServiceImpl;
/**
* Set up database for tests.
*/
public class AbstractAccTest {
public static SimpleHistoryServiceImpl historyService;
protected static TaskanaEngineConfiguration taskanaEngineConfiguration;
private static DataSource dataSource = null;
private static String schemaName = null;
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAccTest.class);
private static final int POOL_TIME_TO_WAIT = 50;
protected AbstractAccTest() {
// not called
}
@BeforeClass
public static void setupTest() throws Exception {
resetDb(null);
}
public static void resetDb(String schemaName) throws SQLException {
DataSource dataSource = getDataSource();
DBWriter writer = new DBWriter();
taskanaEngineConfiguration = new TaskanaEngineConfiguration(dataSource, false,
schemaName != null && !schemaName.isEmpty() ? schemaName : getSchemaName());
historyService = new SimpleHistoryServiceImpl();
historyService.initialize(taskanaEngineConfiguration);
writer.clearDB(dataSource);
writer.generateTestData(dataSource);
}
/**
* returns the DataSource used for Junit test. If the file {user.home}/taskanaUnitTest.properties is present, the
* Datasource is created according to the properties jdbcDriver, jdbcUrl, dbUserName and dbPassword. Assuming, the
* database has the name tskdb, a sample properties file for DB2 looks as follows:
* jdbcDriver=com.ibm.db2.jcc.DB2Driver jdbcUrl=jdbc:db2://localhost:50000/tskdb dbUserName=db2user
* dbPassword=db2password If any of these properties is missing, or the file doesn't exist, the default Datasource
* for h2 in-memory db is created.
*
* @return dataSource for unit test
*/
public static DataSource getDataSource() {
if (dataSource == null) {
String userHomeDirectroy = System.getProperty("user.home");
String propertiesFileName = userHomeDirectroy + "/taskanaUnitTest.properties";
File f = new File(propertiesFileName);
if (f.exists() && !f.isDirectory()) {
dataSource = createDataSourceFromProperties(propertiesFileName);
} else {
dataSource = createDefaultDataSource();
}
}
return dataSource;
}
/**
* create Default DataSource for in-memory database.
*
* @return the TASKANA default datasource.
*/
private static DataSource createDefaultDataSource() {
String jdbcDriver = "org.h2.Driver";
String jdbcUrl = "jdbc:h2:mem:taskana;IGNORECASE=TRUE;LOCK_MODE=0";
String dbUserName = "sa";
String dbPassword = "sa";
DataSource ds = new PooledDataSource(Thread.currentThread().getContextClassLoader(), jdbcDriver,
jdbcUrl, dbUserName, dbPassword);
((PooledDataSource) ds).setPoolTimeToWait(POOL_TIME_TO_WAIT);
((PooledDataSource) ds).forceCloseAll(); // otherwise the MyBatis pool is not initialized correctly
return ds;
}
/**
* returns the SchemaName used for Junit test. If the file {user.home}/taskanaUnitTest.properties is present, the
* SchemaName is created according to the property schemaName. a sample properties file for DB2 looks as follows:
* jdbcDriver=com.ibm.db2.jcc.DB2Driver jdbcUrl=jdbc:db2://localhost:50000/tskdb dbUserName=db2user
* dbPassword=db2password schemaName=TASKANA If any of these properties is missing, or the file doesn't exist, the
* default schemaName TASKANA is created used.
*
* @return String for unit test
*/
public static String getSchemaName() {
if (schemaName == null) {
String userHomeDirectroy = System.getProperty("user.home");
String propertiesFileName = userHomeDirectroy + "/taskanaUnitTest.properties";
File f = new File(propertiesFileName);
if (f.exists() && !f.isDirectory()) {
schemaName = getSchemaNameFromPropertiesObject(propertiesFileName);
} else {
schemaName = "TASKANA";
}
}
return schemaName;
}
/**
* create historyEvent object.
*
* @param workbasketKey
* the workbasketKey, the task currently resides in.
* @param taskId
* the taskid the event belongs to.
* @param type
* the type of the event.
* @param comment
* the individual comment.
* @param previousWorkbasketId
* the workbasketId of the previous workbasket (if applicable).
* @return History event object created.
*/
public static HistoryEventImpl createHistoryEvent(String workbasketKey, String taskId, String type, String comment,
String previousWorkbasketId) {
HistoryEventImpl historyEvent = new HistoryEventImpl();
historyEvent.setWorkbasketKey(workbasketKey);
historyEvent.setTaskId(taskId);
historyEvent.setEventType(type);
historyEvent.setComment(comment);
historyEvent.setOldValue(previousWorkbasketId);
return historyEvent;
}
/**
* create data source from properties file.
*
* @param propertiesFileName
* the name of the properties file.
* @return the datasource constructed from the information in the properties file.
*/
private static DataSource createDataSourceFromProperties(String propertiesFileName) {
DataSource ds = null;
try (InputStream input = new FileInputStream(propertiesFileName)) {
Properties prop = new Properties();
prop.load(input);
boolean propertiesFileIsComplete = true;
String warningMessage = "";
String jdbcDriver = prop.getProperty("jdbcDriver");
if (jdbcDriver == null || jdbcDriver.length() == 0) {
propertiesFileIsComplete = false;
warningMessage += ", jdbcDriver property missing";
}
String jdbcUrl = prop.getProperty("jdbcUrl");
if (jdbcUrl == null || jdbcUrl.length() == 0) {
propertiesFileIsComplete = false;
warningMessage += ", jdbcUrl property missing";
}
String dbUserName = prop.getProperty("dbUserName");
if (dbUserName == null || dbUserName.length() == 0) {
propertiesFileIsComplete = false;
warningMessage += ", dbUserName property missing";
}
String dbPassword = prop.getProperty("dbPassword");
if (dbPassword == null || dbPassword.length() == 0) {
propertiesFileIsComplete = false;
warningMessage += ", dbPassword property missing";
}
if (propertiesFileIsComplete) {
ds = new PooledDataSource(Thread.currentThread().getContextClassLoader(), jdbcDriver,
jdbcUrl, dbUserName, dbPassword);
((PooledDataSource) ds).forceCloseAll(); // otherwise the MyBatis pool is not initialized correctly
} else {
LOGGER.warn("propertiesFile " + propertiesFileName + " is incomplete" + warningMessage);
LOGGER.warn("Using default Datasource for Test");
ds = createDefaultDataSource();
}
} catch (FileNotFoundException e) {
LOGGER.warn("createDataSourceFromProperties caught Exception " + e);
LOGGER.warn("Using default Datasource for Test");
ds = createDefaultDataSource();
} catch (IOException e) {
LOGGER.warn("createDataSourceFromProperties caught Exception " + e);
LOGGER.warn("Using default Datasource for Test");
ds = createDefaultDataSource();
}
return ds;
}
private static String getSchemaNameFromPropertiesObject(String propertiesFileName) {
String schemaName = "TASKANA";
try (InputStream input = new FileInputStream(propertiesFileName)) {
Properties prop = new Properties();
prop.load(input);
boolean propertiesFileIsComplete = true;
String warningMessage = "";
schemaName = prop.getProperty("schemaName");
if (schemaName == null || schemaName.length() == 0) {
propertiesFileIsComplete = false;
warningMessage += ", schemaName property missing";
}
if (!propertiesFileIsComplete) {
LOGGER.warn("propertiesFile " + propertiesFileName + " is incomplete" + warningMessage);
LOGGER.warn("Using default Datasource for Test");
schemaName = "TASKANA";
}
} catch (FileNotFoundException e) {
LOGGER.warn("getSchemaNameFromPropertiesObject caught Exception " + e);
LOGGER.warn("Using default schemaName for Test");
} catch (IOException e) {
LOGGER.warn("createDataSourceFromProperties caught Exception " + e);
LOGGER.warn("Using default Datasource for Test");
}
return schemaName;
}
}

View File

@ -0,0 +1,312 @@
package acceptance.query;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import java.time.Instant;
import java.util.List;
import org.junit.Test;
import acceptance.AbstractAccTest;
import pro.taskana.BaseQuery.SortDirection;
import pro.taskana.TimeInterval;
import pro.taskana.simplehistory.impl.HistoryEventImpl;
import pro.taskana.simplehistory.query.HistoryQuery;
import pro.taskana.simplehistory.query.HistoryQueryColumnName;
/**
* Test for History queries.
*/
public class QueryHistoryAccTest extends AbstractAccTest {
public QueryHistoryAccTest() {
super();
}
@Test
public void testListValuesAscendingAndDescending() {
List<String> defaultList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.COMMENT, null);
List<String> ascendingList = historyService.createHistoryQuery()
.listValues(HistoryQueryColumnName.COMMENT, SortDirection.ASCENDING);
List<String> descendingList = historyService.createHistoryQuery()
.listValues(HistoryQueryColumnName.COMMENT, SortDirection.DESCENDING);
assertEquals(3, ascendingList.size());
assertArrayEquals(defaultList.toArray(), ascendingList.toArray());
assertEquals(ascendingList.get(2), descendingList.get(0));
}
@Test
public void testComplexQuery() {
HistoryQuery query = historyService.createHistoryQuery()
.businessProcessIdLike("just some string", "BPI:%")
.domainLike("%A")
.orderByCreated(SortDirection.DESCENDING);
List<HistoryEventImpl> results = query.list();
assertEquals(2, results.size());
assertEquals("admin", results.get(0).getUserId());
assertEquals("peter", results.get(1).getUserId());
results = query.orderByUserId(SortDirection.DESCENDING).list();
assertEquals(2, results.size());
assertEquals("admin", results.get(0).getUserId());
assertEquals("peter", results.get(1).getUserId());
assertEquals(3, query.domainLike().count());
}
@Test
public void testQueryListOffset() {
List<HistoryEventImpl> result = historyService.createHistoryQuery().list(1, 2);
List<HistoryEventImpl> wrongList = historyService.createHistoryQuery().list();
assertEquals(2, result.size());
assertNotEquals(wrongList.get(0).getUserId(), result.get(0).getUserId());
assertEquals(wrongList.get(1).getUserId(), result.get(0).getUserId());
}
@Test
public void testCorrectResultWithWrongConstraints() {
List<HistoryEventImpl> result = historyService.createHistoryQuery().list(1, 1000);
assertEquals(2, result.size());
assertEquals("created by Peter", result.get(0).getComment());
result = historyService.createHistoryQuery().list(100, 1000);
assertTrue(result.isEmpty());
}
@Test
public void testSingle() {
HistoryEventImpl single = historyService.createHistoryQuery().userIdIn("peter").single();
assertEquals("CREATE", single.getEventType());
single = historyService.createHistoryQuery().eventTypeIn("CREATE", "xy").single();
assertEquals("admin", single.getUserId());
}
@Test
public void testCount() {
long count = historyService.createHistoryQuery().userIdIn("peter").count();
assertEquals(1, count);
count = historyService.createHistoryQuery().count();
assertEquals(3, count);
count = historyService.createHistoryQuery().userIdIn("klaus", "arnold", "benni").count();
assertEquals(0, count);
}
@Test
public void testQueryAttributesIn() {
List<HistoryEventImpl> returnValues = historyService.createHistoryQuery()
.businessProcessIdIn("BPI:01", "BPI:02")
.list();
assertEquals(2, returnValues.size());
returnValues = historyService.createHistoryQuery().parentBusinessProcessIdIn("BPI:01").list();
assertEquals(1, returnValues.size());
returnValues = historyService.createHistoryQuery().taskIdIn("TKI:000000000000000000000000000000000000").list();
assertEquals(2, returnValues.size());
returnValues = historyService.createHistoryQuery().eventTypeIn("CREATE").list();
assertEquals(3, returnValues.size());
TimeInterval timeInterval = new TimeInterval(Instant.now().minusSeconds(10), Instant.now());
returnValues = historyService.createHistoryQuery().createdWithin(timeInterval).list();
assertEquals(2, returnValues.size());
returnValues = historyService.createHistoryQuery().userIdIn("admin").list();
assertEquals(2, returnValues.size());
returnValues = historyService.createHistoryQuery().domainIn("DOMAIN_A").list();
assertEquals(2, returnValues.size());
returnValues = historyService.createHistoryQuery()
.workbasketKeyIn("WBI:100000000000000000000000000000000001")
.list();
assertEquals(2, returnValues.size());
returnValues = historyService.createHistoryQuery().porCompanyIn("00").list();
assertEquals(2, returnValues.size());
returnValues = historyService.createHistoryQuery().porSystemIn("PASystem").list();
assertEquals(2, returnValues.size());
returnValues = historyService.createHistoryQuery().porInstanceIn("22").list();
assertEquals(1, returnValues.size());
returnValues = historyService.createHistoryQuery().porTypeIn("VN").list();
assertEquals(0, returnValues.size());
returnValues = historyService.createHistoryQuery().porValueIn("11223344").list();
assertEquals(2, returnValues.size());
returnValues = historyService.createHistoryQuery().taskClassificationKeyIn("L140101").list();
assertEquals(2, returnValues.size());
returnValues = historyService.createHistoryQuery().taskClassificationCategoryIn("TASK").list();
assertEquals(2, returnValues.size());
returnValues = historyService.createHistoryQuery().attachmentClassificationKeyIn("DOCTYPE_DEFAULT").list();
assertEquals(1, returnValues.size());
returnValues = historyService.createHistoryQuery().custom1In("custom1").list();
assertEquals(3, returnValues.size());
returnValues = historyService.createHistoryQuery().custom2In("custom2").list();
assertEquals(1, returnValues.size());
returnValues = historyService.createHistoryQuery().custom3In("custom3").list();
assertEquals(2, returnValues.size());
returnValues = historyService.createHistoryQuery().custom4In("custom4").list();
assertEquals(1, returnValues.size());
returnValues = historyService.createHistoryQuery().commentIn("created a bug").list();
assertEquals(1, returnValues.size());
returnValues = historyService.createHistoryQuery().oldValueIn("old_val").list();
assertEquals(1, returnValues.size());
returnValues = historyService.createHistoryQuery().newValueIn("new_val").list();
assertEquals(1, returnValues.size());
returnValues = historyService.createHistoryQuery().oldDataIn("123").list();
assertEquals(2, returnValues.size());
returnValues = historyService.createHistoryQuery().newDataIn("456").list();
assertEquals(3, returnValues.size());
returnValues = historyService.createHistoryQuery().oldValueLike("old%").list();
assertEquals(1, returnValues.size());
returnValues = historyService.createHistoryQuery().newValueLike("new_%").list();
assertEquals(2, returnValues.size());
returnValues = historyService.createHistoryQuery().oldDataLike("%23%").list();
assertEquals(3, returnValues.size());
returnValues = historyService.createHistoryQuery().newDataLike("456%").list();
assertEquals(3, returnValues.size());
}
@Test
public void testSomeLikeMethods() {
List<HistoryEventImpl> returnValues = historyService.createHistoryQuery()
.businessProcessIdLike("BPI:0%")
.list();
assertEquals(3, returnValues.size());
returnValues = historyService.createHistoryQuery().parentBusinessProcessIdLike("BPI:01", " %").list();
assertEquals(1, returnValues.size());
returnValues = historyService.createHistoryQuery().taskIdLike("TKI:000000000000000%").list();
assertEquals(3, returnValues.size());
returnValues = historyService.createHistoryQuery().oldValueLike("old%").list();
assertEquals(1, returnValues.size());
returnValues = historyService.createHistoryQuery().newValueLike("new_%").list();
assertEquals(2, returnValues.size());
returnValues = historyService.createHistoryQuery().oldDataLike("%23%").list();
assertEquals(3, returnValues.size());
returnValues = historyService.createHistoryQuery().newDataLike("456%").list();
assertEquals(3, returnValues.size());
}
@Test
public void testListValues() {
List<String> returnedList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.ID, null);
assertEquals(3, returnedList.size());
returnedList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.BUSINESS_PROCESS_ID, null);
assertEquals(3, returnedList.size());
returnedList = historyService.createHistoryQuery()
.listValues(HistoryQueryColumnName.PARENT_BUSINESS_PROCESS_ID, null);
assertEquals(2, returnedList.size());
returnedList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.TASK_ID, null);
assertEquals(2, returnedList.size());
returnedList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.EVENT_TYPE, null);
assertEquals(1, returnedList.size());
returnedList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.CREATED, null);
assertEquals(2, returnedList.size());
returnedList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.USER_ID, null);
assertEquals(2, returnedList.size());
returnedList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.DOMAIN, null);
assertEquals(2, returnedList.size());
returnedList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.WORKBASKET_KEY, null);
assertEquals(2, returnedList.size());
returnedList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.POR_COMPANY, null);
assertEquals(2, returnedList.size());
returnedList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.POR_SYSTEM, null);
assertEquals(2, returnedList.size());
returnedList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.POR_INSTANCE, null);
assertEquals(2, returnedList.size());
returnedList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.POR_TYPE, null);
assertEquals(2, returnedList.size());
returnedList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.POR_VALUE, null);
assertEquals(2, returnedList.size());
returnedList = historyService.createHistoryQuery()
.listValues(HistoryQueryColumnName.TASK_CLASSIFICATION_KEY, null);
assertEquals(2, returnedList.size());
returnedList = historyService.createHistoryQuery()
.listValues(HistoryQueryColumnName.TASK_CLASSIFICATION_CATEGORY, null);
assertEquals(2, returnedList.size());
returnedList = historyService.createHistoryQuery()
.listValues(HistoryQueryColumnName.ATTACHMENT_CLASSIFICATION_KEY, null);
assertEquals(2, returnedList.size());
returnedList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.COMMENT, null);
assertEquals(3, returnedList.size());
returnedList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.OLD_VALUE, null);
assertEquals(3, returnedList.size());
returnedList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.NEW_VALUE, null);
assertEquals(3, returnedList.size());
returnedList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.CUSTOM_1, null);
assertEquals(1, returnedList.size());
returnedList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.CUSTOM_2, null);
assertEquals(2, returnedList.size());
returnedList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.CUSTOM_3, null);
assertEquals(2, returnedList.size());
returnedList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.CUSTOM_4, null);
assertEquals(2, returnedList.size());
returnedList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.OLD_DATA, null);
assertEquals(2, returnedList.size());
returnedList = historyService.createHistoryQuery().listValues(HistoryQueryColumnName.NEW_DATA, null);
assertEquals(1, returnedList.size());
}
}

View File

@ -0,0 +1,80 @@
package configuration;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Set up the database's writer and generates data for tests.
*/
public class DBWriter {
private static final Logger LOGGER = LoggerFactory.getLogger(DBWriter.class);
private static final String INSERTVALUES = "/sql/history-events.sql";
private StringWriter outWriter = new StringWriter();
private PrintWriter logWriter;
private StringWriter errorWriter;
private PrintWriter errorLogWriter;
public DBWriter() {
this.logWriter = new PrintWriter(this.outWriter);
this.errorWriter = new StringWriter();
this.errorLogWriter = new PrintWriter(this.errorWriter);
}
public void generateTestData(DataSource dataSource) throws SQLException {
ScriptRunner runner = null;
try {
runner = configScriptRunner(dataSource);
runner.runScript(
new InputStreamReader(
this.getClass().getResourceAsStream(INSERTVALUES)));
} finally {
if (runner != null) {
runner.closeConnection();
}
LOGGER.debug(outWriter.toString());
if (!errorWriter.toString().trim().isEmpty()) {
LOGGER.error(errorWriter.toString());
}
}
}
public void clearDB(DataSource dataSource) throws SQLException {
ScriptRunner runner = null;
try {
runner = configScriptRunner(dataSource);
runner.runScript(new StringReader("DELETE FROM HISTORY_EVENTS;"));
} finally {
if (runner != null) {
runner.closeConnection();
}
LOGGER.debug(outWriter.toString());
if (!errorWriter.toString().trim().isEmpty()) {
LOGGER.error(errorWriter.toString());
}
}
}
private ScriptRunner configScriptRunner(DataSource dataSource) throws SQLException {
Connection connection = dataSource.getConnection();
LOGGER.debug(connection.getMetaData().toString());
ScriptRunner runner = new ScriptRunner(connection);
runner.setStopOnError(true);
runner.setLogWriter(this.logWriter);
runner.setErrorLogWriter(this.errorLogWriter);
runner.setStopOnError(true);
runner.setLogWriter(this.logWriter);
runner.setErrorLogWriter(this.errorLogWriter);
return runner;
}
}

View File

@ -0,0 +1,46 @@
package configuration;
import static org.junit.Assert.assertEquals;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.junit.Assert;
import org.junit.Test;
import acceptance.AbstractAccTest;
import pro.taskana.TaskanaEngine;
import pro.taskana.configuration.TaskanaEngineConfiguration;
/**
* Unit Test for TaskanaEngineConfigurationTest.
*
* @author MMR
*/
public class TaskanaEngineConfigurationTest extends AbstractAccTest {
@Test
public void testCreateTaskanaEngine() throws SQLException {
DataSource ds = getDataSource();
TaskanaEngineConfiguration taskEngineConfiguration = new TaskanaEngineConfiguration(ds, false,
getSchemaName());
TaskanaEngine te = taskEngineConfiguration.buildTaskanaEngine();
Assert.assertNotNull(te);
}
@Test
public void testCreateTaskanaHistoryEventWithNonDefaultSchemaName() throws SQLException {
resetDb("SOMECUSTOMSCHEMANAME");
long count = historyService.createHistoryQuery().workbasketKeyIn("wbKey1").count();
assertEquals(0, count);
historyService.create(
AbstractAccTest.createHistoryEvent("wbKey1", "taskId1", "type1", "Some comment", "wbKey2"));
count = historyService.createHistoryQuery().workbasketKeyIn("wbKey1").count();
assertEquals(1, count);
}
}

View File

@ -0,0 +1,76 @@
package pro.taskana.simplehistory.impl;
import static org.junit.Assert.assertArrayEquals;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.validateMockitoUsage;
import java.sql.SQLException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import pro.taskana.TimeInterval;
import pro.taskana.simplehistory.impl.mappings.HistoryQueryMapper;
/**
* Unit Test for SimpleHistoryServiceImplTest.
*
* @author BV
*/
@RunWith(MockitoJUnitRunner.class)
public class HistoryQueryImplTest {
private HistoryQueryImpl historyQueryImpl;
@Mock
private TaskanaHistoryEngineImpl taskanaHistoryEngineMock;
@Mock
private HistoryQueryMapper historyQueryMock;
@Before
public void setup() {
historyQueryImpl = new HistoryQueryImpl(taskanaHistoryEngineMock, historyQueryMock);
}
@Test
public void testShouldReturnList() throws SQLException {
List<HistoryEventImpl> returnList = new ArrayList<>();
returnList.add(createHistoryEvent("abcd", "T22", "car", "BV", "this was important", null));
TimeInterval interval = new TimeInterval(Instant.now().minusNanos(1000), Instant.now());
doNothing().when(taskanaHistoryEngineMock).openConnection();
doNothing().when(taskanaHistoryEngineMock).returnConnection();
doReturn(returnList).when(historyQueryMock).queryHistoryEvent(historyQueryImpl);
List<HistoryEventImpl> result = historyQueryImpl
.taskIdIn("TKI:01")
.workbasketKeyIn("T22", "some_long_long, long loooooooooooooooooooooooooooooooooooong String.")
.userIdIn("BV")
.commentLike("%as important")
.createdWithin(interval)
.list();
validateMockitoUsage();
assertArrayEquals(returnList.toArray(), result.toArray());
}
private HistoryEventImpl createHistoryEvent(String taskId, String workbasketKey, String type, String userId,
String comment, Instant created) {
HistoryEventImpl he = new HistoryEventImpl();
he.setTaskId(taskId);
he.setWorkbasketKey(workbasketKey);
he.setEventType(type);
he.setUserId(userId);
he.setComment(comment);
he.setCreated(created);
return he;
}
}

View File

@ -0,0 +1,125 @@
package pro.taskana.simplehistory.impl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.apache.ibatis.session.SqlSessionManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import acceptance.AbstractAccTest;
import pro.taskana.configuration.TaskanaEngineConfiguration;
import pro.taskana.simplehistory.impl.mappings.HistoryEventMapper;
import pro.taskana.simplehistory.impl.mappings.HistoryQueryMapper;
/**
* Unit Test for SimpleHistoryServiceImplTest.
*
* @author MMR
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest(TaskanaHistoryEngineImpl.class)
@PowerMockIgnore("javax.management.*")
public class SimpleHistoryServiceImplTest {
@InjectMocks
private SimpleHistoryServiceImpl cutSpy;
@Mock
private HistoryEventMapper historyEventMapperMock;
@Mock
private HistoryQueryMapper historyQueryMapperMock;
@Mock
private TaskanaHistoryEngineImpl taskanaHistoryEngineMock;
@Mock
private TaskanaEngineConfiguration taskanaEngineConfiguration;
@Mock
private SqlSessionManager sqlSessionManagerMock;
@Mock
private HistoryQueryImpl historyQueryMock;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testInitializeSimpleHistoryService() throws SQLException {
doReturn(historyEventMapperMock).when(sqlSessionManagerMock).getMapper(HistoryEventMapper.class);
doReturn(historyQueryMapperMock).when(sqlSessionManagerMock).getMapper(HistoryQueryMapper.class);
doReturn(sqlSessionManagerMock).when(taskanaHistoryEngineMock).getSqlSession();
PowerMockito.mockStatic(TaskanaHistoryEngineImpl.class);
Mockito.when(TaskanaHistoryEngineImpl.createTaskanaEngine(taskanaEngineConfiguration)).thenReturn(taskanaHistoryEngineMock);
cutSpy.initialize(taskanaEngineConfiguration);
verify(sqlSessionManagerMock, times(2)).getMapper(any());
verify(taskanaHistoryEngineMock, times(2)).getSqlSession();
PowerMockito.verifyStatic();
}
@Test
public void testInitializeSimpleHistoryServiceWithNonDefaultSchemaName() throws SQLException {
doReturn(historyEventMapperMock).when(sqlSessionManagerMock).getMapper(HistoryEventMapper.class);
doReturn(historyQueryMapperMock).when(sqlSessionManagerMock).getMapper(HistoryQueryMapper.class);
doReturn(sqlSessionManagerMock).when(taskanaHistoryEngineMock).getSqlSession();
PowerMockito.mockStatic(TaskanaHistoryEngineImpl.class);
Mockito.when(TaskanaHistoryEngineImpl.createTaskanaEngine(taskanaEngineConfiguration)).thenReturn(taskanaHistoryEngineMock);
cutSpy.initialize(taskanaEngineConfiguration);
verify(sqlSessionManagerMock, times(2)).getMapper(any());
verify(taskanaHistoryEngineMock, times(2)).getSqlSession();
PowerMockito.verifyStatic();
}
@Test
public void testCreateEvent() throws SQLException {
HistoryEventImpl expectedWb = AbstractAccTest.createHistoryEvent("wbKey1", "taskId1", "type1", "Some comment", "wbKey2");
doNothing().when(historyEventMapperMock).insert(expectedWb);
cutSpy.create(expectedWb);
verify(taskanaHistoryEngineMock, times(1)).openConnection();
verify(historyEventMapperMock, times(1)).insert(expectedWb);
verify(taskanaHistoryEngineMock, times(1)).returnConnection();
assertTrue(expectedWb.getCreated() != null);
}
@Test
public void testQueryEvent() throws SQLException {
List<HistoryEventImpl> returnList = new ArrayList<>();
returnList.add(AbstractAccTest.createHistoryEvent("wbKey1", "taskId1", "type1", "Some comment", "wbKey2"));
doReturn(returnList).when(historyQueryMapperMock).queryHistoryEvent(any());
List<HistoryEventImpl> result = cutSpy.createHistoryQuery().taskIdIn("taskId1").list();
verify(taskanaHistoryEngineMock, times(1)).openConnection();
verify(historyQueryMapperMock, times(1)).queryHistoryEvent(any());
verify(taskanaHistoryEngineMock, times(1)).returnConnection();
assertEquals(returnList.size(), result.size());
assertEquals(returnList.get(0).getWorkbasketKey(), result.get(0).getWorkbasketKey());
}
}

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</Console>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console" />
</Root>
</Loggers>
</Configuration>

View File

@ -0,0 +1,7 @@
INSERT INTO HISTORY_EVENTS (BUSINESS_PROCESS_ID, PARENT_BUSINESS_PROCESS_ID, TASK_ID, EVENT_TYPE, CREATED, USER_ID, DOMAIN, WORKBASKET_KEY, POR_COMPANY, POR_SYSTEM, POR_INSTANCE, POR_TYPE, POR_VALUE, TASK_CLASSIFICATION_KEY,
TASK_CLASSIFICATION_CATEGORY, ATTACHMENT_CLASSIFICATION_KEY, COMMENT, OLD_VALUE, NEW_VALUE, CUSTOM_1, CUSTOM_2, CUSTOM_3, CUSTOM_4, OLD_DATA, NEW_DATA) VALUES
-- BUSINESS_PROCESS_ID, PARENT_BUSINESS_PROCESS_ID, TASK_ID, EVENT_TYPE, CREATED, USER_ID, DOMAIN, WORKBASKET_KEY, POR_COMPANY , POR_SYSTEM, POR_INSTANCE , POR_TYPE , POR_VALUE , TASK_CLASSIFICATION_KEY, TASK_CLASSIFICATION_CATEGORY , ATTACHMENT_CLASSIFICATION_KEY , COMMENT , OLD_VALUE , NEW_VALUE , CUSTOM_1 , CUSTOM_2 , CUSTOM_3 , CUSTOM_4 , OLD_DATA , NEW_DATA
('BPI:01' ,'' ,'TKI:000000000000000000000000000000000000', 'CREATE', CURRENT_TIMESTAMP , 'admin', 'DOMAIN_B', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '11223344', 'L140101' , 'TASK' ,'' , 'this task has been created' ,'old_val' ,'new_val' ,'custom1' ,'custom2' , 'custom3' ,'custom4' ,'123' ,'456'),
('BPI:02' ,'' ,'TKI:000000000000000000000000000000000000', 'CREATE', DATEADD('DAY', -2, CURRENT_TIMESTAMP),'peter', 'DOMAIN_A', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '11223344', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'456'),
('BPI:03' ,'BPI:01','TKI:000000000000000000000000000000000001', 'CREATE', CURRENT_TIMESTAMP , 'admin', 'DOMAIN_A', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'123' ,'456')
;

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>taskana-simplehistory-rest-spring-example</artifactId>
<name>${project.groupId}:${project.artifactId}</name>
<description>Demo project for taskana-simplehistory-rest-spring</description>
<parent>
<groupId>pro.taskana.simplehistory</groupId>
<artifactId>taskana-simplehistory-parent</artifactId>
<version>1.1.5-SNAPSHOT</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>pro.taskana.simplehistory</groupId>
<artifactId>taskana-simplehistory-rest-spring</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.plugin</groupId>
<artifactId>spring-plugin-core</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<!-- Tests -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-documentation-to-static-folder</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.outputDirectory}/static/docs/rest
</outputDirectory>
<resources>
<resource>
<directory>
${project.build.directory}/generated-docs
</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,66 @@
package rest.pro.taskana.rest.simplehistory;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import pro.taskana.rest.simplehistory.TaskHistoryRestConfiguration;
import pro.taskana.rest.simplehistory.sampledata.SampleDataGenerator;
/**
* Example Application showing the implementation of taskana-rest-spring.
*/
@SpringBootApplication
@ComponentScan(basePackages = "pro.taskana.rest.simplehistory")
@Import({TaskHistoryRestConfiguration.class, WebMvcConfig.class})
public class ExampleRestApplication {
@Value("${taskana.schemaName:TASKANA}")
public String schemaName;
private SampleDataGenerator sampleDataGenerator;
public static void main(String[] args) {
SpringApplication.run(ExampleRestApplication.class, args);
}
@Bean
@Primary
@ConfigurationProperties(prefix = "datasource")
public DataSourceProperties dataSourceProperties() {
DataSourceProperties props = new DataSourceProperties();
props.setUrl("jdbc:h2:mem:taskana;IGNORECASE=TRUE;LOCK_MODE=0;INIT=CREATE SCHEMA IF NOT EXISTS " + schemaName);
return props;
}
@Bean
public DataSource dataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
@Bean
public PlatformTransactionManager txManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
@DependsOn("getTaskanaEngine") // generate sample data after schema was inserted
public SampleDataGenerator generateSampleData(DataSource dataSource) throws SQLException {
sampleDataGenerator = new SampleDataGenerator(dataSource);
sampleDataGenerator.generateSampleData(schemaName);
return sampleDataGenerator;
}
}

View File

@ -0,0 +1,60 @@
package rest.pro.taskana.rest.simplehistory;
import java.util.List;
import javax.annotation.PostConstruct;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
/**
* The Web MVC Configuration.
*/
@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/META-INF/resources/", "classpath:/resources/",
"classpath:/static/", "classpath:/public/"};
private ObjectMapper objectMapper;
WebMvcConfig(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!registry.hasMappingForPattern("/webjars/**")) {
registry.addResourceHandler("/webjars/**").addResourceLocations(
"classpath:/META-INF/resources/webjars/");
}
if (!registry.hasMappingForPattern("/**")) {
registry.addResourceHandler("/**").addResourceLocations(
CLASSPATH_RESOURCE_LOCATIONS);
}
}
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
for (HttpMessageConverter<?> converter : converters) {
if (converter instanceof MappingJackson2HttpMessageConverter) {
MappingJackson2HttpMessageConverter jacksonConverter = (MappingJackson2HttpMessageConverter) converter;
jacksonConverter.setPrettyPrint(true);
}
}
}
@PostConstruct
public void enableObjectIndent() {
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
}
}

View File

@ -0,0 +1,2 @@
logging.level.pro.taskana=DEBUG
taskana.schemaName=TASKANA

View File

@ -0,0 +1,205 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>taskana-simplehistory-rest-spring</artifactId>
<name>${project.groupId}:${project.artifactId}</name>
<description>The taskana history events plugin, spring based REST API.</description>
<url>http://taskana.pro</url>
<parent>
<groupId>pro.taskana.simplehistory</groupId>
<artifactId>taskana-simplehistory-parent</artifactId>
<version>1.1.5-SNAPSHOT</version>
</parent>
<licenses>
<license>
<name>The Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
<developers>
<developer>
<name>Holger Hagen</name>
<email>holger.hagen@novatec-gmbh.de</email>
<organization>NovaTec Consulting GmbH</organization>
<organizationUrl>https://www.novatec-gmbh.de</organizationUrl>
</developer>
</developers>
<scm>
<connection>scm:git:git://github.com/taskana/TaskanaSimpleHistory.git</connection>
<developerConnection>scm:git:ssh://github.com:taskana/TaskanaSimpleHistory.git</developerConnection>
<url>http://github.com/taskana/TaskanaSimpleHistory/tree/master</url>
</scm>
<profiles>
<profile>
<id>snapshot</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.8</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>false</autoReleaseAfterClose>
</configuration>
</plugin>
</plugins>
</build>
<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
</profile>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.8</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>false</autoReleaseAfterClose>
</configuration>
</plugin>
</plugins>
</build>
<distributionManagement>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<showWarnings>true</showWarnings>
<compilerArgs>
<arg>-Xlint:all</arg>
</compilerArgs>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>pro.taskana.simplehistory</groupId>
<artifactId>taskana-simplehistory-provider</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>pro.taskana</groupId>
<artifactId>taskana-rest-spring</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.hateoas</groupId>
<artifactId>spring-hateoas</artifactId>
<version>0.24.0.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.10</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,29 @@
package pro.taskana.rest.resource;
import org.springframework.beans.BeanUtils;
import org.springframework.hateoas.mvc.ResourceAssemblerSupport;
import pro.taskana.history.api.TaskanaHistoryEvent;
import pro.taskana.simplehistory.impl.HistoryEventImpl;
/**
* Transforms any {@link HistoryEventImpl} into its {@link TaskHistoryEventResource}.
*/
public class TaskHistoryEventAssembler extends ResourceAssemblerSupport<TaskanaHistoryEvent, TaskHistoryEventResource> {
public TaskHistoryEventAssembler() {
super(HistoryEventImpl.class, TaskHistoryEventResource.class);
}
@Override
public TaskHistoryEventResource toResource(TaskanaHistoryEvent historyEvent) {
TaskHistoryEventResource resource = createResourceWithId(historyEvent.getId(), historyEvent);
BeanUtils.copyProperties(historyEvent, resource);
if (historyEvent.getCreated() != null) {
resource.setCreated(historyEvent.getCreated().toString());
}
resource.setTaskHistoryId(String.valueOf(historyEvent.getId()));
resource.removeLinks();
return resource;
}
}

View File

@ -0,0 +1,50 @@
package pro.taskana.rest.resource;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import java.util.List;
import org.springframework.hateoas.Link;
import pro.taskana.rest.resource.PagedResources.PageMetadata;
import pro.taskana.rest.simplehistory.TaskHistoryEventController;
import pro.taskana.simplehistory.impl.HistoryEventImpl;
/**
* Mapper to convert from a list of HistoryEventImpl to a TaskHistoryEventResource.
*/
public class TaskHistoryEventListAssembler extends AbstractRessourcesAssembler {
public TaskHistoryEventListAssembler() {
}
public TaskHistoryEventListResource toResources(List<HistoryEventImpl> historyEvents,
PageMetadata pageMetadata) {
TaskHistoryEventAssembler assembler = new TaskHistoryEventAssembler();
List<TaskHistoryEventResource> resources = assembler.toResources(historyEvents);
TaskHistoryEventListResource pagedResources = new TaskHistoryEventListResource(
resources,
pageMetadata);
pagedResources.add(new Link(original.toUriString()).withSelfRel());
if (pageMetadata != null) {
pagedResources.add(linkTo(TaskHistoryEventController.class).withRel("allTaskHistoryEvent"));
pagedResources.add(new Link(original.replaceQueryParam("page", 1).toUriString()).withRel(Link.REL_FIRST));
pagedResources.add(new Link(original.replaceQueryParam("page", pageMetadata.getTotalPages()).toUriString())
.withRel(Link.REL_LAST));
if (pageMetadata.getNumber() > 1) {
pagedResources
.add(new Link(original.replaceQueryParam("page", pageMetadata.getNumber() - 1).toUriString())
.withRel(Link.REL_PREVIOUS));
}
if (pageMetadata.getNumber() < pageMetadata.getTotalPages()) {
pagedResources
.add(new Link(original.replaceQueryParam("page", pageMetadata.getNumber() + 1).toUriString())
.withRel(Link.REL_NEXT));
}
}
return pagedResources;
}
}

View File

@ -0,0 +1,34 @@
package pro.taskana.rest.resource;
import java.util.Collection;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.PagedResources.PageMetadata;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Resource class for {@link TaskHistoryEventResource} with Pagination.
*/
public class TaskHistoryEventListResource extends PagedResources<TaskHistoryEventResource> {
public TaskHistoryEventListResource() {
super();
}
public TaskHistoryEventListResource(Collection<TaskHistoryEventResource> content, PageMetadata metadata,
Link... links) {
super(content, metadata, links);
}
public TaskHistoryEventListResource(Collection<TaskHistoryEventResource> content, PageMetadata metadata,
Iterable<Link> links) {
super(content, metadata, links);
}
@Override
@JsonProperty("taskHistoryEvents")
public Collection<TaskHistoryEventResource> getContent() {
return super.getContent();
}
}

View File

@ -0,0 +1,266 @@
package pro.taskana.rest.resource;
import javax.validation.constraints.NotNull;
import org.springframework.hateoas.ResourceSupport;
/**
* Resource class for {@link pro.taskana.history.api.TaskanaHistoryEvent}.
*/
public class TaskHistoryEventResource extends ResourceSupport {
@NotNull
private String taskHistoryEventId;
private String businessProcessId;
private String parentBusinessProcessId;
private String taskId;
private String eventType;
private String created;
private String userId;
private String domain;
private String workbasketKey;
private String porCompany;
private String porType;
private String porSystem;
private String porInstance;
private String porValue;
private String taskClassificationKey;
private String taskClassificationCategory;
private String attachmentClassificationKey;
private String comment;
private String oldValue;
private String newValue;
private String custom1;
private String custom2;
private String custom3;
private String custom4;
private String oldData;
private String newData;
public String getTaskHistoryId() {
return taskHistoryEventId;
}
public void setTaskHistoryId(String taskHistoryId) {
this.taskHistoryEventId = taskHistoryId;
}
public String getBusinessProcessId() {
return businessProcessId;
}
public void setBusinessProcessId(String businessProcessId) {
this.businessProcessId = businessProcessId;
}
public String getParentBusinessProcessId() {
return parentBusinessProcessId;
}
public void setParentBusinessProcessId(String parentBusinessProcessId) {
this.parentBusinessProcessId = parentBusinessProcessId;
}
public String getTaskId() {
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
public String getEventType() {
return eventType;
}
public void setEventType(String eventType) {
this.eventType = eventType;
}
public String getCreated() {
return created;
}
public void setCreated(String created) {
this.created = created;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getDomain() {
return domain;
}
public void setDomain(String domain) {
this.domain = domain;
}
public String getWorkbasketKey() {
return workbasketKey;
}
public void setWorkbasketKey(String workbasketKey) {
this.workbasketKey = workbasketKey;
}
public String getPorCompany() {
return porCompany;
}
public void setPorCompany(String porCompany) {
this.porCompany = porCompany;
}
public String getPorType() {
return porType;
}
public void setPorType(String porType) {
this.porType = porType;
}
public String getPorSystem() {
return porSystem;
}
public void setPorSystem(String porSystem) {
this.porSystem = porSystem;
}
public String getPorInstance() {
return porInstance;
}
public void setPorInstance(String porInstance) {
this.porInstance = porInstance;
}
public String getPorValue() {
return porValue;
}
public void setPorValue(String porValue) {
this.porValue = porValue;
}
public String getTaskClassificationKey() {
return taskClassificationKey;
}
public void setTaskClassificationKey(String taskClassificationKey) {
this.taskClassificationKey = taskClassificationKey;
}
public String getTaskClassificationCategory() {
return taskClassificationCategory;
}
public void setTaskClassificationCategory(String taskClassificationCategory) {
this.taskClassificationCategory = taskClassificationCategory;
}
public String getAttachmentClassificationKey() {
return attachmentClassificationKey;
}
public void setAttachmentClassificationKey(String attachmentClassificationKey) {
this.attachmentClassificationKey = attachmentClassificationKey;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public String getOldValue() {
return oldValue;
}
public void setOldValue(String oldValue) {
this.oldValue = oldValue;
}
public String getNewValue() {
return newValue;
}
public void setNewValue(String newValue) {
this.newValue = newValue;
}
public String getCustom1() {
return custom1;
}
public void setCustom1(String custom1) {
this.custom1 = custom1;
}
public String getCustom2() {
return custom2;
}
public void setCustom2(String custom2) {
this.custom2 = custom2;
}
public String getCustom3() {
return custom3;
}
public void setCustom3(String custom3) {
this.custom3 = custom3;
}
public String getCustom4() {
return custom4;
}
public void setCustom4(String custom4) {
this.custom4 = custom4;
}
public String getOldData() {
return oldData;
}
public void setOldData(String oldData) {
this.oldData = oldData;
}
public String getNewData() {
return newData;
}
public void setNewData(String newData) {
this.newData = newData;
}
@Override
public String toString() {
return "TaskHistoryEventResource ["
+ "taskHistoryEventId= " + this.taskHistoryEventId
+ "businessProcessId= " + this.businessProcessId
+ "parentBusinessProcessId= " + this.parentBusinessProcessId
+ "taskId= " + this.taskId
+ "eventType= " + this.eventType
+ "created= " + this.created
+ "userId= " + this.userId
+ "domain= " + this.domain
+ "workbasketKey= " + this.workbasketKey
+ "oldValue= " + this.oldValue
+ "newValue= " + this.newValue
+ "oldData= " + this.oldData
+ "newData= " + this.newData
+ "]";
}
}

View File

@ -0,0 +1,474 @@
package pro.taskana.rest.simplehistory;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.hateoas.config.EnableHypermediaSupport;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import pro.taskana.BaseQuery;
import pro.taskana.TimeInterval;
import pro.taskana.configuration.TaskanaEngineConfiguration;
import pro.taskana.exceptions.InvalidArgumentException;
import pro.taskana.impl.util.LoggerUtils;
import pro.taskana.rest.AbstractPagingController;
import pro.taskana.rest.resource.PagedResources.PageMetadata;
import pro.taskana.rest.resource.TaskHistoryEventListAssembler;
import pro.taskana.rest.resource.TaskHistoryEventListResource;
import pro.taskana.simplehistory.impl.HistoryEventImpl;
import pro.taskana.simplehistory.impl.SimpleHistoryServiceImpl;
import pro.taskana.simplehistory.query.HistoryQuery;
/**
* Controller for all TaskHistoryEvent related endpoints.
*/
@RestController
@EnableHypermediaSupport(type = EnableHypermediaSupport.HypermediaType.HAL)
@RequestMapping(path = "/api/v1/task-history-event", produces = "application/hal+json")
public class TaskHistoryEventController extends AbstractPagingController {
private static final Logger LOGGER = LoggerFactory.getLogger(TaskHistoryEventController.class);
private static final String LIKE = "%";
private static final String BUSINESS_PROCESS_ID = "business-process-id";
private static final String BUSINESS_PROCESS_ID_LIKE = "business-process-id-like";
private static final String PARENT_BUSINESS_PROCESS_ID = "parent-business-process-id";
private static final String PARENT_BUSINESS_PROCESS_ID_LIKE = "parent-business-process-id-like";
private static final String TASK_ID = "task-id";
private static final String TASK_ID_LIKE = "task-id-like";
private static final String EVENT_TYPE = "event-type";
private static final String EVENT_TYPE_LIKE = "event-type-like";
private static final String CREATED = "created";
private static final String USER_ID = "user-id";
private static final String USER_ID_LIKE = "user-id-like";
private static final String DOMAIN = "domain";
private static final String WORKBASKET_KEY = "workbasket-key";
private static final String WORKBASKET_KEY_LIKE = "workbasket-key-like";
private static final String POR_COMPANY = "por-company";
private static final String POR_COMPANY_LIKE = "por-company-like";
private static final String POR_SYSTEM = "por-system";
private static final String POR_SYSTEM_LIKE = "por-system-like";
private static final String POR_INSTANCE = "por-instance";
private static final String POR_INSTANCE_LIKE = "por-instance-like";
private static final String POR_TYPE = "por-type";
private static final String POR_TYPE_LIKE = "por-type-like";
private static final String POR_VALUE = "por-value";
private static final String POR_VALUE_LIKE = "por-value-like";
private static final String TASK_CLASSIFICATION_KEY = "task-classification-key";
private static final String TASK_CLASSIFICATION_KEY_LIKE = "task-classification-key-like";
private static final String TASK_CLASSIFICATION_CATEGORY = "task-classification-category";
private static final String TASK_CLASSIFICATION_CATEGORY_LIKE = "task-classification-category-like";
private static final String ATTACHMENT_CLASSIFICATION_KEY = "attachment-classification-key";
private static final String ATTACHMENT_CLASSIFICATION_KEY_LIKE = "attachment-classification-key-like";
private static final String CUSTOM_1 = "custom-1";
private static final String CUSTOM_1_LIKE = "custom-1-like";
private static final String CUSTOM_2 = "custom-2";
private static final String CUSTOM_2_LIKE = "custom-2-like";
private static final String CUSTOM_3 = "custom-3";
private static final String CUSTOM_3_LIKE = "custom-3-like";
private static final String CUSTOM_4 = "custom-4";
private static final String CUSTOM_4_LIKE = "custom-4-like";
private static final String SORT_BY = "sort-by";
private static final String SORT_DIRECTION = "order";
private static final String PAGING_PAGE = "page";
private static final String PAGING_PAGE_SIZE = "page-size";
private SimpleHistoryServiceImpl simpleHistoryService;
private TaskanaEngineConfiguration taskanaEngineConfiguration;
public TaskHistoryEventController(TaskanaEngineConfiguration taskanaEngineConfiguration,
SimpleHistoryServiceImpl simpleHistoryServiceImpl) {
this.taskanaEngineConfiguration = taskanaEngineConfiguration;
this.simpleHistoryService = simpleHistoryServiceImpl;
simpleHistoryService.initialize(taskanaEngineConfiguration);
}
@GetMapping
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<TaskHistoryEventListResource> getTaskHistoryEvent(
@RequestParam MultiValueMap<String, String> params) throws InvalidArgumentException {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Entry to getTaskHistoryEvent(params= {})", LoggerUtils.mapToString(params));
}
HistoryQuery query = simpleHistoryService.createHistoryQuery();
query = applySortingParams(query, params);
query = applyFilterParams(query, params);
PageMetadata pageMetadata = null;
List<HistoryEventImpl> historyEvents = null;
String page = params.getFirst(PAGING_PAGE);
String pageSize = params.getFirst(PAGING_PAGE_SIZE);
params.remove(PAGING_PAGE);
params.remove(PAGING_PAGE_SIZE);
validateNoInvalidParameterIsLeft(params);
if (page != null && pageSize != null) {
long totalElements = query.count();
pageMetadata = initPageMetadata(pageSize, page, totalElements);
historyEvents = query.listPage((int) pageMetadata.getNumber(),
(int) pageMetadata.getSize());
} else if (page == null && pageSize == null) {
historyEvents = query.list();
} else {
throw new InvalidArgumentException("Paging information is incomplete.");
}
TaskHistoryEventListAssembler assembler = new TaskHistoryEventListAssembler();
TaskHistoryEventListResource pagedResources = assembler.toResources(historyEvents, pageMetadata);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Exit from getTaskHistoryEvent(), returning {}",
new ResponseEntity<>(pagedResources, HttpStatus.OK));
}
return new ResponseEntity<>(pagedResources, HttpStatus.OK);
}
private HistoryQuery applySortingParams(HistoryQuery query, MultiValueMap<String, String> params)
throws IllegalArgumentException, InvalidArgumentException {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Entry to applySortingParams(params= {})", LoggerUtils.mapToString(params));
}
String sortBy = params.getFirst(SORT_BY);
if (sortBy != null) {
BaseQuery.SortDirection sortDirection;
if (params.getFirst(SORT_DIRECTION) != null && "desc".equals(params.getFirst(SORT_DIRECTION))) {
sortDirection = BaseQuery.SortDirection.DESCENDING;
} else {
sortDirection = BaseQuery.SortDirection.ASCENDING;
}
switch (sortBy) {
case (BUSINESS_PROCESS_ID):
query = query.orderByBusinessProcessId(sortDirection);
break;
case (PARENT_BUSINESS_PROCESS_ID):
query = query.orderByParentBusinessProcessId(sortDirection);
break;
case (TASK_ID):
query = query.orderByTaskId(sortDirection);
break;
case (EVENT_TYPE):
query = query.orderByEventType(sortDirection);
break;
case (CREATED):
query = query.orderByCreated(sortDirection);
break;
case (USER_ID):
query = query.orderByUserId(sortDirection);
break;
case (DOMAIN):
query = query.orderByDomain(sortDirection);
break;
case (WORKBASKET_KEY):
query = query.orderByWorkbasketKey(sortDirection);
break;
case (POR_COMPANY):
query = query.orderByPorCompany(sortDirection);
break;
case (POR_SYSTEM):
query = query.orderByPorSystem(sortDirection);
break;
case (POR_INSTANCE):
query = query.orderByPorInstance(sortDirection);
break;
case (POR_TYPE):
query = query.orderByPorType(sortDirection);
break;
case (POR_VALUE):
query = query.orderByPorValue(sortDirection);
break;
case (TASK_CLASSIFICATION_KEY):
query = query.orderByTaskClassificationKey(sortDirection);
break;
case (TASK_CLASSIFICATION_CATEGORY):
query = query.orderByTaskClassificationCategory(sortDirection);
break;
case (ATTACHMENT_CLASSIFICATION_KEY):
query = query.orderByAttachmentClassificationKey(sortDirection);
break;
case (CUSTOM_1):
query = query.orderByCustomAttribute(1, sortDirection);
break;
case (CUSTOM_2):
query = query.orderByCustomAttribute(2, sortDirection);
break;
case (CUSTOM_3):
query = query.orderByCustomAttribute(3, sortDirection);
break;
case (CUSTOM_4):
query = query.orderByCustomAttribute(4, sortDirection);
break;
default:
throw new IllegalArgumentException("Unknown order '" + sortBy + "'");
}
}
params.remove(SORT_BY);
params.remove(SORT_DIRECTION);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Exit from applySortingParams(), returning {}", query);
}
return query;
}
private HistoryQuery applyFilterParams(HistoryQuery query,
MultiValueMap<String, String> params) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Entry to applyFilterParams(query= {}, params= {})", query, params);
}
if (params.containsKey(BUSINESS_PROCESS_ID)) {
String[] businessProcessId = extractCommaSeparatedFields(params.get(BUSINESS_PROCESS_ID));
query.businessProcessIdIn(businessProcessId);
params.remove(BUSINESS_PROCESS_ID);
}
if (params.containsKey(BUSINESS_PROCESS_ID_LIKE)) {
query.businessProcessIdLike(LIKE + params.get(BUSINESS_PROCESS_ID_LIKE).get(0) + LIKE);
params.remove(BUSINESS_PROCESS_ID_LIKE);
}
if (params.containsKey(PARENT_BUSINESS_PROCESS_ID)) {
String[] parentBusinessProcessId = extractCommaSeparatedFields(params.get(PARENT_BUSINESS_PROCESS_ID));
query.parentBusinessProcessIdIn(parentBusinessProcessId);
params.remove(PARENT_BUSINESS_PROCESS_ID);
}
if (params.containsKey(PARENT_BUSINESS_PROCESS_ID_LIKE)) {
query.parentBusinessProcessIdLike(LIKE + params.get(PARENT_BUSINESS_PROCESS_ID_LIKE).get(0) + LIKE);
params.remove(PARENT_BUSINESS_PROCESS_ID_LIKE);
}
if (params.containsKey(TASK_ID)) {
String[] taskId = extractCommaSeparatedFields(params.get(TASK_ID));
query.taskIdIn(taskId);
params.remove(TASK_ID);
}
if (params.containsKey(TASK_ID_LIKE)) {
query.taskIdLike(LIKE + params.get(TASK_ID_LIKE).get(0) + LIKE);
params.remove(TASK_ID_LIKE);
}
if (params.containsKey(EVENT_TYPE)) {
String[] eventType = extractCommaSeparatedFields(params.get(EVENT_TYPE));
query.eventTypeIn(eventType);
params.remove(EVENT_TYPE);
}
if (params.containsKey(EVENT_TYPE_LIKE)) {
query.eventTypeLike(LIKE + params.get(EVENT_TYPE_LIKE).get(0) + LIKE);
params.remove(EVENT_TYPE_LIKE);
}
if (params.containsKey(CREATED)) {
String[] created = extractCommaSeparatedFields(params.get(CREATED));
TimeInterval timeInterval = getTimeIntervalOf(created);
query.createdWithin(timeInterval);
params.remove(CREATED);
}
if (params.containsKey(USER_ID)) {
String[] userId = extractCommaSeparatedFields(params.get(USER_ID));
query.userIdIn(userId);
params.remove(USER_ID);
}
if (params.containsKey(USER_ID_LIKE)) {
query.userIdLike(LIKE + params.get(USER_ID_LIKE).get(0) + LIKE);
params.remove(USER_ID_LIKE);
}
if (params.containsKey(DOMAIN)) {
query.domainIn(extractCommaSeparatedFields(params.get(DOMAIN)));
params.remove(DOMAIN);
}
if (params.containsKey(WORKBASKET_KEY)) {
String[] workbasketKey = extractCommaSeparatedFields(params.get(WORKBASKET_KEY));
query.workbasketKeyIn(workbasketKey);
params.remove(WORKBASKET_KEY);
}
if (params.containsKey(WORKBASKET_KEY_LIKE)) {
query.workbasketKeyLike(LIKE + params.get(WORKBASKET_KEY_LIKE).get(0) + LIKE);
params.remove(WORKBASKET_KEY_LIKE);
}
if (params.containsKey(POR_COMPANY)) {
String[] porCompany = extractCommaSeparatedFields(params.get(POR_COMPANY));
query.porCompanyIn(porCompany);
params.remove(POR_COMPANY);
}
if (params.containsKey(POR_COMPANY_LIKE)) {
query.porCompanyLike(LIKE + params.get(POR_COMPANY_LIKE).get(0) + LIKE);
params.remove(POR_COMPANY_LIKE);
}
if (params.containsKey(POR_SYSTEM)) {
String[] porSystem = extractCommaSeparatedFields(params.get(POR_SYSTEM));
query.porSystemIn(porSystem);
params.remove(POR_SYSTEM);
}
if (params.containsKey(POR_SYSTEM_LIKE)) {
query.porSystemLike(LIKE + params.get(POR_SYSTEM_LIKE).get(0) + LIKE);
params.remove(POR_SYSTEM_LIKE);
}
if (params.containsKey(POR_INSTANCE)) {
String[] porInstance = extractCommaSeparatedFields(params.get(POR_INSTANCE));
query.porInstanceIn(porInstance);
params.remove(POR_INSTANCE);
}
if (params.containsKey(POR_INSTANCE_LIKE)) {
query.porInstanceLike(LIKE + params.get(POR_INSTANCE_LIKE).get(0) + LIKE);
params.remove(POR_INSTANCE_LIKE);
}
if (params.containsKey(POR_TYPE)) {
String[] porType = extractCommaSeparatedFields(params.get(POR_TYPE));
query.porTypeIn(porType);
params.remove(POR_TYPE);
}
if (params.containsKey(POR_TYPE_LIKE)) {
query.porTypeLike(LIKE + params.get(POR_TYPE_LIKE).get(0) + LIKE);
params.remove(POR_TYPE_LIKE);
}
if (params.containsKey(POR_VALUE)) {
String[] porValue = extractCommaSeparatedFields(params.get(POR_VALUE));
query.porValueIn(porValue);
params.remove(POR_VALUE);
}
if (params.containsKey(POR_VALUE_LIKE)) {
query.porValueLike(LIKE + params.get(POR_VALUE_LIKE).get(0) + LIKE);
params.remove(POR_VALUE_LIKE);
}
if (params.containsKey(TASK_CLASSIFICATION_KEY)) {
String[] taskClassificationKey = extractCommaSeparatedFields(params.get(TASK_CLASSIFICATION_KEY));
query.taskClassificationKeyIn(taskClassificationKey);
params.remove(TASK_CLASSIFICATION_KEY);
}
if (params.containsKey(TASK_CLASSIFICATION_KEY_LIKE)) {
query.taskClassificationKeyLike(LIKE + params.get(TASK_CLASSIFICATION_KEY_LIKE).get(0) + LIKE);
params.remove(TASK_CLASSIFICATION_KEY_LIKE);
}
if (params.containsKey(TASK_CLASSIFICATION_CATEGORY)) {
String[] taskClassificationCategory = extractCommaSeparatedFields(params.get(TASK_CLASSIFICATION_CATEGORY));
query.taskClassificationCategoryIn(taskClassificationCategory);
params.remove(TASK_CLASSIFICATION_CATEGORY);
}
if (params.containsKey(TASK_CLASSIFICATION_CATEGORY_LIKE)) {
query.taskClassificationCategoryLike(LIKE + params.get(TASK_CLASSIFICATION_CATEGORY_LIKE).get(0) + LIKE);
params.remove(TASK_CLASSIFICATION_CATEGORY_LIKE);
}
if (params.containsKey(ATTACHMENT_CLASSIFICATION_KEY)) {
String[] attachmentClassificationKey = extractCommaSeparatedFields(
params.get(ATTACHMENT_CLASSIFICATION_KEY));
query.attachmentClassificationKeyIn(attachmentClassificationKey);
params.remove(ATTACHMENT_CLASSIFICATION_KEY);
}
if (params.containsKey(ATTACHMENT_CLASSIFICATION_KEY_LIKE)) {
query.attachmentClassificationKeyLike(LIKE + params.get(ATTACHMENT_CLASSIFICATION_KEY_LIKE).get(0) + LIKE);
params.remove(ATTACHMENT_CLASSIFICATION_KEY_LIKE);
}
if (params.containsKey(CUSTOM_1)) {
String[] custom1 = extractCommaSeparatedFields(params.get(CUSTOM_1));
query.custom1In(custom1);
params.remove(CUSTOM_1);
}
if (params.containsKey(CUSTOM_1_LIKE)) {
query.custom1Like(LIKE + params.get(CUSTOM_1_LIKE).get(0) + LIKE);
params.remove(CUSTOM_1_LIKE);
}
if (params.containsKey(CUSTOM_2)) {
String[] custom2 = extractCommaSeparatedFields(params.get(CUSTOM_2));
query.custom2In(custom2);
params.remove(CUSTOM_2);
}
if (params.containsKey(CUSTOM_2_LIKE)) {
query.custom2Like(LIKE + params.get(CUSTOM_2_LIKE).get(0) + LIKE);
params.remove(CUSTOM_2_LIKE);
}
if (params.containsKey(CUSTOM_3)) {
String[] custom3 = extractCommaSeparatedFields(params.get(CUSTOM_3));
query.custom3In(custom3);
params.remove(CUSTOM_3);
}
if (params.containsKey(CUSTOM_3_LIKE)) {
query.custom3Like(LIKE + params.get(CUSTOM_3_LIKE).get(0) + LIKE);
params.remove(CUSTOM_3_LIKE);
}
if (params.containsKey(CUSTOM_4)) {
String[] custom4 = extractCommaSeparatedFields(params.get(CUSTOM_4));
query.custom4In(custom4);
params.remove(CUSTOM_4);
}
if (params.containsKey(CUSTOM_4_LIKE)) {
query.custom4Like(LIKE + params.get(CUSTOM_4_LIKE).get(0) + LIKE);
params.remove(CUSTOM_4_LIKE);
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Exit from applyFilterParams(), returning {}", query);
}
return query;
}
private TimeInterval getTimeIntervalOf(String[] created) {
LocalDate begin;
LocalDate end;
try {
begin = LocalDate.parse(created[0]);
} catch (Exception e) {
throw new IllegalArgumentException(
"Cannot parse String '" + created[0] + "'. Expected a String of the Format 'yyyy-MM-dd'.");
}
if (created.length < 2) {
end = begin.plusDays(1);
} else {
end = LocalDate.parse(created[1]);
}
Instant beginInst = begin.atStartOfDay(ZoneId.systemDefault()).toInstant();
Instant endInst = end.atStartOfDay(ZoneId.systemDefault()).toInstant();
TimeInterval timeInterval = new TimeInterval(beginInst, endInst);
return timeInterval;
}
}

View File

@ -0,0 +1,23 @@
package pro.taskana.rest.simplehistory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import pro.taskana.simplehistory.impl.SimpleHistoryServiceImpl;
/**
* Configuration for Taskana history REST service.
*/
@Configuration
@ComponentScan(basePackages = {"pro.taskana.rest", "pro.taskana.rest.simplehistory"})
@EnableTransactionManagement
public class TaskHistoryRestConfiguration {
@Bean
public SimpleHistoryServiceImpl getSimpleHistoryService() {
return new SimpleHistoryServiceImpl();
}
}

View File

@ -0,0 +1,75 @@
package pro.taskana.rest.simplehistory.sampledata;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class generates sample data for manual testing purposes.
*/
public class SampleDataGenerator {
private static final Logger LOGGER = LoggerFactory.getLogger(SampleDataGenerator.class);
private static final String TEST_DATA = "/sql.sample-data";
private static final String CLEAR = TEST_DATA + "/clear-db.sql";
private static final String HISTORY_EVENT = TEST_DATA + "/history-event.sql";
private ScriptRunner runner;
DataSource dataSource;
public SampleDataGenerator(DataSource dataSource) throws SQLException {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(dataSource.getConnection().getMetaData().toString());
}
this.dataSource = dataSource;
runner = new ScriptRunner(dataSource.getConnection());
}
public void generateSampleData(String schemaName) {
StringWriter outWriter = new StringWriter();
PrintWriter logWriter = new PrintWriter(outWriter);
StringWriter errorWriter = new StringWriter();
PrintWriter errorLogWriter = new PrintWriter(errorWriter);
try {
runner.runScript(selectSchemaScript(dataSource.getConnection().getMetaData().getDatabaseProductName(), schemaName));
runner.setStopOnError(false);
runner.runScript(new BufferedReader(
new InputStreamReader(this.getClass().getResourceAsStream(CLEAR), StandardCharsets.UTF_8)));
} catch (Exception e) {
LOGGER.error("caught Exception {}", e);
}
runner.setStopOnError(true);
runner.setLogWriter(logWriter);
runner.setErrorLogWriter(errorLogWriter);
runner.runScript(new BufferedReader(
new InputStreamReader(this.getClass().getResourceAsStream(HISTORY_EVENT), StandardCharsets.UTF_8)));
runner.closeConnection();
LOGGER.trace(outWriter.toString());
if (!errorWriter.toString().trim().isEmpty()) {
LOGGER.error(errorWriter.toString());
}
}
private StringReader selectSchemaScript(String dbProductName, String schemaName) {
return new StringReader("PostgreSQL".equals(dbProductName)
? "SET search_path TO " + schemaName + ";"
: "SET SCHEMA " + schemaName + ";");
}
}

View File

@ -0,0 +1,2 @@
logging.level.pro.taskana=INFO
taskana.schemaName=TASKANA

View File

@ -0,0 +1,3 @@
-- the order is important!
DELETE FROM HISTORY_EVENTS;
COMMIT;

View File

@ -0,0 +1,3 @@
DROP TABLE HISTORY_EVENTS;
COMMIT;

View File

@ -0,0 +1,52 @@
INSERT INTO HISTORY_EVENTS (BUSINESS_PROCESS_ID, PARENT_BUSINESS_PROCESS_ID, TASK_ID, EVENT_TYPE, CREATED, USER_ID, DOMAIN, WORKBASKET_KEY, POR_COMPANY, POR_SYSTEM, POR_INSTANCE, POR_TYPE, POR_VALUE, TASK_CLASSIFICATION_KEY, TASK_CLASSIFICATION_CATEGORY, ATTACHMENT_CLASSIFICATION_KEY, COMMENT, OLD_VALUE, NEW_VALUE, CUSTOM_1, CUSTOM_2, CUSTOM_3, CUSTOM_4, OLD_DATA, NEW_DATA) VALUES
-- BUSINESS_PROCESS_ID, PARENT_BUSINESS_PROCESS_ID, TASK_ID, EVENT_TYPE, CREATED, USER_ID, DOMAIN, WORKBASKET_KEY, POR_COMPANY , POR_SYSTEM, POR_INSTANCE , POR_TYPE , POR_VALUE , TASK_CLASSIFICATION_KEY, TASK_CLASSIFICATION_CATEGORY , ATTACHMENT_CLASSIFICATION_KEY , COMMENT , OLD_VALUE , NEW_VALUE , CUSTOM_1 , CUSTOM_2 , CUSTOM_3 , CUSTOM_4 , OLD_DATA , NEW_DATA
('BPI:01' ,'', 'TKI:000000000000000000000000000000000000', 'CREATE', CURRENT_TIMESTAMP, 'USER_2_2', 'DOMAIN_B', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '11223344', 'L140101' , 'TASK' ,'' , 'this task has been created' ,'old_val' ,'new_val' ,'custom1' ,'custom2' , 'custom3' ,'custom4' ,'123' ,'456'),
('BPI:02' ,'', 'TKI:000000000000000000000000000000000000', 'UPDATE', DATEADD('DAY', -2, CURRENT_TIMESTAMP), 'USER_1_1', 'DOMAIN_A', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '65464564', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'777'),
('BPI:03' ,'BPI:01', 'TKI:000000000000000000000000000000000001', 'DELETE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_B', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'119' ,'555'),
('BPI:04' ,'' , 'TKI:000000000000000000000000000000000000', 'UPDATE', DATEADD('DAY', -1, CURRENT_TIMESTAMP), 'USER_1_2', 'DOMAIN_B', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '11223344', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'999'),
('BPI:03' ,'BPI:02', 'TKI:000000000000000000000000000000000001', 'DELETE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_A', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'1188' ,'QQQ'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'CREATE', DATEADD('DAY', -6, CURRENT_TIMESTAMP), 'USER_2_2', 'DOMAIN_A', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '11223344', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'eee'),
('BPI:06' ,'BPI:04', 'TKI:000000000000000000000000000000000001', 'UPDATE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_B', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'ZZZ' ,'777'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'DELETE', DATEADD('DAY', -5, CURRENT_TIMESTAMP), 'USER_2_1', 'DOMAIN_B', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '11223344', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'999'),
('BPI:04' ,'BPI:03', 'TKI:000000000000000000000000000000000001', 'CREATE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_B', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'288' ,'ooo'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'UPDATE', DATEADD('DAY', -1, CURRENT_TIMESTAMP), 'USER_1_1', 'DOMAIN_A', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '65464564', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'SSS'),
('BPI:04' ,'BPI:01', 'TKI:000000000000000000000000000000000001', 'DELETE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_A', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'DDD' ,'555'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'CREATE', DATEADD('DAY', -2, CURRENT_TIMESTAMP), 'USER_1_2', 'DOMAIN_A', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '68887564', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'555'),
('BPI:03' ,'BPI:05', 'TKI:000000000000000000000000000000000001', 'UPDATE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_A', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'123' ,'777'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'DELETE', DATEADD('DAY', -5, CURRENT_TIMESTAMP), 'USER_2_2', 'DOMAIN_A', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '68887564', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'456'),
('BPI:03' ,'BPI:07', 'TKI:000000000000000000000000000000000001', 'CREATE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_A', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'288' ,'ooo'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'UPDATE', DATEADD('DAY', -1, CURRENT_TIMESTAMP), 'USER_2_1', 'DOMAIN_B', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '11223344', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'456'),
('BPI:03' ,'BPI:07', 'TKI:000000000000000000000000000000000001', 'DELETE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_B', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'PPP' ,'777'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'CREATE', DATEADD('DAY', -5, CURRENT_TIMESTAMP), 'USER_1_1', 'DOMAIN_A', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '11223344', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'999'),
('BPI:05' ,'BPI:03', 'TKI:000000000000000000000000000000000001', 'UPDATE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_A', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'123' ,'eee'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'CREATE', DATEADD('DAY', -2, CURRENT_TIMESTAMP), 'USER_1_2', 'DOMAIN_A', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '11223344', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'555'),
('BPI:04' ,'BPI:04', 'TKI:000000000000000000000000000000000001', 'UPDATE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_A', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'123' ,'555'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'CREATE', DATEADD('DAY', -6, CURRENT_TIMESTAMP), 'USER_2_2', 'DOMAIN_A', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '77887564', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'SSS'),
('BPI:03' ,'BPI:01', 'TKI:000000000000000000000000000000000001', 'DELETE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_A', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'PPP' ,'456'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'UPDATE', DATEADD('DAY', -1, CURRENT_TIMESTAMP), 'USER_1_2', 'DOMAIN_B', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '77887500', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'777'),
('BPI:05' ,'BPI:03', 'TKI:000000000000000000000000000000000001', 'CREATE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_B', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'123' ,'ooo'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'DELETE', DATEADD('DAY', -2, CURRENT_TIMESTAMP), 'USER_2_1', 'DOMAIN_A', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '77887500', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'QQQ'),
('BPI:05' ,'BPI:04', 'TKI:000000000000000000000000000000000001', 'UPDATE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_B', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'288' ,'456'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'CREATE', DATEADD('DAY', -5, CURRENT_TIMESTAMP), 'USER_2_2', 'DOMAIN_A', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '11223344', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'555'),
('BPI:03' ,'BPI:05', 'TKI:000000000000000000000000000000000001', 'UPDATE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_A', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'000' ,'555'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'CREATE', DATEADD('DAY', -6, CURRENT_TIMESTAMP), 'USER_2_1', 'DOMAIN_A', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '11223344', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'777'),
('BPI:04' ,'BPI:07', 'TKI:000000000000000000000000000000000001', 'UPDATE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_A', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'PPP' ,'eee'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'UPDATE', DATEADD('DAY', -5, CURRENT_TIMESTAMP), 'USER_1_2', 'DOMAIN_B', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '11223344', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'999'),
('BPI:03' ,'BPI:01', 'TKI:000000000000000000000000000000000001', 'CREATE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_A', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'PPP' ,'ooo'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'CREATE', DATEADD('DAY', -1, CURRENT_TIMESTAMP), 'USER_1_1', 'DOMAIN_A', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '11223344', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'555'),
('BPI:05' ,'BPI:03', 'TKI:000000000000000000000000000000000001', 'DELETE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_A', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'123' ,'777'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'UPDATE', DATEADD('DAY', -1, CURRENT_TIMESTAMP), 'USER_1_2', 'DOMAIN_A', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '77887500', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'SSS'),
('BPI:06' ,'BPI:07', 'TKI:000000000000000000000000000000000001', 'DELETE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_B', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'123' ,'QQQ'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'UPDATE', DATEADD('DAY', -1, CURRENT_TIMESTAMP), 'USER_2_2', 'DOMAIN_B', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '11887500', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'456'),
('BPI:03' ,'BPI:03', 'TKI:000000000000000000000000000000000001', 'CREATE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_B', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'000' ,'999'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'DELETE', DATEADD('DAY', -1, CURRENT_TIMESTAMP), 'USER_2_2', 'DOMAIN_B', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '11887599', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'eee'),
('BPI:03' ,'BPI:04', 'TKI:000000000000000000000000000000000001', 'CREATE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_A', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'aaa' ,'555'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'CREATE', DATEADD('DAY', -6, CURRENT_TIMESTAMP), 'USER_1_2', 'DOMAIN_A', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '11223344', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'555'),
('BPI:06' ,'BPI:03', 'TKI:000000000000000000000000000000000001', 'UPDATE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_A', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'acc' ,'ooo'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'DELETE', DATEADD('DAY', -1, CURRENT_TIMESTAMP), 'USER_1_2', 'DOMAIN_A', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '11223344', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'777'),
('BPI:04' ,'BPI:03', 'TKI:000000000000000000000000000000000001', 'CREATE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_A', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'acc' ,'999'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'DELETE', DATEADD('DAY', -1, CURRENT_TIMESTAMP), 'USER_2_2', 'DOMAIN_B', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '11887599', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'999'),
('BPI:03' ,'BPI:05', 'TKI:000000000000000000000000000000000001', 'UPDATE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_A', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'WWW' ,'SSS'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'UPDATE', DATEADD('DAY', -5, CURRENT_TIMESTAMP), 'USER_2_1', 'DOMAIN_B', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '11887599', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'eee'),
('BPI:06' ,'BPI:05', 'TKI:000000000000000000000000000000000001', 'UPDATE', CURRENT_TIMESTAMP, 'USER_2_1', 'DOMAIN_A', 'WBI:100000000000000000000000000000000002', '11' , '' , '22' , '' , '' , 'L140101' , 'TASK' ,'DOCTYPE_DEFAULT' , 'created a bug' ,'' ,'' ,'custom1' ,'' , 'custom3' ,'' ,'123' ,'555'),
('BPI:02' ,'' , 'TKI:000000000000000000000000000000000000', 'DELETE', DATEADD('DAY', -1, CURRENT_TIMESTAMP), 'USER_1_2', 'DOMAIN_B', 'WBI:100000000000000000000000000000000001', '00' , 'PASystem', '00' , 'VNR' , '11223344', '' , '' ,'' , 'created by Peter' ,'2old_val' ,'new_val2' ,'custom1' ,'' , 'custom2' ,'' ,'234' ,'777');

View File

@ -0,0 +1,172 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>taskana-simplehistory-spring-test</artifactId>
<version>1.1.5-SNAPSHOT</version>
<name>${project.groupId}:${project.artifactId}</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.2.RELEASE</version>
<relativePath></relativePath>
</parent>
<licenses>
<license>
<name>The Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>pro.taskana.simplehistory</groupId>
<artifactId>taskana-simplehistory-rest-spring</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.plugin</groupId>
<artifactId>spring-plugin-core</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.6.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- Required for generation of REST documentation -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- Required for skip plugin tests by default -->
<excludes>
<exclude>**/*Plugin*Test.java</exclude>
</excludes>
<includes>
<include>**/*Test.java</include>
<include>**/*Documentation.java</include>
</includes>
<!-- Travis build workaround to prevent error that VM is closed due to an error. -->
<argLine>-Xms1024m -Xmx2048m</argLine>
</configuration>
</plugin>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>1.5.3</version>
<executions>
<execution>
<id>generate-docs</id>
<phase>prepare-package</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>html</backend>
<doctype>book</doctype>
<attributes>
<snippets>target/generated-snippets</snippets>
<docinfo>shared</docinfo>
</attributes>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-rest-docs</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.outputDirectory}/static/docs/rest
</outputDirectory>
<resources>
<resource>
<directory>
${project.build.directory}/generated-docs
</directory>
</resource>
<resource>
<directory>${project.basedir}/src/js</directory>
</resource>
</resources>
</configuration>
</execution>
<execution>
<id>copy-documentation-to-taskana-simplehistory-rest-spring-example</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>
../taskana-simplehistory-rest-spring-example/target/generated-docs
</outputDirectory>
<resources>
<resource>
<directory>
${project.build.outputDirectory}/static/docs/rest
</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,64 @@
<!-- Sourcecode at https://stackoverflow.com/questions/34481638/how-to-use-tocify-with-asciidoctor-for-a-dynamic-toc -->
<script src="./jquery-1.11.3.min.js"></script>
<script src="./jquery-ui.min.js"></script>
<script src="./jquery.tocify.min.js"></script>
<style>
.tocify-header {
font-style: italic;
}
.tocify-subheader {
font-style: normal;
font-size: 100%;
}
.tocify ul {
margin: 0;
}
.tocify-focus {
color: #7a2518;
background-color: rgba(0, 0, 0, 0.1);
}
.tocify-focus > a {
color: #7a2518;
}
</style>
<script type="text/javascript">
$(function () {
$("#toc").append("<div id='generated-toc'></div>");
$("#generated-toc").tocify({
extendPage: true,
context: "#content",
highlightOnScroll: true,
hideEffect: "slideUp",
hashGenerator: function(text, element) {
return $(element).attr("id");
},
smoothScroll: false,
theme: "none",
selectors: $( "#content" ).has( "h1" ).size() > 0 ? "h1,h2,h3,h4,h5" : "h2,h3,h4,h5",
ignoreSelector: ".discrete"
});
var handleTocOnResize = function() {
if ($(document).width() < 768) {
$("#generated-toc").hide();
$(".sectlevel0").show();
$(".sectlevel1").show();
}
else {
$("#generated-toc").show();
$(".sectlevel0").hide();
$(".sectlevel1").hide();
}
}
$(window).resize(handleTocOnResize);
handleTocOnResize();
});
</script>

View File

@ -0,0 +1,105 @@
= Taskana RESTful API Documentation
taskana.pro;
:doctype: book
:icons: font
:source-highlighter: highlightjs
:toc: left
:toclevels: 4
:sectlinks:
= Overview
[big]#*This Documentation is still under development and probably incomplete and/or flawed in certain areas.*#
== HTTP verbs
The Taskana RESTful API tries to adhere as closely as possible to standard HTTP and REST conventions in its
use of HTTP verbs.
|===
| Verb | Usage
| `GET`
| Used to retrieve a resource
| `POST`
| Used to create a new resource
| `PUT`
| Used to update a resource
| `DELTE`
| Used to delete a existing resource
|===
== HTTP status codes
The Taskana RESTful API tries to adhere as closely as possible to standard HTTP and REST conventions in its
use of HTTP status codes.
|===
| Status code | Usage
| `200 OK`
| The request completed successfully.
| `201 Created`
| The request completed successfully und create the new resource.
| `204 No Content`
| The request completed successfully and there is no content to send in the response payload.
| `400 Bad Request`
| The request was not performed because of a client error like a invalid parameter.
| `401 Unauthorized`
| The request has not been applied because it lacks valid authentication credentials for the target resource.
| `403 FORBIDDEN`
| The current user <user> has no read permission for <Resource Type> <Resource>.
| `404 Not Found`
| The requested resource did not exist.
| `405 Method not allowed`
| The method used in this request is can not be used on this resource.
| `406` Not acceptable
| Wrong content-type in request header.
| `409 Conflict`
| The resource could not be updatet or created because of a conflict with an existing one.
| `415 Unsupported Media Type`
| The content of the request can't be understood due to being in an unsupported media-type.
|===
== Common Fields
Taskana uses Spring HATEOAS to achive the best possible REST-conformity. +
In HATEOAS every response contains a map named *_links* in which the links for navigation are included. +
If a resource has embedded resources these are found in a map named *_embedded*.
== History event
It is a plugin which can get the history of action performed
=== Get all task history event
==== Example request
include::../../../{snippets}/GetAllTaskHistoryEventDocTest/http-request.adoc[]
==== Example response
include::../../../{snippets}/GetAllTaskHistoryEventDocTest/response-body.adoc[]
=== Get a specific task history event
==== Example request
include::../../../{snippets}/GetSpecificTaskHistoryEventDocTest/http-request.adoc[]
==== Example response
include::../../../{snippets}/GetSpecificTaskHistoryEventDocTest/response-body.adoc[]

View File

@ -0,0 +1,68 @@
package pro.taskana.rest;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import pro.taskana.rest.simplehistory.TaskHistoryRestConfiguration;
import pro.taskana.rest.simplehistory.sampledata.SampleDataGenerator;
/**
* Example Application to create the documentation.
*/
@SpringBootApplication
@ComponentScan(basePackages = "pro.taskana.rest.simplehistory")
@Import( {TaskHistoryRestConfiguration.class})
public class ExampleDocumentationApplication {
@Value("${taskana.schemaName:TASKANA}")
private String schemaName;
@Autowired
private SampleDataGenerator sampleDataGenerator;
public static void main(String[] args) {
SpringApplication.run(ExampleDocumentationApplication.class, args);
}
@Bean
@Primary
@ConfigurationProperties(prefix = "datasource")
public DataSourceProperties dataSourceProperties() {
DataSourceProperties props = new DataSourceProperties();
props.setUrl("jdbc:h2:mem:taskana;IGNORECASE=TRUE;LOCK_MODE=0;INIT=CREATE SCHEMA IF NOT EXISTS " + schemaName);
return props;
}
@Bean
public DataSource dataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
@Bean
public PlatformTransactionManager txManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
@DependsOn("getTaskanaEngine") // generate sample data after schema was inserted
public SampleDataGenerator generateSampleData(DataSource dataSource) throws SQLException {
sampleDataGenerator = new SampleDataGenerator(dataSource);
sampleDataGenerator.generateSampleData(schemaName);
return sampleDataGenerator;
}
}

View File

@ -0,0 +1,2 @@
logging.level.pro.taskana=INFO
taskana.schemaName=TASKANA

View File

@ -0,0 +1,205 @@
package pro.taskana;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.Collections;
import javax.sql.DataSource;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.hal.Jackson2HalModule;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import pro.taskana.exceptions.SystemException;
import pro.taskana.rest.resource.TaskHistoryEventListResource;
import pro.taskana.rest.simplehistory.TaskHistoryRestConfiguration;
import pro.taskana.rest.simplehistory.sampledata.SampleDataGenerator;
/**
* Controller for integration test.
*/
@EnableAutoConfiguration
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {TaskHistoryRestConfiguration.class},
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class TaskHistoryEventControllerIntTest {
@Value("${taskana.schemaName:TASKANA}")
public String schemaName;
private static final Logger LOGGER = LoggerFactory.getLogger(TaskHistoryEventControllerIntTest.class);
String server = "http://127.0.0.1:";
RestTemplate template;
HttpEntity<String> request;
@LocalServerPort
int port;
@Autowired
private DataSource dataSource;
@Before
public void before() {
template = getRestTemplate();
SampleDataGenerator sampleDataGenerator;
try {
sampleDataGenerator = new SampleDataGenerator(dataSource);
sampleDataGenerator.generateSampleData(schemaName);
} catch (SQLException e) {
throw new SystemException("tried to reset DB and caught Exception " + e, e);
}
}
@Test
public void testGetAllHistoryEvent() {
ResponseEntity<TaskHistoryEventListResource> response = template.exchange(
server + port + "/api/v1/task-history-event", HttpMethod.GET, request,
new ParameterizedTypeReference<TaskHistoryEventListResource>() {
});
assertNotNull(response.getBody().getLink(Link.REL_SELF));
assertEquals(50, response.getBody().getContent().size());
}
@Test
public void testGetAllHistoryEventDescendingOrder() {
String parameters = "/api/v1/task-history-event?sort-by=business-process-id&order=desc&page-size=3&page=1";
ResponseEntity<TaskHistoryEventListResource> response = template.exchange(
server + port + parameters, HttpMethod.GET, request,
new ParameterizedTypeReference<TaskHistoryEventListResource>() {
});
assertNotNull(response.getBody().getLink(Link.REL_SELF));
assertEquals(3, response.getBody().getContent().size());
assertTrue(response.getBody()
.getLink(Link.REL_SELF)
.getHref()
.endsWith(parameters));
}
@Test
public void testGetSpecificTaskHistoryEvent() {
ResponseEntity<TaskHistoryEventListResource> response = template.exchange(
server + port
+ "/api/v1/task-history-event?business-process-id=BPI:01&sort-by=business-process-id&order=asc&page-size=6&page=1",
HttpMethod.GET, request,
new ParameterizedTypeReference<TaskHistoryEventListResource>() {
});
assertNotNull(response.getBody().getLink(Link.REL_SELF));
assertNotNull(response.getBody().getLinks());
assertNotNull(response.getBody().getMetadata());
assertEquals(1, response.getBody().getContent().size());
}
@Test
public void testThrowsExceptionIfInvalidFilterIsUsed() {
try {
template.exchange(
server + port + "/api/v1/task-history-event?invalid=BPI:01", HttpMethod.GET, request,
new ParameterizedTypeReference<TaskHistoryEventListResource>() {
});
fail();
} catch (HttpClientErrorException e) {
assertEquals(HttpStatus.BAD_REQUEST, e.getStatusCode());
assertTrue(e.getResponseBodyAsString().contains("[invalid]"));
}
}
@Test
public void testGetHistoryEventOfDate() {
String currentTime = LocalDateTime.now().toString();
try {
template.exchange(
server + port + "/api/v1/task-history-event?created=" + currentTime, HttpMethod.GET, request,
new ParameterizedTypeReference<TaskHistoryEventListResource>() {
});
fail();
} catch (HttpClientErrorException e) {
assertEquals(HttpStatus.BAD_REQUEST, e.getStatusCode());
assertTrue(e.getResponseBodyAsString().contains(currentTime));
}
// correct Format 'yyyy-MM-dd'
currentTime = currentTime.substring(0, 10);
ResponseEntity<TaskHistoryEventListResource> response = template.exchange(
server + port + "/api/v1/task-history-event?created=" + currentTime, HttpMethod.GET, request,
new ParameterizedTypeReference<TaskHistoryEventListResource>() {
});
assertNotNull(response.getBody().getLink(Link.REL_SELF));
assertEquals(25, response.getBody().getContent().size());
}
@Test
public void testGetSecondPageSortedByKey() {
String parameters = "/api/v1/task-history-event?sort-by=workbasket-key&order=desc&page=2&page-size=2";
ResponseEntity<TaskHistoryEventListResource> response = template.exchange(
server + port + parameters, HttpMethod.GET, request,
new ParameterizedTypeReference<TaskHistoryEventListResource>() {
});
assertEquals(2, response.getBody().getContent().size());
assertEquals("WBI:100000000000000000000000000000000002",
response.getBody().getContent().iterator().next().getWorkbasketKey());
assertNotNull(response.getBody().getLink(Link.REL_SELF));
assertTrue(response.getBody()
.getLink(Link.REL_SELF)
.getHref()
.endsWith(parameters));
assertNotNull(response.getBody().getLink("allTaskHistoryEvent"));
assertTrue(response.getBody()
.getLink("allTaskHistoryEvent")
.getHref()
.endsWith("/api/v1/task-history-event"));
assertNotNull(response.getBody().getLink(Link.REL_FIRST));
assertNotNull(response.getBody().getLink(Link.REL_LAST));
}
/**
* Return a REST template which is capable of dealing with responses in HAL format.
*
* @return RestTemplate
*/
private RestTemplate getRestTemplate() {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.registerModule(new Jackson2HalModule());
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(MediaType.parseMediaTypes("application/hal+json"));
converter.setObjectMapper(mapper);
RestTemplate template = new RestTemplate(Collections.<HttpMessageConverter<?>> singletonList(converter));
return template;
}
}

View File

@ -0,0 +1,197 @@
package pro.taskana.doc.api;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
import static org.springframework.restdocs.payload.PayloadDocumentation.subsectionWithPath;
import java.util.HashMap;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.restdocs.JUnitRestDocumentation;
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders;
import org.springframework.restdocs.payload.FieldDescriptor;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import pro.taskana.rest.simplehistory.TaskHistoryRestConfiguration;
/**
* Generate documentation for the history event controller.
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TaskHistoryRestConfiguration.class,
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class TaskHistoryEventControllerRestDocumentation {
@LocalServerPort
int port;
@Rule
public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
private HashMap<String, String> taskHistoryEventFieldDescriptionsMap = new HashMap<String, String>();
private FieldDescriptor[] allTaskHistoryEventFieldDescriptors;
private FieldDescriptor[] taskHistoryEventFieldDescriptors;
@Before
public void setUp() {
document("{methodName}",
preprocessRequest(prettyPrint()),
preprocessResponse(prettyPrint()));
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
.apply(documentationConfiguration(this.restDocumentation)
.operationPreprocessors()
.withResponseDefaults(prettyPrint())
.withRequestDefaults(prettyPrint()))
.build();
taskHistoryEventFieldDescriptionsMap.put("taskHistoryId", "Unique ID");
taskHistoryEventFieldDescriptionsMap.put("businessProcessId", "The id of the business process");
taskHistoryEventFieldDescriptionsMap.put("parentBusinessProcessId",
"The id of the parent business process");
taskHistoryEventFieldDescriptionsMap.put("taskId", "The id of the task");
taskHistoryEventFieldDescriptionsMap.put("eventType", "The type of the event");
taskHistoryEventFieldDescriptionsMap.put("created", "The time was created");
taskHistoryEventFieldDescriptionsMap.put("userId", "The id of the user");
taskHistoryEventFieldDescriptionsMap.put("domain", "Domain");
taskHistoryEventFieldDescriptionsMap.put("workbasketKey", "The key of workbasket");
taskHistoryEventFieldDescriptionsMap.put("porCompany", "");
taskHistoryEventFieldDescriptionsMap.put("porSystem", "");
taskHistoryEventFieldDescriptionsMap.put("porInstance", "");
taskHistoryEventFieldDescriptionsMap.put("porValue", "");
taskHistoryEventFieldDescriptionsMap.put("porType", "");
taskHistoryEventFieldDescriptionsMap.put("taskClassificationKey", "The key of classification task");
taskHistoryEventFieldDescriptionsMap.put("taskClassificationCategory",
"The category of classification");
taskHistoryEventFieldDescriptionsMap.put("attachmentClassificationKey", "");
taskHistoryEventFieldDescriptionsMap.put("comment", "");
taskHistoryEventFieldDescriptionsMap.put("oldValue", "The old value");
taskHistoryEventFieldDescriptionsMap.put("newValue", "The new value");
taskHistoryEventFieldDescriptionsMap.put("custom1", "A custom property with name \"1\"");
taskHistoryEventFieldDescriptionsMap.put("custom2", "A custom property with name \"2\"");
taskHistoryEventFieldDescriptionsMap.put("custom3", "A custom property with name \"3\"");
taskHistoryEventFieldDescriptionsMap.put("custom4", "A custom property with name \"4\"");
taskHistoryEventFieldDescriptionsMap.put("oldData", "The old data");
taskHistoryEventFieldDescriptionsMap.put("newData", "The new data");
taskHistoryEventFieldDescriptionsMap.put("_links.self.href", "The links of this task history event");
taskHistoryEventFieldDescriptionsMap.put("_links.allTaskHistoryEvent.href", "Link to all task history event");
taskHistoryEventFieldDescriptionsMap.put("_links.first.href", "Link to the first result");
taskHistoryEventFieldDescriptionsMap.put("_links.last.href", "Link to the last result");
allTaskHistoryEventFieldDescriptors = new FieldDescriptor[] {
subsectionWithPath("taskHistoryEvents").description("An array of Task history event"),
fieldWithPath("_links.allTaskHistoryEvent.href").ignored(),
fieldWithPath("_links.self.href").ignored(),
fieldWithPath("_links.first.href").ignored(),
fieldWithPath("_links.last.href").ignored(),
fieldWithPath("_links.next.href").ignored(),
fieldWithPath("page.size").ignored(),
fieldWithPath("page.totalElements").ignored(),
fieldWithPath("page.totalPages").ignored(),
fieldWithPath("page.number").ignored()
};
taskHistoryEventFieldDescriptors = new FieldDescriptor[] {
fieldWithPath("taskHistoryEvents[].taskHistoryId").description(
taskHistoryEventFieldDescriptionsMap.get("taskHistoryId")),
fieldWithPath("taskHistoryEvents[].businessProcessId").description(
taskHistoryEventFieldDescriptionsMap.get("businessProcessId")),
fieldWithPath("taskHistoryEvents[].parentBusinessProcessId").description(
taskHistoryEventFieldDescriptionsMap.get("parentBusinessProcessId")),
fieldWithPath("taskHistoryEvents[].taskId").description(
taskHistoryEventFieldDescriptionsMap.get("taskId")),
fieldWithPath("taskHistoryEvents[].eventType").description(
taskHistoryEventFieldDescriptionsMap.get("eventType")),
fieldWithPath("taskHistoryEvents[].created").description(
taskHistoryEventFieldDescriptionsMap.get("created")),
fieldWithPath("taskHistoryEvents[].userId").description(
taskHistoryEventFieldDescriptionsMap.get("userId")),
fieldWithPath("taskHistoryEvents[].domain").description(
taskHistoryEventFieldDescriptionsMap.get("domain")),
fieldWithPath("taskHistoryEvents[].workbasketKey").description(
taskHistoryEventFieldDescriptionsMap.get("workbasketKey")),
fieldWithPath("taskHistoryEvents[].porCompany").description(
taskHistoryEventFieldDescriptionsMap.get("porCompany")),
fieldWithPath("taskHistoryEvents[].porSystem").description(
taskHistoryEventFieldDescriptionsMap.get("porSystem")),
fieldWithPath("taskHistoryEvents[].porInstance").description(
taskHistoryEventFieldDescriptionsMap.get("porInstance")),
fieldWithPath("taskHistoryEvents[].porValue").description(
taskHistoryEventFieldDescriptionsMap.get("porValue")),
fieldWithPath("taskHistoryEvents[].porType").description(
taskHistoryEventFieldDescriptionsMap.get("porType")),
fieldWithPath("taskHistoryEvents[].taskClassificationKey").description(
taskHistoryEventFieldDescriptionsMap.get("taskClassificationKey")),
fieldWithPath("taskHistoryEvents[].taskClassificationCategory").description(
taskHistoryEventFieldDescriptionsMap.get("taskClassificationCategory")),
fieldWithPath("taskHistoryEvents[].attachmentClassificationKey").description(
taskHistoryEventFieldDescriptionsMap.get("attachmentClassificationKey")),
fieldWithPath("taskHistoryEvents[].comment").description(
taskHistoryEventFieldDescriptionsMap.get("comment")),
fieldWithPath("taskHistoryEvents[].oldValue").description(
taskHistoryEventFieldDescriptionsMap.get("oldValue")),
fieldWithPath("taskHistoryEvents[].newValue").description(
taskHistoryEventFieldDescriptionsMap.get("newValue")),
fieldWithPath("taskHistoryEvents[].custom1").description(
taskHistoryEventFieldDescriptionsMap.get("custom1")),
fieldWithPath("taskHistoryEvents[].custom2").description(
taskHistoryEventFieldDescriptionsMap.get("custom2")),
fieldWithPath("taskHistoryEvents[].custom3").description(
taskHistoryEventFieldDescriptionsMap.get("custom3")),
fieldWithPath("taskHistoryEvents[].custom4").description(
taskHistoryEventFieldDescriptionsMap.get("custom4")),
fieldWithPath("taskHistoryEvents[].oldData").description(
taskHistoryEventFieldDescriptionsMap.get("oldData")),
fieldWithPath("taskHistoryEvents[].newData").description(
taskHistoryEventFieldDescriptionsMap.get("newData")),
fieldWithPath("_links.self.href").ignored(),
fieldWithPath("page").ignored()
};
}
@Test
public void getAllTaskHistoryEventDocTest() throws Exception {
this.mockMvc.perform(
RestDocumentationRequestBuilders.get(
"http://127.0.0.1:" + port + "/api/v1/task-history-event?page=1&page-size=3")
.accept("application/hal+json")
.header("Authorization", "Basic dGVhbWxlYWRfMTp0ZWFtbGVhZF8x"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcRestDocumentation.document("GetAllTaskHistoryEventDocTest",
responseFields(allTaskHistoryEventFieldDescriptors)));
}
@Test
public void getSpecificTaskHistoryEventDocTest() throws Exception {
this.mockMvc.perform(RestDocumentationRequestBuilders.get(
"http://127.0.0.1:" + port + "/api/v1/task-history-event?business-process-id=BPI:02")
.accept("application/hal+json")
.header("Authorization", "Basic dGVhbWxlYWRfMTp0ZWFtbGVhZF8x"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcRestDocumentation.document("GetSpecificTaskHistoryEventDocTest",
responseFields(taskHistoryEventFieldDescriptors)));
}
}

View File

@ -13,6 +13,7 @@
<modules>
<module>lib</module>
<module>rest</module>
<!-- History is an optional module. Thus not a child of the taskana parent. -->
</modules>
<properties>