Merge branch 'master' into newhome

Conflicts:
	java/com.sap.sailing.gwt.ui/SailingGWT.launch (added Search.html entry point to SailingGWT.launch)
This commit is contained in:
Axel Uhl committed 2014-06-05 09:04:08 +02:00
commit 6f1979b756
16 files changed
+616 -41

No files matched your search

@@ -22,6 +22,7 @@ import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.EventBase;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.LeaderboardSearchResult;
import com.sap.sailing.domain.base.LeaderboardSearchResultBase;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
@@ -556,5 +557,25 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
*/
Util.Pair<Iterable<EventBase>, Exception> updateRemoteServerEventCacheSynchronously(RemoteSailingServerReference ref);
/**
* Searches the content of this server, not that of any remote servers referenced by any {@link RemoteSailingServerReference}s.
*/
Result<LeaderboardSearchResult> search(KeywordQuery query);
/**
* Searches a specific remote server whose reference has the {@link RemoteSailingServerReference#getName() name}
* <code>remoteServerReferenceName</code>. If a remote server reference with that name is not known,
* <code>null</code> is returned. Otherwise, a non-<code>null</code> and possibly empty search result set is
* returned.
*/
Result<LeaderboardSearchResultBase> searchRemotely(String remoteServerReferenceName, KeywordQuery query);
/**
* References to remote servers may be dead or alive. This is internally determined by regularly polling those
* servers for their events list. If the events list cannot be successfully retrieved, the server is considered "dead."
* This method returns the "live" server references.
*/
Iterable<RemoteSailingServerReference> getLiveRemoteServerReferences();
RemoteSailingServerReference getRemoteServerReferenceByName(String remoteServerReferenceName);
}
@@ -5,28 +5,18 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import com.sap.sailing.domain.base.LeaderboardSearchResult;
import com.sap.sailing.domain.base.LeaderboardSearchResultBase;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
import com.sap.sailing.server.RacingEventService;
import com.sap.sse.common.Util;
public class RegattaSearchResultRanker implements Comparator<LeaderboardSearchResult> {
private final TrackedRegattaRegistry trackedRegattaRegistry;
protected RegattaSearchResultRanker(RacingEventService racingEventService) {
this.trackedRegattaRegistry = racingEventService;
}
public class LeaderboardSearchResultBaseRanker<T extends LeaderboardSearchResultBase> implements Comparator<T> {
@Override
public int compare(LeaderboardSearchResult o1, LeaderboardSearchResult o2) {
Regatta r1 = o1.getRegatta();
Regatta r2 = o2.getRegatta();
TrackedRegatta trackedR1 = r1 == null ? null : trackedRegattaRegistry.getTrackedRegatta(r1);
TrackedRegatta trackedR2 = r2 == null ? null : trackedRegattaRegistry.getTrackedRegatta(r2);
public int compare(T o1, T o2) {
TrackedRegatta trackedR1 = getTrackedRegatta(o1);
TrackedRegatta trackedR2 = getTrackedRegatta(o2);
final int result;
if (trackedR1 == null) {
if (trackedR2 == null) {
@@ -44,16 +34,8 @@ public class RegattaSearchResultRanker implements Comparator<LeaderboardSearchRe
}
return result;
}
private int compareByEarliestStartOfATrackedRace(TrackedRegatta trackedR1, TrackedRegatta trackedR2) {
assert trackedR1 != null;
assert trackedR2 != null;
TimePoint earliestTrackedRaceInR1 = getEarliestTrackedRace(trackedR1);
TimePoint earliestTrackedRaceInR2 = getEarliestTrackedRace(trackedR2);
return Util.compareToWithNull(earliestTrackedRaceInR1, earliestTrackedRaceInR2, /* nullIsLess */ false);
}
private TimePoint getEarliestTrackedRace(TrackedRegatta trackedRegatta) {
protected TimePoint getEarliestTrackedRace(TrackedRegatta trackedRegatta) {
List<TimePoint> startOfTrackingTimes = new ArrayList<>();
for (TrackedRace trackedRace : trackedRegatta.getTrackedRaces()) {
if (trackedRace.getStartOfTracking() != null) {
@@ -68,4 +50,20 @@ public class RegattaSearchResultRanker implements Comparator<LeaderboardSearchRe
}
return result;
}
protected int compareByEarliestStartOfATrackedRace(TrackedRegatta trackedR1, TrackedRegatta trackedR2) {
assert trackedR1 != null;
assert trackedR2 != null;
TimePoint earliestTrackedRaceInR1 = getEarliestTrackedRace(trackedR1);
TimePoint earliestTrackedRaceInR2 = getEarliestTrackedRace(trackedR2);
return Util.compareToWithNull(earliestTrackedRaceInR1, earliestTrackedRaceInR2, /* nullIsLess */ false);
}
/**
* Can't know a tracked regatta if we only have a {@link LeaderboardSearchResultBase} which doesn't reference a
* real {@link Regatta} object.
*/
protected TrackedRegatta getTrackedRegatta(T o1) {
return null;
}
}
@@ -0,0 +1,21 @@
package com.sap.sailing.server.impl;
import com.sap.sailing.domain.base.LeaderboardSearchResult;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
import com.sap.sailing.server.RacingEventService;
public class LeaderboardSearchResultRanker extends LeaderboardSearchResultBaseRanker<LeaderboardSearchResult> {
private final TrackedRegattaRegistry trackedRegattaRegistry;
protected LeaderboardSearchResultRanker(RacingEventService racingEventService) {
this.trackedRegattaRegistry = racingEventService;
}
protected TrackedRegatta getTrackedRegatta(LeaderboardSearchResult o1) {
Regatta r1 = o1.getRegatta();
TrackedRegatta trackedR1 = r1 == null ? null : trackedRegattaRegistry.getTrackedRegatta(r1);
return trackedR1;
}
}
@@ -1,12 +1,16 @@
package com.sap.sailing.server.impl;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.SocketException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -28,6 +32,10 @@ import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
@@ -40,6 +48,7 @@ import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.EventBase;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.LeaderboardSearchResult;
import com.sap.sailing.domain.base.LeaderboardSearchResultBase;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceColumnInSeries;
@@ -135,6 +144,11 @@ import com.sap.sailing.server.OperationExecutionListener;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.RacingEventServiceOperation;
import com.sap.sailing.server.Replicator;
import com.sap.sailing.server.gateway.deserialization.impl.CourseAreaJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.EventBaseJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.LeaderboardGroupBaseJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.LeaderboardSearchResultBaseJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.VenueJsonDeserializer;
import com.sap.sailing.server.masterdata.DataImportLockWithProgress;
import com.sap.sailing.server.operationaltransformation.AddCourseArea;
import com.sap.sailing.server.operationaltransformation.AddDefaultRegatta;
@@ -174,6 +188,7 @@ import com.sap.sailing.util.impl.NamedReentrantReadWriteLock;
import com.sap.sse.common.Util;
import com.sap.sse.common.search.KeywordQuery;
import com.sap.sse.common.search.Result;
import com.sap.sse.common.search.ResultImpl;
public class RacingEventServiceImpl implements RacingEventServiceWithTestSupport, RegattaListener, LeaderboardRegistry, Replicator {
private static final Logger logger = Logger.getLogger(RacingEventServiceImpl.class.getName());
@@ -881,6 +896,16 @@ public class RacingEventServiceImpl implements RacingEventServiceWithTestSupport
mongoObjectFactory.storeSailingServer(result);
return result;
}
@Override
public Iterable<RemoteSailingServerReference> getLiveRemoteServerReferences() {
return remoteSailingServerSet.getLiveRemoteServerReferences();
}
@Override
public RemoteSailingServerReference getRemoteServerReferenceByName(String remoteServerReferenceName) {
return remoteSailingServerSet.getServerReferenceByName(remoteServerReferenceName);
}
@Override
public com.sap.sse.common.Util.Pair<Iterable<EventBase>, Exception> updateRemoteServerEventCacheSynchronously(RemoteSailingServerReference ref) {
@@ -2594,6 +2619,53 @@ public class RacingEventServiceImpl implements RacingEventServiceWithTestSupport
@Override
public Result<LeaderboardSearchResult> search(KeywordQuery query) {
return new RegattaByKeywordSearchService().search(this, query);
long start = System.currentTimeMillis();
logger.info("Searching local server for "+query);
Result<LeaderboardSearchResult> result = new RegattaByKeywordSearchService().search(this, query);
logger.fine("Search for "+query+" took "+(System.currentTimeMillis()-start)+"ms");
return result;
}
@Override
public Result<LeaderboardSearchResultBase> searchRemotely(String remoteServerReferenceName, KeywordQuery query) {
long start = System.currentTimeMillis();
ResultImpl<LeaderboardSearchResultBase> result = null;
RemoteSailingServerReference remoteRef = remoteSailingServerSet.getServerReferenceByName(remoteServerReferenceName);
if (remoteRef == null) {
result = null;
} else {
BufferedReader bufferedReader = null;
try {
try {
final URL eventsURL = new URL(remoteRef.getURL(), "sailingserver/api/v1/search?q="+URLEncoder.encode(query.toString(), "UTF-8"));
logger.info("Searching remote server "+remoteRef+" for "+query);
URLConnection urlConnection = eventsURL.openConnection();
urlConnection.connect();
bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
JSONParser parser = new JSONParser();
Object eventsAsObject = parser.parse(bufferedReader);
final LeaderboardGroupBaseJsonDeserializer leaderboardGroupBaseJsonDeserializer = new LeaderboardGroupBaseJsonDeserializer();
LeaderboardSearchResultBaseJsonDeserializer deserializer = new LeaderboardSearchResultBaseJsonDeserializer(
new EventBaseJsonDeserializer(new VenueJsonDeserializer(new CourseAreaJsonDeserializer(
DomainFactory.INSTANCE)), leaderboardGroupBaseJsonDeserializer),
leaderboardGroupBaseJsonDeserializer);
result = new ResultImpl<LeaderboardSearchResultBase>(query, new LeaderboardSearchResultBaseRanker<LeaderboardSearchResultBase>());
JSONArray hitsAsJsonArray = (JSONArray) eventsAsObject;
for (Object hitAsObject : hitsAsJsonArray) {
JSONObject hitAsJson = (JSONObject) hitAsObject;
LeaderboardSearchResultBase hit = deserializer.deserialize(hitAsJson);
result.addHit(hit);
}
} finally {
if (bufferedReader != null) {
bufferedReader.close();
}
}
} catch (IOException | ParseException e) {
logger.log(Level.INFO, "Exception trying to fetch events from remote server "+remoteRef+": "+e.getMessage(), e);
}
}
logger.fine("Remote search on "+remoteRef+" for "+query+" took "+(System.currentTimeMillis()-start)+"ms");
return result;
}
}
@@ -33,7 +33,7 @@ import com.sap.sse.common.search.ResultImpl;
*/
public class RegattaByKeywordSearchService {
Result<LeaderboardSearchResult> search(final RacingEventService racingEventService, KeywordQuery query) {
ResultImpl<LeaderboardSearchResult> result = new ResultImpl<>(query, new RegattaSearchResultRanker(racingEventService));
ResultImpl<LeaderboardSearchResult> result = new ResultImpl<>(query, new LeaderboardSearchResultRanker(racingEventService));
final Map<Leaderboard, Event> eventForLeaderboard = new HashMap<>();
final Map<Leaderboard, Set<LeaderboardGroup>> leaderboardGroupsForLeaderboard = new HashMap<>();
AbstractListFilter<Leaderboard> leaderboardFilter = new AbstractListFilter<Leaderboard>() {
@@ -6,8 +6,10 @@ import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -22,7 +24,6 @@ import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.EventBase;
import com.sap.sailing.domain.base.RemoteSailingServerReference;
import com.sap.sailing.server.gateway.deserialization.impl.CourseAreaJsonDeserializer;
@@ -30,6 +31,7 @@ import com.sap.sailing.server.gateway.deserialization.impl.EventBaseJsonDeserial
import com.sap.sailing.server.gateway.deserialization.impl.LeaderboardGroupBaseJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.VenueJsonDeserializer;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
/**
* A set of {@link RemoteSailingServerReference}s including a cache of their {@link EventBase events} that is
@@ -44,7 +46,8 @@ public class RemoteSailingServerSet {
private static final Logger logger = Logger.getLogger(RemoteSailingServerSet.class.getName());
/**
* Holds the {@link Event} objects for the events of all registered sailing server instances.
* Holds the remote server references managed by this set. Keys are the
* {@link RemoteSailingServerReference#getName() names} of the server references.
*/
private final ConcurrentHashMap<String, RemoteSailingServerReference> remoteSailingServers;
@@ -76,6 +79,14 @@ public class RemoteSailingServerSet {
triggerAsynchronousEventCacheUpdate(ref);
}
}
/**
* If this set has a {@link RemoteSailingServerReference} whose {@link RemoteSailingServerReference#getName() name} equals
* <code>name</code>, it is returned. Otherwise, <code>null</code> is returned.
*/
public RemoteSailingServerReference getServerReferenceByName(String name) {
return remoteSailingServers.get(name);
}
private void triggerAsynchronousEventCacheUpdate(final RemoteSailingServerReference ref) {
new Thread("Event Cache Updater for remote server "+ref) {
@@ -150,4 +161,15 @@ public class RemoteSailingServerSet {
}
return updateRemoteServerEventCacheSynchronously(ref);
}
public Iterable<RemoteSailingServerReference> getLiveRemoteServerReferences() {
List<RemoteSailingServerReference> result = new ArrayList<>();
for (Map.Entry<RemoteSailingServerReference, Pair<Iterable<EventBase>, Exception>> e : cachedEventsForRemoteSailingServers.entrySet()) {
if (e.getValue().getB() == null) {
// no exception; reference considered live
result.add(e.getKey());
}
}
return result;
}
}