TSK-1800: add secondary object references

This commit is contained in:
ryzheboka 2022-01-18 15:53:58 +01:00 committed by Elena Mokeeva
parent 3e8fdc6199
commit 967e59e012
68 changed files with 3538 additions and 1214 deletions

View File

@ -1,3 +1,4 @@
INSERT INTO OBJECT_REFERENCE VALUES ('1', 'Company1', 'System1', 'Instance1', 'Type1', 'Value1');
INSERT INTO OBJECT_REFERENCE VALUES ('2', 'Company2', 'System2', 'Instance2', 'Type2', 'Value2');
INSERT INTO OBJECT_REFERENCE VALUES ('3', 'Company3', 'System3', 'Instance3', 'Type3', 'Value3');
INSERT INTO OBJECT_REFERENCE VALUES ('ID1', 'TKI:000000000000000000000000000000000000', 'Company1', 'System1', 'Instance1', 'Type1', 'Value1');
INSERT INTO OBJECT_REFERENCE VALUES ('ID2', 'TKI:000000000000000000000000000000000000', 'Company2', 'System2', 'Instance2', 'Type2', 'Value2');
INSERT INTO OBJECT_REFERENCE VALUES ('ID3', 'TKI:000000000000000000000000000000000001', 'Company3', 'System3', 'Instance3', 'Type3', 'Value2');
INSERT INTO OBJECT_REFERENCE VALUES ('ID4', 'TKI:000000000000000000000000000000000002', 'Company1', 'System4', 'Instance4', 'Type2', 'Value2');

View File

@ -1,3 +1,3 @@
INSERT INTO OBJECT_REFERENCE VALUES ('1', 'Company1', 'System1', 'Instance1', 'Type1', 'Value1');
INSERT INTO OBJECT_REFERENCE VALUES ('2', 'Company2', 'System2', 'Instance2', 'Type2', 'Value2');
INSERT INTO OBJECT_REFERENCE VALUES ('3', 'Company3', 'System3', 'Instance3', 'Type3', 'Value3');
INSERT INTO OBJECT_REFERENCE VALUES ('1', 'TaskId1', 'Company1', 'System1', 'Instance1', 'Type1', 'Value1');
INSERT INTO OBJECT_REFERENCE VALUES ('2', 'TaskId2', 'Company2', 'System2', 'Instance2', 'Type2', 'Value2');
INSERT INTO OBJECT_REFERENCE VALUES ('3', 'TaskId3', 'Company3', 'System3', 'Instance3', 'Type3', 'Value3');

View File

