Bug 5085: Removed old SharedSailingDataImpl in com.sap.sailing.server

because there is a replacement in com.sap.sailing.shared.server
This commit is contained in:
Steffen Schaefer committed 2019-12-09 09:19:14 +01:00
1 parent 1fb07c69f4
commit 329dc75bdf
4 files changed
+37 -664

No files matched your search

@@ -34,7 +34,6 @@ import com.sap.sailing.domain.common.tracking.impl.GPSFixImpl;
import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl;
import com.sap.sailing.domain.persistence.DomainObjectFactory;
import com.sap.sailing.domain.persistence.MongoObjectFactory;
import com.sap.sailing.domain.persistence.PersistenceFactory;
import com.sap.sailing.domain.persistence.racelog.tracking.FixMongoHandler;
import com.sap.sailing.domain.persistence.racelog.tracking.impl.DoubleVectorFixMongoHandlerImpl;
import com.sap.sailing.domain.persistence.racelog.tracking.impl.GPSFixMongoHandlerImpl;
@@ -112,7 +111,7 @@ public class Activator implements BundleActivator {
private ServiceTracker<SecurityService, SecurityService> securityServiceTracker;
private SharedSailingDataImpl sharedSailingData;
private ServiceTracker<SharedSailingData, SharedSailingData> sharedSailingDataTracker;
public Activator() {
clearPersistentCompetitors = Boolean
@@ -198,6 +197,7 @@ public class Activator implements BundleActivator {
notificationService.stop();
mailQueue.stop();
mailServiceTracker.close();
sharedSailingDataTracker.close();
securityServiceTracker.close();
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
mbs.unregisterMBean(mBeanName);
@@ -240,17 +240,12 @@ public class Activator implements BundleActivator {
// instead.
serviceFinderFactory = new CachedOsgiTypeBasedServiceFinderFactory(context);
sharedSailingData = new SharedSailingDataImpl(PersistenceFactory.INSTANCE
.getDefaultDomainObjectFactory(), PersistenceFactory.INSTANCE
.getDefaultMongoObjectFactory(serviceFinderFactory), serviceFinderFactory, securityServiceTracker);
registrations.add(context.registerService(SharedSailingData.class, sharedSailingData, /* properties */ null));
registrations.add(context.registerService(ClearStateTestSupport.class, sharedSailingData, /* properties */ null));
registrations.add(context.registerService(Replicable.class, sharedSailingData, /* properties */ null));
sharedSailingDataTracker = ServiceTrackerFactory.createAndOpen(context, SharedSailingData.class);
racingEventService = new RacingEventServiceImpl(clearPersistentCompetitors,
serviceFinderFactory, trackedRegattaListener, notificationService,
trackedRaceStatisticsCache, restoreTrackedRaces, securityServiceTracker,
sharedSailingData);
sharedSailingDataTracker);
notificationService.setRacingEventService(racingEventService);
masterDataImportClassLoaderServiceTracker = new ServiceTracker<MasterDataImportClassLoaderService, MasterDataImportClassLoaderService>(
context, MasterDataImportClassLoaderService.class,
@@ -18,6 +18,8 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.osgi.util.tracker.ServiceTracker;
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState;
@@ -97,13 +99,13 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
private static final Logger log = Logger.getLogger(CourseAndMarkConfigurationFactoryImpl.class.getName());
private final SharedSailingData sharedSailingData;
private final ServiceTracker<SharedSailingData, SharedSailingData> sharedSailingDataTracker;
private final SensorFixStore sensorFixStore;
private final Function<DeviceIdentifier, Position> positionResolver;
private final RaceLogResolver raceLogResolver;
public CourseAndMarkConfigurationFactoryImpl(SharedSailingData sharedSailingData, SensorFixStore sensorFixStore, RaceLogResolver raceLogResolver) {
this.sharedSailingData = sharedSailingData;
public CourseAndMarkConfigurationFactoryImpl(ServiceTracker<SharedSailingData, SharedSailingData> sharedSailingDataTracker, SensorFixStore sensorFixStore, RaceLogResolver raceLogResolver) {
this.sharedSailingDataTracker = sharedSailingDataTracker;
this.sensorFixStore = sensorFixStore;
this.raceLogResolver = raceLogResolver;
positionResolver = identifier -> {
@@ -122,6 +124,10 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
return lastPosition;
};
}
private SharedSailingData getSharedSailingData() {
return sharedSailingDataTracker.getService();
}
private CourseTemplate resolveCourseTemplateSafe(CourseBase course) {
CourseTemplate courseTemplateOrNull = null;
@@ -139,7 +145,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
if (course.getOriginatingCourseTemplateIdOrNull() == null) {
return null;
}
return sharedSailingData.getCourseTemplateById(course.getOriginatingCourseTemplateIdOrNull());
return getSharedSailingData().getCourseTemplateById(course.getOriginatingCourseTemplateIdOrNull());
}
private CourseConfigurationWithMarkRoles handleSaveToInventory(CourseConfiguration courseConfiguration) {
@@ -154,9 +160,9 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
}
if (markPropertiesOrNull == null) {
// If no mark properties exist yet, a new one is created
markPropertiesOrNull = sharedSailingData.createMarkProperties(markConfiguration.getEffectiveProperties(), Collections.emptySet());
markPropertiesOrNull = getSharedSailingData().createMarkProperties(markConfiguration.getEffectiveProperties(), Collections.emptySet());
} else {
sharedSailingData.updateMarkProperties(markPropertiesOrNull.getId(), markConfiguration.getEffectiveProperties(), null, null, Collections.emptySet());
getSharedSailingData().updateMarkProperties(markPropertiesOrNull.getId(), markConfiguration.getEffectiveProperties(), null, null, Collections.emptySet());
}
Positioning positioningOrNull = markConfiguration.getOptionalPositioning();
if (positioningOrNull == null && markConfiguration instanceof RegattaMarkConfiguration) {
@@ -168,9 +174,9 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
final DeviceIdentifier deviceIdentifier = positioningOrNull.getDeviceIdentifier();
final Position fixedPosition = positioningOrNull.getPosition();
if (deviceIdentifier != null) {
sharedSailingData.setTrackingDeviceIdentifierForMarkProperties(markPropertiesOrNull, deviceIdentifier);
getSharedSailingData().setTrackingDeviceIdentifierForMarkProperties(markPropertiesOrNull, deviceIdentifier);
} else {
sharedSailingData.setFixedPositionForMarkProperties(markPropertiesOrNull, fixedPosition);
getSharedSailingData().setFixedPositionForMarkProperties(markPropertiesOrNull, fixedPosition);
}
}
final MarkConfiguration effectiveMarkConfiguration;
@@ -214,7 +220,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
if (r instanceof MarkRole) {
mr = (MarkRole) r;
} else {
mr = sharedSailingData.createMarkRole(r.getName());
mr = getSharedSailingData().createMarkRole(r.getName());
}
return mr;
}
@@ -228,7 +234,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
markRole = optionalCourseTemplate.getMarkRoleByIdIfContainedInCourseTemplate(markRoleId);
}
if (markRole == null) {
markRole = sharedSailingData.getMarkRoleById(markRoleId);
markRole = getSharedSailingData().getMarkRoleById(markRoleId);
}
return markRole;
}
@@ -251,7 +257,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
if (markTemplateOrNull != null && markTemplateOrNull.hasEqualAppeareanceWith(markConfiguration.getEffectiveProperties())) {
effectiveMarkTemplate = markTemplateOrNull;
} else {
effectiveMarkTemplate = sharedSailingData
effectiveMarkTemplate = getSharedSailingData()
.createMarkTemplate(markConfiguration.getEffectiveProperties());
}
if (markConfiguration instanceof RegattaMarkConfiguration) {
@@ -318,7 +324,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
}
};
final CourseTemplate newCourseTemplate = sharedSailingData.createCourseTemplate(courseConfigurationAfterInventory.getName(), new HashSet<>(markTemplatesByMarkConfigurations.values()),
final CourseTemplate newCourseTemplate = getSharedSailingData().createCourseTemplate(courseConfigurationAfterInventory.getName(), new HashSet<>(markTemplatesByMarkConfigurations.values()),
waypointTemplateMapper.effectiveWaypoints, ensureMarkRoles(waypointTemplateMapper.allAssociatedRoles), courseConfigurationAfterInventory.getRepeatablePart(),
tags, courseConfigurationAfterInventory.getOptionalImageURL(),
courseConfigurationAfterInventory.getNumberOfLaps());
@@ -336,7 +342,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
if (markProperties != null) {
final IsMarkRole role = getExplicitOrImplicitMarkRole(associatedRoles, markConfiguration);
try {
sharedSailingData.recordUsage(markProperties, ensureMarkRole(role));
getSharedSailingData().recordUsage(markProperties, ensureMarkRole(role));
} catch (Exception e) {
log.log(Level.WARNING,
"Could not record usage for mark properties " + markProperties + " and role " + role,
@@ -345,7 +351,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
final MarkTemplate markTemplateOrNull = markConfiguration.getOptionalMarkTemplate();
if (markTemplateOrNull != null) {
try {
sharedSailingData.recordUsage(markTemplateOrNull, markProperties);
getSharedSailingData().recordUsage(markTemplateOrNull, markProperties);
} catch (Exception e) {
log.log(Level.WARNING, "Could not record usage for mark properties " + markProperties
+ " and mark template " + markTemplateOrNull, e);
@@ -877,7 +883,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
.collect(Collectors.toMap(s -> s.getKey(), s -> (MarkTemplateBasedMarkConfiguration)s.getValue()));
final Set<MarkProperties> markPropertiesCandidates = new HashSet<>();
Util.addAll(sharedSailingData.getAllMarkProperties(tagsToFilterMarkProperties), markPropertiesCandidates);
Util.addAll(getSharedSailingData().getAllMarkProperties(tagsToFilterMarkProperties), markPropertiesCandidates);
// Already included mark properties may not get associated again
markPropertiesCandidates.removeAll(markConfigurationsToEdit.stream()
.map(this::getAssociatedMarkPropertiesIfAvailable).filter(v -> v != null).collect(Collectors.toSet()));
@@ -964,7 +970,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
}
if (resolvedMarkTemplate == null) {
try {
resolvedMarkTemplate = sharedSailingData.getMarkTemplateById(markTemplateID);
resolvedMarkTemplate = getSharedSailingData().getMarkTemplateById(markTemplateID);
} catch(Exception e) {
// This call may fail due to missing permissions but should not prevent the user from creating a course for a regatta.
// This is just the case, a regatta Mark is based on a MarkTemplate that is not part of the associated CourseTemplate.
@@ -980,13 +986,13 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
final MarkTemplate markTemplateOrNull = markTemplateIdOrNull == null ? null : resolveMarkTemplateByID(courseTemplate, markTemplateIdOrNull);
final UUID markPropertiesIdOrNull = mark.getOriginatingMarkPropertiesIdOrNull();
final MarkProperties markPropertiesOrNull = markPropertiesIdOrNull == null ? null
: sharedSailingData.getMarkPropertiesById(markPropertiesIdOrNull);
: getSharedSailingData().getMarkPropertiesById(markPropertiesIdOrNull);
final RegattaMarkConfiguration regattaMarkConfiguration = new RegattaMarkConfigurationImpl(mark,
/* optionalPositioning */ null, getPositioningIfAvailable(regatta, mark), markTemplateOrNull,
markPropertiesOrNull, /* storeToInventory */ false);
return regattaMarkConfiguration;
}
private abstract class CourseSequenceMapper<C, M extends C, W> {
final Map<M, IsMarkRole> explicitAssociatedRoles = new HashMap<>();
final Map<M, IsMarkRole> allAssociatedRoles = new HashMap<>();
@@ -598,7 +598,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
public RacingEventServiceImpl(boolean clearPersistentCompetitorAndBoatStore, final TypeBasedServiceFinderFactory serviceFinderFactory, boolean restoreTrackedRaces) {
this(clearPersistentCompetitorAndBoatStore, serviceFinderFactory, null, /* sailingNotificationService */ null,
/* trackedRaceStatisticsCache */ null, restoreTrackedRaces, null, /* sharedSailingData */ null);
/* trackedRaceStatisticsCache */ null, restoreTrackedRaces, null, /* sharedSailingDataTracker */ null);
}
/**
@@ -624,7 +624,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
final TypeBasedServiceFinderFactory serviceFinderFactory, TrackedRegattaListenerManager trackedRegattaListener,
SailingNotificationService sailingNotificationService,
TrackedRaceStatisticsCache trackedRaceStatisticsCache, boolean restoreTrackedRaces,
ServiceTracker<SecurityService, SecurityService> securityServiceTracker, SharedSailingData sharedSailingData) {
ServiceTracker<SecurityService, SecurityService> securityServiceTracker,
ServiceTracker<SharedSailingData, SharedSailingData> sharedSailingDataTracker) {
this((final RaceLogAndTrackedRaceResolver raceLogResolver) -> {
return new ConstructorParameters() {
private final MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE
@@ -655,7 +656,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
};
}, MediaDBFactory.INSTANCE.getDefaultMediaDB(), null, null, serviceFinderFactory, trackedRegattaListener,
sailingNotificationService, trackedRaceStatisticsCache, restoreTrackedRaces,
securityServiceTracker, sharedSailingData);
securityServiceTracker, sharedSailingDataTracker);
}
private RacingEventServiceImpl(final boolean clearPersistentCompetitorStore, WindStore windStore,
@@ -689,7 +690,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
}
};
}, MediaDBFactory.INSTANCE.getDefaultMediaDB(), windStore, sensorFixStore, serviceFinderFactory, null,
sailingNotificationService, /* trackedRaceStatisticsCache */ null, restoreTrackedRaces, null, /* sharedSailingData */ null);
sailingNotificationService, /* trackedRaceStatisticsCache */ null, restoreTrackedRaces, null,
/* sharedSailingDataTracker */ null);
}
public RacingEventServiceImpl(final DomainObjectFactory domainObjectFactory, MongoObjectFactory mongoObjectFactory,
@@ -717,7 +719,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
}
};
}, mediaDB, windStore, sensorFixStore, null, null, /* sailingNotificationService */ null,
/* trackedRaceStatisticsCache */ null, restoreTrackedRaces, null, /* sharedSailingData */ null);
/* trackedRaceStatisticsCache */ null, restoreTrackedRaces, null, /* sharedSailingDataTracker */ null);
}
/**
@@ -753,7 +755,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
SailingNotificationService sailingNotificationService,
TrackedRaceStatisticsCache trackedRaceStatisticsCache, boolean restoreTrackedRaces,
ServiceTracker<SecurityService, SecurityService> securityServiceTracker,
SharedSailingData sharedSailingData) {
ServiceTracker<SharedSailingData, SharedSailingData> sharedSailingDataTracker) {
logger.info("Created " + this);
this.securityServiceTracker = securityServiceTracker;
this.numberOfTrackedRacesRestored = new AtomicInteger();
@@ -840,7 +842,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
logger.log(Level.SEVERE, "Exception trying to obtain MongoDB sensor fix store", e);
throw new RuntimeException(e);
}
this.courseAndMarkConfigurationFactory = new CourseAndMarkConfigurationFactoryImpl(sharedSailingData,
this.courseAndMarkConfigurationFactory = new CourseAndMarkConfigurationFactoryImpl(sharedSailingDataTracker,
this.sensorFixStore, this);
this.raceManagerDeviceConfigurationsById = new HashMap<>();
this.raceManagerDeviceConfigurationsByName = new HashMap<>();
@@ -1,630 +0,0 @@
package com.sap.sailing.server.impl;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import org.osgi.util.tracker.ServiceTracker;
import com.sap.sailing.domain.common.DeviceIdentifier;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.common.security.SecuredDomainType;
import com.sap.sailing.domain.coursetemplate.CommonMarkProperties;
import com.sap.sailing.domain.coursetemplate.CourseTemplate;
import com.sap.sailing.domain.coursetemplate.MarkProperties;
import com.sap.sailing.domain.coursetemplate.MarkPropertiesBuilder;
import com.sap.sailing.domain.coursetemplate.MarkRole;
import com.sap.sailing.domain.coursetemplate.MarkTemplate;
import com.sap.sailing.domain.coursetemplate.MarkTemplate.MarkTemplateResolver;
import com.sap.sailing.domain.coursetemplate.RepeatablePart;
import com.sap.sailing.domain.coursetemplate.WaypointTemplate;
import com.sap.sailing.domain.coursetemplate.impl.CourseTemplateImpl;
import com.sap.sailing.domain.coursetemplate.impl.MarkPropertiesImpl;
import com.sap.sailing.domain.coursetemplate.impl.MarkRoleImpl;
import com.sap.sailing.domain.coursetemplate.impl.MarkTemplateImpl;
import com.sap.sailing.domain.persistence.DomainObjectFactory;
import com.sap.sailing.domain.persistence.MongoObjectFactory;
import com.sap.sailing.domain.persistence.racelog.tracking.DeviceIdentifierMongoHandler;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.TypeBasedServiceFinder;
import com.sap.sse.common.TypeBasedServiceFinderFactory;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.replication.OperationExecutionListener;
import com.sap.sse.replication.OperationWithResult;
import com.sap.sse.replication.OperationWithResultWithIdWrapper;
import com.sap.sse.replication.OperationsToMasterSender;
import com.sap.sse.replication.OperationsToMasterSendingQueue;
import com.sap.sse.replication.ReplicationMasterDescriptor;
import com.sap.sse.replication.ReplicationService;
import com.sap.sse.security.SecurityService;
import com.sap.sse.util.ClearStateTestSupport;
import com.sap.sse.util.ObjectInputStreamResolvingAgainstCache;
public class SharedSailingDataImpl implements ReplicatingSharedSailingData, ClearStateTestSupport {
private final DomainObjectFactory domainObjectFactory;
private final MongoObjectFactory mongoObjectFactory;
private final Map<UUID, MarkProperties> markPropertiesById = new ConcurrentHashMap<>();
private final Map<UUID, MarkTemplate> markTemplatesById = new ConcurrentHashMap<>();
private final Map<UUID, CourseTemplate> courseTemplatesById = new ConcurrentHashMap<>();
private final Map<UUID, MarkRole> markRolesById = new ConcurrentHashMap<>();
private final TypeBasedServiceFinder<DeviceIdentifierMongoHandler> deviceIdentifierServiceFinder;
private final ServiceTracker<SecurityService, SecurityService> securityServiceTracker;
public SharedSailingDataImpl(final DomainObjectFactory domainObjectFactory,
final MongoObjectFactory mongoObjectFactory, TypeBasedServiceFinderFactory serviceFinderFactory,
ServiceTracker<SecurityService, SecurityService> securityServiceTracker) {
this.domainObjectFactory = domainObjectFactory;
this.mongoObjectFactory = mongoObjectFactory;
this.deviceIdentifierServiceFinder = serviceFinderFactory
.createServiceFinder(DeviceIdentifierMongoHandler.class);
this.securityServiceTracker = securityServiceTracker;
load();
}
private void load() {
// load mark templates and mark roles before mark properties and course templates
domainObjectFactory.loadAllMarkTemplates().forEach(m -> markTemplatesById.put(m.getId(), m));
domainObjectFactory.loadAllMarkRoles().forEach(m -> markRolesById.put(m.getId(), m));
domainObjectFactory.loadAllMarkProperties(markTemplatesById::get, markRolesById::get)
.forEach(m -> markPropertiesById.put(m.getId(), m));
domainObjectFactory.loadAllCourseTemplates(markTemplatesById::get, markRolesById::get)
.forEach(c -> courseTemplatesById.put(c.getId(), c));
}
@Override
public void clearState() throws Exception {
markPropertiesById.keySet().forEach(mongoObjectFactory::removeMarkProperties);
markTemplatesById.keySet().forEach(mongoObjectFactory::removeMarkTemplate);
courseTemplatesById.keySet().forEach(mongoObjectFactory::removeCourseTemplate);
markRolesById.keySet().forEach(mongoObjectFactory::removeMarkRole);
removeAll();
}
private void removeAll() {
markPropertiesById.clear();
markTemplatesById.clear();
courseTemplatesById.clear();
markRolesById.clear();
}
public SecurityService getSecurityService() {
return securityServiceTracker.getService();
}
@Override
public Iterable<MarkProperties> getAllMarkProperties(Iterable<String> tagsToFilterFor) {
return markPropertiesById.values().stream().filter(m -> containsAny(m.getTags(), tagsToFilterFor))
.filter(getSecurityService()::hasCurrentUserReadPermission).collect(Collectors.toList());
}
private <T> boolean containsAny(Iterable<T> iterable, Iterable<T> search) {
if (Util.isEmpty(search)) {
return true;
}
for (T t : search) {
if (Util.contains(iterable, t)) {
return true;
}
}
return false;
}
@Override
public Iterable<MarkTemplate> getAllMarkTemplates() {
return markTemplatesById.values().stream().filter(getSecurityService()::hasCurrentUserReadPermission)
.collect(Collectors.toList());
}
@Override
public Iterable<CourseTemplate> getAllCourseTemplates(Iterable<String> tagsToFilterFor) {
return courseTemplatesById.values().stream().filter(c -> containsAny(c.getTags(), tagsToFilterFor))
.filter(getSecurityService()::hasCurrentUserReadPermission).collect(Collectors.toList());
}
@Override
public Iterable<CourseTemplate> getAllCourseTemplates() {
return courseTemplatesById.values().stream().filter(getSecurityService()::hasCurrentUserReadPermission)
.collect(Collectors.toList());
}
@Override
public Iterable<MarkProperties> getAllMarkProperties() {
return markPropertiesById.values().stream().filter(getSecurityService()::hasCurrentUserReadPermission)
.collect(Collectors.toList());
}
@Override
public Iterable<MarkRole> getAllMarkRoles() {
return markRolesById.values().stream().filter(getSecurityService()::hasCurrentUserReadPermission)
.collect(Collectors.toList());
}
@Override
public MarkRole createMarkRole(final String name) {
final UUID idOfNewMarkRole = UUID.randomUUID();
getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
SecuredDomainType.MARK_ROLE,
MarkRole.getTypeRelativeObjectIdentifier(idOfNewMarkRole),
idOfNewMarkRole + "/" + name, () -> {
final UUID idOfNewMarkRoleForReplication = idOfNewMarkRole;
final String nameForReplication = name;
apply(s -> s.internalCreateMarkRole(idOfNewMarkRoleForReplication, nameForReplication));
});
return getMarkRoleById(idOfNewMarkRole);
}
@Override
public Void internalCreateMarkRole(UUID idOfNewMarkRole, String name) {
final MarkRole markRole = new MarkRoleImpl(idOfNewMarkRole, name);
mongoObjectFactory.storeMarkRole(markRole);
markRolesById.put(markRole.getId(), markRole);
return null;
}
@Override
public MarkRole getMarkRoleById(UUID id) {
if (id == null) {
return null;
}
final MarkRole markRole = markRolesById.get(id);
if (markRole != null) {
getSecurityService().checkCurrentUserReadPermission(markRole);
}
return markRole;
}
@Override
public MarkProperties createMarkProperties(CommonMarkProperties properties, Iterable<String> tags) {
final UUID idOfNewMarkProperties = UUID.randomUUID();
getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
SecuredDomainType.MARK_PROPERTIES,
MarkProperties.getTypeRelativeObjectIdentifier(idOfNewMarkProperties),
idOfNewMarkProperties + "/" + properties.getName(), () -> {
final UUID idOfNewMarkPropertiesForReplication = idOfNewMarkProperties;
final CommonMarkProperties propertiesForReplication = properties;
final Iterable<String> tagsForReplication = tags;
apply(s -> s.internalCreateMarkProperties(idOfNewMarkPropertiesForReplication, propertiesForReplication, tagsForReplication));
});
return getMarkPropertiesById(idOfNewMarkProperties);
}
@Override
public MarkProperties updateMarkProperties(UUID uuid, CommonMarkProperties properties, Position position,
DeviceIdentifier deviceIdentifier, Iterable<String> tags) {
final MarkProperties markProperties = markPropertiesById.get(uuid);
if (markProperties == null) {
throw new NullPointerException(String.format("Could not find mark properties with id %s", uuid.toString()));
}
getSecurityService().checkCurrentUserUpdatePermission(markProperties);
apply(s -> internalUpdateMarkProperties(uuid, properties, position, deviceIdentifier, tags));
return getMarkPropertiesById(uuid);
}
@Override
public Void internalUpdateMarkProperties(UUID idOfMarkProperties, CommonMarkProperties properties,
Position position, DeviceIdentifier deviceIdentifier, Iterable<String> tags) {
final MarkPropertiesImpl markProperties = (MarkPropertiesImpl) markPropertiesById.get(idOfMarkProperties);
markProperties.setColor(properties.getColor());
markProperties.setFixedPosition(position);
markProperties.setPattern(properties.getPattern());
markProperties.setShape(properties.getShape());
markProperties.setShortName(properties.getShortName());
markProperties.setTrackingDeviceIdentifier(deviceIdentifier);
markProperties.setType(properties.getType());
markProperties.setTags(tags);
mongoObjectFactory.storeMarkProperties(deviceIdentifierServiceFinder, markProperties);
markPropertiesById.put(idOfMarkProperties, markProperties);
return null;
}
@Override
public Void internalCreateMarkProperties(UUID idOfNewMarkProperties, CommonMarkProperties properties,
Iterable<String> tags) {
final MarkProperties markProperties = new MarkPropertiesBuilder(idOfNewMarkProperties, properties.getName(),
properties.getShortName(), properties.getColor(), properties.getShape(), properties.getPattern(),
properties.getType()).withTags(tags).build();
mongoObjectFactory.storeMarkProperties(deviceIdentifierServiceFinder, markProperties);
markPropertiesById.put(markProperties.getId(), markProperties);
return null;
}
@Override
public void setFixedPositionForMarkProperties(final MarkProperties markProperties, final Position position) {
final UUID markPropertiesUUID = markProperties.getId();
apply(s -> s.internalSetFixedPositionForMarkProperties(markPropertiesUUID, position));
}
@Override
public Void internalSetFixedPositionForMarkProperties(UUID markPropertiesId, Position position) {
final MarkProperties markProperties = markPropertiesById.get(markPropertiesId);
markProperties.setTrackingDeviceIdentifier(null);
markProperties.setFixedPosition(position);
mongoObjectFactory.storeMarkProperties(deviceIdentifierServiceFinder, markProperties);
return null;
}
@Override
public MarkProperties getMarkPropertiesById(UUID id) {
if (id == null) {
return null;
}
final MarkProperties markProperties = markPropertiesById.get(id);
if (markProperties != null) {
getSecurityService().checkCurrentUserReadPermission(markProperties);
}
return markProperties;
}
@Override
public void setTrackingDeviceIdentifierForMarkProperties(final MarkProperties markProperties,
final DeviceIdentifier deviceIdentifier) {
final UUID markPropertiesUUID = markProperties.getId();
apply(s -> s.internalSetTrackingDeviceIdentifierForMarkProperties(markPropertiesUUID, deviceIdentifier));
}
@Override
public Void internalSetTrackingDeviceIdentifierForMarkProperties(UUID markPropertiesId,
DeviceIdentifier deviceIdentifier) {
final MarkProperties markProperties = markPropertiesById.get(markPropertiesId);
markProperties.setFixedPosition(null);
markProperties.setTrackingDeviceIdentifier(deviceIdentifier);
mongoObjectFactory.storeMarkProperties(deviceIdentifierServiceFinder, markProperties);
return null;
}
@Override
public MarkTemplate createMarkTemplate(CommonMarkProperties properties) {
final UUID idOfNewMarkTemplate = UUID.randomUUID();
getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
SecuredDomainType.MARK_TEMPLATE, MarkTemplate.getTypeRelativeObjectIdentifier(idOfNewMarkTemplate),
idOfNewMarkTemplate + "/" + properties.getName(), () -> {
final UUID idOfNewMarkTemplateForReplication = idOfNewMarkTemplate;
final CommonMarkProperties propertiesForReplication = properties;
apply(s -> s.internalCreateMarkTemplate(idOfNewMarkTemplateForReplication, propertiesForReplication));
});
return getMarkTemplateById(idOfNewMarkTemplate);
}
@Override
public Void internalCreateMarkTemplate(UUID idOfNewMarkTemplate, CommonMarkProperties properties) {
final MarkTemplate markTemplate = new MarkTemplateImpl(idOfNewMarkTemplate, properties);
mongoObjectFactory.storeMarkTemplate(markTemplate);
markTemplatesById.put(markTemplate.getId(), markTemplate);
return null;
}
@Override
public MarkTemplate getMarkTemplateById(UUID id) {
final MarkTemplate markTemplate = markTemplatesById.get(id);
if (markTemplate != null) {
getSecurityService().checkCurrentUserReadPermission(markTemplate);
}
return markTemplate;
}
@Override
public CourseTemplate createCourseTemplate(String courseTemplateName, Iterable<MarkTemplate> marks,
Iterable<WaypointTemplate> waypoints, Map<MarkTemplate, MarkRole> associatedRoles,
RepeatablePart optionalRepeatablePart, Iterable<String> tags, URL optionalImageURL,
Integer defaultNumberOfLaps) {
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, MarkRole> effectiveAssociatedRoles = new HashMap<>();
final Set<MarkRole> alreadyUsedRoles = new HashSet<>();
for (MarkTemplate markTemplate : marksInSequence) {
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 = createMarkRole(markTemplate.getName());
}
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();
getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
SecuredDomainType.COURSE_TEMPLATE,
CourseTemplate.getTypeRelativeObjectIdentifier(idOfNewCourseTemplate),
idOfNewCourseTemplate + "/" + courseTemplateName, () -> {
final UUID idOfNewCourseTemplateForReplication = idOfNewCourseTemplate;
final String courseTemplateNameForReplication = courseTemplateName;
final Iterable<MarkTemplate> marksForReplication = marks;
final Iterable<WaypointTemplate> waypointsForReplication = waypoints;
final Map<MarkTemplate, MarkRole> effectiveAssociatedRolesForReplication = effectiveAssociatedRoles;
final RepeatablePart optionalRepeatablePartForReplication = optionalRepeatablePart;
final Iterable<String> tagsForReplication = tags;
final URL optionalImageURLForReplication = optionalImageURL;
final Integer defaultNumberOfLapsForReplication = defaultNumberOfLaps;
apply(s -> s.internalCreateCourseTemplate(idOfNewCourseTemplateForReplication, courseTemplateNameForReplication, marksForReplication,
waypointsForReplication, effectiveAssociatedRolesForReplication, optionalRepeatablePartForReplication, tagsForReplication, optionalImageURLForReplication,
defaultNumberOfLapsForReplication));
});
return getCourseTemplateById(idOfNewCourseTemplate);
}
@Override
public CourseTemplate updateCourseTemplate(UUID uuid, String name, URL optionalImageURL, ArrayList<String> tags) {
getSecurityService().checkCurrentUserUpdatePermission(courseTemplatesById.get(uuid));
apply(s -> internalUpdateCourseTemplate(uuid, name, optionalImageURL, tags));
return getCourseTemplateById(uuid);
}
@Override
public Void internalUpdateCourseTemplate(UUID uuid, String name, URL optionalImageURL,
ArrayList<String> tags) {
CourseTemplate existingCourseTemplate = courseTemplatesById.get(uuid);
CourseTemplateImpl courseTemplate = new CourseTemplateImpl(uuid, name,
existingCourseTemplate.getMarkTemplates(), existingCourseTemplate.getWaypointTemplates(),
existingCourseTemplate.getAssociatedRoles(), optionalImageURL,
existingCourseTemplate.getRepeatablePart(), existingCourseTemplate.getDefaultNumberOfLaps());
courseTemplate.setTags(tags);
mongoObjectFactory.storeCourseTemplate(courseTemplate);
courseTemplatesById.put(courseTemplate.getId(), courseTemplate);
return null;
}
@Override
public Void internalCreateCourseTemplate(UUID idOfNewCourseTemplate, String courseTemplateName,
Iterable<MarkTemplate> marks, Iterable<WaypointTemplate> waypoints,
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);
courseTemplate.setTags(tags);
mongoObjectFactory.storeCourseTemplate(courseTemplate);
courseTemplatesById.put(courseTemplate.getId(), courseTemplate);
return null;
}
@Override
public CourseTemplate getCourseTemplateById(UUID id) {
final CourseTemplate courseTemplate = courseTemplatesById.get(id);
if (courseTemplate != null) {
getSecurityService().checkCurrentUserReadPermission(courseTemplate);
}
return courseTemplate;
}
@Override
public Void internalRecordUsage(UUID markTemplateId, UUID markPropertiesId) {
final MarkProperties markProperties = markPropertiesById.get(markPropertiesId);
final MarkTemplate markTemplate = markTemplatesById.get(markTemplateId);
markProperties.getLastUsedTemplate().put(markTemplate, new MillisecondsTimePoint(System.currentTimeMillis()));
mongoObjectFactory.storeMarkProperties(deviceIdentifierServiceFinder, markProperties);
return null;
}
@Override
public void recordUsage(MarkTemplate markTemplate, MarkProperties markProperties) {
getSecurityService().checkCurrentUserUpdatePermission(markProperties);
final UUID markPropertiesId = markProperties.getId();
final UUID markTemplateId = markTemplate.getId();
apply(s -> s.internalRecordUsage(markTemplateId, markPropertiesId));
}
@Override
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);
return null;
}
@Override
public void recordUsage(final MarkProperties markProperties, final MarkRole roleName) {
getSecurityService().checkCurrentUserUpdatePermission(markProperties);
final UUID markPropertiesId = markProperties.getId();
apply(s -> s.internalRecordUsage(markPropertiesId, roleName));
}
@Override
public Map<MarkProperties, TimePoint> getUsedMarkProperties(MarkTemplate markTemplate) {
final Map<MarkProperties, TimePoint> recordedUsage = new HashMap<>();
for (final MarkProperties mp : markPropertiesById.values()) {
if (mp.getLastUsedTemplate().containsKey(markTemplate)) {
recordedUsage.put(mp, mp.getLastUsedTemplate().get(markTemplate));
}
}
return recordedUsage;
}
@Override
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)) {
recordedUsage.put(mp, mp.getLastUsedRole().get(roleName));
}
}
return recordedUsage;
}
@Override
public void deleteMarkProperties(MarkProperties markProperties) {
final UUID id = markProperties.getId();
getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(markProperties,
() -> apply(s -> s.internalDeleteMarkProperties(id)));
}
@Override
public Void internalDeleteMarkProperties(UUID markPropertiesUUID) {
if (this.markPropertiesById.remove(markPropertiesUUID) != null) {
mongoObjectFactory.removeMarkProperties(markPropertiesUUID);
} else {
throw new NullPointerException(
String.format("Did not find a mark properties with ID %s", markPropertiesUUID));
}
return null;
}
@Override
public void deleteCourseTemplate(CourseTemplate courseTemplate) {
final UUID id = courseTemplate.getId();
getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(courseTemplate,
() -> apply(s -> s.internalDeleteCourseTemplate(id)));
}
@Override
public Void internalDeleteCourseTemplate(UUID courseTemplateUUID) {
if (this.courseTemplatesById.remove(courseTemplateUUID) != null) {
mongoObjectFactory.removeCourseTemplate(courseTemplateUUID);
} else {
throw new NullPointerException(
String.format("Did not find a course template with ID %s", courseTemplateUUID));
}
return null;
}
// Replication related methods and fields
private final ConcurrentHashMap<OperationExecutionListener<ReplicatingSharedSailingData>, OperationExecutionListener<ReplicatingSharedSailingData>> operationExecutionListeners = new ConcurrentHashMap<>();
private ThreadLocal<Boolean> currentlyFillingFromInitialLoad = ThreadLocal.withInitial(() -> false);
private ThreadLocal<Boolean> currentlyApplyingOperationReceivedFromMaster = ThreadLocal.withInitial(() -> false);
private final Set<OperationWithResultWithIdWrapper<ReplicatingSharedSailingData, ?>> operationsSentToMasterForReplication = new HashSet<>();
private ReplicationMasterDescriptor master;
/**
* This field is expected to be set by the {@link ReplicationService} once it has "adopted" this replicable. The
* {@link ReplicationService} "injects" this service so it can be used here as a delegate for the
* {@link OperationsToMasterSendingQueue#scheduleForSending(OperationWithResult, OperationsToMasterSender)} method.
*/
private OperationsToMasterSendingQueue unsentOperationsToMasterSender;
@Override
public Serializable getId() {
return getClass().getName();
}
@Override
public ReplicationMasterDescriptor getMasterDescriptor() {
return master;
}
@Override
public void startedReplicatingFrom(ReplicationMasterDescriptor master) {
this.master = master;
}
@Override
public void stoppedReplicatingFrom(ReplicationMasterDescriptor master) {
this.master = null;
}
@Override
public Iterable<OperationExecutionListener<ReplicatingSharedSailingData>> getOperationExecutionListeners() {
return operationExecutionListeners.keySet();
}
@Override
public void addOperationExecutionListener(OperationExecutionListener<ReplicatingSharedSailingData> listener) {
this.operationExecutionListeners.put(listener, listener);
}
@Override
public void removeOperationExecutionListener(OperationExecutionListener<ReplicatingSharedSailingData> listener) {
this.operationExecutionListeners.remove(listener);
}
@Override
public boolean isCurrentlyFillingFromInitialLoad() {
return currentlyFillingFromInitialLoad.get();
}
@Override
public void setCurrentlyFillingFromInitialLoad(boolean currentlyFillingFromInitialLoad) {
this.currentlyFillingFromInitialLoad.set(currentlyFillingFromInitialLoad);
}
@Override
public boolean isCurrentlyApplyingOperationReceivedFromMaster() {
return currentlyApplyingOperationReceivedFromMaster.get();
}
@Override
public void setCurrentlyApplyingOperationReceivedFromMaster(boolean currentlyApplyingOperationReceivedFromMaster) {
this.currentlyApplyingOperationReceivedFromMaster.set(currentlyApplyingOperationReceivedFromMaster);
}
@Override
public void addOperationSentToMasterForReplication(
OperationWithResultWithIdWrapper<ReplicatingSharedSailingData, ?> operationWithResultWithIdWrapper) {
this.operationsSentToMasterForReplication.add(operationWithResultWithIdWrapper);
}
@Override
public boolean hasSentOperationToMaster(OperationWithResult<ReplicatingSharedSailingData, ?> operation) {
return operationsSentToMasterForReplication.remove(operation);
}
@Override
public ObjectInputStream createObjectInputStreamResolvingAgainstCache(InputStream is) throws IOException {
return new ObjectInputStreamResolvingAgainstCache<MarkTemplateResolver>(is,
mt -> markTemplatesById.computeIfAbsent(mt.getId(), id -> mt), null) {
};
}
@SuppressWarnings("unchecked")
@Override
public synchronized void initiallyFillFromInternal(ObjectInputStream is)
throws IOException, ClassNotFoundException, InterruptedException {
markTemplatesById.putAll((Map<UUID, MarkTemplate>) is.readObject());
markPropertiesById.putAll((Map<UUID, MarkProperties>) is.readObject());
courseTemplatesById.putAll((Map<UUID, CourseTemplate>) is.readObject());
}
@Override
public void serializeForInitialReplicationInternal(ObjectOutputStream objectOutputStream) throws IOException {
objectOutputStream.writeObject(markTemplatesById);
objectOutputStream.writeObject(markPropertiesById);
objectOutputStream.writeObject(courseTemplatesById);
}
@Override
public synchronized void clearReplicaState() throws MalformedURLException, IOException, InterruptedException {
removeAll();
}
@Override
public void setUnsentOperationToMasterSender(OperationsToMasterSendingQueue service) {
this.unsentOperationsToMasterSender = service;
}
@Override
public <S, O extends OperationWithResult<S, ?>, T> void scheduleForSending(
OperationWithResult<S, T> operationWithResult, OperationsToMasterSender<S, O> sender) {
if (unsentOperationsToMasterSender != null) {
unsentOperationsToMasterSender.scheduleForSending(operationWithResult, sender);
}
}
}