Bug 5085: Changed CourseTemplate and CourseConfiguration to use MarkRole

instead of String and changed CourseBase to reference MarkRoles by using
their UUID
This commit is contained in:
Steffen Schaefer committed 2019-11-18 11:15:36 +01:00
1 parent 98192e9a08
commit 367e8f7d62
32 files changed
+273 -151

No files matched your search

@@ -223,11 +223,13 @@ public interface DomainObjectFactory {
*/
Map<? extends Integer, ? extends Pair<DetailedRaceInfo, AnniversaryType>> getAnniversaryData() throws MalformedURLException;
Iterable<MarkProperties> loadAllMarkProperties(Function<UUID, MarkTemplate> markTemplateResolver);
Iterable<MarkProperties> loadAllMarkProperties(Function<UUID, MarkTemplate> markTemplateResolver,
Function<UUID, MarkRole> markRoleResolver);
Iterable<MarkTemplate> loadAllMarkTemplates();
Iterable<MarkRole> loadAllMarkRoles();
Iterable<CourseTemplate> loadAllCourseTemplates(Function<UUID, MarkTemplate> markTemplateResolver);
Iterable<CourseTemplate> loadAllCourseTemplates(Function<UUID, MarkTemplate> markTemplateResolver,
Function<UUID, MarkRole> markRoleResolver);
}
@@ -1941,10 +1941,10 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
entryObject.getString(FieldNames.RACE_LOG_COURSE_ASSOCIATED_ROLES_MARK_ID.name()));
final Mark mark = baseDomainFactory.getExistingMarkById(markUUID);
if (mark != null) {
final String roleOrNull = entryObject
.getString(FieldNames.RACE_LOG_COURSE_ASSOCIATED_ROLES_ROLE.name());
if (roleOrNull != null) {
courseData.getA().addRoleMapping(mark, roleOrNull);
final String roleIdAsStringOrNull = entryObject
.getString(FieldNames.RACE_LOG_COURSE_ASSOCIATED_ROLES_ROLE_ID.name());
if (roleIdAsStringOrNull != null) {
courseData.getA().addRoleMapping(mark, UUID.fromString(roleIdAsStringOrNull));
}
} else {
logger.warning(String.format("Could not resolve mark with id %s for course %s.", markUUID, id));
@@ -2739,13 +2739,14 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
}
@Override
public Iterable<MarkProperties> loadAllMarkProperties(Function<UUID, MarkTemplate> markTemplateResolver) {
public Iterable<MarkProperties> loadAllMarkProperties(Function<UUID, MarkTemplate> markTemplateResolver,
Function<UUID, MarkRole> markRoleResolver) {
final List<MarkProperties> result = new ArrayList<>();
final MongoCollection<Document> configurationCollection = database
.getCollection(CollectionNames.MARK_PROPERTIES.name());
try {
for (final Document dbObject : configurationCollection.find()) {
final MarkProperties entry = loadMarkPropertiesEntry(dbObject, markTemplateResolver);
final MarkProperties entry = loadMarkPropertiesEntry(dbObject, markTemplateResolver, markRoleResolver);
result.add(entry);
}
} catch (Exception e) {
@@ -2757,7 +2758,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
}
private MarkProperties loadMarkPropertiesEntry(final Document dbObject,
Function<UUID, MarkTemplate> markTemplateResolver) {
Function<UUID, MarkTemplate> markTemplateResolver,
Function<UUID, MarkRole> markRoleResolver) {
//load all mandatory data
final UUID id = UUID.fromString(dbObject.getString(FieldNames.MARK_PROPERTIES_ID.name()));
final String name = dbObject.getString(FieldNames.COMMON_MARK_PROPERTIES_NAME.name());
@@ -2819,8 +2821,10 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
final Document lastUsedRoleObject = dbObject.get(FieldNames.MARK_PROPERTIES_USED_ROLE.name(), Document.class);
final Map<Object, Object> mapUsedRole = new HashMap<>();
lastUsedRoleObject.forEach((k, v) -> mapUsedRole.put(k, v));
final Map<String, TimePoint> lastUsedRole = mapUsedRole.entrySet().stream()
.collect(Collectors.toMap(k -> k.toString(), v -> parseTimePoint(v)));
final Map<MarkRole, TimePoint> lastUsedRole = mapUsedRole.entrySet().stream()
.collect(Collectors.toMap(
(Object markRoleIdObject) -> markRoleResolver.apply(UUID.fromString((String) markRoleIdObject)),
v -> parseTimePoint(v)));
builder.withLastUsedRole(lastUsedRole);
return builder.build();
@@ -3259,13 +3263,14 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
}
@Override
public Iterable<CourseTemplate> loadAllCourseTemplates(Function<UUID, MarkTemplate> markTemplateResolver) {
public Iterable<CourseTemplate> loadAllCourseTemplates(Function<UUID, MarkTemplate> markTemplateResolver,
Function<UUID, MarkRole> markRoleResolver) {
final List<CourseTemplate> result = new ArrayList<>();
final MongoCollection<Document> configurationCollection = database
.getCollection(CollectionNames.COURSE_TEMPLATES.name());
try {
for (final Document dbObject : configurationCollection.find()) {
final CourseTemplate entry = loadCourseTemplateEntry(dbObject, markTemplateResolver);
final CourseTemplate entry = loadCourseTemplateEntry(dbObject, markTemplateResolver, markRoleResolver);
result.add(entry);
}
} catch (Exception e) {
@@ -3277,7 +3282,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
}
private CourseTemplate loadCourseTemplateEntry(Document dbObject,
Function<UUID, MarkTemplate> markTemplateResolver) {
Function<UUID, MarkTemplate> markTemplateResolver,
Function<UUID, MarkRole> markRoleResolver) {
// load master data
final UUID id = UUID.fromString(dbObject.getString(FieldNames.COURSE_TEMPLATE_ID.name()));
final String name = dbObject.getString(FieldNames.COURSE_TEMPLATE_NAME.name());
@@ -3297,7 +3303,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
final ArrayList<?> markTemplatesList = dbObject.get(FieldNames.COURSE_TEMPLATE_MARK_TEMPLATES.name(),
ArrayList.class);
final Set<MarkTemplate> markTemplates = new HashSet<>();
final Map<MarkTemplate, String> associatedRoles = new HashMap<>();
final Map<MarkTemplate, MarkRole> associatedRoles = new HashMap<>();
for (Object entry : markTemplatesList) {
if (entry instanceof Document) {
final Document entryObject = (Document) entry;
@@ -3306,9 +3312,10 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
markTemplateUUID);
if (markTemplate != null) {
markTemplates.add(markTemplate);
final String roleOrNull = entryObject.getString(FieldNames.COURSE_TEMPLATE_MARK_TEMPLATE_ROLE.name());
if (roleOrNull != null) {
associatedRoles.put(markTemplate, roleOrNull);
final String roleIdAsStringOrNull = entryObject.getString(FieldNames.COURSE_TEMPLATE_MARK_TEMPLATE_ROLE.name());
final MarkRole markRoleOrNull = roleIdAsStringOrNull == null ? null : markRoleResolver.apply(UUID.fromString(roleIdAsStringOrNull));
if (markRoleOrNull != null) {
associatedRoles.put(markTemplate, markRoleOrNull);
}
} else {
logger.warning(String.format("Could not resolve MarkTemplate with id %s for CourseTemplate %s.",
@@ -101,7 +101,7 @@ public enum FieldNames {
RACE_LOG_EVENT_AUTHOR_PRIORITY, RACE_LOG_EVENT_INVOLVED_BOATS, RACE_LOG_EVENT_FLAG_UPPER, RACE_LOG_EVENT_FLAG_LOWER, RACE_LOG_EVENT_FLAG_DISPLAYED,
RACE_LOG_EVENT_START_TIME, RACE_LOG_EVENT_CLASS, RACE_LOG_EVENT_NEXT_STATUS, RACE_LOG_COURSE_DESIGN, RACE_LOG_COURSE_DESIGNER_MODE, WAYPOINT_ID, WAYPOINT_NAME,
WAYPOINT_PASSINGINSTRUCTIONS, CONTROLPOINT, CONTROLPOINT_CLASS, MARK_ID, MARK_COLOR, MARK_NAME, MARK_SHORT_NAME, MARK_PATTERN, MARK_SHAPE, MARK_TYPE,
MARK_ORIGINATING_MARK_TEMPLATE_ID, MARK_ORIGINATING_MARK_PROPERTIES_ID, RACE_LOG_COURSE_ORIGINATING_TEMPLATE_ID, RACE_LOG_COURSE_ASSOCIATED_ROLES, RACE_LOG_COURSE_ASSOCIATED_ROLES_MARK_ID, RACE_LOG_COURSE_ASSOCIATED_ROLES_ROLE,
MARK_ORIGINATING_MARK_TEMPLATE_ID, MARK_ORIGINATING_MARK_PROPERTIES_ID, RACE_LOG_COURSE_ORIGINATING_TEMPLATE_ID, RACE_LOG_COURSE_ASSOCIATED_ROLES, RACE_LOG_COURSE_ASSOCIATED_ROLES_MARK_ID, RACE_LOG_COURSE_ASSOCIATED_ROLES_ROLE_ID,
CONTROLPOINT_VALUE, CONTROLPOINTWITHTWOMARKS_ID, CONTROLPOINTWITHTWOMARKS_NAME, CONTROLPOINTWITHTWOMARKS_SHORT_NAME, CONTROLPOINTWITHTWOMARKS_LEFT, CONTROLPOINTWITHTWOMARKS_RIGHT,
RACE_LOG_POSITIONED_COMPETITORS, RACE_LOG_PATHFINDER_ID, RACE_LOG_GATE_LINE_OPENING_TIME, RACE_LOG_GOLF_DOWN_TIME, RACE_LOG_START_PROCEDURE_TYPE,
RACE_LOG_PROTEST_START_TIME, RACE_LOG_PROTEST_END_TIME, RACE_LOG_COURSE_DESIGN_NAME, RACE_LOG_REVOKED_EVENT_ID, RACE_LOG_REVOKED_EVENT_TYPE,
@@ -192,7 +192,7 @@ public enum FieldNames {
// mark template fields
MARK_TEMPLATE_ID,
// mark role fields
MARK_ROLE_ID, MARK_ROLE_NAME,
@@ -1316,7 +1316,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
courseDesignChangedEvent.getCourseDesign().getAssociatedRoles().forEach((mark, role) -> {
final Document mapping = new Document();
mapping.put(FieldNames.RACE_LOG_COURSE_ASSOCIATED_ROLES_MARK_ID.name(), mark.getId().toString());
mapping.put(FieldNames.RACE_LOG_COURSE_ASSOCIATED_ROLES_ROLE.name(), role);
mapping.put(FieldNames.RACE_LOG_COURSE_ASSOCIATED_ROLES_ROLE_ID.name(), role.toString());
roleMap.add(mapping);
});
@@ -1474,7 +1474,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
result.put(FieldNames.MARK_PROPERTIES_USED_TEMPLATE.name(), new BasicDBObject(lastUsedTemplateMap));
Map<String, Long> lastUsedRoleMap = markProperties.getLastUsedRole().entrySet().stream()
.collect(Collectors.toMap(k -> k.getKey(), v -> v.getValue().asMillis()));
.collect(Collectors.toMap(k -> k.getKey().getId().toString(), v -> v.getValue().asMillis()));
result.put(FieldNames.MARK_PROPERTIES_USED_ROLE.name(), new BasicDBObject(lastUsedRoleMap));
return result;
}
@@ -2067,9 +2067,9 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
courseTemplate.getMarkTemplates().forEach(m -> {
final BasicDBObject markTemplateObject = new BasicDBObject(
FieldNames.COURSE_TEMPLATE_MARK_TEMPLATE_ID.name(), m.getId().toString());
final String role = courseTemplate.getAssociatedRoles().get(m);
final MarkRole role = courseTemplate.getAssociatedRoles().get(m);
if (role != null) {
markTemplateObject.append(FieldNames.COURSE_TEMPLATE_MARK_TEMPLATE_ROLE.name(), role);
markTemplateObject.append(FieldNames.COURSE_TEMPLATE_MARK_TEMPLATE_ROLE.name(), role.getId().toString());
}
markTemplates.add(markTemplateObject);
});
@@ -59,8 +59,8 @@ public interface CourseBase extends Named {
* @return the associated roles required for checking course template validity and when creating a new course
* template from this course.
*/
Map<Mark, String> getAssociatedRoles();
Map<Mark, UUID> getAssociatedRoles();
void addRoleMapping(Mark mark, String role);
void addRoleMapping(Mark mark, UUID role);
}
@@ -21,7 +21,7 @@ public class CourseDataImpl extends NamedImpl implements CourseBase {
private final UUID originatingCourseTemplateId;
private final Map<Mark, String> associatedRoles = new HashMap<>();
private final Map<Mark, UUID> associatedRoles = new HashMap<>();
public CourseDataImpl(String name) {
this(name, null);
@@ -91,11 +91,11 @@ public class CourseDataImpl extends NamedImpl implements CourseBase {
return originatingCourseTemplateId;
}
public void addRoleMapping(Mark mark, String role) {
public void addRoleMapping(Mark mark, UUID role) {
associatedRoles.put(mark, role);
}
public Map<Mark, String> getAssociatedRoles() {
public Map<Mark, UUID> getAssociatedRoles() {
return associatedRoles;
}
@@ -1,4 +1,4 @@
package com.sap.sailing.domain.coursetemplate;
public interface CourseConfiguration extends CourseConfigurationBase {
public interface CourseConfiguration extends CourseConfigurationBase<IsMarkRole> {
}
@@ -22,7 +22,7 @@ import com.sap.sse.common.Named;
* The configuration for all marks are returned by {@link #getAllMarks()} because when pushing
* this to a Regatta the marks for all these configurations have to be established.
*/
public interface CourseConfigurationBase extends WithOptionalRepeatablePart, Named {
public interface CourseConfigurationBase<R extends IsMarkRole> extends WithOptionalRepeatablePart, Named {
/**
* If this course configuration has been obtained from a {@link CourseTemplate} without modifying the sequence of
* waypoints and their mapping to {@link MarkTemplate}s, this method will return that {@link CourseTemplate}. In all
@@ -51,7 +51,7 @@ public interface CourseConfigurationBase extends WithOptionalRepeatablePart, Nam
* Returns all {@link MarkConfiguration MarkConfigurations} that are part of the {@link CourseConfigurationBase} and
* have a role name explicitly associated.
*/
Map<MarkConfiguration, String> getAssociatedRoles();
Map<MarkConfiguration, R> getAssociatedRoles();
/**
* A {@link CourseConfigurationBase} having a {@link RepeatablePart} can optionally also specify a number of laps.
@@ -0,0 +1,4 @@
package com.sap.sailing.domain.coursetemplate;
public interface CourseConfigurationWithMarkRoles extends CourseConfigurationBase<MarkRole> {
}
@@ -69,7 +69,7 @@ public interface CourseTemplate extends WithOptionalRepeatablePart, NamedWithUUI
Iterable<WaypointTemplate> getWaypointTemplates();
Map<MarkTemplate, String> getAssociatedRoles();
Map<MarkTemplate, MarkRole> getAssociatedRoles();
URL getOptionalImageURL();
@@ -73,7 +73,7 @@ public interface MarkProperties extends CommonMarkPropertiesWithOptionalPosition
Map<MarkTemplate, TimePoint> getLastUsedTemplate();
Map<String, TimePoint> getLastUsedRole();
Map<MarkRole, TimePoint> getLastUsedRole();
public static TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier(UUID markPropertiesUUID) {
return new TypeRelativeObjectIdentifier(markPropertiesUUID.toString());
@@ -23,7 +23,7 @@ public class MarkPropertiesBuilder {
private DeviceIdentifier deviceId;
private Position position;
private Map<MarkTemplate, TimePoint> lastUsedTemplate;
private Map<String, TimePoint> lastUsedRole;
private Map<MarkRole, TimePoint> lastUsedRole;
public MarkPropertiesBuilder(UUID id, String name, String shortName, Color color, String shape, String pattern,
MarkType type) {
@@ -77,7 +77,7 @@ public class MarkPropertiesBuilder {
this.lastUsedTemplate = lastUsedTemplate;
}
public void withLastUsedRole(Map<String, TimePoint> lastUsedRole) {
public void withLastUsedRole(Map<MarkRole, TimePoint> lastUsedRole) {
this.lastUsedRole = lastUsedRole;
}
@@ -11,14 +11,14 @@ import com.sap.sailing.domain.coursetemplate.MarkConfiguration;
import com.sap.sailing.domain.coursetemplate.RepeatablePart;
import com.sap.sailing.domain.coursetemplate.WaypointWithMarkConfiguration;
public abstract class CourseConfigurationBaseImpl implements CourseConfigurationBase<R> {
public abstract class CourseConfigurationBaseImpl<R extends IsMarkRole> implements CourseConfigurationBase<R> {
private static final long serialVersionUID = -9189989170055144298L;
private final CourseTemplate optionalCourseTemplate;
// TODO decide if we should combine markConfigurations and roleMapping to one field
private final Set<MarkConfiguration> markConfigurations;
private final Map<MarkConfiguration, String> associatedRoles;
private final Map<MarkConfiguration, R> associatedRoles;
private final List<WaypointWithMarkConfiguration> waypoints;
private final RepeatablePart optionalRepeatablePart;
private final String name;
@@ -26,7 +26,7 @@ public abstract class CourseConfigurationBaseImpl implements CourseConfiguration
private Integer numberOfLaps;
public CourseConfigurationBaseImpl(CourseTemplate optionalCourseTemplate, Set<MarkConfiguration> markConfigurations,
Map<MarkConfiguration, String> associatedRoles, List<WaypointWithMarkConfiguration> waypoints,
Map<MarkConfiguration, R> associatedRoles, List<WaypointWithMarkConfiguration> waypoints,
RepeatablePart optionalRepeatablePart, Integer numberOfLaps, String name) {
super();
this.optionalCourseTemplate = optionalCourseTemplate;
@@ -59,7 +59,7 @@ public abstract class CourseConfigurationBaseImpl implements CourseConfiguration
}
@Override
public Map<MarkConfiguration, String> getAssociatedRoles() {
public Map<MarkConfiguration, R> getAssociatedRoles() {
return associatedRoles;
}
@@ -11,12 +11,12 @@ import com.sap.sailing.domain.coursetemplate.MarkConfiguration;
import com.sap.sailing.domain.coursetemplate.RepeatablePart;
import com.sap.sailing.domain.coursetemplate.WaypointWithMarkConfiguration;
public class CourseConfigurationImpl extends CourseConfigurationBaseImpl implements CourseConfiguration {
public class CourseConfigurationImpl extends CourseConfigurationBaseImpl<IsMarkRole> implements CourseConfiguration {
private static final long serialVersionUID = 4471259140392773170L;
public CourseConfigurationImpl(CourseTemplate optionalCourseTemplate, Set<MarkConfiguration> markConfigurations,
Map<MarkConfiguration, String> associatedRoles, List<WaypointWithMarkConfiguration> waypoints,
Map<MarkConfiguration, IsMarkRole> associatedRoles, List<WaypointWithMarkConfiguration> waypoints,
RepeatablePart optionalRepeatablePart, Integer numberOfLaps, String name) {
super(optionalCourseTemplate, markConfigurations, associatedRoles, waypoints, optionalRepeatablePart,
numberOfLaps, name);
@@ -0,0 +1,27 @@
package com.sap.sailing.domain.coursetemplate.impl;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.sap.sailing.domain.coursetemplate.CourseConfigurationWithMarkRoles;
import com.sap.sailing.domain.coursetemplate.CourseTemplate;
import com.sap.sailing.domain.coursetemplate.MarkConfiguration;
import com.sap.sailing.domain.coursetemplate.MarkRole;
import com.sap.sailing.domain.coursetemplate.RepeatablePart;
import com.sap.sailing.domain.coursetemplate.WaypointWithMarkConfiguration;
public class CourseConfigurationWithMarkRolesImpl extends CourseConfigurationBaseImpl<MarkRole>
implements CourseConfigurationWithMarkRoles {
private static final long serialVersionUID = 6040984618331175522L;
public CourseConfigurationWithMarkRolesImpl(CourseTemplate optionalCourseTemplate,
Set<MarkConfiguration> markConfigurations, Map<MarkConfiguration, MarkRole> associatedRoles,
List<WaypointWithMarkConfiguration> waypoints, RepeatablePart optionalRepeatablePart, Integer numberOfLaps,
String name) {
super(optionalCourseTemplate, markConfigurations, associatedRoles, waypoints, optionalRepeatablePart,
numberOfLaps, name);
}
}
@@ -9,6 +9,7 @@ import java.util.Set;
import java.util.UUID;
import com.sap.sailing.domain.coursetemplate.CourseTemplate;
import com.sap.sailing.domain.coursetemplate.MarkRole;
import com.sap.sailing.domain.coursetemplate.MarkTemplate;
import com.sap.sailing.domain.coursetemplate.RepeatablePart;
import com.sap.sailing.domain.coursetemplate.WaypointTemplate;
@@ -22,7 +23,7 @@ public class CourseTemplateImpl extends NamedWithUUIDImpl implements CourseTempl
private final ArrayList<WaypointTemplate> waypoints;
private final Map<MarkTemplate, String> associatedRoles;
private final Map<MarkTemplate, MarkRole> associatedRoles;
private Iterable<String> tags = new ArrayList<>();
@@ -35,17 +36,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,
Map<MarkTemplate, String> associatedRoles, URL optionalImageURL) {
Map<MarkTemplate, MarkRole> associatedRoles, URL optionalImageURL) {
this(UUID.randomUUID(), name, marks, waypoints, associatedRoles, optionalImageURL);
}
public CourseTemplateImpl(UUID id, String name, Iterable<MarkTemplate> marks,
Iterable<WaypointTemplate> waypoints, Map<MarkTemplate, String> associatedRoles, URL optionalImageURL) {
Iterable<WaypointTemplate> waypoints, Map<MarkTemplate, MarkRole> associatedRoles, URL optionalImageURL) {
this(id, name, marks, waypoints, associatedRoles, optionalImageURL, /* optionalRepeatablePart */ null, null);
}
public CourseTemplateImpl(UUID id, String name, Iterable<MarkTemplate> marks, Iterable<WaypointTemplate> waypoints,
Map<MarkTemplate, String> associatedRoles, URL optionalImageURL, RepeatablePart optionalRepeatablePart,
Map<MarkTemplate, MarkRole> associatedRoles, URL optionalImageURL, RepeatablePart optionalRepeatablePart,
Integer defaultNumberOfLaps) {
super(name, id);
this.defaultNumberOfLaps = defaultNumberOfLaps;
@@ -110,11 +111,11 @@ public class CourseTemplateImpl extends NamedWithUUIDImpl implements CourseTempl
@Override
public Map<MarkTemplate, String> getAssociatedRoles() {
public Map<MarkTemplate, MarkRole> getAssociatedRoles() {
return associatedRoles;
}
public void setAssociatedRoles(Map<MarkTemplate, String> associatedRoles) {
public void setAssociatedRoles(Map<MarkTemplate, MarkRole> associatedRoles) {
this.associatedRoles.clear();
this.associatedRoles.putAll(associatedRoles);
}
@@ -9,6 +9,7 @@ import com.sap.sailing.domain.common.MarkType;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.coursetemplate.CommonMarkProperties;
import com.sap.sailing.domain.coursetemplate.MarkProperties;
import com.sap.sailing.domain.coursetemplate.MarkRole;
import com.sap.sailing.domain.coursetemplate.MarkTemplate;
import com.sap.sse.common.Color;
import com.sap.sse.common.TimePoint;
@@ -21,7 +22,7 @@ public class MarkPropertiesImpl extends CommonMarkPropertiesImpl implements Mark
private UUID id;
private final Map<MarkTemplate, TimePoint> lastUsedTemplate = new HashMap<>();
private final Map<String, TimePoint> lastUsedRole = new HashMap<>();
private final Map<MarkRole, TimePoint> lastUsedRole = new HashMap<>();
public MarkPropertiesImpl(String name, String shortName, Color color, String shape, String pattern, MarkType type) {
this(UUID.randomUUID(), name, shortName, color, shape, pattern, type);
@@ -103,11 +104,11 @@ public class MarkPropertiesImpl extends CommonMarkPropertiesImpl implements Mark
}
@Override
public Map<String, TimePoint> getLastUsedRole() {
public Map<MarkRole, TimePoint> getLastUsedRole() {
return lastUsedRole;
}
public void setLastUsedRole(Map<String, TimePoint> lastUsedRole) {
public void setLastUsedRole(Map<MarkRole, TimePoint> lastUsedRole) {
this.lastUsedRole.clear();
this.lastUsedRole.putAll(lastUsedRole);
}
@@ -1,6 +1,7 @@
package com.sap.sailing.domain.base;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import com.sap.sailing.domain.common.PassingInstruction;
@@ -43,7 +44,7 @@ public interface Course extends CourseBase, Renamable {
* had been used.
*/
void update(Iterable<Util.Pair<ControlPoint, PassingInstruction>> newControlPoints,
Map<Mark, String> associatedRoles, DomainFactory baseDomainFactory) throws PatchFailedException;
Map<Mark, UUID> associatedRoles, DomainFactory baseDomainFactory) throws PatchFailedException;
int getNumberOfWaypoints();
@@ -45,7 +45,7 @@ public class CourseImpl extends RenamableImpl implements Course {
private final Map<Waypoint, Integer> waypointIndexes;
private final List<Leg> legs;
private final UUID originatingCourseTemplateId;
private final Map<Mark, String> associatedRoles = new HashMap<>();
private final Map<Mark, UUID> associatedRoles = new HashMap<>();
private transient Set<CourseListener> listeners;
private transient NamedReentrantReadWriteLock lock;
@@ -350,7 +350,7 @@ public class CourseImpl extends RenamableImpl implements Course {
@Override
public void update(Iterable<Pair<ControlPoint, PassingInstruction>> newControlPoints,
Map<Mark, String> associatedRoles, DomainFactory baseDomainFactory) throws PatchFailedException {
Map<Mark, UUID> associatedRoles, DomainFactory baseDomainFactory) throws PatchFailedException {
Patch<Waypoint> patch = null;
synchronized (updateMonitor) {
lockForRead();
@@ -408,12 +408,12 @@ public class CourseImpl extends RenamableImpl implements Course {
}
@Override
public Map<Mark, String> getAssociatedRoles() {
public Map<Mark, UUID> getAssociatedRoles() {
return associatedRoles;
}
@Override
public void addRoleMapping(Mark mark, String role) {
associatedRoles.put(mark, role);
public void addRoleMapping(Mark mark, UUID markRoleId) {
associatedRoles.put(mark, markRoleId);
}
}
@@ -40,7 +40,7 @@ public interface SharedSailingData {
Iterable<MarkTemplate> getAllMarkTemplates();
Iterable<CourseTemplate> getAllCourseTemplates(Iterable<String> tagsToFilterFor);
Iterable<MarkRole> getAllMarkRoles();
MarkRole createMarkRole(String name);
@@ -72,7 +72,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,
Map<MarkTemplate, String> associatedRoles, RepeatablePart optionalRepeatablePart, Iterable<String> tags,
Map<MarkTemplate, MarkRole> associatedRoles, RepeatablePart optionalRepeatablePart, Iterable<String> tags,
URL optionalImageURL, Integer defaultNumberOfLaps);
CourseTemplate getCourseTemplateById(UUID id);
@@ -89,7 +89,7 @@ public interface SharedSailingData {
* Keeps the {@link MillisecondsTimePoint#now() current time} of this call which will be returned for the role name
* when invoking {@link #getUsedMarkProperties(String)}.
*/
void recordUsage(MarkProperties markProperties, String roleName);
void recordUsage(MarkProperties markProperties, MarkRole markRole);
/**
* Returns the time points when {@link MarkProperties} objects were {@link #recordUsage(MarkTemplate, MarkProperties) last used}
@@ -101,7 +101,7 @@ public interface SharedSailingData {
* Returns the time points when {@link MarkProperties} objects were {@link #recordUsage(MarkProperties, String) last used}
* for the role name passed in the {@code roleName} parameter.
*/
Map<MarkProperties, TimePoint> getUsedMarkProperties(String roleName);
Map<MarkProperties, TimePoint> getUsedMarkProperties(MarkRole roleName);
void deleteMarkProperties(MarkProperties markProperties);
@@ -139,7 +139,7 @@ public class CourseTemplateEditDialog extends DataEntryDialog<CourseTemplateDTO>
// TODO: implement
final UUID id = currentUuid == null ? UUID.randomUUID() : currentUuid;
final ArrayList<MarkTemplateDTO> markTemplates = new ArrayList<MarkTemplateDTO>();
final Map<MarkTemplateDTO, String> associatedRoles = new HashMap<MarkTemplateDTO, String>();
final Map<MarkTemplateDTO, UUID> associatedRoles = new HashMap<>();
final String optionalUrl = urlTextBox.getText() != null && !urlTextBox.getText().isEmpty()
? urlTextBox.getText()
: null;
@@ -340,6 +340,7 @@ import com.sap.sailing.domain.coursetemplate.ControlPointTemplate;
import com.sap.sailing.domain.coursetemplate.CourseTemplate;
import com.sap.sailing.domain.coursetemplate.MarkPairTemplate.MarkPairTemplateFactory;
import com.sap.sailing.domain.coursetemplate.MarkProperties;
import com.sap.sailing.domain.coursetemplate.MarkRole;
import com.sap.sailing.domain.coursetemplate.MarkTemplate;
import com.sap.sailing.domain.coursetemplate.RepeatablePart;
import com.sap.sailing.domain.coursetemplate.WaypointTemplate;
@@ -9966,8 +9967,9 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
}
public CourseTemplateDTO convertToCourseTemplateDTO(CourseTemplate courseTemplate) {
final Map<MarkTemplateDTO, String> convertedAssociatedRoles = courseTemplate.getAssociatedRoles().entrySet()
.stream().collect(Collectors.toMap(k -> convertToMarkTemplateDTO(k.getKey()), v -> v.getValue()));
final Map<MarkTemplateDTO, UUID> convertedAssociatedRoles = courseTemplate.getAssociatedRoles().entrySet()
.stream().collect(Collectors.toMap(entry -> convertToMarkTemplateDTO(entry.getKey()),
entry -> entry.getValue().getId()));
final List<MarkTemplateDTO> convertedMarkTemplates = StreamSupport
.stream(courseTemplate.getMarkTemplates().spliterator(), false).map(this::convertToMarkTemplateDTO)
.collect(Collectors.toList());
@@ -10052,9 +10054,10 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
final MarkPairTemplateFactory markPairTemplateFactory = new MarkPairTemplateFactory();
final List<WaypointTemplate> waypoints = courseTemplate.getWaypointTemplates().stream()
.map(wp -> convertToWaypointTemplate(wp, markPairTemplateFactory)).collect(Collectors.toList());
final Map<MarkTemplate, String> associatedRoles = courseTemplate.getAssociatedRoles().entrySet().stream()
.collect(Collectors.toMap(k -> getSharedSailingData().getMarkTemplateById(k.getKey().getUuid()),
Entry::getValue));
final Map<MarkTemplate, MarkRole> associatedRoles = courseTemplate.getAssociatedRoles().entrySet().stream()
.collect(Collectors.toMap(
entry -> getSharedSailingData().getMarkTemplateById(entry.getKey().getUuid()),
entry -> getSharedSailingData().getMarkRoleById(entry.getValue())));
final RepeatablePart optionalRepeatablePart = courseTemplate.getRepeatablePart() != null
? convertToRepeatablePart(courseTemplate.getRepeatablePart())
: null;
@@ -26,7 +26,7 @@ public class CourseTemplateDTO extends NamedDTO implements SecuredDTO {
// use concrete types instead of Iterable for GWT serialization
private ArrayList<MarkTemplateDTO> markTemplates = new ArrayList<>();
private ArrayList<WaypointTemplateDTO> waypointTemplates = new ArrayList<>();
private HashMap<MarkTemplateDTO, String> associatedRoles = new HashMap<>();
private HashMap<MarkTemplateDTO, UUID> associatedRoles = new HashMap<>();
private ArrayList<String> tags = new ArrayList<>();
private String optionalImageUrl;
@@ -41,7 +41,7 @@ public class CourseTemplateDTO extends NamedDTO implements SecuredDTO {
}
public CourseTemplateDTO(UUID uuid, String name, Iterable<MarkTemplateDTO> markTemplates,
Iterable<WaypointTemplateDTO> waypointTemplates, Map<MarkTemplateDTO, String> associatedRoles,
Iterable<WaypointTemplateDTO> waypointTemplates, Map<MarkTemplateDTO, UUID> associatedRoles,
String optionalImageUrl, Iterable<String> tags, RepeatablePartDTO repeatablePart,
Integer defaultNumberOfLaps) {
super(name);
@@ -49,7 +49,7 @@ public class CourseTemplateDTO extends NamedDTO implements SecuredDTO {
this.defaultNumberOfLaps = defaultNumberOfLaps;
Util.addAll(markTemplates, this.markTemplates);
Util.addAll(waypointTemplates, this.waypointTemplates);
this.associatedRoles.putAll(this.associatedRoles);
this.associatedRoles.putAll(associatedRoles);
this.optionalImageUrl = optionalImageUrl;
Util.addAll(tags, this.tags);
this.repeatablePart = repeatablePart;
@@ -105,7 +105,7 @@ public class CourseTemplateDTO extends NamedDTO implements SecuredDTO {
return waypointTemplates;
}
public HashMap<MarkTemplateDTO, String> getAssociatedRoles() {
public HashMap<MarkTemplateDTO, UUID> getAssociatedRoles() {
return associatedRoles;
}
@@ -20,10 +20,12 @@ import com.sap.sailing.domain.coursetemplate.CommonMarkProperties;
import com.sap.sailing.domain.coursetemplate.CourseConfiguration;
import com.sap.sailing.domain.coursetemplate.CourseTemplate;
import com.sap.sailing.domain.coursetemplate.FreestyleMarkConfiguration;
import com.sap.sailing.domain.coursetemplate.IsMarkRole;
import com.sap.sailing.domain.coursetemplate.MarkConfiguration;
import com.sap.sailing.domain.coursetemplate.MarkPairWithConfiguration;
import com.sap.sailing.domain.coursetemplate.MarkProperties;
import com.sap.sailing.domain.coursetemplate.MarkPropertiesBasedMarkConfiguration;
import com.sap.sailing.domain.coursetemplate.MarkRole;
import com.sap.sailing.domain.coursetemplate.MarkTemplate;
import com.sap.sailing.domain.coursetemplate.MarkTemplateBasedMarkConfiguration;
import com.sap.sailing.domain.coursetemplate.Positioning;
@@ -36,6 +38,7 @@ import com.sap.sailing.domain.coursetemplate.impl.FixedPositioningImpl;
import com.sap.sailing.domain.coursetemplate.impl.FreestyleMarkConfigurationImpl;
import com.sap.sailing.domain.coursetemplate.impl.MarkPairWithConfigurationImpl;
import com.sap.sailing.domain.coursetemplate.impl.MarkPropertiesBasedMarkConfigurationImpl;
import com.sap.sailing.domain.coursetemplate.impl.MarkRoleNameImpl;
import com.sap.sailing.domain.coursetemplate.impl.MarkTemplateBasedMarkConfigurationImpl;
import com.sap.sailing.domain.coursetemplate.impl.RegattaMarkConfigurationImpl;
import com.sap.sailing.domain.coursetemplate.impl.StoredDeviceIdentifierPositioningImpl;
@@ -59,7 +62,7 @@ public class CourseConfigurationBuilder {
private final String name;
// TODO decide if we should combine markConfigurations and roleMapping to one field
private Set<MarkConfiguration> markConfigurations = new HashSet<>();
private Map<MarkConfiguration, String> associatedRoles = new HashMap<>();
private Map<MarkConfiguration, IsMarkRole> associatedRoles = new HashMap<>();
private List<WaypointWithMarkConfiguration> waypoints = new ArrayList<>();
private RepeatablePart optionalRepeatablePart;
private Integer numberOfLaps;
@@ -133,6 +136,22 @@ public class CourseConfigurationBuilder {
}
return resolvedMarkTemplate;
}
private MarkRole resolveMarkRoleByID(UUID markRoleID) {
MarkRole resolvedMarkRole = null;
if (optionalCourseTemplate != null) {
for (MarkRole markRole : optionalCourseTemplate.getAssociatedRoles().values()) {
if (markRole.getId().equals(markRoleID)) {
resolvedMarkRole = markRole;
break;
}
}
}
if (resolvedMarkRole == null) {
resolvedMarkRole = sharedSailingData.getMarkRoleById(markRoleID);
}
return resolvedMarkRole;
}
public MarkPropertiesBasedMarkConfiguration addMarkPropertiesConfiguration(UUID markPropertiesID,
UUID optionalMarkTemplateID, StorablePositioning optionalPositioning, boolean storeToInventory) {
@@ -209,17 +228,24 @@ public class CourseConfigurationBuilder {
waypoints.add(new WaypointWithMarkConfigurationImpl(markPair, passingInstruction));
}
public void setRole(MarkConfiguration markConfiguration, String roleName) {
public void setRole(MarkConfiguration markConfiguration, UUID markRoleId, String roleName) {
if (!markConfigurations.contains(markConfiguration)) {
throw new IllegalArgumentException();
}
final IsMarkRole candidate;
if (markRoleId != null) {
candidate = resolveMarkRoleByID(markRoleId);
} else {
candidate = new MarkRoleNameImpl(roleName);
}
associatedRoles.forEach((mc, existingRole) -> {
if (roleName.equals(existingRole) && !mc.equals(markConfiguration)) {
if (candidate.equals(existingRole) && !mc.equals(markConfiguration)) {
throw new IllegalArgumentException(
"Role name '" + roleName + "' is already used for another mark configuration");
}
});
associatedRoles.put(markConfiguration, roleName);
associatedRoles.put(markConfiguration, candidate);
}
public void setOptionalRepeatablePart(RepeatablePart optionalRepeatablePart) {
@@ -86,10 +86,13 @@ public class CourseConfigurationJsonDeserializer implements JsonDeserializer<Cou
markPropertiesID != null ? UUID.fromString(markPropertiesID) : null,
markID != null ? UUID.fromString(markID) : null, optionalFreestyleProperties,
storablePositioning, storeToInventory);
String roleName = (String) markConfigurationJSON
.get(CourseConfigurationJsonSerializer.FIELD_MARK_CONFIGURATION_ASSOCIATED_ROLE);
if (roleName != null && !roleName.isEmpty()) {
builder.setRole(markConfiguration, roleName);
final String markRoleIdOrNullAsString = (String) markConfigurationJSON
.get(CourseConfigurationJsonSerializer.FIELD_MARK_CONFIGURATION_ASSOCIATED_ROLE_ID);
final UUID markRoleIdOrNull = markRoleIdOrNullAsString == null ? null : UUID.fromString(markRoleIdOrNullAsString);
String markRoleNameOrNull = (String) markConfigurationJSON
.get(CourseConfigurationJsonSerializer.FIELD_MARK_CONFIGURATION_ASSOCIATED_ROLE_ID);
if (markRoleIdOrNull != null || (markRoleNameOrNull != null && !markRoleNameOrNull.isEmpty())) {
builder.setRole(markConfiguration, markRoleIdOrNull, markRoleNameOrNull);
}
markConfigurationsByID.put(
@@ -16,6 +16,7 @@ import com.sap.sailing.domain.common.PassingInstruction;
import com.sap.sailing.domain.coursetemplate.ControlPointTemplate;
import com.sap.sailing.domain.coursetemplate.CourseTemplate;
import com.sap.sailing.domain.coursetemplate.MarkPairTemplate.MarkPairTemplateFactory;
import com.sap.sailing.domain.coursetemplate.MarkRole;
import com.sap.sailing.domain.coursetemplate.MarkTemplate;
import com.sap.sailing.domain.coursetemplate.RepeatablePart;
import com.sap.sailing.domain.coursetemplate.WaypointTemplate;
@@ -29,10 +30,13 @@ import com.sap.sailing.server.gateway.serialization.impl.MarkTemplateJsonSeriali
public class CourseTemplateJsonDeserializer implements JsonDeserializer<CourseTemplate> {
private final Function<UUID, MarkTemplate> markTemplateResolver;
private final Function<UUID, MarkRole> markRoleResolver;
private final JsonDeserializer<RepeatablePart> repeatablePartJsonDeserializer;
public CourseTemplateJsonDeserializer(Function<UUID, MarkTemplate> markTemplateResolver) {
public CourseTemplateJsonDeserializer(Function<UUID, MarkTemplate> markTemplateResolver,
Function<UUID, MarkRole> markRoleResolver) {
this.markTemplateResolver = markTemplateResolver;
this.markRoleResolver = markRoleResolver;
repeatablePartJsonDeserializer = new RepeatablePartJsonDeserializer();
}
@@ -53,7 +57,7 @@ public class CourseTemplateJsonDeserializer implements JsonDeserializer<CourseTe
}
final Map<UUID, MarkTemplate> allMarkTemplatesById = new HashMap<UUID, MarkTemplate>();
final Map<MarkTemplate, String> roles = new HashMap<>();
final Map<MarkTemplate, MarkRole> roles = new HashMap<>();
final JSONArray allMarkTemplatesJSON = (JSONArray) json.get(CourseTemplateJsonSerializer.FIELD_ALL_MARK_TEMPLATES);
for (Object markTemplateWithOptionalRoleNameObject : allMarkTemplatesJSON) {
final JSONObject markTemplateWithOptionalRoleName = (JSONObject) markTemplateWithOptionalRoleNameObject;
@@ -64,9 +68,10 @@ public class CourseTemplateJsonDeserializer implements JsonDeserializer<CourseTe
throw new JsonDeserializationException("Mark template with ID " + markTemplateUUID + " can't be resolved");
}
allMarkTemplatesById.put(markTemplateUUID, resolvedMarkTemplate);
String roleName = (String) markTemplateWithOptionalRoleName.get(CourseTemplateJsonSerializer.FIELD_ASSOCIATED_ROLE);
if (roleName != null && !roleName.isEmpty()) {
roles.put(resolvedMarkTemplate, roleName);
final String markRoleIdAsStringOrNull = (String) markTemplateWithOptionalRoleName.get(CourseTemplateJsonSerializer.FIELD_ASSOCIATED_ROLE_ID);
if (markRoleIdAsStringOrNull != null && !markRoleIdAsStringOrNull.isEmpty()) {
final MarkRole resolvedMarkRole = markRoleResolver.apply(UUID.fromString(markRoleIdAsStringOrNull));
roles.put(resolvedMarkTemplate, resolvedMarkRole);
}
}
@@ -11,9 +11,11 @@ import com.sap.sailing.domain.coursetemplate.CommonMarkProperties;
import com.sap.sailing.domain.coursetemplate.ControlPointWithMarkConfiguration;
import com.sap.sailing.domain.coursetemplate.CourseConfiguration;
import com.sap.sailing.domain.coursetemplate.FreestyleMarkConfiguration;
import com.sap.sailing.domain.coursetemplate.IsMarkRole;
import com.sap.sailing.domain.coursetemplate.MarkConfiguration;
import com.sap.sailing.domain.coursetemplate.MarkPairWithConfiguration;
import com.sap.sailing.domain.coursetemplate.MarkPropertiesBasedMarkConfiguration;
import com.sap.sailing.domain.coursetemplate.MarkRole;
import com.sap.sailing.domain.coursetemplate.Positioning;
import com.sap.sailing.domain.coursetemplate.RegattaMarkConfiguration;
import com.sap.sailing.domain.coursetemplate.RepeatablePart;
@@ -32,6 +34,7 @@ public class CourseConfigurationJsonSerializer implements JsonSerializer<CourseC
public static final String FIELD_MARK_CONFIGURATION_EFFECTIVE_PROPERTIES = "effectiveProperties";
public static final String FIELD_MARK_CONFIGURATION_FREESTYLE_PROPERTIES = "freestyleProperties";
public static final String FIELD_MARK_CONFIGURATION_ASSOCIATED_ROLE = "associatedRole";
public static final String FIELD_MARK_CONFIGURATION_ASSOCIATED_ROLE_ID = "associatedRoleId";
public static final String FIELD_MARK_CONFIGURATION_POSITIONING = "positioning";
public static final String FIELD_MARK_CONFIGURATION_EFFECTIVE_POSITIONING = "effectivePositioning";
public static final String FIELD_MARK_CONFIGURATION_STORE_TO_INVENTORY = "storeToInventory";
@@ -74,9 +77,12 @@ public class CourseConfigurationJsonSerializer implements JsonSerializer<CourseC
markConfigurationsEntry.put(FIELD_MARK_CONFIGURATION_MARK_TEMPLATE_ID,
markConfiguration.getOptionalMarkTemplate().getId().toString());
}
final String associatedRole = courseConfiguration.getAssociatedRoles().get(markConfiguration);
final IsMarkRole associatedRole = courseConfiguration.getAssociatedRoles().get(markConfiguration);
if (associatedRole != null) {
markConfigurationsEntry.put(FIELD_MARK_CONFIGURATION_ASSOCIATED_ROLE, associatedRole);
markConfigurationsEntry.put(FIELD_MARK_CONFIGURATION_ASSOCIATED_ROLE, associatedRole.getName());
if (associatedRole instanceof MarkRole) {
markConfigurationsEntry.put(FIELD_MARK_CONFIGURATION_ASSOCIATED_ROLE_ID, ((MarkRole)associatedRole).getId().toString());
}
}
if (markConfiguration instanceof FreestyleMarkConfiguration) {
final FreestyleMarkConfiguration freeStyleMarkConfiguration = (FreestyleMarkConfiguration) markConfiguration;
@@ -4,6 +4,7 @@ import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import com.sap.sailing.domain.coursetemplate.CourseTemplate;
import com.sap.sailing.domain.coursetemplate.MarkRole;
import com.sap.sailing.domain.coursetemplate.MarkTemplate;
import com.sap.sailing.domain.coursetemplate.RepeatablePart;
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
@@ -20,7 +21,7 @@ public class CourseTemplateJsonSerializer implements JsonSerializer<CourseTempla
public static final String FIELD_CONTROL_POINT_NAME = "controlPointName";
public static final String FIELD_CONTROL_POINT_SHORT_NAME = "controlPointShortName";
public static final String FIELD_MARK_TEMPLATE_IDS = "markTemplateIds";
public static final String FIELD_ASSOCIATED_ROLE = "associatedRole";
public static final String FIELD_ASSOCIATED_ROLE_ID = "associatedRoleId";
public static final String FIELD_OPTIONAL_REPEATABLE_PART = "optionalRepeatablePart";
public static final String FIELD_DEFAULT_NUMBER_OF_LAPS = "defaultNumberOfLaps";
@@ -47,9 +48,9 @@ public class CourseTemplateJsonSerializer implements JsonSerializer<CourseTempla
final JSONArray allMarkTemplates = new JSONArray();
courseTemplate.getMarkTemplates().forEach(mt -> {
final JSONObject markTemplateEntry = markTemplateJsonSerializer.serialize(mt);
final String associatedRoleOrNull = courseTemplate.getAssociatedRoles().get(mt);
final MarkRole associatedRoleOrNull = courseTemplate.getAssociatedRoles().get(mt);
if (associatedRoleOrNull != null) {
markTemplateEntry.put(FIELD_ASSOCIATED_ROLE, associatedRoleOrNull);
markTemplateEntry.put(FIELD_ASSOCIATED_ROLE_ID, associatedRoleOrNull.getId().toString());
}
allMarkTemplates.add(markTemplateEntry);
});
@@ -37,7 +37,8 @@ public class CourseTemplateResource extends AbstractSailingServerResource {
}
private JsonDeserializer<CourseTemplate> getCourseTemplateDeserializer() {
return new CourseTemplateJsonDeserializer(getSharedSailingData()::getMarkTemplateById);
return new CourseTemplateJsonDeserializer(getSharedSailingData()::getMarkTemplateById,
getSharedSailingData()::getMarkRoleById);
}
private Response getBadCourseTemplateValidationErrorResponse(String errorText) {
@@ -49,15 +49,18 @@ import com.sap.sailing.domain.coursetemplate.CommonMarkProperties;
import com.sap.sailing.domain.coursetemplate.ControlPointTemplate;
import com.sap.sailing.domain.coursetemplate.ControlPointWithMarkConfiguration;
import com.sap.sailing.domain.coursetemplate.CourseConfiguration;
import com.sap.sailing.domain.coursetemplate.CourseConfigurationWithMarkRoles;
import com.sap.sailing.domain.coursetemplate.CourseTemplate;
import com.sap.sailing.domain.coursetemplate.FixedPositioning;
import com.sap.sailing.domain.coursetemplate.FreestyleMarkConfiguration;
import com.sap.sailing.domain.coursetemplate.IsMarkRole;
import com.sap.sailing.domain.coursetemplate.MarkConfiguration;
import com.sap.sailing.domain.coursetemplate.MarkPairTemplate;
import com.sap.sailing.domain.coursetemplate.MarkPairTemplate.MarkPairTemplateFactory;
import com.sap.sailing.domain.coursetemplate.MarkPairWithConfiguration;
import com.sap.sailing.domain.coursetemplate.MarkProperties;
import com.sap.sailing.domain.coursetemplate.MarkPropertiesBasedMarkConfiguration;
import com.sap.sailing.domain.coursetemplate.MarkRole;
import com.sap.sailing.domain.coursetemplate.MarkTemplate;
import com.sap.sailing.domain.coursetemplate.MarkTemplateBasedMarkConfiguration;
import com.sap.sailing.domain.coursetemplate.Positioning;
@@ -67,9 +70,11 @@ import com.sap.sailing.domain.coursetemplate.SmartphoneUUIDPositioning;
import com.sap.sailing.domain.coursetemplate.WaypointTemplate;
import com.sap.sailing.domain.coursetemplate.WaypointWithMarkConfiguration;
import com.sap.sailing.domain.coursetemplate.impl.CourseConfigurationImpl;
import com.sap.sailing.domain.coursetemplate.impl.CourseConfigurationWithMarkRolesImpl;
import com.sap.sailing.domain.coursetemplate.impl.FreestyleMarkConfigurationImpl;
import com.sap.sailing.domain.coursetemplate.impl.MarkPairWithConfigurationImpl;
import com.sap.sailing.domain.coursetemplate.impl.MarkPropertiesBasedMarkConfigurationImpl;
import com.sap.sailing.domain.coursetemplate.impl.MarkRoleNameImpl;
import com.sap.sailing.domain.coursetemplate.impl.MarkTemplateBasedMarkConfigurationImpl;
import com.sap.sailing.domain.coursetemplate.impl.RegattaMarkConfigurationImpl;
import com.sap.sailing.domain.coursetemplate.impl.WaypointTemplateImpl;
@@ -137,7 +142,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
return sharedSailingData.getCourseTemplateById(course.getOriginatingCourseTemplateIdOrNull());
}
private CourseConfiguration handleSaveToInventory(CourseConfiguration courseConfiguration) {
private CourseConfigurationWithMarkRoles handleSaveToInventory(CourseConfiguration courseConfiguration) {
final Map<MarkConfiguration, MarkConfiguration> effectiveConfigurations = new HashMap<>();
for (MarkConfiguration markConfiguration : courseConfiguration.getAllMarks()) {
if (markConfiguration.isStoreToInventory()) {
@@ -189,16 +194,47 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
final CourseConfigurationToCourseConfigurationMapper waypointConfigurationMapper = new CourseConfigurationToCourseConfigurationMapper(
courseConfiguration.getWaypoints(), courseConfiguration.getAssociatedRoles(),
effectiveConfigurations);
return new CourseConfigurationImpl(courseConfiguration.getOptionalCourseTemplate(),
new HashSet<>(effectiveConfigurations.values()), waypointConfigurationMapper.explicitAssociatedRoles,
return new CourseConfigurationWithMarkRolesImpl(courseConfiguration.getOptionalCourseTemplate(),
new HashSet<>(effectiveConfigurations.values()), ensureMarkRoles(waypointConfigurationMapper.explicitAssociatedRoles),
waypointConfigurationMapper.effectiveWaypoints, courseConfiguration.getRepeatablePart(),
courseConfiguration.getNumberOfLaps(), courseConfiguration.getName());
}
private <C> Map<C, MarkRole> ensureMarkRoles(
Map<C, IsMarkRole> explicitAssociatedRoles) {
final Map<C, MarkRole> result = new HashMap<>();
explicitAssociatedRoles.forEach((c, r) -> result.put(c, ensureMarkRole(r)));
return result;
}
private MarkRole ensureMarkRole(IsMarkRole r) {
final MarkRole mr;
if (r instanceof MarkRole) {
mr = (MarkRole) r;
} else {
mr = sharedSailingData.createMarkRole(r.getName());
}
return mr;
}
private MarkRole resolveMarkRole(UUID markRoleId, CourseTemplate optionalCourseTemplate) {
if (markRoleId == null) {
return null;
}
if (optionalCourseTemplate != null) {
for (MarkRole markRoleInCourseTemplate : optionalCourseTemplate.getAssociatedRoles().values()) {
if (markRoleInCourseTemplate.getId().equals(markRoleId)) {
return markRoleInCourseTemplate;
}
}
}
return sharedSailingData.getMarkRoleById(markRoleId);
}
@Override
public CourseConfiguration createCourseTemplateAndUpdatedConfiguration(
final CourseConfiguration courseConfiguration, Iterable<String> tags, URL optionalImageUrl) {
final CourseConfiguration courseConfigurationAfterInventory = handleSaveToInventory(courseConfiguration);
final CourseConfigurationWithMarkRoles courseConfigurationAfterInventory = handleSaveToInventory(courseConfiguration);
final Map<MarkConfiguration, MarkTemplate> markTemplatesByMarkConfigurations = new HashMap<>();
final Map<MarkConfiguration, MarkConfiguration> marksConfigurationsMapping = new HashMap<>();
@@ -281,7 +317,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
};
final CourseTemplate newCourseTemplate = sharedSailingData.createCourseTemplate(courseConfigurationAfterInventory.getName(), new HashSet<>(markTemplatesByMarkConfigurations.values()),
waypointTemplateMapper.effectiveWaypoints, waypointTemplateMapper.allAssociatedRoles, courseConfigurationAfterInventory.getRepeatablePart(),
waypointTemplateMapper.effectiveWaypoints, ensureMarkRoles(waypointTemplateMapper.allAssociatedRoles), courseConfigurationAfterInventory.getRepeatablePart(),
tags, optionalImageUrl,
courseConfigurationAfterInventory.getNumberOfLaps());
return new CourseConfigurationImpl(newCourseTemplate,
@@ -292,16 +328,16 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
}
private void recordUsagesForMarkProperties(Iterable<WaypointWithMarkConfiguration> waypoints,
Map<MarkConfiguration, String> associatedRoles) {
Map<MarkConfiguration, ? extends IsMarkRole> associatedRoles) {
for (MarkConfiguration markConfiguration : getAllMarkConfigurations(waypoints)) {
final MarkProperties markProperties = getAssociatedMarkPropertiesIfAvailable(markConfiguration);
if (markProperties != null) {
final String roleName = getExplicitOrImplicitRoleName(associatedRoles, markConfiguration);
final IsMarkRole role = getExplicitOrImplicitMarkRole(associatedRoles, markConfiguration);
try {
sharedSailingData.recordUsage(markProperties, roleName);
sharedSailingData.recordUsage(markProperties, ensureMarkRole(role));
} catch (Exception e) {
log.log(Level.WARNING,
"Could not record usage for mark properties " + markProperties + " and role " + roleName,
"Could not record usage for mark properties " + markProperties + " and role " + role,
e);
}
final MarkTemplate markTemplateOrNull = markConfiguration.getOptionalMarkTemplate();
@@ -317,10 +353,10 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
}
}
private String getExplicitOrImplicitRoleName(Map<MarkConfiguration, String> associatedRoles, MarkConfiguration markConfiguration) {
String effectiveRole = associatedRoles.get(markConfiguration);
private IsMarkRole getExplicitOrImplicitMarkRole(Map<MarkConfiguration, ? extends IsMarkRole> associatedRoles, MarkConfiguration markConfiguration) {
IsMarkRole effectiveRole = associatedRoles.get(markConfiguration);
if (effectiveRole == null) {
markConfiguration.getEffectiveProperties().getName();
effectiveRole = new MarkRoleNameImpl(markConfiguration.getEffectiveProperties().getName());
}
return effectiveRole;
}
@@ -415,7 +451,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
public CourseBase createCourseFromConfigurationAndDefineMarksAsNeeded(Regatta regatta,
final CourseConfiguration courseConfiguration, TimePoint timePointForDefinitionOfMarksAndDeviceMappings,
AbstractLogEventAuthor author) {
final CourseConfiguration courseConfigurationAfterInventory = handleSaveToInventory(courseConfiguration);
final CourseConfigurationWithMarkRoles courseConfigurationAfterInventory = handleSaveToInventory(courseConfiguration);
recordUsagesForMarkProperties(courseConfiguration.getWaypoints(), courseConfiguration.getAssociatedRoles());
final Map<MarkConfiguration, Mark> marksByMarkConfigurations = new HashMap<>();
@@ -478,10 +514,10 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
protected Waypoint getOrCreateWaypoint(ControlPoint controlPoint, PassingInstruction passingInstruction) {
return new WaypointImpl(controlPoint, passingInstruction);
}
};
courseSequenceMapper.effectiveWaypoints.forEach(wp -> course.addWaypoint(Util.size(course.getWaypoints()), wp));
courseSequenceMapper.explicitAssociatedRoles.forEach(course::addRoleMapping);
ensureMarkRoles(courseSequenceMapper.explicitAssociatedRoles)
.forEach((m, mr) -> course.addRoleMapping(m, mr.getId()));
return course;
}
@@ -505,8 +541,8 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
}
}
final LastUsageBasedAssociater<RegattaMarkConfiguration, String> usagesForRole = new LastUsageBasedAssociater<>(
courseTemplate.getAssociatedRoles().values());
final LastUsageBasedAssociater<RegattaMarkConfiguration, IsMarkRole> usagesForRole = new LastUsageBasedAssociater<>(
new HashSet<IsMarkRole>(courseTemplate.getAssociatedRoles().values()));
for (RaceColumn raceColumn : optionalRegatta.getRaceColumns()) {
for (Fleet fleet : raceColumn.getFleets()) {
@@ -549,9 +585,9 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
? effectiveUsageTP
: existingTP);
String roleName = courseOrNull.getAssociatedRoles().get(mark);
IsMarkRole roleName = resolveMarkRole(courseOrNull.getAssociatedRoles().get(mark), courseTemplate);
if (roleName == null) {
roleName = mark.getName();
roleName = new MarkRoleNameImpl(mark.getName());
}
usagesForRole.addUsage(regattaMarkConfiguration, roleName, effectiveUsageTP);
}
@@ -566,7 +602,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
// Primary matching is based on the associated role.
for (Iterator<MarkTemplate> iterator = markTemplatesToAssociate.iterator(); iterator.hasNext();) {
MarkTemplate mt = iterator.next();
String roleOrNull = courseTemplate.getAssociatedRoles().get(mt);
MarkRole roleOrNull = courseTemplate.getAssociatedRoles().get(mt);
if (roleOrNull != null) {
RegattaMarkConfiguration bestMatchForRole = usagesForRole.getBestMatchForT2(roleOrNull);
if (bestMatchForRole != null) {
@@ -618,7 +654,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
replaceTemplateBasedConfigurationCandidatesBySuggestedProperties(markTemplatesToMarkConfigurations, allMarkConfigurations, tagsToFilterMarkProperties,
courseTemplate.getAssociatedRoles());
final Map<MarkConfiguration, String> resultingRoleMapping = createRoleMappingWithMarkTemplateMapping(
final Map<MarkConfiguration, IsMarkRole> resultingRoleMapping = createRoleMappingWithMarkTemplateMapping(
courseTemplate, markTemplatesToMarkConfigurations);
final List<WaypointWithMarkConfiguration> resultingWaypoints = createWaypointConfigurationsWithMarkTemplateMapping(
courseTemplate, markTemplatesToMarkConfigurations);
@@ -627,10 +663,10 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
courseTemplate.getName());
}
private Map<MarkConfiguration, String> createRoleMappingWithMarkTemplateMapping(CourseTemplate courseTemplate,
private Map<MarkConfiguration, IsMarkRole> createRoleMappingWithMarkTemplateMapping(CourseTemplate courseTemplate,
final Map<MarkTemplate, MarkConfiguration> markTemplatesToMarkConfigurations) {
final Map<MarkConfiguration, String> resultingRoleMapping = new HashMap<>();
for (Entry<MarkTemplate, String> markTemplateWithRole : courseTemplate.getAssociatedRoles().entrySet()) {
final Map<MarkConfiguration, IsMarkRole> resultingRoleMapping = new HashMap<>();
for (Entry<MarkTemplate, MarkRole> markTemplateWithRole : courseTemplate.getAssociatedRoles().entrySet()) {
resultingRoleMapping.put(markTemplatesToMarkConfigurations.get(markTemplateWithRole.getKey()),
markTemplateWithRole.getValue());
}
@@ -672,10 +708,11 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
final Map<Mark, RegattaMarkConfiguration> markConfigurationsByMark = createMarkConfigurationsForRegatta(regatta, courseTemplateOrNull);
allMarkConfigurations.addAll(markConfigurationsByMark.values());
final Map<MarkConfiguration, String> resultingRoleMapping = new HashMap<>();
final Map<MarkConfiguration, IsMarkRole> resultingRoleMapping = new HashMap<>();
if (course != null) {
for (Entry<Mark, String> entry : course.getAssociatedRoles().entrySet()) {
resultingRoleMapping.put(markConfigurationsByMark.get(entry.getKey()), entry.getValue());
for (Entry<Mark, UUID> entry : course.getAssociatedRoles().entrySet()) {
resultingRoleMapping.put(markConfigurationsByMark.get(entry.getKey()),
resolveMarkRole(entry.getValue(), courseTemplateOrNull));
}
}
@@ -713,10 +750,10 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
}
if (!handledByTemplate) {
if (course != null) {
for (Entry<Mark, String> markWithRole : course.getAssociatedRoles().entrySet()) {
for (Entry<Mark, UUID> markWithRole : course.getAssociatedRoles().entrySet()) {
resultingRoleMapping.put(
markConfigurationsByMark.get(markWithRole.getKey()),
markWithRole.getValue());
resolveMarkRole(markWithRole.getValue(), courseTemplateOrNull));
}
for (Waypoint waypoint : course.getWaypoints()) {
final ControlPoint controlPoint = waypoint.getControlPoint();
@@ -805,16 +842,13 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
while (markTemplateIterator.hasNext()) {
final MarkTemplate markTemplate = markTemplateIterator.next();
final Mark mark = markIterator.next();
final String roleForMarkTempalte = courseTemplate.getAssociatedRoles().get(markTemplate);
final MarkRole roleForMarkTempalte = courseTemplate.getAssociatedRoles().get(markTemplate);
if (roleForMarkTempalte == null) {
validCourseTemplateUsage = false;
break;
}
String roleForMark = course.getAssociatedRoles().get(mark);
if (roleForMark == null) {
roleForMark = mark.getName();
}
if (!Util.equalsWithNull(roleForMarkTempalte, roleForMark)) {
final MarkRole roleForMarkOrNull = resolveMarkRole(course.getAssociatedRoles().get(mark), courseTemplate);
if (!Util.equalsWithNull(roleForMarkTempalte, roleForMarkOrNull)) {
validCourseTemplateUsage = false;
break;
}
@@ -832,7 +866,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
private void replaceTemplateBasedConfigurationCandidatesBySuggestedProperties(Map<MarkTemplate, MarkConfiguration> markTemplatesToMarkConfigurationsToReplace,
Set<MarkConfiguration> markConfigurationsToEdit, Iterable<String> tagsToFilterMarkProperties,
Map<MarkTemplate, String> associatedRoles) {
Map<MarkTemplate, MarkRole> associatedRoles) {
// find candidates for replacement of mark configuration
final Map<MarkTemplate, MarkTemplateBasedMarkConfiguration> replacementCandidates = markTemplatesToMarkConfigurationsToReplace.entrySet()
.stream().filter(e -> e.getValue() instanceof MarkTemplateBasedMarkConfiguration)
@@ -844,7 +878,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
markPropertiesCandidates.removeAll(markConfigurationsToEdit.stream()
.map(this::getAssociatedMarkPropertiesIfAvailable).filter(v -> v != null).collect(Collectors.toSet()));
final LastUsageBasedAssociater<MarkProperties, String> roleBasedAssociater = new LastUsageBasedAssociater<>(
final LastUsageBasedAssociater<MarkProperties, MarkRole> roleBasedAssociater = new LastUsageBasedAssociater<>(
replacementCandidates.keySet().stream().map(associatedRoles::get).filter(v -> v != null)
.collect(Collectors.toSet()));
@@ -857,7 +891,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
for (Iterator<Entry<MarkTemplate, MarkTemplateBasedMarkConfiguration>> iterator = replacementCandidates.entrySet().iterator(); iterator
.hasNext();) {
Entry<MarkTemplate, MarkTemplateBasedMarkConfiguration> entry = iterator.next();
final String roleName = associatedRoles.get(entry.getKey());
final MarkRole roleName = associatedRoles.get(entry.getKey());
if (roleName != null) {
final MarkProperties bestMatchOrNull = roleBasedAssociater.getBestMatchForT2(roleName);
if (bestMatchOrNull != null) {
@@ -955,20 +989,20 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
}
private abstract class CourseSequenceMapper<C, M extends C, W> {
final Map<M, String> explicitAssociatedRoles = new HashMap<>();
final Map<M, String> allAssociatedRoles = new HashMap<>();
final Map<M, IsMarkRole> explicitAssociatedRoles = new HashMap<>();
final Map<M, IsMarkRole> allAssociatedRoles = new HashMap<>();
final List<W> effectiveWaypoints = new ArrayList<>();
private final Iterable<WaypointWithMarkConfiguration> waypoints;
private final Map<MarkConfiguration, String> existingRoleMapping;
private final Map<MarkConfiguration, ? extends IsMarkRole> existingRoleMapping;
public CourseSequenceMapper(Iterable<WaypointWithMarkConfiguration> waypoints,
Map<MarkConfiguration, String> existingRoleMapping) {
Map<MarkConfiguration, ? extends IsMarkRole> existingRoleMapping) {
this.waypoints = waypoints;
this.existingRoleMapping = existingRoleMapping;
}
public void calculateEffectiveWaypoints() {
// all preexisting explicit roles are added to the result
for (Entry<MarkConfiguration, String> entry : existingRoleMapping.entrySet()) {
for (Entry<MarkConfiguration, ? extends IsMarkRole> entry : existingRoleMapping.entrySet()) {
explicitAssociatedRoles.put(mapMarkConfiguration(entry.getKey()), entry.getValue());
}
allAssociatedRoles.putAll(explicitAssociatedRoles);
@@ -1002,7 +1036,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
throw new IllegalStateException("Non declared mark found in waypoint sequence");
}
// If an explicit role mapping isn't given -> default to the mark's name
allAssociatedRoles.computeIfAbsent(mark, m -> getExplicitOrImplicitRoleName(existingRoleMapping, markConfiguration));
allAssociatedRoles.computeIfAbsent(mark, m -> getExplicitOrImplicitMarkRole(existingRoleMapping, markConfiguration));
return mark;
}
@@ -1018,7 +1052,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
private final Map<MarkConfiguration, M> existingMapping;
public CourseSequenceReplacementMapper(Iterable<WaypointWithMarkConfiguration> waypoints,
Map<MarkConfiguration, String> existingRoleMapping, Map<MarkConfiguration, M> existingMapping) {
Map<MarkConfiguration, ? extends IsMarkRole> existingRoleMapping, Map<MarkConfiguration, M> existingMapping) {
super(waypoints, existingRoleMapping);
this.existingMapping = existingMapping;
calculateEffectiveWaypoints();
@@ -1033,7 +1067,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
private class CourseConfigurationToCourseConfigurationMapper extends
CourseSequenceReplacementMapper<ControlPointWithMarkConfiguration, MarkConfiguration, WaypointWithMarkConfiguration> {
public CourseConfigurationToCourseConfigurationMapper(Iterable<WaypointWithMarkConfiguration> waypoints,
Map<MarkConfiguration, String> existingRoleMapping,
Map<MarkConfiguration, ? extends IsMarkRole> existingRoleMapping,
Map<MarkConfiguration, MarkConfiguration> existingMapping) {
super(waypoints, existingRoleMapping, existingMapping);
}
@@ -18,7 +18,7 @@ import com.sap.sse.replication.ReplicableWithObjectInputStream;
public interface ReplicatingSharedSailingData extends SharedSailingData,
ReplicableWithObjectInputStream<ReplicatingSharedSailingData, OperationWithResult<ReplicatingSharedSailingData, ?>> {
Void internalCreateMarkRole(UUID idOfNewMarkRole, String name);
Void internalCreateMarkProperties(UUID idOfNewMarkProperties, CommonMarkProperties properties,
@@ -31,7 +31,7 @@ public interface ReplicatingSharedSailingData extends SharedSailingData,
Void internalCreateCourseTemplate(UUID idOfNewCourseTemplate, String courseTemplateName,
Iterable<MarkTemplate> marks, Iterable<WaypointTemplate> waypoints,
Map<MarkTemplate, String> associatedRoles, RepeatablePart optionalRepeatablePart, Iterable<String> tags,
Map<MarkTemplate, MarkRole> associatedRoles, RepeatablePart optionalRepeatablePart, Iterable<String> tags,
URL optionalImageURL, Integer defaultNumberOfLaps);
Void internalSetTrackingDeviceIdentifierForMarkProperties(UUID markPropertiesUUID, DeviceIdentifier deviceIdentifier);
@@ -44,7 +44,7 @@ public interface ReplicatingSharedSailingData extends SharedSailingData,
Void internalRecordUsage(UUID markTemplateId, UUID markPropertiesId);
Void internalRecordUsage(UUID markPropertiesId, String roleName);
Void internalRecordUsage(UUID markPropertiesId, MarkRole roleName);
Void internalUpdateCourseTemplate(UUID uuid, String name, URL optionalImageURL, ArrayList<String> tags);
@@ -83,10 +83,10 @@ public class SharedSailingDataImpl implements ReplicatingSharedSailingData, Clea
domainObjectFactory.loadAllMarkTemplates().forEach(m -> markTemplatesById.put(m.getId(), m));
domainObjectFactory.loadAllMarkRoles().forEach(m -> markRolesById.put(m.getId(), m));
domainObjectFactory.loadAllMarkProperties(v -> markTemplatesById.get(v))
domainObjectFactory.loadAllMarkProperties(markTemplatesById::get, markRolesById::get)
.forEach(m -> markPropertiesById.put(m.getId(), m));
domainObjectFactory.loadAllCourseTemplates(m -> markTemplatesById.get(m))
domainObjectFactory.loadAllCourseTemplates(markTemplatesById::get, markRolesById::get)
.forEach(c -> courseTemplatesById.put(c.getId(), c));
}
@@ -326,7 +326,7 @@ public class SharedSailingDataImpl implements ReplicatingSharedSailingData, Clea
@Override
public CourseTemplate createCourseTemplate(String courseTemplateName, Iterable<MarkTemplate> marks,
Iterable<WaypointTemplate> waypoints, Map<MarkTemplate, String> associatedRoles,
Iterable<WaypointTemplate> waypoints, Map<MarkTemplate, MarkRole> associatedRoles,
RepeatablePart optionalRepeatablePart, Iterable<String> tags, URL optionalImageURL,
Integer defaultNumberOfLaps) {
final Set<MarkTemplate> marksInSequence = new HashSet<>();
@@ -337,14 +337,14 @@ public class SharedSailingDataImpl implements ReplicatingSharedSailingData, Clea
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<>();
final Map<MarkTemplate, MarkRole> effectiveAssociatedRoles = new HashMap<>();
final Set<MarkRole> alreadyUsedRoles = new HashSet<>();
for (MarkTemplate markTemplate : marksInSequence) {
String roleNameForMarkInSequence = associatedRoles.get(markTemplate);
MarkRole roleNameForMarkInSequence = associatedRoles.get(markTemplate);
if (roleNameForMarkInSequence == null) {
// In case, no role name is explicitly given for a mark being part of the sequence,
// the role defaults to the mark's name
roleNameForMarkInSequence = markTemplate.getName();
roleNameForMarkInSequence = createMarkRole(markTemplate.getName());
}
if (!alreadyUsedRoles.add(roleNameForMarkInSequence)) {
throw new IllegalArgumentException(
@@ -362,7 +362,7 @@ public class SharedSailingDataImpl implements ReplicatingSharedSailingData, Clea
final String courseTemplateNameForReplication = courseTemplateName;
final Iterable<MarkTemplate> marksForReplication = marks;
final Iterable<WaypointTemplate> waypointsForReplication = waypoints;
final Map<MarkTemplate, String> effectiveAssociatedRolesForReplication = effectiveAssociatedRoles;
final Map<MarkTemplate, MarkRole> effectiveAssociatedRolesForReplication = effectiveAssociatedRoles;
final RepeatablePart optionalRepeatablePartForReplication = optionalRepeatablePart;
final Iterable<String> tagsForReplication = tags;
final URL optionalImageURLForReplication = optionalImageURL;
@@ -399,7 +399,7 @@ public class SharedSailingDataImpl implements ReplicatingSharedSailingData, Clea
@Override
public Void internalCreateCourseTemplate(UUID idOfNewCourseTemplate, String courseTemplateName,
Iterable<MarkTemplate> marks, Iterable<WaypointTemplate> waypoints,
Map<MarkTemplate, String> associatedRoles, RepeatablePart optionalRepeatablePart, Iterable<String> tags,
Map<MarkTemplate, MarkRole> associatedRoles, RepeatablePart optionalRepeatablePart, Iterable<String> tags,
URL optionalImageURL, Integer defaultNumberOfLaps) {
final CourseTemplateImpl courseTemplate = new CourseTemplateImpl(idOfNewCourseTemplate, courseTemplateName,
marks, waypoints, associatedRoles, optionalImageURL, optionalRepeatablePart, defaultNumberOfLaps);
@@ -437,7 +437,7 @@ public class SharedSailingDataImpl implements ReplicatingSharedSailingData, Clea
}
@Override
public Void internalRecordUsage(final UUID markPropertiesId, final String roleName) {
public Void internalRecordUsage(final UUID markPropertiesId, final MarkRole roleName) {
final MarkProperties markProperties = markPropertiesById.get(markPropertiesId);
markProperties.getLastUsedRole().put(roleName, new MillisecondsTimePoint(System.currentTimeMillis()));
mongoObjectFactory.storeMarkProperties(deviceIdentifierServiceFinder, markProperties);
@@ -445,7 +445,7 @@ public class SharedSailingDataImpl implements ReplicatingSharedSailingData, Clea
}
@Override
public void recordUsage(final MarkProperties markProperties, final String roleName) {
public void recordUsage(final MarkProperties markProperties, final MarkRole roleName) {
getSecurityService().checkCurrentUserUpdatePermission(markProperties);
final UUID markPropertiesId = markProperties.getId();
@@ -464,7 +464,7 @@ public class SharedSailingDataImpl implements ReplicatingSharedSailingData, Clea
}
@Override
public Map<MarkProperties, TimePoint> getUsedMarkProperties(String roleName) {
public Map<MarkProperties, TimePoint> getUsedMarkProperties(MarkRole roleName) {
final Map<MarkProperties, TimePoint> recordedUsage = new HashMap<>();
for (final MarkProperties mp : markPropertiesById.values()) {
if (mp.getLastUsedRole().containsKey(roleName)) {