mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-07 19:42:17 +00:00
serialize cached image sizes with EventBase so they are available in GWT front-end to decide what goes to the stage and what not
This commit is contained in:
1 parent
da14d835c7
commit
1b46a87d79
9 files changed
+131
-18
No files matched your search
+12
@@ -1,6 +1,7 @@
|
||||
package com.sap.sailing.domain.base;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import com.sap.sailing.domain.common.Renamable;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
@@ -119,4 +120,15 @@ public interface EventBase extends Named, WithDescription, Renamable, WithID {
|
||||
void setOfficialWebsiteURL(URL officialWebsiteURL);
|
||||
|
||||
Iterable<? extends LeaderboardGroupBase> getLeaderboardGroups();
|
||||
|
||||
public static interface ImageSize {
|
||||
int getWidth();
|
||||
int getHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* For the images references by the image URLs in {@link #getImageURLs()}, {@link #getSponsorImageURLs()} and {@link #getLogoImageURL()}
|
||||
* determines the image dimensions.
|
||||
*/
|
||||
ImageSize getImageSize(URL imageURL) throws InterruptedException, ExecutionException;
|
||||
}
|
||||
+23
@@ -220,4 +220,27 @@ public abstract class EventBaseImpl implements EventBase {
|
||||
public void setOfficialWebsiteURL(URL officialWebsiteURL) {
|
||||
this.officialWebsiteURL = officialWebsiteURL;
|
||||
}
|
||||
|
||||
public static class ImageSizeImpl implements ImageSize {
|
||||
private final int width;
|
||||
private final int height;
|
||||
public ImageSizeImpl(int width, int height) {
|
||||
super();
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "("+getWidth()+"x"+getHeight()+")";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+18
-3
@@ -1,6 +1,10 @@
|
||||
package com.sap.sailing.domain.base.impl;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import com.sap.sailing.domain.base.EventBase;
|
||||
import com.sap.sailing.domain.base.LeaderboardGroupBase;
|
||||
@@ -9,7 +13,8 @@ import com.sap.sailing.domain.common.TimePoint;
|
||||
|
||||
/**
|
||||
* A simplified implementation of the {@link EventBase} interface which maintains an immutable collection of
|
||||
* {@link LeaderboardGroupBase} objects to implement the {@link #getLeaderboardGroups()} method.
|
||||
* {@link LeaderboardGroupBase} objects to implement the {@link #getLeaderboardGroups()} method. A local image
|
||||
* size cache can be maintained using the {@link #setImageSize} method.
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
@@ -17,21 +22,31 @@ import com.sap.sailing.domain.common.TimePoint;
|
||||
public class StrippedEventImpl extends EventBaseImpl {
|
||||
private static final long serialVersionUID = 5608501747499933988L;
|
||||
private final Iterable<LeaderboardGroupBase> leaderboardGroups;
|
||||
private final Map<URL, ImageSize> imageSizes;
|
||||
|
||||
public StrippedEventImpl(String name, TimePoint startDate, TimePoint endDate, String venueName,
|
||||
boolean isPublic, UUID id, Iterable<LeaderboardGroupBase> leaderboardGroups) {
|
||||
super(name, startDate, endDate, venueName, isPublic, id);
|
||||
this.leaderboardGroups = leaderboardGroups;
|
||||
this(name, startDate, endDate, new VenueImpl(venueName), isPublic, id, leaderboardGroups);
|
||||
}
|
||||
|
||||
public StrippedEventImpl(String name, TimePoint startDate, TimePoint endDate, Venue venue,
|
||||
boolean isPublic, UUID id, Iterable<LeaderboardGroupBase> leaderboardGroups) {
|
||||
super(name, startDate, endDate, venue, isPublic, id);
|
||||
this.leaderboardGroups = leaderboardGroups;
|
||||
this.imageSizes = new HashMap<URL, EventBase.ImageSize>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<LeaderboardGroupBase> getLeaderboardGroups() {
|
||||
return leaderboardGroups;
|
||||
}
|
||||
|
||||
public void setImageSize(URL imageURL, ImageSize imageSize) {
|
||||
imageSizes.put(imageURL, imageSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageSize getImageSize(URL imageURL) throws InterruptedException, ExecutionException {
|
||||
return imageSizes.get(imageURL);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.sap.sailing.domain.base;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
@@ -59,6 +58,6 @@ public interface Event extends EventBase {
|
||||
* Note that exceptions may result should the image be unavailable. If the image URL leads to a document that is not an image,
|
||||
* <code>null</code> will result.
|
||||
*/
|
||||
Dimension getImageSize(URL imageURL) throws InterruptedException, ExecutionException;
|
||||
ImageSize getImageSize(URL imageURL) throws InterruptedException, ExecutionException;
|
||||
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.sap.sailing.domain.base.impl;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.net.URL;
|
||||
@@ -36,7 +35,7 @@ public class EventImpl extends EventBaseImpl implements Event {
|
||||
|
||||
private ConcurrentLinkedQueue<LeaderboardGroup> leaderboardGroups;
|
||||
|
||||
private transient ConcurrentHashMap<URL, Future<Dimension>> imageSizeFetchers;
|
||||
private transient ConcurrentHashMap<URL, Future<ImageSize>> imageSizeFetchers;
|
||||
private transient ExecutorService executor;
|
||||
|
||||
public EventImpl(String name, TimePoint startDate, TimePoint endDate, String venueName, boolean isPublic, UUID id) {
|
||||
@@ -103,13 +102,13 @@ public class EventImpl extends EventBaseImpl implements Event {
|
||||
return leaderboardGroups.remove(leaderboardGroup);
|
||||
}
|
||||
|
||||
private Future<Dimension> getOrCreateImageSizeCalculator(final URL imageURL) {
|
||||
Future<Dimension> imageSizeFetcher = imageSizeFetchers.get(imageURL);
|
||||
private Future<ImageSize> getOrCreateImageSizeCalculator(final URL imageURL) {
|
||||
Future<ImageSize> imageSizeFetcher = imageSizeFetchers.get(imageURL);
|
||||
if (imageSizeFetcher == null) {
|
||||
imageSizeFetcher = executor.submit(new Callable<Dimension>() {
|
||||
imageSizeFetcher = executor.submit(new Callable<ImageSize>() {
|
||||
@Override
|
||||
public Dimension call() throws IOException {
|
||||
Dimension result = null;
|
||||
public ImageSize call() throws IOException {
|
||||
ImageSize result = null;
|
||||
ImageInputStream in = null;
|
||||
try {
|
||||
URLConnection conn = imageURL.openConnection();
|
||||
@@ -119,7 +118,7 @@ public class EventImpl extends EventBaseImpl implements Event {
|
||||
ImageReader reader = readers.next();
|
||||
try {
|
||||
reader.setInput(in);
|
||||
result = new Dimension(reader.getWidth(0), reader.getHeight(0));
|
||||
result = new ImageSizeImpl(reader.getWidth(0), reader.getHeight(0));
|
||||
} finally {
|
||||
reader.dispose();
|
||||
}
|
||||
@@ -138,8 +137,8 @@ public class EventImpl extends EventBaseImpl implements Event {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getImageSize(URL imageURL) throws InterruptedException, ExecutionException {
|
||||
Future<Dimension> imageSizeCalculator = getOrCreateImageSizeCalculator(imageURL);
|
||||
public ImageSize getImageSize(URL imageURL) throws InterruptedException, ExecutionException {
|
||||
Future<ImageSize> imageSizeCalculator = getOrCreateImageSizeCalculator(imageURL);
|
||||
return imageSizeCalculator.get();
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -116,6 +116,8 @@ public class EventBaseDTO extends NamedDTO implements IsSerializable {
|
||||
public String getStageImageURL() {
|
||||
String result = null;
|
||||
for(String imageUrl: imageURLs) {
|
||||
// FIXME consolidate with getPhotoGalleryImageURLs, removing redundant "STAGE" code
|
||||
// TODO use image size to find largest image(s) in case none is explicitly marked with "state" in its URL
|
||||
if(imageUrl.contains("stage") || imageUrl.contains("STAGE")) {
|
||||
result = imageUrl;
|
||||
break;
|
||||
@@ -127,6 +129,7 @@ public class EventBaseDTO extends NamedDTO implements IsSerializable {
|
||||
public List<String> getPhotoGalleryImageURLs() {
|
||||
List<String> result = new ArrayList<String>();
|
||||
for(String imageUrl: imageURLs) {
|
||||
// FIXME consolidate with getStageImageURL, removing redundant "STAGE" code
|
||||
if(!imageUrl.contains("stage") && !imageUrl.contains("STAGE")) {
|
||||
result.add(imageUrl);
|
||||
}
|
||||
|
||||
+16
-1
@@ -50,7 +50,7 @@ public class EventBaseJsonDeserializer implements JsonDeserializer<EventBase> {
|
||||
leaderboardGroups.add(leaderboardGroupDeserializer.deserialize((JSONObject) lgJson));
|
||||
}
|
||||
}
|
||||
EventBaseImpl result = new StrippedEventImpl(name, startDate == null ? null : new MillisecondsTimePoint(startDate.longValue()),
|
||||
StrippedEventImpl result = new StrippedEventImpl(name, startDate == null ? null : new MillisecondsTimePoint(startDate.longValue()),
|
||||
endDate == null ? null : new MillisecondsTimePoint(endDate.longValue()), venue, /* is public */ true, id, leaderboardGroups);
|
||||
result.setDescription(description);
|
||||
if (officialWebsiteURLAsString != null) {
|
||||
@@ -88,6 +88,21 @@ public class EventBaseJsonDeserializer implements JsonDeserializer<EventBase> {
|
||||
throw new JsonDeserializationException("Error deserializing sponsor image URLs for event "+name, e);
|
||||
}
|
||||
}
|
||||
JSONArray imageSizes = (JSONArray) object.get(EventBaseJsonSerializer.FIELD_IMAGE_SIZES);
|
||||
if (imageSizes != null) {
|
||||
for (Object imageURLAndSizeObject : imageSizes) {
|
||||
JSONObject imageURLAndSizeJson = (JSONObject) imageURLAndSizeObject;
|
||||
try {
|
||||
result.setImageSize(
|
||||
new URL((String) imageURLAndSizeJson.get(EventBaseJsonSerializer.FIELD_IMAGE_URL)),
|
||||
new EventBaseImpl.ImageSizeImpl(
|
||||
((Number) imageURLAndSizeJson.get(EventBaseJsonSerializer.FIELD_IMAGE_WIDTH)).intValue(),
|
||||
((Number) imageURLAndSizeJson.get(EventBaseJsonSerializer.FIELD_IMAGE_HEIGHT)).intValue()));
|
||||
} catch (MalformedURLException e) {
|
||||
throw new JsonDeserializationException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
+43
@@ -1,16 +1,22 @@
|
||||
package com.sap.sailing.server.gateway.serialization.impl;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import com.sap.sailing.domain.base.EventBase;
|
||||
import com.sap.sailing.domain.base.EventBase.ImageSize;
|
||||
import com.sap.sailing.domain.base.LeaderboardGroupBase;
|
||||
import com.sap.sailing.domain.base.Venue;
|
||||
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
|
||||
|
||||
public class EventBaseJsonSerializer implements JsonSerializer<EventBase> {
|
||||
private static final Logger logger = Logger.getLogger(EventBaseJsonSerializer.class.getName());
|
||||
|
||||
public static final String FIELD_ID = "id";
|
||||
public static final String FIELD_NAME = "name";
|
||||
public static final String FIELD_DESCRIPTION = "description";
|
||||
@@ -21,6 +27,10 @@ public class EventBaseJsonSerializer implements JsonSerializer<EventBase> {
|
||||
public static final String FIELD_VIDEO_URLS = "videoURLs";
|
||||
public static final String FIELD_SPONSOR_IMAGE_URLS = "sponsorImageURLs";
|
||||
public static final String FIELD_LOGO_IMAGE_URL = "logoImageURL";
|
||||
public static final String FIELD_IMAGE_SIZES = "imageSizes";
|
||||
public static final String FIELD_IMAGE_URL = "imageURL";
|
||||
public static final String FIELD_IMAGE_WIDTH = "imageWidth";
|
||||
public static final String FIELD_IMAGE_HEIGHT = "imageHeight";
|
||||
public static final String FIELD_OFFICIAL_WEBSITE_URL = "officialWebsiteURL";
|
||||
public static final String FIELDS_LEADERBOARD_GROUPS = "leaderboardGroups";
|
||||
|
||||
@@ -50,9 +60,42 @@ public class EventBaseJsonSerializer implements JsonSerializer<EventBase> {
|
||||
for (LeaderboardGroupBase lg : event.getLeaderboardGroups()) {
|
||||
leaderboardGroups.add(leaderboardGroupBaseSerializer.serialize(lg));
|
||||
}
|
||||
JSONArray imageSizes = new JSONArray();
|
||||
result.put(FIELD_IMAGE_SIZES, imageSizes);
|
||||
for (URL imageURL : event.getImageURLs()) {
|
||||
addImageSize(imageURL, imageSizes, event);
|
||||
}
|
||||
if (event.getLogoImageURL() != null) {
|
||||
addImageSize(event.getLogoImageURL(), imageSizes, event);
|
||||
}
|
||||
for (URL sponsorImageURL : event.getSponsorImageURLs()) {
|
||||
addImageSize(sponsorImageURL, imageSizes, event);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* If <code>eventBase</code> knows the size of the image with URL <code>imageURL</code>, that size is serialized as
|
||||
* JSON object to <code>imageSizes</code>
|
||||
*/
|
||||
private void addImageSize(URL imageURL, JSONArray imageSizes, EventBase eventBase) {
|
||||
ImageSize imageSize;
|
||||
try {
|
||||
imageSize = eventBase.getImageSize(imageURL);
|
||||
if (imageSize != null) {
|
||||
JSONObject imageSizeJson = new JSONObject();
|
||||
imageSizes.add(imageSizeJson);
|
||||
imageSizeJson.put(FIELD_IMAGE_URL, imageURL.toString());
|
||||
imageSizeJson.put(FIELD_IMAGE_WIDTH, imageSize.getWidth());
|
||||
imageSizeJson.put(FIELD_IMAGE_HEIGHT, imageSize.getHeight());
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
logger.log(Level.FINE, "Couldn't retrieve image size for URL "+imageURL, e);
|
||||
} catch (ExecutionException e) {
|
||||
logger.log(Level.FINE, "Couldn't retrieve image size for URL "+imageURL, e);
|
||||
}
|
||||
}
|
||||
|
||||
private JSONArray getURLsAsStringArray(Iterable<URL> urls) {
|
||||
JSONArray jsonImageURLs = new JSONArray();
|
||||
for (URL url : urls) {
|
||||
|
||||
+6
-2
@@ -118,7 +118,9 @@ public class SearchServiceTest {
|
||||
cal.set(2014, 5, 8, 16, 00);
|
||||
final TimePoint pfingstbuschEndDate = new MillisecondsTimePoint(cal.getTime());
|
||||
pfingstbusch = server.apply(new CreateEvent("Pfingsbusch", pfingstbuschStartDate, pfingstbuschEndDate, "Kiel", /* isPublic */
|
||||
true, UUID.randomUUID(), Collections.<URL>emptySet(), Collections.<URL>emptySet(), createURLsFromString(sponsorImageURLs), (logoimageURL)AsString == null ? null : new URL(logoimageURLAsString), officialWebsiteURLAsString == null ? null : new URL(officialWebsiteURLAsString)));
|
||||
true, UUID.randomUUID(), Collections.<URL>emptySet(), Collections.<URL>emptySet(),
|
||||
/* sponsorImageURLs */ Collections.<URL>emptySet(),
|
||||
/* logoImageURLAsString */ null, /* officialWebsiteURLAsString */ null));
|
||||
kiel = pfingstbusch.getVenue();
|
||||
final CourseAreaImpl kielAlpha = new CourseAreaImpl("Alpha", UUID.randomUUID());
|
||||
kiel.addCourseArea(kielAlpha);
|
||||
@@ -149,7 +151,9 @@ public class SearchServiceTest {
|
||||
cal.set(2014, 5, 8, 18, 00);
|
||||
final TimePoint aalEndDate = new MillisecondsTimePoint(cal.getTime());
|
||||
aalEvent = server.apply(new CreateEvent("Aalregatta", aalStartDate, aalEndDate, "Flensburg", /* isPublic */
|
||||
true, UUID.randomUUID(), Collections.<URL>emptySet(), Collections.<URL>emptySet(), createURLsFromString(sponsorImageURLs), (logoimageURL)AsString == null ? null : new URL(logoimageURLAsString), officialWebsiteURLAsString == null ? null : new URL(officialWebsiteURLAsString)));
|
||||
true, UUID.randomUUID(), Collections.<URL>emptySet(), Collections.<URL>emptySet(),
|
||||
/* sponsorImageURLs */ Collections.<URL>emptySet(), /* logoimageURL */ null,
|
||||
/* officialWebsiteURLAsString */ null));
|
||||
flensburg = aalEvent.getVenue();
|
||||
final CourseAreaImpl flensburgStandard = new CourseAreaImpl("Standard", UUID.randomUUID());
|
||||
flensburg.addCourseArea(flensburgStandard);
|
||||
|
||||
Reference in new issue
Block a user