implemented de-serialization through DomainFactory for Buoy, Competitor, Nationality, Waypoint, ControlPoint

This commit is contained in:
Axel Uhl committed 2012-04-23 12:17:04 +02:00
1 parent 652eaa5efa
commit 987fbfb30e
24 files changed
+273 -54

No files matched your search

@@ -4,7 +4,7 @@ import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.common.Named;
import com.sap.sailing.domain.tracking.TrackedRace;
public interface BoatClass extends Named {
public interface BoatClass extends Named, IsManagedByDomainFactory {
/**
* The distance returned by this method should be appropriate for use in
* {@link TrackedRace#approximate(Competitor, Distance, TimePoint, TimePoint)} so that penalty circles and other
@@ -1,4 +1,11 @@
package com.sap.sailing.domain.base;
public interface Buoy extends ControlPoint {
/**
* A buoy's name is used as its ID which is only identifying the buoy uniquely within a single race or course
* definition.
*
* @author Axel Uhl (D043530)
*
*/
public interface Buoy extends WithID, ControlPoint, IsManagedByDomainFactory {
}
@@ -2,7 +2,7 @@ package com.sap.sailing.domain.base;
import com.sap.sailing.domain.common.Named;
public interface Competitor extends Named, WithID {
public interface Competitor extends Named, WithID, IsManagedByDomainFactory {
Team getTeam();
Boat getBoat();
@@ -15,13 +15,24 @@ public interface DomainFactory {
* Looks up or, if not found, creates a {@link Nationality} object and re-uses <code>threeLetterIOCCode</code> also as the
* nationality's name.
*/
Nationality getOrCreateNationality(String nationalityName);
Nationality getOrCreateNationality(String threeLetterIOCCode);
Buoy getOrCreateBuoy(String id);
Gate createGate(Buoy left, Buoy right, String name);
/**
* The waypoint created is weakly cached so that when requested again by
* {@link #getExistingWaypointById(Serializable)} it is found.
*/
Waypoint createWaypoint(ControlPoint controlPoint);
Waypoint getExistingWaypointById(Serializable id);
/**
* Caches an existing waypoint. This is useful, e.g., after de-serialization of a waypoint that has a yet unknown ID.
*/
void cacheWaypoint(Waypoint waypoint);
MarkPassing createMarkPassing(TimePoint timePoint, Waypoint waypoint, Competitor competitor);
@@ -31,10 +42,13 @@ public interface DomainFactory {
Competitor createCompetitor(Serializable id, String name, Team team, Boat boat);
Competitor getOrCreateCompetitor(Serializable competitorId, String name, Team team, Boat boat);
/**
* When de-serializing objects of types whose instances that are managed and cached by this domain factory,
* de-serialized instances need to be replaced by / resolved to the counterparts already known by this factory.
* The stream returned by this method can be used
*/
ObjectInputStreamResolvingAgainstDomainFactory createObjectInputStreamResolvingAgainstThisFactory(InputStream inputStream) throws IOException;
}
@@ -0,0 +1,18 @@
package com.sap.sailing.domain.base;
/**
* Classes implementing this interface have their instance life cycle managed by a {@link DomainFactory}. This is important
* particularly during de-serialization when the de-serialized instance needs to be replaced by an instance managed by
* the domain factory.<p>
*
* If the de-serializing stream is a {@link ObjectInputStreamResolvingAgainstDomainFactory} stream, it will automatically
* do a {@link #resolve(Object)} for instances whose classes implement this interface. Implementing classes need to
* delegate accordingly to the domain factory passed as argument.
*
* @author Axel Uhl (D043530)
*
*/
public interface IsManagedByDomainFactory {
IsManagedByDomainFactory resolve(DomainFactory domainFactory);
}
@@ -3,7 +3,7 @@ package com.sap.sailing.domain.base;
import com.sap.sailing.domain.common.CountryCode;
import com.sap.sailing.domain.common.Named;
public interface Nationality extends Named, WithImage {
public interface Nationality extends Named, WithImage, IsManagedByDomainFactory {
String getThreeLetterIOCAcronym();
CountryCode getCountryCode();
@@ -22,11 +22,13 @@ public abstract class ObjectInputStreamResolvingAgainstDomainFactory extends Obj
/**
* Package protected on purpose; instances to be created using
* {@link DomainFactory#createObjectInputStreamResolvingAgainstThisFactory(InputStream)}.
* {@link DomainFactory#createObjectInputStreamResolvingAgainstThisFactory(InputStream)}. This constructor
* {@link #enableResolveObject(boolean) enables resolving} by default.
*/
protected ObjectInputStreamResolvingAgainstDomainFactory(InputStream in, DomainFactory domainFactory) throws IOException {
super(in);
this.domainFactory = domainFactory;
enableResolveObject(true);
}
@Override
@@ -39,4 +41,15 @@ public abstract class ObjectInputStreamResolvingAgainstDomainFactory extends Obj
String className = classDesc.getName();
return Thread.currentThread().getContextClassLoader().loadClass(className);
}
@Override
protected Object resolveObject(Object o) {
Object result;
if (o instanceof IsManagedByDomainFactory) {
result = ((IsManagedByDomainFactory) o).resolve(getDomainFactory());
} else {
result = o;
}
return result;
}
}
@@ -10,7 +10,7 @@ import com.sap.sailing.domain.common.Named;
* @author Axel Uhl (d043530)
*
*/
public interface Waypoint extends Named, WithID {
public interface Waypoint extends Named, WithID, IsManagedByDomainFactory {
ControlPoint getControlPoint();
Iterable<Buoy> getBuoys();
@@ -1,6 +1,7 @@
package com.sap.sailing.domain.base.impl;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.common.impl.NamedImpl;
@@ -99,4 +100,10 @@ public class BoatClassImpl extends NamedImpl implements BoatClass {
private double getConfidenceMultiplierForClusterSize(int numberOfBoatsInSmallestCluster) {
return 1.0 + 1.0/1000000.0 - 1.0/(double) numberOfBoatsInSmallestCluster;
}
@Override
public BoatClass resolve(DomainFactory domainFactory) {
return domainFactory.getOrCreateBoatClass(getName(), typicallyStartsUpwind());
}
}
@@ -1,8 +1,10 @@
package com.sap.sailing.domain.base.impl;
import java.io.Serializable;
import java.util.Collections;
import com.sap.sailing.domain.base.Buoy;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.common.impl.NamedImpl;
public class BuoyImpl extends NamedImpl implements Buoy {
@@ -11,6 +13,11 @@ public class BuoyImpl extends NamedImpl implements Buoy {
public BuoyImpl(String name) {
super(name);
}
@Override
public Serializable getId() {
return getName();
}
@SuppressWarnings("unchecked")
@Override
@@ -19,4 +26,9 @@ public class BuoyImpl extends NamedImpl implements Buoy {
return (Iterable<Buoy>) result;
}
@Override
public Buoy resolve(DomainFactory domainFactory) {
Buoy result = domainFactory.getOrCreateBuoy(getName());
return result;
}
}
@@ -4,6 +4,7 @@ import java.io.Serializable;
import com.sap.sailing.domain.base.Boat;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Team;
import com.sap.sailing.domain.common.impl.NamedImpl;
@@ -35,4 +36,9 @@ public class CompetitorImpl extends NamedImpl implements Competitor {
return boat;
}
@Override
public Competitor resolve(DomainFactory domainFactory) {
Competitor result = domainFactory.getOrCreateCompetitor(getId(), getName(), getTeam(), getBoat());
return result;
}
}
@@ -6,6 +6,7 @@ import java.io.InputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import com.sap.sailing.domain.base.Boat;
import com.sap.sailing.domain.base.BoatClass;
@@ -25,7 +26,7 @@ import com.sap.sailing.domain.tracking.impl.MarkPassingImpl;
public class DomainFactoryImpl implements DomainFactory {
/**
* Ensure that the <em>same</em> string is used as key that is also used to set the {@link Nationality}
* object's {@link Nationality#getName() name}.
* object's {@link Nationality#getThreeLetterIOCAcronym() IOC code}.
*/
private final Map<String, Nationality> nationalityCache;
@@ -34,21 +35,24 @@ public class DomainFactoryImpl implements DomainFactory {
private final Map<String, BoatClass> boatClassCache;
private final Map<Serializable, Competitor> competitorCache;
private final WeakHashMap<Serializable, Waypoint> waypointCache;
public DomainFactoryImpl() {
nationalityCache = new HashMap<String, Nationality>();
buoyCache = new HashMap<String, Buoy>();
boatClassCache = new HashMap<String, BoatClass>();
competitorCache = new HashMap<Serializable, Competitor>();
waypointCache = new WeakHashMap<Serializable, Waypoint>();
}
@Override
public Nationality getOrCreateNationality(String nationalityName) {
public Nationality getOrCreateNationality(String threeLetterIOCCode) {
synchronized (nationalityCache) {
Nationality result = nationalityCache.get(nationalityName);
Nationality result = nationalityCache.get(threeLetterIOCCode);
if (result == null) {
result = new NationalityImpl(nationalityName, nationalityName);
nationalityCache.put(nationalityName, result);
result = new NationalityImpl(threeLetterIOCCode);
nationalityCache.put(threeLetterIOCCode, result);
}
return result;
}
@@ -75,8 +79,23 @@ public class DomainFactoryImpl implements DomainFactory {
}
@Override
public Waypoint createWaypoint(ControlPoint controlPoint) {
return new WaypointImpl(controlPoint);
public synchronized Waypoint createWaypoint(ControlPoint controlPoint) {
Waypoint result = new WaypointImpl(controlPoint);
waypointCache.put(result.getId(), result);
return result;
}
@Override
public synchronized void cacheWaypoint(Waypoint waypoint) {
if (getExistingWaypointById(waypoint.getId()) != null) {
throw new IllegalArgumentException("Trying to cache an already cached waypoint: "+waypoint);
}
waypointCache.put(waypoint.getId(), waypoint);
}
@Override
public Waypoint getExistingWaypointById(Serializable id) {
return waypointCache.get(id);
}
@Override
@@ -102,11 +121,20 @@ public class DomainFactoryImpl implements DomainFactory {
}
@Override
public Competitor createCompetitor(Serializable id, String name, Team team, Boat boat) {
public synchronized Competitor createCompetitor(Serializable id, String name, Team team, Boat boat) {
Competitor result = new CompetitorImpl(id, name, team, boat);
competitorCache.put(id, result);
return result;
}
@Override
public synchronized Competitor getOrCreateCompetitor(Serializable competitorId, String name, Team team, Boat boat) {
Competitor result = getExistingCompetitorById(competitorId);
if (result == null) {
result = createCompetitor(competitorId, name, team, boat);
}
return result;
}
@Override
public ObjectInputStreamResolvingAgainstDomainFactory createObjectInputStreamResolvingAgainstThisFactory(
@@ -2,6 +2,8 @@ package com.sap.sailing.domain.base.impl;
import java.io.InputStream;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.IsManagedByDomainFactory;
import com.sap.sailing.domain.base.Nationality;
import com.sap.sailing.domain.common.CountryCode;
import com.sap.sailing.domain.common.CountryCodeFactory;
@@ -10,7 +12,7 @@ public class NationalityImpl implements Nationality {
private static final long serialVersionUID = 238906193483424259L;
private final String threeLetterIOCAcronym;
public NationalityImpl(String name, String threeLetterIOCAcronym) {
public NationalityImpl(String threeLetterIOCAcronym) {
if (threeLetterIOCAcronym.length() != 3) {
throw new IllegalArgumentException("Three-letter IOC nationality acronym \""+threeLetterIOCAcronym+"\" doesn't have three letters.");
}
@@ -40,5 +42,10 @@ public class NationalityImpl implements Nationality {
public CountryCode getCountryCode() {
return CountryCodeFactory.INSTANCE.getFromThreeLetterIOCName(getThreeLetterIOCAcronym());
}
@Override
public IsManagedByDomainFactory resolve(DomainFactory domainFactory) {
return domainFactory.getOrCreateNationality(getThreeLetterIOCAcronym());
}
}
@@ -11,5 +11,4 @@ public class ObjectInputStreamResolvingAgainstDomainFactoryImpl extends ObjectIn
throws IOException {
super(in, domainFactory);
}
}
@@ -2,6 +2,7 @@ package com.sap.sailing.domain.base.impl;
import com.sap.sailing.domain.base.Buoy;
import com.sap.sailing.domain.base.ControlPoint;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Waypoint;
public class WaypointImpl implements Waypoint {
@@ -39,5 +40,15 @@ public class WaypointImpl implements Waypoint {
public Integer getId() {
return id;
}
@Override
public Waypoint resolve(DomainFactory domainFactory) {
Waypoint result = domainFactory.getExistingWaypointById(getId());
if (result == null) {
domainFactory.cacheWaypoint(this);
result = this;
}
return result;
}
}
@@ -2,6 +2,8 @@ package com.sap.sailing.domain.tracking.impl;
import com.sap.sailing.domain.base.Boat;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.IsManagedByDomainFactory;
import com.sap.sailing.domain.base.Team;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.common.TimePoint;
@@ -50,6 +52,11 @@ public class DummyMarkPassingWithTimePointOnly implements MarkPassing {
public Boat getBoat() {
return null;
}
@Override
public IsManagedByDomainFactory resolve(DomainFactory domainFactory) {
return this;
}
};
}