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.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.ZoneId; import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.LongStream; 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.CustomHoliday;
import pro.taskana.common.api.exceptions.InvalidArgumentException; import pro.taskana.common.api.exceptions.InvalidArgumentException;
@ -37,6 +36,15 @@ public final class WorkingDaysToDaysConverter {
private static boolean germanHolidaysEnabled; private static boolean germanHolidaysEnabled;
private static boolean corpusChristiEnabled; // Fronleichnam private static boolean corpusChristiEnabled; // Fronleichnam
private static Set<CustomHoliday> customHolidays = new HashSet<>(); 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 Instant referenceDate;
private LocalDate easterSunday; private LocalDate easterSunday;
@ -127,7 +135,7 @@ public final class WorkingDaysToDaysConverter {
return instant.plus(Duration.ofDays(days)); 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) { public boolean hasWorkingDaysInBetween(Instant left, Instant right) {
long days = Duration.between(left, right).abs().toDays(); long days = Duration.between(left, right).abs().toDays();
Instant firstInstant = left.isBefore(right) ? left : right; Instant firstInstant = left.isBefore(right) ? left : right;
@ -155,28 +163,25 @@ public final class WorkingDaysToDaysConverter {
} }
public boolean isGermanHoliday(LocalDate date) { public boolean isGermanHoliday(LocalDate date) {
// Fix and movable holidays that are valid throughout Germany: New years day, Labour Day, Day of if (germanHolidays.contains(CustomHoliday.of(date.getDayOfMonth(), date.getMonthValue()))) {
// German
// Unity, Christmas,
if (Stream.of(GermanFixHolidays.values()).anyMatch(day -> day.matches(date))) {
return true; return true;
} }
// Easter holidays Good Friday, Easter Monday, Ascension Day, Whit Monday. // Easter holidays Good Friday, Easter Monday, Ascension Day, Whit Monday.
long diffFromEasterSunday = DAYS.between(easterSunday, date); long diffFromEasterSunday = DAYS.between(easterSunday, date);
List<Long> offSets = Builder builder =
new ArrayList<>( LongStream.builder()
Arrays.asList( .add(OFFSET_GOOD_FRIDAY)
OFFSET_GOOD_FRIDAY, .add(OFFSET_EASTER_MONDAY)
OFFSET_EASTER_MONDAY, .add(OFFSET_ASCENSION_DAY)
OFFSET_ASCENSION_DAY, .add(OFFSET_WHIT_MONDAY);
OFFSET_WHIT_MONDAY));
if (corpusChristiEnabled) { 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); 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) { void refreshReferenceDate(Instant newReferenceDate) {
int yearOfReferenceDate = int yearOfReferenceDate =
LocalDateTime.ofInstant(referenceDate, ZoneId.systemDefault()).getYear(); LocalDateTime.ofInstant(referenceDate, ZoneId.systemDefault()).getYear();
@ -227,14 +224,21 @@ public final class WorkingDaysToDaysConverter {
this.referenceDate = newReferenceDate; this.referenceDate = newReferenceDate;
} }
private int calculateDirection(long numberOfDays, ZeroDirection zeroDirection) {
if (numberOfDays == 0) {
return zeroDirection.getDirection();
} else {
return numberOfDays >= 0 ? 1 : -1;
}
}
@Override @Override
public String toString() { public String toString() {
return "WorkingDaysToDaysConverter{" return "WorkingDaysToDaysConverter [referenceDate="
+ "dateCreated="
+ referenceDate + referenceDate
+ ", easterSunday=" + ", easterSunday="
+ easterSunday + easterSunday
+ '}'; + "]";
} }
private enum ZeroDirection { private enum ZeroDirection {
@ -251,25 +255,4 @@ public final class WorkingDaysToDaysConverter {
return direction; 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 ); 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 -- 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: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' , 'DOM_XY' , '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' , 'DOM_XY' , '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' , 'DOM_XY' , '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' , 'DOM_XY' , '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' , 'DOM_XY' , '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' , 'DOM_XY' , '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' , 'DOM_XY' , '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' , 'DOM_XY' , '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' , 'DOM_XY' , '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); 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 -- 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: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', 'DOM_XY', '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', 'DOM_XY', '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', 'DOM_XY', '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', 'DOM_XY', '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', 'DOM_XY', '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', 'DOM_XY', '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', 'DOM_XY', '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', 'DOM_XY', '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', 'DOM_XY', '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.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.SerializationFeature;
import com.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.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.hateoas.MediaTypes;
import org.springframework.hateoas.mediatype.hal.Jackson2HalModule; import org.springframework.hateoas.mediatype.hal.Jackson2HalModule;
import org.springframework.http.HttpEntity; import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
@ -67,9 +71,13 @@ public class RestHelper {
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
mapper.registerModule(new Jackson2HalModule()); mapper.registerModule(new Jackson2HalModule());
mapper
.registerModule(new ParameterNamesModule())
.registerModule(new Jdk8Module())
.registerModule(new JavaTimeModule());
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(MediaType.parseMediaTypes("application/hal+json")); converter.setSupportedMediaTypes(Collections.singletonList(MediaTypes.HAL_JSON));
converter.setObjectMapper(mapper); converter.setObjectMapper(mapper);
RestTemplate template = new RestTemplate(); RestTemplate template = new RestTemplate();

View File

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

View File

@ -1,10 +1,12 @@
package pro.taskana.classification.rest; 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.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -13,6 +15,7 @@ import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException; import org.springframework.dao.DuplicateKeyException;
import org.springframework.hateoas.config.EnableHypermediaSupport; import org.springframework.hateoas.config.EnableHypermediaSupport;
import org.springframework.http.ResponseEntity; 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.InvalidArgumentException;
import pro.taskana.common.api.exceptions.NotAuthorizedException; import pro.taskana.common.api.exceptions.NotAuthorizedException;
import pro.taskana.common.rest.Mapping; import pro.taskana.common.rest.Mapping;
import pro.taskana.common.rest.models.TaskanaPagedModel;
/** Controller for Importing / Exporting classifications. */ /** Controller for Importing / Exporting classifications. */
@SuppressWarnings("unused") @SuppressWarnings("unused")
@ -47,37 +51,41 @@ public class ClassificationDefinitionController {
private static final Logger LOGGER = private static final Logger LOGGER =
LoggerFactory.getLogger(ClassificationDefinitionController.class); LoggerFactory.getLogger(ClassificationDefinitionController.class);
private final ObjectMapper mapper;
private final ClassificationService classificationService; private final ClassificationService classificationService;
private final ClassificationRepresentationModelAssembler private final ClassificationRepresentationModelAssembler
classificationRepresentationModelAssembler; classificationRepresentationModelAssembler;
@Autowired
ClassificationDefinitionController( ClassificationDefinitionController(
ObjectMapper mapper,
ClassificationService classificationService, ClassificationService classificationService,
ClassificationRepresentationModelAssembler classificationRepresentationModelAssembler) { ClassificationRepresentationModelAssembler classificationRepresentationModelAssembler) {
this.mapper = mapper;
this.classificationService = classificationService; this.classificationService = classificationService;
this.classificationRepresentationModelAssembler = classificationRepresentationModelAssembler; this.classificationRepresentationModelAssembler = classificationRepresentationModelAssembler;
} }
@GetMapping(path = Mapping.URL_CLASSIFICATIONDEFINITION) @GetMapping(path = Mapping.URL_CLASSIFICATIONDEFINITION)
@Transactional(readOnly = true, rollbackFor = Exception.class) @Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<List<ClassificationRepresentationModel>> exportClassifications( public ResponseEntity<TaskanaPagedModel<ClassificationRepresentationModel>> exportClassifications(
@RequestParam(required = false) String domain) throws ClassificationNotFoundException { @RequestParam(required = false) String domain) throws ClassificationNotFoundException {
LOGGER.debug("Entry to exportClassifications(domain= {})", domain); LOGGER.debug("Entry to exportClassifications(domain= {})", domain);
ClassificationQuery query = classificationService.createClassificationQuery(); ClassificationQuery query = classificationService.createClassificationQuery();
List<ClassificationSummary> summaries = List<ClassificationSummary> summaries =
domain != null ? query.domainIn(domain).list() : query.list(); domain != null ? query.domainIn(domain).list() : query.list();
List<ClassificationRepresentationModel> export = new ArrayList<>();
for (ClassificationSummary summary : summaries) { TaskanaPagedModel<ClassificationRepresentationModel> pageModel =
Classification classification = summaries.stream()
classificationService.getClassification(summary.getKey(), summary.getDomain()); .map(ClassificationSummary::getId)
.map(wrap(classificationService::getClassification))
.collect(
Collectors.collectingAndThen(
Collectors.toList(), classificationRepresentationModelAssembler::toPageModel));
export.add(classificationRepresentationModelAssembler.toModel(classification)); ResponseEntity<TaskanaPagedModel<ClassificationRepresentationModel>> response =
} ResponseEntity.ok(pageModel);
ResponseEntity<List<ClassificationRepresentationModel>> response = ResponseEntity.ok(export);
if (LOGGER.isDebugEnabled()) { if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Exit from exportClassifications(), returning {}", response); LOGGER.debug("Exit from exportClassifications(), returning {}", response);
} }
@ -93,13 +101,13 @@ public class ClassificationDefinitionController {
DomainNotFoundException, IOException { DomainNotFoundException, IOException {
LOGGER.debug("Entry to importClassifications()"); LOGGER.debug("Entry to importClassifications()");
Map<String, String> systemIds = getSystemIds(); Map<String, String> systemIds = getSystemIds();
List<ClassificationRepresentationModel> classificationsResources = TaskanaPagedModel<ClassificationRepresentationModel> classificationsResources =
extractClassificationResourcesFromFile(file); extractClassificationResourcesFromFile(file);
checkForDuplicates(classificationsResources); checkForDuplicates(classificationsResources.getContent());
Map<Classification, String> childrenInFile = Map<Classification, String> childrenInFile =
mapChildrenToParentKeys(classificationsResources, systemIds); mapChildrenToParentKeys(classificationsResources.getContent(), systemIds);
insertOrUpdateClassificationsWithoutParent(classificationsResources, systemIds); insertOrUpdateClassificationsWithoutParent(classificationsResources.getContent(), systemIds);
updateParentChildrenRelations(childrenInFile); updateParentChildrenRelations(childrenInFile);
ResponseEntity<Void> response = ResponseEntity.noContent().build(); ResponseEntity<Void> response = ResponseEntity.noContent().build();
LOGGER.debug("Exit from importClassifications(), returning {}", response); LOGGER.debug("Exit from importClassifications(), returning {}", response);
@ -112,15 +120,15 @@ public class ClassificationDefinitionController {
Collectors.toMap(i -> i.getKey() + "|" + i.getDomain(), ClassificationSummary::getId)); Collectors.toMap(i -> i.getKey() + "|" + i.getDomain(), ClassificationSummary::getId));
} }
private List<ClassificationRepresentationModel> extractClassificationResourcesFromFile( private TaskanaPagedModel<ClassificationRepresentationModel>
MultipartFile file) throws IOException { extractClassificationResourcesFromFile(MultipartFile file) throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return mapper.readValue( 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<>(); List<String> identifiers = new ArrayList<>();
Set<String> duplicates = new HashSet<>(); Set<String> duplicates = new HashSet<>();
for (ClassificationRepresentationModel classification : classificationList) { for (ClassificationRepresentationModel classification : classificationList) {
@ -138,7 +146,7 @@ public class ClassificationDefinitionController {
} }
private Map<Classification, String> mapChildrenToParentKeys( private Map<Classification, String> mapChildrenToParentKeys(
List<ClassificationRepresentationModel> classificationRepresentationModels, Collection<ClassificationRepresentationModel> classificationRepresentationModels,
Map<String, String> systemIds) { Map<String, String> systemIds) {
LOGGER.debug("Entry to mapChildrenToParentKeys()"); LOGGER.debug("Entry to mapChildrenToParentKeys()");
Map<Classification, String> childrenInFile = new HashMap<>(); Map<Classification, String> childrenInFile = new HashMap<>();
@ -159,8 +167,9 @@ public class ClassificationDefinitionController {
} }
String parentKeyAndDomain = cl.getParentKey() + "|" + cl.getDomain(); String parentKeyAndDomain = cl.getParentKey() + "|" + cl.getDomain();
if ((!cl.getParentKey().isEmpty() && !cl.getParentKey().equals("") && ( if ((!cl.getParentKey().isEmpty()
newKeysWithDomain.contains(parentKeyAndDomain) && !cl.getParentKey().equals("")
&& (newKeysWithDomain.contains(parentKeyAndDomain)
|| systemIds.containsKey(parentKeyAndDomain)))) { || systemIds.containsKey(parentKeyAndDomain)))) {
childrenInFile.put( childrenInFile.put(
classificationRepresentationModelAssembler.toEntityModel(cl), cl.getParentKey()); classificationRepresentationModelAssembler.toEntityModel(cl), cl.getParentKey());
@ -176,7 +185,7 @@ public class ClassificationDefinitionController {
} }
private void insertOrUpdateClassificationsWithoutParent( private void insertOrUpdateClassificationsWithoutParent(
List<ClassificationRepresentationModel> classificationRepresentationModels, Collection<ClassificationRepresentationModel> classificationRepresentationModels,
Map<String, String> systemIds) Map<String, String> systemIds)
throws ClassificationNotFoundException, NotAuthorizedException, InvalidArgumentException, throws ClassificationNotFoundException, NotAuthorizedException, InvalidArgumentException,
ClassificationAlreadyExistException, DomainNotFoundException, ConcurrencyException { ClassificationAlreadyExistException, DomainNotFoundException, ConcurrencyException {
@ -197,8 +206,8 @@ public class ClassificationDefinitionController {
updateExistingClassification(classificationRepresentationModel, systemId); updateExistingClassification(classificationRepresentationModel, systemId);
} else { } else {
classificationService.createClassification( classificationService.createClassification(
classificationRepresentationModelAssembler classificationRepresentationModelAssembler.toEntityModel(
.toEntityModel(classificationRepresentationModel)); classificationRepresentationModel));
} }
} }
LOGGER.debug("Exit from insertOrUpdateClassificationsWithoutParent()"); 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 static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
import java.time.Instant;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.server.RepresentationModelAssembler;
import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component; 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.ClassificationController;
import pro.taskana.classification.rest.models.ClassificationRepresentationModel; import pro.taskana.classification.rest.models.ClassificationRepresentationModel;
import pro.taskana.common.api.exceptions.SystemException; 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 * Transforms {@link Classification} to its resource counterpart {@link
@ -24,13 +24,12 @@ import pro.taskana.common.api.exceptions.SystemException;
*/ */
@Component @Component
public class ClassificationRepresentationModelAssembler public class ClassificationRepresentationModelAssembler
implements RepresentationModelAssembler<Classification, ClassificationRepresentationModel> { implements TaskanaPagingAssembler<Classification, ClassificationRepresentationModel> {
final ClassificationService classificationService; final ClassificationService classificationService;
@Autowired @Autowired
public ClassificationRepresentationModelAssembler( public ClassificationRepresentationModelAssembler(ClassificationService classificationService) {
ClassificationService classificationService) {
this.classificationService = classificationService; this.classificationService = classificationService;
} }
@ -42,7 +41,8 @@ public class ClassificationRepresentationModelAssembler
try { try {
resource.add( resource.add(
WebMvcLinkBuilder.linkTo( WebMvcLinkBuilder.linkTo(
methodOn(ClassificationController.class).getClassification(classification.getId())) methodOn(ClassificationController.class)
.getClassification(classification.getId()))
.withSelfRel()); .withSelfRel());
} catch (ClassificationNotFoundException e) { } catch (ClassificationNotFoundException e) {
throw new SystemException("caught unexpected Exception.", e.getCause()); throw new SystemException("caught unexpected Exception.", e.getCause());
@ -50,6 +50,11 @@ public class ClassificationRepresentationModelAssembler
return resource; return resource;
} }
@Override
public TaskanaPagedModelKeys getProperty() {
return TaskanaPagedModelKeys.CLASSIFICATIONS;
}
public Classification toEntityModel( public Classification toEntityModel(
ClassificationRepresentationModel classificationRepresentationModel) { ClassificationRepresentationModel classificationRepresentationModel) {
ClassificationImpl classification = ClassificationImpl classification =
@ -61,12 +66,8 @@ public class ClassificationRepresentationModelAssembler
BeanUtils.copyProperties(classificationRepresentationModel, classification); BeanUtils.copyProperties(classificationRepresentationModel, classification);
classification.setId(classificationRepresentationModel.getClassificationId()); classification.setId(classificationRepresentationModel.getClassificationId());
if (classificationRepresentationModel.getCreated() != null) { classification.setCreated(classificationRepresentationModel.getCreated());
classification.setCreated(Instant.parse(classificationRepresentationModel.getCreated())); classification.setModified(classificationRepresentationModel.getModified());
}
if (classificationRepresentationModel.getModified() != null) {
classification.setModified(Instant.parse(classificationRepresentationModel.getModified()));
}
return classification; return classification;
} }
} }

View File

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

View File

@ -1,28 +1,25 @@
package pro.taskana.classification.rest.models; package pro.taskana.classification.rest.models;
import java.time.Instant;
import pro.taskana.classification.api.models.Classification; import pro.taskana.classification.api.models.Classification;
/** /** EntityModel class for {@link Classification}. */
* EntityModel class for {@link Classification}. public class ClassificationRepresentationModel extends ClassificationSummaryRepresentationModel {
*/
public class ClassificationRepresentationModel
extends ClassificationSummaryRepresentationModel {
private Boolean isValidInDomain; 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; private String description;
public ClassificationRepresentationModel() { public ClassificationRepresentationModel() {}
}
public ClassificationRepresentationModel(Classification classification) { public ClassificationRepresentationModel(Classification classification) {
super(classification); super(classification);
this.isValidInDomain = classification.getIsValidInDomain(); this.isValidInDomain = classification.getIsValidInDomain();
this.created = this.created = classification.getCreated();
classification.getCreated() != null ? classification.getCreated().toString() : null; this.modified = classification.getModified();
this.modified =
classification.getModified() != null ? classification.getModified().toString() : null;
this.description = classification.getDescription(); this.description = classification.getDescription();
} }
@ -30,23 +27,23 @@ public class ClassificationRepresentationModel
return isValidInDomain; return isValidInDomain;
} }
public void setIsValidInDomain(Boolean validInDomain) { public void setIsValidInDomain(Boolean isValidInDomain) {
isValidInDomain = validInDomain; this.isValidInDomain = isValidInDomain;
} }
public String getCreated() { public Instant getCreated() {
return created; return created;
} }
public void setCreated(String created) { public void setCreated(Instant created) {
this.created = created; this.created = created;
} }
public String getModified() { public Instant getModified() {
return modified; return modified;
} }
public void setModified(String modified) { public void setModified(Instant modified) {
this.modified = modified; this.modified = modified;
} }
@ -57,55 +54,4 @@ public class ClassificationRepresentationModel
public void setDescription(String description) { public void setDescription(String description) {
this.description = 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,26 +17,23 @@ import org.springframework.hateoas.RepresentationModel;
* *
* @param <T> The class of the paginated content * @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>> { extends RepresentationModel<TaskanaPagedModel<T>> {
@JsonIgnore @JsonIgnore private TaskanaPagedModelKeys key;
private TaskanaPagedModelKeys key; @JsonIgnore private Collection<? extends T> content;
@JsonIgnore
private Collection<? extends T> content;
@JsonProperty(value = "page", access = Access.WRITE_ONLY) @JsonProperty(value = "page", access = Access.WRITE_ONLY)
private PageMetadata metadata; private PageMetadata metadata;
@SuppressWarnings("unused") // needed for jackson @SuppressWarnings("unused") // needed for jackson
private TaskanaPagedModel() { private TaskanaPagedModel() {}
}
/** /**
* Creates a new {@link TaskanaPagedModel} from the given content. * Creates a new {@link TaskanaPagedModel} from the given content.
* *
* @param property property which will be used for serialization. * @param property property which will be used for serialization.
* @param content must not be {@literal null}. * @param content must not be {@literal null}.
* @param metadata the metadata. Can be null. If null, no metadata will be serialized. * @param metadata the metadata. Can be null. If null, no metadata will be serialized.
*/ */
public TaskanaPagedModel( public TaskanaPagedModel(
@ -46,6 +43,10 @@ public class TaskanaPagedModel<T extends RepresentationModel<T>>
this.key = property; this.key = property;
} }
public TaskanaPagedModel(TaskanaPagedModelKeys property, Collection<? extends T> content) {
this(property, content, null);
}
public Collection<T> getContent() { public Collection<T> getContent() {
return Collections.unmodifiableCollection(content); return Collections.unmodifiableCollection(content);
} }
@ -54,6 +55,10 @@ public class TaskanaPagedModel<T extends RepresentationModel<T>>
return metadata; return metadata;
} }
public TaskanaPagedModelKeys getKey() {
return key;
}
@JsonAnySetter @JsonAnySetter
private void deserialize(String propertyName, Collection<T> content) { private void deserialize(String propertyName, Collection<T> content) {
TaskanaPagedModelKeys.getEnumFromPropertyName(propertyName) TaskanaPagedModelKeys.getEnumFromPropertyName(propertyName)

View File

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

View File

@ -1,23 +1,60 @@
package pro.taskana.task.rest.assembler; package pro.taskana.task.rest.assembler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.server.RepresentationModelAssembler; import org.springframework.hateoas.server.RepresentationModelAssembler;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component; 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.api.models.AttachmentSummary;
import pro.taskana.task.internal.models.AttachmentImpl;
import pro.taskana.task.rest.models.AttachmentSummaryRepresentationModel; import pro.taskana.task.rest.models.AttachmentSummaryRepresentationModel;
/** /** EntityModel assembler for {@link AttachmentSummaryRepresentationModel}. */
* EntityModel assembler for {@link AttachmentSummaryRepresentationModel}.
*/
@Component @Component
public class AttachmentSummaryRepresentationModelAssembler implements public class AttachmentSummaryRepresentationModelAssembler
RepresentationModelAssembler<AttachmentSummary, AttachmentSummaryRepresentationModel> { 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 @NonNull
@Override @Override
public AttachmentSummaryRepresentationModel toModel( public AttachmentSummaryRepresentationModel toModel(@NonNull AttachmentSummary summary) {
@NonNull AttachmentSummary attachmentSummary) { AttachmentSummaryRepresentationModel repModel = new AttachmentSummaryRepresentationModel();
return new AttachmentSummaryRepresentationModel(attachmentSummary); 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.linkTo;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
import java.time.Instant;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; 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.lang.NonNull;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -30,7 +29,7 @@ import pro.taskana.workbasket.rest.assembler.WorkbasketSummaryRepresentationMode
*/ */
@Component @Component
public class TaskRepresentationModelAssembler public class TaskRepresentationModelAssembler
extends RepresentationModelAssemblerSupport<Task, TaskRepresentationModel> { implements RepresentationModelAssembler<Task, TaskRepresentationModel> {
private final TaskService taskService; private final TaskService taskService;
@ -47,7 +46,6 @@ public class TaskRepresentationModelAssembler
ClassificationSummaryRepresentationModelAssembler classificationAssembler, ClassificationSummaryRepresentationModelAssembler classificationAssembler,
WorkbasketSummaryRepresentationModelAssembler workbasketSummaryRepresentationModelAssembler, WorkbasketSummaryRepresentationModelAssembler workbasketSummaryRepresentationModelAssembler,
AttachmentRepresentationModelAssembler attachmentAssembler) { AttachmentRepresentationModelAssembler attachmentAssembler) {
super(TaskController.class, TaskRepresentationModel.class);
this.taskService = taskService; this.taskService = taskService;
this.classificationAssembler = classificationAssembler; this.classificationAssembler = classificationAssembler;
this.workbasketSummaryRepresentationModelAssembler this.workbasketSummaryRepresentationModelAssembler
@ -68,8 +66,7 @@ public class TaskRepresentationModelAssembler
return resource; return resource;
} }
public Task toEntityModel(TaskRepresentationModel resource) throws InvalidArgumentException { public Task toEntityModel(TaskRepresentationModel resource) {
validateTaskResource(resource);
TaskImpl task = TaskImpl task =
(TaskImpl) (TaskImpl)
taskService.newTask( taskService.newTask(
@ -77,24 +74,7 @@ public class TaskRepresentationModelAssembler
task.setId(resource.getTaskId()); task.setId(resource.getTaskId());
task.setExternalId(resource.getExternalId()); task.setExternalId(resource.getExternalId());
BeanUtils.copyProperties(resource, task); 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( task.setClassificationSummary(
classificationAssembler.toEntityModel( classificationAssembler.toEntityModel(
resource.getClassificationSummary())); resource.getClassificationSummary()));
@ -113,20 +93,4 @@ public class TaskRepresentationModelAssembler
return task; 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; package pro.taskana.task.rest.models;
import java.time.Instant;
import org.springframework.hateoas.RepresentationModel; import org.springframework.hateoas.RepresentationModel;
import pro.taskana.classification.rest.models.ClassificationSummaryRepresentationModel; import pro.taskana.classification.rest.models.ClassificationSummaryRepresentationModel;
import pro.taskana.task.api.models.AttachmentSummary; import pro.taskana.task.api.models.AttachmentSummary;
import pro.taskana.task.api.models.ObjectReference; import pro.taskana.task.api.models.ObjectReference;
/** /** EntityModel class for {@link AttachmentSummary}. */
* EntityModel class for {@link AttachmentSummary}.
*/
public class AttachmentSummaryRepresentationModel public class AttachmentSummaryRepresentationModel
extends RepresentationModel<AttachmentSummaryRepresentationModel> { extends RepresentationModel<AttachmentSummaryRepresentationModel> {
protected String attachmentId; protected String attachmentId;
protected String taskId; protected String taskId;
protected String created; protected Instant created;
protected String modified; protected Instant modified;
protected Instant received;
protected ClassificationSummaryRepresentationModel classificationSummary; protected ClassificationSummaryRepresentationModel classificationSummary;
protected ObjectReference objectReference; protected ObjectReference objectReference;
protected String channel; protected String channel;
protected String received;
AttachmentSummaryRepresentationModel() { // TODO: remove this constructor
} public AttachmentSummaryRepresentationModel() {}
// TODO: remove this constructor
public AttachmentSummaryRepresentationModel(AttachmentSummary attachmentSummary) { public AttachmentSummaryRepresentationModel(AttachmentSummary attachmentSummary) {
this.attachmentId = attachmentSummary.getId(); this.attachmentId = attachmentSummary.getId();
this.taskId = attachmentSummary.getTaskId(); this.taskId = attachmentSummary.getTaskId();
this.created = this.created = attachmentSummary.getCreated();
attachmentSummary.getCreated() != null ? attachmentSummary.getCreated().toString() : null; this.modified = attachmentSummary.getModified();
this.modified = this.received = attachmentSummary.getReceived();
attachmentSummary.getModified() != null ? attachmentSummary.getModified().toString() : null;
this.classificationSummary = this.classificationSummary =
new ClassificationSummaryRepresentationModel(attachmentSummary.getClassificationSummary()); new ClassificationSummaryRepresentationModel(attachmentSummary.getClassificationSummary());
this.objectReference = attachmentSummary.getObjectReference(); this.objectReference = attachmentSummary.getObjectReference();
this.channel = attachmentSummary.getChannel(); this.channel = attachmentSummary.getChannel();
this.received =
attachmentSummary.getReceived() != null ? attachmentSummary.getReceived().toString() : null;
} }
public String getAttachmentId() { public String getAttachmentId() {
@ -55,22 +52,30 @@ public class AttachmentSummaryRepresentationModel
this.taskId = taskId; this.taskId = taskId;
} }
public String getCreated() { public Instant getCreated() {
return created; return created;
} }
public void setCreated(String created) { public void setCreated(Instant created) {
this.created = created; this.created = created;
} }
public String getModified() { public Instant getModified() {
return modified; return modified;
} }
public void setModified(String modified) { public void setModified(Instant modified) {
this.modified = modified; this.modified = modified;
} }
public Instant getReceived() {
return received;
}
public void setReceived(Instant received) {
this.received = received;
}
public ClassificationSummaryRepresentationModel getClassificationSummary() { public ClassificationSummaryRepresentationModel getClassificationSummary() {
return classificationSummary; return classificationSummary;
} }
@ -95,34 +100,4 @@ public class AttachmentSummaryRepresentationModel
public void setChannel(String channel) { public void setChannel(String channel) {
this.channel = 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; package pro.taskana.task.rest.models;
import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -21,12 +22,12 @@ public class TaskSummaryRepresentationModel
protected String taskId; protected String taskId;
protected String externalId; protected String externalId;
protected String created; // ISO-8601 protected Instant created; // ISO-8601
protected String claimed; // ISO-8601 protected Instant claimed; // ISO-8601
protected String completed; // ISO-8601 protected Instant completed; // ISO-8601
protected String modified; // ISO-8601 protected Instant modified; // ISO-8601
protected String planned; // ISO-8601 protected Instant planned; // ISO-8601
protected String due; // ISO-8601 protected Instant due; // ISO-8601
protected String name; protected String name;
protected String creator; protected String creator;
protected String note; protected String note;
@ -66,12 +67,12 @@ public class TaskSummaryRepresentationModel
public TaskSummaryRepresentationModel(TaskSummary taskSummary) throws InvalidArgumentException { public TaskSummaryRepresentationModel(TaskSummary taskSummary) throws InvalidArgumentException {
this.taskId = taskSummary.getId(); this.taskId = taskSummary.getId();
this.externalId = taskSummary.getExternalId(); this.externalId = taskSummary.getExternalId();
created = taskSummary.getCreated() != null ? taskSummary.getCreated().toString() : null; created = taskSummary.getCreated();
claimed = taskSummary.getClaimed() != null ? taskSummary.getClaimed().toString() : null; claimed = taskSummary.getClaimed();
completed = taskSummary.getCompleted() != null ? taskSummary.getCompleted().toString() : null; completed = taskSummary.getCompleted();
modified = taskSummary.getModified() != null ? taskSummary.getModified().toString() : null; modified = taskSummary.getModified();
planned = taskSummary.getPlanned() != null ? taskSummary.getPlanned().toString() : null; planned = taskSummary.getPlanned();
due = taskSummary.getDue() != null ? taskSummary.getDue().toString() : null; due = taskSummary.getDue();
this.name = taskSummary.getName(); this.name = taskSummary.getName();
this.creator = taskSummary.getCreator(); this.creator = taskSummary.getCreator();
this.note = taskSummary.getNote(); this.note = taskSummary.getNote();
@ -126,51 +127,51 @@ public class TaskSummaryRepresentationModel
this.externalId = externalId; this.externalId = externalId;
} }
public String getCreated() { public Instant getCreated() {
return created; return created;
} }
public void setCreated(String created) { public void setCreated(Instant created) {
this.created = created; this.created = created;
} }
public String getClaimed() { public Instant getClaimed() {
return claimed; return claimed;
} }
public void setClaimed(String claimed) { public void setClaimed(Instant claimed) {
this.claimed = claimed; this.claimed = claimed;
} }
public String getCompleted() { public Instant getCompleted() {
return completed; return completed;
} }
public void setCompleted(String completed) { public void setCompleted(Instant completed) {
this.completed = completed; this.completed = completed;
} }
public String getModified() { public Instant getModified() {
return modified; return modified;
} }
public void setModified(String modified) { public void setModified(Instant modified) {
this.modified = modified; this.modified = modified;
} }
public String getPlanned() { public Instant getPlanned() {
return planned; return planned;
} }
public void setPlanned(String planned) { public void setPlanned(Instant planned) {
this.planned = planned; this.planned = planned;
} }
public String getDue() { public Instant getDue() {
return due; return due;
} }
public void setDue(String due) { public void setDue(Instant due) {
this.due = 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.Workbasket;
import pro.taskana.workbasket.api.models.WorkbasketAccessItem; import pro.taskana.workbasket.api.models.WorkbasketAccessItem;
import pro.taskana.workbasket.api.models.WorkbasketSummary; 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.WorkbasketAccessItemRepresentationModelAssembler;
import pro.taskana.workbasket.rest.assembler.WorkbasketRepresentationModelAssembler; import pro.taskana.workbasket.rest.assembler.WorkbasketRepresentationModelAssembler;
import pro.taskana.workbasket.rest.assembler.WorkbasketSummaryRepresentationModelAssembler; import pro.taskana.workbasket.rest.assembler.WorkbasketSummaryRepresentationModelAssembler;
@ -80,8 +79,7 @@ public class WorkbasketController extends AbstractPagingController {
private final WorkbasketSummaryRepresentationModelAssembler private final WorkbasketSummaryRepresentationModelAssembler
workbasketSummaryRepresentationModelAssembler; workbasketSummaryRepresentationModelAssembler;
private final DistributionTargetRepresentationModelAssembler
distributionTargetRepresentationModelAssembler;
private final WorkbasketAccessItemRepresentationModelAssembler private final WorkbasketAccessItemRepresentationModelAssembler
workbasketAccessItemRepresentationModelAssembler; workbasketAccessItemRepresentationModelAssembler;
@ -90,15 +88,13 @@ public class WorkbasketController extends AbstractPagingController {
WorkbasketService workbasketService, WorkbasketService workbasketService,
WorkbasketRepresentationModelAssembler workbasketRepresentationModelAssembler, WorkbasketRepresentationModelAssembler workbasketRepresentationModelAssembler,
WorkbasketSummaryRepresentationModelAssembler workbasketSummaryRepresentationModelAssembler, WorkbasketSummaryRepresentationModelAssembler workbasketSummaryRepresentationModelAssembler,
DistributionTargetRepresentationModelAssembler distributionTargetRepresentationModelAssembler,
WorkbasketAccessItemRepresentationModelAssembler WorkbasketAccessItemRepresentationModelAssembler
workbasketAccessItemRepresentationModelAssembler) { workbasketAccessItemRepresentationModelAssembler) {
this.workbasketService = workbasketService; this.workbasketService = workbasketService;
this.workbasketRepresentationModelAssembler = workbasketRepresentationModelAssembler; this.workbasketRepresentationModelAssembler = workbasketRepresentationModelAssembler;
this.workbasketSummaryRepresentationModelAssembler = this.workbasketSummaryRepresentationModelAssembler =
workbasketSummaryRepresentationModelAssembler; workbasketSummaryRepresentationModelAssembler;
this.distributionTargetRepresentationModelAssembler =
distributionTargetRepresentationModelAssembler;
this.workbasketAccessItemRepresentationModelAssembler = this.workbasketAccessItemRepresentationModelAssembler =
workbasketAccessItemRepresentationModelAssembler; workbasketAccessItemRepresentationModelAssembler;
} }
@ -236,7 +232,7 @@ public class WorkbasketController extends AbstractPagingController {
workbasketService.getWorkbasketAccessItems(workbasketId); workbasketService.getWorkbasketAccessItems(workbasketId);
result = result =
ResponseEntity.ok( ResponseEntity.ok(
workbasketAccessItemRepresentationModelAssembler.toPageModel( workbasketAccessItemRepresentationModelAssembler.toPageModelForSingleWorkbasket(
workbasketId, accessItems, null)); workbasketId, accessItems, null));
if (LOGGER.isDebugEnabled()) { if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Exit from getWorkbasketAccessItems(), returning {}", result); LOGGER.debug("Exit from getWorkbasketAccessItems(), returning {}", result);
@ -268,7 +264,7 @@ public class WorkbasketController extends AbstractPagingController {
ResponseEntity<TaskanaPagedModel<WorkbasketAccessItemRepresentationModel>> response = ResponseEntity<TaskanaPagedModel<WorkbasketAccessItemRepresentationModel>> response =
ResponseEntity.ok( ResponseEntity.ok(
workbasketAccessItemRepresentationModelAssembler.toPageModel( workbasketAccessItemRepresentationModelAssembler.toPageModelForSingleWorkbasket(
workbasketId, updatedWbAccessItems, null)); workbasketId, updatedWbAccessItems, null));
if (LOGGER.isDebugEnabled()) { if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Exit from setWorkbasketAccessItems(), returning {}", response); LOGGER.debug("Exit from setWorkbasketAccessItems(), returning {}", response);
@ -287,7 +283,8 @@ public class WorkbasketController extends AbstractPagingController {
List<WorkbasketSummary> distributionTargets = List<WorkbasketSummary> distributionTargets =
workbasketService.getDistributionTargets(workbasketId); workbasketService.getDistributionTargets(workbasketId);
TaskanaPagedModel<WorkbasketSummaryRepresentationModel> distributionTargetListResource = TaskanaPagedModel<WorkbasketSummaryRepresentationModel> distributionTargetListResource =
distributionTargetRepresentationModelAssembler.toPageModel(distributionTargets, null); workbasketSummaryRepresentationModelAssembler
.toDistributionTargetPageModel(distributionTargets, null);
ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> result = ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> result =
ResponseEntity.ok(distributionTargetListResource); ResponseEntity.ok(distributionTargetListResource);
if (LOGGER.isDebugEnabled()) { if (LOGGER.isDebugEnabled()) {
@ -317,7 +314,8 @@ public class WorkbasketController extends AbstractPagingController {
workbasketService.getDistributionTargets(sourceWorkbasketId); workbasketService.getDistributionTargets(sourceWorkbasketId);
ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> response = ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> response =
ResponseEntity.ok( ResponseEntity.ok(
distributionTargetRepresentationModelAssembler.toPageModel(distributionTargets, null)); workbasketSummaryRepresentationModelAssembler
.toDistributionTargetPageModel(distributionTargets, null));
if (LOGGER.isDebugEnabled()) { if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Exit from getTasksStatusReport(), returning {}", response); LOGGER.debug("Exit from getTasksStatusReport(), returning {}", response);
} }

View File

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

View File

@ -1,6 +1,5 @@
package pro.taskana.workbasket.rest.assembler; package pro.taskana.workbasket.rest.assembler;
import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -11,6 +10,9 @@ import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import pro.taskana.common.api.exceptions.NotAuthorizedException; 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.WorkbasketService;
import pro.taskana.workbasket.api.exceptions.WorkbasketNotFoundException; import pro.taskana.workbasket.api.exceptions.WorkbasketNotFoundException;
import pro.taskana.workbasket.api.models.Workbasket; import pro.taskana.workbasket.api.models.Workbasket;
@ -27,41 +29,40 @@ import pro.taskana.workbasket.rest.models.WorkbasketRepresentationModelWithoutLi
* all additional information about that workbasket. * all additional information about that workbasket.
*/ */
@Component @Component
public class WorkbasketDefinitionRepresentationModelAssembler { public class WorkbasketDefinitionRepresentationModelAssembler
implements TaskanaPagingAssembler<Workbasket, WorkbasketDefinitionRepresentationModel> {
private final WorkbasketService workbasketService; private final WorkbasketService workbasketService;
@Autowired @Autowired
public WorkbasketDefinitionRepresentationModelAssembler( public WorkbasketDefinitionRepresentationModelAssembler(WorkbasketService workbasketService) {
WorkbasketService workbasketService) {
this.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 @NonNull
public WorkbasketDefinitionRepresentationModel toModel(Workbasket workbasket) public WorkbasketDefinitionRepresentationModel toModel(@NonNull Workbasket workbasket) {
throws NotAuthorizedException, WorkbasketNotFoundException {
WorkbasketRepresentationModelWithoutLinks basket = WorkbasketRepresentationModelWithoutLinks basket =
new WorkbasketRepresentationModelWithoutLinks(workbasket); new WorkbasketRepresentationModelWithoutLinks(workbasket);
List<WorkbasketAccessItemImpl> authorizations = new ArrayList<>(); List<WorkbasketAccessItemImpl> authorizations = new ArrayList<>();
for (WorkbasketAccessItem accessItem : try {
workbasketService.getWorkbasketAccessItems(basket.getWorkbasketId())) { for (WorkbasketAccessItem accessItem :
authorizations.add((WorkbasketAccessItemImpl) accessItem); workbasketService.getWorkbasketAccessItems(basket.getWorkbasketId())) {
authorizations.add((WorkbasketAccessItemImpl) accessItem);
}
} 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);
} }
Set<String> distroTargets =
workbasketService.getDistributionTargets(workbasket.getId()).stream()
.map(WorkbasketSummary::getId)
.collect(Collectors.toSet());
return new WorkbasketDefinitionRepresentationModel(basket, distroTargets, authorizations); return new WorkbasketDefinitionRepresentationModel(basket, distroTargets, authorizations);
} }
@ -72,12 +73,13 @@ public class WorkbasketDefinitionRepresentationModelAssembler {
BeanUtils.copyProperties(wbResource, workbasket); BeanUtils.copyProperties(wbResource, workbasket);
workbasket.setId(wbResource.getWorkbasketId()); workbasket.setId(wbResource.getWorkbasketId());
if (wbResource.getModified() != null) { workbasket.setModified(wbResource.getModified());
workbasket.setModified(Instant.parse(wbResource.getModified())); workbasket.setCreated(wbResource.getCreated());
}
if (wbResource.getCreated() != null) {
workbasket.setCreated(Instant.parse(wbResource.getCreated()));
}
return workbasket; 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.linkTo;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
import java.time.Instant;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.server.RepresentationModelAssembler; import org.springframework.hateoas.server.RepresentationModelAssembler;
@ -32,8 +31,7 @@ public class WorkbasketRepresentationModelAssembler
private final WorkbasketService workbasketService; private final WorkbasketService workbasketService;
@Autowired @Autowired
public WorkbasketRepresentationModelAssembler( public WorkbasketRepresentationModelAssembler(WorkbasketService workbasketService) {
WorkbasketService workbasketService) {
this.workbasketService = workbasketService; this.workbasketService = workbasketService;
} }
@ -55,12 +53,8 @@ public class WorkbasketRepresentationModelAssembler
BeanUtils.copyProperties(wbResource, workbasket); BeanUtils.copyProperties(wbResource, workbasket);
workbasket.setId(wbResource.getWorkbasketId()); workbasket.setId(wbResource.getWorkbasketId());
if (wbResource.getModified() != null) { workbasket.setModified(wbResource.getModified());
workbasket.setModified(Instant.parse(wbResource.getModified())); workbasket.setCreated(wbResource.getCreated());
}
if (wbResource.getCreated() != null) {
workbasket.setCreated(Instant.parse(wbResource.getCreated()));
}
return workbasket; return workbasket;
} }

View File

@ -1,5 +1,6 @@
package pro.taskana.workbasket.rest.assembler; 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 static pro.taskana.common.rest.models.TaskanaPagedModelKeys.WORKBASKETS;
import java.util.List; import java.util.List;
@ -13,7 +14,6 @@ import org.springframework.stereotype.Component;
import pro.taskana.common.rest.Mapping; import pro.taskana.common.rest.Mapping;
import pro.taskana.common.rest.models.TaskanaPagedModel; import pro.taskana.common.rest.models.TaskanaPagedModel;
import pro.taskana.common.rest.models.TaskanaPagedModelKeys;
import pro.taskana.resource.rest.PageLinks; import pro.taskana.resource.rest.PageLinks;
import pro.taskana.workbasket.api.WorkbasketService; import pro.taskana.workbasket.api.WorkbasketService;
import pro.taskana.workbasket.api.models.WorkbasketSummary; import pro.taskana.workbasket.api.models.WorkbasketSummary;
@ -60,10 +60,17 @@ public class WorkbasketSummaryRepresentationModelAssembler implements
.collect( .collect(
Collectors.collectingAndThen( Collectors.collectingAndThen(
Collectors.toList(), Collectors.toList(),
list -> new TaskanaPagedModel<>(getKey(), list, pageMetadata))); list -> new TaskanaPagedModel<>(WORKBASKETS, list, pageMetadata)));
} }
protected TaskanaPagedModelKeys getKey() { @PageLinks(Mapping.URL_WORKBASKET_ID_DISTRIBUTION)
return WORKBASKETS; 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; package pro.taskana.workbasket.rest.models;
import java.time.Instant;
import pro.taskana.workbasket.api.models.Workbasket; import pro.taskana.workbasket.api.models.Workbasket;
/** /**
@ -9,49 +11,31 @@ public class WorkbasketRepresentationModel
extends WorkbasketSummaryRepresentationModel { extends WorkbasketSummaryRepresentationModel {
private String created; // ISO-8601 private Instant created; // ISO-8601
private String modified; // ISO-8601 private Instant modified; // ISO-8601
public WorkbasketRepresentationModel() { public WorkbasketRepresentationModel() {
} }
public WorkbasketRepresentationModel(Workbasket workbasket) { public WorkbasketRepresentationModel(Workbasket workbasket) {
super(workbasket); super(workbasket);
this.created = workbasket.getCreated() != null ? workbasket.getCreated().toString() : null; this.created = workbasket.getCreated();
this.modified = workbasket.getModified() != null ? workbasket.getModified().toString() : null; this.modified = workbasket.getModified();
} }
public String getCreated() { public Instant getCreated() {
return created; return created;
} }
public void setCreated(String created) { public void setCreated(Instant created) {
this.created = created; this.created = created;
} }
public String getModified() { public Instant getModified() {
return modified; return modified;
} }
public void setModified(String modified) { public void setModified(Instant modified) {
this.modified = 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 = ResponseEntity<TaskanaPagedModel<ClassificationSummaryRepresentationModel>> response =
template.exchange( template.exchange(
restHelper.toUrl(Mapping.URL_CLASSIFICATIONS) 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, HttpMethod.GET,
restHelper.defaultRequest(), restHelper.defaultRequest(),
CLASSIFICATION_SUMMARY_PAGE_MODEL_TYPE); CLASSIFICATION_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody().getContent()).hasSize(5); assertThat(response.getBody().getContent()).hasSize(5);
assertThat(response.getBody().getContent().iterator().next().getKey()).isEqualTo("L1050"); assertThat(response.getBody().getContent().iterator().next().getKey()).isEqualTo("L1050");
assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull();
String href = response
.getBody()
.getRequiredLink(IanaLinkRelations.SELF)
.getHref();
assertThat( assertThat(
response href
.getBody()
.getRequiredLink(IanaLinkRelations.SELF)
.getHref()
.endsWith( .endsWith(
"/api/v1/classifications?" "/api/v1/classifications?"
+ "domain=DOMAIN_A&sort-by=key&order=asc&page-size=5&page=2")) + "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.IOException;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.time.Instant;
import java.util.List; import java.util.Arrays;
import java.util.Collections;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -27,28 +28,47 @@ import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestTemplate; 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.ClassificationRepresentationModel;
import pro.taskana.classification.rest.models.ClassificationSummaryRepresentationModel; import pro.taskana.classification.rest.models.ClassificationSummaryRepresentationModel;
import pro.taskana.common.rest.Mapping; import pro.taskana.common.rest.Mapping;
import pro.taskana.common.rest.RestHelper; import pro.taskana.common.rest.RestHelper;
import pro.taskana.common.rest.TaskanaSpringBootTest; import pro.taskana.common.rest.TaskanaSpringBootTest;
import pro.taskana.common.rest.models.TaskanaPagedModel; import pro.taskana.common.rest.models.TaskanaPagedModel;
import pro.taskana.common.rest.models.TaskanaPagedModelKeys;
/** Test classification definitions. */ /** Test classification definitions. */
@TaskanaSpringBootTest @TaskanaSpringBootTest
class ClassificationDefinitionControllerIntTest { class ClassificationDefinitionControllerIntTest {
private static final ParameterizedTypeReference< private static final ParameterizedTypeReference<
TaskanaPagedModel<ClassificationSummaryRepresentationModel>> TaskanaPagedModel<ClassificationRepresentationModel>>
CLASSIFICATION_SUMMARY_PAGE_MODEL_TYPE = CLASSIFICATION_PAGE_MODEL_TYPE =
new ParameterizedTypeReference< new ParameterizedTypeReference<TaskanaPagedModel<ClassificationRepresentationModel>>() {};
TaskanaPagedModel<ClassificationSummaryRepresentationModel>>() {};
private static final Logger LOGGER = LoggerFactory.getLogger(ClassificationController.class); private static final Logger LOGGER = LoggerFactory.getLogger(ClassificationController.class);
private static RestTemplate template; 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 @BeforeAll
static void init() { static void init() {
@ -57,27 +77,34 @@ class ClassificationDefinitionControllerIntTest {
@Test @Test
void testExportClassifications() { void testExportClassifications() {
ResponseEntity<ClassificationRepresentationModel[]> response = ResponseEntity<TaskanaPagedModel<ClassificationRepresentationModel>> response =
template.exchange( template.exchange(
restHelper.toUrl(Mapping.URL_CLASSIFICATIONDEFINITION) + "?domain=DOMAIN_B", restHelper.toUrl(Mapping.URL_CLASSIFICATIONDEFINITION) + "?domain=DOMAIN_B",
HttpMethod.GET, HttpMethod.GET,
restHelper.defaultRequest(), restHelper.defaultRequest(),
ParameterizedTypeReference.forType(ClassificationRepresentationModel[].class)); CLASSIFICATION_PAGE_MODEL_TYPE);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody().length >= 5).isTrue(); assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().length <= 7).isTrue(); assertThat(response.getBody().getContent())
assertThat(response.getBody()[0]).isInstanceOf(ClassificationRepresentationModel.class); .extracting(ClassificationRepresentationModel::getClassificationId)
.containsOnlyOnce(
"CLI:200000000000000000000000000000000015",
"CLI:200000000000000000000000000000000017",
"CLI:200000000000000000000000000000000018",
"CLI:200000000000000000000000000000000003",
"CLI:200000000000000000000000000000000004");
} }
@Test @Test
void testExportClassificationsFromWrongDomain() { void testExportClassificationsFromWrongDomain() {
ResponseEntity<ClassificationRepresentationModel[]> response = ResponseEntity<TaskanaPagedModel<ClassificationRepresentationModel>> response =
template.exchange( template.exchange(
restHelper.toUrl(Mapping.URL_CLASSIFICATIONDEFINITION) + "?domain=ADdfe", restHelper.toUrl(Mapping.URL_CLASSIFICATIONDEFINITION) + "?domain=ADdfe",
HttpMethod.GET, HttpMethod.GET,
restHelper.defaultRequest(), restHelper.defaultRequest(),
ParameterizedTypeReference.forType(ClassificationRepresentationModel[].class)); CLASSIFICATION_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isEmpty(); assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getContent()).isEmpty();
} }
@Test @Test
@ -91,8 +118,8 @@ class ClassificationDefinitionControllerIntTest {
classification.setType("TASK"); classification.setType("TASK");
classification.setDomain("DOMAIN_A"); classification.setDomain("DOMAIN_A");
classification.setIsValidInDomain(true); classification.setIsValidInDomain(true);
classification.setCreated("2016-05-12T10:12:12.12Z"); classification.setCreated(Instant.parse("2016-05-12T10:12:12.12Z"));
classification.setModified("2018-05-12T10:12:12.12Z"); classification.setModified(Instant.parse("2018-05-12T10:12:12.12Z"));
classification.setName("name"); classification.setName("name");
classification.setDescription("description"); classification.setDescription("description");
classification.setPriority(4); classification.setPriority(4);
@ -107,8 +134,9 @@ class ClassificationDefinitionControllerIntTest {
classification.setCustom7("custom"); classification.setCustom7("custom");
classification.setCustom8("custom"); classification.setCustom8("custom");
List<String> clList = new ArrayList<>(); TaskanaPagedModel<ClassificationRepresentationModel> clList =
clList.add(objMapper.writeValueAsString(classification)); new TaskanaPagedModel<>(
TaskanaPagedModelKeys.CLASSIFICATIONS, Collections.singletonList(classification));
ResponseEntity<Void> response = importRequest(clList); ResponseEntity<Void> response = importRequest(clList);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
@ -118,8 +146,9 @@ class ClassificationDefinitionControllerIntTest {
void testFailureWhenKeyIsMissing() throws IOException { void testFailureWhenKeyIsMissing() throws IOException {
ClassificationRepresentationModel classification = new ClassificationRepresentationModel(); ClassificationRepresentationModel classification = new ClassificationRepresentationModel();
classification.setDomain("DOMAIN_A"); classification.setDomain("DOMAIN_A");
List<String> clList = new ArrayList<>(); TaskanaPagedModel<ClassificationRepresentationModel> clList =
clList.add(objMapper.writeValueAsString(classification)); new TaskanaPagedModel<>(
TaskanaPagedModelKeys.CLASSIFICATIONS, Collections.singletonList(classification));
try { try {
importRequest(clList); importRequest(clList);
@ -132,8 +161,9 @@ class ClassificationDefinitionControllerIntTest {
void testFailureWhenDomainIsMissing() throws IOException { void testFailureWhenDomainIsMissing() throws IOException {
ClassificationRepresentationModel classification = new ClassificationRepresentationModel(); ClassificationRepresentationModel classification = new ClassificationRepresentationModel();
classification.setKey("one"); classification.setKey("one");
List<String> clList = new ArrayList<>(); TaskanaPagedModel<ClassificationRepresentationModel> clList =
clList.add(objMapper.writeValueAsString(classification)); new TaskanaPagedModel<>(
TaskanaPagedModelKeys.CLASSIFICATIONS, Collections.singletonList(classification));
try { try {
importRequest(clList); importRequest(clList);
@ -143,25 +173,25 @@ class ClassificationDefinitionControllerIntTest {
} }
@Test @Test
void testFailureWhenUpdatingTypeOfExistingClassification() throws IOException { void testFailureWhenUpdatingTypeOfExistingClassification() throws Exception {
ClassificationSummaryRepresentationModel classification = ClassificationRepresentationModel classification =
this.getClassificationWithKeyAndDomain("T6310", ""); getClassificationWithKeyAndDomain("T6310", "");
classification.setType("DOCUMENT"); classification.setType("DOCUMENT");
List<String> clList = new ArrayList<>(); TaskanaPagedModel<ClassificationRepresentationModel> clList =
clList.add(objMapper.writeValueAsString(classification)); new TaskanaPagedModel<>(
TaskanaPagedModelKeys.CLASSIFICATIONS, Collections.singletonList(classification));
try { assertThatThrownBy(() -> importRequest(clList))
importRequest(clList); .isInstanceOf(HttpClientErrorException.class)
} catch (HttpClientErrorException e) { .extracting(e -> (HttpClientErrorException) e)
assertThat(e.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); .extracting(HttpClientErrorException::getStatusCode)
} .isEqualTo(HttpStatus.BAD_REQUEST);
} }
@Test @Test
void testImportMultipleClassifications() throws IOException { void testImportMultipleClassifications() throws IOException {
ClassificationRepresentationModel classification1 = ClassificationRepresentationModel classification1 =
this.createClassification("id1", "ImportKey1", "DOMAIN_A", null, null); this.createClassification("id1", "ImportKey1", "DOMAIN_A", null, null);
final String c1 = objMapper.writeValueAsString(classification1);
ClassificationRepresentationModel classification2 = ClassificationRepresentationModel classification2 =
this.createClassification( this.createClassification(
@ -169,77 +199,81 @@ class ClassificationDefinitionControllerIntTest {
classification2.setCategory("MANUAL"); classification2.setCategory("MANUAL");
classification2.setType("TASK"); classification2.setType("TASK");
classification2.setIsValidInDomain(true); classification2.setIsValidInDomain(true);
classification2.setCreated("2016-05-12T10:12:12.12Z"); classification2.setCreated(Instant.parse("2016-05-12T10:12:12.12Z"));
classification2.setModified("2018-05-12T10:12:12.12Z"); classification2.setModified(Instant.parse("2018-05-12T10:12:12.12Z"));
classification2.setName("name"); classification2.setName("name");
classification2.setDescription("description"); classification2.setDescription("description");
classification2.setPriority(4); classification2.setPriority(4);
classification2.setServiceLevel("P2D"); classification2.setServiceLevel("P2D");
classification2.setApplicationEntryPoint("entry1"); classification2.setApplicationEntryPoint("entry1");
String c2 = objMapper.writeValueAsString(classification2);
List<String> clList = new ArrayList<>(); TaskanaPagedModel<ClassificationRepresentationModel> clList =
clList.add(c1); new TaskanaPagedModel<>(
clList.add(c2); TaskanaPagedModelKeys.CLASSIFICATIONS, Arrays.asList(classification1, classification2));
ResponseEntity<Void> response = importRequest(clList); ResponseEntity<Void> response = importRequest(clList);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
} }
@Test @Test
void testImportDuplicateClassification() throws IOException { void testImportDuplicateClassification() {
ClassificationRepresentationModel classification1 = new ClassificationRepresentationModel(); ClassificationRepresentationModel classification1 = new ClassificationRepresentationModel();
classification1.setClassificationId("id1"); classification1.setClassificationId("id1");
classification1.setKey("ImportKey3"); classification1.setKey("ImportKey3");
classification1.setDomain("DOMAIN_A"); classification1.setDomain("DOMAIN_A");
String c1 = objMapper.writeValueAsString(classification1);
List<String> clList = new ArrayList<>(); TaskanaPagedModel<ClassificationRepresentationModel> clList =
clList.add(c1); new TaskanaPagedModel<>(
clList.add(c1); TaskanaPagedModelKeys.CLASSIFICATIONS, Arrays.asList(classification1, classification1));
try { assertThatThrownBy(() -> importRequest(clList))
importRequest(clList); .isInstanceOf(HttpClientErrorException.class)
} catch (HttpClientErrorException e) { .extracting(e -> (HttpClientErrorException) e)
assertThat(e.getStatusCode()).isEqualTo(HttpStatus.CONFLICT); .extracting(HttpStatusCodeException::getStatusCode)
} .isEqualTo(HttpStatus.CONFLICT);
} }
@Test @Test
void testInsertExistingClassificationWithOlderTimestamp() throws IOException { void testInsertExistingClassificationWithOlderTimestamp() throws Exception {
ClassificationSummaryRepresentationModel existingClassification = ClassificationRepresentationModel existingClassification =
getClassificationWithKeyAndDomain("L110107", "DOMAIN_A"); getClassificationWithKeyAndDomain("L110107", "DOMAIN_A");
existingClassification.setName("first new Name"); 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); ResponseEntity<Void> response = importRequest(clList);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
existingClassification.setName("second new Name"); existingClassification.setName("second new Name");
clList = new ArrayList<>(); clList =
clList.add(objMapper.writeValueAsString(existingClassification)); new TaskanaPagedModel<>(
TaskanaPagedModelKeys.CLASSIFICATIONS,
Collections.singletonList(existingClassification));
response = importRequest(clList); response = importRequest(clList);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
ClassificationSummaryRepresentationModel testClassification = ClassificationRepresentationModel testClassification =
this.getClassificationWithKeyAndDomain("L110107", "DOMAIN_A"); this.getClassificationWithKeyAndDomain("L110107", "DOMAIN_A");
assertThat(testClassification.getName()).isEqualTo("second new Name"); assertThat(testClassification.getName()).isEqualTo("second new Name");
} }
@Test @Test
void testHookExistingChildToNewParent() throws IOException { void testHookExistingChildToNewParent() throws Exception {
final ClassificationRepresentationModel newClassification = final ClassificationRepresentationModel newClassification =
createClassification("new Classification", "newClass", "DOMAIN_A", null, "L11010"); createClassification("new Classification", "newClass", "DOMAIN_A", null, "L11010");
ClassificationSummaryRepresentationModel existingClassification = ClassificationRepresentationModel existingClassification =
getClassificationWithKeyAndDomain("L110102", "DOMAIN_A"); getClassificationWithKeyAndDomain("L110102", "DOMAIN_A");
existingClassification.setParentId("new Classification"); existingClassification.setParentId("new Classification");
existingClassification.setParentKey("newClass"); existingClassification.setParentKey("newClass");
List<String> clList = new ArrayList<>(); TaskanaPagedModel<ClassificationRepresentationModel> clList =
clList.add(objMapper.writeValueAsString(existingClassification)); new TaskanaPagedModel<>(
clList.add(objMapper.writeValueAsString(newClassification)); TaskanaPagedModelKeys.CLASSIFICATIONS,
Arrays.asList(existingClassification, newClassification));
ResponseEntity<Void> response = importRequest(clList); ResponseEntity<Void> response = importRequest(clList);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
@ -259,41 +293,37 @@ class ClassificationDefinitionControllerIntTest {
} }
@Test @Test
void testImportParentAndChildClassification() throws IOException { void testImportParentAndChildClassification() throws Exception {
ClassificationRepresentationModel classification1 = ClassificationRepresentationModel classification1 =
this.createClassification("parentId", "ImportKey6", "DOMAIN_A", null, null); this.createClassification("parentId", "ImportKey6", "DOMAIN_A", null, null);
final String c1 = objMapper.writeValueAsString(classification1);
ClassificationRepresentationModel classification2 = ClassificationRepresentationModel classification2 =
this.createClassification("childId1", "ImportKey7", "DOMAIN_A", null, "ImportKey6"); 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 = ClassificationRepresentationModel classification3 =
this.createClassification("childId2", "ImportKey8", "DOMAIN_A", "parentId", null);
ClassificationRepresentationModel classification4 =
this.createClassification( this.createClassification(
"grandchildId1", "ImportKey9", "DOMAIN_A", "childId1", "ImportKey7"); "grandchildId1", "ImportKey9", "DOMAIN_A", "childId1", "ImportKey7");
final String c31 = objMapper.writeValueAsString(classification3); ClassificationRepresentationModel classification5 =
classification3 =
this.createClassification("grandchild2", "ImportKey10", "DOMAIN_A", null, "ImportKey7"); this.createClassification("grandchild2", "ImportKey10", "DOMAIN_A", null, "ImportKey7");
final String c32 = objMapper.writeValueAsString(classification3);
List<String> clList = new ArrayList<>(); TaskanaPagedModel<ClassificationRepresentationModel> clList =
clList.add(c31); new TaskanaPagedModel<>(
clList.add(c32); TaskanaPagedModelKeys.CLASSIFICATIONS,
clList.add(c21); Arrays.asList(
clList.add(c22); classification1,
clList.add(c1); classification2,
classification3,
classification4,
classification5));
ResponseEntity<Void> response = importRequest(clList); ResponseEntity<Void> response = importRequest(clList);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
ClassificationSummaryRepresentationModel parentCl = ClassificationRepresentationModel parentCl =
getClassificationWithKeyAndDomain("ImportKey6", "DOMAIN_A"); getClassificationWithKeyAndDomain("ImportKey6", "DOMAIN_A");
ClassificationSummaryRepresentationModel childCl = ClassificationRepresentationModel childCl =
getClassificationWithKeyAndDomain("ImportKey7", "DOMAIN_A"); getClassificationWithKeyAndDomain("ImportKey7", "DOMAIN_A");
ClassificationSummaryRepresentationModel grandchildCl = ClassificationRepresentationModel grandchildCl =
getClassificationWithKeyAndDomain("ImportKey9", "DOMAIN_A"); getClassificationWithKeyAndDomain("ImportKey9", "DOMAIN_A");
assertThat(parentCl).isNotNull(); assertThat(parentCl).isNotNull();
@ -304,31 +334,27 @@ class ClassificationDefinitionControllerIntTest {
} }
@Test @Test
void testImportParentAndChildClassificationWithKey() throws IOException { void testImportParentAndChildClassificationWithKey() throws Exception {
ClassificationRepresentationModel classification1 = ClassificationRepresentationModel parent =
createClassification("parent", "ImportKey11", "DOMAIN_A", null, null); createClassification("parent", "ImportKey11", "DOMAIN_A", null, null);
classification1.setCustom1("parent is correct"); parent.setCustom1("parent is correct");
String parent = objMapper.writeValueAsString(classification1); ClassificationRepresentationModel wrongParent =
ClassificationRepresentationModel classification2 =
createClassification("wrongParent", "ImportKey11", "DOMAIN_B", null, null); createClassification("wrongParent", "ImportKey11", "DOMAIN_B", null, null);
String wrongParent = objMapper.writeValueAsString(classification2); ClassificationRepresentationModel child =
ClassificationRepresentationModel classification3 =
createClassification("child", "ImportKey13", "DOMAIN_A", null, "ImportKey11"); createClassification("child", "ImportKey13", "DOMAIN_A", null, "ImportKey11");
String child = objMapper.writeValueAsString(classification3);
List<String> clList = new ArrayList<>(); TaskanaPagedModel<ClassificationRepresentationModel> clList =
clList.add(wrongParent); new TaskanaPagedModel<>(
clList.add(parent); TaskanaPagedModelKeys.CLASSIFICATIONS, Arrays.asList(parent, wrongParent, child));
clList.add(child);
ResponseEntity<Void> response = importRequest(clList); ResponseEntity<Void> response = importRequest(clList);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
ClassificationSummaryRepresentationModel rightParentCl = ClassificationRepresentationModel rightParentCl =
getClassificationWithKeyAndDomain("ImportKey11", "DOMAIN_A"); getClassificationWithKeyAndDomain("ImportKey11", "DOMAIN_A");
ClassificationSummaryRepresentationModel wrongParentCl = ClassificationRepresentationModel wrongParentCl =
getClassificationWithKeyAndDomain("ImportKey11", "DOMAIN_B"); getClassificationWithKeyAndDomain("ImportKey11", "DOMAIN_B");
ClassificationSummaryRepresentationModel childCl = ClassificationRepresentationModel childCl =
getClassificationWithKeyAndDomain("ImportKey13", "DOMAIN_A"); getClassificationWithKeyAndDomain("ImportKey13", "DOMAIN_A");
assertThat(rightParentCl).isNotNull(); assertThat(rightParentCl).isNotNull();
@ -339,50 +365,46 @@ class ClassificationDefinitionControllerIntTest {
} }
@Test @Test
void testChangeParentByImportingExistingClassification() void testChangeParentByImportingExistingClassification() throws Exception {
throws IOException, InterruptedException { ClassificationRepresentationModel child1 =
ClassificationSummaryRepresentationModel child1 =
this.getClassificationWithKeyAndDomain("L110105", "DOMAIN_A"); this.getClassificationWithKeyAndDomain("L110105", "DOMAIN_A");
assertThat(child1.getParentKey()).isEqualTo("L11010"); assertThat(child1.getParentKey()).isEqualTo("L11010");
child1.setParentId("CLI:100000000000000000000000000000000002"); child1.setParentId("CLI:100000000000000000000000000000000002");
child1.setParentKey("L10303"); child1.setParentKey("L10303");
final String withNewParent = objMapper.writeValueAsString(child1);
ClassificationSummaryRepresentationModel child2 = ClassificationRepresentationModel child2 =
this.getClassificationWithKeyAndDomain("L110107", "DOMAIN_A"); this.getClassificationWithKeyAndDomain("L110107", "DOMAIN_A");
assertThat(child2.getParentKey()).isEqualTo("L11010"); assertThat(child2.getParentKey()).isEqualTo("L11010");
child2.setParentId(""); child2.setParentId("");
child2.setParentKey(""); child2.setParentKey("");
String withoutParent = objMapper.writeValueAsString(child2);
List<String> clList = new ArrayList<>(); TaskanaPagedModel<ClassificationRepresentationModel> clList =
clList.add(withNewParent); new TaskanaPagedModel<>(
clList.add(withoutParent); TaskanaPagedModelKeys.CLASSIFICATIONS, Arrays.asList(child1, child2));
ResponseEntity<Void> response = importRequest(clList); ResponseEntity<Void> response = importRequest(clList);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
Thread.sleep(10); Thread.sleep(10);
LOGGER.debug("Wait 10 ms to give the system a chance to update"); LOGGER.debug("Wait 10 ms to give the system a chance to update");
ClassificationSummaryRepresentationModel childWithNewParent = ClassificationRepresentationModel childWithNewParent =
this.getClassificationWithKeyAndDomain("L110105", "DOMAIN_A"); this.getClassificationWithKeyAndDomain("L110105", "DOMAIN_A");
assertThat(childWithNewParent.getParentKey()).isEqualTo(child1.getParentKey()); assertThat(childWithNewParent.getParentKey()).isEqualTo(child1.getParentKey());
ClassificationSummaryRepresentationModel childWithoutParent = ClassificationRepresentationModel childWithoutParent =
this.getClassificationWithKeyAndDomain("L110107", "DOMAIN_A"); this.getClassificationWithKeyAndDomain("L110107", "DOMAIN_A");
assertThat(childWithoutParent.getParentId()).isEqualTo(child2.getParentId()); assertThat(childWithoutParent.getParentId()).isEqualTo(child2.getParentId());
assertThat(childWithoutParent.getParentKey()).isEqualTo(child2.getParentKey()); assertThat(childWithoutParent.getParentKey()).isEqualTo(child2.getParentKey());
} }
@Test @Test
void testFailOnImportDuplicates() throws IOException { void testFailOnImportDuplicates() throws Exception {
ClassificationSummaryRepresentationModel classification = ClassificationRepresentationModel classification =
this.getClassificationWithKeyAndDomain("L110105", "DOMAIN_A"); this.getClassificationWithKeyAndDomain("L110105", "DOMAIN_A");
String classificationString = objMapper.writeValueAsString(classification);
List<String> clList = new ArrayList<>(); TaskanaPagedModel<ClassificationRepresentationModel> clList =
clList.add(classificationString); new TaskanaPagedModel<>(
clList.add(classificationString); TaskanaPagedModelKeys.CLASSIFICATIONS, Arrays.asList(classification, classification));
assertThatThrownBy(() -> importRequest(clList)) assertThatThrownBy(() -> importRequest(clList))
.isInstanceOf(HttpClientErrorException.class) .isInstanceOf(HttpClientErrorException.class)
@ -402,29 +424,18 @@ class ClassificationDefinitionControllerIntTest {
return classificationRepresentationModel; return classificationRepresentationModel;
} }
private ClassificationSummaryRepresentationModel getClassificationWithKeyAndDomain( private ClassificationRepresentationModel getClassificationWithKeyAndDomain(
String key, String domain) { String key, String domain) throws ClassificationNotFoundException {
LOGGER.debug("Request classification with key={} in domain={}", key, domain); return classificationAssembler.toModel(classificationService.getClassification(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 ResponseEntity<Void> importRequest(List<String> clList) throws IOException { private ResponseEntity<Void> importRequest(
TaskanaPagedModel<ClassificationRepresentationModel> clList) throws IOException {
LOGGER.debug("Start Import"); LOGGER.debug("Start Import");
File tmpFile = File.createTempFile("test", ".tmp"); File tmpFile = File.createTempFile("test", ".tmp");
OutputStreamWriter writer = OutputStreamWriter writer =
new OutputStreamWriter(new FileOutputStream(tmpFile), StandardCharsets.UTF_8); new OutputStreamWriter(new FileOutputStream(tmpFile), StandardCharsets.UTF_8);
writer.write(clList.toString()); mapper.writeValue(writer, clList);
writer.close();
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>(); 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.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.SerializationFeature;
import com.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.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.hateoas.MediaTypes;
import org.springframework.hateoas.mediatype.hal.Jackson2HalModule; import org.springframework.hateoas.mediatype.hal.Jackson2HalModule;
import org.springframework.http.HttpEntity; import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
@ -81,9 +85,11 @@ public class RestHelper {
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
mapper.registerModule(new Jackson2HalModule()); mapper.registerModule(new Jackson2HalModule());
mapper.registerModule(new ParameterNamesModule())
.registerModule(new Jdk8Module())
.registerModule(new JavaTimeModule());
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(MediaType.parseMediaTypes("application/hal+json")); converter.setSupportedMediaTypes(Collections.singletonList(MediaTypes.HAL_JSON));
converter.setObjectMapper(mapper); converter.setObjectMapper(mapper);
RestTemplate template = new RestTemplate(); RestTemplate template = new RestTemplate();

View File

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

View File

@ -406,9 +406,9 @@ class WorkbasketControllerRestDocumentation extends BaseRestDocumentation {
this.mockMvc this.mockMvc
.perform( .perform(
RestDocumentationRequestBuilders.get( RestDocumentationRequestBuilders.get(
restHelper.toUrl( restHelper.toUrl(
Mapping.URL_WORKBASKET_ID_DISTRIBUTION, Mapping.URL_WORKBASKET_ID_DISTRIBUTION,
"WBI:100000000000000000000000000000000002")) "WBI:100000000000000000000000000000000002"))
.header("Authorization", "Basic dGVhbWxlYWRfMTp0ZWFtbGVhZF8x")) .header("Authorization", "Basic dGVhbWxlYWRfMTp0ZWFtbGVhZF8x"))
.andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(MockMvcResultMatchers.status().isOk())
.andDo( .andDo(

View File

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

View File

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

View File

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

View File

@ -100,21 +100,11 @@ class TaskSummaryAssemblerTest {
void testEquality(TaskSummaryImpl taskSummary, TaskSummaryRepresentationModel resource) { void testEquality(TaskSummaryImpl taskSummary, TaskSummaryRepresentationModel resource) {
Assert.assertEquals(taskSummary.getId(), resource.getTaskId()); Assert.assertEquals(taskSummary.getId(), resource.getTaskId());
Assert.assertEquals(taskSummary.getExternalId(), resource.getExternalId()); Assert.assertEquals(taskSummary.getExternalId(), resource.getExternalId());
Assert.assertEquals( Assert.assertEquals(taskSummary.getCreated(), resource.getCreated());
taskSummary.getCreated() == null ? null : taskSummary.getCreated().toString(), Assert.assertEquals(taskSummary.getClaimed(), resource.getClaimed());
resource.getCreated()); Assert.assertEquals(taskSummary.getCompleted(), resource.getCompleted());
Assert.assertEquals( Assert.assertEquals(taskSummary.getModified(), resource.getModified());
taskSummary.getClaimed() == null ? null : taskSummary.getClaimed().toString(), Assert.assertEquals(taskSummary.getPlanned(), resource.getPlanned());
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.getDescription(), resource.getDescription()); Assert.assertEquals(taskSummary.getDescription(), resource.getDescription());
Assert.assertEquals(taskSummary.getName(), resource.getName()); Assert.assertEquals(taskSummary.getName(), resource.getName());
Assert.assertEquals(taskSummary.getCreator(), resource.getCreator()); 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.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static pro.taskana.common.rest.RestHelper.TEMPLATE;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.Instant; import java.time.Instant;
import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.ParameterizedTypeReference;
@ -17,7 +17,6 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import pro.taskana.common.rest.Mapping; import pro.taskana.common.rest.Mapping;
import pro.taskana.common.rest.RestHelper; import pro.taskana.common.rest.RestHelper;
@ -42,46 +41,49 @@ class WorkbasketControllerIntTest {
WORKBASKET_SUMMARY_PAGE_MODEL_TYPE = WORKBASKET_SUMMARY_PAGE_MODEL_TYPE =
new ParameterizedTypeReference< new ParameterizedTypeReference<
TaskanaPagedModel<WorkbasketSummaryRepresentationModel>>() {}; TaskanaPagedModel<WorkbasketSummaryRepresentationModel>>() {};
private static RestTemplate template; private final RestHelper restHelper;
@Autowired RestHelper restHelper; private final ObjectMapper mapper;
@BeforeAll @Autowired
static void init() { WorkbasketControllerIntTest(RestHelper restHelper, ObjectMapper mapper) {
template = RestHelper.TEMPLATE; this.restHelper = restHelper;
this.mapper = mapper;
} }
@Test @Test
void testGetWorkbasket() { void testGetWorkbasket() {
ResponseEntity<WorkbasketRepresentationModel> response = ResponseEntity<WorkbasketRepresentationModel> response =
template.exchange( TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET_ID, "WBI:100000000000000000000000000000000006"), restHelper.toUrl(Mapping.URL_WORKBASKET_ID, "WBI:100000000000000000000000000000000006"),
HttpMethod.GET, HttpMethod.GET,
restHelper.defaultRequest(), restHelper.defaultRequest(),
ParameterizedTypeReference.forType(WorkbasketRepresentationModel.class)); ParameterizedTypeReference.forType(WorkbasketRepresentationModel.class));
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getHeaders().getContentType().toString()) assertThat(response.getHeaders().getContentType()).isEqualTo(MediaTypes.HAL_JSON);
.isEqualTo(MediaTypes.HAL_JSON_VALUE);
} }
@Test @Test
void testGetAllWorkbaskets() { void testGetAllWorkbaskets() {
ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> response = ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> response =
template.exchange( TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET), restHelper.toUrl(Mapping.URL_WORKBASKET),
HttpMethod.GET, HttpMethod.GET,
restHelper.defaultRequest(), restHelper.defaultRequest(),
WORKBASKET_SUMMARY_PAGE_MODEL_TYPE); WORKBASKET_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull();
} }
@Test @Test
void testGetAllWorkbasketsBusinessAdminHasOpenPermission() { void testGetAllWorkbasketsBusinessAdminHasOpenPermission() {
ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> response = ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> response =
template.exchange( TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET) + "?required-permission=OPEN", restHelper.toUrl(Mapping.URL_WORKBASKET) + "?required-permission=OPEN",
HttpMethod.GET, HttpMethod.GET,
restHelper.defaultRequest(), restHelper.defaultRequest(),
WORKBASKET_SUMMARY_PAGE_MODEL_TYPE); WORKBASKET_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getRequiredLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getRequiredLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getContent()).hasSize(3); assertThat(response.getBody().getContent()).hasSize(3);
} }
@ -90,11 +92,12 @@ class WorkbasketControllerIntTest {
void testGetAllWorkbasketsKeepingFilters() { void testGetAllWorkbasketsKeepingFilters() {
String parameters = "?type=PERSONAL&sort-by=key&order=desc"; String parameters = "?type=PERSONAL&sort-by=key&order=desc";
ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> response = ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> response =
template.exchange( TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET) + parameters, restHelper.toUrl(Mapping.URL_WORKBASKET) + parameters,
HttpMethod.GET, HttpMethod.GET,
restHelper.defaultRequest(), restHelper.defaultRequest(),
WORKBASKET_SUMMARY_PAGE_MODEL_TYPE); WORKBASKET_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat( assertThat(
response response
@ -108,11 +111,12 @@ class WorkbasketControllerIntTest {
@Test @Test
void testThrowsExceptionIfInvalidFilterIsUsed() { void testThrowsExceptionIfInvalidFilterIsUsed() {
ThrowingCallable httpCall = ThrowingCallable httpCall =
() -> template.exchange( () ->
restHelper.toUrl(Mapping.URL_WORKBASKET) + "?invalid=PERSONAL", TEMPLATE.exchange(
HttpMethod.GET, restHelper.toUrl(Mapping.URL_WORKBASKET) + "?invalid=PERSONAL",
restHelper.defaultRequest(), HttpMethod.GET,
WORKBASKET_SUMMARY_PAGE_MODEL_TYPE); restHelper.defaultRequest(),
WORKBASKET_SUMMARY_PAGE_MODEL_TYPE);
assertThatThrownBy(httpCall) assertThatThrownBy(httpCall)
.isInstanceOf(HttpClientErrorException.class) .isInstanceOf(HttpClientErrorException.class)
.hasMessageContaining("[invalid]") .hasMessageContaining("[invalid]")
@ -125,10 +129,8 @@ class WorkbasketControllerIntTest {
String workbasketId = "WBI:100000000000000000000000000000000001"; String workbasketId = "WBI:100000000000000000000000000000000001";
final ObjectMapper mapper = new ObjectMapper();
ResponseEntity<WorkbasketRepresentationModel> initialWorkbasketResourceRequestResponse = ResponseEntity<WorkbasketRepresentationModel> initialWorkbasketResourceRequestResponse =
template.exchange( TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET_ID, workbasketId), restHelper.toUrl(Mapping.URL_WORKBASKET_ID, workbasketId),
HttpMethod.GET, HttpMethod.GET,
new HttpEntity<String>(restHelper.getHeaders()), new HttpEntity<String>(restHelper.getHeaders()),
@ -137,16 +139,17 @@ class WorkbasketControllerIntTest {
WorkbasketRepresentationModel workbasketRepresentationModel = WorkbasketRepresentationModel workbasketRepresentationModel =
initialWorkbasketResourceRequestResponse.getBody(); initialWorkbasketResourceRequestResponse.getBody();
assertThat(workbasketRepresentationModel).isNotNull();
workbasketRepresentationModel.setKey("GPK_KSC"); workbasketRepresentationModel.setKey("GPK_KSC");
workbasketRepresentationModel.setDomain("DOMAIN_A"); workbasketRepresentationModel.setDomain("DOMAIN_A");
workbasketRepresentationModel.setType(WorkbasketType.PERSONAL); workbasketRepresentationModel.setType(WorkbasketType.PERSONAL);
workbasketRepresentationModel.setName("was auch immer"); workbasketRepresentationModel.setName("was auch immer");
workbasketRepresentationModel.setOwner("Joerg"); workbasketRepresentationModel.setOwner("Joerg");
workbasketRepresentationModel.setModified(String.valueOf(Instant.now())); workbasketRepresentationModel.setModified(Instant.now());
ThrowingCallable httpCall = ThrowingCallable httpCall =
() -> { () -> {
template.exchange( TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET_ID, workbasketId), restHelper.toUrl(Mapping.URL_WORKBASKET_ID, workbasketId),
HttpMethod.PUT, HttpMethod.PUT,
new HttpEntity<>( new HttpEntity<>(
@ -166,7 +169,7 @@ class WorkbasketControllerIntTest {
ThrowingCallable httpCall = ThrowingCallable httpCall =
() -> { () -> {
template.exchange( TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET_ID, workbasketId), restHelper.toUrl(Mapping.URL_WORKBASKET_ID, workbasketId),
HttpMethod.GET, HttpMethod.GET,
new HttpEntity<String>(restHelper.getHeaders()), new HttpEntity<String>(restHelper.getHeaders()),
@ -183,11 +186,12 @@ class WorkbasketControllerIntTest {
String parameters = "?sort-by=key&order=desc&page-size=5&page=2"; String parameters = "?sort-by=key&order=desc&page-size=5&page=2";
ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> response = ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> response =
template.exchange( TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET) + parameters, restHelper.toUrl(Mapping.URL_WORKBASKET) + parameters,
HttpMethod.GET, HttpMethod.GET,
restHelper.defaultRequest(), restHelper.defaultRequest(),
WORKBASKET_SUMMARY_PAGE_MODEL_TYPE); WORKBASKET_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getContent()).hasSize(5); assertThat(response.getBody().getContent()).hasSize(5);
assertThat(response.getBody().getContent().iterator().next().getKey()).isEqualTo("USER_1_1"); assertThat(response.getBody().getContent().iterator().next().getKey()).isEqualTo("USER_1_1");
assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull();
@ -210,7 +214,7 @@ class WorkbasketControllerIntTest {
String workbasketID = "WBI:100000000000000000000000000000000005"; String workbasketID = "WBI:100000000000000000000000000000000005";
ResponseEntity<?> response = ResponseEntity<?> response =
template.exchange( TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET_ID, workbasketID), restHelper.toUrl(Mapping.URL_WORKBASKET_ID, workbasketID),
HttpMethod.DELETE, HttpMethod.DELETE,
new HttpEntity<>(restHelper.getHeadersBusinessAdmin()), new HttpEntity<>(restHelper.getHeadersBusinessAdmin()),
@ -224,7 +228,7 @@ class WorkbasketControllerIntTest {
ThrowingCallable call = ThrowingCallable call =
() -> () ->
template.exchange( TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET_ID, workbasketWithNonCompletedTasks), restHelper.toUrl(Mapping.URL_WORKBASKET_ID, workbasketWithNonCompletedTasks),
HttpMethod.DELETE, HttpMethod.DELETE,
new HttpEntity<>(restHelper.getHeadersBusinessAdmin()), new HttpEntity<>(restHelper.getHeadersBusinessAdmin()),
@ -238,7 +242,7 @@ class WorkbasketControllerIntTest {
@Test @Test
void testRemoveWorkbasketAsDistributionTarget() { void testRemoveWorkbasketAsDistributionTarget() {
ResponseEntity<?> response = ResponseEntity<?> response =
template.exchange( TEMPLATE.exchange(
restHelper.toUrl( restHelper.toUrl(
Mapping.URL_WORKBASKET_ID_DISTRIBUTION, "WBI:100000000000000000000000000000000007"), Mapping.URL_WORKBASKET_ID_DISTRIBUTION, "WBI:100000000000000000000000000000000007"),
HttpMethod.DELETE, HttpMethod.DELETE,
@ -247,47 +251,47 @@ class WorkbasketControllerIntTest {
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> response2 = ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> response2 =
template.exchange( TEMPLATE.exchange(
restHelper.toUrl( restHelper.toUrl(
Mapping.URL_WORKBASKET_ID_DISTRIBUTION, "WBI:100000000000000000000000000000000002"), Mapping.URL_WORKBASKET_ID_DISTRIBUTION, "WBI:100000000000000000000000000000000002"),
HttpMethod.GET, HttpMethod.GET,
restHelper.defaultRequest(), restHelper.defaultRequest(),
WORKBASKET_SUMMARY_PAGE_MODEL_TYPE); WORKBASKET_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response2.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(response2.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat( assertThat(response2.getBody()).isNotNull();
response2.getBody().getContent().stream() assertThat(response2.getBody().getContent())
.map(WorkbasketSummaryRepresentationModel::getWorkbasketId) .extracting(WorkbasketSummaryRepresentationModel::getWorkbasketId)
.noneMatch("WBI:100000000000000000000000000000000007"::equals)) .doesNotContain("WBI:100000000000000000000000000000000007");
.isTrue();
} }
@Test @Test
void testGetWorkbasketAccessItems() { void testGetWorkbasketAccessItems() {
ResponseEntity<TaskanaPagedModel<WorkbasketAccessItemRepresentationModel>> response = ResponseEntity<TaskanaPagedModel<WorkbasketAccessItemRepresentationModel>> response =
template.exchange( TEMPLATE.exchange(
restHelper.toUrl( restHelper.toUrl(
Mapping.URL_WORKBASKET_ID_ACCESSITEMS, "WBI:100000000000000000000000000000000005"), Mapping.URL_WORKBASKET_ID_ACCESSITEMS, "WBI:100000000000000000000000000000000005"),
HttpMethod.GET, HttpMethod.GET,
restHelper.defaultRequest(), restHelper.defaultRequest(),
WORKBASKET_ACCESS_ITEM_PAGE_MODEL_TYPE); WORKBASKET_ACCESS_ITEM_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getHeaders().getContentType().toString()) assertThat(response.getHeaders().getContentType()).isEqualTo(MediaTypes.HAL_JSON);
.isEqualTo(MediaTypes.HAL_JSON_VALUE);
assertThat(response.getBody().getContent()).hasSize(3); assertThat(response.getBody().getContent()).hasSize(3);
} }
@Test @Test
void testGetWorkbasketDistributionTargets() { void testGetWorkbasketDistributionTargets() {
ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> response = ResponseEntity<TaskanaPagedModel<WorkbasketSummaryRepresentationModel>> response =
template.exchange( TEMPLATE.exchange(
restHelper.toUrl( restHelper.toUrl(
Mapping.URL_WORKBASKET_ID_DISTRIBUTION, "WBI:100000000000000000000000000000000001"), Mapping.URL_WORKBASKET_ID_DISTRIBUTION, "WBI:100000000000000000000000000000000001"),
HttpMethod.GET, HttpMethod.GET,
restHelper.defaultRequest(), restHelper.defaultRequest(),
WORKBASKET_SUMMARY_PAGE_MODEL_TYPE); WORKBASKET_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getHeaders().getContentType().toString()) assertThat(response.getHeaders().getContentType())
.isEqualTo(MediaTypes.HAL_JSON_VALUE); .isEqualTo(MediaTypes.HAL_JSON);
assertThat(response.getBody().getContent()).hasSize(4); 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 java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy; 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 com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; 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.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpClientErrorException; 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.Mapping;
import pro.taskana.common.rest.RestHelper; import pro.taskana.common.rest.RestHelper;
import pro.taskana.common.rest.TaskanaSpringBootTest; 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.sampledata.SampleDataGenerator;
import pro.taskana.workbasket.rest.models.WorkbasketDefinitionRepresentationModel; import pro.taskana.workbasket.rest.models.WorkbasketDefinitionRepresentationModel;
@ -46,20 +47,19 @@ import pro.taskana.workbasket.rest.models.WorkbasketDefinitionRepresentationMode
@TaskanaSpringBootTest @TaskanaSpringBootTest
class WorkbasketDefinitionControllerIntTest { class WorkbasketDefinitionControllerIntTest {
private static RestTemplate template; private final ObjectMapper objMapper;
private final RestHelper restHelper;
private final DataSource dataSource;
@Value("${taskana.schemaName:TASKANA}") @Value("${taskana.schemaName:TASKANA}")
String schemaName; String schemaName;
ObjectMapper objMapper = new ObjectMapper(); @Autowired
WorkbasketDefinitionControllerIntTest(
@Autowired RestHelper restHelper; ObjectMapper objMapper, RestHelper restHelper, DataSource dataSource) {
this.objMapper = objMapper;
@Autowired private DataSource dataSource; this.restHelper = restHelper;
this.dataSource = dataSource;
@BeforeAll
static void init() {
template = RestHelper.TEMPLATE;
} }
@BeforeEach @BeforeEach
@ -70,17 +70,18 @@ class WorkbasketDefinitionControllerIntTest {
@Test @Test
void testExportWorkbasketFromDomain() { void testExportWorkbasketFromDomain() {
ResponseEntity<List<WorkbasketDefinitionRepresentationModel>> response = ResponseEntity<TaskanaPagedModel<WorkbasketDefinitionRepresentationModel>> response =
executeExportRequestForDomain("DOMAIN_A"); executeExportRequestForDomain("DOMAIN_A");
assertThat(response.getBody()).isNotNull(); assertThat(response.getBody()).isNotNull();
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody().get(0)) assertThat(response.getBody().getContent())
.isInstanceOf(WorkbasketDefinitionRepresentationModel.class); .hasOnlyElementsOfType(WorkbasketDefinitionRepresentationModel.class);
boolean allAuthorizationsAreEmpty = true; boolean allAuthorizationsAreEmpty = true;
boolean allDistributionTargetsAreEmpty = true; boolean allDistributionTargetsAreEmpty = true;
for (WorkbasketDefinitionRepresentationModel workbasketDefinition : response.getBody()) { for (WorkbasketDefinitionRepresentationModel workbasketDefinition :
response.getBody().getContent()) {
if (allAuthorizationsAreEmpty && !workbasketDefinition.getAuthorizations().isEmpty()) { if (allAuthorizationsAreEmpty && !workbasketDefinition.getAuthorizations().isEmpty()) {
allAuthorizationsAreEmpty = false; allAuthorizationsAreEmpty = false;
} }
@ -98,24 +99,29 @@ class WorkbasketDefinitionControllerIntTest {
@Test @Test
void testExportWorkbasketsFromWrongDomain() { void testExportWorkbasketsFromWrongDomain() {
ResponseEntity<List<WorkbasketDefinitionRepresentationModel>> response = ResponseEntity<TaskanaPagedModel<WorkbasketDefinitionRepresentationModel>> response =
executeExportRequestForDomain("wrongDomain"); executeExportRequestForDomain("wrongDomain");
assertThat(response.getBody()).isEmpty(); assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getContent()).isEmpty();
assertThat(response.getBody().getKey()).isSameAs(TaskanaPagedModelKeys.WORKBASKET_DEFINITIONS);
} }
@Test @Test
void testImportEveryWorkbasketFromDomainA() throws IOException { void testImportEveryWorkbasketFromDomainA() throws IOException {
List<WorkbasketDefinitionRepresentationModel> wbList = TaskanaPagedModel<WorkbasketDefinitionRepresentationModel> wbList =
executeExportRequestForDomain("DOMAIN_A").getBody(); executeExportRequestForDomain("DOMAIN_A").getBody();
for (WorkbasketDefinitionRepresentationModel w : wbList) { assertThat(wbList).isNotNull();
for (WorkbasketDefinitionRepresentationModel w : wbList.getContent()) {
expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.NO_CONTENT, w); expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.NO_CONTENT, w);
} }
} }
@Test @Test
void testImportWorkbasketWithoutDistributionTargets() throws IOException { void testImportWorkbasketWithoutDistributionTargets() throws IOException {
WorkbasketDefinitionRepresentationModel w = TaskanaPagedModel<WorkbasketDefinitionRepresentationModel> pagedModel =
executeExportRequestForDomain("DOMAIN_A").getBody().get(0); executeExportRequestForDomain("DOMAIN_A").getBody();
assertThat(pagedModel).isNotNull();
WorkbasketDefinitionRepresentationModel w = pagedModel.getContent().iterator().next();
w.setDistributionTargets(new HashSet<>()); w.setDistributionTargets(new HashSet<>());
this.expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.NO_CONTENT, w); this.expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.NO_CONTENT, w);
@ -127,13 +133,15 @@ class WorkbasketDefinitionControllerIntTest {
@Test @Test
void testImportWorkbasketWithDistributionTargetsInImportFile() throws IOException { void testImportWorkbasketWithDistributionTargetsInImportFile() throws IOException {
List<WorkbasketDefinitionRepresentationModel> wbList = TaskanaPagedModel<WorkbasketDefinitionRepresentationModel> wbList =
executeExportRequestForDomain("DOMAIN_A").getBody(); 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<>()); w.setDistributionTargets(new HashSet<>());
String letMeBeYourDistributionTarget = w.getWorkbasket().getWorkbasketId(); String letMeBeYourDistributionTarget = w.getWorkbasket().getWorkbasketId();
WorkbasketDefinitionRepresentationModel w2 = wbList.get(1); WorkbasketDefinitionRepresentationModel w2 = iterator.next();
w2.setDistributionTargets(Collections.singleton(letMeBeYourDistributionTarget)); w2.setDistributionTargets(Collections.singleton(letMeBeYourDistributionTarget));
expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.NO_CONTENT, w, w2); expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.NO_CONTENT, w, w2);
@ -150,11 +158,14 @@ class WorkbasketDefinitionControllerIntTest {
@Test @Test
void testImportWorkbasketWithDistributionTargetsInSystem() throws IOException { void testImportWorkbasketWithDistributionTargetsInSystem() throws IOException {
List<WorkbasketDefinitionRepresentationModel> wbList = TaskanaPagedModel<WorkbasketDefinitionRepresentationModel> wbList =
executeExportRequestForDomain("DOMAIN_A").getBody(); executeExportRequestForDomain("DOMAIN_A").getBody();
wbList.removeIf(definition -> definition.getDistributionTargets().isEmpty()); assertThat(wbList).isNotNull();
WorkbasketDefinitionRepresentationModel w = wbList.get(0); List<WorkbasketDefinitionRepresentationModel> content = new ArrayList<>(wbList.getContent());
content.removeIf(definition -> definition.getDistributionTargets().isEmpty());
WorkbasketDefinitionRepresentationModel w = content.iterator().next();
expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.NO_CONTENT, w); expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.NO_CONTENT, w);
changeWorkbasketIdOrKey(w, null, "new"); changeWorkbasketIdOrKey(w, null, "new");
@ -163,50 +174,58 @@ class WorkbasketDefinitionControllerIntTest {
@Test @Test
void testImportWorkbasketWithDistributionTargetsNotInSystem() throws IOException { void testImportWorkbasketWithDistributionTargetsNotInSystem() throws IOException {
List<WorkbasketDefinitionRepresentationModel> wbList = TaskanaPagedModel<WorkbasketDefinitionRepresentationModel> wbList =
executeExportRequestForDomain("DOMAIN_A").getBody(); executeExportRequestForDomain("DOMAIN_A").getBody();
WorkbasketDefinitionRepresentationModel w = wbList.get(0); assertThat(wbList).isNotNull();
WorkbasketDefinitionRepresentationModel w = wbList.getContent().iterator().next();
w.setDistributionTargets(Collections.singleton("invalidWorkbasketId")); w.setDistributionTargets(Collections.singleton("invalidWorkbasketId"));
try { ThrowingCallable httpCall =
expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.BAD_REQUEST, w); () -> expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.BAD_REQUEST, w);
fail("Expected http-Status 400"); assertThatThrownBy(httpCall)
} catch (HttpClientErrorException e) { .isInstanceOf(HttpClientErrorException.class)
assertThat(e.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); .extracting(e -> (HttpClientErrorException) e)
} .extracting(HttpStatusCodeException::getStatusCode)
.isEqualTo(HttpStatus.BAD_REQUEST);
w.getWorkbasket().setKey("anotherNewKey"); w.getWorkbasket().setKey("anotherNewKey");
try {
expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.BAD_REQUEST, w); assertThatThrownBy(httpCall)
fail("Expected http-Status 400"); .isInstanceOf(HttpClientErrorException.class)
} catch (HttpClientErrorException e) { .extracting(e -> (HttpClientErrorException) e)
assertThat(e.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); .extracting(HttpStatusCodeException::getStatusCode)
} .isEqualTo(HttpStatus.BAD_REQUEST);
} }
@Test @Test
void testFailOnImportDuplicates() throws IOException { void testFailOnImportDuplicates() throws IOException {
WorkbasketDefinitionRepresentationModel w = TaskanaPagedModel<WorkbasketDefinitionRepresentationModel> pagedModel =
executeExportRequestForDomain("DOMAIN_A").getBody().get(0); executeExportRequestForDomain("DOMAIN_A").getBody();
try {
expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.CONFLICT, w, w); assertThat(pagedModel).isNotNull();
fail("Expected http-Status 409"); WorkbasketDefinitionRepresentationModel w = pagedModel.getContent().iterator().next();
} catch (HttpClientErrorException e) { ThrowingCallable httpCall =
assertThat(e.getStatusCode()).isEqualTo(HttpStatus.CONFLICT); () -> expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.CONFLICT, w, w);
} assertThatThrownBy(httpCall)
.isInstanceOf(HttpClientErrorException.class)
.extracting(e -> (HttpClientErrorException) e)
.extracting(HttpStatusCodeException::getStatusCode)
.isEqualTo(HttpStatus.CONFLICT);
} }
@Test @Test
void testNoErrorWhenImportWithSameIdButDifferentKeyAndDomain() throws IOException { void testNoErrorWhenImportWithSameIdButDifferentKeyAndDomain() throws IOException {
List<WorkbasketDefinitionRepresentationModel> wbList = TaskanaPagedModel<WorkbasketDefinitionRepresentationModel> wbList =
executeExportRequestForDomain("DOMAIN_A").getBody(); executeExportRequestForDomain("DOMAIN_A").getBody();
WorkbasketDefinitionRepresentationModel w = wbList.get(0); assertThat(wbList).isNotNull();
WorkbasketDefinitionRepresentationModel differentLogicalId = wbList.get(1); Iterator<WorkbasketDefinitionRepresentationModel> iterator = wbList.getContent().iterator();
WorkbasketDefinitionRepresentationModel w = iterator.next();
WorkbasketDefinitionRepresentationModel differentLogicalId = iterator.next();
this.changeWorkbasketIdOrKey(differentLogicalId, w.getWorkbasket().getWorkbasketId(), null); this.changeWorkbasketIdOrKey(differentLogicalId, w.getWorkbasket().getWorkbasketId(), null);
// breaks the logic but not the script- should we really allow this case? // breaks the logic but not the script- should we really allow this case?
WorkbasketDefinitionRepresentationModel theDestroyer = wbList.get(2); WorkbasketDefinitionRepresentationModel theDestroyer = iterator.next();
theDestroyer.setDistributionTargets( theDestroyer.setDistributionTargets(
Collections.singleton(differentLogicalId.getWorkbasket().getWorkbasketId())); Collections.singleton(differentLogicalId.getWorkbasket().getWorkbasketId()));
@ -216,16 +235,15 @@ class WorkbasketDefinitionControllerIntTest {
@Test @Test
void testErrorWhenImportWithSameAccessIdAndWorkbasket() { void testErrorWhenImportWithSameAccessIdAndWorkbasket() {
WorkbasketDefinitionRepresentationModel w = TaskanaPagedModel<WorkbasketDefinitionRepresentationModel> pagedModel =
executeExportRequestForDomain("DOMAIN_A").getBody().get(0); 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 = ThrowingCallable httpCall =
() -> { () -> {
expectStatusWhenExecutingImportRequestOfWorkbaskets( expectStatusWhenExecutingImportRequestOfWorkbaskets(HttpStatus.CONFLICT, w, w);
HttpStatus.CONFLICT, Arrays.asList(w1String, w2String));
}; };
assertThatThrownBy(httpCall).isInstanceOf(HttpClientErrorException.class); assertThatThrownBy(httpCall).isInstanceOf(HttpClientErrorException.class);
} }
@ -242,30 +260,33 @@ class WorkbasketDefinitionControllerIntTest {
} }
} }
private ResponseEntity<List<WorkbasketDefinitionRepresentationModel>> private ResponseEntity<TaskanaPagedModel<WorkbasketDefinitionRepresentationModel>>
executeExportRequestForDomain(String domain) { executeExportRequestForDomain(String domain) {
return template.exchange( return TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKETDEFIITIONS) + "?domain=" + domain, restHelper.toUrl(Mapping.URL_WORKBASKETDEFIITIONS) + "?domain=" + domain,
HttpMethod.GET, HttpMethod.GET,
restHelper.defaultRequest(), restHelper.defaultRequest(),
new ParameterizedTypeReference<List<WorkbasketDefinitionRepresentationModel>>() {}); new ParameterizedTypeReference<
TaskanaPagedModel<WorkbasketDefinitionRepresentationModel>>() {});
} }
private void expectStatusWhenExecutingImportRequestOfWorkbaskets( private void expectStatusWhenExecutingImportRequestOfWorkbaskets(
HttpStatus expectedStatus, WorkbasketDefinitionRepresentationModel... workbaskets) HttpStatus expectedStatus, WorkbasketDefinitionRepresentationModel... workbaskets)
throws IOException { throws IOException {
List<String> workbasketStrings = TaskanaPagedModel<WorkbasketDefinitionRepresentationModel> pagedModel =
Arrays.stream(workbaskets).map(this::workbasketToString).collect(Collectors.toList()); new TaskanaPagedModel<>(
expectStatusWhenExecutingImportRequestOfWorkbaskets(expectedStatus, workbasketStrings); TaskanaPagedModelKeys.WORKBASKET_DEFINITIONS, Arrays.asList(workbaskets));
expectStatusWhenExecutingImportRequestOfWorkbaskets(expectedStatus, pagedModel);
} }
private void expectStatusWhenExecutingImportRequestOfWorkbaskets( private void expectStatusWhenExecutingImportRequestOfWorkbaskets(
HttpStatus expectedStatus, List<String> workbasketStrings) throws IOException { HttpStatus expectedStatus,
TaskanaPagedModel<WorkbasketDefinitionRepresentationModel> pageModel)
throws IOException {
File tmpFile = File.createTempFile("test", ".tmp"); File tmpFile = File.createTempFile("test", ".tmp");
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(tmpFile), UTF_8); try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(tmpFile), UTF_8)) {
writer.write(workbasketStrings.toString()); objMapper.writeValue(writer, pageModel);
writer.close(); }
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>(); MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
HttpHeaders headers = restHelper.getHeaders(); HttpHeaders headers = restHelper.getHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA); headers.setContentType(MediaType.MULTIPART_FORM_DATA);
@ -275,16 +296,7 @@ class WorkbasketDefinitionControllerIntTest {
String serverUrl = restHelper.toUrl(Mapping.URL_WORKBASKETDEFIITIONS); String serverUrl = restHelper.toUrl(Mapping.URL_WORKBASKETDEFIITIONS);
ResponseEntity<Void> responseImport = ResponseEntity<Void> responseImport =
template.postForEntity(serverUrl, requestEntity, Void.class); TEMPLATE.postForEntity(serverUrl, requestEntity, Void.class);
assertThat(responseImport.getStatusCode()).isEqualTo(expectedStatus); 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 @TaskanaSpringBootTest
class WorkbasketRepresentationModelAssemblerTest { class WorkbasketRepresentationModelAssemblerTest {
@Autowired WorkbasketService workbasketService; private final WorkbasketService workbasketService;
@Autowired WorkbasketRepresentationModelAssembler workbasketRepresentationModelAssembler; private final WorkbasketRepresentationModelAssembler workbasketRepresentationModelAssembler;
@Autowired
WorkbasketRepresentationModelAssemblerTest(
WorkbasketService workbasketService,
WorkbasketRepresentationModelAssembler workbasketRepresentationModelAssembler) {
this.workbasketService = workbasketService;
this.workbasketRepresentationModelAssembler = workbasketRepresentationModelAssembler;
}
@Test @Test
void workbasketToResource() { void workbasketToResource() {
@ -53,7 +61,7 @@ class WorkbasketRepresentationModelAssemblerTest {
// given // given
WorkbasketRepresentationModel resource = new WorkbasketRepresentationModel(); WorkbasketRepresentationModel resource = new WorkbasketRepresentationModel();
resource.setWorkbasketId("1"); resource.setWorkbasketId("1");
resource.setModified("2010-01-01T12:00:00Z"); resource.setModified(Instant.parse("2010-01-01T12:00:00Z"));
resource.setType(WorkbasketType.PERSONAL); resource.setType(WorkbasketType.PERSONAL);
// when // when
Workbasket workbasket = workbasketRepresentationModelAssembler.toEntityModel(resource); Workbasket workbasket = workbasketRepresentationModelAssembler.toEntityModel(resource);
@ -66,7 +74,7 @@ class WorkbasketRepresentationModelAssemblerTest {
// given // given
WorkbasketRepresentationModel resource = new WorkbasketRepresentationModel(); WorkbasketRepresentationModel resource = new WorkbasketRepresentationModel();
resource.setWorkbasketId("1"); resource.setWorkbasketId("1");
resource.setCreated("2010-01-01T12:00:00Z"); resource.setCreated(Instant.parse("2010-01-01T12:00:00Z"));
resource.setType(WorkbasketType.PERSONAL); resource.setType(WorkbasketType.PERSONAL);
// when // when
Workbasket workbasket = workbasketRepresentationModelAssembler.toEntityModel(resource); Workbasket workbasket = workbasketRepresentationModelAssembler.toEntityModel(resource);
@ -80,8 +88,8 @@ class WorkbasketRepresentationModelAssemblerTest {
WorkbasketRepresentationModel workbasketRepresentationModel = WorkbasketRepresentationModel workbasketRepresentationModel =
new WorkbasketRepresentationModel(); new WorkbasketRepresentationModel();
workbasketRepresentationModel.setWorkbasketId("1"); workbasketRepresentationModel.setWorkbasketId("1");
workbasketRepresentationModel.setCreated("2010-01-01T12:00:00Z"); workbasketRepresentationModel.setCreated(Instant.parse("2010-01-01T12:00:00Z"));
workbasketRepresentationModel.setModified("2010-01-01T12:00:00Z"); workbasketRepresentationModel.setModified(Instant.parse("2010-01-01T12:00:00Z"));
workbasketRepresentationModel.setCustom1("Custom1"); workbasketRepresentationModel.setCustom1("Custom1");
workbasketRepresentationModel.setCustom2("Custom2"); workbasketRepresentationModel.setCustom2("Custom2");
workbasketRepresentationModel.setCustom3("Custom3"); workbasketRepresentationModel.setCustom3("Custom3");
@ -124,9 +132,9 @@ class WorkbasketRepresentationModelAssemblerTest {
assertThat(workbasketRepresentationModel.getWorkbasketId()).isEqualTo(workbasket.getId()); assertThat(workbasketRepresentationModel.getWorkbasketId()).isEqualTo(workbasket.getId());
assertThat(workbasketRepresentationModel.getKey()).isEqualTo(workbasket.getKey()); assertThat(workbasketRepresentationModel.getKey()).isEqualTo(workbasket.getKey());
assertThat(workbasketRepresentationModel.getCreated()) assertThat(workbasketRepresentationModel.getCreated())
.isEqualTo(workbasket.getCreated() == null ? null : workbasket.getCreated().toString()); .isEqualTo(workbasket.getCreated());
assertThat(workbasketRepresentationModel.getModified()) assertThat(workbasketRepresentationModel.getModified())
.isEqualTo(workbasket.getModified() == null ? null : workbasket.getModified().toString()); .isEqualTo(workbasket.getModified());
assertThat(workbasketRepresentationModel.getName()).isEqualTo(workbasket.getName()); assertThat(workbasketRepresentationModel.getName()).isEqualTo(workbasket.getName());
assertThat(workbasketRepresentationModel.getDescription()) assertThat(workbasketRepresentationModel.getDescription())
.isEqualTo(workbasket.getDescription()); .isEqualTo(workbasket.getDescription());