Task-1259: Refactoring of assembler classes

This commit is contained in:
Christopher Heiting 2020-05-25 10:16:22 +02:00 committed by Mustapha Zorgati
parent 3dc5377c75
commit 0442dc54b4
36 changed files with 885 additions and 928 deletions

View File

@ -8,14 +8,13 @@ import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.LongStream;
import java.util.stream.Stream;
import java.util.stream.LongStream.Builder;
import pro.taskana.common.api.CustomHoliday;
import pro.taskana.common.api.exceptions.InvalidArgumentException;
@ -37,6 +36,15 @@ public final class WorkingDaysToDaysConverter {
private static boolean germanHolidaysEnabled;
private static boolean corpusChristiEnabled; // Fronleichnam
private static Set<CustomHoliday> customHolidays = new HashSet<>();
private static Set<CustomHoliday> germanHolidays =
new HashSet<>(
Arrays.asList(
CustomHoliday.of(1, 1), // new year
CustomHoliday.of(1, 5), // labour day
CustomHoliday.of(3, 10), // german unity
CustomHoliday.of(25, 12), // Christmas
CustomHoliday.of(26, 12) // Christmas
));
private Instant referenceDate;
private LocalDate easterSunday;
@ -127,7 +135,7 @@ public final class WorkingDaysToDaysConverter {
return instant.plus(Duration.ofDays(days));
}
/** counts working days between two dates, inclusive for both margins. */
/** counts working days between two dates, exclusive for both margins. */
public boolean hasWorkingDaysInBetween(Instant left, Instant right) {
long days = Duration.between(left, right).abs().toDays();
Instant firstInstant = left.isBefore(right) ? left : right;
@ -155,28 +163,25 @@ public final class WorkingDaysToDaysConverter {
}
public boolean isGermanHoliday(LocalDate date) {
// Fix and movable holidays that are valid throughout Germany: New years day, Labour Day, Day of
// German
// Unity, Christmas,
if (Stream.of(GermanFixHolidays.values()).anyMatch(day -> day.matches(date))) {
if (germanHolidays.contains(CustomHoliday.of(date.getDayOfMonth(), date.getMonthValue()))) {
return true;
}
// Easter holidays Good Friday, Easter Monday, Ascension Day, Whit Monday.
long diffFromEasterSunday = DAYS.between(easterSunday, date);
List<Long> offSets =
new ArrayList<>(
Arrays.asList(
OFFSET_GOOD_FRIDAY,
OFFSET_EASTER_MONDAY,
OFFSET_ASCENSION_DAY,
OFFSET_WHIT_MONDAY));
Builder builder =
LongStream.builder()
.add(OFFSET_GOOD_FRIDAY)
.add(OFFSET_EASTER_MONDAY)
.add(OFFSET_ASCENSION_DAY)
.add(OFFSET_WHIT_MONDAY);
if (corpusChristiEnabled) {
offSets.add(OFFSET_CORPUS_CHRISTI);
builder.add(OFFSET_CORPUS_CHRISTI);
}
return offSets.contains(diffFromEasterSunday);
return builder.build().anyMatch(c -> c == diffFromEasterSunday);
}
/**
@ -208,14 +213,6 @@ public final class WorkingDaysToDaysConverter {
return LocalDate.of(year, 3, 22).plusDays((long) d + e);
}
private int calculateDirection(long numberOfDays, ZeroDirection zeroDirection) {
if (numberOfDays == 0) {
return zeroDirection.getDirection();
} else {
return numberOfDays >= 0 ? 1 : -1;
}
}
void refreshReferenceDate(Instant newReferenceDate) {
int yearOfReferenceDate =
LocalDateTime.ofInstant(referenceDate, ZoneId.systemDefault()).getYear();
@ -227,14 +224,21 @@ public final class WorkingDaysToDaysConverter {
this.referenceDate = newReferenceDate;
}
private int calculateDirection(long numberOfDays, ZeroDirection zeroDirection) {
if (numberOfDays == 0) {
return zeroDirection.getDirection();
} else {
return numberOfDays >= 0 ? 1 : -1;
}
}
@Override
public String toString() {
return "WorkingDaysToDaysConverter{"
+ "dateCreated="
return "WorkingDaysToDaysConverter [referenceDate="
+ referenceDate
+ ", easterSunday="
+ easterSunday
+ '}';
+ "]";
}
private enum ZeroDirection {
@ -251,25 +255,4 @@ public final class WorkingDaysToDaysConverter {
return direction;
}
}
/** Enumeration of German holidays. */
private enum GermanFixHolidays {
NEWYEAR(1, 1),
LABOURDAY(5, 1),
GERMANUNITY(10, 3),
CHRISTMAS1(12, 25),
CHRISTMAS2(12, 26);
private final int month;
private final int day;
GermanFixHolidays(int month, int day) {
this.month = month;
this.day = day;
}
public boolean matches(LocalDate date) {
return date.getDayOfMonth() == day && date.getMonthValue() == month;
}
}
}

View File

@ -20,13 +20,13 @@ INSERT INTO WORKBASKET VALUES ('WBI:100000000000000000000000000000000014', 'USER
INSERT INTO WORKBASKET VALUES ('WBI:100000000000000000000000000000000015', 'USER_3_2' , RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'PPK User 2 KSC 1 Domain B', 'DOMAIN_B', 'PERSONAL', 'PPK User 1 KSC 1 Domain B' , 'owner0815' , 'ABCABC' , 'cust2' , 'cust3' , 'cust4' , 'orgl1' , 'orgl2' , 'orgl3' , 'orgl4' , false );
-- Workbaskets for sorting test
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000900', 'sort001' , RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'basxet0' , 'DOM_XY' , 'TOPIC' , 'Lorem ipsum dolor sit amet.', 'Max' , '' , '' , '' , '' , '' , '' , '' , '' , false );
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000901', 'Sort002' , RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'Basxet1' , 'DOM_XY' , 'TOPIC' , 'Lorem ipsum dolor sit amet.', 'Max' , '' , '' , '' , '' , '' , '' , '' , '' , false );
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000902', 'sOrt003' , RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'bAsxet2' , 'DOM_XY' , 'TOPIC' , 'Lorem ipsum dolor sit amet.', 'Max' , '' , '' , '' , '' , '' , '' , '' , '' , false );
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000903', 'soRt004' , RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'baSxet3' , 'DOM_XY' , 'TOPIC' , 'Lorem ipsum dolor sit amet.', 'Max' , '' , '' , '' , '' , '' , '' , '' , '' , false );
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000904', 'sorT005' , RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'basXet4' , 'DOM_XY' , 'TOPIC' , 'Lorem ipsum dolor sit amet.', 'Max' , '' , '' , '' , '' , '' , '' , '' , '' , false );
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000905', 'Sort006' , RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'basxEt5' , 'DOM_XY' , 'TOPIC' , 'Lorem ipsum dolor sit amet.', 'Max' , '' , '' , '' , '' , '' , '' , '' , '' , false );
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000906', 'SOrt007' , RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'basxeT6' , 'DOM_XY' , 'TOPIC' , 'Lorem ipsum dolor sit amet.', 'Max' , '' , '' , '' , '' , '' , '' , '' , '' , false );
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000907', 'SoRt008' , RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'BAsxet7' , 'DOM_XY' , 'TOPIC' , 'Lorem ipsum dolor sit amet.', 'Max' , '' , '' , '' , '' , '' , '' , '' , '' , false );
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000908', 'SorT009' , RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'BaSxet8' , 'DOM_XY' , 'TOPIC' , 'Lorem ipsum dolor sit amet.', 'Max' , '' , '' , '' , '' , '' , '' , '' , '' , false );
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000909', 'Sort010' , RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'BasXet9' , 'DOM_XY' , 'TOPIC' , 'Lorem ipsum dolor sit amet.', 'Max' , '' , '' , '' , '' , '' , '' , '' , '' , false );
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000900', 'sort001' , RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'basxet0' , 'DOMAIN_A' , 'TOPIC' , 'Lorem ipsum dolor sit amet.', 'Max' , '' , '' , '' , '' , '' , '' , '' , '' , false );
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000901', 'Sort002' , RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'Basxet1' , 'DOMAIN_A' , 'TOPIC' , 'Lorem ipsum dolor sit amet.', 'Max' , '' , '' , '' , '' , '' , '' , '' , '' , false );
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000902', 'sOrt003' , RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'bAsxet2' , 'DOMAIN_A' , 'TOPIC' , 'Lorem ipsum dolor sit amet.', 'Max' , '' , '' , '' , '' , '' , '' , '' , '' , false );
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000903', 'soRt004' , RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'baSxet3' , 'DOMAIN_A' , 'TOPIC' , 'Lorem ipsum dolor sit amet.', 'Max' , '' , '' , '' , '' , '' , '' , '' , '' , false );
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000904', 'sorT005' , RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'basXet4' , 'DOMAIN_A' , 'TOPIC' , 'Lorem ipsum dolor sit amet.', 'Max' , '' , '' , '' , '' , '' , '' , '' , '' , false );
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000905', 'Sort006' , RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'basxEt5' , 'DOMAIN_A' , 'TOPIC' , 'Lorem ipsum dolor sit amet.', 'Max' , '' , '' , '' , '' , '' , '' , '' , '' , false );
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000906', 'SOrt007' , RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'basxeT6' , 'DOMAIN_A' , 'TOPIC' , 'Lorem ipsum dolor sit amet.', 'Max' , '' , '' , '' , '' , '' , '' , '' , '' , false );
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000907', 'SoRt008' , RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'BAsxet7' , 'DOMAIN_A' , 'TOPIC' , 'Lorem ipsum dolor sit amet.', 'Max' , '' , '' , '' , '' , '' , '' , '' , '' , false );
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000908', 'SorT009' , RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'BaSxet8' , 'DOMAIN_A' , 'TOPIC' , 'Lorem ipsum dolor sit amet.', 'Max' , '' , '' , '' , '' , '' , '' , '' , '' , false );
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000909', 'Sort010' , RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'BasXet9' , 'DOMAIN_A' , 'TOPIC' , 'Lorem ipsum dolor sit amet.', 'Max' , '' , '' , '' , '' , '' , '' , '' , '' , false );

View File

@ -18,13 +18,13 @@ INSERT INTO WORKBASKET VALUES ('WBI:100000000000000000000000000000000014', 'USER
INSERT INTO WORKBASKET VALUES ('WBI:100000000000000000000000000000000015', 'USER_3_2', RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'PPK User 2 KSC 1 Domain B', 'DOMAIN_B', 'PERSONAL', 'PPK User 1 KSC 1 Domain B', 'owner0815', 'ABCABC', 'cust2', 'cust3', 'cust4', 'orgl1', 'orgl2', 'orgl3', 'orgl4', FALSE);
-- Workbaskets for sorting test
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000900', 'sort001', RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'basxet0', 'DOM_XY', 'TOPIC', 'Lorem ipsum dolor sit amet.', 'Max', '', '', '', '', '', '', '', '', FALSE);
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000901', 'Sort002', RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'Basxet1', 'DOM_XY', 'TOPIC', 'Lorem ipsum dolor sit amet.', 'Max', '', '', '', '', '', '', '', '', FALSE);
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000902', 'sOrt003', RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'bAsxet2', 'DOM_XY', 'TOPIC', 'Lorem ipsum dolor sit amet.', 'Max', '', '', '', '', '', '', '', '', FALSE);
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000903', 'soRt004', RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'baSxet3', 'DOM_XY', 'TOPIC', 'Lorem ipsum dolor sit amet.', 'Max', '', '', '', '', '', '', '', '', FALSE);
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000904', 'sorT005', RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'basXet4', 'DOM_XY', 'TOPIC', 'Lorem ipsum dolor sit amet.', 'Max', '', '', '', '', '', '', '', '', FALSE);
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000905', 'Sort006', RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'basxEt5', 'DOM_XY', 'TOPIC', 'Lorem ipsum dolor sit amet.', 'Max', '', '', '', '', '', '', '', '', FALSE);
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000906', 'SOrt007', RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'basxeT6', 'DOM_XY', 'TOPIC', 'Lorem ipsum dolor sit amet.', 'Max', '', '', '', '', '', '', '', '', FALSE);
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000907', 'SoRt008', RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'BAsxet7', 'DOM_XY', 'TOPIC', 'Lorem ipsum dolor sit amet.', 'Max', '', '', '', '', '', '', '', '', FALSE);
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000908', 'SorT009', RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'BaSxet8', 'DOM_XY', 'TOPIC', 'Lorem ipsum dolor sit amet.', 'Max', '', '', '', '', '', '', '', '', FALSE);
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000909', 'Sort010', RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'BasXet9', 'DOM_XY', 'TOPIC', 'Lorem ipsum dolor sit amet.', 'Max', '', '', '', '', '', '', '', '', FALSE);
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000900', 'sort001', RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'basxet0', 'DOMAIN_A', 'TOPIC', 'Lorem ipsum dolor sit amet.', 'Max', '', '', '', '', '', '', '', '', FALSE);
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000901', 'Sort002', RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'Basxet1', 'DOMAIN_A', 'TOPIC', 'Lorem ipsum dolor sit amet.', 'Max', '', '', '', '', '', '', '', '', FALSE);
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000902', 'sOrt003', RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'bAsxet2', 'DOMAIN_A', 'TOPIC', 'Lorem ipsum dolor sit amet.', 'Max', '', '', '', '', '', '', '', '', FALSE);
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000903', 'soRt004', RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'baSxet3', 'DOMAIN_A', 'TOPIC', 'Lorem ipsum dolor sit amet.', 'Max', '', '', '', '', '', '', '', '', FALSE);
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000904', 'sorT005', RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'basXet4', 'DOMAIN_A', 'TOPIC', 'Lorem ipsum dolor sit amet.', 'Max', '', '', '', '', '', '', '', '', FALSE);
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000905', 'Sort006', RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'basxEt5', 'DOMAIN_A', 'TOPIC', 'Lorem ipsum dolor sit amet.', 'Max', '', '', '', '', '', '', '', '', FALSE);
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000906', 'SOrt007', RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'basxeT6', 'DOMAIN_A', 'TOPIC', 'Lorem ipsum dolor sit amet.', 'Max', '', '', '', '', '', '', '', '', FALSE);
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000907', 'SoRt008', RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'BAsxet7', 'DOMAIN_A', 'TOPIC', 'Lorem ipsum dolor sit amet.', 'Max', '', '', '', '', '', '', '', '', FALSE);
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000908', 'SorT009', RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'BaSxet8', 'DOMAIN_A', 'TOPIC', 'Lorem ipsum dolor sit amet.', 'Max', '', '', '', '', '', '', '', '', FALSE);
INSERT INTO WORKBASKET VALUES ('WBI:000000000000000000000000000000000909', 'Sort010', RELATIVE_DATE(0) , RELATIVE_DATE(0) , 'BasXet9', 'DOMAIN_A', 'TOPIC', 'Lorem ipsum dolor sit amet.', 'Max', '', '', '', '', '', '', '', '', FALSE);

View File

@ -3,12 +3,16 @@ package pro.taskana;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import java.util.Collections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.hateoas.MediaTypes;
import org.springframework.hateoas.mediatype.hal.Jackson2HalModule;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@ -67,9 +71,13 @@ public class RestHelper {
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
mapper.registerModule(new Jackson2HalModule());
mapper
.registerModule(new ParameterNamesModule())
.registerModule(new Jdk8Module())
.registerModule(new JavaTimeModule());
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(MediaType.parseMediaTypes("application/hal+json"));
converter.setSupportedMediaTypes(Collections.singletonList(MediaTypes.HAL_JSON));
converter.setObjectMapper(mapper);
RestTemplate template = new RestTemplate();

View File

@ -1,13 +1,13 @@
package pro.taskana.jobs;
import static org.assertj.core.api.Assertions.assertThat;
import static pro.taskana.RestHelper.TEMPLATE;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
@ -19,14 +19,12 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.web.client.RestTemplate;
import pro.taskana.RestConfiguration;
import pro.taskana.RestHelper;
import pro.taskana.classification.api.models.Classification;
import pro.taskana.classification.rest.assembler.ClassificationRepresentationModelAssembler;
import pro.taskana.classification.rest.models.ClassificationRepresentationModel;
import pro.taskana.common.api.exceptions.InvalidArgumentException;
import pro.taskana.common.rest.Mapping;
import pro.taskana.task.api.models.Task;
import pro.taskana.task.rest.assembler.TaskRepresentationModelAssembler;
@ -42,17 +40,25 @@ class AsyncUpdateJobIntTest {
private static final String CLASSIFICATION_ID = "CLI:100000000000000000000000000000000003";
@SuppressWarnings("checkstyle:DeclarationOrder")
static RestTemplate template;
private final ClassificationRepresentationModelAssembler
classificationRepresentationModelAssembler;
private final TaskRepresentationModelAssembler taskRepresentationModelAssembler;
private final JobScheduler jobScheduler;
private final RestHelper restHelper;
private final ObjectMapper mapper;
@Autowired ClassificationRepresentationModelAssembler classificationRepresentationModelAssembler;
@Autowired TaskRepresentationModelAssembler taskRepresentationModelAssembler;
@Autowired JobScheduler jobScheduler;
@Autowired RestHelper restHelper;
@BeforeAll
static void init() {
template = RestHelper.TEMPLATE;
@Autowired
AsyncUpdateJobIntTest(
ClassificationRepresentationModelAssembler classificationRepresentationModelAssembler,
TaskRepresentationModelAssembler taskRepresentationModelAssembler,
JobScheduler jobScheduler,
RestHelper restHelper,
ObjectMapper mapper) {
this.classificationRepresentationModelAssembler = classificationRepresentationModelAssembler;
this.taskRepresentationModelAssembler = taskRepresentationModelAssembler;
this.jobScheduler = jobScheduler;
this.restHelper = restHelper;
this.mapper = mapper;
}
@Test
@ -60,10 +66,9 @@ class AsyncUpdateJobIntTest {
// 1st step: get old classification :
final Instant before = Instant.now();
final ObjectMapper mapper = new ObjectMapper();
ResponseEntity<ClassificationRepresentationModel> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_CLASSIFICATIONS_ID, CLASSIFICATION_ID),
HttpMethod.GET,
new HttpEntity<String>(restHelper.getHeaders()),
@ -78,7 +83,7 @@ class AsyncUpdateJobIntTest {
classification.setServiceLevel("P5D");
classification.setPriority(1000);
template.put(
TEMPLATE.put(
restHelper.toUrl(Mapping.URL_CLASSIFICATIONS_ID, CLASSIFICATION_ID),
new HttpEntity<>(mapper.writeValueAsString(classification), restHelper.getHeaders()));
@ -89,7 +94,7 @@ class AsyncUpdateJobIntTest {
// verify the classification modified timestamp is after 'before'
ResponseEntity<ClassificationRepresentationModel> repeatedResponse =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_CLASSIFICATIONS_ID, CLASSIFICATION_ID),
HttpMethod.GET,
new HttpEntity<String>(restHelper.getHeaders()),
@ -150,17 +155,17 @@ class AsyncUpdateJobIntTest {
}
}
private void verifyTaskIsModifiedAfterOrEquals(String taskId, Instant before)
throws InvalidArgumentException {
private void verifyTaskIsModifiedAfterOrEquals(String taskId, Instant before) {
ResponseEntity<TaskRepresentationModel> taskResponse =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS_ID, taskId),
HttpMethod.GET,
new HttpEntity<>(restHelper.getHeadersAdmin()),
ParameterizedTypeReference.forType(TaskRepresentationModel.class));
TaskRepresentationModel taskRepresentationModel = taskResponse.getBody();
assertThat(taskRepresentationModel).isNotNull();
Task task = taskRepresentationModelAssembler.toEntityModel(taskRepresentationModel);
Instant modified = task.getModified();

View File

@ -1,10 +1,12 @@
package pro.taskana.classification.rest;
import static pro.taskana.common.internal.util.CheckedFunction.wrap;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -13,6 +15,7 @@ import java.util.Set;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.hateoas.config.EnableHypermediaSupport;
import org.springframework.http.ResponseEntity;
@ -37,6 +40,7 @@ import pro.taskana.common.api.exceptions.DomainNotFoundException;
import pro.taskana.common.api.exceptions.InvalidArgumentException;
import pro.taskana.common.api.exceptions.NotAuthorizedException;
import pro.taskana.common.rest.Mapping;
import pro.taskana.common.rest.models.TaskanaPagedModel;
/** Controller for Importing / Exporting classifications. */
@SuppressWarnings("unused")
@ -47,37 +51,41 @@ public class ClassificationDefinitionController {
private static final Logger LOGGER =
LoggerFactory.getLogger(ClassificationDefinitionController.class);
private final ObjectMapper mapper;
private final ClassificationService classificationService;
private final ClassificationRepresentationModelAssembler
classificationRepresentationModelAssembler;
@Autowired
ClassificationDefinitionController(
ObjectMapper mapper,
ClassificationService classificationService,
ClassificationRepresentationModelAssembler classificationRepresentationModelAssembler) {
this.mapper = mapper;
this.classificationService = classificationService;
this.classificationRepresentationModelAssembler = classificationRepresentationModelAssembler;
}
@GetMapping(path = Mapping.URL_CLASSIFICATIONDEFINITION)
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<List<ClassificationRepresentationModel>> exportClassifications(
public ResponseEntity<TaskanaPagedModel<ClassificationRepresentationModel>> exportClassifications(
@RequestParam(required = false) String domain) throws ClassificationNotFoundException {
LOGGER.debug("Entry to exportClassifications(domain= {})", domain);
ClassificationQuery query = classificationService.createClassificationQuery();
List<ClassificationSummary> summaries =
domain != null ? query.domainIn(domain).list() : query.list();
List<ClassificationRepresentationModel> export = new ArrayList<>();
for (ClassificationSummary summary : summaries) {
Classification classification =
classificationService.getClassification(summary.getKey(), summary.getDomain());
TaskanaPagedModel<ClassificationRepresentationModel> pageModel =
summaries.stream()
.map(ClassificationSummary::getId)
.map(wrap(classificationService::getClassification))
.collect(
Collectors.collectingAndThen(
Collectors.toList(), classificationRepresentationModelAssembler::toPageModel));
export.add(classificationRepresentationModelAssembler.toModel(classification));
}
ResponseEntity<List<ClassificationRepresentationModel>> response = ResponseEntity.ok(export);
ResponseEntity<TaskanaPagedModel<ClassificationRepresentationModel>> response =
ResponseEntity.ok(pageModel);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Exit from exportClassifications(), returning {}", response);
}
@ -93,13 +101,13 @@ public class ClassificationDefinitionController {
DomainNotFoundException, IOException {
LOGGER.debug("Entry to importClassifications()");
Map<String, String> systemIds = getSystemIds();
List<ClassificationRepresentationModel> classificationsResources =
TaskanaPagedModel<ClassificationRepresentationModel> classificationsResources =
extractClassificationResourcesFromFile(file);
checkForDuplicates(classificationsResources);
checkForDuplicates(classificationsResources.getContent());
Map<Classification, String> childrenInFile =
mapChildrenToParentKeys(classificationsResources, systemIds);
insertOrUpdateClassificationsWithoutParent(classificationsResources, systemIds);
mapChildrenToParentKeys(classificationsResources.getContent(), systemIds);
insertOrUpdateClassificationsWithoutParent(classificationsResources.getContent(), systemIds);
updateParentChildrenRelations(childrenInFile);
ResponseEntity<Void> response = ResponseEntity.noContent().build();
LOGGER.debug("Exit from importClassifications(), returning {}", response);
@ -112,15 +120,15 @@ public class ClassificationDefinitionController {
Collectors.toMap(i -> i.getKey() + "|" + i.getDomain(), ClassificationSummary::getId));
}
private List<ClassificationRepresentationModel> extractClassificationResourcesFromFile(
MultipartFile file) throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
private TaskanaPagedModel<ClassificationRepresentationModel>
extractClassificationResourcesFromFile(MultipartFile file) throws IOException {
return mapper.readValue(
file.getInputStream(), new TypeReference<List<ClassificationRepresentationModel>>() {});
file.getInputStream(),
new TypeReference<TaskanaPagedModel<ClassificationRepresentationModel>>() {});
}
private void checkForDuplicates(List<ClassificationRepresentationModel> classificationList) {
private void checkForDuplicates(
Collection<ClassificationRepresentationModel> classificationList) {
List<String> identifiers = new ArrayList<>();
Set<String> duplicates = new HashSet<>();
for (ClassificationRepresentationModel classification : classificationList) {
@ -138,7 +146,7 @@ public class ClassificationDefinitionController {
}
private Map<Classification, String> mapChildrenToParentKeys(
List<ClassificationRepresentationModel> classificationRepresentationModels,
Collection<ClassificationRepresentationModel> classificationRepresentationModels,
Map<String, String> systemIds) {
LOGGER.debug("Entry to mapChildrenToParentKeys()");
Map<Classification, String> childrenInFile = new HashMap<>();
@ -159,8 +167,9 @@ public class ClassificationDefinitionController {
}
String parentKeyAndDomain = cl.getParentKey() + "|" + cl.getDomain();
if ((!cl.getParentKey().isEmpty() && !cl.getParentKey().equals("") && (
newKeysWithDomain.contains(parentKeyAndDomain)
if ((!cl.getParentKey().isEmpty()
&& !cl.getParentKey().equals("")
&& (newKeysWithDomain.contains(parentKeyAndDomain)
|| systemIds.containsKey(parentKeyAndDomain)))) {
childrenInFile.put(
classificationRepresentationModelAssembler.toEntityModel(cl), cl.getParentKey());
@ -176,7 +185,7 @@ public class ClassificationDefinitionController {
}
private void insertOrUpdateClassificationsWithoutParent(
List<ClassificationRepresentationModel> classificationRepresentationModels,
Collection<ClassificationRepresentationModel> classificationRepresentationModels,
Map<String, String> systemIds)
throws ClassificationNotFoundException, NotAuthorizedException, InvalidArgumentException,
ClassificationAlreadyExistException, DomainNotFoundException, ConcurrencyException {
@ -197,8 +206,8 @@ public class ClassificationDefinitionController {
updateExistingClassification(classificationRepresentationModel, systemId);
} else {
classificationService.createClassification(
classificationRepresentationModelAssembler
.toEntityModel(classificationRepresentationModel));
classificationRepresentationModelAssembler.toEntityModel(
classificationRepresentationModel));
}
}
LOGGER.debug("Exit from insertOrUpdateClassificationsWithoutParent()");

View File

@ -2,10 +2,8 @@ package pro.taskana.classification.rest.assembler;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
import java.time.Instant;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.server.RepresentationModelAssembler;
import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
@ -17,6 +15,8 @@ import pro.taskana.classification.internal.models.ClassificationImpl;
import pro.taskana.classification.rest.ClassificationController;
import pro.taskana.classification.rest.models.ClassificationRepresentationModel;
import pro.taskana.common.api.exceptions.SystemException;
import pro.taskana.common.rest.assembler.TaskanaPagingAssembler;
import pro.taskana.common.rest.models.TaskanaPagedModelKeys;
/**
* Transforms {@link Classification} to its resource counterpart {@link
@ -24,13 +24,12 @@ import pro.taskana.common.api.exceptions.SystemException;
*/
@Component
public class ClassificationRepresentationModelAssembler
implements RepresentationModelAssembler<Classification, ClassificationRepresentationModel> {
implements TaskanaPagingAssembler<Classification, ClassificationRepresentationModel> {
final ClassificationService classificationService;
@Autowired
public ClassificationRepresentationModelAssembler(
ClassificationService classificationService) {
public ClassificationRepresentationModelAssembler(ClassificationService classificationService) {
this.classificationService = classificationService;
}
@ -42,7 +41,8 @@ public class ClassificationRepresentationModelAssembler
try {
resource.add(
WebMvcLinkBuilder.linkTo(
methodOn(ClassificationController.class).getClassification(classification.getId()))
methodOn(ClassificationController.class)
.getClassification(classification.getId()))
.withSelfRel());
} catch (ClassificationNotFoundException e) {
throw new SystemException("caught unexpected Exception.", e.getCause());
@ -50,6 +50,11 @@ public class ClassificationRepresentationModelAssembler
return resource;
}
@Override
public TaskanaPagedModelKeys getProperty() {
return TaskanaPagedModelKeys.CLASSIFICATIONS;
}
public Classification toEntityModel(
ClassificationRepresentationModel classificationRepresentationModel) {
ClassificationImpl classification =
@ -61,12 +66,8 @@ public class ClassificationRepresentationModelAssembler
BeanUtils.copyProperties(classificationRepresentationModel, classification);
classification.setId(classificationRepresentationModel.getClassificationId());
if (classificationRepresentationModel.getCreated() != null) {
classification.setCreated(Instant.parse(classificationRepresentationModel.getCreated()));
}
if (classificationRepresentationModel.getModified() != null) {
classification.setModified(Instant.parse(classificationRepresentationModel.getModified()));
}
classification.setCreated(classificationRepresentationModel.getCreated());
classification.setModified(classificationRepresentationModel.getModified());
return classification;
}
}

View File

@ -2,12 +2,9 @@ package pro.taskana.classification.rest.assembler;
import static pro.taskana.common.rest.models.TaskanaPagedModelKeys.CLASSIFICATIONS;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.PagedModel.PageMetadata;
import org.springframework.hateoas.server.RepresentationModelAssembler;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
@ -16,16 +13,16 @@ import pro.taskana.classification.api.models.ClassificationSummary;
import pro.taskana.classification.internal.models.ClassificationImpl;
import pro.taskana.classification.rest.models.ClassificationSummaryRepresentationModel;
import pro.taskana.common.rest.Mapping;
import pro.taskana.common.rest.assembler.TaskanaPagingAssembler;
import pro.taskana.common.rest.models.TaskanaPagedModel;
import pro.taskana.common.rest.models.TaskanaPagedModelKeys;
import pro.taskana.resource.rest.PageLinks;
/**
* EntityModel assembler for {@link ClassificationSummaryRepresentationModel}.
*/
/** EntityModel assembler for {@link ClassificationSummaryRepresentationModel}. */
@Component
public class ClassificationSummaryRepresentationModelAssembler
implements
RepresentationModelAssembler<ClassificationSummary, ClassificationSummaryRepresentationModel> {
implements TaskanaPagingAssembler<
ClassificationSummary, ClassificationSummaryRepresentationModel> {
private final ClassificationService classificationService;
@ -52,14 +49,15 @@ public class ClassificationSummaryRepresentationModelAssembler
return classification.asSummary();
}
@Override
public TaskanaPagedModelKeys getProperty() {
return CLASSIFICATIONS;
}
@PageLinks(Mapping.URL_CLASSIFICATIONS)
@Override
public TaskanaPagedModel<ClassificationSummaryRepresentationModel> toPageModel(
List<ClassificationSummary> classificationSummaries, PageMetadata pageMetadata) {
return classificationSummaries.stream()
.map(this::toModel)
.collect(
Collectors.collectingAndThen(
Collectors.toList(),
list -> new TaskanaPagedModel<>(CLASSIFICATIONS, list, pageMetadata)));
Iterable<? extends ClassificationSummary> entities, PageMetadata pageMetadata) {
return TaskanaPagingAssembler.super.toPageModel(entities, pageMetadata);
}
}

View File

@ -1,28 +1,25 @@
package pro.taskana.classification.rest.models;
import java.time.Instant;
import pro.taskana.classification.api.models.Classification;
/**
* EntityModel class for {@link Classification}.
*/
public class ClassificationRepresentationModel
extends ClassificationSummaryRepresentationModel {
/** EntityModel class for {@link Classification}. */
public class ClassificationRepresentationModel extends ClassificationSummaryRepresentationModel {
private Boolean isValidInDomain;
private String created; // ISO-8601
private String modified; // ISO-8601
private Instant created; // ISO-8601
private Instant modified; // ISO-8601
private String description;
public ClassificationRepresentationModel() {
}
public ClassificationRepresentationModel() {}
public ClassificationRepresentationModel(Classification classification) {
super(classification);
this.isValidInDomain = classification.getIsValidInDomain();
this.created =
classification.getCreated() != null ? classification.getCreated().toString() : null;
this.modified =
classification.getModified() != null ? classification.getModified().toString() : null;
this.created = classification.getCreated();
this.modified = classification.getModified();
this.description = classification.getDescription();
}
@ -30,23 +27,23 @@ public class ClassificationRepresentationModel
return isValidInDomain;
}
public void setIsValidInDomain(Boolean validInDomain) {
isValidInDomain = validInDomain;
public void setIsValidInDomain(Boolean isValidInDomain) {
this.isValidInDomain = isValidInDomain;
}
public String getCreated() {
public Instant getCreated() {
return created;
}
public void setCreated(String created) {
public void setCreated(Instant created) {
this.created = created;
}
public String getModified() {
public Instant getModified() {
return modified;
}
public void setModified(String modified) {
public void setModified(Instant modified) {
this.modified = modified;
}
@ -57,55 +54,4 @@ public class ClassificationRepresentationModel
public void setDescription(String description) {
this.description = description;
}
@Override
public String toString() {
return "ClassificationResource [classificationId="
+ classificationId
+ ", key="
+ key
+ ", parentId="
+ parentId
+ ", parentKey="
+ parentKey
+ ", category="
+ category
+ ", type="
+ type
+ ", domain="
+ domain
+ ", isValidInDomain="
+ isValidInDomain
+ ", created="
+ created
+ ", modified="
+ modified
+ ", name="
+ name
+ ", description="
+ description
+ ", priority="
+ priority
+ ", serviceLevel="
+ serviceLevel
+ ", applicationEntryPoint="
+ applicationEntryPoint
+ ", custom1="
+ custom1
+ ", custom2="
+ custom2
+ ", custom3="
+ custom3
+ ", custom4="
+ custom4
+ ", custom5="
+ custom5
+ ", custom6="
+ custom6
+ ", custom7="
+ custom7
+ ", custom8="
+ custom8
+ "]";
}
}

View File

@ -0,0 +1,29 @@
package pro.taskana.common.rest.assembler;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.springframework.hateoas.PagedModel.PageMetadata;
import org.springframework.hateoas.RepresentationModel;
import org.springframework.hateoas.server.RepresentationModelAssembler;
import pro.taskana.common.rest.models.TaskanaPagedModel;
import pro.taskana.common.rest.models.TaskanaPagedModelKeys;
public interface TaskanaPagingAssembler<T, D extends RepresentationModel<? super D>>
extends RepresentationModelAssembler<T, D> {
TaskanaPagedModelKeys getProperty();
default TaskanaPagedModel<D> toPageModel(
Iterable<? extends T> entities, PageMetadata pageMetadata) {
return StreamSupport.stream(entities.spliterator(), false)
.map(this::toModel)
.collect(
Collectors.collectingAndThen(
Collectors.toList(), l -> new TaskanaPagedModel<>(getProperty(), l, pageMetadata)));
}
default TaskanaPagedModel<D> toPageModel(Iterable<? extends T> entities) {
return toPageModel(entities, null);
}
}

View File

@ -17,20 +17,17 @@ import org.springframework.hateoas.RepresentationModel;
*
* @param <T> The class of the paginated content
*/
public class TaskanaPagedModel<T extends RepresentationModel<T>>
public class TaskanaPagedModel<T extends RepresentationModel<? super T>>
extends RepresentationModel<TaskanaPagedModel<T>> {
@JsonIgnore
private TaskanaPagedModelKeys key;
@JsonIgnore
private Collection<? extends T> content;
@JsonIgnore private TaskanaPagedModelKeys key;
@JsonIgnore private Collection<? extends T> content;
@JsonProperty(value = "page", access = Access.WRITE_ONLY)
private PageMetadata metadata;
@SuppressWarnings("unused") // needed for jackson
private TaskanaPagedModel() {
}
private TaskanaPagedModel() {}
/**
* Creates a new {@link TaskanaPagedModel} from the given content.
@ -46,6 +43,10 @@ public class TaskanaPagedModel<T extends RepresentationModel<T>>
this.key = property;
}
public TaskanaPagedModel(TaskanaPagedModelKeys property, Collection<? extends T> content) {
this(property, content, null);
}
public Collection<T> getContent() {
return Collections.unmodifiableCollection(content);
}
@ -54,6 +55,10 @@ public class TaskanaPagedModel<T extends RepresentationModel<T>>
return metadata;
}
public TaskanaPagedModelKeys getKey() {
return key;
}
@JsonAnySetter
private void deserialize(String propertyName, Collection<T> content) {
TaskanaPagedModelKeys.getEnumFromPropertyName(propertyName)

View File

@ -12,7 +12,8 @@ public enum TaskanaPagedModelKeys {
DISTRIBUTION_TARGETS("distributionTargets"),
TASKS("tasks"),
TASK_COMMENTS("taskComments"),
WORKBASKETS("workbaskets");
WORKBASKETS("workbaskets"),
WORKBASKET_DEFINITIONS("workbasketDefinitions");
private static final Map<String, TaskanaPagedModelKeys> PROPERTY_MAP =
Arrays.stream(TaskanaPagedModelKeys.values())

View File

@ -1,23 +1,60 @@
package pro.taskana.task.rest.assembler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.server.RepresentationModelAssembler;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import pro.taskana.classification.rest.assembler.ClassificationSummaryRepresentationModelAssembler;
import pro.taskana.task.api.TaskService;
import pro.taskana.task.api.models.AttachmentSummary;
import pro.taskana.task.internal.models.AttachmentImpl;
import pro.taskana.task.rest.models.AttachmentSummaryRepresentationModel;
/**
* EntityModel assembler for {@link AttachmentSummaryRepresentationModel}.
*/
/** EntityModel assembler for {@link AttachmentSummaryRepresentationModel}. */
@Component
public class AttachmentSummaryRepresentationModelAssembler implements
RepresentationModelAssembler<AttachmentSummary, AttachmentSummaryRepresentationModel> {
public class AttachmentSummaryRepresentationModelAssembler
implements RepresentationModelAssembler<
AttachmentSummary, AttachmentSummaryRepresentationModel> {
private final TaskService taskService;
private final ClassificationSummaryRepresentationModelAssembler classificationSummaryAssembler;
@Autowired
public AttachmentSummaryRepresentationModelAssembler(
TaskService taskService,
ClassificationSummaryRepresentationModelAssembler classificationSummaryAssembler) {
this.taskService = taskService;
this.classificationSummaryAssembler = classificationSummaryAssembler;
}
@NonNull
@Override
public AttachmentSummaryRepresentationModel toModel(
@NonNull AttachmentSummary attachmentSummary) {
return new AttachmentSummaryRepresentationModel(attachmentSummary);
public AttachmentSummaryRepresentationModel toModel(@NonNull AttachmentSummary summary) {
AttachmentSummaryRepresentationModel repModel = new AttachmentSummaryRepresentationModel();
repModel.setAttachmentId(summary.getId());
repModel.setTaskId(summary.getTaskId());
repModel.setCreated(summary.getCreated());
repModel.setModified(summary.getModified());
repModel.setReceived(summary.getReceived());
repModel.setClassificationSummary(
classificationSummaryAssembler.toModel(summary.getClassificationSummary()));
repModel.setObjectReference(summary.getObjectReference());
repModel.setChannel(summary.getChannel());
return repModel;
}
public AttachmentSummary toEntityModel(AttachmentSummaryRepresentationModel repModel) {
AttachmentImpl attachment = (AttachmentImpl) taskService.newAttachment();
attachment.setId(repModel.getAttachmentId());
attachment.setTaskId(repModel.getTaskId());
attachment.setCreated(repModel.getCreated());
attachment.setModified(repModel.getModified());
attachment.setReceived(repModel.getReceived());
attachment.setClassificationSummary(
classificationSummaryAssembler.toEntityModel(repModel.getClassificationSummary()));
attachment.setObjectReference(repModel.getObjectReference());
attachment.setChannel(repModel.getChannel());
return attachment;
}
}

View File

@ -3,12 +3,11 @@ package pro.taskana.task.rest.assembler;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
import java.time.Instant;
import java.util.Objects;
import java.util.stream.Collectors;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport;
import org.springframework.hateoas.server.RepresentationModelAssembler;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
@ -30,7 +29,7 @@ import pro.taskana.workbasket.rest.assembler.WorkbasketSummaryRepresentationMode
*/
@Component
public class TaskRepresentationModelAssembler
extends RepresentationModelAssemblerSupport<Task, TaskRepresentationModel> {
implements RepresentationModelAssembler<Task, TaskRepresentationModel> {
private final TaskService taskService;
@ -47,7 +46,6 @@ public class TaskRepresentationModelAssembler
ClassificationSummaryRepresentationModelAssembler classificationAssembler,
WorkbasketSummaryRepresentationModelAssembler workbasketSummaryRepresentationModelAssembler,
AttachmentRepresentationModelAssembler attachmentAssembler) {
super(TaskController.class, TaskRepresentationModel.class);
this.taskService = taskService;
this.classificationAssembler = classificationAssembler;
this.workbasketSummaryRepresentationModelAssembler
@ -68,8 +66,7 @@ public class TaskRepresentationModelAssembler
return resource;
}
public Task toEntityModel(TaskRepresentationModel resource) throws InvalidArgumentException {
validateTaskResource(resource);
public Task toEntityModel(TaskRepresentationModel resource) {
TaskImpl task =
(TaskImpl)
taskService.newTask(
@ -77,24 +74,7 @@ public class TaskRepresentationModelAssembler
task.setId(resource.getTaskId());
task.setExternalId(resource.getExternalId());
BeanUtils.copyProperties(resource, task);
if (resource.getCreated() != null) {
task.setCreated(Instant.parse(resource.getCreated()));
}
if (resource.getModified() != null) {
task.setModified(Instant.parse(resource.getModified()));
}
if (resource.getClaimed() != null) {
task.setClaimed(Instant.parse(resource.getClaimed()));
}
if (resource.getCompleted() != null) {
task.setCompleted(Instant.parse(resource.getCompleted()));
}
if (resource.getDue() != null) {
task.setDue(Instant.parse(resource.getDue()));
}
if (resource.getPlanned() != null) {
task.setPlanned(Instant.parse(resource.getPlanned()));
}
task.setClassificationSummary(
classificationAssembler.toEntityModel(
resource.getClassificationSummary()));
@ -113,20 +93,4 @@ public class TaskRepresentationModelAssembler
return task;
}
private void validateTaskResource(TaskRepresentationModel resource)
throws InvalidArgumentException {
if (resource.getWorkbasketSummary() == null
|| resource.getWorkbasketSummary().getWorkbasketId() == null
|| resource.getWorkbasketSummary().getWorkbasketId().isEmpty()) {
throw new InvalidArgumentException(
"TaskResource must have a workbasket summary with a valid workbasketId.");
}
if (resource.getClassificationSummary() == null
|| resource.getClassificationSummary().getKey() == null
|| resource.getClassificationSummary().getKey().isEmpty()) {
throw new InvalidArgumentException(
"TaskResource must have a classification summary with a valid classification key.");
}
}
}

View File

@ -1,42 +1,39 @@
package pro.taskana.task.rest.models;
import java.time.Instant;
import org.springframework.hateoas.RepresentationModel;
import pro.taskana.classification.rest.models.ClassificationSummaryRepresentationModel;
import pro.taskana.task.api.models.AttachmentSummary;
import pro.taskana.task.api.models.ObjectReference;
/**
* EntityModel class for {@link AttachmentSummary}.
*/
/** EntityModel class for {@link AttachmentSummary}. */
public class AttachmentSummaryRepresentationModel
extends RepresentationModel<AttachmentSummaryRepresentationModel> {
protected String attachmentId;
protected String taskId;
protected String created;
protected String modified;
protected Instant created;
protected Instant modified;
protected Instant received;
protected ClassificationSummaryRepresentationModel classificationSummary;
protected ObjectReference objectReference;
protected String channel;
protected String received;
AttachmentSummaryRepresentationModel() {
}
// TODO: remove this constructor
public AttachmentSummaryRepresentationModel() {}
// TODO: remove this constructor
public AttachmentSummaryRepresentationModel(AttachmentSummary attachmentSummary) {
this.attachmentId = attachmentSummary.getId();
this.taskId = attachmentSummary.getTaskId();
this.created =
attachmentSummary.getCreated() != null ? attachmentSummary.getCreated().toString() : null;
this.modified =
attachmentSummary.getModified() != null ? attachmentSummary.getModified().toString() : null;
this.created = attachmentSummary.getCreated();
this.modified = attachmentSummary.getModified();
this.received = attachmentSummary.getReceived();
this.classificationSummary =
new ClassificationSummaryRepresentationModel(attachmentSummary.getClassificationSummary());
this.objectReference = attachmentSummary.getObjectReference();
this.channel = attachmentSummary.getChannel();
this.received =
attachmentSummary.getReceived() != null ? attachmentSummary.getReceived().toString() : null;
}
public String getAttachmentId() {
@ -55,22 +52,30 @@ public class AttachmentSummaryRepresentationModel
this.taskId = taskId;
}
public String getCreated() {
public Instant getCreated() {
return created;
}
public void setCreated(String created) {
public void setCreated(Instant created) {
this.created = created;
}
public String getModified() {
public Instant getModified() {
return modified;
}
public void setModified(String modified) {
public void setModified(Instant modified) {
this.modified = modified;
}
public Instant getReceived() {
return received;
}
public void setReceived(Instant received) {
this.received = received;
}
public ClassificationSummaryRepresentationModel getClassificationSummary() {
return classificationSummary;
}
@ -95,34 +100,4 @@ public class AttachmentSummaryRepresentationModel
public void setChannel(String channel) {
this.channel = channel;
}
public String getReceived() {
return received;
}
public void setReceived(String received) {
this.received = received;
}
@Override
public String toString() {
return "AttachmentSummaryResource ["
+ "attachmentId= "
+ this.attachmentId
+ "taskId= "
+ this.taskId
+ "created= "
+ this.created
+ "modified= "
+ this.modified
+ "classificationSummaryResource= "
+ this.classificationSummary
+ "objectReference= "
+ this.objectReference
+ "channel= "
+ this.channel
+ "received= "
+ this.received
+ "]";
}
}

View File

@ -1,5 +1,6 @@
package pro.taskana.task.rest.models;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@ -21,12 +22,12 @@ public class TaskSummaryRepresentationModel
protected String taskId;
protected String externalId;
protected String created; // ISO-8601
protected String claimed; // ISO-8601
protected String completed; // ISO-8601
protected String modified; // ISO-8601
protected String planned; // ISO-8601
protected String due; // ISO-8601
protected Instant created; // ISO-8601
protected Instant claimed; // ISO-8601
protected Instant completed; // ISO-8601
protected Instant modified; // ISO-8601
protected Instant planned; // ISO-8601
protected Instant due; // ISO-8601
protected String name;
protected String creator;
protected String note;
@ -66,12 +67,12 @@ public class TaskSummaryRepresentationModel
public TaskSummaryRepresentationModel(TaskSummary taskSummary) throws InvalidArgumentException {
this.taskId = taskSummary.getId();
this.externalId = taskSummary.getExternalId();
created = taskSummary.getCreated() != null ? taskSummary.getCreated().toString() : null;
claimed = taskSummary.getClaimed() != null ? taskSummary.getClaimed().toString() : null;
completed = taskSummary.getCompleted() != null ? taskSummary.getCompleted().toString() : null;
modified = taskSummary.getModified() != null ? taskSummary.getModified().toString() : null;
planned = taskSummary.getPlanned() != null ? taskSummary.getPlanned().toString() : null;
due = taskSummary.getDue() != null ? taskSummary.getDue().toString() : null;
created = taskSummary.getCreated();
claimed = taskSummary.getClaimed();
completed = taskSummary.getCompleted();
modified = taskSummary.getModified();
planned = taskSummary.getPlanned();
due = taskSummary.getDue();
this.name = taskSummary.getName();
this.creator = taskSummary.getCreator();
this.note = taskSummary.getNote();
@ -126,51 +127,51 @@ public class TaskSummaryRepresentationModel
this.externalId = externalId;
}
public String getCreated() {
public Instant getCreated() {
return created;
}
public void setCreated(String created) {
public void setCreated(Instant created) {
this.created = created;
}
public String getClaimed() {
public Instant getClaimed() {
return claimed;
}
public void setClaimed(String claimed) {
public void setClaimed(Instant claimed) {
this.claimed = claimed;
}
public String getCompleted() {
public Instant getCompleted() {
return completed;
}
public void setCompleted(String completed) {
public void setCompleted(Instant completed) {
this.completed = completed;
}
public String getModified() {
public Instant getModified() {
return modified;
}
public void setModified(String modified) {
public void setModified(Instant modified) {
this.modified = modified;
}
public String getPlanned() {
public Instant getPlanned() {
return planned;
}
public void setPlanned(String planned) {
public void setPlanned(Instant planned) {
this.planned = planned;
}
public String getDue() {
public Instant getDue() {
return due;
}
public void setDue(String due) {
public void setDue(Instant due) {
this.due = due;
}

View File

@ -42,7 +42,6 @@ import pro.taskana.workbasket.api.exceptions.WorkbasketNotFoundException;
import pro.taskana.workbasket.api.models.Workbasket;
import pro.taskana.workbasket.api.models.WorkbasketAccessItem;
import pro.taskana.workbasket.api.models.WorkbasketSummary;
import pro.taskana.workbasket.rest.assembler.DistributionTargetRepresentationModelAssembler;
import pro.taskana.workbasket.rest.assembler.WorkbasketAccessItemRepresentationModelAssembler;
import pro.taskana.workbasket.rest.assembler.WorkbasketRepresentationModelAssembler;
import pro.taskana.workbasket.rest.assembler.WorkbasketSummaryRepresentationModelAssembler;
@ -80,8 +79,7 @@ public class WorkbasketController extends AbstractPagingController {
private final WorkbasketSummaryRepresentationModelAssembler
workbasketSummaryRepresentationModelAssembler;
private final DistributionTargetRepresentationModelAssembler
distributionTargetRepresentationModelAssembler;
private final WorkbasketAccessItemRepresentationModelAssembler
workbasketAccessItemRepresentationModelAssembler;
@ -90,15 +88,13 @@ public class WorkbasketController extends AbstractPagingController {
WorkbasketService workbasketService,
WorkbasketRepresentationModelAssembler workbasketRepresentationModelAssembler,
WorkbasketSummaryRepresentationModelAssembler workbasketSummaryRepresentationModelAssembler,
DistributionTargetRepresentationModelAssembler distributionTargetRepresentationModelAssembler,
WorkbasketAccessItemRepresentationModelAssembler
workbasketAccessItemRepresentationModelAssembler) {
this.workbasketService = workbasketService;
this.workbasketRepresentationModelAssembler = workbasketRepresentationModelAssembler;
this.workbasketSummaryRepresentationModelAssembler =
workbasketSummaryRepresentationModelAssembler;
this.distributionTargetRepresentationModelAssembler =
distributionTargetRepresentationModelAssembler;
this.workbasketAccessItemRepresentationModelAssembler =
workbasketAccessItemRepresentationModelAssembler;
}
@ -236,7 +232,7 @@ public class WorkbasketController extends AbstractPagingController {
workbasketService.getWorkbasketAccessItems(workbasketId);
result =
ResponseEntity.ok(
workbasketAccessItemRepresentationModelAssembler.toPageModel(
workbasketAccessItemRepresentationModelAssembler.toPageModelForSingleWorkbasket(
workbasketId, accessItems, null));
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Exit from getWorkbasketAccessItems(), returning {}", result);
@ -268,7 +264,7 @@ public class WorkbasketController extends AbstractPagingController {
ResponseEntity<TaskanaPagedModel<WorkbasketAccessItemRepresentationModel>> response =
ResponseEntity.ok(
workbasketAccessItemRepresentationModelAssembler.toPageModel(
workbasketAccessItemRepresentationModelAssembler.toPageModelForSingleWorkbasket(
workbasketId, updatedWbAccessItems, null));
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Exit from setWorkbasketAccessItems(), returning {}", response);
@ -287,7 +283,8 @@ public class WorkbasketController extends AbstractPagingController {
List<WorkbasketSummary> distributionTargets =
workbasketService.getDistributionTargets(workbasketId);
TaskanaPagedModel<WorkbasketSummaryRepresentationModel> distributionTargetListResource =
distributionTargetRepresentationModelAssembler.toPageModel(distributionTargets, null);
workbasketSummaryRepresentationModelAssembler
.toDistributionTargetPageModel(distributionTargets, null);
ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> result =
ResponseEntity.ok(distributionTargetListResource);
if (LOGGER.isDebugEnabled()) {
@ -317,7 +314,8 @@ public class WorkbasketController extends AbstractPagingController {
workbasketService.getDistributionTargets(sourceWorkbasketId);
ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> response =
ResponseEntity.ok(
distributionTargetRepresentationModelAssembler.toPageModel(distributionTargets, null));
workbasketSummaryRepresentationModelAssembler
.toDistributionTargetPageModel(distributionTargets, null));
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Exit from getTasksStatusReport(), returning {}", response);
}

View File

@ -1,11 +1,12 @@
package pro.taskana.workbasket.rest;
import static pro.taskana.common.internal.util.CheckedFunction.wrap;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -14,6 +15,7 @@ import java.util.Set;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.hateoas.config.EnableHypermediaSupport;
import org.springframework.http.ResponseEntity;
@ -29,6 +31,7 @@ import pro.taskana.common.api.exceptions.DomainNotFoundException;
import pro.taskana.common.api.exceptions.InvalidArgumentException;
import pro.taskana.common.api.exceptions.NotAuthorizedException;
import pro.taskana.common.rest.Mapping;
import pro.taskana.common.rest.models.TaskanaPagedModel;
import pro.taskana.workbasket.api.WorkbasketQuery;
import pro.taskana.workbasket.api.WorkbasketService;
import pro.taskana.workbasket.api.exceptions.InvalidWorkbasketException;
@ -53,33 +56,38 @@ public class WorkbasketDefinitionController {
LoggerFactory.getLogger(WorkbasketDefinitionController.class);
private final WorkbasketService workbasketService;
private final WorkbasketDefinitionRepresentationModelAssembler workbasketDefinitionAssembler;
private final ObjectMapper mapper;
@Autowired
WorkbasketDefinitionController(
WorkbasketService workbasketService,
WorkbasketDefinitionRepresentationModelAssembler workbasketDefinitionAssembler) {
WorkbasketDefinitionRepresentationModelAssembler workbasketDefinitionAssembler,
ObjectMapper mapper) {
this.workbasketService = workbasketService;
this.workbasketDefinitionAssembler = workbasketDefinitionAssembler;
this.mapper = mapper;
}
@GetMapping(path = Mapping.URL_WORKBASKETDEFIITIONS)
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<List<WorkbasketDefinitionRepresentationModel>> exportWorkbaskets(
@RequestParam(required = false) String domain)
throws NotAuthorizedException, WorkbasketNotFoundException {
public ResponseEntity<TaskanaPagedModel<WorkbasketDefinitionRepresentationModel>>
exportWorkbaskets(@RequestParam(required = false) String domain) {
LOGGER.debug("Entry to exportWorkbaskets(domain= {})", domain);
WorkbasketQuery workbasketQuery = workbasketService.createWorkbasketQuery();
List<WorkbasketSummary> workbasketSummaryList =
domain != null ? workbasketQuery.domainIn(domain).list() : workbasketQuery.list();
List<WorkbasketDefinitionRepresentationModel> basketExports = new ArrayList<>();
for (WorkbasketSummary summary : workbasketSummaryList) {
Workbasket workbasket = workbasketService.getWorkbasket(summary.getId());
basketExports.add(workbasketDefinitionAssembler.toModel(workbasket));
}
ResponseEntity<List<WorkbasketDefinitionRepresentationModel>> response =
ResponseEntity.ok(basketExports);
TaskanaPagedModel<WorkbasketDefinitionRepresentationModel> pageModel =
workbasketSummaryList.stream()
.map(WorkbasketSummary::getId)
.map(wrap(workbasketService::getWorkbasket))
.collect(
Collectors.collectingAndThen(
Collectors.toList(), workbasketDefinitionAssembler::toPageModel));
ResponseEntity<TaskanaPagedModel<WorkbasketDefinitionRepresentationModel>> response =
ResponseEntity.ok(pageModel);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Exit from exportWorkbaskets(), returning {}", response);
}
@ -118,29 +126,26 @@ public class WorkbasketDefinitionController {
InvalidArgumentException, WorkbasketAccessItemAlreadyExistException,
ConcurrencyException {
LOGGER.debug("Entry to importWorkbaskets()");
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
List<WorkbasketDefinitionRepresentationModel> definitions =
TaskanaPagedModel<WorkbasketDefinitionRepresentationModel> definitions =
mapper.readValue(
file.getInputStream(),
new TypeReference<List<WorkbasketDefinitionRepresentationModel>>() {});
new TypeReference<TaskanaPagedModel<WorkbasketDefinitionRepresentationModel>>() {});
// key: logical ID
// value: system ID (in database)
Map<String, String> systemIds =
workbasketService.createWorkbasketQuery().list().stream()
.collect(Collectors.toMap(this::logicalId, WorkbasketSummary::getId));
checkForDuplicates(definitions);
checkForDuplicates(definitions.getContent());
// key: old system ID
// value: system ID
Map<String, String> idConversion = new HashMap<>();
// STEP 1: update or create workbaskets from the import
for (WorkbasketDefinitionRepresentationModel definition : definitions) {
Workbasket importedWb = workbasketDefinitionAssembler
.toEntityModel(definition.getWorkbasket());
for (WorkbasketDefinitionRepresentationModel definition : definitions.getContent()) {
Workbasket importedWb =
workbasketDefinitionAssembler.toEntityModel(definition.getWorkbasket());
String newId;
WorkbasketImpl wbWithoutId = (WorkbasketImpl) removeId(importedWb);
if (systemIds.containsKey(logicalId(importedWb))) {
@ -160,7 +165,8 @@ public class WorkbasketDefinitionController {
boolean authenticated =
definition.getAuthorizations().stream()
.anyMatch(
access -> (access.getWorkbasketId().equals(importedWb.getId()))
access ->
(access.getWorkbasketId().equals(importedWb.getId()))
&& (access.getWorkbasketKey().equals(importedWb.getKey())));
if (!authenticated && !definition.getAuthorizations().isEmpty()) {
throw new InvalidWorkbasketException(
@ -181,7 +187,7 @@ public class WorkbasketDefinitionController {
// STEP 2: update distribution targets
// This can not be done in step 1 because the system IDs are only known after step 1
for (WorkbasketDefinitionRepresentationModel definition : definitions) {
for (WorkbasketDefinitionRepresentationModel definition : definitions.getContent()) {
List<String> distributionTargets = new ArrayList<>();
for (String oldId : definition.getDistributionTargets()) {
if (idConversion.containsKey(oldId)) {
@ -211,7 +217,7 @@ public class WorkbasketDefinitionController {
return workbasketDefinitionAssembler.toEntityModel(wbRes);
}
private void checkForDuplicates(List<WorkbasketDefinitionRepresentationModel> definitions) {
private void checkForDuplicates(Collection<WorkbasketDefinitionRepresentationModel> definitions) {
List<String> identifiers = new ArrayList<>();
Set<String> duplicates = new HashSet<>();
for (WorkbasketDefinitionRepresentationModel definition : definitions) {

View File

@ -1,21 +1 @@
package pro.taskana.workbasket.rest.assembler;
import static pro.taskana.common.rest.models.TaskanaPagedModelKeys.DISTRIBUTION_TARGETS;
import org.springframework.stereotype.Component;
import pro.taskana.common.rest.models.TaskanaPagedModelKeys;
/**
* Transforms WorkbasketSummary to its resource counterpart DistributionTargerResource and vice
* versa.
*/
@Component
public class DistributionTargetRepresentationModelAssembler
extends WorkbasketSummaryRepresentationModelAssembler {
@Override
protected TaskanaPagedModelKeys getKey() {
return DISTRIBUTION_TARGETS;
}
}

View File

@ -58,7 +58,7 @@ public class WorkbasketAccessItemRepresentationModelAssembler
return wbAccItemModel;
}
public TaskanaPagedModel<WorkbasketAccessItemRepresentationModel> toPageModel(
public TaskanaPagedModel<WorkbasketAccessItemRepresentationModel> toPageModelForSingleWorkbasket(
String workbasketId,
List<WorkbasketAccessItem> workbasketAccessItems,
PageMetadata pageMetadata)

View File

@ -1,6 +1,5 @@
package pro.taskana.workbasket.rest.assembler;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@ -11,6 +10,9 @@ import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import pro.taskana.common.api.exceptions.NotAuthorizedException;
import pro.taskana.common.api.exceptions.SystemException;
import pro.taskana.common.rest.assembler.TaskanaPagingAssembler;
import pro.taskana.common.rest.models.TaskanaPagedModelKeys;
import pro.taskana.workbasket.api.WorkbasketService;
import pro.taskana.workbasket.api.exceptions.WorkbasketNotFoundException;
import pro.taskana.workbasket.api.models.Workbasket;
@ -27,41 +29,40 @@ import pro.taskana.workbasket.rest.models.WorkbasketRepresentationModelWithoutLi
* all additional information about that workbasket.
*/
@Component
public class WorkbasketDefinitionRepresentationModelAssembler {
public class WorkbasketDefinitionRepresentationModelAssembler
implements TaskanaPagingAssembler<Workbasket, WorkbasketDefinitionRepresentationModel> {
private final WorkbasketService workbasketService;
@Autowired
public WorkbasketDefinitionRepresentationModelAssembler(
WorkbasketService workbasketService) {
public WorkbasketDefinitionRepresentationModelAssembler(WorkbasketService workbasketService) {
this.workbasketService = workbasketService;
}
/**
* maps the distro targets to their id to remove overhead.
*
* @param workbasket {@link Workbasket} which will be converted
* @return a {@link WorkbasketDefinitionRepresentationModel}, containing the {@code basket}, its
* distribution targets and its authorizations
* @throws NotAuthorizedException if the user is not authorized
* @throws WorkbasketNotFoundException if {@code basket} is an unknown workbasket
*/
@NonNull
public WorkbasketDefinitionRepresentationModel toModel(Workbasket workbasket)
throws NotAuthorizedException, WorkbasketNotFoundException {
public WorkbasketDefinitionRepresentationModel toModel(@NonNull Workbasket workbasket) {
WorkbasketRepresentationModelWithoutLinks basket =
new WorkbasketRepresentationModelWithoutLinks(workbasket);
List<WorkbasketAccessItemImpl> authorizations = new ArrayList<>();
try {
for (WorkbasketAccessItem accessItem :
workbasketService.getWorkbasketAccessItems(basket.getWorkbasketId())) {
authorizations.add((WorkbasketAccessItemImpl) accessItem);
}
Set<String> distroTargets =
} catch (NotAuthorizedException e) {
throw new SystemException("Caught Exception", e);
}
Set<String> distroTargets = null;
try {
distroTargets =
workbasketService.getDistributionTargets(workbasket.getId()).stream()
.map(WorkbasketSummary::getId)
.collect(Collectors.toSet());
} catch (NotAuthorizedException | WorkbasketNotFoundException e) {
throw new SystemException("Caught Exception", e);
}
return new WorkbasketDefinitionRepresentationModel(basket, distroTargets, authorizations);
}
@ -72,12 +73,13 @@ public class WorkbasketDefinitionRepresentationModelAssembler {
BeanUtils.copyProperties(wbResource, workbasket);
workbasket.setId(wbResource.getWorkbasketId());
if (wbResource.getModified() != null) {
workbasket.setModified(Instant.parse(wbResource.getModified()));
}
if (wbResource.getCreated() != null) {
workbasket.setCreated(Instant.parse(wbResource.getCreated()));
}
workbasket.setModified(wbResource.getModified());
workbasket.setCreated(wbResource.getCreated());
return workbasket;
}
@Override
public TaskanaPagedModelKeys getProperty() {
return TaskanaPagedModelKeys.WORKBASKET_DEFINITIONS;
}
}

View File

@ -3,7 +3,6 @@ package pro.taskana.workbasket.rest.assembler;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
import java.time.Instant;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.server.RepresentationModelAssembler;
@ -32,8 +31,7 @@ public class WorkbasketRepresentationModelAssembler
private final WorkbasketService workbasketService;
@Autowired
public WorkbasketRepresentationModelAssembler(
WorkbasketService workbasketService) {
public WorkbasketRepresentationModelAssembler(WorkbasketService workbasketService) {
this.workbasketService = workbasketService;
}
@ -55,12 +53,8 @@ public class WorkbasketRepresentationModelAssembler
BeanUtils.copyProperties(wbResource, workbasket);
workbasket.setId(wbResource.getWorkbasketId());
if (wbResource.getModified() != null) {
workbasket.setModified(Instant.parse(wbResource.getModified()));
}
if (wbResource.getCreated() != null) {
workbasket.setCreated(Instant.parse(wbResource.getCreated()));
}
workbasket.setModified(wbResource.getModified());
workbasket.setCreated(wbResource.getCreated());
return workbasket;
}

View File

@ -1,5 +1,6 @@
package pro.taskana.workbasket.rest.assembler;
import static pro.taskana.common.rest.models.TaskanaPagedModelKeys.DISTRIBUTION_TARGETS;
import static pro.taskana.common.rest.models.TaskanaPagedModelKeys.WORKBASKETS;
import java.util.List;
@ -13,7 +14,6 @@ import org.springframework.stereotype.Component;
import pro.taskana.common.rest.Mapping;
import pro.taskana.common.rest.models.TaskanaPagedModel;
import pro.taskana.common.rest.models.TaskanaPagedModelKeys;
import pro.taskana.resource.rest.PageLinks;
import pro.taskana.workbasket.api.WorkbasketService;
import pro.taskana.workbasket.api.models.WorkbasketSummary;
@ -60,10 +60,17 @@ public class WorkbasketSummaryRepresentationModelAssembler implements
.collect(
Collectors.collectingAndThen(
Collectors.toList(),
list -> new TaskanaPagedModel<>(getKey(), list, pageMetadata)));
list -> new TaskanaPagedModel<>(WORKBASKETS, list, pageMetadata)));
}
protected TaskanaPagedModelKeys getKey() {
return WORKBASKETS;
@PageLinks(Mapping.URL_WORKBASKET_ID_DISTRIBUTION)
public TaskanaPagedModel<WorkbasketSummaryRepresentationModel> toDistributionTargetPageModel(
List<WorkbasketSummary> workbasketSummaries, PageMetadata pageMetadata) {
return workbasketSummaries.stream()
.map(this::toModel)
.collect(
Collectors.collectingAndThen(
Collectors.toList(),
list -> new TaskanaPagedModel<>(DISTRIBUTION_TARGETS, list, pageMetadata)));
}
}

View File

@ -1,5 +1,7 @@
package pro.taskana.workbasket.rest.models;
import java.time.Instant;
import pro.taskana.workbasket.api.models.Workbasket;
/**
@ -9,49 +11,31 @@ public class WorkbasketRepresentationModel
extends WorkbasketSummaryRepresentationModel {
private String created; // ISO-8601
private String modified; // ISO-8601
private Instant created; // ISO-8601
private Instant modified; // ISO-8601
public WorkbasketRepresentationModel() {
}
public WorkbasketRepresentationModel(Workbasket workbasket) {
super(workbasket);
this.created = workbasket.getCreated() != null ? workbasket.getCreated().toString() : null;
this.modified = workbasket.getModified() != null ? workbasket.getModified().toString() : null;
this.created = workbasket.getCreated();
this.modified = workbasket.getModified();
}
public String getCreated() {
public Instant getCreated() {
return created;
}
public void setCreated(String created) {
public void setCreated(Instant created) {
this.created = created;
}
public String getModified() {
public Instant getModified() {
return modified;
}
public void setModified(String modified) {
public void setModified(Instant modified) {
this.modified = modified;
}
@Override
public String toString() {
return "WorkbasketResource ["
+ "workbasketId= "
+ this.workbasketId
+ "key= "
+ this.key
+ "name= "
+ this.name
+ "domain= "
+ this.domain
+ "type= "
+ this.type
+ "owner= "
+ this.owner
+ "]";
}
}

View File

@ -103,18 +103,19 @@ class ClassificationControllerIntTest {
ResponseEntity<TaskanaPagedModel<ClassificationSummaryRepresentationModel>> response =
template.exchange(
restHelper.toUrl(Mapping.URL_CLASSIFICATIONS)
+ "?domain=DOMAIN_A&sort-by=key&order=asc&page=2&page-size=5",
+ "?domain=DOMAIN_A&sort-by=key&order=asc&page-size=5&page=2",
HttpMethod.GET,
restHelper.defaultRequest(),
CLASSIFICATION_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody().getContent()).hasSize(5);
assertThat(response.getBody().getContent().iterator().next().getKey()).isEqualTo("L1050");
assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(
response
String href = response
.getBody()
.getRequiredLink(IanaLinkRelations.SELF)
.getHref()
.getHref();
assertThat(
href
.endsWith(
"/api/v1/classifications?"
+ "domain=DOMAIN_A&sort-by=key&order=asc&page-size=5&page=2"))

View File

@ -9,8 +9,9 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collections;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
@ -27,28 +28,47 @@ import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestTemplate;
import pro.taskana.classification.api.ClassificationService;
import pro.taskana.classification.api.exceptions.ClassificationNotFoundException;
import pro.taskana.classification.rest.assembler.ClassificationRepresentationModelAssembler;
import pro.taskana.classification.rest.models.ClassificationRepresentationModel;
import pro.taskana.classification.rest.models.ClassificationSummaryRepresentationModel;
import pro.taskana.common.rest.Mapping;
import pro.taskana.common.rest.RestHelper;
import pro.taskana.common.rest.TaskanaSpringBootTest;
import pro.taskana.common.rest.models.TaskanaPagedModel;
import pro.taskana.common.rest.models.TaskanaPagedModelKeys;
/** Test classification definitions. */
@TaskanaSpringBootTest
class ClassificationDefinitionControllerIntTest {
private static final ParameterizedTypeReference<
TaskanaPagedModel<ClassificationSummaryRepresentationModel>>
CLASSIFICATION_SUMMARY_PAGE_MODEL_TYPE =
new ParameterizedTypeReference<
TaskanaPagedModel<ClassificationSummaryRepresentationModel>>() {};
TaskanaPagedModel<ClassificationRepresentationModel>>
CLASSIFICATION_PAGE_MODEL_TYPE =
new ParameterizedTypeReference<TaskanaPagedModel<ClassificationRepresentationModel>>() {};
private static final Logger LOGGER = LoggerFactory.getLogger(ClassificationController.class);
private static RestTemplate template;
@Autowired RestHelper restHelper;
private ObjectMapper objMapper = new ObjectMapper();
private final RestHelper restHelper;
private final ObjectMapper mapper;
private final ClassificationService classificationService;
private final ClassificationRepresentationModelAssembler classificationAssembler;
@Autowired
ClassificationDefinitionControllerIntTest(
RestHelper restHelper,
ObjectMapper mapper,
ClassificationService classificationService,
ClassificationRepresentationModelAssembler classificationAssembler) {
this.restHelper = restHelper;
this.mapper = mapper;
this.classificationService = classificationService;
this.classificationAssembler = classificationAssembler;
}
@BeforeAll
static void init() {
@ -57,27 +77,34 @@ class ClassificationDefinitionControllerIntTest {
@Test
void testExportClassifications() {
ResponseEntity<ClassificationRepresentationModel[]> response =
ResponseEntity<TaskanaPagedModel<ClassificationRepresentationModel>> response =
template.exchange(
restHelper.toUrl(Mapping.URL_CLASSIFICATIONDEFINITION) + "?domain=DOMAIN_B",
HttpMethod.GET,
restHelper.defaultRequest(),
ParameterizedTypeReference.forType(ClassificationRepresentationModel[].class));
CLASSIFICATION_PAGE_MODEL_TYPE);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody().length >= 5).isTrue();
assertThat(response.getBody().length <= 7).isTrue();
assertThat(response.getBody()[0]).isInstanceOf(ClassificationRepresentationModel.class);
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getContent())
.extracting(ClassificationRepresentationModel::getClassificationId)
.containsOnlyOnce(
"CLI:200000000000000000000000000000000015",
"CLI:200000000000000000000000000000000017",
"CLI:200000000000000000000000000000000018",
"CLI:200000000000000000000000000000000003",
"CLI:200000000000000000000000000000000004");
}
@Test
void testExportClassificationsFromWrongDomain() {
ResponseEntity<ClassificationRepresentationModel[]> response =
ResponseEntity<TaskanaPagedModel<ClassificationRepresentationModel>> response =
template.exchange(
restHelper.toUrl(Mapping.URL_CLASSIFICATIONDEFINITION) + "?domain=ADdfe",
HttpMethod.GET,
restHelper.defaultRequest(),
ParameterizedTypeReference.forType(ClassificationRepresentationModel[].class));
assertThat(response.getBody()).isEmpty();
CLASSIFICATION_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getContent()).isEmpty();
}
@Test
@ -91,8 +118,8 @@ class ClassificationDefinitionControllerIntTest {
classification.setType("TASK");
classification.setDomain("DOMAIN_A");
classification.setIsValidInDomain(true);
classification.setCreated("2016-05-12T10:12:12.12Z");
classification.setModified("2018-05-12T10:12:12.12Z");
classification.setCreated(Instant.parse("2016-05-12T10:12:12.12Z"));
classification.setModified(Instant.parse("2018-05-12T10:12:12.12Z"));
classification.setName("name");
classification.setDescription("description");
classification.setPriority(4);
@ -107,8 +134,9 @@ class ClassificationDefinitionControllerIntTest {
classification.setCustom7("custom");
classification.setCustom8("custom");
List<String> clList = new ArrayList<>();
clList.add(objMapper.writeValueAsString(classification));
TaskanaPagedModel<ClassificationRepresentationModel> clList =
new TaskanaPagedModel<>(
TaskanaPagedModelKeys.CLASSIFICATIONS, Collections.singletonList(classification));
ResponseEntity<Void> response = importRequest(clList);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
@ -118,8 +146,9 @@ class ClassificationDefinitionControllerIntTest {
void testFailureWhenKeyIsMissing() throws IOException {
ClassificationRepresentationModel classification = new ClassificationRepresentationModel();
classification.setDomain("DOMAIN_A");
List<String> clList = new ArrayList<>();
clList.add(objMapper.writeValueAsString(classification));
TaskanaPagedModel<ClassificationRepresentationModel> clList =
new TaskanaPagedModel<>(
TaskanaPagedModelKeys.CLASSIFICATIONS, Collections.singletonList(classification));
try {
importRequest(clList);
@ -132,8 +161,9 @@ class ClassificationDefinitionControllerIntTest {
void testFailureWhenDomainIsMissing() throws IOException {
ClassificationRepresentationModel classification = new ClassificationRepresentationModel();
classification.setKey("one");
List<String> clList = new ArrayList<>();
clList.add(objMapper.writeValueAsString(classification));
TaskanaPagedModel<ClassificationRepresentationModel> clList =
new TaskanaPagedModel<>(
TaskanaPagedModelKeys.CLASSIFICATIONS, Collections.singletonList(classification));
try {
importRequest(clList);
@ -143,25 +173,25 @@ class ClassificationDefinitionControllerIntTest {
}
@Test
void testFailureWhenUpdatingTypeOfExistingClassification() throws IOException {
ClassificationSummaryRepresentationModel classification =
this.getClassificationWithKeyAndDomain("T6310", "");
void testFailureWhenUpdatingTypeOfExistingClassification() throws Exception {
ClassificationRepresentationModel classification =
getClassificationWithKeyAndDomain("T6310", "");
classification.setType("DOCUMENT");
List<String> clList = new ArrayList<>();
clList.add(objMapper.writeValueAsString(classification));
TaskanaPagedModel<ClassificationRepresentationModel> clList =
new TaskanaPagedModel<>(
TaskanaPagedModelKeys.CLASSIFICATIONS, Collections.singletonList(classification));
try {
importRequest(clList);
} catch (HttpClientErrorException e) {
assertThat(e.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
}
assertThatThrownBy(() -> importRequest(clList))
.isInstanceOf(HttpClientErrorException.class)
.extracting(e -> (HttpClientErrorException) e)
.extracting(HttpClientErrorException::getStatusCode)
.isEqualTo(HttpStatus.BAD_REQUEST);
}
@Test
void testImportMultipleClassifications() throws IOException {
ClassificationRepresentationModel classification1 =
this.createClassification("id1", "ImportKey1", "DOMAIN_A", null, null);
final String c1 = objMapper.writeValueAsString(classification1);
ClassificationRepresentationModel classification2 =
this.createClassification(
@ -169,77 +199,81 @@ class ClassificationDefinitionControllerIntTest {
classification2.setCategory("MANUAL");
classification2.setType("TASK");
classification2.setIsValidInDomain(true);
classification2.setCreated("2016-05-12T10:12:12.12Z");
classification2.setModified("2018-05-12T10:12:12.12Z");
classification2.setCreated(Instant.parse("2016-05-12T10:12:12.12Z"));
classification2.setModified(Instant.parse("2018-05-12T10:12:12.12Z"));
classification2.setName("name");
classification2.setDescription("description");
classification2.setPriority(4);
classification2.setServiceLevel("P2D");
classification2.setApplicationEntryPoint("entry1");
String c2 = objMapper.writeValueAsString(classification2);
List<String> clList = new ArrayList<>();
clList.add(c1);
clList.add(c2);
TaskanaPagedModel<ClassificationRepresentationModel> clList =
new TaskanaPagedModel<>(
TaskanaPagedModelKeys.CLASSIFICATIONS, Arrays.asList(classification1, classification2));
ResponseEntity<Void> response = importRequest(clList);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
}
@Test
void testImportDuplicateClassification() throws IOException {
void testImportDuplicateClassification() {
ClassificationRepresentationModel classification1 = new ClassificationRepresentationModel();
classification1.setClassificationId("id1");
classification1.setKey("ImportKey3");
classification1.setDomain("DOMAIN_A");
String c1 = objMapper.writeValueAsString(classification1);
List<String> clList = new ArrayList<>();
clList.add(c1);
clList.add(c1);
TaskanaPagedModel<ClassificationRepresentationModel> clList =
new TaskanaPagedModel<>(
TaskanaPagedModelKeys.CLASSIFICATIONS, Arrays.asList(classification1, classification1));
try {
importRequest(clList);
} catch (HttpClientErrorException e) {
assertThat(e.getStatusCode()).isEqualTo(HttpStatus.CONFLICT);
}
assertThatThrownBy(() -> importRequest(clList))
.isInstanceOf(HttpClientErrorException.class)
.extracting(e -> (HttpClientErrorException) e)
.extracting(HttpStatusCodeException::getStatusCode)
.isEqualTo(HttpStatus.CONFLICT);
}
@Test
void testInsertExistingClassificationWithOlderTimestamp() throws IOException {
ClassificationSummaryRepresentationModel existingClassification =
void testInsertExistingClassificationWithOlderTimestamp() throws Exception {
ClassificationRepresentationModel existingClassification =
getClassificationWithKeyAndDomain("L110107", "DOMAIN_A");
existingClassification.setName("first new Name");
List<String> clList = new ArrayList<>();
clList.add(objMapper.writeValueAsString(existingClassification));
TaskanaPagedModel<ClassificationRepresentationModel> clList =
new TaskanaPagedModel<>(
TaskanaPagedModelKeys.CLASSIFICATIONS,
Collections.singletonList(existingClassification));
ResponseEntity<Void> response = importRequest(clList);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
existingClassification.setName("second new Name");
clList = new ArrayList<>();
clList.add(objMapper.writeValueAsString(existingClassification));
clList =
new TaskanaPagedModel<>(
TaskanaPagedModelKeys.CLASSIFICATIONS,
Collections.singletonList(existingClassification));
response = importRequest(clList);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
ClassificationSummaryRepresentationModel testClassification =
ClassificationRepresentationModel testClassification =
this.getClassificationWithKeyAndDomain("L110107", "DOMAIN_A");
assertThat(testClassification.getName()).isEqualTo("second new Name");
}
@Test
void testHookExistingChildToNewParent() throws IOException {
void testHookExistingChildToNewParent() throws Exception {
final ClassificationRepresentationModel newClassification =
createClassification("new Classification", "newClass", "DOMAIN_A", null, "L11010");
ClassificationSummaryRepresentationModel existingClassification =
ClassificationRepresentationModel existingClassification =
getClassificationWithKeyAndDomain("L110102", "DOMAIN_A");
existingClassification.setParentId("new Classification");
existingClassification.setParentKey("newClass");
List<String> clList = new ArrayList<>();
clList.add(objMapper.writeValueAsString(existingClassification));
clList.add(objMapper.writeValueAsString(newClassification));
TaskanaPagedModel<ClassificationRepresentationModel> clList =
new TaskanaPagedModel<>(
TaskanaPagedModelKeys.CLASSIFICATIONS,
Arrays.asList(existingClassification, newClassification));
ResponseEntity<Void> response = importRequest(clList);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
@ -259,41 +293,37 @@ class ClassificationDefinitionControllerIntTest {
}
@Test
void testImportParentAndChildClassification() throws IOException {
void testImportParentAndChildClassification() throws Exception {
ClassificationRepresentationModel classification1 =
this.createClassification("parentId", "ImportKey6", "DOMAIN_A", null, null);
final String c1 = objMapper.writeValueAsString(classification1);
ClassificationRepresentationModel classification2 =
this.createClassification("childId1", "ImportKey7", "DOMAIN_A", null, "ImportKey6");
final String c21 = objMapper.writeValueAsString(classification2);
classification2 =
this.createClassification("childId2", "ImportKey8", "DOMAIN_A", "parentId", null);
final String c22 = objMapper.writeValueAsString(classification2);
ClassificationRepresentationModel classification3 =
this.createClassification("childId2", "ImportKey8", "DOMAIN_A", "parentId", null);
ClassificationRepresentationModel classification4 =
this.createClassification(
"grandchildId1", "ImportKey9", "DOMAIN_A", "childId1", "ImportKey7");
final String c31 = objMapper.writeValueAsString(classification3);
classification3 =
ClassificationRepresentationModel classification5 =
this.createClassification("grandchild2", "ImportKey10", "DOMAIN_A", null, "ImportKey7");
final String c32 = objMapper.writeValueAsString(classification3);
List<String> clList = new ArrayList<>();
clList.add(c31);
clList.add(c32);
clList.add(c21);
clList.add(c22);
clList.add(c1);
TaskanaPagedModel<ClassificationRepresentationModel> clList =
new TaskanaPagedModel<>(
TaskanaPagedModelKeys.CLASSIFICATIONS,
Arrays.asList(
classification1,
classification2,
classification3,
classification4,
classification5));
ResponseEntity<Void> response = importRequest(clList);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
ClassificationSummaryRepresentationModel parentCl =
ClassificationRepresentationModel parentCl =
getClassificationWithKeyAndDomain("ImportKey6", "DOMAIN_A");
ClassificationSummaryRepresentationModel childCl =
ClassificationRepresentationModel childCl =
getClassificationWithKeyAndDomain("ImportKey7", "DOMAIN_A");
ClassificationSummaryRepresentationModel grandchildCl =
ClassificationRepresentationModel grandchildCl =
getClassificationWithKeyAndDomain("ImportKey9", "DOMAIN_A");
assertThat(parentCl).isNotNull();
@ -304,31 +334,27 @@ class ClassificationDefinitionControllerIntTest {
}
@Test
void testImportParentAndChildClassificationWithKey() throws IOException {
ClassificationRepresentationModel classification1 =
void testImportParentAndChildClassificationWithKey() throws Exception {
ClassificationRepresentationModel parent =
createClassification("parent", "ImportKey11", "DOMAIN_A", null, null);
classification1.setCustom1("parent is correct");
String parent = objMapper.writeValueAsString(classification1);
ClassificationRepresentationModel classification2 =
parent.setCustom1("parent is correct");
ClassificationRepresentationModel wrongParent =
createClassification("wrongParent", "ImportKey11", "DOMAIN_B", null, null);
String wrongParent = objMapper.writeValueAsString(classification2);
ClassificationRepresentationModel classification3 =
ClassificationRepresentationModel child =
createClassification("child", "ImportKey13", "DOMAIN_A", null, "ImportKey11");
String child = objMapper.writeValueAsString(classification3);
List<String> clList = new ArrayList<>();
clList.add(wrongParent);
clList.add(parent);
clList.add(child);
TaskanaPagedModel<ClassificationRepresentationModel> clList =
new TaskanaPagedModel<>(
TaskanaPagedModelKeys.CLASSIFICATIONS, Arrays.asList(parent, wrongParent, child));
ResponseEntity<Void> response = importRequest(clList);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
ClassificationSummaryRepresentationModel rightParentCl =
ClassificationRepresentationModel rightParentCl =
getClassificationWithKeyAndDomain("ImportKey11", "DOMAIN_A");
ClassificationSummaryRepresentationModel wrongParentCl =
ClassificationRepresentationModel wrongParentCl =
getClassificationWithKeyAndDomain("ImportKey11", "DOMAIN_B");
ClassificationSummaryRepresentationModel childCl =
ClassificationRepresentationModel childCl =
getClassificationWithKeyAndDomain("ImportKey13", "DOMAIN_A");
assertThat(rightParentCl).isNotNull();
@ -339,50 +365,46 @@ class ClassificationDefinitionControllerIntTest {
}
@Test
void testChangeParentByImportingExistingClassification()
throws IOException, InterruptedException {
ClassificationSummaryRepresentationModel child1 =
void testChangeParentByImportingExistingClassification() throws Exception {
ClassificationRepresentationModel child1 =
this.getClassificationWithKeyAndDomain("L110105", "DOMAIN_A");
assertThat(child1.getParentKey()).isEqualTo("L11010");
child1.setParentId("CLI:100000000000000000000000000000000002");
child1.setParentKey("L10303");
final String withNewParent = objMapper.writeValueAsString(child1);
ClassificationSummaryRepresentationModel child2 =
ClassificationRepresentationModel child2 =
this.getClassificationWithKeyAndDomain("L110107", "DOMAIN_A");
assertThat(child2.getParentKey()).isEqualTo("L11010");
child2.setParentId("");
child2.setParentKey("");
String withoutParent = objMapper.writeValueAsString(child2);
List<String> clList = new ArrayList<>();
clList.add(withNewParent);
clList.add(withoutParent);
TaskanaPagedModel<ClassificationRepresentationModel> clList =
new TaskanaPagedModel<>(
TaskanaPagedModelKeys.CLASSIFICATIONS, Arrays.asList(child1, child2));
ResponseEntity<Void> response = importRequest(clList);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
Thread.sleep(10);
LOGGER.debug("Wait 10 ms to give the system a chance to update");
ClassificationSummaryRepresentationModel childWithNewParent =
ClassificationRepresentationModel childWithNewParent =
this.getClassificationWithKeyAndDomain("L110105", "DOMAIN_A");
assertThat(childWithNewParent.getParentKey()).isEqualTo(child1.getParentKey());
ClassificationSummaryRepresentationModel childWithoutParent =
ClassificationRepresentationModel childWithoutParent =
this.getClassificationWithKeyAndDomain("L110107", "DOMAIN_A");
assertThat(childWithoutParent.getParentId()).isEqualTo(child2.getParentId());
assertThat(childWithoutParent.getParentKey()).isEqualTo(child2.getParentKey());
}
@Test
void testFailOnImportDuplicates() throws IOException {
ClassificationSummaryRepresentationModel classification =
void testFailOnImportDuplicates() throws Exception {
ClassificationRepresentationModel classification =
this.getClassificationWithKeyAndDomain("L110105", "DOMAIN_A");
String classificationString = objMapper.writeValueAsString(classification);
List<String> clList = new ArrayList<>();
clList.add(classificationString);
clList.add(classificationString);
TaskanaPagedModel<ClassificationRepresentationModel> clList =
new TaskanaPagedModel<>(
TaskanaPagedModelKeys.CLASSIFICATIONS, Arrays.asList(classification, classification));
assertThatThrownBy(() -> importRequest(clList))
.isInstanceOf(HttpClientErrorException.class)
@ -402,29 +424,18 @@ class ClassificationDefinitionControllerIntTest {
return classificationRepresentationModel;
}
private ClassificationSummaryRepresentationModel getClassificationWithKeyAndDomain(
String key, String domain) {
LOGGER.debug("Request classification with key={} in domain={}", key, domain);
HttpEntity<String> request = new HttpEntity<>(restHelper.getHeaders());
ResponseEntity<TaskanaPagedModel<ClassificationSummaryRepresentationModel>> response =
template.exchange(
restHelper.toUrl(Mapping.URL_CLASSIFICATIONS) + "?key=" + key + "&domain=" + domain,
HttpMethod.GET,
request,
CLASSIFICATION_SUMMARY_PAGE_MODEL_TYPE);
return response
.getBody()
.getContent()
.toArray(new ClassificationSummaryRepresentationModel[1])[0];
private ClassificationRepresentationModel getClassificationWithKeyAndDomain(
String key, String domain) throws ClassificationNotFoundException {
return classificationAssembler.toModel(classificationService.getClassification(key, domain));
}
private ResponseEntity<Void> importRequest(List<String> clList) throws IOException {
private ResponseEntity<Void> importRequest(
TaskanaPagedModel<ClassificationRepresentationModel> clList) throws IOException {
LOGGER.debug("Start Import");
File tmpFile = File.createTempFile("test", ".tmp");
OutputStreamWriter writer =
new OutputStreamWriter(new FileOutputStream(tmpFile), StandardCharsets.UTF_8);
writer.write(clList.toString());
writer.close();
mapper.writeValue(writer, clList);
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();

View File

@ -3,12 +3,16 @@ package pro.taskana.common.rest;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import java.util.Collections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.hateoas.MediaTypes;
import org.springframework.hateoas.mediatype.hal.Jackson2HalModule;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@ -81,9 +85,11 @@ public class RestHelper {
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
mapper.registerModule(new Jackson2HalModule());
mapper.registerModule(new ParameterNamesModule())
.registerModule(new Jdk8Module())
.registerModule(new JavaTimeModule());
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(MediaType.parseMediaTypes("application/hal+json"));
converter.setSupportedMediaTypes(Collections.singletonList(MediaTypes.HAL_JSON));
converter.setObjectMapper(mapper);
RestTemplate template = new RestTemplate();

View File

@ -27,8 +27,8 @@ class ClassificationDefinitionControllerRestDocumentation extends BaseRestDocume
classificationDefinitionsFieldDescriptors =
new FieldDescriptor[] {
subsectionWithPath("[]")
.description("An array of <<ClassificationResource, classifications>>")
subsectionWithPath("classifications")
.description("An array of <<ClassificationRepresentationModels, classifications>>")
};
}
@ -49,7 +49,8 @@ class ClassificationDefinitionControllerRestDocumentation extends BaseRestDocume
@Test
void importClassificationDefinitions() throws Exception {
String definitionString = "[{\"key\":\"Key0815\", \"domain\":\"DOMAIN_B\"}]";
String definitionString =
"{\"classifications\":[{\"key\":\"Key0815\", \"domain\":\"DOMAIN_B\"}]}";
this.mockMvc
.perform(

View File

@ -27,8 +27,10 @@ class WorkbasketDefinitionControllerRestDocumentation extends BaseRestDocumentat
workbasketDefinitionsFieldDescriptors =
new FieldDescriptor[] {
subsectionWithPath("[]")
.description("An array of <<WorkbasketDefinitions, workbasketsDefinitions>>")
subsectionWithPath("workbasketDefinitions")
.description(
"An array of <<WorkbasketDefinitionRepresentationModels, "
+ "workbasketsDefinitions>>")
};
}
@ -49,7 +51,7 @@ class WorkbasketDefinitionControllerRestDocumentation extends BaseRestDocumentat
@Test
void importWorkbasketDefinition() throws Exception {
String definitionString =
"["
"{ \"workbasketDefinitions\": ["
+ "{"
+ "\"distributionTargets\":[], "
+ "\"authorizations\":[], "
@ -57,7 +59,7 @@ class WorkbasketDefinitionControllerRestDocumentation extends BaseRestDocumentat
+ "\"domain\": \"DOMAIN_A\", \"type\":\"GROUP\" , "
+ "\"workbasketId\":\"gibtsNed\"}"
+ "}"
+ "]";
+ "]}";
this.mockMvc
.perform(

View File

@ -3,8 +3,8 @@ package pro.taskana.task.rest;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static pro.taskana.common.rest.RestHelper.TEMPLATE;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.BufferedReader;
@ -18,7 +18,6 @@ import java.time.Instant;
import java.time.temporal.ChronoUnit;
import javax.sql.DataSource;
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@ -30,7 +29,6 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import pro.taskana.classification.rest.models.ClassificationSummaryRepresentationModel;
import pro.taskana.common.rest.Mapping;
@ -51,18 +49,18 @@ class TaskControllerIntTest {
private static final ParameterizedTypeReference<TaskanaPagedModel<TaskSummaryRepresentationModel>>
TASK_SUMMARY_PAGE_MODEL_TYPE =
new ParameterizedTypeReference<TaskanaPagedModel<TaskSummaryRepresentationModel>>() {};
private static RestTemplate template;
private final RestHelper restHelper;
private final ObjectMapper mapper;
private final DataSource dataSource;
@Value("${taskana.schemaName:TASKANA}")
public String schemaName;
@Autowired RestHelper restHelper;
@Autowired private DataSource dataSource;
@BeforeAll
static void init() {
template = RestHelper.TEMPLATE;
@Autowired
TaskControllerIntTest(RestHelper restHelper, ObjectMapper mapper, DataSource dataSource) {
this.restHelper = restHelper;
this.mapper = mapper;
this.dataSource = dataSource;
}
void resetDb() {
@ -73,29 +71,27 @@ class TaskControllerIntTest {
@Test
void testGetAllTasks() {
ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS),
HttpMethod.GET,
restHelper.defaultRequest(),
TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF))
.isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getContent()).hasSize(25);
}
@Test
void testGetAllTasksByWorkbasketId() {
ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS)
+ "?workbasket-id=WBI:100000000000000000000000000000000001",
HttpMethod.GET,
restHelper.defaultRequest(),
TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF))
.isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getContent()).hasSize(22);
}
@ -108,7 +104,7 @@ class TaskControllerIntTest {
Instant fourthInstant = Instant.now().minus(11, ChronoUnit.DAYS);
ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS)
+ "?workbasket-id=WBI:100000000000000000000000000000000001"
+ "&planned="
@ -125,8 +121,7 @@ class TaskControllerIntTest {
restHelper.defaultRequest(),
TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF))
.isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getContent()).hasSize(6);
}
@ -137,7 +132,7 @@ class TaskControllerIntTest {
Instant plannedToInstant = Instant.now().minus(3, ChronoUnit.DAYS);
ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS)
+ "?workbasket-id=WBI:100000000000000000000000000000000001"
+ "&planned-from="
@ -149,8 +144,7 @@ class TaskControllerIntTest {
restHelper.defaultRequest(),
TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF))
.isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getContent()).hasSize(3);
}
@ -160,7 +154,7 @@ class TaskControllerIntTest {
Instant plannedFromInstant = Instant.now().minus(6, ChronoUnit.DAYS);
ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS)
+ "?workbasket-id=WBI:100000000000000000000000000000000001"
+ "&planned-from="
@ -170,15 +164,15 @@ class TaskControllerIntTest {
restHelper.defaultRequest(),
TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF))
.isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getContent()).hasSize(4);
}
@Test
void testGetAllTasksByWorkbasketIdWithInvalidPlannedParamsCombination() {
ThrowingCallable httpCall =
() -> template.exchange(
() ->
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS)
+ "?workbasket-id=WBI:100000000000000000000000000000000001"
+ "&planned=2020-01-22T09:44:47.453Z,,"
@ -203,7 +197,7 @@ class TaskControllerIntTest {
Instant fourthInstant = Instant.now().minus(11, ChronoUnit.DAYS);
ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS)
+ "?workbasket-id=WBI:100000000000000000000000000000000001"
+ "&due="
@ -220,15 +214,14 @@ class TaskControllerIntTest {
restHelper.defaultRequest(),
TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF))
.isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getContent()).hasSize(6);
}
@Test
void should_ReturnAllTasksByWildcardSearch_For_ProvidedSearchValue() {
ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS)
+ "?wildcard-search-value=%99%"
+ "&wildcard-search-fields=NAME,custom_3,CuStOM_4",
@ -236,8 +229,7 @@ class TaskControllerIntTest {
new HttpEntity<String>(restHelper.getHeadersAdmin()),
TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF))
.isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getContent()).hasSize(4);
}
@ -245,7 +237,8 @@ class TaskControllerIntTest {
void should_ThrowException_When_ProvidingInvalidWildcardSearchParameters() {
ThrowingCallable httpCall =
() -> template.exchange(
() ->
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS) + "?wildcard-search-value=%rt%",
HttpMethod.GET,
restHelper.defaultRequest(),
@ -257,7 +250,8 @@ class TaskControllerIntTest {
.isEqualTo(HttpStatus.BAD_REQUEST);
ThrowingCallable httpCall2 =
() -> template.exchange(
() ->
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS)
+ "?wildcard-search-fields=NAME,CUSTOM_3,CUSTOM_4",
HttpMethod.GET,
@ -277,7 +271,7 @@ class TaskControllerIntTest {
Instant dueToInstant = Instant.now().minus(3, ChronoUnit.DAYS);
ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS)
+ "?workbasket-id=WBI:100000000000000000000000000000000001"
+ "&due-from="
@ -289,8 +283,7 @@ class TaskControllerIntTest {
restHelper.defaultRequest(),
TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF))
.isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getContent()).hasSize(9);
}
@ -300,7 +293,7 @@ class TaskControllerIntTest {
Instant dueToInstant = Instant.now().minus(1, ChronoUnit.DAYS);
ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS)
+ "?workbasket-id=WBI:100000000000000000000000000000000001"
+ "&due-until="
@ -310,15 +303,15 @@ class TaskControllerIntTest {
restHelper.defaultRequest(),
TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF))
.isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getContent()).hasSize(6);
}
@Test
void testGetAllTasksByWorkbasketIdWithInvalidDueParamsCombination() {
ThrowingCallable httpCall =
() -> template.exchange(
() ->
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS)
+ "?workbasket-id=WBI:100000000000000000000000000000000001"
+ "&due=2020-01-22T09:44:47.453Z,,"
@ -340,21 +333,20 @@ class TaskControllerIntTest {
headers.add("Authorization", "Basic dXNlcl8xXzI6dXNlcl8xXzI="); // user_1_2
HttpEntity<String> request = new HttpEntity<>(headers);
ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS) + "?workbasket-key=USER_1_2&domain=DOMAIN_A",
HttpMethod.GET,
request,
TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF))
.isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getContent()).hasSize(20);
}
@Test
void testGetAllTasksByExternalId() {
ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS)
+ "?external-id=ETI:000000000000000000000000000000000003,"
+ "ETI:000000000000000000000000000000000004",
@ -362,8 +354,7 @@ class TaskControllerIntTest {
restHelper.defaultRequest(),
TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF))
.isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getContent()).hasSize(2);
}
@ -375,7 +366,8 @@ class TaskControllerIntTest {
HttpEntity<String> request = new HttpEntity<>(headers);
ThrowingCallable httpCall =
() -> template.exchange(
() ->
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS) + "?workbasket-key=USER_1_2",
HttpMethod.GET,
request,
@ -388,29 +380,27 @@ class TaskControllerIntTest {
@Test
void testGetAllTasksWithAdminRole() {
ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS),
HttpMethod.GET,
new HttpEntity<>(restHelper.getHeadersAdmin()),
TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF))
.isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getContent()).hasSize(73);
}
@Test
void testGetAllTasksKeepingFilters() {
ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS)
+ "?por.type=VNR&por.value=22334455&sort-by=por.value&order=desc",
HttpMethod.GET,
restHelper.defaultRequest(),
TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF))
.isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(
response
.getBody()
@ -424,7 +414,8 @@ class TaskControllerIntTest {
@Test
void testThrowsExceptionIfInvalidFilterIsUsed() {
ThrowingCallable httpCall =
() -> template.exchange(
() ->
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS) + "?invalid=VNR",
HttpMethod.GET,
restHelper.defaultRequest(),
@ -441,7 +432,7 @@ class TaskControllerIntTest {
HttpEntity<String> request = new HttpEntity<>(restHelper.getHeadersAdmin());
ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS)
+ "?state=READY,CLAIMED&sort-by=por.value&order=desc&page-size=5&page=14",
HttpMethod.GET,
@ -487,7 +478,7 @@ class TaskControllerIntTest {
HttpEntity<String> request = new HttpEntity<>(headers);
ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS) + "?sort-by=due&order=desc",
HttpMethod.GET,
request,
@ -496,7 +487,7 @@ class TaskControllerIntTest {
assertThat((response.getBody()).getContent()).hasSize(25);
response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS) + "?sort-by=due&order=desc&page-size=5&page=5",
HttpMethod.GET,
request,
@ -533,7 +524,7 @@ class TaskControllerIntTest {
headers.add("Authorization", "Basic dGVhbWxlYWRfMTp0ZWFtbGVhZF8x");
HttpEntity<String> request = new HttpEntity<>(headers);
ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS)
+ "?por.company=00&por.system=PASystem&por.instance=00&"
+ "por.type=VNR&por.value=22334455&sort-by=por.type&"
@ -572,7 +563,6 @@ class TaskControllerIntTest {
con.setRequestMethod("GET");
con.setRequestProperty("Authorization", "Basic YWRtaW46YWRtaW4=");
assertThat(con.getResponseCode()).isEqualTo(200);
final ObjectMapper objectMapper = new ObjectMapper();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream(), UTF_8));
String inputLine;
@ -583,7 +573,7 @@ class TaskControllerIntTest {
in.close();
con.disconnect();
String response = content.toString();
JsonNode jsonNode = objectMapper.readTree(response);
JsonNode jsonNode = mapper.readTree(response);
String created = jsonNode.get("created").asText();
assertThat(response.contains("\"attachments\":[]")).isFalse();
assertThat(created.matches("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z")).isTrue();
@ -634,8 +624,6 @@ class TaskControllerIntTest {
in.close();
con.disconnect();
String updatedTask = content.toString();
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
TaskRepresentationModel originalTaskObject =
mapper.readValue(originalTask, TaskRepresentationModel.class);
TaskRepresentationModel updatedTaskObject =
@ -649,7 +637,7 @@ class TaskControllerIntTest {
TaskRepresentationModel taskRepresentationModel = getTaskResourceSample();
ResponseEntity<TaskRepresentationModel> responseCreate =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS),
HttpMethod.POST,
new HttpEntity<>(taskRepresentationModel, restHelper.getHeaders()),
@ -663,7 +651,7 @@ class TaskControllerIntTest {
assertThat(taskIdOfCreatedTask.startsWith("TKI:")).isTrue();
ResponseEntity<TaskRepresentationModel> responseDeleted =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS_ID, taskIdOfCreatedTask),
HttpMethod.DELETE,
new HttpEntity<>(restHelper.getHeadersAdmin()),
@ -680,11 +668,12 @@ class TaskControllerIntTest {
void testCreateWithPlannedAndDueDate() {
TaskRepresentationModel taskRepresentationModel = getTaskResourceSample();
Instant now = Instant.now();
taskRepresentationModel.setPlanned(now.toString());
taskRepresentationModel.setDue(now.toString());
taskRepresentationModel.setPlanned(now);
taskRepresentationModel.setDue(now);
ThrowingCallable httpCall =
() -> template.exchange(
() ->
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS),
HttpMethod.POST,
new HttpEntity<>(taskRepresentationModel, restHelper.getHeaders()),
@ -744,7 +733,7 @@ class TaskControllerIntTest {
// retrieve task from Rest Api
ResponseEntity<TaskRepresentationModel> getTaskResponse =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS_ID, claimed_task_id),
HttpMethod.GET,
new HttpEntity<>(restHelper.getHeadersUser_1_2()),
@ -758,7 +747,7 @@ class TaskControllerIntTest {
// cancel claim
ResponseEntity<TaskRepresentationModel> cancelClaimResponse =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS_ID_CLAIM, claimed_task_id),
HttpMethod.DELETE,
new HttpEntity<>(restHelper.getHeadersUser_1_2()),
@ -781,7 +770,7 @@ class TaskControllerIntTest {
// retrieve task from Rest Api
ResponseEntity<TaskRepresentationModel> responseGet =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS_ID, claimed_task_id),
HttpMethod.GET,
new HttpEntity<>(restHelper.getHeadersUser_1_2()),
@ -794,7 +783,8 @@ class TaskControllerIntTest {
// try to cancel claim
ThrowingCallable httpCall =
() -> template.exchange(
() ->
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_TASKS_ID_CLAIM, claimed_task_id),
HttpMethod.DELETE,
new HttpEntity<>(restHelper.getHeadersUser_1_2()),
@ -812,7 +802,7 @@ class TaskControllerIntTest {
// retrieve task from Rest Api
ResponseEntity<TaskRepresentationModel> responseGet =
template.exchange(
TEMPLATE.exchange(
taskUrlString,
HttpMethod.GET,
new HttpEntity<>(restHelper.getHeadersUser_1_2()),
@ -828,7 +818,7 @@ class TaskControllerIntTest {
final String anyUserName = "dummyUser";
theTaskRepresentationModel.setOwner(anyUserName);
ResponseEntity<TaskRepresentationModel> responseUpdate =
template.exchange(
TEMPLATE.exchange(
taskUrlString,
HttpMethod.PUT,
new HttpEntity<>(theTaskRepresentationModel, restHelper.getHeadersUser_1_2()),
@ -848,7 +838,7 @@ class TaskControllerIntTest {
// retrieve task from Rest Api
ResponseEntity<TaskRepresentationModel> responseGet =
template.exchange(
TEMPLATE.exchange(
taskUrlString,
HttpMethod.GET,
new HttpEntity<>(restHelper.getHeadersUser_1_2()),
@ -865,7 +855,8 @@ class TaskControllerIntTest {
theTaskRepresentationModel.setOwner(anyUserName);
ThrowingCallable httpCall =
() -> template.exchange(
() ->
TEMPLATE.exchange(
taskUrlString,
HttpMethod.PUT,
new HttpEntity<>(theTaskRepresentationModel, restHelper.getHeadersUser_1_2()),
@ -881,8 +872,7 @@ class TaskControllerIntTest {
classificationResource.setKey("L11010");
WorkbasketSummaryRepresentationModel workbasketSummary =
new WorkbasketSummaryRepresentationModel();
workbasketSummary.setWorkbasketId(
"WBI:100000000000000000000000000000000004");
workbasketSummary.setWorkbasketId("WBI:100000000000000000000000000000000004");
ObjectReference objectReference = new ObjectReference();
objectReference.setCompany("MyCompany1");
@ -893,8 +883,7 @@ class TaskControllerIntTest {
TaskRepresentationModel taskRepresentationModel = new TaskRepresentationModel();
taskRepresentationModel.setClassificationSummary(classificationResource);
taskRepresentationModel.setWorkbasketSummary(
workbasketSummary);
taskRepresentationModel.setWorkbasketSummary(workbasketSummary);
taskRepresentationModel.setPrimaryObjRef(objectReference);
return taskRepresentationModel;
}

View File

@ -68,12 +68,12 @@ class TaskRepresentationModelAssemberTest {
TaskRepresentationModel resource = new TaskRepresentationModel();
resource.setTaskId("taskId");
resource.setExternalId("externalId");
resource.setCreated("2019-09-13T08:44:17.588Z");
resource.setClaimed("2019-09-13T08:44:17.588Z");
resource.setCompleted("2019-09-13T08:44:17.588Z");
resource.setModified("2019-09-13T08:44:17.588Z");
resource.setPlanned("2019-09-13T08:44:17.588Z");
resource.setDue("2019-09-13T08:44:17.588Z");
resource.setCreated(Instant.parse("2019-09-13T08:44:17.588Z"));
resource.setClaimed(Instant.parse("2019-09-13T08:44:17.588Z"));
resource.setCompleted(Instant.parse("2019-09-13T08:44:17.588Z"));
resource.setModified(Instant.parse("2019-09-13T08:44:17.588Z"));
resource.setPlanned(Instant.parse("2019-09-13T08:44:17.588Z"));
resource.setDue(Instant.parse("2019-09-13T08:44:17.588Z"));
resource.setName("name");
resource.setCreator("creator");
resource.setDescription("desc");

View File

@ -100,21 +100,11 @@ class TaskSummaryAssemblerTest {
void testEquality(TaskSummaryImpl taskSummary, TaskSummaryRepresentationModel resource) {
Assert.assertEquals(taskSummary.getId(), resource.getTaskId());
Assert.assertEquals(taskSummary.getExternalId(), resource.getExternalId());
Assert.assertEquals(
taskSummary.getCreated() == null ? null : taskSummary.getCreated().toString(),
resource.getCreated());
Assert.assertEquals(
taskSummary.getClaimed() == null ? null : taskSummary.getClaimed().toString(),
resource.getClaimed());
Assert.assertEquals(
taskSummary.getCompleted() == null ? null : taskSummary.getCompleted().toString(),
resource.getCompleted());
Assert.assertEquals(
taskSummary.getModified() == null ? null : taskSummary.getModified().toString(),
resource.getModified());
Assert.assertEquals(
taskSummary.getPlanned() == null ? null : taskSummary.getPlanned().toString(),
resource.getPlanned());
Assert.assertEquals(taskSummary.getCreated(), resource.getCreated());
Assert.assertEquals(taskSummary.getClaimed(), resource.getClaimed());
Assert.assertEquals(taskSummary.getCompleted(), resource.getCompleted());
Assert.assertEquals(taskSummary.getModified(), resource.getModified());
Assert.assertEquals(taskSummary.getPlanned(), resource.getPlanned());
Assert.assertEquals(taskSummary.getDescription(), resource.getDescription());
Assert.assertEquals(taskSummary.getName(), resource.getName());
Assert.assertEquals(taskSummary.getCreator(), resource.getCreator());

View File

@ -2,11 +2,11 @@ package pro.taskana.workbasket.rest;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static pro.taskana.common.rest.RestHelper.TEMPLATE;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.Instant;
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
@ -17,7 +17,6 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import pro.taskana.common.rest.Mapping;
import pro.taskana.common.rest.RestHelper;
@ -42,46 +41,49 @@ class WorkbasketControllerIntTest {
WORKBASKET_SUMMARY_PAGE_MODEL_TYPE =
new ParameterizedTypeReference<
TaskanaPagedModel<WorkbasketSummaryRepresentationModel>>() {};
private static RestTemplate template;
@Autowired RestHelper restHelper;
private final RestHelper restHelper;
private final ObjectMapper mapper;
@BeforeAll
static void init() {
template = RestHelper.TEMPLATE;
@Autowired
WorkbasketControllerIntTest(RestHelper restHelper, ObjectMapper mapper) {
this.restHelper = restHelper;
this.mapper = mapper;
}
@Test
void testGetWorkbasket() {
ResponseEntity<WorkbasketRepresentationModel> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET_ID, "WBI:100000000000000000000000000000000006"),
HttpMethod.GET,
restHelper.defaultRequest(),
ParameterizedTypeReference.forType(WorkbasketRepresentationModel.class));
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getHeaders().getContentType().toString())
.isEqualTo(MediaTypes.HAL_JSON_VALUE);
assertThat(response.getHeaders().getContentType()).isEqualTo(MediaTypes.HAL_JSON);
}
@Test
void testGetAllWorkbaskets() {
ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET),
HttpMethod.GET,
restHelper.defaultRequest(),
WORKBASKET_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull();
}
@Test
void testGetAllWorkbasketsBusinessAdminHasOpenPermission() {
ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET) + "?required-permission=OPEN",
HttpMethod.GET,
restHelper.defaultRequest(),
WORKBASKET_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getRequiredLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getContent()).hasSize(3);
}
@ -90,11 +92,12 @@ class WorkbasketControllerIntTest {
void testGetAllWorkbasketsKeepingFilters() {
String parameters = "?type=PERSONAL&sort-by=key&order=desc";
ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET) + parameters,
HttpMethod.GET,
restHelper.defaultRequest(),
WORKBASKET_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(
response
@ -108,7 +111,8 @@ class WorkbasketControllerIntTest {
@Test
void testThrowsExceptionIfInvalidFilterIsUsed() {
ThrowingCallable httpCall =
() -> template.exchange(
() ->
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET) + "?invalid=PERSONAL",
HttpMethod.GET,
restHelper.defaultRequest(),
@ -125,10 +129,8 @@ class WorkbasketControllerIntTest {
String workbasketId = "WBI:100000000000000000000000000000000001";
final ObjectMapper mapper = new ObjectMapper();
ResponseEntity<WorkbasketRepresentationModel> initialWorkbasketResourceRequestResponse =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET_ID, workbasketId),
HttpMethod.GET,
new HttpEntity<String>(restHelper.getHeaders()),
@ -137,16 +139,17 @@ class WorkbasketControllerIntTest {
WorkbasketRepresentationModel workbasketRepresentationModel =
initialWorkbasketResourceRequestResponse.getBody();
assertThat(workbasketRepresentationModel).isNotNull();
workbasketRepresentationModel.setKey("GPK_KSC");
workbasketRepresentationModel.setDomain("DOMAIN_A");
workbasketRepresentationModel.setType(WorkbasketType.PERSONAL);
workbasketRepresentationModel.setName("was auch immer");
workbasketRepresentationModel.setOwner("Joerg");
workbasketRepresentationModel.setModified(String.valueOf(Instant.now()));
workbasketRepresentationModel.setModified(Instant.now());
ThrowingCallable httpCall =
() -> {
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET_ID, workbasketId),
HttpMethod.PUT,
new HttpEntity<>(
@ -166,7 +169,7 @@ class WorkbasketControllerIntTest {
ThrowingCallable httpCall =
() -> {
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET_ID, workbasketId),
HttpMethod.GET,
new HttpEntity<String>(restHelper.getHeaders()),
@ -183,11 +186,12 @@ class WorkbasketControllerIntTest {
String parameters = "?sort-by=key&order=desc&page-size=5&page=2";
ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET) + parameters,
HttpMethod.GET,
restHelper.defaultRequest(),
WORKBASKET_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getContent()).hasSize(5);
assertThat(response.getBody().getContent().iterator().next().getKey()).isEqualTo("USER_1_1");
assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull();
@ -210,7 +214,7 @@ class WorkbasketControllerIntTest {
String workbasketID = "WBI:100000000000000000000000000000000005";
ResponseEntity<?> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET_ID, workbasketID),
HttpMethod.DELETE,
new HttpEntity<>(restHelper.getHeadersBusinessAdmin()),
@ -224,7 +228,7 @@ class WorkbasketControllerIntTest {
ThrowingCallable call =
() ->
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET_ID, workbasketWithNonCompletedTasks),
HttpMethod.DELETE,
new HttpEntity<>(restHelper.getHeadersBusinessAdmin()),
@ -238,7 +242,7 @@ class WorkbasketControllerIntTest {
@Test
void testRemoveWorkbasketAsDistributionTarget() {
ResponseEntity<?> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(
Mapping.URL_WORKBASKET_ID_DISTRIBUTION, "WBI:100000000000000000000000000000000007"),
HttpMethod.DELETE,
@ -247,47 +251,47 @@ class WorkbasketControllerIntTest {
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> response2 =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(
Mapping.URL_WORKBASKET_ID_DISTRIBUTION, "WBI:100000000000000000000000000000000002"),
HttpMethod.GET,
restHelper.defaultRequest(),
WORKBASKET_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response2.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(
response2.getBody().getContent().stream()
.map(WorkbasketSummaryRepresentationModel::getWorkbasketId)
.noneMatch("WBI:100000000000000000000000000000000007"::equals))
.isTrue();
assertThat(response2.getBody()).isNotNull();
assertThat(response2.getBody().getContent())
.extracting(WorkbasketSummaryRepresentationModel::getWorkbasketId)
.doesNotContain("WBI:100000000000000000000000000000000007");
}
@Test
void testGetWorkbasketAccessItems() {
ResponseEntity<TaskanaPagedModel<WorkbasketAccessItemRepresentationModel>> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(
Mapping.URL_WORKBASKET_ID_ACCESSITEMS, "WBI:100000000000000000000000000000000005"),
HttpMethod.GET,
restHelper.defaultRequest(),
WORKBASKET_ACCESS_ITEM_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getHeaders().getContentType().toString())
.isEqualTo(MediaTypes.HAL_JSON_VALUE);
assertThat(response.getHeaders().getContentType()).isEqualTo(MediaTypes.HAL_JSON);
assertThat(response.getBody().getContent()).hasSize(3);
}
@Test
void testGetWorkbasketDistributionTargets() {
ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> response =
template.exchange(
TEMPLATE.exchange(
restHelper.toUrl(
Mapping.URL_WORKBASKET_ID_DISTRIBUTION, "WBI:100000000000000000000000000000000001"),
HttpMethod.GET,
restHelper.defaultRequest(),
WORKBASKET_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getHeaders().getContentType().toString())
.isEqualTo(MediaTypes.HAL_JSON_VALUE);
assertThat(response.getHeaders().getContentType())
.isEqualTo(MediaTypes.HAL_JSON);
assertThat(response.getBody().getContent()).hasSize(4);
}
}

View File

@ -3,22 +3,21 @@ package pro.taskana.workbasket.rest;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.fail;
import static pro.taskana.common.rest.RestHelper.TEMPLATE;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import javax.sql.DataSource;
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
@ -34,11 +33,13 @@ import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.client.HttpStatusCodeException;
import pro.taskana.common.rest.Mapping;
import pro.taskana.common.rest.RestHelper;
import pro.taskana.common.rest.TaskanaSpringBootTest;
import pro.taskana.common.rest.models.TaskanaPagedModel;
import pro.taskana.common.rest.models.TaskanaPagedModelKeys;
import pro.taskana.sampledata.SampleDataGenerator;
import pro.taskana.workbasket.rest.models.WorkbasketDefinitionRepresentationModel;
@ -46,20 +47,19 @@ import pro.taskana.workbasket.rest.models.WorkbasketDefinitionRepresentationMode
@TaskanaSpringBootTest
class WorkbasketDefinitionControllerIntTest {
private static RestTemplate template;
private final ObjectMapper objMapper;
private final RestHelper restHelper;
private final DataSource dataSource;
@Value("${taskana.schemaName:TASKANA}")
String schemaName;
ObjectMapper objMapper = new ObjectMapper();
@Autowired RestHelper restHelper;
@Autowired private DataSource dataSource;
@BeforeAll
static void init() {
template = RestHelper.TEMPLATE;
@Autowired
WorkbasketDefinitionControllerIntTest(
ObjectMapper objMapper, RestHelper restHelper, DataSource dataSource) {
this.objMapper = objMapper;
this.restHelper = restHelper;
this.dataSource = dataSource;
}
@BeforeEach
@ -70,17 +70,18 @@ class WorkbasketDefinitionControllerIntTest {
@Test
void testExportWorkbasketFromDomain() {
ResponseEntity<List<WorkbasketDefinitionRepresentationModel>> response =
ResponseEntity<TaskanaPagedModel<WorkbasketDefinitionRepresentationModel>> response =
executeExportRequestForDomain("DOMAIN_A");
assertThat(response.getBody()).isNotNull();
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody().get(0))
.isInstanceOf(WorkbasketDefinitionRepresentationModel.class);
assertThat(response.getBody().getContent())
.hasOnlyElementsOfType(WorkbasketDefinitionRepresentationModel.class);
boolean allAuthorizationsAreEmpty = true;
boolean allDistributionTargetsAreEmpty = true;
for (WorkbasketDefinitionRepresentationModel workbasketDefinition : response.getBody()) {
for (WorkbasketDefinitionRepresentationModel workbasketDefinition :
response.getBody().getContent()) {
if (allAuthorizationsAreEmpty && !workbasketDefinition.getAuthorizations().isEmpty()) {
allAuthorizationsAreEmpty = false;
}
@ -98,24 +99,29 @@ class WorkbasketDefinitionControllerIntTest {
@Test
void testExportWorkbasketsFromWrongDomain() {
ResponseEntity<List<WorkbasketDefinitionRepresentationModel>> response =
ResponseEntity<TaskanaPagedModel<WorkbasketDefinitionRepresentationModel>> response =
executeExportRequestForDomain("wrongDomain");
assertThat(response.getBody()).isEmpty();
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getContent()).isEmpty();
assertThat(response.getBody().getKey()).isSameAs(TaskanaPagedModelKeys.WORKBASKET_DEFINITIONS);
}
@Test
void testImportEveryWorkbasketFromDomainA() throws IOException {
List<WorkbasketDefinitionRepresentationModel> wbList =
TaskanaPagedModel<WorkbasketDefinitionRepresentationModel> wbList =
executeExportRequestForDomain("DOMAIN_A").getBody();
for (WorkbasketDefinitionRepresentationModel w : wbList) {
assertThat(wbList).isNotNull();
for (WorkbasketDefinitionRepresentationModel w : wbList.getContent()) {
expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.NO_CONTENT, w);
}
}
@Test
void testImportWorkbasketWithoutDistributionTargets() throws IOException {
WorkbasketDefinitionRepresentationModel w =
executeExportRequestForDomain("DOMAIN_A").getBody().get(0);
TaskanaPagedModel<WorkbasketDefinitionRepresentationModel> pagedModel =
executeExportRequestForDomain("DOMAIN_A").getBody();
assertThat(pagedModel).isNotNull();
WorkbasketDefinitionRepresentationModel w = pagedModel.getContent().iterator().next();
w.setDistributionTargets(new HashSet<>());
this.expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.NO_CONTENT, w);
@ -127,13 +133,15 @@ class WorkbasketDefinitionControllerIntTest {
@Test
void testImportWorkbasketWithDistributionTargetsInImportFile() throws IOException {
List<WorkbasketDefinitionRepresentationModel> wbList =
TaskanaPagedModel<WorkbasketDefinitionRepresentationModel> wbList =
executeExportRequestForDomain("DOMAIN_A").getBody();
assertThat(wbList).isNotNull();
Iterator<WorkbasketDefinitionRepresentationModel> iterator = wbList.getContent().iterator();
WorkbasketDefinitionRepresentationModel w = wbList.get(0);
WorkbasketDefinitionRepresentationModel w = iterator.next();
w.setDistributionTargets(new HashSet<>());
String letMeBeYourDistributionTarget = w.getWorkbasket().getWorkbasketId();
WorkbasketDefinitionRepresentationModel w2 = wbList.get(1);
WorkbasketDefinitionRepresentationModel w2 = iterator.next();
w2.setDistributionTargets(Collections.singleton(letMeBeYourDistributionTarget));
expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.NO_CONTENT, w, w2);
@ -150,11 +158,14 @@ class WorkbasketDefinitionControllerIntTest {
@Test
void testImportWorkbasketWithDistributionTargetsInSystem() throws IOException {
List<WorkbasketDefinitionRepresentationModel> wbList =
TaskanaPagedModel<WorkbasketDefinitionRepresentationModel> wbList =
executeExportRequestForDomain("DOMAIN_A").getBody();
wbList.removeIf(definition -> definition.getDistributionTargets().isEmpty());
WorkbasketDefinitionRepresentationModel w = wbList.get(0);
assertThat(wbList).isNotNull();
List<WorkbasketDefinitionRepresentationModel> content = new ArrayList<>(wbList.getContent());
content.removeIf(definition -> definition.getDistributionTargets().isEmpty());
WorkbasketDefinitionRepresentationModel w = content.iterator().next();
expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.NO_CONTENT, w);
changeWorkbasketIdOrKey(w, null, "new");
@ -163,50 +174,58 @@ class WorkbasketDefinitionControllerIntTest {
@Test
void testImportWorkbasketWithDistributionTargetsNotInSystem() throws IOException {
List<WorkbasketDefinitionRepresentationModel> wbList =
TaskanaPagedModel<WorkbasketDefinitionRepresentationModel> wbList =
executeExportRequestForDomain("DOMAIN_A").getBody();
WorkbasketDefinitionRepresentationModel w = wbList.get(0);
assertThat(wbList).isNotNull();
WorkbasketDefinitionRepresentationModel w = wbList.getContent().iterator().next();
w.setDistributionTargets(Collections.singleton("invalidWorkbasketId"));
try {
expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.BAD_REQUEST, w);
fail("Expected http-Status 400");
} catch (HttpClientErrorException e) {
assertThat(e.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
}
ThrowingCallable httpCall =
() -> expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.BAD_REQUEST, w);
assertThatThrownBy(httpCall)
.isInstanceOf(HttpClientErrorException.class)
.extracting(e -> (HttpClientErrorException) e)
.extracting(HttpStatusCodeException::getStatusCode)
.isEqualTo(HttpStatus.BAD_REQUEST);
w.getWorkbasket().setKey("anotherNewKey");
try {
expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.BAD_REQUEST, w);
fail("Expected http-Status 400");
} catch (HttpClientErrorException e) {
assertThat(e.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
}
assertThatThrownBy(httpCall)
.isInstanceOf(HttpClientErrorException.class)
.extracting(e -> (HttpClientErrorException) e)
.extracting(HttpStatusCodeException::getStatusCode)
.isEqualTo(HttpStatus.BAD_REQUEST);
}
@Test
void testFailOnImportDuplicates() throws IOException {
WorkbasketDefinitionRepresentationModel w =
executeExportRequestForDomain("DOMAIN_A").getBody().get(0);
try {
expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.CONFLICT, w, w);
fail("Expected http-Status 409");
} catch (HttpClientErrorException e) {
assertThat(e.getStatusCode()).isEqualTo(HttpStatus.CONFLICT);
}
TaskanaPagedModel<WorkbasketDefinitionRepresentationModel> pagedModel =
executeExportRequestForDomain("DOMAIN_A").getBody();
assertThat(pagedModel).isNotNull();
WorkbasketDefinitionRepresentationModel w = pagedModel.getContent().iterator().next();
ThrowingCallable httpCall =
() -> expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.CONFLICT, w, w);
assertThatThrownBy(httpCall)
.isInstanceOf(HttpClientErrorException.class)
.extracting(e -> (HttpClientErrorException) e)
.extracting(HttpStatusCodeException::getStatusCode)
.isEqualTo(HttpStatus.CONFLICT);
}
@Test
void testNoErrorWhenImportWithSameIdButDifferentKeyAndDomain() throws IOException {
List<WorkbasketDefinitionRepresentationModel> wbList =
TaskanaPagedModel<WorkbasketDefinitionRepresentationModel> wbList =
executeExportRequestForDomain("DOMAIN_A").getBody();
WorkbasketDefinitionRepresentationModel w = wbList.get(0);
WorkbasketDefinitionRepresentationModel differentLogicalId = wbList.get(1);
assertThat(wbList).isNotNull();
Iterator<WorkbasketDefinitionRepresentationModel> iterator = wbList.getContent().iterator();
WorkbasketDefinitionRepresentationModel w = iterator.next();
WorkbasketDefinitionRepresentationModel differentLogicalId = iterator.next();
this.changeWorkbasketIdOrKey(differentLogicalId, w.getWorkbasket().getWorkbasketId(), null);
// breaks the logic but not the script- should we really allow this case?
WorkbasketDefinitionRepresentationModel theDestroyer = wbList.get(2);
WorkbasketDefinitionRepresentationModel theDestroyer = iterator.next();
theDestroyer.setDistributionTargets(
Collections.singleton(differentLogicalId.getWorkbasket().getWorkbasketId()));
@ -216,16 +235,15 @@ class WorkbasketDefinitionControllerIntTest {
@Test
void testErrorWhenImportWithSameAccessIdAndWorkbasket() {
WorkbasketDefinitionRepresentationModel w =
executeExportRequestForDomain("DOMAIN_A").getBody().get(0);
TaskanaPagedModel<WorkbasketDefinitionRepresentationModel> pagedModel =
executeExportRequestForDomain("DOMAIN_A").getBody();
assertThat(pagedModel).isNotNull();
WorkbasketDefinitionRepresentationModel w = pagedModel.getContent().iterator().next();
String w1String = workbasketToString(w);
w.getWorkbasket().setKey("new Key for this WB");
String w2String = workbasketToString(w);
ThrowingCallable httpCall =
() -> {
expectStatusWhenExecutingImportRequestOfWorkbaskets(
HttpStatus.CONFLICT, Arrays.asList(w1String, w2String));
expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.CONFLICT, w, w);
};
assertThatThrownBy(httpCall).isInstanceOf(HttpClientErrorException.class);
}
@ -242,30 +260,33 @@ class WorkbasketDefinitionControllerIntTest {
}
}
private ResponseEntity<List<WorkbasketDefinitionRepresentationModel>>
private ResponseEntity<TaskanaPagedModel<WorkbasketDefinitionRepresentationModel>>
executeExportRequestForDomain(String domain) {
return template.exchange(
return TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKETDEFIITIONS) + "?domain=" + domain,
HttpMethod.GET,
restHelper.defaultRequest(),
new ParameterizedTypeReference<List<WorkbasketDefinitionRepresentationModel>>() {});
new ParameterizedTypeReference<
TaskanaPagedModel<WorkbasketDefinitionRepresentationModel>>() {});
}
private void expectStatusWhenExecutingImportRequestOfWorkbaskets(
HttpStatus expectedStatus, WorkbasketDefinitionRepresentationModel... workbaskets)
throws IOException {
List<String> workbasketStrings =
Arrays.stream(workbaskets).map(this::workbasketToString).collect(Collectors.toList());
expectStatusWhenExecutingImportRequestOfWorkbaskets(expectedStatus, workbasketStrings);
TaskanaPagedModel<WorkbasketDefinitionRepresentationModel> pagedModel =
new TaskanaPagedModel<>(
TaskanaPagedModelKeys.WORKBASKET_DEFINITIONS, Arrays.asList(workbaskets));
expectStatusWhenExecutingImportRequestOfWorkbaskets(expectedStatus, pagedModel);
}
private void expectStatusWhenExecutingImportRequestOfWorkbaskets(
HttpStatus expectedStatus, List<String> workbasketStrings) throws IOException {
HttpStatus expectedStatus,
TaskanaPagedModel<WorkbasketDefinitionRepresentationModel> pageModel)
throws IOException {
File tmpFile = File.createTempFile("test", ".tmp");
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(tmpFile), UTF_8);
writer.write(workbasketStrings.toString());
writer.close();
try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(tmpFile), UTF_8)) {
objMapper.writeValue(writer, pageModel);
}
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
HttpHeaders headers = restHelper.getHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
@ -275,16 +296,7 @@ class WorkbasketDefinitionControllerIntTest {
String serverUrl = restHelper.toUrl(Mapping.URL_WORKBASKETDEFIITIONS);
ResponseEntity<Void> responseImport =
template.postForEntity(serverUrl, requestEntity, Void.class);
TEMPLATE.postForEntity(serverUrl, requestEntity, Void.class);
assertThat(responseImport.getStatusCode()).isEqualTo(expectedStatus);
}
private String workbasketToString(
WorkbasketDefinitionRepresentationModel workbasketDefinitionRepresentationModel) {
try {
return objMapper.writeValueAsString(workbasketDefinitionRepresentationModel);
} catch (JsonProcessingException e) {
return "";
}
}
}

View File

@ -18,8 +18,16 @@ import pro.taskana.workbasket.rest.models.WorkbasketRepresentationModel;
@TaskanaSpringBootTest
class WorkbasketRepresentationModelAssemblerTest {
@Autowired WorkbasketService workbasketService;
@Autowired WorkbasketRepresentationModelAssembler workbasketRepresentationModelAssembler;
private final WorkbasketService workbasketService;
private final WorkbasketRepresentationModelAssembler workbasketRepresentationModelAssembler;
@Autowired
WorkbasketRepresentationModelAssemblerTest(
WorkbasketService workbasketService,
WorkbasketRepresentationModelAssembler workbasketRepresentationModelAssembler) {
this.workbasketService = workbasketService;
this.workbasketRepresentationModelAssembler = workbasketRepresentationModelAssembler;
}
@Test
void workbasketToResource() {
@ -53,7 +61,7 @@ class WorkbasketRepresentationModelAssemblerTest {
// given
WorkbasketRepresentationModel resource = new WorkbasketRepresentationModel();
resource.setWorkbasketId("1");
resource.setModified("2010-01-01T12:00:00Z");
resource.setModified(Instant.parse("2010-01-01T12:00:00Z"));
resource.setType(WorkbasketType.PERSONAL);
// when
Workbasket workbasket = workbasketRepresentationModelAssembler.toEntityModel(resource);
@ -66,7 +74,7 @@ class WorkbasketRepresentationModelAssemblerTest {
// given
WorkbasketRepresentationModel resource = new WorkbasketRepresentationModel();
resource.setWorkbasketId("1");
resource.setCreated("2010-01-01T12:00:00Z");
resource.setCreated(Instant.parse("2010-01-01T12:00:00Z"));
resource.setType(WorkbasketType.PERSONAL);
// when
Workbasket workbasket = workbasketRepresentationModelAssembler.toEntityModel(resource);
@ -80,8 +88,8 @@ class WorkbasketRepresentationModelAssemblerTest {
WorkbasketRepresentationModel workbasketRepresentationModel =
new WorkbasketRepresentationModel();
workbasketRepresentationModel.setWorkbasketId("1");
workbasketRepresentationModel.setCreated("2010-01-01T12:00:00Z");
workbasketRepresentationModel.setModified("2010-01-01T12:00:00Z");
workbasketRepresentationModel.setCreated(Instant.parse("2010-01-01T12:00:00Z"));
workbasketRepresentationModel.setModified(Instant.parse("2010-01-01T12:00:00Z"));
workbasketRepresentationModel.setCustom1("Custom1");
workbasketRepresentationModel.setCustom2("Custom2");
workbasketRepresentationModel.setCustom3("Custom3");
@ -124,9 +132,9 @@ class WorkbasketRepresentationModelAssemblerTest {
assertThat(workbasketRepresentationModel.getWorkbasketId()).isEqualTo(workbasket.getId());
assertThat(workbasketRepresentationModel.getKey()).isEqualTo(workbasket.getKey());
assertThat(workbasketRepresentationModel.getCreated())
.isEqualTo(workbasket.getCreated() == null ? null : workbasket.getCreated().toString());
.isEqualTo(workbasket.getCreated());
assertThat(workbasketRepresentationModel.getModified())
.isEqualTo(workbasket.getModified() == null ? null : workbasket.getModified().toString());
.isEqualTo(workbasket.getModified());
assertThat(workbasketRepresentationModel.getName()).isEqualTo(workbasket.getName());
assertThat(workbasketRepresentationModel.getDescription())
.isEqualTo(workbasket.getDescription());