Bug 5085: Implemented missing handling of role associations for

CourseTemplates
This commit is contained in:
Steffen Schaefer
2019-08-20 16:12:50 +02:00
parent bc78c6ead2
commit b21a1f1798
8 changed files with 52 additions and 22 deletions
@@ -3198,7 +3198,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
final CourseTemplateImpl courseTemplateImpl = new CourseTemplateImpl(id, name, markTemplates, waypointTemplates,
optionaImageURL, optionalRepeatablePart);
associatedRoles, optionaImageURL, optionalRepeatablePart);
courseTemplateImpl.setTags(tags);
return courseTemplateImpl;
}
@@ -6,6 +6,7 @@ import static org.junit.Assume.assumeNoException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
@@ -51,6 +52,7 @@ public class TestLapConfiguration {
new WaypointTemplateImpl(gate, PassingInstruction.Gate),
new WaypointTemplateImpl(top, PassingInstruction.Port),
new WaypointTemplateImpl(startFinish, PassingInstruction.Line)),
/* associatedRoles */ Collections.emptyMap(),
/* optionaImageURL */ null,
new RepeatablePartImpl(/* zeroBasedIndexOfRepeatablePartStart */ 1,
/* zeroBasedIndexOfRepeatablePartEnd */ 3));
@@ -96,6 +98,7 @@ public class TestLapConfiguration {
courseTemplate = new CourseTemplateImpl("Test",
/* marks */ Arrays.asList(startBoat),
/* waypoints */ Arrays.asList(new WaypointTemplateImpl(startFinish, PassingInstruction.Line)),
/* associatedRoles */ Collections.emptyMap(),
/* optionaImageURL */ null);
fail("Expected an IllegalArgumentException due to missing mark <pin> but it wasn't thrown");
} catch (IllegalArgumentException e) {
@@ -110,6 +113,7 @@ public class TestLapConfiguration {
startFinish = new ControlPointTemplateImpl("Start/Finish", Arrays.asList(startBoat, pin));
courseTemplate = new CourseTemplateImpl("Test", /* marks */ Arrays.asList(startBoat, pin),
/* waypoints */ Arrays.asList(new WaypointTemplateImpl(startFinish, PassingInstruction.Line)),
/* associatedRoles */ Collections.emptyMap(),
/* optionaImageURL */ null);
try {
courseTemplate.getWaypointTemplates(0);
@@ -23,7 +23,7 @@ public class CourseTemplateImpl extends NamedWithUUIDImpl implements CourseTempl
private final ArrayList<WaypointTemplate> waypoints;
private final Map<MarkTemplate, String> associatedRoles = new HashMap<>();
private final Map<MarkTemplate, String> associatedRoles;
private Iterable<String> tags = new ArrayList<>();
@@ -34,17 +34,17 @@ public class CourseTemplateImpl extends NamedWithUUIDImpl implements CourseTempl
/** Creates a course template with a random UUID. */
public CourseTemplateImpl(String name, Iterable<MarkTemplate> marks, Iterable<WaypointTemplate> waypoints,
URL optionalImageURL) {
this(UUID.randomUUID(), name, marks, waypoints, optionalImageURL);
Map<MarkTemplate, String> associatedRoles, URL optionalImageURL) {
this(UUID.randomUUID(), name, marks, waypoints, associatedRoles, optionalImageURL);
}
public CourseTemplateImpl(UUID id, String name, Iterable<MarkTemplate> marks,
Iterable<WaypointTemplate> waypoints, URL optionalImageURL) {
this(id, name, marks, waypoints, optionalImageURL, /* optionalRepeatablePart */ null);
Iterable<WaypointTemplate> waypoints, Map<MarkTemplate, String> associatedRoles, URL optionalImageURL) {
this(id, name, marks, waypoints, associatedRoles, optionalImageURL, /* optionalRepeatablePart */ null);
}
public CourseTemplateImpl(UUID id, String name, Iterable<MarkTemplate> marks, Iterable<WaypointTemplate> waypoints,
URL optionalImageURL, RepeatablePart optionalRepeatablePart) {
Map<MarkTemplate, String> associatedRoles, URL optionalImageURL, RepeatablePart optionalRepeatablePart) {
super(name, id);
if (optionalRepeatablePart != null) {
optionalRepeatablePart.validateRepeatablePartForSequence(waypoints);
@@ -56,6 +56,7 @@ public class CourseTemplateImpl extends NamedWithUUIDImpl implements CourseTempl
this.marks = theMarks;
this.optionalImageURL = optionalImageURL;
this.optionalRepeatablePart = optionalRepeatablePart;
this.associatedRoles = new HashMap<>(associatedRoles);
validateWaypointsAgainstMarks();
}
@@ -51,7 +51,7 @@ public interface SharedSailingData {
* @param waypoints the waypoints in their defined order (iteration order equals order of waypoints in course)
*/
CourseTemplate createCourseTemplate(String courseTemplateName, Iterable<MarkTemplate> marks, Iterable<WaypointTemplate> waypoints,
RepeatablePart optionalRepeatablePart, Iterable<String> tags, URL optionalImageURL);
Map<MarkTemplate, String> associatedRoles, RepeatablePart optionalRepeatablePart, Iterable<String> tags, URL optionalImageURL);
CourseTemplate getCourseTemplateById(UUID id);
@@ -108,8 +108,8 @@ public class CourseTemplateJsonDeserializer implements JsonDeserializer<CourseTe
optionalRepeatablePart = repeatablePartJsonDeserializer.deserialize(repeatablePartJSON);
}
CourseTemplateImpl courseTemplate = new CourseTemplateImpl(null, courseTemplateName, allMarkTemplatesById.values(), waypoints, optionalImageURL, optionalRepeatablePart);
courseTemplate.setAssociatedRoles(roles);
final CourseTemplateImpl courseTemplate = new CourseTemplateImpl(null, courseTemplateName,
allMarkTemplatesById.values(), waypoints, roles, optionalImageURL, optionalRepeatablePart);
courseTemplate.setTags(tags);
return courseTemplate;
}
@@ -90,8 +90,9 @@ public class CourseTemplateResource extends AbstractSailingServerResource {
.deserialize((JSONObject) parsedObject);
final CourseTemplate createdCourseTemplate = getSharedSailingData().createCourseTemplate(
deserializedCourseTemplate.getName(), deserializedCourseTemplate.getMarkTemplates(),
deserializedCourseTemplate.getWaypointTemplates(1), deserializedCourseTemplate.getRepeatablePart(),
deserializedCourseTemplate.getTags(), deserializedCourseTemplate.getOptionalImageURL());
deserializedCourseTemplate.getWaypointTemplates(1), deserializedCourseTemplate.getAssociatedRoles(),
deserializedCourseTemplate.getRepeatablePart(), deserializedCourseTemplate.getTags(),
deserializedCourseTemplate.getOptionalImageURL());
final JSONObject serializedMarkedProperties = courseTemplateSerializer.serialize(createdCourseTemplate);
final String jsonResult = serializedMarkedProperties.toJSONString();
return Response.ok(jsonResult).build();
@@ -1,6 +1,7 @@
package com.sap.sailing.server.impl;
import java.net.URL;
import java.util.Map;
import java.util.UUID;
import com.sap.sailing.domain.common.DeviceIdentifier;
@@ -21,9 +22,10 @@ public interface ReplicatingSharedSailingData extends SharedSailingData,
Void internalCreateMarkTemplate(UUID idOfNewMarkTemplate, CommonMarkProperties properties);
Void internalCreateCourseTemplate(UUID idOfNewCourseTemplate, String courseTemplateName, Iterable<MarkTemplate> marks,
Iterable<WaypointTemplate> waypoints, RepeatablePart optionalRepeatablePart,
Iterable<String> tags, URL optionalImageURL);
Void internalCreateCourseTemplate(UUID idOfNewCourseTemplate, String courseTemplateName,
Iterable<MarkTemplate> marks, Iterable<WaypointTemplate> waypoints,
Map<MarkTemplate, String> associatedRoles, RepeatablePart optionalRepeatablePart, Iterable<String> tags,
URL optionalImageURL);
Void internalSetTrackingDeviceIdentifierForMarkProperties(UUID markPropertiesUUID, DeviceIdentifier deviceIdentifier);
@@ -218,25 +218,47 @@ public class SharedSailingDataImpl implements ReplicatingSharedSailingData, Clea
@Override
public CourseTemplate createCourseTemplate(String courseTemplateName, Iterable<MarkTemplate> marks,
Iterable<WaypointTemplate> waypoints, RepeatablePart optionalRepeatablePart, Iterable<String> tags,
URL optionalImageURL) {
Iterable<WaypointTemplate> waypoints, Map<MarkTemplate, String> associatedRoles,
RepeatablePart optionalRepeatablePart, Iterable<String> tags, URL optionalImageURL) {
final Set<MarkTemplate> marksInSequence = new HashSet<>();
for (WaypointTemplate waypoint : waypoints) {
Util.addAll(waypoint.getControlPointTemplate().getMarks(), marksInSequence);
}
if (!Util.containsAll(marks, marksInSequence)) {
throw new IllegalArgumentException("All marks contained in the sequence are expected to be part of the course template");
}
final Map<MarkTemplate, String> effectiveAssociatedRoles = new HashMap<>();
final Set<String> alreadyUsedRoles = new HashSet<>();
for (MarkTemplate markTemplate : marksInSequence) {
String roleNameForMarkInSequence = associatedRoles.get(markTemplate);
if (roleNameForMarkInSequence == null) {
roleNameForMarkInSequence = markTemplate.getShortName();
}
if (alreadyUsedRoles.add(roleNameForMarkInSequence)) {
throw new IllegalArgumentException(
"Role name " + roleNameForMarkInSequence + " can't be used twice in a course template");
}
effectiveAssociatedRoles.put(markTemplate, roleNameForMarkInSequence);
}
final UUID idOfNewCourseTemplate = UUID.randomUUID();
return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
SecuredDomainType.COURSE_TEMPLATE,
CourseTemplate.getTypeRelativeObjectIdentifier(idOfNewCourseTemplate),
idOfNewCourseTemplate + "/" + courseTemplateName, () -> {
apply(s -> s.internalCreateCourseTemplate(idOfNewCourseTemplate, courseTemplateName, marks,
waypoints, optionalRepeatablePart, tags, optionalImageURL));
waypoints, effectiveAssociatedRoles, optionalRepeatablePart, tags, optionalImageURL));
return getCourseTemplateById(idOfNewCourseTemplate);
});
}
@Override
public Void internalCreateCourseTemplate(UUID idOfNewCourseTemplate, String courseTemplateName, Iterable<MarkTemplate> marks,
Iterable<WaypointTemplate> waypoints, RepeatablePart optionalRepeatablePart,
Iterable<String> tags, URL optionalImageURL) {
public Void internalCreateCourseTemplate(UUID idOfNewCourseTemplate, String courseTemplateName,
Iterable<MarkTemplate> marks, Iterable<WaypointTemplate> waypoints,
Map<MarkTemplate, String> associatedRoles, RepeatablePart optionalRepeatablePart, Iterable<String> tags,
URL optionalImageURL) {
final CourseTemplate courseTemplate = new CourseTemplateImpl(idOfNewCourseTemplate, courseTemplateName, marks,
waypoints, optionalImageURL, optionalRepeatablePart);
waypoints, associatedRoles, optionalImageURL, optionalRepeatablePart);
mongoObjectFactory.storeCourseTemplate(courseTemplate);
courseTemplatesById.put(courseTemplate.getId(), courseTemplate);
return null;