@ -14,6 +14,7 @@ public final class IdGenerator {
public static final String ID_PREFIX_EXT_TASK = "ETI";
public static final String ID_PREFIX_BUSINESS_PROCESS = "BPI";
public static final String ID_PREFIX_ATTACHMENT = "TAI";
public static final String ID_PREFIX_OBJECT_REFERENCE = "ORI";
public static final String ID_PREFIX_TASK_COMMENT = "TCI";

View File

@ -1,15 +1,18 @@
SET SCHEMA %schemaName%;
CREATE TABLE TASKANA_SCHEMA_VERSION(
CREATE TABLE TASKANA_SCHEMA_VERSION
(
ID INT NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
VERSION VARCHAR(255) NOT NULL,
CREATED TIMESTAMP NOT NULL,
PRIMARY KEY (ID)
);
-- The VERSION value must match the value of TaskanaEngineConfiguration.TASKANA_SCHEMA_VERSION
INSERT INTO TASKANA_SCHEMA_VERSION (VERSION, CREATED) VALUES ('5.0.0', CURRENT_TIMESTAMP);
INSERT INTO TASKANA_SCHEMA_VERSION (VERSION, CREATED)
VALUES ('5.0.0', CURRENT_TIMESTAMP);
CREATE TABLE CLASSIFICATION(
CREATE TABLE CLASSIFICATION
(
ID VARCHAR(40) NOT NULL,
KEY VARCHAR(32) NOT NULL,
PARENT_ID VARCHAR(40) NOT NULL,
@ -37,7 +40,8 @@ CREATE TABLE CLASSIFICATION(
CONSTRAINT UC_CLASS_KEY_DOMAIN UNIQUE (KEY, DOMAIN)
);
CREATE TABLE WORKBASKET(
CREATE TABLE WORKBASKET
(
ID VARCHAR(40) NOT NULL,
KEY VARCHAR(64) NOT NULL,
CREATED TIMESTAMP NULL,
@ -60,7 +64,8 @@ CREATE TABLE WORKBASKET(
CONSTRAINT WB_KEY_DOMAIN UNIQUE (KEY, DOMAIN)
);
CREATE TABLE TASK (
CREATE TABLE TASK
(
ID VARCHAR(40) NOT NULL,
EXTERNAL_ID VARCHAR(64) NOT NULL,
CREATED TIMESTAMP NULL,
@ -126,13 +131,15 @@ CREATE TABLE TASK (
CONSTRAINT TASK_CLASS FOREIGN KEY (CLASSIFICATION_ID) REFERENCES CLASSIFICATION ON DELETE NO ACTION
);
CREATE TABLE DISTRIBUTION_TARGETS(
CREATE TABLE DISTRIBUTION_TARGETS
(
SOURCE_ID VARCHAR(40) NOT NULL,
TARGET_ID VARCHAR(40) NOT NULL,
PRIMARY KEY (SOURCE_ID, TARGET_ID)
);
CREATE TABLE WORKBASKET_ACCESS_LIST(
CREATE TABLE WORKBASKET_ACCESS_LIST
(
ID VARCHAR(40) NOT NULL,
WORKBASKET_ID VARCHAR(40) NOT NULL,
ACCESS_ID VARCHAR(255) NOT NULL,
@ -159,8 +166,10 @@ CREATE TABLE WORKBASKET_ACCESS_LIST(
CONSTRAINT ACCESS_LIST_WB FOREIGN KEY (WORKBASKET_ID) REFERENCES WORKBASKET ON DELETE CASCADE
);
CREATE TABLE OBJECT_REFERENCE(
CREATE TABLE OBJECT_REFERENCE
(
ID VARCHAR(40) NOT NULL,
TASK_ID VARCHAR(40) NOT NULL,
COMPANY VARCHAR(32) NOT NULL,
SYSTEM VARCHAR(32),
SYSTEM_INSTANCE VARCHAR(32),
@ -168,7 +177,8 @@ CREATE TABLE OBJECT_REFERENCE(
VALUE VARCHAR(128) NOT NULL
);
CREATE TABLE ATTACHMENT(
CREATE TABLE ATTACHMENT
(
ID VARCHAR(40) NOT NULL,
TASK_ID VARCHAR(40) NOT NULL,
CREATED TIMESTAMP NULL,
@ -187,16 +197,19 @@ CREATE TABLE ATTACHMENT(
CONSTRAINT ATT_CLASS FOREIGN KEY (CLASSIFICATION_ID) REFERENCES CLASSIFICATION ON DELETE NO ACTION
);
CREATE TABLE CONFIGURATION (
CREATE TABLE CONFIGURATION
(
NAME VARCHAR(8) NOT NULL,
ENFORCE_SECURITY BOOLEAN NULL,
CUSTOM_ATTRIBUTES CLOB NULL,
PRIMARY KEY (NAME)
);
INSERT INTO CONFIGURATION (NAME) VALUES ('MASTER');
INSERT INTO CONFIGURATION (NAME)
VALUES ('MASTER');
CREATE TABLE TASK_COMMENT(
CREATE TABLE TASK_COMMENT
(
ID VARCHAR(40) NOT NULL,
TASK_ID VARCHAR(40) NOT NULL,
TEXT_FIELD VARCHAR(1024) NULL,
@ -207,7 +220,8 @@ CREATE TABLE TASK_COMMENT(
CONSTRAINT COMMENT_TASK FOREIGN KEY (TASK_ID) REFERENCES TASK ON DELETE CASCADE
);
CREATE TABLE SCHEDULED_JOB(
CREATE TABLE SCHEDULED_JOB
(
JOB_ID INTEGER NOT NULL,
PRIORITY INTEGER NULL,
CREATED TIMESTAMP NULL,
@ -221,7 +235,8 @@ CREATE TABLE SCHEDULED_JOB(
PRIMARY KEY (JOB_ID)
);
CREATE TABLE TASK_HISTORY_EVENT (
CREATE TABLE TASK_HISTORY_EVENT
(
ID VARCHAR(40) NOT NULL,
BUSINESS_PROCESS_ID VARCHAR(128) NULL,
PARENT_BUSINESS_PROCESS_ID VARCHAR(128) NULL,
@ -309,7 +324,8 @@ CREATE TABLE CLASSIFICATION_HISTORY_EVENT
);
-- USER can not be taken as table name because it is a reserved keyword.
CREATE TABLE USER_INFO (
CREATE TABLE USER_INFO
(
USER_ID VARCHAR(32) NOT NULL,
FIRST_NAME VARCHAR(32) NULL,
LASTNAME VARCHAR(32) NULL,
@ -330,8 +346,7 @@ CREATE TABLE USER_INFO (
CREATE SEQUENCE SCHEDULED_JOB_SEQ
MINVALUE 1
START WITH 1
INCREMENT BY 1
CACHE 10;
INCREMENT BY 1 CACHE 10;
-- LIST OF RECOMMENDED INDEXES
@ -339,8 +354,7 @@ CREATE SEQUENCE SCHEDULED_JOB_SEQ
-- The script needs to be reviewed and adapted for each indiviual TASKANA setup.
-- ===========================
CREATE UNIQUE INDEX IDX_CLASSIFICATION_ID ON CLASSIFICATION
("ID" ASC)
INCLUDE ("CUSTOM_8", "CUSTOM_7", "CUSTOM_6", "CUSTOM_5", "CUSTOM_4", "CUSTOM_3", "CUSTOM_2",
("ID" ASC) INCLUDE ("CUSTOM_8", "CUSTOM_7", "CUSTOM_6", "CUSTOM_5", "CUSTOM_4", "CUSTOM_3", "CUSTOM_2",
"CUSTOM_1", "APPLICATION_ENTRY_POINT", "SERVICE_LEVEL", "PRIORITY", "DESCRIPTION", "NAME",
"CREATED", "VALID_IN_DOMAIN", "DOMAIN", "TYPE", "CATEGORY", "PARENT_KEY", "PARENT_ID", "KEY")
ALLOW REVERSE SCANS COLLECT SAMPLED DETAILED STATISTICS;
@ -351,57 +365,49 @@ CREATE INDEX IDX_CLASSIFICATION_CATEGORY ON CLASSIFICATION
"CUSTOM_6" ASC, "CUSTOM_5" ASC, "CUSTOM_4" ASC, "CUSTOM_3" ASC, "CUSTOM_2" ASC,
"APPLICATION_ENTRY_POINT" ASC, "SERVICE_LEVEL" ASC, "PRIORITY" ASC, "DESCRIPTION" ASC,
"NAME" ASC, "CREATED" ASC, "VALID_IN_DOMAIN" ASC, "PARENT_KEY" ASC, "PARENT_ID" ASC, "KEY" ASC,
"ID" ASC)
ALLOW REVERSE SCANS COLLECT SAMPLED DETAILED STATISTICS;
"ID" ASC) ALLOW REVERSE SCANS COLLECT SAMPLED DETAILED STATISTICS;
COMMIT WORK;
CREATE UNIQUE INDEX IDX_CLASSIFICATION_KEY_DOMAIN ON CLASSIFICATION
("KEY" ASC, "DOMAIN" ASC)
INCLUDE ("CUSTOM_8", "CUSTOM_7", "CUSTOM_6", "CUSTOM_5", "CUSTOM_4", "CUSTOM_3", "CUSTOM_2",
("KEY" ASC, "DOMAIN" ASC) INCLUDE ("CUSTOM_8", "CUSTOM_7", "CUSTOM_6", "CUSTOM_5", "CUSTOM_4", "CUSTOM_3", "CUSTOM_2",
"CUSTOM_1", "APPLICATION_ENTRY_POINT", "SERVICE_LEVEL", "PRIORITY", "DESCRIPTION", "NAME",
"CREATED", "VALID_IN_DOMAIN", "TYPE", "CATEGORY", "PARENT_KEY", "PARENT_ID", "ID")
ALLOW REVERSE SCANS COLLECT SAMPLED DETAILED STATISTICS;
COMMIT WORK;
CREATE INDEX IDX_TASK_WORKBASKET_KEY_DOMAIN ON TASK
("WORKBASKET_KEY" ASC, "DOMAIN" DESC)
ALLOW REVERSE SCANS COLLECT SAMPLED DETAILED STATISTICS;
("WORKBASKET_KEY" ASC, "DOMAIN" DESC) ALLOW REVERSE SCANS COLLECT SAMPLED DETAILED STATISTICS;
COMMIT WORK;
CREATE INDEX IDX_TASK_POR_VALUE ON TASK
(UPPER("POR_VALUE") ASC, "WORKBASKET_ID" ASC)
ALLOW REVERSE SCANS COLLECT SAMPLED DETAILED STATISTICS;
(UPPER("POR_VALUE") ASC, "WORKBASKET_ID" ASC) ALLOW REVERSE SCANS COLLECT SAMPLED DETAILED STATISTICS;
COMMIT WORK;
CREATE INDEX IDX_ATTACHMENT_TASK_ID ON ATTACHMENT
("TASK_ID" ASC, "RECEIVED" ASC, "CLASSIFICATION_ID" ASC, "CLASSIFICATION_KEY" ASC,
"MODIFIED" ASC, "CREATED" ASC, "ID" ASC)
ALLOW REVERSE SCANS COLLECT SAMPLED DETAILED STATISTICS;
"MODIFIED" ASC, "CREATED" ASC, "ID"
ASC) ALLOW REVERSE SCANS COLLECT SAMPLED DETAILED STATISTICS;
COMMIT WORK;
CREATE UNIQUE INDEX IDX_WORKBASKET_ID ON WORKBASKET
("ID" ASC)
INCLUDE ("ORG_LEVEL_4", "ORG_LEVEL_3", "ORG_LEVEL_2", "ORG_LEVEL_1", "OWNER", "DESCRIPTION",
("ID" ASC) INCLUDE ("ORG_LEVEL_4", "ORG_LEVEL_3", "ORG_LEVEL_2", "ORG_LEVEL_1", "OWNER", "DESCRIPTION",
"TYPE", "DOMAIN", "NAME", "KEY")
ALLOW REVERSE SCANS COLLECT SAMPLED DETAILED STATISTICS;
COMMIT WORK;
CREATE UNIQUE INDEX IDX_WORKBASKET_KEY_DOMAIN ON WORKBASKET
("KEY" ASC, "DOMAIN" ASC)
INCLUDE ("ORG_LEVEL_4", "ORG_LEVEL_3", "ORG_LEVEL_2", "ORG_LEVEL_1", "CUSTOM_4", "CUSTOM_3",
("KEY" ASC, "DOMAIN" ASC) INCLUDE ("ORG_LEVEL_4", "ORG_LEVEL_3", "ORG_LEVEL_2", "ORG_LEVEL_1", "CUSTOM_4", "CUSTOM_3",
"CUSTOM_2", "CUSTOM_1", "OWNER", "DESCRIPTION", "TYPE", "NAME", "MODIFIED", "CREATED", "ID")
ALLOW REVERSE SCANS COLLECT SAMPLED DETAILED STATISTICS;
COMMIT WORK;
CREATE UNIQUE INDEX IDX_WORKBASKET_KEY_DOMAIN_ID ON WORKBASKET
("KEY" ASC, "DOMAIN" ASC)
INCLUDE ("ID")
("KEY" ASC, "DOMAIN" ASC) INCLUDE ("ID")
ALLOW REVERSE SCANS COLLECT SAMPLED DETAILED STATISTICS;
COMMIT WORK;
CREATE INDEX IDX_WORKBASKET_ACCESS_LIST_ACCESS_ID ON WORKBASKET_ACCESS_LIST
("ACCESS_ID" ASC, "WORKBASKET_ID" ASC, "PERM_READ" ASC)
ALLOW REVERSE SCANS COLLECT SAMPLED DETAILED STATISTICS;
("ACCESS_ID" ASC, "WORKBASKET_ID" ASC, "PERM_READ" ASC) ALLOW REVERSE SCANS COLLECT SAMPLED DETAILED STATISTICS;
COMMIT WORK;
CREATE INDEX IDX_WORKBASKET_ACCESS_LIST_WORKBASKET_ID ON WORKBASKET_ACCESS_LIST
@ -409,6 +415,6 @@ CREATE INDEX IDX_WORKBASKET_ACCESS_LIST_WORKBASKET_ID ON WORKBASKET_ACCESS_LIST
"PERM_CUSTOM_9" ASC, "PERM_CUSTOM_8" ASC, "PERM_CUSTOM_7" ASC, "PERM_CUSTOM_6" ASC,
"PERM_CUSTOM_5" ASC, "PERM_CUSTOM_4" ASC, "PERM_CUSTOM_3" ASC, "PERM_CUSTOM_2" ASC,
"PERM_CUSTOM_1" ASC, "PERM_DISTRIBUTE" ASC, "PERM_TRANSFER" ASC, "PERM_APPEND" ASC,
"PERM_OPEN" ASC, "PERM_READ" ASC, "ACCESS_ID" ASC)
ALLOW REVERSE SCANS COLLECT SAMPLED DETAILED STATISTICS;
"PERM_OPEN" ASC, "PERM_READ" ASC, "ACCESS_ID"
ASC) ALLOW REVERSE SCANS COLLECT SAMPLED DETAILED STATISTICS;
COMMIT WORK;

View File

@ -4,6 +4,8 @@ SET SCHEMA %schemaName%;
INSERT INTO TASKANA_SCHEMA_VERSION (VERSION, CREATED) VALUES ('5.0.0', CURRENT_TIMESTAMP);
ALTER TABLE OBJECT_REFERENCE ADD COLUMN TASK_ID VARCHAR(40) NOT NULL DEFAULT 'EMPTY';
DROP INDEX "DB2ADMIN"."IDX1805212017540";
DROP INDEX "DB2ADMIN"."IDX1805212018000";
DROP INDEX "DB2ADMIN"."IDX1805212018030";

View File

@ -7,16 +7,19 @@ SET SCHEMA %schemaName%;
-- here in this file!
-- SET COLLATION DEFAULT_de_DE;
CREATE TABLE TASKANA_SCHEMA_VERSION(
CREATE TABLE TASKANA_SCHEMA_VERSION
(
ID INT NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1),
VERSION VARCHAR(255) NOT NULL,
CREATED TIMESTAMP NOT NULL,
PRIMARY KEY (ID)
);
-- The VERSION value must match the value of TaskanaEngineConfiguration.TASKANA_SCHEMA_VERSION
INSERT INTO TASKANA_SCHEMA_VERSION (VERSION, CREATED) VALUES ('5.0.0', CURRENT_TIMESTAMP);
INSERT INTO TASKANA_SCHEMA_VERSION (VERSION, CREATED)
VALUES ('5.0.0', CURRENT_TIMESTAMP);
CREATE TABLE CLASSIFICATION(
CREATE TABLE CLASSIFICATION
(
ID VARCHAR(40) NOT NULL,
KEY VARCHAR(32) NOT NULL,
PARENT_ID VARCHAR(40) NOT NULL,
@ -44,7 +47,8 @@ CREATE TABLE CLASSIFICATION(
CONSTRAINT UC_CLASS_KEY_DOMAIN UNIQUE (KEY, DOMAIN)
);
CREATE TABLE WORKBASKET(
CREATE TABLE WORKBASKET
(
ID VARCHAR(40) NOT NULL,
KEY VARCHAR(64) NOT NULL,
CREATED TIMESTAMP NULL,
@ -67,7 +71,8 @@ CREATE TABLE WORKBASKET(
CONSTRAINT WB_KEY_DOMAIN UNIQUE (KEY, DOMAIN)
);
CREATE TABLE TASK (
CREATE TABLE TASK
(
ID VARCHAR(40) NOT NULL,
EXTERNAL_ID VARCHAR(64) NOT NULL,
CREATED TIMESTAMP NULL,
@ -133,13 +138,15 @@ CREATE TABLE TASK (
CONSTRAINT TASK_CLASS FOREIGN KEY (CLASSIFICATION_ID) REFERENCES CLASSIFICATION ON DELETE NO ACTION
);
CREATE TABLE DISTRIBUTION_TARGETS(
CREATE TABLE DISTRIBUTION_TARGETS
(
SOURCE_ID VARCHAR(40) NOT NULL,
TARGET_ID VARCHAR(40) NOT NULL,
PRIMARY KEY (SOURCE_ID, TARGET_ID)
);
CREATE TABLE WORKBASKET_ACCESS_LIST(
CREATE TABLE WORKBASKET_ACCESS_LIST
(
ID VARCHAR(40) NOT NULL,
WORKBASKET_ID VARCHAR(40) NOT NULL,
ACCESS_ID VARCHAR(255) NOT NULL,
@ -166,8 +173,10 @@ CREATE TABLE WORKBASKET_ACCESS_LIST(
CONSTRAINT ACCESS_LIST_WB FOREIGN KEY (WORKBASKET_ID) REFERENCES WORKBASKET ON DELETE CASCADE
);
CREATE TABLE OBJECT_REFERENCE(
CREATE TABLE OBJECT_REFERENCE
(
ID VARCHAR(40) NOT NULL,
TASK_ID VARCHAR(40) NOT NULL,
COMPANY VARCHAR(32) NOT NULL,
SYSTEM VARCHAR(32),
SYSTEM_INSTANCE VARCHAR(32),
@ -175,7 +184,8 @@ CREATE TABLE OBJECT_REFERENCE(
VALUE VARCHAR(128) NOT NULL
);
CREATE TABLE ATTACHMENT(
CREATE TABLE ATTACHMENT
(
ID VARCHAR(40) NOT NULL,
TASK_ID VARCHAR(40) NOT NULL,
CREATED TIMESTAMP NULL,
@ -194,7 +204,8 @@ CREATE TABLE ATTACHMENT(
CONSTRAINT ATT_CLASS FOREIGN KEY (CLASSIFICATION_ID) REFERENCES CLASSIFICATION ON DELETE NO ACTION
);
CREATE TABLE TASK_COMMENT(
CREATE TABLE TASK_COMMENT
(
ID VARCHAR(40) NOT NULL,
TASK_ID VARCHAR(40) NOT NULL,
TEXT_FIELD VARCHAR(1024) NULL,
@ -205,7 +216,8 @@ CREATE TABLE TASK_COMMENT(
CONSTRAINT COMMENT_TASK FOREIGN KEY (TASK_ID) REFERENCES TASK ON DELETE CASCADE
);
CREATE TABLE SCHEDULED_JOB(
CREATE TABLE SCHEDULED_JOB
(
JOB_ID INTEGER NOT NULL,
PRIORITY INTEGER NULL,
CREATED TIMESTAMP NULL,
@ -219,7 +231,8 @@ CREATE TABLE SCHEDULED_JOB(
PRIMARY KEY (JOB_ID)
);
CREATE TABLE TASK_HISTORY_EVENT (
CREATE TABLE TASK_HISTORY_EVENT
(
ID VARCHAR(40) NOT NULL,
BUSINESS_PROCESS_ID VARCHAR(128) NULL,
PARENT_BUSINESS_PROCESS_ID VARCHAR(128) NULL,
@ -306,16 +319,19 @@ CREATE TABLE CLASSIFICATION_HISTORY_EVENT
PRIMARY KEY (ID)
);
CREATE TABLE CONFIGURATION (
CREATE TABLE CONFIGURATION
(
NAME VARCHAR(8) NOT NULL,
ENFORCE_SECURITY BOOLEAN NULL,
CUSTOM_ATTRIBUTES CLOB NULL,
PRIMARY KEY (NAME)
);
INSERT INTO CONFIGURATION (NAME) VALUES ('MASTER');
INSERT INTO CONFIGURATION (NAME)
VALUES ('MASTER');
CREATE TABLE USER_INFO (
CREATE TABLE USER_INFO
(
USER_ID VARCHAR(32) NOT NULL,
FIRST_NAME VARCHAR(32) NULL,
LASTNAME VARCHAR(32) NULL,
@ -336,6 +352,5 @@ CREATE TABLE USER_INFO (
CREATE SEQUENCE SCHEDULED_JOB_SEQ
MINVALUE 1
START WITH 1
INCREMENT BY 1
CACHE 10;
INCREMENT BY 1 CACHE 10;

View File

@ -2,4 +2,4 @@
INSERT INTO TASKANA_SCHEMA_VERSION (VERSION, CREATED) VALUES ('5.0.0', CURRENT_TIMESTAMP);
ALTER TABLE OBJECT_REFERENCE ADD COLUMN TASK_ID VARCHAR(40) NOT NULL DEFAULT 'EMPTY';

View File

@ -1,17 +1,21 @@
CREATE SCHEMA IF NOT EXISTS %schemaName%;
SET search_path TO %schemaName%;
SET
search_path TO %schemaName%;
CREATE TABLE TASKANA_SCHEMA_VERSION(
CREATE TABLE TASKANA_SCHEMA_VERSION
(
ID INT NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1),
VERSION VARCHAR(255) NOT NULL,
CREATED TIMESTAMP NOT NULL,
PRIMARY KEY (ID)
);
-- The VERSION value must match the value of TaskanaEngineConfiguration.TASKANA_SCHEMA_VERSION
INSERT INTO TASKANA_SCHEMA_VERSION (VERSION, CREATED) VALUES ('5.0.0', CURRENT_TIMESTAMP);
INSERT INTO TASKANA_SCHEMA_VERSION (VERSION, CREATED)
VALUES ('5.0.0', CURRENT_TIMESTAMP);
CREATE TABLE CLASSIFICATION(
CREATE TABLE CLASSIFICATION
(
ID VARCHAR(40) NOT NULL,
KEY VARCHAR(32) NOT NULL,
PARENT_ID VARCHAR(40) NOT NULL,
@ -39,7 +43,8 @@ CREATE TABLE CLASSIFICATION(
CONSTRAINT UC_CLASS_KEY_DOMAIN UNIQUE (KEY, DOMAIN)
);
CREATE TABLE WORKBASKET(
CREATE TABLE WORKBASKET
(
ID VARCHAR(40) NOT NULL,
KEY VARCHAR(64) NOT NULL,
CREATED TIMESTAMP NULL,
@ -62,7 +67,8 @@ CREATE TABLE WORKBASKET(
CONSTRAINT WB_KEY_DOMAIN UNIQUE (KEY, DOMAIN)
);
CREATE TABLE TASK (
CREATE TABLE TASK
(
ID VARCHAR(40) NOT NULL,
EXTERNAL_ID VARCHAR(64) NOT NULL,
CREATED TIMESTAMP NULL,
@ -128,13 +134,15 @@ CREATE TABLE TASK (
CONSTRAINT TASK_CLASS FOREIGN KEY (CLASSIFICATION_ID) REFERENCES CLASSIFICATION ON DELETE NO ACTION
);
CREATE TABLE DISTRIBUTION_TARGETS(
CREATE TABLE DISTRIBUTION_TARGETS
(
SOURCE_ID VARCHAR(40) NOT NULL,
TARGET_ID VARCHAR(40) NOT NULL,
PRIMARY KEY (SOURCE_ID, TARGET_ID)
);
CREATE TABLE WORKBASKET_ACCESS_LIST(
CREATE TABLE WORKBASKET_ACCESS_LIST
(
ID VARCHAR(40) NOT NULL,
WORKBASKET_ID VARCHAR(40) NOT NULL,
ACCESS_ID VARCHAR(255) NOT NULL,
@ -161,8 +169,10 @@ CREATE TABLE WORKBASKET_ACCESS_LIST(
CONSTRAINT ACCESS_LIST_WB FOREIGN KEY (WORKBASKET_ID) REFERENCES WORKBASKET ON DELETE CASCADE
);
CREATE TABLE OBJECT_REFERENCE(
CREATE TABLE OBJECT_REFERENCE
(
ID VARCHAR(40) NOT NULL,
TASK_ID VARCHAR(40) NOT NULL,
COMPANY VARCHAR(32) NOT NULL,
SYSTEM VARCHAR(32),
SYSTEM_INSTANCE VARCHAR(32),
@ -170,7 +180,8 @@ CREATE TABLE OBJECT_REFERENCE(
VALUE VARCHAR(128) NOT NULL
);
CREATE TABLE ATTACHMENT(
CREATE TABLE ATTACHMENT
(
ID VARCHAR(40) NOT NULL,
TASK_ID VARCHAR(40) NOT NULL,
CREATED TIMESTAMP NULL,
@ -189,7 +200,8 @@ CREATE TABLE ATTACHMENT(
CONSTRAINT ATT_CLASS FOREIGN KEY (CLASSIFICATION_ID) REFERENCES CLASSIFICATION ON DELETE NO ACTION
);
CREATE TABLE TASK_COMMENT(
CREATE TABLE TASK_COMMENT
(
ID VARCHAR(40) NOT NULL,
TASK_ID VARCHAR(40) NOT NULL,
TEXT_FIELD VARCHAR(1024) NULL,
@ -200,7 +212,8 @@ CREATE TABLE TASK_COMMENT(
CONSTRAINT COMMENT_TASK FOREIGN KEY (TASK_ID) REFERENCES TASK ON DELETE CASCADE
);
CREATE TABLE SCHEDULED_JOB(
CREATE TABLE SCHEDULED_JOB
(
JOB_ID INTEGER NOT NULL,
PRIORITY INTEGER NULL,
CREATED TIMESTAMP NULL,
@ -214,7 +227,8 @@ CREATE TABLE SCHEDULED_JOB(
PRIMARY KEY (JOB_ID)
);
CREATE TABLE TASK_HISTORY_EVENT (
CREATE TABLE TASK_HISTORY_EVENT
(
ID VARCHAR(40) NOT NULL,
BUSINESS_PROCESS_ID VARCHAR(128) NULL,
PARENT_BUSINESS_PROCESS_ID VARCHAR(128) NULL,
@ -301,17 +315,20 @@ CREATE TABLE CLASSIFICATION_HISTORY_EVENT
PRIMARY KEY (ID)
);
CREATE TABLE CONFIGURATION (
CREATE TABLE CONFIGURATION
(
NAME VARCHAR(8) NOT NULL,
ENFORCE_SECURITY BOOLEAN NULL,
CUSTOM_ATTRIBUTES TEXT NULL,
PRIMARY KEY (NAME)
);
INSERT INTO CONFIGURATION (NAME) VALUES ('MASTER');
INSERT INTO CONFIGURATION (NAME)
VALUES ('MASTER');
CREATE TABLE USER_INFO (
CREATE TABLE USER_INFO
(
USER_ID VARCHAR(32) NOT NULL,
FIRST_NAME VARCHAR(32) NULL,
LASTNAME VARCHAR(32) NULL,
@ -332,10 +349,10 @@ CREATE TABLE USER_INFO (
CREATE SEQUENCE SCHEDULED_JOB_SEQ
MINVALUE 1
START WITH 1
INCREMENT BY 1
CACHE 10;
INCREMENT BY 1 CACHE 10;
SET search_path TO taskana;
SET
search_path TO taskana;
CREATE INDEX IDX_CLASSIFICATION_ID ON CLASSIFICATION
(ID ASC, CUSTOM_8, CUSTOM_7, CUSTOM_6, CUSTOM_5, CUSTOM_4,

View File

@ -4,6 +4,8 @@ SET search_path = %schemaName%;
INSERT INTO TASKANA_SCHEMA_VERSION (VERSION, CREATED) VALUES ('5.0.0', CURRENT_TIMESTAMP);
ALTER TABLE OBJECT_REFERENCE ADD COLUMN TASK_ID VARCHAR(40) NOT NULL DEFAULT 'EMPTY';
DROP INDEX IF EXISTS IDX_CLASSIFICATION_1;
CREATE INDEX IDX_CLASSIFICATION_ID ON CLASSIFICATION
(ID ASC, CUSTOM_8, CUSTOM_7, CUSTOM_6, CUSTOM_5, CUSTOM_4,

View File

@ -30,6 +30,7 @@ import pro.taskana.simplehistory.impl.workbasket.WorkbasketHistoryEventMapper;
import pro.taskana.spi.history.api.events.task.TaskHistoryEvent;
import pro.taskana.spi.history.api.events.workbasket.WorkbasketHistoryEvent;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
/** Set up database for tests. */
public abstract class AbstractAccTest {
@ -184,7 +185,7 @@ public abstract class AbstractAccTest {
protected ObjectReference createObjectRef(
String company, String system, String systemInstance, String type, String value) {
ObjectReference objectRef = new ObjectReference();
ObjectReferenceImpl objectRef = new ObjectReferenceImpl();
objectRef.setCompany(company);
objectRef.setSystem(system);
objectRef.setSystemInstance(systemInstance);

View File

@ -12,10 +12,11 @@ import pro.taskana.common.api.exceptions.NotAuthorizedException;
import pro.taskana.task.api.exceptions.AttachmentPersistenceException;
import pro.taskana.task.api.exceptions.InvalidOwnerException;
import pro.taskana.task.api.exceptions.InvalidStateException;
import pro.taskana.task.api.exceptions.ObjectReferencePersistenceException;
import pro.taskana.task.api.exceptions.TaskAlreadyExistException;
import pro.taskana.task.api.exceptions.TaskNotFoundException;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.api.models.Task;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
import pro.taskana.workbasket.api.exceptions.WorkbasketNotFoundException;
/** Example Bootstrap Application. */
@ -28,9 +29,10 @@ public class ExampleBootstrap {
public void init(@Observes @Initialized(ApplicationScoped.class) Object init)
throws TaskNotFoundException, NotAuthorizedException, WorkbasketNotFoundException,
ClassificationNotFoundException, InvalidStateException, InvalidOwnerException,
TaskAlreadyExistException, InvalidArgumentException, AttachmentPersistenceException {
TaskAlreadyExistException, InvalidArgumentException, AttachmentPersistenceException,
ObjectReferencePersistenceException {
System.out.println("---------------------------> Start App");
ObjectReference objRef = new ObjectReference();
ObjectReferenceImpl objRef = new ObjectReferenceImpl();
objRef.setCompany("aCompany");
objRef.setSystem("aSystem");
objRef.setSystemInstance("anInstance");

View File

@ -13,8 +13,8 @@ import org.slf4j.LoggerFactory;
import pro.taskana.classification.api.ClassificationService;
import pro.taskana.classification.api.models.Classification;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.api.models.Task;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
import pro.taskana.workbasket.api.WorkbasketType;
import pro.taskana.workbasket.api.models.Workbasket;
@ -39,7 +39,7 @@ public class TaskanaCdiTestRestController {
Task task = taskanaEjb.getTaskService().newTask(workbasket.getKey());
task.setClassificationKey(classification.getKey());
ObjectReference objRef = new ObjectReference();
ObjectReferenceImpl objRef = new ObjectReferenceImpl();
objRef.setCompany("aCompany");
objRef.setSystem("aSystem");
objRef.setSystemInstance("anInstance");

View File

@ -9,9 +9,10 @@ import pro.taskana.common.api.exceptions.InvalidArgumentException;
import pro.taskana.common.api.exceptions.NotAuthorizedException;
import pro.taskana.task.api.TaskService;
import pro.taskana.task.api.exceptions.AttachmentPersistenceException;
import pro.taskana.task.api.exceptions.ObjectReferencePersistenceException;
import pro.taskana.task.api.exceptions.TaskAlreadyExistException;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.api.models.Task;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
import pro.taskana.workbasket.api.WorkbasketService;
import pro.taskana.workbasket.api.exceptions.WorkbasketNotFoundException;
@ -38,9 +39,10 @@ public class TaskanaEjb {
public void triggerRollback()
throws NotAuthorizedException, WorkbasketNotFoundException, ClassificationNotFoundException,
TaskAlreadyExistException, InvalidArgumentException, AttachmentPersistenceException {
TaskAlreadyExistException, InvalidArgumentException, AttachmentPersistenceException,
ObjectReferencePersistenceException {
final Task task = taskService.newTask(null);
ObjectReference objRef = new ObjectReference();
ObjectReferenceImpl objRef = new ObjectReferenceImpl();
objRef.setCompany("aCompany");
objRef.setSystem("aSystem");
objRef.setSystemInstance("anInstance");

View File

@ -144,6 +144,7 @@ public class TaskanaEngineImpl implements TaskanaEngine {
sessionManager.getMapper(TaskMapper.class),
sessionManager.getMapper(TaskCommentMapper.class),
sessionManager.getMapper(AttachmentMapper.class),
sessionManager.getMapper(ObjectReferenceMapper.class),
sessionManager.getMapper(UserMapper.class));
}

View File

@ -1458,6 +1458,50 @@ public interface TaskQuery extends BaseQuery<TaskSummary, TaskQueryColumnName> {
TaskQuery orderByAttachmentReceived(SortDirection sortDirection);
// endregion
// region secondaryObjectReference
/**
* Add the {@link ObjectReference} to exact match to your query. Each individual value has to
* match. Fields with the value 'null' will be ignored. The id of each ObjectReference will be
* ignored
*
* <p>If you specify multiple arguments they are combined with the OR keyword.
*
* @param objectReferences the combined values which are searched together.
* @return the query
*/
TaskQuery secondaryObjectReferenceIn(ObjectReference... objectReferences);
// endregion
// region secondaryObjectReferenceCompany
TaskQuery sorCompanyIn(String... companyIn);
TaskQuery sorCompanyLike(String... companyLike);
// endregion
// region secondaryObjectReferenceSystem
TaskQuery sorSystemIn(String... systemIn);
TaskQuery sorSystemLike(String... systemLike);
// endregion
// region secondaryObjectReferenceSystemInstance
TaskQuery sorSystemInstanceIn(String... systemInstanceIn);
TaskQuery sorSystemInstanceLike(String... systemInstanceLike);
// endregion
// region secondaryObjectReferenceType
TaskQuery sorTypeIn(String... typeIn);
TaskQuery sorTypeLike(String... typeLike);
// endregion
// region secondaryObjectReferenceValue
TaskQuery sorValueIn(String... valueIn);
TaskQuery sorValueLike(String... valueLike);
// region customAttributes
/**

View File

@ -57,7 +57,12 @@ public enum TaskQueryColumnName implements QueryColumnName {
A_CLASSIFICATION_ID("a.classification_id"),
A_CLASSIFICATION_KEY("a.classification_key"),
A_CHANNEL("a.channel"),
A_REF_VALUE("a.ref_value");
A_REF_VALUE("a.ref_value"),
O_COMPANY("o.company"),
O_SYSTEM("o.system"),
O_SYSTEM_INSTANCE("o.system_instance"),
O_TYPE("o.type"),
O_VALUE("o.value");
private final String name;
@ -69,6 +74,10 @@ public enum TaskQueryColumnName implements QueryColumnName {
return this.name().startsWith("A_");
}
public boolean isObjectReferenceColumn() {
return this.name().startsWith("O_");
}
@Override
public String toString() {
return name;

View File

@ -13,6 +13,7 @@ import pro.taskana.common.api.exceptions.TaskanaException;
import pro.taskana.task.api.exceptions.AttachmentPersistenceException;
import pro.taskana.task.api.exceptions.InvalidOwnerException;
import pro.taskana.task.api.exceptions.InvalidStateException;
import pro.taskana.task.api.exceptions.ObjectReferencePersistenceException;
import pro.taskana.task.api.exceptions.TaskAlreadyExistException;
import pro.taskana.task.api.exceptions.TaskCommentNotFoundException;
import pro.taskana.task.api.exceptions.TaskNotFoundException;
@ -145,10 +146,13 @@ public interface TaskService {
* @throws InvalidArgumentException thrown if the primary ObjectReference is invalid
* @throws AttachmentPersistenceException if an Attachment with ID will be added multiple times
* without using the task-methods
* @throws ObjectReferencePersistenceException if an ObjectReference with ID will be added
* multiple times without using the task-methods
*/
Task createTask(Task taskToCreate)
throws NotAuthorizedException, WorkbasketNotFoundException, ClassificationNotFoundException,
TaskAlreadyExistException, InvalidArgumentException, AttachmentPersistenceException;
TaskAlreadyExistException, InvalidArgumentException, AttachmentPersistenceException,
ObjectReferencePersistenceException;
/**
* Gets the details of a task by Id without checking permissions.
@ -312,6 +316,16 @@ public interface TaskService {
*/
Attachment newAttachment();
/**
* Returns a not inserted instance of {@link ObjectReference}.
*
* @return an empty new ObjectReference
*/
ObjectReference newObjectReference();
ObjectReference newObjectReference(
String company, String system, String systemInstance, String type, String value);
/**
* Update a task.
*
@ -326,13 +340,15 @@ public interface TaskService {
* @throws NotAuthorizedException if the current user is not authorized to update the task
* @throws AttachmentPersistenceException if an Attachment with ID will be added multiple times
* without using the task-methods
* @throws ObjectReferencePersistenceException if an ObjectReference with ID will be added
* multiple times without using the task-methods
* @throws InvalidStateException if an attempt is made to change the owner of the task and the
* task is not in state READY .
*/
Task updateTask(Task task)
throws InvalidArgumentException, TaskNotFoundException, ConcurrencyException,
ClassificationNotFoundException, NotAuthorizedException, AttachmentPersistenceException,
InvalidStateException;
ObjectReferencePersistenceException, InvalidStateException;
/**
* Transfers a list of {@linkplain Task Tasks} to another {@linkplain

View File

@ -0,0 +1,42 @@
package pro.taskana.task.api.exceptions;
import pro.taskana.common.api.exceptions.ErrorCode;
import pro.taskana.common.api.exceptions.TaskanaException;
import pro.taskana.common.internal.util.MapCreator;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.api.models.Task;
/**
* This exception is thrown when an {@linkplain ObjectReference} should be inserted to the DB, but
* it does already exist. <br>
* This may happen when a not inserted {@linkplain ObjectReference} with the same {@linkplain
* ObjectReference#getId() id} will be added twice on a {@linkplain Task}. This can't happen if the
* correct {@linkplain Task}-Methods will be used instead of the List ones.
*/
public class ObjectReferencePersistenceException extends TaskanaException {
public static final String ERROR_KEY = "OBJECT_REFERENCE_ALREADY_EXISTS";
private final String objectReferenceId;
private final String taskId;
public ObjectReferencePersistenceException(
String objectReferenceId, String taskId, Throwable cause) {
super(
String.format(
"Cannot insert ObjectReference with id '%s' for Task with id '%s' "
+ "because it already exists.",
objectReferenceId, taskId),
ErrorCode.of(
ERROR_KEY, MapCreator.of("objectReferenceId", objectReferenceId, "taskId", taskId)),
cause);
this.objectReferenceId = objectReferenceId;
this.taskId = taskId;
}
public String getObjectReferenceId() {
return objectReferenceId;
}
public String getTaskId() {
return taskId;
}
}

View File

@ -1,135 +1,96 @@
package pro.taskana.task.api.models;
import java.util.Objects;
/** ObjectReference-Interface to specify ObjectReference Attributes. */
public interface ObjectReference {
import pro.taskana.common.api.exceptions.InvalidArgumentException;
/**
* Gets the id of the ObjectReference.
*
* @return the id of the ObjectReference.
*/
String getId();
/** ObjectReference entity. */
public class ObjectReference {
private String id;
private String company;
private String system;
private String systemInstance;
private String type;
private String value;
/**
* Gets the id of the associated task.
*
* @return the taskId
*/
String getTaskId();
public ObjectReference() {}
/**
* Gets the company of the ObjectReference.
*
* @return the company
*/
String getCompany();
private ObjectReference(ObjectReference copyFrom) {
company = copyFrom.company;
system = copyFrom.system;
systemInstance = copyFrom.systemInstance;
type = copyFrom.type;
value = copyFrom.value;
}
/**
* Sets the company of the ObjectReference.
*
* @param company the company of the object reference
*/
void setCompany(String company);
public static void validate(ObjectReference objectReference, String objRefType, String objName)
throws InvalidArgumentException {
// check that all values in the ObjectReference are set correctly
if (objectReference == null) {
throw new InvalidArgumentException(
String.format("%s of %s must not be null.", objRefType, objName));
} else if (objectReference.getCompany() == null || objectReference.getCompany().isEmpty()) {
throw new InvalidArgumentException(
String.format("Company of %s of %s must not be empty", objRefType, objName));
} else if (objectReference.getType() == null || objectReference.getType().length() == 0) {
throw new InvalidArgumentException(
String.format("Type of %s of %s must not be empty", objRefType, objName));
} else if (objectReference.getValue() == null || objectReference.getValue().length() == 0) {
throw new InvalidArgumentException(
String.format("Value of %s of %s must not be empty", objRefType, objName));
}
}
/**
* Gets the system of the ObjectReference.
*
* @return the system
*/
String getSystem();
public String getId() {
return id;
}
/**
* Sets the system of the ObjectReference.
*
* @param system the system of the ObjectReference
*/
void setSystem(String system);
public void setId(String id) {
this.id = id;
}
/**
* Gets the systemInstance of the ObjectReference.
*
* @return the systemInstance
*/
String getSystemInstance();
public String getCompany() {
return company;
}
/**
* Sets the system instance of the ObjectReference.
*
* @param systemInstance the system instance of the ObjectReference
*/
void setSystemInstance(String systemInstance);
public void setCompany(String company) {
this.company = company;
}
/**
* Gets the type of the ObjectReference.
*
* @return the type
*/
String getType();
public String getSystem() {
return system;
}
/**
* Sets the type of the ObjectReference.
*
* @param type the type of the ObjectReference
*/
void setType(String type);
public void setSystem(String system) {
this.system = system;
}
/**
* Gets the value of the ObjectReference.
*
* @return the value
*/
String getValue();
public String getSystemInstance() {
return systemInstance;
}
/**
* Sets the value of the ObjectReference.
*
* @param value the value of the ObjectReference
*/
void setValue(String value);
public void setSystemInstance(String systemInstance) {
this.systemInstance = systemInstance;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public ObjectReference copy() {
return new ObjectReference(this);
}
@Override
public int hashCode() {
return Objects.hash(id, company, system, systemInstance, type, value);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof ObjectReference)) {
return false;
}
ObjectReference other = (ObjectReference) obj;
return Objects.equals(id, other.id)
&& Objects.equals(company, other.company)
&& Objects.equals(system, other.system)
&& Objects.equals(systemInstance, other.systemInstance)
&& Objects.equals(type, other.type)
&& Objects.equals(value, other.value);
}
@Override
public String toString() {
return "ObjectReference ["
+ "id="
+ this.id
+ ", company="
+ this.company
+ ", system="
+ this.system
+ ", systemInstance="
+ this.systemInstance
+ ", type="
+ this.type
+ ", value="
+ this.value
+ "]";
}
/**
* Duplicates this ObjectReference without the id and taskId.
*
* @return a copy of this ObjectReference
*/
ObjectReference copy();
}

View File

@ -19,10 +19,10 @@ public interface Task extends TaskSummary {
String CALLBACK_STATE = "callbackState";
/**
* Sets the external Id. It can be used to correlate the task to a task in an external system. The
* external Id is enforced to be unique. An attempt to create a task with an existing external Id
* will be rejected. So, this Id can be used to enforce idempotency of task creation. The
* externalId can only be set before the task is inserted. Taskana rejects attempts to modify
* Sets the external Id. It can be used to correlate the Task to a Task in an external system. The
* external Id is enforced to be unique. An attempt to create a Task with an existing external Id
* will be rejected. So, this Id can be used to enforce idempotency of Task creation. The
* externalId can only be set before the Task is inserted. Taskana rejects attempts to modify
* externalId.
*
* @param externalId the external Id
@ -30,7 +30,7 @@ public interface Task extends TaskSummary {
void setExternalId(String externalId);
/**
* Sets the time when the work on this task should be started.
* Sets the time when the work on this Task should be started.
*
* @param planned as exact {@link Instant}
*/
@ -44,36 +44,36 @@ public interface Task extends TaskSummary {
void setReceived(Instant received);
/**
* Sets the time when the work on this task should be finished.
* Sets the time when the work on this Task should be finished.
*
* @param due as exact {@link Instant}
*/
void setDue(Instant due);
/**
* Sets the name of the current task.
* Sets the name of the current Task.
*
* @param name the name of the task
* @param name the name of the Task
*/
void setName(String name);
/**
* Sets the description of the task.
* Sets the description of the Task.
*
* @param description the description of the task
* @param description the description of the Task
*/
void setDescription(String description);
/**
* Sets the Classification key that - together with the Domain from this task's work basket -
* selects the appropriate {@link Classification} for this task.
* Sets the Classification key that - together with the Domain from this Task's work basket -
* selects the appropriate {@link Classification} for this Task.
*
* @param classificationKey the classification key for the task
* @param classificationKey the classification key for the Task
*/
void setClassificationKey(String classificationKey);
/**
* Returns the key of the Workbasket where the task is stored in.
* Returns the key of the Workbasket where the Task is stored in.
*
* @return workbasketKey
*/
@ -119,47 +119,59 @@ public interface Task extends TaskSummary {
* Add an attachment.<br>
* NULL will be ignored and an attachment with the same ID will be replaced by the newer one.<br>
*
* @param attachment the {@link Attachment attachment} to be added to the task
* @param attachment the {@link Attachment attachment} to be added to the Task
*/
void addAttachment(Attachment attachment);
/**
* Return the attachments for this task. <br>
* Return the attachments for this Task. <br>
* Do not use List.add()/addAll() for adding Elements, because it can cause redundant data. Use
* addAttachment(). Clear() and remove() can be used, because it's a controllable change.
*
* @return the {@link List list} of {@link Attachment attachments} for this task
* @return the {@link List list} of {@link Attachment attachments} for this Task
*/
List<Attachment> getAttachments();
/**
* Sets the external business process id.
*
* @param businessProcessId Sets the business process id the task belongs to.
* @param businessProcessId Sets the business process id the Task belongs to.
*/
void setBusinessProcessId(String businessProcessId);
/**
* Sets the parent business process id to group associated processes.
*
* @param parentBusinessProcessId Sets the parent business process id the task belongs to
* @param parentBusinessProcessId Sets the parent business process id the Task belongs to
*/
void setParentBusinessProcessId(String parentBusinessProcessId);
/**
* Sets the ownerId of this task.
* Sets the ownerId of this Task.
*
* @param taskOwnerId the user id of the task's owner
* @param taskOwnerId the user id of the Task's owner
*/
void setOwner(String taskOwnerId);
/**
* Sets the {@link ObjectReference primaryObjectReference} of the task.
* Sets the {@link ObjectReference primaryObjectReference} of the Task.
*
* @param primaryObjRef to task main-subject
* @param primaryObjRef to Task main-subject
*/
void setPrimaryObjRef(ObjectReference primaryObjRef);
/**
* Initializes and sets the {@link ObjectReference primaryObjectReference} of the Task.
*
* @param company of the {@link ObjectReference primaryObjectReference} to be set
* @param system of the {@link ObjectReference primaryObjectReference} to be set
* @param systemInstance of the {@link ObjectReference primaryObjectReference} to be set
* @param type of the {@link ObjectReference primaryObjectReference} to be set
* @param value of the {@link ObjectReference primaryObjectReference} to be set
*/
void setPrimaryObjRef(
String company, String system, String systemInstance, String type, String value);
/**
* Sets/Changing the custom note for this Task.
*
@ -170,12 +182,12 @@ public interface Task extends TaskSummary {
/**
* Return a summary of the current Task.
*
* @return the TaskSummary object for the current task
* @return the TaskSummary object for the current Task
*/
TaskSummary asSummary();
/**
* Removes an attachment of the current task locally, when the ID is represented and does return
* Removes an attachment of the current Task locally, when the ID is represented and does return
* the removed attachment or null if there was no match.<br>
* The changed Task need to be updated calling the {@link TaskService#updateTask(Task)}.
*
@ -194,7 +206,7 @@ public interface Task extends TaskSummary {
/**
* Duplicates this Task without the internal and external id. All referenced {@link Attachment}s
* are copied as well.
* and {@link ObjectReference}s are copied as well.
*
* @return a copy of this Task
*/

View File

@ -5,6 +5,7 @@ import java.util.List;
import pro.taskana.classification.api.models.ClassificationSummary;
import pro.taskana.task.api.TaskCustomField;
import pro.taskana.task.api.TaskService;
import pro.taskana.task.api.TaskState;
import pro.taskana.workbasket.api.models.WorkbasketSummary;
@ -15,21 +16,21 @@ import pro.taskana.workbasket.api.models.WorkbasketSummary;
public interface TaskSummary {
/**
* Gets the id of the task.
* Gets the id of the Task.
*
* @return taskId
*/
String getId();
/**
* Gets the external id of the task.
* Gets the external id of the Task.
*
* @return the external Id
*/
String getExternalId();
/**
* Gets the name of the task-creator.
* Gets the name of the creator of the Task.
*
* @return creator
*/
@ -38,133 +39,176 @@ public interface TaskSummary {
/**
* Gets the time when the task was created.
*
* @return the created Instant
* @return the created {@link Instant}
*/
Instant getCreated();
/**
* Gets the time when the task was claimed.
* Gets the time when the Task was claimed.
*
* @return the claimed Instant
* @return the claimed {@link Instant}
*/
Instant getClaimed();
/**
* Gets the time when the task was completed.
* Gets the time when the Task was completed.
*
* @return the completed Instant
* @return the completed {@link Instant}
*/
Instant getCompleted();
/**
* Gets the time when the task was last modified.
* Gets the time when the Task was last modified.
*
* @return the last modified Instant
* @return the last modified {@link Instant}
*/
Instant getModified();
/**
* Gets the time when the task is planned to be executed.
* Gets the time when the Task is planned to be executed.
*
* @return the planned Instant
* @return the planned {@link Instant}
*/
Instant getPlanned();
/**
* Gets the time when when the surrounding process was started.
* Gets the time when the surrounding process was started.
*
* @return the received Instant
* @return the received {@link Instant}
*/
Instant getReceived();
/**
* Gets the time when the task is due.
* Gets the time when the Task is due.
*
* @return the due Instant
* @return the due {@link Instant}
*/
Instant getDue();
/**
* Gets the name of the task.
* Gets the name of the Task.
*
* @return the task's name
* @return the Task's name
*/
String getName();
/**
* Gets the note attached to the task.
* Gets the note attached to the Task.
*
* @return the task's note
* @return the Task's note
*/
String getNote();
/**
* Gets the description of the task.
* Gets the description of the Task.
*
* @return the task's description
* @return the Task's description
*/
String getDescription();
/**
* Gets the priority of the task.
* Gets the priority of the Task.
*
* @return the task's priority
* @return the Task's priority
*/
int getPriority();
/**
* Gets the state of the task.
* Gets the state of the Task.
*
* @return the task's state
* @return the Task's state
*/
TaskState getState();
/**
* Gets the classification summary of the task.
* Gets the {@link ClassificationSummary} of the Task.
*
* @return the task's classificationSummary
* @return the Task's {@link ClassificationSummary}
*/
ClassificationSummary getClassificationSummary();
/**
* Gets the workbasket summary of the task.
* Gets the {@link WorkbasketSummary} of the Task.
*
* @return the task's workbasketSummary
* @return the Task's {@link WorkbasketSummary}
*/
WorkbasketSummary getWorkbasketSummary();
/**
* Gets the attachment summaries of the task.
* Gets the {@link AttachmentSummary attachmentSummaries} of the Task.
*
* @return the task's attachment summaries
* @return the Task's {@link AttachmentSummary attachmentSummaries}
*/
List<AttachmentSummary> getAttachmentSummaries();
/**
* Gets the domain of the task.
* Gets the secondary {@link ObjectReference}s of the Task.
*
* @return the task's domain
* @return the Task's secondary {@link ObjectReference}s
*/
List<ObjectReference> getSecondaryObjectReferences();
/**
* Add an {@link ObjectReference} to the list of secondary {@link ObjectReference}s.<br>
* NULL will be ignored and an ObjectReference with the same ID will be replaced by the newer one.
* <br>
*
* @param objectReference the secondary {@link ObjectReference objectReference} to be added to the
* Task
*/
void addSecondaryObjectReference(ObjectReference objectReference);
/**
* Add an {@link ObjectReference} to the list of secondary {@link ObjectReference}s.<br>
* NULL will be ignored and an ObjectReference with the same ID will be replaced by the newer one.
* <br>
*
* @param company of the {@link ObjectReference objectReference} to be added to the Task
* @param system of the {@link ObjectReference objectReference} to be added to the Task
* @param systemInstance of the {@link ObjectReference objectReference} to be added to the Task
* @param type of the {@link ObjectReference objectReference} to be added to the Task
* @param value of the {@link ObjectReference objectReference} to be added to the Task
*/
void addSecondaryObjectReference(
String company, String system, String systemInstance, String type, String value);
/**
* Removes a secondary {@link ObjectReference} of the current Task locally, when the ID is
* represented and does return the removed {@link ObjectReference} or null if there was no match.
* <br>
* The changed Task need to be updated calling the {@link TaskService#updateTask(Task)}.
*
* @param objectReferenceID ID of the {@link ObjectReference} which should be removed.
* @return the {@link ObjectReference} which will be removed after updating OR null if there was
* no matching {@link ObjectReference}
*/
ObjectReference removeSecondaryObjectReference(String objectReferenceID);
/**
* Gets the domain of the Task.
*
* @return the Task's domain
*/
String getDomain();
/**
* Gets the businessProcessId of the task.
* Gets the businessProcessId of the Task.
*
* @return the task's businessProcessId
* @return the Task's businessProcessId
*/
String getBusinessProcessId();
/**
* Gets the parentBusinessProcessId of the task.
* Gets the parentBusinessProcessId of the Task.
*
* @return the task's parentBusinessProcessId
* @return the Task's parentBusinessProcessId
*/
String getParentBusinessProcessId();
/**
* Gets the owner of the task.
* Gets the owner of the Task.
*
* @return the task's owner
* @return the Task's owner
*/
String getOwner();
@ -176,28 +220,28 @@ public interface TaskSummary {
String getOwnerLongName();
/**
* Gets the primary ObjectReference of the task.
* Gets the primary {@link ObjectReference} of the Task.
*
* @return the task's primary ObjectReference
* @return the Task's primary {@link ObjectReference}
*/
ObjectReference getPrimaryObjRef();
/**
* Gets the isRead flag of the task.
* Gets the isRead flag of the Task.
*
* @return the task's isRead flag
* @return the Task's isRead flag
*/
boolean isRead();
/**
* Gets the isTransferred flag of the task.
* Gets the isTransferred flag of the Task.
*
* @return the task's isTransferred flag.
* @return the Task's isTransferred flag.
*/
boolean isTransferred();
/**
* Gets the custom attribute of the task.
* Gets the custom attribute of the Task.
*
* @param customField identifies which custom attribute is requested.
* @return the value for the given customField

View File

@ -19,9 +19,9 @@ import pro.taskana.common.internal.util.IdGenerator;
import pro.taskana.task.api.exceptions.AttachmentPersistenceException;
import pro.taskana.task.api.models.Attachment;
import pro.taskana.task.api.models.AttachmentSummary;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.api.models.Task;
import pro.taskana.task.internal.models.AttachmentImpl;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
import pro.taskana.task.internal.models.TaskImpl;
public class AttachmentHandler {
@ -183,7 +183,7 @@ public class AttachmentHandler {
throw new InvalidArgumentException("ClassificationKey of Attachment must not be empty.");
}
ObjectReference.validate(attachment.getObjectReference(), "ObjectReference", "Attachment");
ObjectReferenceImpl.validate(attachment.getObjectReference(), "ObjectReference", "Attachment");
classification =
classificationService

View File

@ -23,8 +23,8 @@ public interface AttachmentMapper {
@Insert(
"INSERT INTO ATTACHMENT (ID, TASK_ID, CREATED, MODIFIED, CLASSIFICATION_KEY, CLASSIFICATION_ID, REF_COMPANY, REF_SYSTEM, REF_INSTANCE, REF_TYPE, REF_VALUE, CHANNEL, RECEIVED, CUSTOM_ATTRIBUTES) "
+ "VALUES (#{att.id}, #{att.taskId}, #{att.created}, #{att.modified}, #{att.classificationSummary.key}, #{att.classificationSummary.id}, #{att.objectReference.company}, #{att.objectReference.system}, #{att.objectReference.systemInstance}, "
+ " #{att.objectReference.type}, #{att.objectReference.value}, #{att.channel}, #{att.received}, #{att.customAttributes,jdbcType=CLOB,javaType=java.util.Map,typeHandler=pro.taskana.common.internal.persistence.MapTypeHandler} )")
+ "VALUES (#{att.id}, #{att.taskId}, #{att.created}, #{att.modified}, #{att.classificationSummary.key}, #{att.classificationSummary.id}, #{att.objectReferenceImpl.company}, #{att.objectReferenceImpl.system}, #{att.objectReferenceImpl.systemInstance}, "
+ " #{att.objectReferenceImpl.type}, #{att.objectReferenceImpl.value}, #{att.channel}, #{att.received}, #{att.customAttributes,jdbcType=CLOB,javaType=java.util.Map,typeHandler=pro.taskana.common.internal.persistence.MapTypeHandler} )")
void insert(@Param("att") AttachmentImpl att);
@Select(
@ -39,11 +39,11 @@ public interface AttachmentMapper {
@Result(property = "modified", column = "MODIFIED")
@Result(property = "classificationSummaryImpl.key", column = "CLASSIFICATION_KEY")
@Result(property = "classificationSummaryImpl.id", column = "CLASSIFICATION_ID")
@Result(property = "objectReference.company", column = "REF_COMPANY")
@Result(property = "objectReference.system", column = "REF_SYSTEM")
@Result(property = "objectReference.systemInstance", column = "REF_INSTANCE")
@Result(property = "objectReference.type", column = "REF_TYPE")
@Result(property = "objectReference.value", column = "REF_VALUE")
@Result(property = "objectReferenceImpl.company", column = "REF_COMPANY")
@Result(property = "objectReferenceImpl.system", column = "REF_SYSTEM")
@Result(property = "objectReferenceImpl.systemInstance", column = "REF_INSTANCE")
@Result(property = "objectReferenceImpl.type", column = "REF_TYPE")
@Result(property = "objectReferenceImpl.value", column = "REF_VALUE")
@Result(property = "channel", column = "CHANNEL")
@Result(property = "received", column = "RECEIVED")
@Result(
@ -74,11 +74,11 @@ public interface AttachmentMapper {
@Result(property = "modified", column = "MODIFIED")
@Result(property = "classificationSummaryImpl.key", column = "CLASSIFICATION_KEY")
@Result(property = "classificationSummaryImpl.id", column = "CLASSIFICATION_ID")
@Result(property = "objectReference.company", column = "REF_COMPANY")
@Result(property = "objectReference.system", column = "REF_SYSTEM")
@Result(property = "objectReference.systemInstance", column = "REF_INSTANCE")
@Result(property = "objectReference.type", column = "REF_TYPE")
@Result(property = "objectReference.value", column = "REF_VALUE")
@Result(property = "objectReferenceImpl.company", column = "REF_COMPANY")
@Result(property = "objectReferenceImpl.system", column = "REF_SYSTEM")
@Result(property = "objectReferenceImpl.systemInstance", column = "REF_INSTANCE")
@Result(property = "objectReferenceImpl.type", column = "REF_TYPE")
@Result(property = "objectReferenceImpl.value", column = "REF_VALUE")
@Result(property = "channel", column = "CHANNEL")
@Result(property = "received", column = "RECEIVED")
List<AttachmentSummaryImpl> findAttachmentSummariesByTaskIds(
@ -93,8 +93,8 @@ public interface AttachmentMapper {
@Update(
"UPDATE ATTACHMENT SET TASK_ID = #{taskId}, CREATED = #{created}, MODIFIED = #{modified},"
+ " CLASSIFICATION_KEY = #{classificationSummary.key}, CLASSIFICATION_ID = #{classificationSummary.id}, REF_COMPANY = #{objectReference.company}, REF_SYSTEM = #{objectReference.system},"
+ " REF_INSTANCE = #{objectReference.systemInstance}, REF_TYPE = #{objectReference.type}, REF_VALUE = #{objectReference.value},"
+ " CLASSIFICATION_KEY = #{classificationSummary.key}, CLASSIFICATION_ID = #{classificationSummary.id}, REF_COMPANY = #{objectReferenceImpl.company}, REF_SYSTEM = #{objectReferenceImpl.system},"
+ " REF_INSTANCE = #{objectReferenceImpl.systemInstance}, REF_TYPE = #{objectReferenceImpl.type}, REF_VALUE = #{objectReferenceImpl.value},"
+ " CHANNEL = #{channel}, RECEIVED = #{received}, CUSTOM_ATTRIBUTES = #{customAttributes,jdbcType=CLOB,javaType=java.util.Map,typeHandler=pro.taskana.common.internal.persistence.MapTypeHandler}"
+ " WHERE ID = #{id}")
void update(AttachmentImpl attachment);

View File

@ -0,0 +1,164 @@
package pro.taskana.task.internal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.ibatis.exceptions.PersistenceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pro.taskana.common.api.exceptions.InvalidArgumentException;
import pro.taskana.common.internal.util.IdGenerator;
import pro.taskana.task.api.exceptions.ObjectReferencePersistenceException;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.api.models.Task;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
import pro.taskana.task.internal.models.TaskImpl;
/** Handles all operations on secondary {@link ObjectReference}s. */
public class ObjectReferenceHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(ObjectReferenceHandler.class);
private final ObjectReferenceMapper objectReferenceMapper;
ObjectReferenceHandler(ObjectReferenceMapper objectReferenceMapper) {
this.objectReferenceMapper = objectReferenceMapper;
}
void insertNewSecondaryObjectReferencesOnTaskCreation(TaskImpl task)
throws ObjectReferencePersistenceException, InvalidArgumentException {
List<ObjectReference> objectReferences = task.getSecondaryObjectReferences();
if (objectReferences != null) {
for (ObjectReference objectReference : objectReferences) {
ObjectReferenceImpl objectReferenceImpl = (ObjectReferenceImpl) objectReference;
initObjectReference(objectReferenceImpl, task);
ObjectReferenceImpl.validate(objectReferenceImpl, "ObjectReference", "Task");
try {
objectReferenceMapper.insert(objectReferenceImpl);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(
"TaskService.createTask() for TaskId={} INSERTED an object reference={}.",
task.getId(),
objectReference);
}
} catch (PersistenceException e) {
throw new ObjectReferencePersistenceException(objectReference.getId(), task.getId(), e);
}
}
}
}
void insertAndDeleteObjectReferencesOnTaskUpdate(TaskImpl newTaskImpl, TaskImpl oldTaskImpl)
throws ObjectReferencePersistenceException, InvalidArgumentException {
List<ObjectReference> newObjectReferences =
newTaskImpl.getSecondaryObjectReferences().stream()
.filter(Objects::nonNull)
.collect(Collectors.toList());
newTaskImpl.setSecondaryObjectReferences(newObjectReferences);
for (ObjectReference objectReference : newObjectReferences) {
ObjectReferenceImpl.validate(objectReference, "Object Reference", "Task");
initObjectReference((ObjectReferenceImpl) objectReference, newTaskImpl);
}
deleteRemovedObjectReferencesOnTaskUpdate(newTaskImpl, oldTaskImpl);
insertNewObjectReferencesOnTaskUpdate(newTaskImpl, oldTaskImpl);
updateModifiedObjectReferencesOnTaskUpdate(newTaskImpl, oldTaskImpl);
}
private void insertNewObjectReferencesOnTaskUpdate(TaskImpl newTaskImpl, TaskImpl oldTaskImpl)
throws ObjectReferencePersistenceException {
Set<String> oldObjectReferencesIds =
oldTaskImpl.getSecondaryObjectReferences().stream()
.map(ObjectReference::getId)
.collect(Collectors.toSet());
List<ObjectReference> newObjectReferences =
newTaskImpl.getSecondaryObjectReferences().stream()
.filter(o -> !oldObjectReferencesIds.contains(o.getId()))
.collect(Collectors.toList());
for (ObjectReference objectReference : newObjectReferences) {
insertNewObjectReferenceOnTaskUpdate(newTaskImpl, objectReference);
}
}
private void updateModifiedObjectReferencesOnTaskUpdate(
TaskImpl newTaskImpl, TaskImpl oldTaskImpl) {
List<ObjectReference> newObjectReferences = newTaskImpl.getSecondaryObjectReferences();
List<ObjectReference> oldObjectReferences = oldTaskImpl.getSecondaryObjectReferences();
if (newObjectReferences != null
&& !newObjectReferences.isEmpty()
&& oldObjectReferences != null
&& !oldObjectReferences.isEmpty()) {
final Map<String, ObjectReference> oldObjectReferencesMap =
oldObjectReferences.stream()
.collect(Collectors.toMap(ObjectReference::getId, Function.identity()));
newObjectReferences.forEach(
o -> {
if (oldObjectReferencesMap.containsKey(o.getId())
&& !o.equals(oldObjectReferencesMap.get(o.getId()))) {
objectReferenceMapper.update((ObjectReferenceImpl) o);
}
});
}
}
private void deleteRemovedObjectReferencesOnTaskUpdate(
TaskImpl newTaskImpl, TaskImpl oldTaskImpl) {
final List<ObjectReference> newObjectReferences = newTaskImpl.getSecondaryObjectReferences();
List<String> newObjectReferencesIds = new ArrayList<>();
if (newObjectReferences != null && !newObjectReferences.isEmpty()) {
newObjectReferencesIds =
newObjectReferences.stream().map(ObjectReference::getId).collect(Collectors.toList());
}
List<ObjectReference> oldObjectReferences = oldTaskImpl.getSecondaryObjectReferences();
if (oldObjectReferences != null && !oldObjectReferences.isEmpty()) {
final List<String> newObjRefIds = newObjectReferencesIds;
oldObjectReferences.forEach(
o -> {
if (!newObjRefIds.contains(o.getId())) {
objectReferenceMapper.delete(o.getId());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(
"TaskService.updateTask() for TaskId={} DELETED an ObjectReference={}.",
newTaskImpl.getId(),
o);
}
}
});
}
}
private void insertNewObjectReferenceOnTaskUpdate(
TaskImpl newTaskImpl, ObjectReference objectReference)
throws ObjectReferencePersistenceException {
ObjectReferenceImpl objectReferenceImpl = (ObjectReferenceImpl) objectReference;
try {
objectReferenceMapper.insert(objectReferenceImpl);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(
"TaskService.updateTask() for TaskId={} INSERTED an ObjectReference={}.",
newTaskImpl.getId(),
objectReferenceImpl);
}
} catch (PersistenceException e) {
throw new ObjectReferencePersistenceException(
objectReferenceImpl.getId(), newTaskImpl.getId(), e);
}
}
private void initObjectReference(ObjectReferenceImpl objectReference, Task newTask) {
if (objectReference.getTaskId() == null) {
objectReference.setTaskId(newTask.getId());
}
if (objectReference.getId() == null) {
objectReference.setId(IdGenerator.generateWithPrefix(IdGenerator.ID_PREFIX_OBJECT_REFERENCE));
}
}
}

View File

@ -1,5 +1,6 @@
package pro.taskana.task.internal;
import java.util.Collection;
import java.util.List;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
@ -9,7 +10,7 @@ import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.annotations.Update;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
/** This class is the mybatis mapping of ObjectReference. */
@SuppressWarnings({"checkstyle:LineLength", "checkstyle:Indentation"})
@ -27,7 +28,47 @@ public interface ObjectReferenceMapper {
@Result(property = "systemInstance", column = "SYSTEM_INSTANCE")
@Result(property = "type", column = "TYPE")
@Result(property = "value", column = "VALUE")
ObjectReference findById(@Param("id") String id);
ObjectReferenceImpl findById(@Param("id") String id);
@Select(
"<script>SELECT ID, TASK_ID, COMPANY, SYSTEM, SYSTEM_INSTANCE, TYPE, VALUE "
+ "FROM OBJECT_REFERENCE "
+ "WHERE TASK_ID = #{taskId}"
+ "<if test=\"_databaseId == 'db2'\">with UR </if> "
+ "</script>")
@Result(property = "id", column = "ID")
@Result(property = "taskId", column = "TASK_ID")
@Result(property = "company", column = "COMPANY")
@Result(property = "system", column = "SYSTEM")
@Result(property = "systemInstance", column = "SYSTEM_INSTANCE")
@Result(property = "type", column = "TYPE")
@Result(property = "value", column = "VALUE")
List<ObjectReferenceImpl> findObjectReferencesByTaskId(@Param("taskId") String taskId);
@Select(
"<script>SELECT ID, TASK_ID, COMPANY, SYSTEM, SYSTEM_INSTANCE, TYPE, VALUE "
+ "FROM OBJECT_REFERENCE "
+ "<where>"
+ "<choose>"
+ "<when test='taskIds == null'>"
+ " 1 = 2 "
+ "</when>"
+ "<otherwise>"
+ "TASK_ID IN (<foreach collection='taskIds' item='item' separator=',' >#{item}</foreach>) "
+ "</otherwise>"
+ "</choose>"
+ "</where>"
+ "<if test=\"_databaseId == 'db2'\">with UR </if> "
+ "</script>")
@Result(property = "id", column = "ID")
@Result(property = "taskId", column = "TASK_ID")
@Result(property = "company", column = "COMPANY")
@Result(property = "system", column = "SYSTEM")
@Result(property = "systemInstance", column = "SYSTEM_INSTANCE")
@Result(property = "type", column = "TYPE")
@Result(property = "value", column = "VALUE")
List<ObjectReferenceImpl> findObjectReferencesByTaskIds(
@Param("taskIds") Collection<String> taskIds);
@Select(
"<script>SELECT ID, COMPANY, SYSTEM, SYSTEM_INSTANCE, TYPE, VALUE "
@ -45,7 +86,8 @@ public interface ObjectReferenceMapper {
@Result(property = "systemInstance", column = "SYSTEM_INSTANCE")
@Result(property = "type", column = "TYPE")
@Result(property = "value", column = "VALUE")
ObjectReference findByObjectReference(@Param("objectReference") ObjectReference objectReference);
ObjectReferenceImpl findByObjectReference(
@Param("objectReference") ObjectReferenceImpl objectReference);
@SelectProvider(type = ObjectReferenceQuerySqlProvider.class, method = "queryObjectReferences")
@Result(property = "id", column = "ID")
@ -54,7 +96,7 @@ public interface ObjectReferenceMapper {
@Result(property = "systemInstance", column = "SYSTEM_INSTANCE")
@Result(property = "type", column = "TYPE")
@Result(property = "value", column = "VALUE")
List<ObjectReference> queryObjectReferences(ObjectReferenceQueryImpl objectReference);
List<ObjectReferenceImpl> queryObjectReferences(ObjectReferenceQueryImpl objectReference);
@SelectProvider(
type = ObjectReferenceQuerySqlProvider.class,
@ -67,17 +109,21 @@ public interface ObjectReferenceMapper {
List<String> queryObjectReferenceColumnValues(ObjectReferenceQueryImpl objectReference);
@Insert(
"INSERT INTO OBJECT_REFERENCE (ID, COMPANY, SYSTEM, SYSTEM_INSTANCE, TYPE, VALUE) "
+ "VALUES (#{ref.id}, #{ref.company}, #{ref.system}, #{ref.systemInstance}, #{ref.type}, #{ref.value})")
void insert(@Param("ref") ObjectReference ref);
"INSERT INTO OBJECT_REFERENCE (ID, TASK_ID, COMPANY, SYSTEM, SYSTEM_INSTANCE, TYPE, VALUE) "
+ "VALUES (#{ref.id}, #{ref.taskId}, #{ref.company}, #{ref.system}, #{ref.systemInstance}, #{ref.type}, #{ref.value})")
void insert(@Param("ref") ObjectReferenceImpl ref);
@Update(
value =
"UPDATE OBJECT_REFERENCE "
+ "SET COMPANY = #{ref.company}, SYSTEM = #{ref.system}, SYSTEM_INSTANCE = #{ref.systemInstance}, TYPE = #{ref.type}, VALUE = #{ref.value} "
+ "WHERE ID = #{ref.id}")
void update(@Param("ref") ObjectReference ref);
void update(@Param("ref") ObjectReferenceImpl ref);
@Delete("DELETE FROM OBJECT_REFERENCE WHERE ID = #{id}")
void delete(String id);
@Delete(
"<script>DELETE FROM OBJECT_REFERENCE WHERE TASK_ID IN(<foreach item='item' collection='taskIds' separator=',' >#{item}</foreach>)</script>")
void deleteMultipleByTaskIds(@Param("taskIds") List<String> taskIds);
}

View File

@ -56,11 +56,11 @@ public interface TaskMapper {
@Result(property = "businessProcessId", column = "BUSINESS_PROCESS_ID")
@Result(property = "parentBusinessProcessId", column = "PARENT_BUSINESS_PROCESS_ID")
@Result(property = "owner", column = "OWNER")
@Result(property = "primaryObjRef.company", column = "POR_COMPANY")
@Result(property = "primaryObjRef.system", column = "POR_SYSTEM")
@Result(property = "primaryObjRef.systemInstance", column = "POR_INSTANCE")
@Result(property = "primaryObjRef.type", column = "POR_TYPE")
@Result(property = "primaryObjRef.value", column = "POR_VALUE")
@Result(property = "primaryObjRefImpl.company", column = "POR_COMPANY")
@Result(property = "primaryObjRefImpl.system", column = "POR_SYSTEM")
@Result(property = "primaryObjRefImpl.systemInstance", column = "POR_INSTANCE")
@Result(property = "primaryObjRefImpl.type", column = "POR_TYPE")
@Result(property = "primaryObjRefImpl.value", column = "POR_VALUE")
@Result(property = "isRead", column = "IS_READ")
@Result(property = "isTransferred", column = "IS_TRANSFERRED")
@Result(

View File

@ -56,6 +56,7 @@ public class TaskQueryImpl implements TaskQuery {
private boolean selectAndClaim;
private boolean useDistinctKeyword = false;
private boolean joinWithAttachments = false;
private boolean joinWithSecondaryObjectReferences = false;
private boolean joinWithClassifications = false;
private boolean joinWithAttachmentClassifications = false;
private boolean joinWithWorkbaskets = false;
@ -255,6 +256,29 @@ public class TaskQueryImpl implements TaskQuery {
private TimeInterval[] attachmentReceivedWithin;
private TimeInterval[] attachmentReceivedNotWithin;
// endregion
// region secondaryObjectReferences
private ObjectReference[] secondaryObjectReferences;
// endregion
// region secondaryObjectReferenceCompany
private String[] sorCompanyIn;
private String[] sorCompanyLike;
// endregion
// region secondaryObjectReferenceValue
private String[] sorValueIn;
private String[] sorValueLike;
// endregion
// region secondaryObjectReferenceSystem
private String[] sorSystemIn;
private String[] sorSystemLike;
// endregion
// region secondaryObjectReferenceSystemInstance
private String[] sorSystemInstanceIn;
private String[] sorSystemInstanceLike;
// endregion
// region secondaryObjectReferenceType
private String[] sorTypeIn;
private String[] sorTypeLike;
// endregion
// region customAttributes
private String[] custom1In;
private boolean custom1InContainsNull;
@ -1386,6 +1410,88 @@ public class TaskQueryImpl implements TaskQuery {
public String[] getOwnerLongNameNotLike() {
return ownerLongNameNotLike;
}
// region secondaryObjectReference
@Override
public TaskQuery secondaryObjectReferenceIn(ObjectReference... objectReferences) {
this.joinWithSecondaryObjectReferences = true;
this.secondaryObjectReferences = objectReferences;
return this;
}
// endregion
// region secondaryObjectReferenceCompany
public TaskQuery sorCompanyIn(String... companyIn) {
joinWithSecondaryObjectReferences = true;
sorCompanyIn = companyIn;
return this;
}
public TaskQuery sorCompanyLike(String... companyLike) {
joinWithSecondaryObjectReferences = true;
sorCompanyLike = toUpperCopy(companyLike);
return this;
}
// endregion
// region secondaryObjectReferenceSystem
public TaskQuery sorSystemIn(String... systemIn) {
joinWithSecondaryObjectReferences = true;
sorSystemIn = systemIn;
return this;
}
public TaskQuery sorSystemLike(String... systemLike) {
joinWithSecondaryObjectReferences = true;
sorSystemLike = toUpperCopy(systemLike);
return this;
}
// endregion
// region secondaryObjectReferenceSystemInstance
public TaskQuery sorSystemInstanceIn(String... systemInstanceIn) {
joinWithSecondaryObjectReferences = true;
sorSystemInstanceIn = systemInstanceIn;
return this;
}
public TaskQuery sorSystemInstanceLike(String... systemInstanceLike) {
joinWithSecondaryObjectReferences = true;
sorSystemInstanceLike = toUpperCopy(systemInstanceLike);
return this;
}
// endregion
// region secondaryObjectReferenceType
public TaskQuery sorTypeIn(String... typeIn) {
joinWithSecondaryObjectReferences = true;
sorTypeIn = typeIn;
return this;
}
public TaskQuery sorTypeLike(String... typeLike) {
joinWithSecondaryObjectReferences = true;
sorTypeLike = toUpperCopy(typeLike);
return this;
}
// endregion
// region secondaryObjectReferenceValue
@Override
public TaskQuery sorValueIn(String... valueIn) {
joinWithSecondaryObjectReferences = true;
sorValueIn = valueIn;
return this;
}
public TaskQuery sorValueLike(String... valueLike) {
joinWithSecondaryObjectReferences = true;
sorValueLike = toUpperCopy(valueLike);
return this;
}
// endregion
// region customAttributes
@Override
@ -1779,6 +1885,7 @@ public class TaskQueryImpl implements TaskQuery {
this.wildcardSearchValueLike = wildcardSearchValue.toUpperCase();
return this;
}
// endregion
@Override
public TaskQuery wildcardSearchFieldsIn(WildcardSearchField... wildcardSearchFields) {
@ -1886,6 +1993,10 @@ public class TaskQueryImpl implements TaskQuery {
joinWithAttachments = true;
}
if (columnName.isObjectReferenceColumn()) {
joinWithSecondaryObjectReferences = true;
}
if (columnName == TaskQueryColumnName.OWNER_LONG_NAME) {
joinWithUserInfo = true;
}
@ -1998,7 +2109,7 @@ public class TaskQueryImpl implements TaskQuery {
joinWithAttachments = true;
joinWithAttachmentClassifications = true;
}
if (joinWithAttachments || joinWithClassifications) {
if (joinWithAttachments || joinWithClassifications || joinWithSecondaryObjectReferences) {
useDistinctKeyword = true;
}
}
@ -2110,6 +2221,8 @@ public class TaskQueryImpl implements TaskQuery {
+ joinWithAttachmentClassifications
+ ", joinWithWorkbaskets="
+ joinWithWorkbaskets
+ ", joinWithSecondaryObjectReferences="
+ joinWithSecondaryObjectReferences
+ ", addAttachmentColumnsToSelectClauseForOrdering="
+ addAttachmentColumnsToSelectClauseForOrdering
+ ", addClassificationNameToSelectClauseForOrdering="
@ -2340,6 +2453,28 @@ public class TaskQueryImpl implements TaskQuery {
+ Arrays.toString(attachmentReceivedWithin)
+ ", attachmentReceivedNotWithin="
+ Arrays.toString(attachmentReceivedNotWithin)
+ ", secondaryObjectReferences="
+ Arrays.toString(secondaryObjectReferences)
+ ", sorCompanyIn="
+ Arrays.toString(sorCompanyIn)
+ ", sorCompanyLike="
+ Arrays.toString(sorCompanyLike)
+ ", sorSystemIn="
+ Arrays.toString(sorSystemIn)
+ ", sorSystemNotIn="
+ Arrays.toString(sorSystemLike)
+ ", sorSystemNotLike="
+ Arrays.toString(sorSystemInstanceIn)
+ ", sorSystemInstanceLike="
+ Arrays.toString(sorSystemInstanceLike)
+ ", sorTypeIn="
+ Arrays.toString(sorTypeIn)
+ ", sorTypeLike="
+ Arrays.toString(sorTypeLike)
+ ", sorValueIn="
+ Arrays.toString(sorValueIn)
+ ", sorValueLike="
+ Arrays.toString(sorValueLike)
+ ", custom1In="
+ Arrays.toString(custom1In)
+ ", custom1NotIn="

View File

@ -36,11 +36,11 @@ public interface TaskQueryMapper {
@Result(property = "parentBusinessProcessId", column = "PARENT_BUSINESS_PROCESS_ID")
@Result(property = "owner", column = "OWNER")
@Result(property = "ownerLongName", column = "LONG_NAME")
@Result(property = "primaryObjRef.company", column = "POR_COMPANY")
@Result(property = "primaryObjRef.system", column = "POR_SYSTEM")
@Result(property = "primaryObjRef.systemInstance", column = "POR_INSTANCE")
@Result(property = "primaryObjRef.type", column = "POR_TYPE")
@Result(property = "primaryObjRef.value", column = "POR_VALUE")
@Result(property = "primaryObjRefImpl.company", column = "POR_COMPANY")
@Result(property = "primaryObjRefImpl.system", column = "POR_SYSTEM")
@Result(property = "primaryObjRefImpl.systemInstance", column = "POR_INSTANCE")
@Result(property = "primaryObjRefImpl.type", column = "POR_TYPE")
@Result(property = "primaryObjRefImpl.value", column = "POR_VALUE")
@Result(property = "isRead", column = "IS_READ")
@Result(property = "isTransferred", column = "IS_TRANSFERRED")
@Result(property = "custom1", column = "CUSTOM_1")
@ -88,11 +88,11 @@ public interface TaskQueryMapper {
@Result(property = "parentBusinessProcessId", column = "PARENT_BUSINESS_PROCESS_ID")
@Result(property = "owner", column = "OWNER")
@Result(property = "ownerLongName", column = "ULONG_NAME")
@Result(property = "primaryObjRef.company", column = "POR_COMPANY")
@Result(property = "primaryObjRef.system", column = "POR_SYSTEM")
@Result(property = "primaryObjRef.systemInstance", column = "POR_INSTANCE")
@Result(property = "primaryObjRef.type", column = "POR_TYPE")
@Result(property = "primaryObjRef.value", column = "POR_VALUE")
@Result(property = "primaryObjRefImpl.company", column = "POR_COMPANY")
@Result(property = "primaryObjRefImpl.system", column = "POR_SYSTEM")
@Result(property = "primaryObjRefImpl.systemInstance", column = "POR_INSTANCE")
@Result(property = "primaryObjRefImpl.type", column = "POR_TYPE")
@Result(property = "primaryObjRefImpl.value", column = "POR_VALUE")
@Result(property = "isRead", column = "IS_READ")
@Result(property = "isTransferred", column = "IS_TRANSFERRED")
@Result(property = "custom1", column = "CUSTOM_1")

View File

@ -37,6 +37,9 @@ public class TaskQuerySqlProvider {
+ "<if test=\"joinWithAttachments\">"
+ "LEFT JOIN ATTACHMENT AS a ON t.ID = a.TASK_ID "
+ "</if>"
+ "<if test=\"joinWithSecondaryObjectReferences\">"
+ "LEFT JOIN OBJECT_REFERENCE AS o ON t.ID = o.TASK_ID "
+ "</if>"
+ "<if test=\"joinWithClassifications\">"
+ "LEFT JOIN CLASSIFICATION AS c ON t.CLASSIFICATION_ID = c.ID "
+ "</if>"
@ -83,6 +86,9 @@ public class TaskQuerySqlProvider {
+ "<if test=\"joinWithAttachments\">"
+ "LEFT JOIN ATTACHMENT a ON t.ID = a.TASK_ID "
+ "</if>"
+ "<if test=\"joinWithSecondaryObjectReferences\">"
+ "LEFT JOIN OBJECT_REFERENCE o ON t.ID = o.TASK_ID "
+ "</if>"
+ "<if test=\"joinWithClassifications\">"
+ "LEFT JOIN CLASSIFICATION AS c ON t.CLASSIFICATION_ID = c.ID "
+ "</if>"
@ -135,6 +141,9 @@ public class TaskQuerySqlProvider {
+ "<if test=\"joinWithAttachments\">"
+ "LEFT JOIN ATTACHMENT AS a ON t.ID = a.TASK_ID "
+ "</if>"
+ "<if test=\"joinWithSecondaryObjectReferences\">"
+ "LEFT JOIN OBJECT_REFERENCE AS o ON t.ID = o.TASK_ID "
+ "</if>"
+ "<if test=\"joinWithClassifications\">"
+ "LEFT JOIN CLASSIFICATION AS c ON t.CLASSIFICATION_ID = c.ID "
+ "</if>"
@ -166,6 +175,9 @@ public class TaskQuerySqlProvider {
+ "<if test=\"joinWithAttachmentClassifications\">"
+ "LEFT JOIN CLASSIFICATION AS ac ON a.CLASSIFICATION_ID = ac.ID "
+ "</if>"
+ "<if test=\"joinWithSecondaryObjectReferences\">"
+ "LEFT JOIN OBJECT_REFERENCE AS o ON t.ID = o.TASK_ID "
+ "</if>"
+ "<if test=\"joinWithUserInfo\">"
+ "LEFT JOIN USER_INFO AS u ON t.owner = u.USER_ID "
+ "</if>"
@ -199,6 +211,9 @@ public class TaskQuerySqlProvider {
+ "<if test=\"joinWithAttachmentClassifications\">"
+ "LEFT JOIN CLASSIFICATION AS ac ON a.CLASSIFICATION_ID = ac.ID "
+ "</if>"
+ "<if test=\"joinWithSecondaryObjectReferences\">"
+ "LEFT JOIN OBJECT_REFERENCE AS o ON t.ID = o.TASK_ID "
+ "</if>"
+ "<if test=\"joinWithUserInfo\">"
+ "LEFT JOIN USER_INFO AS u ON t.owner = u.USER_ID "
+ "</if>"
@ -310,6 +325,30 @@ public class TaskQuerySqlProvider {
+ "</if>";
}
private static String commonTaskSecondaryObjectReferencesWhereStatement() {
return "<if test='secondaryObjectReferences != null'>"
+ "AND (<foreach item='item' collection='secondaryObjectReferences' separator=' OR '> "
+ "<if test='item.company != null'>o.COMPANY = #{item.company} </if>"
+ "<if test='item.system != null'> "
+ "<if test='item.company != null'>AND</if> "
+ "o.SYSTEM = #{item.system} </if>"
+ "<if test='item.systemInstance != null'> "
+ "<if test='item.company != null or item.system != null'>AND</if> "
+ "o.SYSTEM_INSTANCE = #{item.systemInstance} </if>"
+ "<if test='item.type != null'> "
+ "<if test='item.company != null or item.system != null or item.systemInstance != null'>"
+ "AND</if> "
+ "o.TYPE = #{item.type} </if>"
+ "<if test='item.value != null'> "
+ "<if test='item.company != null or item.system != null "
+ "or item.systemInstance != null or item.type != null'>"
+ "AND</if> "
+ "o.VALUE = #{item.value} "
+ "</if>"
+ "</foreach>)"
+ "</if>";
}
private static void commonWhereClauses(String filter, String channel, StringBuilder sb) {
whereIn(filter + "In", channel, sb);
whereNotIn(filter + "NotIn", channel, sb);
@ -337,6 +376,17 @@ public class TaskQuerySqlProvider {
commonWhereClauses("porType", "t.POR_TYPE", sb);
commonWhereClauses("porValue", "t.POR_VALUE", sb);
whereIn("sorCompanyIn", "o.COMPANY", sb);
whereLike("sorCompanyLike", "o.COMPANY", sb);
whereIn("sorSystemIn", "o.SYSTEM", sb);
whereLike("sorSystemLike", "o.SYSTEM", sb);
whereIn("sorSystemInstanceIn", "o.SYSTEM_INSTANCE", sb);
whereLike("sorSystemInstanceLike", "o.SYSTEM_INSTANCE", sb);
whereIn("sorTypeIn", "o.TYPE", sb);
whereLike("sorTypeLike", "o.TYPE", sb);
whereIn("sorValueIn", "o.VALUE", sb);
whereLike("sorValueLike", "o.VALUE", sb);
whereIn("attachmentClassificationIdIn", "a.CLASSIFICATION_ID", sb);
whereNotIn("attachmentClassificationIdNotIn", "a.CLASSIFICATION_ID", sb);
whereIn("callbackStateIn", "t.CALLBACK_STATE", sb);
@ -399,6 +449,7 @@ public class TaskQuerySqlProvider {
+ "</foreach>)"
+ "</if> ");
sb.append(commonTaskObjectReferenceWhereStatement());
sb.append(commonTaskSecondaryObjectReferencesWhereStatement());
return sb;
}
}

View File

@ -61,6 +61,7 @@ import pro.taskana.task.api.exceptions.InvalidCallbackStateException;
import pro.taskana.task.api.exceptions.InvalidOwnerException;
import pro.taskana.task.api.exceptions.InvalidStateException;
import pro.taskana.task.api.exceptions.InvalidTaskStateException;
import pro.taskana.task.api.exceptions.ObjectReferencePersistenceException;
import pro.taskana.task.api.exceptions.TaskAlreadyExistException;
import pro.taskana.task.api.exceptions.TaskCommentNotFoundException;
import pro.taskana.task.api.exceptions.TaskNotFoundException;
@ -74,6 +75,7 @@ import pro.taskana.task.internal.ServiceLevelHandler.BulkLog;
import pro.taskana.task.internal.models.AttachmentImpl;
import pro.taskana.task.internal.models.AttachmentSummaryImpl;
import pro.taskana.task.internal.models.MinimalTaskSummary;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
import pro.taskana.task.internal.models.TaskImpl;
import pro.taskana.task.internal.models.TaskSummaryImpl;
import pro.taskana.user.api.models.User;
@ -102,6 +104,8 @@ public class TaskServiceImpl implements TaskService {
private final ServiceLevelHandler serviceLevelHandler;
private final AttachmentHandler attachmentHandler;
private final AttachmentMapper attachmentMapper;
private final ObjectReferenceMapper objectReferenceMapper;
private final ObjectReferenceHandler objectReferenceHandler;
private final UserMapper userMapper;
private final HistoryEventManager historyEventManager;
private final CreateTaskPreprocessorManager createTaskPreprocessorManager;
@ -112,11 +116,13 @@ public class TaskServiceImpl implements TaskService {
TaskMapper taskMapper,
TaskCommentMapper taskCommentMapper,
AttachmentMapper attachmentMapper,
ObjectReferenceMapper objectReferenceMapper,
UserMapper userMapper) {
this.taskanaEngine = taskanaEngine;
this.taskMapper = taskMapper;
this.workbasketService = taskanaEngine.getEngine().getWorkbasketService();
this.attachmentMapper = attachmentMapper;
this.objectReferenceMapper = objectReferenceMapper;
this.userMapper = userMapper;
this.classificationService = taskanaEngine.getEngine().getClassificationService();
this.historyEventManager = taskanaEngine.getHistoryEventManager();
@ -128,6 +134,7 @@ public class TaskServiceImpl implements TaskService {
this.serviceLevelHandler =
new ServiceLevelHandler(taskanaEngine, taskMapper, attachmentMapper, this);
this.attachmentHandler = new AttachmentHandler(attachmentMapper, classificationService);
this.objectReferenceHandler = new ObjectReferenceHandler(objectReferenceMapper);
}
@Override
@ -175,7 +182,8 @@ public class TaskServiceImpl implements TaskService {
@Override
public Task createTask(Task taskToCreate)
throws NotAuthorizedException, WorkbasketNotFoundException, ClassificationNotFoundException,
TaskAlreadyExistException, InvalidArgumentException, AttachmentPersistenceException {
TaskAlreadyExistException, InvalidArgumentException, AttachmentPersistenceException,
ObjectReferencePersistenceException {
if (createTaskPreprocessorManager.isEnabled()) {
taskToCreate = createTaskPreprocessorManager.processTaskBeforeCreation(taskToCreate);
@ -230,7 +238,7 @@ public class TaskServiceImpl implements TaskService {
Classification classification =
this.classificationService.getClassification(classificationKey, workbasket.getDomain());
task.setClassificationSummary(classification.asSummary());
ObjectReference.validate(task.getPrimaryObjRef(), "primary ObjectReference", "Task");
ObjectReferenceImpl.validate(task.getPrimaryObjRef(), "primary ObjectReference", "Task");
standardSettingsOnTaskCreation(task, classification);
setCallbackStateOnTaskCreation(task);
priorityServiceManager.calculatePriorityOfTask(task).ifPresent(task::setPriority);
@ -313,12 +321,16 @@ public class TaskServiceImpl implements TaskService {
if (attachmentImpls == null) {
attachmentImpls = new ArrayList<>();
}
List<ObjectReferenceImpl> secondaryObjectReferences =
objectReferenceMapper.findObjectReferencesByTaskId(resultTask.getId());
if (secondaryObjectReferences == null) {
secondaryObjectReferences = new ArrayList<>();
}
Map<String, ClassificationSummary> classificationSummariesById =
findClassificationForTaskImplAndAttachments(resultTask, attachmentImpls);
addClassificationSummariesToAttachments(attachmentImpls, classificationSummariesById);
resultTask.setAttachments(new ArrayList<>(attachmentImpls));
resultTask.setSecondaryObjectReferences(new ArrayList<>(secondaryObjectReferences));
String classificationId = resultTask.getClassificationSummary().getId();
ClassificationSummary classification = classificationSummariesById.get(classificationId);
if (classification == null) {
@ -423,10 +435,22 @@ public class TaskServiceImpl implements TaskService {
return new AttachmentImpl();
}
@Override
public ObjectReference newObjectReference() {
return new ObjectReferenceImpl();
}
@Override
public ObjectReference newObjectReference(
String company, String system, String systemInstance, String type, String value) {
return new ObjectReferenceImpl(company, system, systemInstance, type, value);
}
@Override
public Task updateTask(Task task)
throws InvalidArgumentException, TaskNotFoundException, ConcurrencyException,
NotAuthorizedException, AttachmentPersistenceException, InvalidStateException,
NotAuthorizedException, AttachmentPersistenceException,
ObjectReferencePersistenceException, InvalidStateException,
ClassificationNotFoundException {
String userId = taskanaEngine.getEngine().getCurrentUserContext().getUserid();
TaskImpl newTaskImpl = (TaskImpl) task;
@ -437,7 +461,9 @@ public class TaskServiceImpl implements TaskService {
checkConcurrencyAndSetModified(newTaskImpl, oldTaskImpl);
attachmentHandler.insertAndDeleteAttachmentsOnTaskUpdate(newTaskImpl, oldTaskImpl);
ObjectReference.validate(newTaskImpl.getPrimaryObjRef(), "primary ObjectReference", "Task");
objectReferenceHandler.insertAndDeleteObjectReferencesOnTaskUpdate(newTaskImpl, oldTaskImpl);
ObjectReferenceImpl.validate(
newTaskImpl.getPrimaryObjRef(), "primary ObjectReference", "Task");
standardUpdateActions(oldTaskImpl, newTaskImpl);
@ -555,6 +581,7 @@ public class TaskServiceImpl implements TaskService {
if (!taskIds.isEmpty()) {
attachmentMapper.deleteMultipleByTaskIds(taskIds);
objectReferenceMapper.deleteMultipleByTaskIds(taskIds);
taskMapper.deleteMultiple(taskIds);
if (taskanaEngine.getEngine().isHistoryEnabled()
@ -588,7 +615,7 @@ public class TaskServiceImpl implements TaskService {
ObjectReference selectionCriteria, Map<TaskCustomField, String> customFieldsToUpdate)
throws InvalidArgumentException {
ObjectReference.validate(selectionCriteria, "ObjectReference", "updateTasks call");
ObjectReferenceImpl.validate(selectionCriteria, "ObjectReference", "updateTasks call");
validateCustomFields(customFieldsToUpdate);
TaskCustomPropertySelector fieldSelector = new TaskCustomPropertySelector();
TaskImpl updated = initUpdatedTask(customFieldsToUpdate, fieldSelector);
@ -952,7 +979,7 @@ public class TaskServiceImpl implements TaskService {
// splitting Augmentation into steps of maximal 32000 tasks
// reason: DB2 has a maximum for parameters in a query
return CollectionUtil.partitionBasedOnSize(taskSummaries, 32000).stream()
.map(this::augmentTaskSummariesByContainedSummariesWithoutPartitioning)
.map(this::appendComplexAttributesToTaskSummariesWithoutPartitioning)
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
@ -975,7 +1002,7 @@ public class TaskServiceImpl implements TaskService {
return Pair.of(filteredTasks, bulkLog);
}
private List<TaskSummaryImpl> augmentTaskSummariesByContainedSummariesWithoutPartitioning(
private List<TaskSummaryImpl> appendComplexAttributesToTaskSummariesWithoutPartitioning(
List<TaskSummaryImpl> taskSummaries) {
Set<String> taskIds =
taskSummaries.stream().map(TaskSummaryImpl::getId).collect(Collectors.toSet());
@ -995,12 +1022,15 @@ public class TaskServiceImpl implements TaskService {
attachmentMapper.findAttachmentSummariesByTaskIds(taskIds);
Map<String, ClassificationSummary> classificationSummariesById =
findClassificationsForTasksAndAttachments(taskSummaries, attachmentSummaries);
Map<String, WorkbasketSummary> workbasketSummariesById = findWorkbasketsForTasks(taskSummaries);
addClassificationSummariesToAttachments(attachmentSummaries, classificationSummariesById);
addClassificationSummariesToTaskSummaries(taskSummaries, classificationSummariesById);
addWorkbasketSummariesToTaskSummaries(taskSummaries, workbasketSummariesById);
addAttachmentSummariesToTaskSummaries(taskSummaries, attachmentSummaries);
Map<String, WorkbasketSummary> workbasketSummariesById = findWorkbasketsForTasks(taskSummaries);
List<ObjectReferenceImpl> objectReferences =
objectReferenceMapper.findObjectReferencesByTaskIds(taskIds);
addWorkbasketSummariesToTaskSummaries(taskSummaries, workbasketSummariesById);
addObjectReferencesToTaskSummaries(taskSummaries, objectReferences);
return taskSummaries;
}
@ -1306,6 +1336,7 @@ public class TaskServiceImpl implements TaskService {
}
attachmentMapper.deleteMultipleByTaskIds(Collections.singletonList(taskId));
objectReferenceMapper.deleteMultipleByTaskIds(Collections.singletonList(taskId));
taskMapper.delete(taskId);
if (taskanaEngine.getEngine().isHistoryEnabled()
@ -1443,7 +1474,7 @@ public class TaskServiceImpl implements TaskService {
private void standardSettingsOnTaskCreation(TaskImpl task, Classification classification)
throws InvalidArgumentException, ClassificationNotFoundException,
AttachmentPersistenceException {
AttachmentPersistenceException, ObjectReferencePersistenceException {
final Instant now = Instant.now();
task.setId(IdGenerator.generateWithPrefix(IdGenerator.ID_PREFIX_TASK));
if (task.getExternalId() == null) {
@ -1480,6 +1511,7 @@ public class TaskServiceImpl implements TaskService {
setDefaultTaskReceivedDateFromAttachments(task);
attachmentHandler.insertNewAttachmentsOnTaskCreation(task);
objectReferenceHandler.insertNewSecondaryObjectReferencesOnTaskCreation(task);
// This has to be called after the AttachmentHandler because the AttachmentHandler fetches
// the Classifications of the Attachments.
// This is necessary to guarantee that the following calculation is correct.
@ -1706,6 +1738,32 @@ public class TaskServiceImpl implements TaskService {
}
}
private void addObjectReferencesToTaskSummaries(
List<TaskSummaryImpl> taskSummaries, List<ObjectReferenceImpl> objectReferences) {
if (taskSummaries == null || taskSummaries.isEmpty()) {
return;
}
Map<String, TaskSummaryImpl> taskSummariesById =
taskSummaries.stream()
.collect(
Collectors.toMap(
TaskSummary::getId,
Function.identity(),
// The TaskQuery#list function
// returns the same task multiple times when that task has more than one
// object reference...Therefore, this MergeFunction is necessary.
(a, b) -> b));
for (ObjectReferenceImpl objectReference : objectReferences) {
String taskId = objectReference.getTaskId();
TaskSummaryImpl taskSummary = taskSummariesById.get(taskId);
if (taskSummary != null) {
taskSummary.addSecondaryObjectReference(objectReference);
}
}
}
private TaskImpl initUpdatedTask(
Map<TaskCustomField, String> customFieldsToUpdate, TaskCustomPropertySelector fieldSelector) {

View File

@ -1,10 +1,11 @@
package pro.taskana.task.internal.builder;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
public class ObjectReferenceBuilder {
private final ObjectReference objectReference = new ObjectReference();
private final ObjectReferenceImpl objectReference = new ObjectReferenceImpl();
private ObjectReferenceBuilder() {}

View File

@ -17,6 +17,7 @@ import pro.taskana.task.api.TaskCustomField;
import pro.taskana.task.api.TaskService;
import pro.taskana.task.api.TaskState;
import pro.taskana.task.api.exceptions.AttachmentPersistenceException;
import pro.taskana.task.api.exceptions.ObjectReferencePersistenceException;
import pro.taskana.task.api.exceptions.TaskAlreadyExistException;
import pro.taskana.task.api.exceptions.TaskNotFoundException;
import pro.taskana.task.api.models.Attachment;
@ -168,6 +169,11 @@ public class TaskBuilder {
return this;
}
public TaskBuilder objectReferences(ObjectReference... objectReferences) {
testTask.setSecondaryObjectReferences(Arrays.asList(objectReferences));
return this;
}
public TaskBuilder customAttribute(TaskCustomField customField, String value) {
testTask.setCustomAttribute(customField, value);
return this;
@ -196,7 +202,7 @@ public class TaskBuilder {
public Task buildAndStore(TaskService taskService)
throws TaskAlreadyExistException, InvalidArgumentException, WorkbasketNotFoundException,
ClassificationNotFoundException, NotAuthorizedException, AttachmentPersistenceException,
TaskNotFoundException {
ObjectReferencePersistenceException, TaskNotFoundException {
try {
Task task = taskService.createTask(testTask);
return taskService.getTask(task.getId());
@ -218,7 +224,7 @@ public class TaskBuilder {
public TaskSummary buildAndStoreAsSummary(TaskService taskService)
throws TaskAlreadyExistException, InvalidArgumentException, TaskNotFoundException,
WorkbasketNotFoundException, ClassificationNotFoundException, NotAuthorizedException,
AttachmentPersistenceException {
AttachmentPersistenceException, ObjectReferencePersistenceException {
return buildAndStore(taskService).asSummary();
}

View File

@ -121,6 +121,16 @@ public class AttachmentSummaryImpl implements AttachmentSummary {
this.classificationSummary = classificationSummary;
}
// auxiliary method to enable MyBatis access to objectReference
public ObjectReferenceImpl getObjectReferenceImpl() {
return (ObjectReferenceImpl) objectReference;
}
// auxiliary method to enable MyBatis access to objectReference
public void setObjectReferenceImpl(ObjectReferenceImpl objectReferenceImpl) {
this.objectReference = objectReferenceImpl;
}
protected boolean canEqual(Object other) {
return (!(other instanceof AttachmentSummaryImpl));
}

View File

@ -0,0 +1,165 @@
package pro.taskana.task.internal.models;
import java.util.Objects;
import pro.taskana.common.api.exceptions.InvalidArgumentException;
import pro.taskana.task.api.models.ObjectReference;
/** ObjectReference entity. */
public class ObjectReferenceImpl implements ObjectReference {
private String id;
private String taskId;
private String company;
private String system;
private String systemInstance;
private String type;
private String value;
public ObjectReferenceImpl() {}
public ObjectReferenceImpl(
String company, String system, String systemInstance, String type, String value) {
this.company = company;
this.system = system;
this.systemInstance = systemInstance;
this.type = type;
this.value = value;
}
private ObjectReferenceImpl(ObjectReferenceImpl copyFrom) {
company = copyFrom.company;
system = copyFrom.system;
systemInstance = copyFrom.systemInstance;
type = copyFrom.type;
value = copyFrom.value;
}
@Override
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public String getTaskId() {
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
@Override
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
@Override
public String getSystem() {
return system;
}
public void setSystem(String system) {
this.system = system;
}
@Override
public String getSystemInstance() {
return systemInstance;
}
public void setSystemInstance(String systemInstance) {
this.systemInstance = systemInstance;
}
@Override
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public ObjectReferenceImpl copy() {
return new ObjectReferenceImpl(this);
}
public static void validate(ObjectReference objectReference, String objRefType, String objName)
throws InvalidArgumentException {
// check that all values in the ObjectReference are set correctly
if (objectReference == null) {
throw new InvalidArgumentException(
String.format("%s of %s must not be null.", objRefType, objName));
} else if (objectReference.getCompany() == null || objectReference.getCompany().isEmpty()) {
throw new InvalidArgumentException(
String.format("Company of %s of %s must not be empty", objRefType, objName));
} else if (objectReference.getType() == null || objectReference.getType().length() == 0) {
throw new InvalidArgumentException(
String.format("Type of %s of %s must not be empty", objRefType, objName));
} else if (objectReference.getValue() == null || objectReference.getValue().length() == 0) {
throw new InvalidArgumentException(
String.format("Value of %s of %s must not be empty", objRefType, objName));
}
}
@Override
public int hashCode() {
return Objects.hash(id, taskId, company, system, systemInstance, type, value);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof ObjectReferenceImpl)) {
return false;
}
ObjectReferenceImpl other = (ObjectReferenceImpl) obj;
return Objects.equals(id, other.id)
&& Objects.equals(taskId, other.taskId)
&& Objects.equals(company, other.company)
&& Objects.equals(system, other.system)
&& Objects.equals(systemInstance, other.systemInstance)
&& Objects.equals(type, other.type)
&& Objects.equals(value, other.value);
}
@Override
public String toString() {
return "ObjectReference ["
+ "id="
+ this.id
+ ", taskId="
+ this.taskId
+ ", company="
+ this.company
+ ", system="
+ this.system
+ ", systemInstance="
+ this.systemInstance
+ ", type="
+ this.type
+ ", value="
+ this.value
+ "]";
}
}

View File

@ -201,6 +201,7 @@ public class TaskImpl extends TaskSummaryImpl implements Task {
attSummaries.add(att.asSummary());
}
taskSummary.setAttachmentSummaries(attSummaries);
taskSummary.setSecondaryObjectReferences(secondaryObjectReferences);
taskSummary.setBusinessProcessId(this.businessProcessId);
taskSummary.setClaimed(claimed);
if (classificationSummary != null) {
@ -313,6 +314,8 @@ public class TaskImpl extends TaskSummaryImpl implements Task {
+ callbackState
+ ", attachments="
+ attachments
+ ", objectReferences="
+ secondaryObjectReferences
+ ", id="
+ id
+ ", externalId="

View File

@ -5,6 +5,7 @@ import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import pro.taskana.classification.api.models.ClassificationSummary;
import pro.taskana.classification.internal.models.ClassificationSummaryImpl;
@ -46,6 +47,7 @@ public class TaskSummaryImpl implements TaskSummary {
protected boolean isTransferred;
// All objects have to be serializable
protected List<AttachmentSummary> attachmentSummaries = new ArrayList<>();
protected List<ObjectReference> secondaryObjectReferences = new ArrayList<>();
protected String custom1;
protected String custom2;
protected String custom3;
@ -88,6 +90,10 @@ public class TaskSummaryImpl implements TaskSummary {
isRead = copyFrom.isRead;
isTransferred = copyFrom.isTransferred;
attachmentSummaries = new ArrayList<>(copyFrom.attachmentSummaries);
secondaryObjectReferences =
copyFrom.secondaryObjectReferences.stream()
.map(ObjectReference::copy)
.collect(Collectors.toList());
custom1 = copyFrom.custom1;
custom2 = copyFrom.custom2;
custom3 = copyFrom.custom3;
@ -268,6 +274,15 @@ public class TaskSummaryImpl implements TaskSummary {
this.attachmentSummaries = attachmentSummaries;
}
@Override
public List<ObjectReference> getSecondaryObjectReferences() {
return secondaryObjectReferences;
}
public void setSecondaryObjectReferences(List<ObjectReference> objectReferences) {
this.secondaryObjectReferences = objectReferences;
}
@Override
public String getDomain() {
return workbasketSummary == null ? null : workbasketSummary.getDomain();
@ -325,6 +340,11 @@ public class TaskSummaryImpl implements TaskSummary {
this.primaryObjRef = primaryObjRef;
}
public void setPrimaryObjRef(
String company, String system, String systemInstance, String type, String value) {
this.primaryObjRef = new ObjectReferenceImpl(company, system, systemInstance, type, value);
}
@Override
public boolean isRead() {
return isRead;
@ -406,6 +426,50 @@ public class TaskSummaryImpl implements TaskSummary {
this.attachmentSummaries.add(attachmentSummary);
}
@Override
public void addSecondaryObjectReference(ObjectReference objectReferenceToAdd) {
if (secondaryObjectReferences == null) {
secondaryObjectReferences = new ArrayList<>();
}
if (objectReferenceToAdd != null) {
((ObjectReferenceImpl) objectReferenceToAdd).setTaskId(this.id);
if (objectReferenceToAdd.getId() != null) {
secondaryObjectReferences.removeIf(
objectReference -> objectReferenceToAdd.getId().equals(objectReference.getId()));
}
secondaryObjectReferences.add(objectReferenceToAdd);
}
}
@Override
public void addSecondaryObjectReference(
String company, String system, String systemInstance, String type, String value) {
ObjectReferenceImpl objectReferenceToAdd =
new ObjectReferenceImpl(company, system, systemInstance, type, value);
if (secondaryObjectReferences == null) {
secondaryObjectReferences = new ArrayList<>();
}
objectReferenceToAdd.setTaskId(this.id);
if (objectReferenceToAdd.getId() != null) {
secondaryObjectReferences.removeIf(
objectReference -> objectReferenceToAdd.getId().equals(objectReference.getId()));
}
secondaryObjectReferences.add(objectReferenceToAdd);
}
@Override
public ObjectReference removeSecondaryObjectReference(String objectReferenceId) {
ObjectReference result = null;
for (ObjectReference objectReference : secondaryObjectReferences) {
if (objectReference.getId().equals(objectReferenceId)
&& secondaryObjectReferences.remove(objectReference)) {
result = objectReference;
break;
}
}
return result;
}
// auxiliary Method to enable Mybatis to access classificationSummary
public ClassificationSummaryImpl getClassificationSummaryImpl() {
return (ClassificationSummaryImpl) classificationSummary;
@ -416,6 +480,16 @@ public class TaskSummaryImpl implements TaskSummary {
setClassificationSummary(classificationSummary);
}
// auxiliary Method to enable Mybatis to access primaryObjRef
public ObjectReferenceImpl getPrimaryObjRefImpl() {
return (ObjectReferenceImpl) primaryObjRef;
}
// auxiliary Method to enable Mybatis to access primaryObjRef
public void setPrimaryObjRefImpl(ObjectReferenceImpl objectReference) {
setPrimaryObjRef(objectReference);
}
public String getCustom1() {
return custom1;
}
@ -592,6 +666,7 @@ public class TaskSummaryImpl implements TaskSummary {
isRead,
isTransferred,
attachmentSummaries,
secondaryObjectReferences,
custom1,
custom2,
custom3,
@ -647,6 +722,7 @@ public class TaskSummaryImpl implements TaskSummary {
&& Objects.equals(ownerLongName, other.ownerLongName)
&& Objects.equals(primaryObjRef, other.primaryObjRef)
&& Objects.equals(attachmentSummaries, other.attachmentSummaries)
&& Objects.equals(secondaryObjectReferences, other.secondaryObjectReferences)
&& Objects.equals(custom1, other.custom1)
&& Objects.equals(custom2, other.custom2)
&& Objects.equals(custom3, other.custom3)
@ -717,6 +793,8 @@ public class TaskSummaryImpl implements TaskSummary {
+ isTransferred
+ ", attachmentSummaries="
+ attachmentSummaries
+ ", objectReferences="
+ secondaryObjectReferences
+ ", custom1="
+ custom1
+ ", custom2="

View File

@ -27,6 +27,7 @@ import pro.taskana.sampledata.SampleDataGenerator;
import pro.taskana.task.api.models.Attachment;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.internal.TaskServiceImpl;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
import pro.taskana.user.api.models.User;
/** Base class for all acceptance tests. */
@ -78,9 +79,9 @@ public abstract class AbstractAccTest {
return sqlSessionManager.getMapper(JobMapper.class);
}
protected ObjectReference createObjectReference(
protected ObjectReferenceImpl createObjectReference(
String company, String system, String systemInstance, String type, String value) {
ObjectReference objectReference = new ObjectReference();
ObjectReferenceImpl objectReference = new ObjectReferenceImpl();
objectReference.setCompany(company);
objectReference.setSystem(system);
objectReference.setSystemInstance(systemInstance);

View File

@ -54,11 +54,11 @@ public interface TaskTestMapper {
@Result(property = "businessProcessId", column = "BUSINESS_PROCESS_ID"),
@Result(property = "parentBusinessProcessId", column = "PARENT_BUSINESS_PROCESS_ID"),
@Result(property = "owner", column = "OWNER"),
@Result(property = "primaryObjRef.company", column = "POR_COMPANY"),
@Result(property = "primaryObjRef.system", column = "POR_SYSTEM"),
@Result(property = "primaryObjRef.systemInstance", column = "POR_INSTANCE"),
@Result(property = "primaryObjRef.type", column = "POR_TYPE"),
@Result(property = "primaryObjRef.value", column = "POR_VALUE"),
@Result(property = "primaryObjRefImpl.company", column = "POR_COMPANY"),
@Result(property = "primaryObjRefImpl.system", column = "POR_SYSTEM"),
@Result(property = "primaryObjRefImpl.systemInstance", column = "POR_INSTANCE"),
@Result(property = "primaryObjRefImpl.type", column = "POR_TYPE"),
@Result(property = "primaryObjRefImpl.value", column = "POR_VALUE"),
@Result(property = "isRead", column = "IS_READ"),
@Result(property = "isTransferred", column = "IS_TRANSFERRED"),
@Result(

View File

@ -6,6 +6,7 @@ import static pro.taskana.task.internal.builder.ObjectReferenceBuilder.newObject
import org.junit.jupiter.api.Test;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
class ObjectReferenceBuilderTest {
@ -20,7 +21,7 @@ class ObjectReferenceBuilderTest {
.value("Value1")
.build();
ObjectReference expectedObjectReference = new ObjectReference();
ObjectReferenceImpl expectedObjectReference = new ObjectReferenceImpl();
expectedObjectReference.setCompany("Company1");
expectedObjectReference.setSystem("System1");
expectedObjectReference.setSystemInstance("Instance1");
@ -28,7 +29,7 @@ class ObjectReferenceBuilderTest {
expectedObjectReference.setValue("Value1");
assertThat(objectReference)
.hasNoNullFieldsOrPropertiesExcept("id")
.hasNoNullFieldsOrPropertiesExcept("id", "taskId")
.isEqualTo(expectedObjectReference);
}
}

View File

@ -37,6 +37,7 @@ import pro.taskana.task.api.models.AttachmentSummary;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.api.models.Task;
import pro.taskana.task.internal.AttachmentMapper;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
import pro.taskana.task.internal.models.TaskImpl;
import pro.taskana.workbasket.api.WorkbasketService;
import pro.taskana.workbasket.api.exceptions.WorkbasketNotFoundException;
@ -79,11 +80,14 @@ class CreateTaskAccTest extends AbstractAccTest {
Task newTask = taskService.newTask("USER-1-1", "DOMAIN_A");
newTask.setClassificationKey("T2100");
ObjectReference objectReference =
ObjectReferenceImpl objectReference =
createObjectReference("COMPANY_A", "SYSTEM_A", "INSTANCE_A", "VNR", "1234567");
objectReference.setTaskId(newTask.getId());
newTask.setPrimaryObjRef(objectReference);
newTask.setOwner("user-1-1");
Task createdTask = taskService.createTask(newTask);
Instant expectedPlanned = moveForwardToWorkingDay(createdTask.getCreated());
assertThat(createdTask).isNotNull();

View File

@ -0,0 +1,176 @@
package acceptance.task;
import static acceptance.DefaultTestEntities.defaultTestClassification;
import static acceptance.DefaultTestEntities.defaultTestObjectReference;
import static acceptance.DefaultTestEntities.defaultTestWorkbasket;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import acceptance.TaskanaEngineProxy;
import java.util.stream.Collectors;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import testapi.TaskanaInject;
import testapi.TaskanaIntegrationTest;
import pro.taskana.classification.api.ClassificationService;
import pro.taskana.classification.api.models.ClassificationSummary;
import pro.taskana.common.api.TaskanaEngine;
import pro.taskana.common.api.exceptions.InvalidArgumentException;
import pro.taskana.common.test.security.WithAccessId;
import pro.taskana.task.api.TaskService;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.api.models.Task;
import pro.taskana.task.internal.ObjectReferenceMapper;
import pro.taskana.task.internal.builder.ObjectReferenceBuilder;
import pro.taskana.task.internal.builder.TaskBuilder;
import pro.taskana.task.internal.models.TaskImpl;
import pro.taskana.workbasket.api.WorkbasketPermission;
import pro.taskana.workbasket.api.WorkbasketService;
import pro.taskana.workbasket.api.models.WorkbasketSummary;
import pro.taskana.workbasket.internal.builder.WorkbasketAccessItemBuilder;
/**
* Acceptance test for all "create task" scenarios that involve secondary {@link ObjectReference}.
*/
@TaskanaIntegrationTest
class CreateTaskWithSorAccTest {
@TaskanaInject TaskService taskService;
@TaskanaInject WorkbasketService workbasketService;
@TaskanaInject ClassificationService classificationService;
@TaskanaInject TaskanaEngine taskanaEngine;
ClassificationSummary defaultClassificationSummary;
WorkbasketSummary defaultWorkbasketSummary;
ObjectReference defaultObjectReference;
@WithAccessId(user = "businessadmin")
@BeforeAll
void setup() throws Exception {
defaultClassificationSummary =
defaultTestClassification().buildAndStoreAsSummary(classificationService);
defaultWorkbasketSummary = defaultTestWorkbasket().buildAndStoreAsSummary(workbasketService);
WorkbasketAccessItemBuilder.newWorkbasketAccessItem()
.workbasketId(defaultWorkbasketSummary.getId())
.accessId("user-1-1")
.permission(WorkbasketPermission.OPEN)
.permission(WorkbasketPermission.READ)
.permission(WorkbasketPermission.APPEND)
.buildAndStore(workbasketService);
defaultObjectReference = defaultTestObjectReference().build();
}
@WithAccessId(user = "user-1-1")
@Test
void should_createObjectReferences_When_CreatingTask() throws Exception {
Task task = taskService.newTask(defaultWorkbasketSummary.getId());
task.setClassificationKey(defaultClassificationSummary.getKey());
task.setPrimaryObjRef(defaultObjectReference);
ObjectReference sor1 =
taskService.newObjectReference(
"FirstCompany", "FirstSystem", null, "FirstType", "FirstValue");
ObjectReference sor2 =
taskService.newObjectReference("SecondCompany", null, null, "SecondType", "SecondValue");
task.addSecondaryObjectReference(sor1);
task.addSecondaryObjectReference(sor2);
Task createdTask = taskService.createTask(task);
TaskanaEngineProxy engineProxy = new TaskanaEngineProxy(taskanaEngine);
ObjectReferenceMapper objectReferenceMapper =
engineProxy.getEngine().getSqlSession().getMapper(ObjectReferenceMapper.class);
try {
engineProxy.openConnection();
assertThat(objectReferenceMapper.findObjectReferencesByTaskId(createdTask.getId()))
.hasSize(2);
} finally {
engineProxy.returnConnection();
}
Task readTask = taskService.getTask(createdTask.getId());
assertThat(readTask.getSecondaryObjectReferences())
.extracting(ObjectReference::getSystem)
.containsExactly("FirstSystem", null);
assertThat(readTask.getSecondaryObjectReferences())
.extracting(ObjectReference::getType)
.containsExactly("FirstType", "SecondType");
assertThat(readTask.getSecondaryObjectReferences())
.extracting(ObjectReference::getValue)
.containsExactly("FirstValue", "SecondValue");
assertThat(readTask.getSecondaryObjectReferences())
.extracting(ObjectReference::getCompany)
.containsExactly("FirstCompany", "SecondCompany");
}
@WithAccessId(user = "user-1-1")
@Test
void should_ThrowException_When_InvalidObjectReference() throws Exception {
ObjectReference sor1 =
taskService.newObjectReference(
"FirstCompany", "FirstSystem", null, "FirstType", "FirstValue");
ObjectReference invalidSor =
taskService.newObjectReference(null, null, null, "Second Type", "Second Value");
TaskImpl task = (TaskImpl) taskService.newTask(defaultWorkbasketSummary.getId());
task.setClassificationKey(defaultClassificationSummary.getKey());
task.setPrimaryObjRef(defaultObjectReference);
task.addSecondaryObjectReference(sor1);
task.addSecondaryObjectReference(invalidSor);
assertThatThrownBy(() -> taskService.createTask(task))
.isInstanceOf(InvalidArgumentException.class)
.hasMessage("Company of ObjectReference of Task must not be empty");
}
@WithAccessId(user = "user-1-1")
@Test
void should_copyObjectReferences_When_DuplicatingTask() throws Exception {
ObjectReference sor1 =
ObjectReferenceBuilder.newObjectReference()
.company("FirstCompany")
.value("FirstValue")
.type("FirstType")
.build();
ObjectReference sor2 =
ObjectReferenceBuilder.newObjectReference()
.company("SecondCompany")
.value("SecondValue")
.type("SecondType")
.build();
Task oldTask =
TaskBuilder.newTask()
.classificationSummary(defaultClassificationSummary)
.workbasketSummary(defaultWorkbasketSummary)
.primaryObjRef(defaultObjectReference)
.objectReferences(sor1, sor2)
.buildAndStore(taskService);
Task newTask = oldTask.copy();
newTask = taskService.createTask(newTask);
Task readOldTask = taskService.getTask(oldTask.getId());
assertThat(readOldTask.getSecondaryObjectReferences())
.extracting(ObjectReference::getTaskId)
.containsExactly(oldTask.getId(), oldTask.getId());
Task readNewTask = taskService.getTask(newTask.getId());
assertThat(readNewTask.getSecondaryObjectReferences())
.extracting(ObjectReference::getTaskId)
.containsExactly(newTask.getId(), newTask.getId());
assertThat(readNewTask.getSecondaryObjectReferences())
.extracting(ObjectReference::getId)
.doesNotContainAnyElementsOf(
readOldTask.getSecondaryObjectReferences().stream()
.map(ObjectReference::getTaskId)
.collect(Collectors.toList()));
}
}

View File

@ -0,0 +1,123 @@
package acceptance.task;
import static acceptance.DefaultTestEntities.defaultTestClassification;
import static acceptance.DefaultTestEntities.defaultTestObjectReference;
import static acceptance.DefaultTestEntities.defaultTestWorkbasket;
import static org.assertj.core.api.Assertions.assertThat;
import acceptance.TaskanaEngineProxy;
import java.util.List;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import testapi.TaskanaInject;
import testapi.TaskanaIntegrationTest;
import pro.taskana.classification.api.ClassificationService;
import pro.taskana.classification.api.models.ClassificationSummary;
import pro.taskana.common.api.TaskanaEngine;
import pro.taskana.common.test.security.WithAccessId;
import pro.taskana.task.api.TaskService;
import pro.taskana.task.api.TaskState;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.api.models.Task;
import pro.taskana.task.internal.ObjectReferenceMapper;
import pro.taskana.task.internal.builder.ObjectReferenceBuilder;
import pro.taskana.task.internal.builder.TaskBuilder;
import pro.taskana.workbasket.api.WorkbasketPermission;
import pro.taskana.workbasket.api.WorkbasketService;
import pro.taskana.workbasket.api.models.WorkbasketSummary;
import pro.taskana.workbasket.internal.builder.WorkbasketAccessItemBuilder;
/**
* Acceptance test for all "delete task" scenarios that involve secondary {@link ObjectReference}s.
*/
@TaskanaIntegrationTest
class DeleteTaskWithSorAccTest {
@TaskanaInject TaskService taskService;
@TaskanaInject WorkbasketService workbasketService;
@TaskanaInject ClassificationService classificationService;
@TaskanaInject TaskanaEngine taskanaEngine;
ClassificationSummary defaultClassificationSummary;
WorkbasketSummary defaultWorkbasketSummary;
ObjectReference defaultObjectReference;
ObjectReference sor1;
ObjectReference sor2;
@WithAccessId(user = "businessadmin")
@BeforeAll
void setup() throws Exception {
defaultClassificationSummary =
defaultTestClassification().buildAndStoreAsSummary(classificationService);
defaultWorkbasketSummary = defaultTestWorkbasket().buildAndStoreAsSummary(workbasketService);
WorkbasketAccessItemBuilder.newWorkbasketAccessItem()
.workbasketId(defaultWorkbasketSummary.getId())
.accessId("user-1-1")
.permission(WorkbasketPermission.OPEN)
.permission(WorkbasketPermission.READ)
.permission(WorkbasketPermission.APPEND)
.buildAndStore(workbasketService);
defaultObjectReference = defaultTestObjectReference().build();
sor1 =
ObjectReferenceBuilder.newObjectReference()
.company("FirstCompany")
.value("FirstValue")
.type("FirstType")
.build();
sor2 =
ObjectReferenceBuilder.newObjectReference()
.company("SecondCompany")
.value("SecondValue")
.type("SecondType")
.build();
}
@WithAccessId(user = "admin")
@Test
void should_DeleteObjectReferences_When_DeletingTask() throws Exception {
Task createdTask =
createCompletedTask().objectReferences(sor1, sor2).buildAndStore(taskService);
taskService.deleteTask(createdTask.getId());
TaskanaEngineProxy engineProxy = new TaskanaEngineProxy(taskanaEngine);
ObjectReferenceMapper objectReferenceMapper =
engineProxy.getEngine().getSqlSession().getMapper(ObjectReferenceMapper.class);
try {
engineProxy.openConnection();
assertThat(objectReferenceMapper.findObjectReferencesByTaskId(createdTask.getId())).isEmpty();
} finally {
engineProxy.returnConnection();
}
}
@WithAccessId(user = "admin")
@Test
void should_DeleteObjectReferences_When_MultipleTasksAreDeleted() throws Exception {
Task firstCreatedTask = createCompletedTask().objectReferences(sor1).buildAndStore(taskService);
Task secondCreatedTask =
createCompletedTask().objectReferences(sor1, sor2).buildAndStore(taskService);
taskService.deleteTasks(List.of(firstCreatedTask.getId(), secondCreatedTask.getId()));
TaskanaEngineProxy engineProxy = new TaskanaEngineProxy(taskanaEngine);
ObjectReferenceMapper objectReferenceMapper =
engineProxy.getEngine().getSqlSession().getMapper(ObjectReferenceMapper.class);
try {
engineProxy.openConnection();
assertThat(
objectReferenceMapper.findObjectReferencesByTaskIds(
List.of(firstCreatedTask.getId(), secondCreatedTask.getId())))
.isEmpty();
} finally {
engineProxy.returnConnection();
}
}
private TaskBuilder createCompletedTask() {
return (TaskBuilder.newTask()
.classificationSummary(defaultClassificationSummary)
.workbasketSummary(defaultWorkbasketSummary)
.primaryObjRef(defaultObjectReference)
.state(TaskState.COMPLETED));
}
}

View File

@ -0,0 +1,91 @@
package acceptance.task;
import static acceptance.DefaultTestEntities.defaultTestClassification;
import static acceptance.DefaultTestEntities.defaultTestObjectReference;
import static acceptance.DefaultTestEntities.defaultTestWorkbasket;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import testapi.TaskanaInject;
import testapi.TaskanaIntegrationTest;
import pro.taskana.classification.api.ClassificationService;
import pro.taskana.classification.api.models.ClassificationSummary;
import pro.taskana.common.test.security.WithAccessId;
import pro.taskana.task.api.TaskService;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.api.models.Task;
import pro.taskana.task.internal.builder.ObjectReferenceBuilder;
import pro.taskana.task.internal.builder.TaskBuilder;
import pro.taskana.workbasket.api.WorkbasketPermission;
import pro.taskana.workbasket.api.WorkbasketService;
import pro.taskana.workbasket.api.models.WorkbasketSummary;
import pro.taskana.workbasket.internal.builder.WorkbasketAccessItemBuilder;
@TaskanaIntegrationTest
class GetTaskWithSorAccTest {
@TaskanaInject TaskService taskService;
@TaskanaInject WorkbasketService workbasketService;
@TaskanaInject ClassificationService classificationService;
ClassificationSummary defaultClassificationSummary;
WorkbasketSummary defaultWorkbasketSummary;
ObjectReference defaultObjectReference;
@WithAccessId(user = "businessadmin")
@BeforeAll
void setup() throws Exception {
defaultClassificationSummary =
defaultTestClassification().buildAndStoreAsSummary(classificationService);
defaultWorkbasketSummary = defaultTestWorkbasket().buildAndStoreAsSummary(workbasketService);
WorkbasketAccessItemBuilder.newWorkbasketAccessItem()
.workbasketId(defaultWorkbasketSummary.getId())
.accessId("user-1-1")
.permission(WorkbasketPermission.OPEN)
.permission(WorkbasketPermission.READ)
.permission(WorkbasketPermission.APPEND)
.buildAndStore(workbasketService);
defaultObjectReference = defaultTestObjectReference().build();
}
@WithAccessId(user = "user-1-1")
@Test
void should_ReturnTaskWithSor_When_RequestingTaskByTaskId() throws Exception {
Task task =
createDefaultTask()
.objectReferences(
defaultSecondaryObjectReference("0"), defaultSecondaryObjectReference("1"))
.buildAndStore(taskService);
Task result = taskService.getTask(task.getId());
assertThat(result.getSecondaryObjectReferences())
.extracting(ObjectReference::getType)
.containsExactly("Type0", "Type1");
assertThat(result.getSecondaryObjectReferences())
.extracting(ObjectReference::getValue)
.containsExactly("Value0", "Value1");
assertThat(result.getSecondaryObjectReferences())
.extracting(ObjectReference::getCompany)
.containsExactly("Company0", "Company1");
}
private TaskBuilder createDefaultTask() {
return (TaskBuilder.newTask()
.classificationSummary(defaultClassificationSummary)
.workbasketSummary(defaultWorkbasketSummary)
.primaryObjRef(defaultObjectReference));
}
private ObjectReference defaultSecondaryObjectReference(String suffix) {
return ObjectReferenceBuilder.newObjectReference()
.company("Company" + suffix)
.value("Value" + suffix)
.type("Type" + suffix)
.build();
}
}

View File

@ -13,9 +13,9 @@ import org.junit.jupiter.api.Test;
import pro.taskana.task.api.models.Attachment;
import pro.taskana.task.api.models.AttachmentSummary;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.internal.models.AttachmentImpl;
import pro.taskana.task.internal.models.AttachmentSummaryImpl;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
import pro.taskana.task.internal.models.TaskCommentImpl;
import pro.taskana.task.internal.models.TaskImpl;
import pro.taskana.task.internal.models.TaskSummaryImpl;
@ -116,7 +116,7 @@ class TaskModelsCloneTest {
@Test
void should_CopyWithoutId_When_ObjectReferenceClone() {
ObjectReference dummyReference = new ObjectReference();
ObjectReferenceImpl dummyReference = new ObjectReferenceImpl();
dummyReference.setId("dummyId");
dummyReference.setSystem("dummySystem");
dummyReference.setCompany("dummyCompany");
@ -124,7 +124,7 @@ class TaskModelsCloneTest {
dummyReference.setType("dummyType");
dummyReference.setValue("dummyValue");
ObjectReference dummyReferenceCloned = dummyReference.copy();
ObjectReferenceImpl dummyReferenceCloned = dummyReference.copy();
assertThat(dummyReferenceCloned).isNotEqualTo(dummyReference);
dummyReferenceCloned.setId(dummyReference.getId());

View File

@ -31,6 +31,7 @@ import pro.taskana.task.api.WildcardSearchField;
import pro.taskana.task.api.models.Attachment;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.api.models.TaskSummary;
import pro.taskana.task.internal.builder.ObjectReferenceBuilder;
import pro.taskana.task.internal.builder.TaskAttachmentBuilder;
import pro.taskana.task.internal.builder.TaskBuilder;
import pro.taskana.workbasket.api.WorkbasketPermission;
@ -2429,6 +2430,532 @@ class TaskQueryImplAccTest {
}
}
@Nested
@TestInstance(Lifecycle.PER_CLASS)
class QueryingObjectReferenceCombinations {
WorkbasketSummary wb;
TaskSummary taskSummary1;
TaskSummary taskSummary2;
TaskSummary taskSummary3;
TaskSummary taskSummary4;
TaskSummary taskSummary5;
TaskSummary taskSummary6;
TaskSummary taskSummary7;
@WithAccessId(user = "user-1-1")
@BeforeAll
void setup() throws Exception {
wb = createWorkbasketWithPermission();
ObjectReference sor1 =
ObjectReferenceBuilder.newObjectReference()
.company("FirstCompany")
.value("FirstValue")
.type("FirstType")
.build();
taskSummary1 =
taskInWorkbasket(wb).objectReferences(sor1).buildAndStoreAsSummary(taskService);
ObjectReference sor2 =
ObjectReferenceBuilder.newObjectReference()
.company("FirstCompany")
.value("SecondValue")
.type("SecondType")
.build();
taskSummary2 =
taskInWorkbasket(wb).objectReferences(sor2).buildAndStoreAsSummary(taskService);
ObjectReference sor2copy = sor2.copy();
ObjectReference sor1copy = sor1.copy();
taskSummary3 =
taskInWorkbasket(wb)
.objectReferences(sor2copy, sor1copy)
.buildAndStoreAsSummary(taskService);
ObjectReference sor3 =
ObjectReferenceBuilder.newObjectReference()
.company("SecondCompany")
.value("SecondValue")
.type("SecondType")
.build();
taskSummary4 =
taskInWorkbasket(wb).objectReferences(sor1, sor3).buildAndStoreAsSummary(taskService);
ObjectReference sor4 =
ObjectReferenceBuilder.newObjectReference()
.company("SecondCompany")
.value("ThirdValue")
.type("ThirdType")
.build();
taskSummary5 =
taskInWorkbasket(wb).objectReferences(sor4).buildAndStoreAsSummary(taskService);
ObjectReference sor5 =
ObjectReferenceBuilder.newObjectReference()
.company("FirstCompany")
.value("ThirdValue")
.type("FirstType")
.build();
taskSummary6 =
taskInWorkbasket(wb).objectReferences(sor5).buildAndStoreAsSummary(taskService);
ObjectReference sor6 =
ObjectReferenceBuilder.newObjectReference()
.company("FirstCompany")
.value("FirstValue")
.type("ThirdType")
.build();
taskSummary7 =
taskInWorkbasket(wb).objectReferences(sor6).buildAndStoreAsSummary(taskService);
}
@WithAccessId(user = "user-1-1")
@Test
void should_ApplyFilter_When_QueryingForValueInCompanyIn() {
List<TaskSummary> tasks =
taskService
.createTaskQuery()
.workbasketIdIn(wb.getId())
.sorValueIn("SecondValue")
.sorCompanyIn("FirstCompany")
.list();
assertThat(tasks).hasSize(2);
}
@WithAccessId(user = "user-1-1")
@Test
void should_ApplyFilter_When_QueryingForValueInMultipleCompanyIn() {
List<TaskSummary> tasks =
taskService
.createTaskQuery()
.workbasketIdIn(wb.getId())
.sorValueIn("SecondValue")
.sorCompanyIn("FirstCompany", "SecondCompany")
.list();
assertThat(tasks).hasSize(3);
}
@WithAccessId(user = "user-1-1")
@Test
void should_ApplyFilter_When_QueryingForValueInMultipleTypeLikeMultiple() {
List<TaskSummary> tasks =
taskService
.createTaskQuery()
.workbasketIdIn(wb.getId())
.sorValueIn("FirstValue", "ThirdValue")
.sorTypeLike("First%", "Third%")
.list();
assertThat(tasks).hasSize(5);
}
}
@Nested
@TestInstance(Lifecycle.PER_CLASS)
class ObjectReferenceValue {
WorkbasketSummary wb;
TaskSummary taskSummary1;
TaskSummary taskSummary2;
TaskSummary taskSummary3;
@WithAccessId(user = "user-1-1")
@BeforeAll
void setup() throws Exception {
wb = createWorkbasketWithPermission();
ObjectReference sor1 =
ObjectReferenceBuilder.newObjectReference()
.company("FirstCompany")
.value("FirstValue")
.type("FirstType")
.build();
ObjectReference sor2 =
ObjectReferenceBuilder.newObjectReference()
.company("FirstCompany")
.value("SecondValue")
.type("SecondType")
.build();
ObjectReference sor2copy = sor2.copy();
ObjectReference sor1copy = sor1.copy();
taskSummary1 =
taskInWorkbasket(wb).objectReferences(sor1).buildAndStoreAsSummary(taskService);
taskSummary2 =
taskInWorkbasket(wb).objectReferences(sor2).buildAndStoreAsSummary(taskService);
taskSummary3 =
taskInWorkbasket(wb)
.objectReferences(sor2copy, sor1copy)
.buildAndStoreAsSummary(taskService);
}
@WithAccessId(user = "user-1-1")
@Test
void should_ApplyFilter_When_QueryingForValueIn() {
List<TaskSummary> list =
taskService
.createTaskQuery()
.workbasketIdIn(wb.getId())
.sorValueIn("FirstValue")
.list();
assertThat(list).containsExactlyInAnyOrder(taskSummary1, taskSummary3);
}
@WithAccessId(user = "user-1-1")
@Test
void should_CountCorrectly_When_QueryingForValueIn() {
long numberOfTasks =
taskService
.createTaskQuery()
.workbasketIdIn(wb.getId())
.sorValueIn("FirstValue")
.count();
assertThat(numberOfTasks).isEqualTo(2);
}
@WithAccessId(user = "user-1-1")
@Test
void should_ApplyFilter_When_QueryingForValueLike() {
List<TaskSummary> list =
taskService.createTaskQuery().workbasketIdIn(wb.getId()).sorValueLike("%Value").list();
assertThat(list).containsExactlyInAnyOrder(taskSummary1, taskSummary2, taskSummary3);
}
}
@Nested
@TestInstance(Lifecycle.PER_CLASS)
class ObjectReferenceType {
WorkbasketSummary wb;
TaskSummary taskSummary1;
TaskSummary taskSummary2;
TaskSummary taskSummary3;
TaskSummary taskSummary4;
@WithAccessId(user = "user-1-1")
@BeforeAll
void setup() throws Exception {
wb = createWorkbasketWithPermission();
ObjectReference sor1 =
ObjectReferenceBuilder.newObjectReference()
.company("FirstCompany")
.value("FirstValue")
.type("FirstType")
.build();
taskSummary1 =
taskInWorkbasket(wb).objectReferences(sor1).buildAndStoreAsSummary(taskService);
ObjectReference sor2 =
ObjectReferenceBuilder.newObjectReference()
.company("FirstCompany")
.value("FirstValue")
.type("SecondType")
.build();
taskSummary2 =
taskInWorkbasket(wb).objectReferences(sor2).buildAndStoreAsSummary(taskService);
ObjectReference sor2copy = sor2.copy();
ObjectReference sor1copy = sor1.copy();
taskSummary3 =
taskInWorkbasket(wb)
.objectReferences(sor2copy, sor1copy)
.buildAndStoreAsSummary(taskService);
ObjectReference sor3 =
ObjectReferenceBuilder.newObjectReference()
.company("FirstCompany")
.value("FirstValue")
.type("ThirdType")
.build();
taskSummary4 =
taskInWorkbasket(wb).objectReferences(sor3).buildAndStoreAsSummary(taskService);
}
@WithAccessId(user = "user-1-1")
@Test
void should_ApplyFilter_When_QueryingForTypeIn() {
List<TaskSummary> list =
taskService.createTaskQuery().workbasketIdIn(wb.getId()).sorTypeIn("FirstType").list();
assertThat(list).containsExactlyInAnyOrder(taskSummary1, taskSummary3);
}
@WithAccessId(user = "user-1-1")
@Test
void should_ReturnSingleTaskSummary_When_QueryingForTypeLikeUsingSingle() {
TaskSummary result =
taskService.createTaskQuery().workbasketIdIn(wb.getId()).sorTypeLike("Third%").single();
assertThat(result).isEqualTo(taskSummary4);
}
@WithAccessId(user = "user-1-1")
@Test
void should_ReturnEmptyList_When_QueryingForNonexistentTypeLike() {
List<TaskSummary> list =
taskService
.createTaskQuery()
.workbasketIdIn(wb.getId())
.sorTypeLike("%NoSuchType")
.list();
assertThat(list).isEmpty();
}
}
@Nested
@TestInstance(Lifecycle.PER_CLASS)
class ObjectReferenceCompany {
WorkbasketSummary wb;
TaskSummary taskSummary1;
TaskSummary taskSummary2;
TaskSummary taskSummary3;
@WithAccessId(user = "user-1-1")
@BeforeAll
void setup() throws Exception {
wb = createWorkbasketWithPermission();
ObjectReference sor1 =
ObjectReferenceBuilder.newObjectReference()
.company("FirstCompany")
.value("FirstValue")
.type("FirstType")
.build();
ObjectReference sor2 =
ObjectReferenceBuilder.newObjectReference()
.company("SecondCompany")
.value("FirstValue")
.type("SecondType")
.build();
ObjectReference sor2copy = sor2.copy();
ObjectReference sor1copy = sor1.copy();
taskSummary1 =
taskInWorkbasket(wb).objectReferences(sor1).buildAndStoreAsSummary(taskService);
taskSummary2 =
taskInWorkbasket(wb).objectReferences(sor2).buildAndStoreAsSummary(taskService);
taskSummary3 =
taskInWorkbasket(wb)
.objectReferences(sor2copy, sor1copy)
.buildAndStoreAsSummary(taskService);
}
@WithAccessId(user = "user-1-1")
@Test
void should_ApplyFilter_When_QueryingForCompanyInWithLimit() {
List<TaskSummary> list =
taskService
.createTaskQuery()
.workbasketIdIn(wb.getId())
.sorCompanyIn("FirstCompany")
.list(0, 1);
assertThat(list).hasSize(1).containsAnyOf(taskSummary1, taskSummary3);
}
@WithAccessId(user = "user-1-1")
@Test
void should_ApplyFilter_When_QueryingForCompanyLike() {
List<TaskSummary> list =
taskService
.createTaskQuery()
.workbasketIdIn(wb.getId())
.sorCompanyLike("%Company")
.list();
assertThat(list).containsExactlyInAnyOrder(taskSummary1, taskSummary2, taskSummary3);
}
@WithAccessId(user = "user-1-1")
@Test
void should_ReturnEmptyList_When_QueryingForNonexistentCompanyLike() {
List<TaskSummary> list =
taskService
.createTaskQuery()
.workbasketIdIn(wb.getId())
.sorCompanyLike("%NoSuchCompany")
.list();
assertThat(list).isEmpty();
}
}
@Nested
@TestInstance(Lifecycle.PER_CLASS)
class ObjectReferenceSystem {
WorkbasketSummary wb;
TaskSummary taskSummary1;
TaskSummary taskSummary2;
TaskSummary taskSummary3;
TaskSummary taskSummary4;
@WithAccessId(user = "user-1-1")
@BeforeAll
void setup() throws Exception {
wb = createWorkbasketWithPermission();
ObjectReference sor1 =
ObjectReferenceBuilder.newObjectReference()
.company("FirstCompany")
.value("FirstValue")
.type("FirstType")
.system("FirstSystem")
.build();
taskSummary1 =
taskInWorkbasket(wb).objectReferences(sor1).buildAndStoreAsSummary(taskService);
ObjectReference sor2 =
ObjectReferenceBuilder.newObjectReference()
.company("SecondCompany")
.value("FirstValue")
.type("SecondType")
.system("SecondSystem")
.build();
taskSummary2 =
taskInWorkbasket(wb).objectReferences(sor2).buildAndStoreAsSummary(taskService);
ObjectReference sor2copy = sor2.copy();
ObjectReference sor1copy = sor1.copy();
taskSummary3 =
taskInWorkbasket(wb)
.objectReferences(sor2copy, sor1copy)
.buildAndStoreAsSummary(taskService);
ObjectReference objRefNoSystem =
ObjectReferenceBuilder.newObjectReference()
.company("SecondCompany")
.value("FirstValue")
.type("SecondType")
.build();
taskSummary4 =
taskInWorkbasket(wb)
.objectReferences(objRefNoSystem)
.buildAndStoreAsSummary(taskService);
}
@WithAccessId(user = "user-1-1")
@Test
void should_ApplyFilter_When_QueryingForSystemIn() {
List<TaskSummary> list =
taskService
.createTaskQuery()
.workbasketIdIn(wb.getId())
.sorSystemIn("FirstSystem")
.list();
assertThat(list).containsExactlyInAnyOrder(taskSummary1, taskSummary3);
}
@WithAccessId(user = "user-1-1")
@Test
void should_ApplyFilter_When_QueryingForSystemLike() {
List<TaskSummary> list =
taskService
.createTaskQuery()
.workbasketIdIn(wb.getId())
.sorSystemLike("%System")
.list();
assertThat(list).containsExactlyInAnyOrder(taskSummary1, taskSummary2, taskSummary3);
}
@WithAccessId(user = "user-1-1")
@Test
void should_ReturnEmptyList_When_QueryingForNonexistentSystemLike() {
List<TaskSummary> list =
taskService
.createTaskQuery()
.workbasketIdIn(wb.getId())
.sorSystemLike("%NoSuchSystem")
.list();
assertThat(list).isEmpty();
}
}
@Nested
@TestInstance(Lifecycle.PER_CLASS)
class ObjectReferenceSystemInstance {
WorkbasketSummary wb;
TaskSummary taskSummary1;
TaskSummary taskSummary2;
TaskSummary taskSummary3;
TaskSummary taskSummary4;
@WithAccessId(user = "user-1-1")
@BeforeAll
void setup() throws Exception {
wb = createWorkbasketWithPermission();
ObjectReference sor1 =
ObjectReferenceBuilder.newObjectReference()
.company("FirstCompany")
.value("FirstValue")
.type("FirstType")
.systemInstance("FirstSystemInstance")
.build();
taskSummary1 =
taskInWorkbasket(wb).objectReferences(sor1).buildAndStoreAsSummary(taskService);
ObjectReference sor2 =
ObjectReferenceBuilder.newObjectReference()
.company("SecondCompany")
.value("FirstValue")
.type("SecondType")
.systemInstance("SecondSystemInstance")
.build();
taskSummary2 =
taskInWorkbasket(wb).objectReferences(sor2).buildAndStoreAsSummary(taskService);
ObjectReference sor2copy = sor2.copy();
ObjectReference sor1copy = sor1.copy();
taskSummary3 =
taskInWorkbasket(wb)
.objectReferences(sor2copy, sor1copy)
.buildAndStoreAsSummary(taskService);
ObjectReference objRefNoSystem =
ObjectReferenceBuilder.newObjectReference()
.company("SecondCompany")
.value("FirstValue")
.type("SecondType")
.build();
taskSummary4 =
taskInWorkbasket(wb)
.objectReferences(objRefNoSystem)
.buildAndStoreAsSummary(taskService);
}
@WithAccessId(user = "user-1-1")
@Test
void should_ApplyFilter_When_QueryingForSystemInstanceIn() {
List<TaskSummary> list =
taskService
.createTaskQuery()
.workbasketIdIn(wb.getId())
.sorSystemInstanceIn("FirstSystemInstance")
.list();
assertThat(list).containsExactlyInAnyOrder(taskSummary1, taskSummary3);
}
@WithAccessId(user = "user-1-1")
@Test
void should_ApplyFilter_When_QueryingForSystemInstanceLike() {
List<TaskSummary> list =
taskService
.createTaskQuery()
.workbasketIdIn(wb.getId())
.sorSystemInstanceLike("%SystemInstance")
.list();
assertThat(list).containsExactlyInAnyOrder(taskSummary1, taskSummary2, taskSummary3);
}
@WithAccessId(user = "user-1-1")
@Test
void should_ReturnEmptyList_When_QueryingForNonexistentSystemInstanceLike() {
List<TaskSummary> list =
taskService
.createTaskQuery()
.workbasketIdIn(wb.getId())
.sorSystemInstanceLike("%NoSuchSystemInstance")
.list();
assertThat(list).isEmpty();
}
}
@Nested
@TestInstance(Lifecycle.PER_CLASS)
class CustomAttributes {}

View File

@ -31,9 +31,9 @@ import pro.taskana.common.test.security.WithAccessId;
import pro.taskana.task.api.TaskCustomField;
import pro.taskana.task.api.TaskState;
import pro.taskana.task.api.exceptions.TaskNotFoundException;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.api.models.Task;
import pro.taskana.task.api.models.TaskSummary;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
import pro.taskana.task.internal.models.TaskImpl;
/** Acceptance test for all "update task" scenarios. */
@ -258,7 +258,7 @@ class UpdateTaskAccTest extends AbstractAccTest {
@Test
void should_UpdateNoTasks_When_UpdateTasksWithUnmatchedObjectReferenceWasCalled()
throws Exception {
ObjectReference por = new ObjectReference();
ObjectReferenceImpl por = new ObjectReferenceImpl();
por.setCompany("00");
por.setSystem("PASystem");
por.setSystemInstance("00");
@ -277,7 +277,7 @@ class UpdateTaskAccTest extends AbstractAccTest {
@WithAccessId(user = "teamlead-1")
@Test
void should_UpdateTasks_When_MatchingPrimaryObjectReferenceWasChanged() throws Exception {
ObjectReference por = new ObjectReference();
ObjectReferenceImpl por = new ObjectReferenceImpl();
por.setCompany("00");
por.setSystem("PASystem");
por.setSystemInstance("00");

View File

@ -0,0 +1,169 @@
package acceptance.task;
import static acceptance.DefaultTestEntities.defaultTestClassification;
import static acceptance.DefaultTestEntities.defaultTestObjectReference;
import static acceptance.DefaultTestEntities.defaultTestWorkbasket;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import testapi.TaskanaInject;
import testapi.TaskanaIntegrationTest;
import pro.taskana.classification.api.ClassificationService;
import pro.taskana.classification.api.models.ClassificationSummary;
import pro.taskana.common.test.security.WithAccessId;
import pro.taskana.task.api.TaskService;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.api.models.Task;
import pro.taskana.task.internal.builder.ObjectReferenceBuilder;
import pro.taskana.task.internal.builder.TaskBuilder;
import pro.taskana.workbasket.api.WorkbasketPermission;
import pro.taskana.workbasket.api.WorkbasketService;
import pro.taskana.workbasket.api.models.WorkbasketSummary;
import pro.taskana.workbasket.internal.builder.WorkbasketAccessItemBuilder;
/** Acceptance test for "update task" scenarios that involve secondary {@link ObjectReference}s. */
@TaskanaIntegrationTest
class UpdateTaskWithSorAccTest {
@TaskanaInject TaskService taskService;
@TaskanaInject WorkbasketService workbasketService;
@TaskanaInject ClassificationService classificationService;
ClassificationSummary defaultClassificationSummary;
WorkbasketSummary defaultWorkbasketSummary;
ObjectReference defaultObjectReference;
@WithAccessId(user = "businessadmin")
@BeforeAll
void setup() throws Exception {
defaultClassificationSummary =
defaultTestClassification().buildAndStoreAsSummary(classificationService);
defaultWorkbasketSummary = defaultTestWorkbasket().buildAndStoreAsSummary(workbasketService);
WorkbasketAccessItemBuilder.newWorkbasketAccessItem()
.workbasketId(defaultWorkbasketSummary.getId())
.accessId("user-1-1")
.permission(WorkbasketPermission.OPEN)
.permission(WorkbasketPermission.READ)
.permission(WorkbasketPermission.APPEND)
.buildAndStore(workbasketService);
defaultObjectReference = defaultTestObjectReference().build();
}
@WithAccessId(user = "user-1-1")
@Test
void should_NotChangeSor_When_UpdateWithoutChanges() throws Exception {
Task task =
createDefaultTask()
.objectReferences(
defaultSecondaryObjectReference("0"), defaultSecondaryObjectReference("1"))
.buildAndStore(taskService);
taskService.updateTask(task);
Task result = taskService.getTask(task.getId());
assertThat(result.getSecondaryObjectReferences())
.extracting(ObjectReference::getType)
.containsExactlyInAnyOrder("Type0", "Type1");
assertThat(result.getSecondaryObjectReferences())
.extracting(ObjectReference::getValue)
.containsExactlyInAnyOrder("Value0", "Value1");
assertThat(result.getSecondaryObjectReferences())
.extracting(ObjectReference::getCompany)
.containsExactlyInAnyOrder("Company0", "Company1");
}
@WithAccessId(user = "user-1-1")
@Test
void should_UpdateExistingSor_When_SorChangedInUpdatedTask() throws Exception {
Task task =
createDefaultTask()
.objectReferences(
defaultSecondaryObjectReference("0"), defaultSecondaryObjectReference("1"))
.buildAndStore(taskService);
ObjectReference sorToUpdate = task.getSecondaryObjectReferences().get(0);
sorToUpdate.setType("NewType");
taskService.updateTask(task);
Task result = taskService.getTask(task.getId());
assertThat(result.getSecondaryObjectReferences())
.extracting(ObjectReference::getType)
.containsExactlyInAnyOrder("NewType", "Type1");
}
@WithAccessId(user = "user-1-1")
@Test
void should_AddNewSor_When_UpdatedTaskContainsNewSor() throws Exception {
Task task =
createDefaultTask()
.objectReferences(
defaultSecondaryObjectReference("0"), defaultSecondaryObjectReference("1"))
.buildAndStore(taskService);
task.addSecondaryObjectReference("NewCompany", null, null, "NewType", "NewValue");
taskService.updateTask(task);
Task result = taskService.getTask(task.getId());
assertThat(result.getSecondaryObjectReferences())
.extracting(ObjectReference::getType)
.containsExactlyInAnyOrder("Type0", "Type1", "NewType");
assertThat(result.getSecondaryObjectReferences())
.extracting(ObjectReference::getValue)
.containsExactlyInAnyOrder("Value0", "Value1", "NewValue");
assertThat(result.getSecondaryObjectReferences())
.extracting(ObjectReference::getCompany)
.containsExactlyInAnyOrder("Company0", "Company1", "NewCompany");
}
@WithAccessId(user = "user-1-1")
@Test
void should_DeleteOneSor_When_UpdatedTaskContainsOneLessSor() throws Exception {
Task task =
createDefaultTask()
.objectReferences(
defaultSecondaryObjectReference("0"), defaultSecondaryObjectReference("1"))
.buildAndStore(taskService);
task.removeSecondaryObjectReference(task.getSecondaryObjectReferences().get(0).getId());
taskService.updateTask(task);
Task result = taskService.getTask(task.getId());
assertThat(result.getSecondaryObjectReferences()).hasSize(1);
}
@WithAccessId(user = "user-1-1")
@Test
void should_DeleteAllSor_When_UpdatedTaskContainsNoSor() throws Exception {
Task task =
createDefaultTask()
.objectReferences(
defaultSecondaryObjectReference("0"), defaultSecondaryObjectReference("1"))
.buildAndStore(taskService);
task.removeSecondaryObjectReference(task.getSecondaryObjectReferences().get(0).getId());
task.removeSecondaryObjectReference(task.getSecondaryObjectReferences().get(0).getId());
taskService.updateTask(task);
Task result = taskService.getTask(task.getId());
assertThat(result.getSecondaryObjectReferences()).isEmpty();
}
private TaskBuilder createDefaultTask() {
return (TaskBuilder.newTask()
.classificationSummary(defaultClassificationSummary)
.workbasketSummary(defaultWorkbasketSummary)
.primaryObjRef(defaultObjectReference));
}
private ObjectReference defaultSecondaryObjectReference(String suffix) {
return ObjectReferenceBuilder.newObjectReference()
.company("Company" + suffix)
.value("Value" + suffix)
.type("Type" + suffix)
.build();
}
}

View File

@ -17,10 +17,11 @@ import pro.taskana.task.api.TaskService;
import pro.taskana.task.api.exceptions.AttachmentPersistenceException;
import pro.taskana.task.api.exceptions.InvalidOwnerException;
import pro.taskana.task.api.exceptions.InvalidStateException;
import pro.taskana.task.api.exceptions.ObjectReferencePersistenceException;
import pro.taskana.task.api.exceptions.TaskAlreadyExistException;
import pro.taskana.task.api.exceptions.TaskNotFoundException;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.api.models.Task;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
import pro.taskana.workbasket.api.WorkbasketType;
import pro.taskana.workbasket.api.exceptions.WorkbasketAlreadyExistException;
import pro.taskana.workbasket.api.exceptions.WorkbasketNotFoundException;
@ -41,7 +42,7 @@ public class ExampleBootstrap {
NotAuthorizedException, ClassificationAlreadyExistException,
MalformedServiceLevelException, TaskAlreadyExistException, WorkbasketNotFoundException,
ClassificationNotFoundException, AttachmentPersistenceException, TaskNotFoundException,
InvalidOwnerException, InvalidStateException {
InvalidOwnerException, InvalidStateException, ObjectReferencePersistenceException {
System.out.println("---------------------------> Start App");
Workbasket wb = taskanaEngine.getWorkbasketService().newWorkbasket("workbasket", "DOMAIN_A");
@ -56,7 +57,7 @@ public class ExampleBootstrap {
Task task = taskanaEngine.getTaskService().newTask(wb.getId());
task.setName("Spring example task");
task.setClassificationKey(classification.getKey());
ObjectReference objRef = new ObjectReference();
ObjectReferenceImpl objRef = new ObjectReferenceImpl();
objRef.setCompany("aCompany");
objRef.setSystem("aSystem");
objRef.setSystemInstance("anInstance");

View File

@ -31,6 +31,7 @@ import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.api.models.Task;
import pro.taskana.task.api.models.TaskSummary;
import pro.taskana.task.internal.jobs.TaskCleanupJob;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
import pro.taskana.task.internal.models.TaskImpl;
import pro.taskana.workbasket.api.WorkbasketService;
import pro.taskana.workbasket.api.WorkbasketType;
@ -230,7 +231,7 @@ class TaskanaTransactionIntTest {
}
private static ObjectReference createDefaultObjRef() {
ObjectReference objRef = new ObjectReference();
ObjectReferenceImpl objRef = new ObjectReferenceImpl();
objRef.setCompany("company");
objRef.setSystem("system");
objRef.setSystemInstance("instance");

View File

@ -9,9 +9,10 @@ import pro.taskana.common.api.exceptions.InvalidArgumentException;
import pro.taskana.common.api.exceptions.NotAuthorizedException;
import pro.taskana.task.api.TaskService;
import pro.taskana.task.api.exceptions.AttachmentPersistenceException;
import pro.taskana.task.api.exceptions.ObjectReferencePersistenceException;
import pro.taskana.task.api.exceptions.TaskAlreadyExistException;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.api.models.Task;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
import pro.taskana.workbasket.api.exceptions.WorkbasketNotFoundException;
/** TODO. */
@ -27,10 +28,11 @@ public class TaskanaComponent {
public void triggerRollback()
throws NotAuthorizedException, WorkbasketNotFoundException, ClassificationNotFoundException,
TaskAlreadyExistException, InvalidArgumentException, AttachmentPersistenceException {
TaskAlreadyExistException, InvalidArgumentException, AttachmentPersistenceException,
ObjectReferencePersistenceException {
Task task = taskService.newTask("1");
task.setName("Unit Test Task");
ObjectReference objRef = new ObjectReference();
ObjectReferenceImpl objRef = new ObjectReferenceImpl();
objRef.setCompany("aCompany");
objRef.setSystem("aSystem");
objRef.setSystemInstance("anInstance");

View File

@ -8,6 +8,7 @@ import org.springframework.web.bind.annotation.InitBinder;
import pro.taskana.monitor.rest.models.PriorityColumnHeaderRepresentationModel;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
@ControllerAdvice
public class JsonPropertyEditorRegistrator {
@ -25,6 +26,6 @@ public class JsonPropertyEditorRegistrator {
PriorityColumnHeaderRepresentationModel.class,
new JsonPropertyEditor(objectMapper, PriorityColumnHeaderRepresentationModel.class));
binder.registerCustomEditor(
ObjectReference.class, new JsonPropertyEditor(objectMapper, ObjectReference.class));
ObjectReference.class, new JsonPropertyEditor(objectMapper, ObjectReferenceImpl.class));
}
}

View File

@ -37,6 +37,7 @@ import pro.taskana.task.api.TaskService;
import pro.taskana.task.api.exceptions.AttachmentPersistenceException;
import pro.taskana.task.api.exceptions.InvalidOwnerException;
import pro.taskana.task.api.exceptions.InvalidStateException;
import pro.taskana.task.api.exceptions.ObjectReferencePersistenceException;
import pro.taskana.task.api.exceptions.TaskAlreadyExistException;
import pro.taskana.task.api.exceptions.TaskNotFoundException;
import pro.taskana.task.api.models.Task;
@ -84,13 +85,11 @@ public class TaskController {
TaskQueryFilterParameter filterParameter,
TaskQuerySortParameter sortParameter,
QueryPagingParameter<TaskSummary, TaskQuery> pagingParameter) {
QueryParamsValidator.validateParams(
request,
TaskQueryFilterParameter.class,
QuerySortParameter.class,
QueryPagingParameter.class);
TaskQuery query = taskService.createTaskQuery();
filterParameter.apply(query);
@ -332,6 +331,8 @@ public class TaskController {
* @throws InvalidArgumentException if any input is semantically wrong.
* @throws AttachmentPersistenceException if an Attachment with ID will be added multiple times
* without using the task-methods
* @throws ObjectReferencePersistenceException if an ObjectReference with ID will be added
* multiple times without using the task-methods
* @title Create a new Task
*/
@PostMapping(path = RestEndpoints.URL_TASKS)
@ -339,7 +340,8 @@ public class TaskController {
public ResponseEntity<TaskRepresentationModel> createTask(
@RequestBody TaskRepresentationModel taskRepresentationModel)
throws WorkbasketNotFoundException, ClassificationNotFoundException, NotAuthorizedException,
TaskAlreadyExistException, InvalidArgumentException, AttachmentPersistenceException {
TaskAlreadyExistException, InvalidArgumentException, AttachmentPersistenceException,
ObjectReferencePersistenceException {
Task fromResource = taskRepresentationModelAssembler.toEntityModel(taskRepresentationModel);
Task createdTask = taskService.createTask(fromResource);
@ -388,6 +390,8 @@ public class TaskController {
* @throws NotAuthorizedException if the current user is not authorized.
* @throws AttachmentPersistenceException if the modified Task contains two attachments with the
* same id.
* @throws ObjectReferencePersistenceException if the modified Task contains two object references
* with the same id.
* @throws InvalidStateException if an attempt is made to change the owner of the Task and the
* Task is not in state READY.
* @title Update a Task
@ -399,7 +403,7 @@ public class TaskController {
@RequestBody TaskRepresentationModel taskRepresentationModel)
throws TaskNotFoundException, ClassificationNotFoundException, InvalidArgumentException,
ConcurrencyException, NotAuthorizedException, AttachmentPersistenceException,
InvalidStateException {
InvalidStateException, ObjectReferencePersistenceException {
if (!taskId.equals(taskRepresentationModel.getTaskId())) {
throw new InvalidArgumentException(
String.format(

View File

@ -859,6 +859,91 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/
@JsonProperty("por-value-not-like")
private final String[] porValueNotLike;
// endregion
// region secondaryObjectReference
/**
* Filter by the primary object reference of the task. This is an exact match. "sor" is a
* parameter of complex type. Its following attributes from sor[].id to sor[].value can be
* specified according to the description of complex parameters in the overview, e.g.
* sor={"value":"exampleValue"}
*/
@JsonProperty("sor")
private final ObjectReference[] secondaryObjectReferenceIn;
// endregion
// region secondaryObjectReferenceCompany
/**
* Filter by the company of the secondary object reference of the task. This is an exact match.
*/
@JsonProperty("sor-company")
private final String[] sorCompanyIn;
/**
* Filter by the company of the secondary object references of the task. This results in a
* substring search (% is appended to the front and end of the requested value). Further SQL
* "LIKE" wildcard characters will be resolved correctly.
*/
@JsonProperty("sor-company-like")
private final String[] sorCompanyLike;
// endregion
// region secondaryObjectReferenceSystem
/** Filter by the system of the secondary object reference of the task. This is an exact match. */
@JsonProperty("sor-system")
private final String[] sorSystemIn;
/**
* Filter by the system of the secondary object reference of the task. This results in a substring
* search (% is appended to the front and end of the requested value). Further SQL "LIKE" wildcard
* characters will be resolved correctly.
*/
@JsonProperty("sor-system-like")
private final String[] sorSystemLike;
// endregion
// region secondaryObjectReferenceSystemInstance
/**
* Filter by the system instance of the secondary object reference of the task. This is an exact
* match.
*/
@JsonProperty("sor-instance")
private final String[] sorInstanceIn;
/**
* Filter by the system instance of the secondary object reference of the task. This results in a
* substring search (% is appended to the front and end of the requested value). Further SQL
* "LIKE" wildcard characters will be resolved correctly.
*/
@JsonProperty("sor-instance-like")
private final String[] sorInstanceLike;
// endregion
// region secondaryObjectReferenceSystemType
/** Filter by the type of the secondary object reference of the task. This is an exact match. */
@JsonProperty("sor-type")
private final String[] sorTypeIn;
/**
* Filter by the type of the secondary object reference of the task. This results in a substring
* search (% is appended to the front and end of the requested value). Further SQL "LIKE" wildcard
* characters will be resolved correctly.
*/
@JsonProperty("sor-type-like")
private final String[] sorTypeLike;
// endregion
// region primaryObjectReferenceSystemValue
/** Filter by the value of the secondary object reference of the task. This is an exact match. */
@JsonProperty("sor-value")
private final String[] sorValueIn;
/**
* Filter by the value of the secondary object reference of the task. This results in a substring
* search (% is appended to the front and end of the requested value). Further SQL "LIKE" wildcard
* characters will be resolved correctly.
*/
@JsonProperty("sor-value-like")
private final String[] sorValueLike;
// endregion
// region read
/** Filter by the is read flag of the task. This is an exact match. */
@ -1527,6 +1612,17 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
"por-value-not",
"por-value-like",
"por-value-not-like",
"sor",
"sor-company",
"sor-company-like",
"sor-system",
"sor-system-like",
"sor-instance",
"sor-instance-like",
"sor-type",
"sor-type-like",
"sor-value",
"sor-value-like",
"is-read",
"is-transferred",
"attachment-classification-id",
@ -1725,6 +1821,17 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
String[] porValueNotIn,
String[] porValueLike,
String[] porValueNotLike,
ObjectReference[] secondaryObjectReferenceIn,
String[] sorCompanyIn,
String[] sorCompanyLike,
String[] sorSystemIn,
String[] sorSystemLike,
String[] sorInstanceIn,
String[] sorInstanceLike,
String[] sorTypeIn,
String[] sorTypeLike,
String[] sorValueIn,
String[] sorValueLike,
Boolean isRead,
Boolean isTransferred,
String[] attachmentClassificationIdIn,
@ -1922,6 +2029,17 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
this.porValueNotIn = porValueNotIn;
this.porValueLike = porValueLike;
this.porValueNotLike = porValueNotLike;
this.secondaryObjectReferenceIn = secondaryObjectReferenceIn;
this.sorCompanyIn = sorCompanyIn;
this.sorCompanyLike = sorCompanyLike;
this.sorSystemIn = sorSystemIn;
this.sorSystemLike = sorSystemLike;
this.sorInstanceIn = sorInstanceIn;
this.sorInstanceLike = sorInstanceLike;
this.sorTypeIn = sorTypeIn;
this.sorTypeLike = sorTypeLike;
this.sorValueIn = sorValueIn;
this.sorValueLike = sorValueLike;
this.isRead = isRead;
this.isTransferred = isTransferred;
this.attachmentClassificationIdIn = attachmentClassificationIdIn;
@ -2261,6 +2379,31 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
.map(this::wrapElementsInLikeStatement)
.ifPresent(query::primaryObjectReferenceValueNotLike);
Optional.ofNullable(secondaryObjectReferenceIn).ifPresent(query::secondaryObjectReferenceIn);
Optional.ofNullable(sorCompanyIn).ifPresent(query::sorCompanyIn);
Optional.ofNullable(sorCompanyLike)
.map(this::wrapElementsInLikeStatement)
.ifPresent(query::sorCompanyLike);
Optional.ofNullable(sorSystemIn).ifPresent(query::sorSystemIn);
Optional.ofNullable(sorSystemLike)
.map(this::wrapElementsInLikeStatement)
.ifPresent(query::sorSystemLike);
Optional.ofNullable(sorInstanceIn).ifPresent(query::sorSystemInstanceIn);
Optional.ofNullable(sorInstanceLike)
.map(this::wrapElementsInLikeStatement)
.ifPresent(query::sorSystemInstanceLike);
Optional.ofNullable(sorTypeIn).ifPresent(query::sorTypeIn);
Optional.ofNullable(sorTypeLike)
.map(this::wrapElementsInLikeStatement)
.ifPresent(query::sorTypeLike);
Optional.ofNullable(sorValueIn).ifPresent(query::sorValueIn);
Optional.ofNullable(sorValueLike)
.map(this::wrapElementsInLikeStatement)
.ifPresent(query::sorValueLike);
Optional.ofNullable(isRead).ifPresent(query::readEquals);
Optional.ofNullable(isTransferred).ifPresent(query::transferredEquals);

View File

@ -5,6 +5,7 @@ import org.springframework.lang.NonNull;
import org.springframework.stereotype.Controller;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
import pro.taskana.task.rest.models.ObjectReferenceRepresentationModel;
@Controller
@ -16,6 +17,7 @@ public class ObjectReferenceRepresentationModelAssembler
public ObjectReferenceRepresentationModel toModel(@NonNull ObjectReference entity) {
ObjectReferenceRepresentationModel repModel = new ObjectReferenceRepresentationModel();
repModel.setId(entity.getId());
repModel.setTaskId(entity.getTaskId());
repModel.setCompany(entity.getCompany());
repModel.setSystem(entity.getSystem());
repModel.setSystemInstance(entity.getSystemInstance());
@ -25,8 +27,9 @@ public class ObjectReferenceRepresentationModelAssembler
}
public ObjectReference toEntity(ObjectReferenceRepresentationModel repModel) {
ObjectReference objectReference = new ObjectReference();
ObjectReferenceImpl objectReference = new ObjectReferenceImpl();
objectReference.setId(repModel.getId());
objectReference.setTaskId(repModel.getTaskId());
objectReference.setCompany(repModel.getCompany());
objectReference.setSystem(repModel.getSystem());
objectReference.setSystemInstance(repModel.getSystemInstance());

View File

@ -74,6 +74,10 @@ public class TaskRepresentationModelAssembler
repModel.setOwner(task.getOwner());
repModel.setOwnerLongName(task.getOwnerLongName());
repModel.setPrimaryObjRef(objectReferenceAssembler.toModel(task.getPrimaryObjRef()));
repModel.setSecondaryObjectReferences(
task.getSecondaryObjectReferences().stream()
.map(objectReferenceAssembler::toModel)
.collect(Collectors.toList()));
repModel.setRead(task.isRead());
repModel.setTransferred(task.isTransferred());
repModel.setAttachments(
@ -164,6 +168,10 @@ public class TaskRepresentationModelAssembler
repModel.getAttachments().stream()
.map(attachmentAssembler::toEntityModel)
.collect(Collectors.toList()));
task.setSecondaryObjectReferences(
repModel.getSecondaryObjectReferences().stream()
.map(objectReferenceAssembler::toEntity)
.collect(Collectors.toList()));
task.setCustomAttributeMap(
repModel.getCustomAttributes().stream()
.collect(Collectors.toMap(CustomAttribute::getKey, CustomAttribute::getValue)));

View File

@ -75,6 +75,10 @@ public class TaskSummaryRepresentationModelAssembler
repModel.setOwner(taskSummary.getOwner());
repModel.setOwnerLongName(taskSummary.getOwnerLongName());
repModel.setPrimaryObjRef(objectReferenceAssembler.toModel(taskSummary.getPrimaryObjRef()));
repModel.setSecondaryObjectReferences(
taskSummary.getSecondaryObjectReferences().stream()
.map(objectReferenceAssembler::toModel)
.collect(Collectors.toList()));
repModel.setRead(taskSummary.isRead());
repModel.setTransferred(taskSummary.isTransferred());
repModel.setAttachmentSummaries(
@ -128,6 +132,10 @@ public class TaskSummaryRepresentationModelAssembler
taskSummary.setOwner(repModel.getOwner());
taskSummary.setOwnerLongName(repModel.getOwnerLongName());
taskSummary.setPrimaryObjRef(objectReferenceAssembler.toEntity(repModel.getPrimaryObjRef()));
taskSummary.setSecondaryObjectReferences(
repModel.getSecondaryObjectReferences().stream()
.map(objectReferenceAssembler::toEntity)
.collect(Collectors.toList()));
taskSummary.setRead(repModel.isRead());
taskSummary.setTransferred(repModel.isTransferred());
taskSummary.setAttachmentSummaries(

View File

@ -7,6 +7,9 @@ public class ObjectReferenceRepresentationModel
/** Unique ID. */
private String id;
/** Task Id. */
private String taskId;
/** The company the referenced primary object belongs to. */
private String company;
/** The (kind of) system, the referenced primary object resides in (e.g. SAP, MySystem A, ...). */
@ -26,6 +29,14 @@ public class ObjectReferenceRepresentationModel
this.id = id;
}
public String getTaskId() {
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
public String getCompany() {
return company;
}

View File

@ -106,6 +106,8 @@ public class TaskSummaryRepresentationModel
protected String custom15;
/** A custom property with name "16". */
protected String custom16;
/** Secondary object references of the task. */
protected List<ObjectReferenceRepresentationModel> secondaryObjectReferences = new ArrayList<>();
/** The attachment summaries of this task. */
private List<AttachmentSummaryRepresentationModel> attachmentSummaries = new ArrayList<>();
@ -286,6 +288,15 @@ public class TaskSummaryRepresentationModel
this.primaryObjRef = primaryObjRef;
}
public List<ObjectReferenceRepresentationModel> getSecondaryObjectReferences() {
return secondaryObjectReferences;
}
public void setSecondaryObjectReferences(
List<ObjectReferenceRepresentationModel> secondaryObjectReferences) {
this.secondaryObjectReferences = secondaryObjectReferences;
}
public boolean isRead() {
return isRead;
}

View File

@ -239,6 +239,51 @@ class TaskControllerIntTest {
assertThat(response.getBody().getContent()).hasSize(4);
}
@Test
void should_ReturnAllTasks_For_ProvidedSecondaryObjectReferenceByTypeAndValue() throws Exception {
String url =
restHelper.toUrl(RestEndpoints.URL_TASKS)
+ "?sor="
+ URLEncoder.encode("{\"type\":\"Type2\",\"value\":\"Value2\"}", "UTF-8");
HttpEntity<Object> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
ResponseEntity<TaskSummaryPagedRepresentationModel> response =
TEMPLATE.exchange(url, HttpMethod.GET, auth, TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getContent()).hasSize(2);
}
@Test
void should_ReturnAllTasks_For_ProvidedSecondaryObjectReferenceByCompany() throws Exception {
String url =
restHelper.toUrl(RestEndpoints.URL_TASKS)
+ "?sor="
+ URLEncoder.encode("{\"company\":\"Company3\"}", "UTF-8");
HttpEntity<Object> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
ResponseEntity<TaskSummaryPagedRepresentationModel> response =
TEMPLATE.exchange(url, HttpMethod.GET, auth, TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getContent()).hasSize(1);
}
@Test
void should_ReturnNoTasks_For_ProvidedNonexistentSecondaryObjectReference() throws Exception {
String url =
restHelper.toUrl(RestEndpoints.URL_TASKS)
+ "?sor="
+ URLEncoder.encode("{\"type\":\"Type2\",\"value\":\"Quatsch\"}", "UTF-8");
HttpEntity<Object> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
ResponseEntity<TaskSummaryPagedRepresentationModel> response =
TEMPLATE.exchange(url, HttpMethod.GET, auth, TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getContent()).isEmpty();
}
@Test
void should_ReturnAllTasksByWildcardSearch_For_ProvidedSearchValue() {
String url =
@ -579,6 +624,89 @@ class TaskControllerIntTest {
assertThat(repModel.getAttachments()).isNotEmpty();
}
@Test
void should_NotGetEmptyObjectReferencesList_When_GettingTaskWithObjectReferences() {
String url =
restHelper.toUrl(RestEndpoints.URL_TASKS_ID, "TKI:000000000000000000000000000000000001");
HttpEntity<Object> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("admin"));
ResponseEntity<TaskRepresentationModel> response =
TEMPLATE.exchange(url, HttpMethod.GET, auth, TASK_MODEL_TYPE);
TaskRepresentationModel repModel = response.getBody();
assertThat(repModel).isNotNull();
assertThat(repModel.getSecondaryObjectReferences()).isNotEmpty();
}
@Test
void should_ReturnFilteredTasks_WhenGettingTasksBySecondaryObjectReferenceValue() {
String url = restHelper.toUrl(RestEndpoints.URL_TASKS) + "?sor-value=Value2";
HttpEntity<Object> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
ResponseEntity<TaskSummaryPagedRepresentationModel> response =
TEMPLATE.exchange(url, HttpMethod.GET, auth, TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getContent()).hasSize(3);
}
@Test
void should_ReturnFilteredTasks_WhenGettingTasksBySecondaryObjectReferenceTypeLike() {
String url = restHelper.toUrl(RestEndpoints.URL_TASKS) + "?sor-type-like=Type";
HttpEntity<Object> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
ResponseEntity<TaskSummaryPagedRepresentationModel> response =
TEMPLATE.exchange(url, HttpMethod.GET, auth, TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getContent()).hasSize(3);
}
@Test
void should_ReturnFilteredTasks_WhenGettingTasksBySecondaryObjectReferenceValueAndCompany() {
String url =
restHelper.toUrl(RestEndpoints.URL_TASKS) + "?sor-value=Value2&&sor-company=Company1";
HttpEntity<Object> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
ResponseEntity<TaskSummaryPagedRepresentationModel> response =
TEMPLATE.exchange(url, HttpMethod.GET, auth, TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getContent()).hasSize(1);
}
@Test
void should_CreateAndDeleteTaskWithObjectReferences_WhenSpecifyingObjectReferences() {
TaskRepresentationModel taskRepresentationModel = getTaskResourceSample();
ObjectReferenceRepresentationModel obj0 = getSampleSecondaryObjectReference("0");
obj0.setTaskId(taskRepresentationModel.getTaskId());
ObjectReferenceRepresentationModel obj1 = getSampleSecondaryObjectReference("1");
obj1.setTaskId(taskRepresentationModel.getTaskId());
List<ObjectReferenceRepresentationModel> secondaryObjectReferences = List.of(obj0, obj1);
taskRepresentationModel.setSecondaryObjectReferences(secondaryObjectReferences);
String url = restHelper.toUrl(RestEndpoints.URL_TASKS);
HttpEntity<TaskRepresentationModel> auth =
new HttpEntity<>(taskRepresentationModel, RestHelper.generateHeadersForUser("teamlead-1"));
ResponseEntity<TaskRepresentationModel> responseCreate =
TEMPLATE.exchange(url, HttpMethod.POST, auth, TASK_MODEL_TYPE);
assertThat(responseCreate.getStatusCode()).isEqualTo(HttpStatus.CREATED);
assertThat(responseCreate.getBody()).isNotNull();
String taskIdOfCreatedTask = responseCreate.getBody().getTaskId();
String url2 = restHelper.toUrl(RestEndpoints.URL_TASKS_ID, taskIdOfCreatedTask);
HttpEntity<Object> auth2 = new HttpEntity<>(RestHelper.generateHeadersForUser("admin"));
ResponseEntity<TaskRepresentationModel> responseDeleted =
TEMPLATE.exchange(
url2, HttpMethod.DELETE, auth2, ParameterizedTypeReference.forType(Void.class));
assertThat(responseDeleted.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
}
@Test
void should_ReturnReceivedDate_When_GettingTask() {
String url =
@ -1029,4 +1157,14 @@ class TaskControllerIntTest {
taskRepresentationModel.setPrimaryObjRef(objectReference);
return taskRepresentationModel;
}
private ObjectReferenceRepresentationModel getSampleSecondaryObjectReference(String suffix) {
ObjectReferenceRepresentationModel objectReference = new ObjectReferenceRepresentationModel();
objectReference.setCompany("SecondaryCompany" + suffix);
objectReference.setSystem("SecondarySystem" + suffix);
objectReference.setSystemInstance("SecondaryInstance" + suffix);
objectReference.setType("SecondaryType" + suffix);
objectReference.setValue("0000000" + suffix);
return objectReference;
}
}

View File

@ -16,8 +16,8 @@ import pro.taskana.common.test.rest.RestHelper;
import pro.taskana.common.test.security.JaasExtension;
import pro.taskana.common.test.security.WithAccessId;
import pro.taskana.task.api.TaskService;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.api.models.Task;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
import pro.taskana.task.rest.assembler.TaskRepresentationModelAssembler;
import pro.taskana.task.rest.models.TaskRepresentationModel;
@ -106,7 +106,7 @@ class TaskControllerRestDocTest extends BaseRestDocTest {
@Test
void createTaskDocTest() throws Exception {
final Task task = taskService.newTask("WBI:100000000000000000000000000000000004");
ObjectReference objectReference = new ObjectReference();
ObjectReferenceImpl objectReference = new ObjectReferenceImpl();
objectReference.setCompany("MyCompany1");
objectReference.setSystem("MySystem1");
objectReference.setSystemInstance("MyInstance1");
@ -114,6 +114,7 @@ class TaskControllerRestDocTest extends BaseRestDocTest {
objectReference.setValue("00000001");
task.setPrimaryObjRef(objectReference);
task.setClassificationKey("L11010");
task.addSecondaryObjectReference("company", "system", "systemInstance", "type", "value");
TaskRepresentationModel repModel = assembler.toModel(task);
mockMvc
.perform(post(RestEndpoints.URL_TASKS).content(objectMapper.writeValueAsString(repModel)))

View File

@ -13,8 +13,8 @@ import pro.taskana.classification.rest.models.ClassificationSummaryRepresentatio
import pro.taskana.common.test.rest.TaskanaSpringBootTest;
import pro.taskana.task.api.TaskService;
import pro.taskana.task.api.models.Attachment;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.internal.models.AttachmentImpl;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
import pro.taskana.task.rest.models.AttachmentRepresentationModel;
import pro.taskana.task.rest.models.ObjectReferenceRepresentationModel;
@ -64,7 +64,7 @@ class AttachmentRepresentationModelAssemblerTest {
@Test
void should_ReturnRepresentationModel_When_ConvertingEntityToRepresentationModel() {
AttachmentImpl attachment = (AttachmentImpl) taskService.newAttachment();
ObjectReference reference = new ObjectReference();
ObjectReferenceImpl reference = new ObjectReferenceImpl();
ClassificationSummary summary =
classService.newClassification("ckey", "cdomain", "MANUAL").asSummary();
reference.setId("abc");
@ -87,7 +87,7 @@ class AttachmentRepresentationModelAssemblerTest {
@Test
void should_Equal_When_ComparingEntityWithConvertedEntity() {
AttachmentImpl attachment = (AttachmentImpl) taskService.newAttachment();
ObjectReference reference = new ObjectReference();
ObjectReferenceImpl reference = new ObjectReferenceImpl();
ClassificationSummary summary =
classService.newClassification("ckey", "cdomain", "MANUAL").asSummary();
reference.setId("abc");

View File

@ -12,8 +12,8 @@ import pro.taskana.classification.rest.models.ClassificationSummaryRepresentatio
import pro.taskana.common.test.rest.TaskanaSpringBootTest;
import pro.taskana.task.api.TaskService;
import pro.taskana.task.api.models.AttachmentSummary;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.internal.models.AttachmentSummaryImpl;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
import pro.taskana.task.rest.models.AttachmentSummaryRepresentationModel;
import pro.taskana.task.rest.models.ObjectReferenceRepresentationModel;
@ -63,7 +63,7 @@ class AttachmentSummaryRepresentationModelAssemblerTest {
void should_ReturnRepresentationModel_When_ConvertingEntityToRepresentationModel() {
AttachmentSummaryImpl attachment =
(AttachmentSummaryImpl) taskService.newAttachment().asSummary();
ObjectReference reference = new ObjectReference();
ObjectReferenceImpl reference = new ObjectReferenceImpl();
ClassificationSummary summary =
classService.newClassification("ckey", "cdomain", "MANUAL").asSummary();
reference.setId("abc");
@ -86,7 +86,7 @@ class AttachmentSummaryRepresentationModelAssemblerTest {
void should_Equal_When_ComparingEntityWithConvertedEntity() {
AttachmentSummaryImpl attachment =
(AttachmentSummaryImpl) taskService.newAttachment().asSummary();
ObjectReference reference = new ObjectReference();
ObjectReferenceImpl reference = new ObjectReferenceImpl();
ClassificationSummary summary =
classService.newClassification("ckey", "cdomain", "MANUAL").asSummary();
reference.setId("abc");

View File

@ -7,6 +7,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import pro.taskana.common.test.rest.TaskanaSpringBootTest;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
import pro.taskana.task.rest.models.ObjectReferenceRepresentationModel;
@TaskanaSpringBootTest
@ -37,7 +38,7 @@ class ObjectReferenceRepresentationModelAssemblerTest {
@Test
void should_ReturnRepresentationModel_When_ConvertingEntityToRepresentationModel() {
ObjectReference entity = new ObjectReference();
ObjectReferenceImpl entity = new ObjectReferenceImpl();
entity.setId("id");
entity.setValue("value");
entity.setType("type");

View File

@ -18,9 +18,9 @@ import pro.taskana.task.api.TaskCustomField;
import pro.taskana.task.api.TaskService;
import pro.taskana.task.api.TaskState;
import pro.taskana.task.api.models.Attachment;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.api.models.Task;
import pro.taskana.task.internal.models.AttachmentImpl;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
import pro.taskana.task.internal.models.TaskImpl;
import pro.taskana.task.rest.models.AttachmentRepresentationModel;
import pro.taskana.task.rest.models.ObjectReferenceRepresentationModel;
@ -152,7 +152,7 @@ class TaskRepresentationModelAssemblerTest {
void should_ReturnRepresentationModel_When_ConvertingEntityToRepresentationModel()
throws Exception {
// given
ObjectReference primaryObjRef = new ObjectReference();
ObjectReferenceImpl primaryObjRef = new ObjectReferenceImpl();
primaryObjRef.setId("abc");
final Workbasket workbasket = workbasketService.newWorkbasket("key", "domain");
ClassificationSummary classification =
@ -215,7 +215,7 @@ class TaskRepresentationModelAssemblerTest {
@Test
void should_Equal_When_ComparingEntityWithConvertedEntity() throws InvalidArgumentException {
// given
ObjectReference primaryObjRef = new ObjectReference();
ObjectReferenceImpl primaryObjRef = new ObjectReferenceImpl();
primaryObjRef.setId("abc");
final WorkbasketSummary workbasket =
workbasketService.newWorkbasket("key", "domain").asSummary();

View File

@ -30,9 +30,9 @@ import pro.taskana.common.test.rest.TaskanaSpringBootTest;
import pro.taskana.task.api.TaskService;
import pro.taskana.task.api.TaskState;
import pro.taskana.task.api.models.AttachmentSummary;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.api.models.TaskSummary;
import pro.taskana.task.internal.models.AttachmentSummaryImpl;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
import pro.taskana.task.internal.models.TaskSummaryImpl;
import pro.taskana.task.rest.models.AttachmentRepresentationModel;
import pro.taskana.task.rest.models.AttachmentSummaryRepresentationModel;
@ -66,7 +66,7 @@ class TaskSummaryRepresentationModelAssemblerTest {
@Test
void should_ReturnRepresentationModel_When_ConvertingEntityToRepresentationModel()
throws Exception {
ObjectReference primaryObjRef = new ObjectReference();
ObjectReferenceImpl primaryObjRef = new ObjectReferenceImpl();
primaryObjRef.setId("abc");
ClassificationSummary classification =
this.classificationService.newClassification("ckey", "cdomain", "MANUAL").asSummary();
@ -222,7 +222,7 @@ class TaskSummaryRepresentationModelAssemblerTest {
@Test
void should_Equal_When_ComparingEntityWithConvertedEntity() {
// given
ObjectReference primaryObjRef = new ObjectReference();
ObjectReferenceImpl primaryObjRef = new ObjectReferenceImpl();
primaryObjRef.setId("abc");
final WorkbasketSummary workbasket =
workbasketService.newWorkbasket("key", "domain").asSummary();
@ -335,7 +335,7 @@ class TaskSummaryRepresentationModelAssemblerTest {
private static void testEqualityAttachments(
List<AttachmentSummary> attachmentSummaries,
List<AttachmentSummaryRepresentationModel> resources) {
assertThat(attachmentSummaries.size()).isEqualTo(resources.size());
assertThat(attachmentSummaries).hasSameSizeAs(resources);
for (int i = 0; i < resources.size(); ++i) {
AttachmentSummaryRepresentationModel resource = resources.get(i);

View File

@ -10,6 +10,7 @@ import pro.taskana.common.internal.configuration.DbSchemaCreator;
import pro.taskana.common.test.config.DataSourceGenerator;
import pro.taskana.sampledata.SampleDataGenerator;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.internal.models.ObjectReferenceImpl;
public abstract class AbstractAccTest {
@ -45,7 +46,7 @@ public abstract class AbstractAccTest {
protected ObjectReference createObjectReference(
String company, String system, String systemInstance, String type, String value) {
ObjectReference objectReference = new ObjectReference();
ObjectReferenceImpl objectReference = new ObjectReferenceImpl();
objectReference.setCompany(company);
objectReference.setSystem(system);
objectReference.setSystemInstance(systemInstance);

View File

@ -6,12 +6,12 @@ import { TaskService } from 'app/workplace/services/task.service';
import { Task } from 'app/workplace/models/task';
import { RequestInProgressService } from 'app/shared/services/request-in-progress/request-in-progress.service';
import { TaskanaDate } from 'app/shared/util/taskana.date';
import { ObjectReference } from 'app/workplace/models/object-reference';
import { Workbasket } from 'app/shared/models/workbasket';
import { WorkplaceService } from 'app/workplace/services/workplace.service';
import { MasterAndDetailService } from 'app/shared/services/master-and-detail/master-and-detail.service';
import { NotificationService } from '../../../shared/services/notifications/notification.service';
import { take, takeUntil } from 'rxjs/operators';
import { ObjectReference } from '../../models/object-reference';
@Component({
selector: 'taskana-task-details',
@ -186,7 +186,10 @@ export class TaskDetailsComponent implements OnInit, OnDestroy {
this.task = task;
this.taskService.selectTask(this.task);
this.taskService.publishUpdatedTask(task);
this.router.navigate([`../${task.taskId}`], { relativeTo: this.route, queryParamsHandling: 'merge' });
this.router.navigate([`../${task.taskId}`], {
relativeTo: this.route,
queryParamsHandling: 'merge'
});
},
() => {
this.requestInProgressService.setRequestInProgress(false);

View File

@ -5,7 +5,7 @@ import { ClassificationSummary } from '../../shared/models/classification-summar
export class Task {
constructor(
public taskId: string,
public primaryObjRef: ObjectReference = new ObjectReference(),
public primaryObjRef?: ObjectReference,
public workbasketSummary?: Workbasket,
public classificationSummary?: ClassificationSummary,
public businessProcessId?: string,