mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-14 06:18:12 +00:00
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:
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,
|
||||
|
||||
+24
-18
@@ -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<>();
|
||||
|
||||
+9
-7
@@ -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<>();
|
||||
|
||||
-630
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user