Merge branch 'master' into mak-navigationPanel

This commit is contained in:
Marcus Kammer committed 2012-05-29 11:39:24 +02:00
commit d46266736e
11 files changed
+115 -30

No files matched your search

@@ -57,7 +57,10 @@ public class DeclinationServiceImpl implements DeclinationService {
int year = cal.get(Calendar.YEAR);
QuadTree<Declination> set;
while ((set = getYearStore(year)) != null) {
Declination resultForYear = set.get(position);
Declination resultForYear;
synchronized (set) {
resultForYear = set.get(position);
}
Distance spatialDistance = resultForYear.getPosition().getDistance(position);
// consider result only if it's closer than maxDistance
if (spatialDistance.compareTo(maxDistance) <= 0) {
@@ -73,7 +76,9 @@ public class DeclinationServiceImpl implements DeclinationService {
if (result == null) {
QuadTree<Declination> importerCacheForYear = importerCache.get(year);
if (importerCacheForYear != null) {
result = importerCacheForYear.get(position);
synchronized (importerCacheForYear) {
result = importerCacheForYear.get(position);
}
if (result.getPosition().getDistance(position).compareTo(maxDistance) <= 0) {
return result;
// else it's further away from the requested position as demanded by maxDistance
@@ -85,7 +90,9 @@ public class DeclinationServiceImpl implements DeclinationService {
importerCacheForYear = new QuadTree<Declination>();
importerCache.put(year, importerCacheForYear);
}
importerCacheForYear.put(result.getPosition(), result);
synchronized (importerCacheForYear) {
importerCacheForYear.put(result.getPosition(), result);
}
}
}
return result;
@@ -49,7 +49,9 @@ public class DeclinationStore {
result = new QuadTree<Declination>();
BufferedReader in = new BufferedReader(new InputStreamReader(is));
while ((record = readExternal(in)) != null) {
result.put(record.getPosition(), record);
synchronized (result) {
result.put(record.getPosition(), record);
}
}
}
return result;
@@ -150,7 +152,10 @@ public class DeclinationStore {
System.out.println("Date: " + year + "/" + (month + 1) + ", Latitude: " + lat);
for (double lng = 0; lng < 180; lng += grid) {
Position point = new DegreePosition(lat, lng);
Declination existingDeclinationRecord = storedDeclinations.get(point);
Declination existingDeclinationRecord;
synchronized (storedDeclinations) {
existingDeclinationRecord = storedDeclinations.get(point);
}
if (existingDeclinationRecord == null
|| DeclinationServiceImpl.timeAndSpaceDistance(existingDeclinationRecord
.getPosition().getDistance(point), timePoint, existingDeclinationRecord
@@ -161,7 +166,10 @@ public class DeclinationStore {
}
for (double lng = -grid; lng > -180; lng -= grid) {
Position point = new DegreePosition(lat, lng);
Declination existingDeclinationRecord = storedDeclinations.get(point);
Declination existingDeclinationRecord;
synchronized (storedDeclinations) {
existingDeclinationRecord = storedDeclinations.get(point);
}
if (existingDeclinationRecord == null
|| DeclinationServiceImpl.timeAndSpaceDistance(existingDeclinationRecord
.getPosition().getDistance(point), timePoint, existingDeclinationRecord
@@ -175,7 +183,10 @@ public class DeclinationStore {
System.out.println("Date: " + year + "/" + (month + 1) + ", Latitude: " + lat);
for (double lng = 0; lng < 180; lng += grid) {
Position point = new DegreePosition(lat, lng);
Declination existingDeclinationRecord = storedDeclinations.get(point);
Declination existingDeclinationRecord;
synchronized (storedDeclinations) {
existingDeclinationRecord = storedDeclinations.get(point);
}
if (DeclinationServiceImpl.timeAndSpaceDistance(existingDeclinationRecord.getPosition().getDistance(point),
timePoint, existingDeclinationRecord.getTimePoint()) > 0.1) {
// less than ~6 nautical miles and/or ~.6 months off
@@ -184,7 +195,10 @@ public class DeclinationStore {
}
for (double lng = -grid; lng > -180; lng -= grid) {
Position point = new DegreePosition(lat, lng);
Declination existingDeclinationRecord = storedDeclinations.get(point);
Declination existingDeclinationRecord;
synchronized (storedDeclinations) {
existingDeclinationRecord = storedDeclinations.get(point);
}
if (DeclinationServiceImpl.timeAndSpaceDistance(existingDeclinationRecord.getPosition().getDistance(point),
timePoint, existingDeclinationRecord.getTimePoint()) > 0.1) {
// less than ~6 nautical miles and/or ~.6 months off
@@ -7,4 +7,5 @@ Bundle-Vendor: SAP
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Export-Package: com.sap.sailing.domain.common,
com.sap.sailing.domain.common.impl,
com.sap.sailing.domain.common.quadtree
com.sap.sailing.domain.common.quadtree,
com.sap.sailing.domain.common.quadtree.impl;x-friends:="com.sap.sailing.domain.test"
@@ -12,9 +12,12 @@ public class AbstractPosition implements Position {
}
public boolean equals(Object o) {
return o instanceof Position &&
getLatRad() == ((Position) o).getLatRad() &&
getLngRad() == ((Position) o).getLngRad();
if (o == null) {
return false;
} else {
return o instanceof Position && getLatRad() == ((Position) o).getLatRad()
&& getLngRad() == ((Position) o).getLngRad();
}
}
@Override
@@ -32,11 +32,16 @@ import com.sap.sailing.domain.common.quadtree.impl.Bounds;
import com.sap.sailing.domain.common.quadtree.impl.QuadTreeNode;
/**
* The QuadTree lets you organize objects in a grid, that redefines
* itself and focuses more gridding when more objects appear in a
* certain area.
* The QuadTree lets you organize objects in a grid, that redefines itself and focuses more gridding when more objects
* appear in a certain area.
* <p>
*
* @param <T> type of object stored by coordinates
* Note that this class is not thread safe. If multiple threads can access the same instance concurrently, callers have
* to ensure proper synchronization. Concurrent reads are permissible while any write should block all other operations.
*
* @param <T>
* type of object stored by coordinates
* @author Axel Uhl (D043530)
*/
public class QuadTree<T> implements Serializable {
@@ -110,7 +110,7 @@ public class QuadTreeNode<T> implements Serializable {
* into the children.
*/
@SuppressWarnings("unchecked")
protected void split() {
protected void split() {
// Make sure we're bigger than the minimum, if we care,
if (minSize != NO_MIN_SIZE) {
if (Math.abs(bounds.getNorthEast().getLatDeg() - bounds.getSouthWest().getLatDeg()) < minSize
@@ -121,7 +121,6 @@ public class QuadTreeNode<T> implements Serializable {
double nsHalf = (bounds.getNorthEast().getLatDeg() + bounds.getSouthWest().getLatDeg()) / 2.0;
double ewHalf = (bounds.getNorthEast().getLngDeg() + bounds.getSouthWest().getLngDeg()) / 2.0;
children = new QuadTreeNode[4];
children[NORTHWEST] = new QuadTreeNode<T>(new Bounds(new DegreePosition(nsHalf, bounds.getSouthWest().getLngDeg()), new DegreePosition(bounds.getNorthEast().getLatDeg(), ewHalf)), maxItems);
children[NORTHEAST] = new QuadTreeNode<T>(new Bounds(new DegreePosition(nsHalf, ewHalf), bounds.getNorthEast()), maxItems);
children[SOUTHEAST] = new QuadTreeNode<T>(new Bounds(new DegreePosition(bounds.getSouthWest().getLatDeg(), ewHalf), new DegreePosition(nsHalf, bounds.getNorthEast().getLngDeg())), maxItems);
@@ -131,7 +130,6 @@ public class QuadTreeNode<T> implements Serializable {
for (Iterator<QuadTreeLeaf<T>> i=temp.iterator(); i.hasNext(); ) {
put(i.next());
}
//items.removeAllElements();
}
/**
@@ -208,9 +206,9 @@ public class QuadTreeNode<T> implements Serializable {
this.allTheSamePoint = false;
}
}
if (this.items.size() > maxItems && !this.allTheSamePoint)
if (this.items.size() > maxItems && !this.allTheSamePoint) {
split();
}
} else {
QuadTreeNode<T> node = getChild(leaf.getPoint());
if (node != null) {
@@ -1,12 +1,14 @@
package com.sap.sailing.domain.test;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import org.junit.Test;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.common.impl.DegreePosition;
import com.sap.sailing.domain.common.quadtree.QuadTree;
import com.sap.sailing.domain.common.quadtree.impl.QuadTreeNode;
public class QuadTreeTest {
private class GLatLngQuadTree extends QuadTree<Position> {
@@ -21,6 +23,53 @@ public class QuadTreeTest {
}
}
private static class QuadTreeWithPublicGetTop<T> extends QuadTree<T> {
private static final long serialVersionUID = -783622065160380333L;
@Override
public QuadTreeNode<T> getTop() {
return super.getTop();
}
}
@Test
public void testNoNPEDuringSecondPutInSameLeaf() {
final QuadTreeWithPublicGetTop<Object> qt = new QuadTreeWithPublicGetTop<Object>();
final Position p = new DegreePosition(0, 0);
final NullPointerException[] npe = new NullPointerException[1];
final boolean[] stop = new boolean[1];
Runnable r = new Runnable() {
@Override
public void run() {
while (!stop[0]) {
synchronized (qt) {
try {
qt.wait();
// if the following try/catch is moved outside the synchronized block, occasional NPEs result
try {
qt.put(p, p);
} catch (NullPointerException e) {
npe[0] = e;
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
};
new Thread(r, "1").start();
new Thread(r, "2").start();
new Thread(r, "3").start();
new Thread(r, "4").start();
for (int i=0; i<10000000; i++) {
synchronized(qt) {
qt.notifyAll();
}
assertNull("NullPointerException "+(npe[0]==null?"":npe[0].getMessage())+" during iteration "+i, npe[0]);
}
stop[0] = true;
}
@Test
public void testDistance() {
GLatLngQuadTree quadtree = new GLatLngQuadTree(new DegreePosition(49.29,
@@ -194,7 +194,9 @@ public class ReverseGeocoderImpl implements ReverseGeocoder {
private void cachePlacemarks(Position position, Double radius, List<Placemark> placemarks) {
Collections.sort(placemarks, new Placemark.ByDistance(position));
if (position != null) {
cache.put(position, new Triple<Position, Double, List<Placemark>>(position, radius, placemarks));
synchronized (cache) {
cache.put(position, new Triple<Position, Double, List<Placemark>>(position, radius, placemarks));
}
}
}
@@ -211,7 +213,9 @@ public class ReverseGeocoderImpl implements ReverseGeocoder {
*/
private void updateCachedPlacemarks(Position cachedPoint, Double newRadius, List<Placemark> newPlacemarks) {
if (cachedPoint != null) {
cache.replace(cachedPoint, new Triple<Position, Double, List<Placemark>>(cachedPoint, newRadius, newPlacemarks));
synchronized (cache) {
cache.replace(cachedPoint, new Triple<Position, Double, List<Placemark>>(cachedPoint, newRadius, newPlacemarks));
}
}
}
@@ -223,7 +227,9 @@ public class ReverseGeocoderImpl implements ReverseGeocoder {
* {@link ReverseGeocoderImpl#POSITION_CACHE_DISTANCE_LIMIT the distance limit}
*/
private Triple<Position, Double, List<Placemark>> checkCache(Position position) {
return cache.get(position, POSITION_CACHE_DISTANCE_LIMIT);
synchronized (cache) {
return cache.get(position, POSITION_CACHE_DISTANCE_LIMIT);
}
}
private JSONArray callNearestService(Position position) throws MalformedURLException, IOException, ParseException {
+1 -1
View File
@@ -238,7 +238,6 @@ input.opencoloumn {
.raceBoardNavigation-innerElement {
background: url("images/btn-cta-orangeleft.png") repeat-x scroll center 0 transparent;
border: medium none;
border-bottom-left-radius: 3px;
border-top-left-radius: 3px;
color: #FFFFFF;
@@ -247,6 +246,7 @@ input.opencoloumn {
font-size: 14px;
margin: 0 0 0 0;
padding: 2px 7px 2px 3px;
height: 19px;
}
.raceBoardNavigation-innerElement:hover {
background: url("images/btn-cta-orangeleft.png") repeat-x scroll center -30px transparent;
@@ -36,9 +36,9 @@ public class GlobalNavigationPanel extends FlowPanel {
if(showHomeNavigation) {
if (leaderboardGroupName != null && !leaderboardGroupName.isEmpty()) {
String leaderBoardGroupLink = spectatorViewLink + "?leaderboardGroupName=" + leaderboardGroupName;
addNavigationLink(leaderboardGroupName, leaderBoardGroupLink, "leaderBoardGroup");
addNavigationLink(leaderboardGroupName, leaderBoardGroupLink, "leaderBoardGroup", "Go to the Event overview.");
} else {
addNavigationLink(stringMessages.home(), homeLink, "home");
addNavigationLink(stringMessages.home(), homeLink, "home", "Go to the Event overview.");
}
}
@@ -47,11 +47,12 @@ public class GlobalNavigationPanel extends FlowPanel {
if (leaderboardGroupName != null && !leaderboardGroupName.isEmpty()) {
leaderBoardLink += "&leaderboardGroupName=" + leaderboardGroupName;
}
addNavigationLink(leaderboardName, leaderBoardLink, "leaderBoard");
addNavigationLink(leaderboardName, leaderBoardLink, "leaderBoard", "Go to the overview and see all Races in one Leaderboard");
}
}
private void addNavigationLink(String linkName, String linkUrl, String styleNameExtension) {
private void addNavigationLink(String linkName, String linkUrl, String styleNameExtension, String htmlTitle) {
String setHtmlTitle = htmlTitle;
String url = linkUrl;
if(debugParam != null && !debugParam.isEmpty()) {
url += url.contains("?") ? "&" : "?";
@@ -60,6 +61,7 @@ public class GlobalNavigationPanel extends FlowPanel {
HTML linkHtml = new HTML(ANCHORTEMPLATE.anchor(URLFactory.INSTANCE.encode(url), linkName));
linkHtml.addStyleName(STYLE_NAME_PREFIX + styleNameExtension);
linkHtml.setTitle(setHtmlTitle);
add(linkHtml);
}
}
@@ -1772,7 +1772,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
groupDTO.name = leaderboardGroup.getName();
groupDTO.description = leaderboardGroup.getDescription();
for (Leaderboard leaderboard : leaderboardGroup.getLeaderboards()) {
groupDTO.leaderboards.add(createStrippedLeaderboardDTO(leaderboard, false));
groupDTO.leaderboards.add(createStrippedLeaderboardDTO(leaderboard, true));
}
return groupDTO;
}