reworked images and videos of event -> removed double maintenance of imageURLs, videoURLs, sponsorImageURLs -> they are now always calculated from images and videos

This commit is contained in:
fmittag committed 2015-06-14 16:21:28 +02:00
1 parent 8125b4f3d4
commit 9decf43909
12 files changed
+143 -374

No files matched your search

@@ -43,5 +43,5 @@
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-superDevMode -incremental -war &quot;${project_loc:com.sap.sailing.dashboards.gwt}&quot; -startupUrl /dashboards/RibDashboard.html -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9998 com.sap.sailing.dashboards.gwt.RibDashboard"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.dashboards.gwt"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XstartOnFirstThread -Xmx2048m"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx2048m"/>
</launchConfiguration>
@@ -185,7 +185,6 @@ import com.sap.sse.common.TimeRange;
import com.sap.sse.common.TypeBasedServiceFinder;
import com.sap.sse.common.TypeBasedServiceFinderFactory;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.Util.Triple;
import com.sap.sse.common.impl.MillisecondsDurationImpl;
import com.sap.sse.common.impl.MillisecondsTimePoint;
@@ -193,9 +192,6 @@ import com.sap.sse.common.impl.RGBColor;
import com.sap.sse.common.impl.TimeRangeImpl;
import com.sap.sse.common.media.ImageDescriptor;
import com.sap.sse.common.media.ImageDescriptorImpl;
import com.sap.sse.common.media.MediaDescriptor;
import com.sap.sse.common.media.MediaTagConstants;
import com.sap.sse.common.media.MediaUtils;
import com.sap.sse.common.media.MimeType;
import com.sap.sse.common.media.VideoDescriptor;
import com.sap.sse.common.media.VideoDescriptorImpl;
@@ -982,7 +978,10 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
try {
for (DBObject object : eventCollection.find()) {
Event event = loadEvent(object);
migrateImagesAndVideosOfEvent(event);
boolean hasMigratedSomething = loadLegacyImageAndVideoURLs(event, object);
if(hasMigratedSomething) {
new MongoObjectFactoryImpl(database).storeEvent(event);
}
result.add(event);
}
} catch (Exception e) {
@@ -1046,7 +1045,6 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
logger.severe("Error parsing official website URL "+officialWebSiteURLAsString+" for event "+name+". Ignoring this URL.");
}
}
loadLegacyImageAndVideoURLs(result, eventDBObject);
BasicDBList images = (BasicDBList) eventDBObject.get(FieldNames.EVENT_IMAGES.name());
if (images != null) {
for (Object imageObject : images) {
@@ -2134,133 +2132,55 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
return result;
}
/**
* Migrates images and videos stored as pure URLs to the new richer media format
* @param event the event to migrate
*/
@SuppressWarnings("deprecation")
private void migrateImagesAndVideosOfEvent(Event event) {
boolean changedAnything = false;
List<ImageDescriptor> newImages = new ArrayList<>();
for (URL url : event.getImageURLs()) {
if (!hasMedia(event.getImages(), url)) {
ImageDescriptor image = migrateImageURLtoImage(url, event.getStartDate());
String urlAsString = url.toString();
if (urlAsString.toLowerCase().indexOf("stage") > 0) {
image.addTag(MediaTagConstants.STAGE);
} else if (urlAsString.toLowerCase().indexOf("eventteaser") > 0) {
image.addTag(MediaTagConstants.TEASER);
}
newImages.add(image);
changedAnything = true;
}
}
for (URL url : event.getSponsorImageURLs()) {
if (!hasMedia(event.getImages(), url)) {
ImageDescriptor image = migrateImageURLtoImage(url, event.getStartDate());
image.addTag(MediaTagConstants.SPONSOR);
newImages.add(image);
changedAnything = true;
}
}
if (event.getLogoImageURL() != null && !hasMedia(event.getImages(), event.getLogoImageURL())) {
ImageDescriptor image = migrateImageURLtoImage(event.getLogoImageURL(), event.getStartDate());
image.addTag(MediaTagConstants.LOGO);
newImages.add(image);
changedAnything = true;
}
List<VideoDescriptor> newVideos = new ArrayList<VideoDescriptor>();
for (URL url : event.getVideoURLs()) {
if (!hasMedia(event.getVideos(), url)) {
MimeType mimeType = MediaUtils.detectMimeTypeFromUrl(url.toString());
VideoDescriptor video = new VideoDescriptorImpl(url, mimeType, event.getStartDate());
newVideos.add(video);
changedAnything = true;
}
}
if (changedAnything) {
for (VideoDescriptor newVideo : newVideos) {
event.addVideo(newVideo);
}
for (ImageDescriptor newImage : newImages) {
event.addImage(newImage);
}
new MongoObjectFactoryImpl(database).storeEvent(event);
}
}
/**
* Legacy code to support conversion of old image and video URLs
* @param event
* @param eventDBObject
*/
@SuppressWarnings("deprecation")
private void loadLegacyImageAndVideoURLs(Event event, DBObject eventDBObject) {
private boolean loadLegacyImageAndVideoURLs(Event event, DBObject eventDBObject) {
URL logoImageURL = null;
List<URL> imageURLs = new ArrayList<URL>();
List<URL> sponsorImageURLs = new ArrayList<URL>();
List<URL> videoURLs = new ArrayList<URL>();
String logoImageURLAsString = (String) eventDBObject.get(FieldNames.EVENT_LOGO_IMAGE_URL.name());
if (logoImageURLAsString != null) {
try {
event.setLogoImageURL(new URL(logoImageURLAsString));
logoImageURL = new URL(logoImageURLAsString);
} catch (MalformedURLException e) {
logger.severe("Error parsing logo image URL "+logoImageURLAsString+" for event "+event.getName()+". Ignoring this URL.");
}
}
BasicDBList imageURLs = (BasicDBList) eventDBObject.get(FieldNames.EVENT_IMAGE_URLS.name());
if (imageURLs != null) {
List<URL> urls = new ArrayList<>();
for (Object imageURL : imageURLs) {
BasicDBList imageURLsJson = (BasicDBList) eventDBObject.get(FieldNames.EVENT_IMAGE_URLS.name());
if (imageURLsJson != null) {
for (Object imageURL : imageURLsJson) {
try {
urls.add(new URL((String) imageURL));
imageURLs.add(new URL((String) imageURL));
} catch (MalformedURLException e) {
logger.severe("Error parsing image URL "+imageURL+" for event "+event.getName()+". Ignoring this image URL.");
}
}
event.setImageURLs(urls);
}
BasicDBList videoURLs = (BasicDBList) eventDBObject.get(FieldNames.EVENT_VIDEO_URLS.name());
if (videoURLs != null) {
List<URL> urls = new ArrayList<>();
for (Object videoURL : videoURLs) {
BasicDBList videoURLsJson = (BasicDBList) eventDBObject.get(FieldNames.EVENT_VIDEO_URLS.name());
if (videoURLsJson != null) {
for (Object videoURL : videoURLsJson) {
try {
urls.add(new URL((String) videoURL));
videoURLs.add(new URL((String) videoURL));
} catch (MalformedURLException e) {
logger.severe("Error parsing video URL "+videoURL+" for event "+event.getName()+". Ignoring this video URL.");
}
}
event.setVideoURLs(urls);
}
BasicDBList sponsorImageURLs = (BasicDBList) eventDBObject.get(FieldNames.EVENT_SPONSOR_IMAGE_URLS.name());
if (sponsorImageURLs != null) {
List<URL> urls = new ArrayList<>();
for (Object sponsorImageURL : sponsorImageURLs) {
BasicDBList sponsorImageURLsJson = (BasicDBList) eventDBObject.get(FieldNames.EVENT_SPONSOR_IMAGE_URLS.name());
if (sponsorImageURLsJson != null) {
for (Object sponsorImageURL : sponsorImageURLsJson) {
try {
urls.add(new URL((String) sponsorImageURL));
sponsorImageURLs.add(new URL((String) sponsorImageURL));
} catch (MalformedURLException e) {
logger.severe("Error parsing sponsor image URL "+sponsorImageURL+" for event "+event.getName()+". Ignoring this sponsor image URL.");
}
}
event.setSponsorImageURLs(urls);
}
}
private ImageDescriptor migrateImageURLtoImage(URL url, TimePoint createdAt) {
ImageDescriptorImpl image = new ImageDescriptorImpl(url, createdAt);
Pair<Integer, Integer> imageDimensions = MediaUtils.getImageDimensions(url);
if (imageDimensions != null) {
image.setSize(imageDimensions);
}
return image;
}
private boolean hasMedia(Iterable<? extends MediaDescriptor> media, URL url) {
for (MediaDescriptor mediaEntry : media) {
if (url.equals(mediaEntry.getURL())) {
return true;
}
}
return false;
return event.setMediaURLs(imageURLs, sponsorImageURLs, videoURLs, logoImageURL);
}
}
@@ -1,13 +1,11 @@
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.sse.common.Named;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.WithID;
import com.sap.sse.common.media.ImageSize;
import com.sap.sse.common.media.WithMedia;
/**
@@ -50,17 +48,6 @@ public interface EventBase extends Named, WithDescription, Renamable, WithID, Wi
*/
Iterable<URL> getImageURLs();
/**
* @deprecated
* Replaces the {@link #getImageURLs() current contents of the image URL sequence} by the image URLs in
* <code>imageURLs</code>.
*
* @param imageURLs
* if <code>null</code>, the internal sequence of image URLs is cleared but remains valid (non-
* <code>null</code>)
*/
void setImageURLs(Iterable<URL> imageURLs);
/**
* @deprecated
* An event may have zero or more sponsors, each of which usually want to see their logo on the web page.
@@ -69,28 +56,12 @@ public interface EventBase extends Named, WithDescription, Renamable, WithID, Wi
*/
Iterable<URL> getSponsorImageURLs();
/**
* @deprecated
* Replaces the {@link #getSponsorImageURLs() current contents of the sponsorship image URL sequence} by the image URLs in
* <code>sponsorImageURLs</code>.
*
* @param sponsorImageURLs
* if <code>null</code>, the internal sequence of sponsorship image URLs is cleared but remains valid (non-
* <code>null</code>)
*/
void setSponsorImageURLs(Iterable<URL> sponsorImageURLs);
/**
* @deprecated
* An optional logo image; may return <code>null</code>.
*/
URL getLogoImageURL();
/**
* @deprecated
*/
void setLogoImageURL(URL logoImageURL);
/**
* @deprecated
* Returns a non-<code>null</code> live but unmodifiable collection of URLs pointing to video resources that can be
@@ -100,17 +71,6 @@ public interface EventBase extends Named, WithDescription, Renamable, WithID, Wi
*/
Iterable<URL> getVideoURLs();
/**
* @deprecated
* Replaces the {@link #getVideoURLs() current contents of the video URL sequence} by the video URLs in
* <code>videoURLs</code>.
*
* @param videoURLs
* if <code>null</code>, the internal sequence of image URLs is cleared but remains valid (non-
* <code>null</code>)
*/
void setVideoURLs(Iterable<URL> videoURLs);
/**
* @return the URL of the event's official web site, or <code>null</code> if such a site does not exist or its URL
* is not known
@@ -121,9 +81,8 @@ public interface EventBase extends Named, WithDescription, Renamable, WithID, Wi
Iterable<? extends LeaderboardGroupBase> getLeaderboardGroups();
/**
* 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;
/**
* Sets and converts all event images and videos from the old URL based format to the new richer format
* */
boolean setMediaURLs(Iterable<URL> imageURLs, Iterable<URL> sponsorImageURLs, Iterable<URL> videoURLs, URL logoImageURL);
}
@@ -13,9 +13,15 @@ import com.sap.sailing.domain.base.EventBase;
import com.sap.sailing.domain.base.Venue;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.media.ImageDescriptor;
import com.sap.sse.common.media.ImageDescriptorImpl;
import com.sap.sse.common.media.MediaDescriptor;
import com.sap.sse.common.media.MediaTagConstants;
import com.sap.sse.common.media.MediaUtils;
import com.sap.sse.common.media.MimeType;
import com.sap.sse.common.media.VideoDescriptor;
import com.sap.sse.common.media.VideoDescriptorImpl;
public abstract class EventBaseImpl implements EventBase {
private static final long serialVersionUID = -5749964088848611074L;
@@ -27,10 +33,6 @@ public abstract class EventBaseImpl implements EventBase {
private final UUID id;
private TimePoint startDate;
private TimePoint endDate;
private ConcurrentLinkedQueue<URL> imageURLs;
private ConcurrentLinkedQueue<URL> videoURLs;
private ConcurrentLinkedQueue<URL> sponsorImageURLs;
private URL logoImageURL;
private URL officialWebsiteURL;
private ConcurrentLinkedQueue<ImageDescriptor> images;
private ConcurrentLinkedQueue<VideoDescriptor> videos;
@@ -50,25 +52,12 @@ public abstract class EventBaseImpl implements EventBase {
this.endDate = endDate;
this.venue = venue;
this.isPublic = isPublic;
this.imageURLs = new ConcurrentLinkedQueue<URL>();
this.videoURLs = new ConcurrentLinkedQueue<URL>();
this.sponsorImageURLs = new ConcurrentLinkedQueue<URL>();
this.images = new ConcurrentLinkedQueue<ImageDescriptor>();
this.videos = new ConcurrentLinkedQueue<VideoDescriptor>();
syncImageAndVideoURLsForBackwardCompatibility();
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject();
if (imageURLs == null) {
imageURLs = new ConcurrentLinkedQueue<URL>();
}
if (videoURLs == null) {
videoURLs = new ConcurrentLinkedQueue<URL>();
}
if (sponsorImageURLs == null) {
sponsorImageURLs = new ConcurrentLinkedQueue<URL>();
}
if (images == null) {
images = new ConcurrentLinkedQueue<ImageDescriptor>();
}
@@ -144,51 +133,41 @@ public abstract class EventBaseImpl implements EventBase {
@Override
public Iterable<URL> getImageURLs() {
return Collections.unmodifiableCollection(imageURLs);
List<URL> result = new ArrayList<URL>();
for (ImageDescriptor image : images) {
if (Util.size(image.getTags()) == 0 || image.hasTag(MediaTagConstants.GALLERY)) {
result.add(image.getURL());
}
}
return result;
}
@Override
public void setImageURLs(Iterable<URL> imageURLs) {
this.imageURLs.clear();
if (imageURLs != null) {
Util.addAll(imageURLs, this.imageURLs);
}
}
@Override
public Iterable<URL> getVideoURLs() {
return Collections.unmodifiableCollection(videoURLs);
}
@Override
public void setVideoURLs(Iterable<URL> videoURLs) {
this.videoURLs.clear();
if (videoURLs != null) {
Util.addAll(videoURLs, this.videoURLs);
List<URL> result = new ArrayList<URL>();
for(VideoDescriptor video: videos) {
result.add(video.getURL());
}
return result;
}
@Override
public Iterable<URL> getSponsorImageURLs() {
return Collections.unmodifiableCollection(sponsorImageURLs);
List<URL> result = new ArrayList<URL>();
for(MediaDescriptor media : findMediaWithTag(images, MediaTagConstants.SPONSOR)) {
result.add(media.getURL());
}
return result;
}
@Override
public void setSponsorImageURLs(Iterable<URL> sponsorImageURLs) {
this.sponsorImageURLs.clear();
if (sponsorImageURLs != null) {
Util.addAll(sponsorImageURLs, this.sponsorImageURLs);
}
}
@Override
public URL getLogoImageURL() {
return logoImageURL;
}
@Override
public void setLogoImageURL(URL logoImageURL) {
this.logoImageURL = logoImageURL;
URL result = null;
List<ImageDescriptor> media = findMediaWithTag(images, MediaTagConstants.LOGO);
if(media.size() > 0) {
result = media.get(0).getURL();
}
return result;
}
@Override
@@ -210,14 +189,12 @@ public abstract class EventBaseImpl implements EventBase {
public void addImage(ImageDescriptor image) {
if (!images.contains(image)) {
images.add(image);
syncImageURLsFromImagesForBackwardCompatibility();
}
}
@Override
public void removeImage(ImageDescriptor image) {
images.remove(image);
syncImageURLsFromImagesForBackwardCompatibility();
}
@Override
@@ -225,7 +202,6 @@ public abstract class EventBaseImpl implements EventBase {
this.images.clear();
if (images != null) {
Util.addAll(images, this.images);
syncImageURLsFromImagesForBackwardCompatibility();
}
}
@@ -238,14 +214,12 @@ public abstract class EventBaseImpl implements EventBase {
public void addVideo(VideoDescriptor video) {
if (!videos.contains(video)) {
videos.add(video);
syncVideoURLsFromVideosForBackwardCompatibility();
}
}
@Override
public void removeVideo(VideoDescriptor video) {
videos.remove(video);
syncVideoURLsFromVideosForBackwardCompatibility();
}
@Override
@@ -253,38 +227,81 @@ public abstract class EventBaseImpl implements EventBase {
this.videos.clear();
if (videos != null) {
Util.addAll(videos, this.videos);
syncVideoURLsFromVideosForBackwardCompatibility();
}
}
private void syncImageURLsFromImagesForBackwardCompatibility() {
List<URL> imageURLs = new ArrayList<>();
List<URL> sponsorImageURLs = new ArrayList<>();
URL logoImageURL = null;
for (ImageDescriptor image : images) {
if (image.hasTag(MediaTagConstants.SPONSOR)) {
sponsorImageURLs.add(image.getURL());
} else if (image.hasTag(MediaTagConstants.LOGO)) {
logoImageURL = image.getURL();
} else {
imageURLs.add(image.getURL());
private <T extends MediaDescriptor> List<T> findMediaWithTag(Iterable<T> media, String tagName) {
List<T> result = new ArrayList<>();
for (T mediaEntry : media) {
if(mediaEntry.hasTag(tagName)) {
result.add(mediaEntry);
}
}
setImageURLs(imageURLs);
setSponsorImageURLs(sponsorImageURLs);
setLogoImageURL(logoImageURL);
return result;
}
private void syncVideoURLsFromVideosForBackwardCompatibility() {
List<URL> videoURLs = new ArrayList<>();
for (VideoDescriptor video : videos) {
videoURLs.add(video.getURL());
/** Sets and converts all event images and videos from the old URL based format to the new richer format */
public boolean setMediaURLs(Iterable<URL> imageURLs, Iterable<URL> sponsorImageURLs, Iterable<URL> videoURLs, URL logoImageURL) {
boolean changed = false;
for (URL url : imageURLs) {
if (!hasMedia(images, url)) {
ImageDescriptor image = migrateImageURLtoImage(url, getStartDate());
String urlAsString = url.toString();
if (urlAsString.toLowerCase().indexOf("stage") > 0) {
image.addTag(MediaTagConstants.STAGE);
} else if (urlAsString.toLowerCase().indexOf("eventteaser") > 0) {
image.addTag(MediaTagConstants.TEASER);
} else {
image.addTag(MediaTagConstants.GALLERY);
}
addImage(image);
changed = true;
}
}
setVideoURLs(videoURLs);
for (URL url : sponsorImageURLs) {
if (!hasMedia(images, url)) {
ImageDescriptor image = migrateImageURLtoImage(url, getStartDate());
image.addTag(MediaTagConstants.SPONSOR);
addImage(image);
changed = true;
}
}
if (logoImageURL != null && !hasMedia(images, logoImageURL)) {
ImageDescriptor image = migrateImageURLtoImage(logoImageURL, getStartDate());
image.addTag(MediaTagConstants.LOGO);
addImage(image);
changed = true;
}
for (URL url : videoURLs) {
if (!hasMedia(videos, url)) {
MimeType mimeType = MediaUtils.detectMimeTypeFromUrl(url.toString());
VideoDescriptor video = new VideoDescriptorImpl(url, mimeType, getStartDate());
addVideo(video);
changed = true;
}
}
return changed;
}
private void syncImageAndVideoURLsForBackwardCompatibility() {
syncImageURLsFromImagesForBackwardCompatibility();
syncVideoURLsFromVideosForBackwardCompatibility();
private ImageDescriptor migrateImageURLtoImage(URL url, TimePoint createdAt) {
ImageDescriptorImpl image = new ImageDescriptorImpl(url, createdAt);
Pair<Integer, Integer> imageDimensions = MediaUtils.getImageDimensions(url);
if (imageDimensions != null) {
image.setSize(imageDimensions);
}
return image;
}
private boolean hasMedia(Iterable<? extends MediaDescriptor> media, URL url) {
for (MediaDescriptor mediaEntry : media) {
if (url.equals(mediaEntry.getURL())) {
return true;
}
}
return false;
}
}
@@ -1,16 +1,11 @@
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;
import com.sap.sailing.domain.base.Venue;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.media.ImageSize;
/**
* A simplified implementation of the {@link EventBase} interface which maintains an immutable collection of
@@ -23,7 +18,6 @@ import com.sap.sse.common.media.ImageSize;
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) {
@@ -34,20 +28,10 @@ public class StrippedEventImpl extends EventBaseImpl {
boolean isPublic, UUID id, Iterable<LeaderboardGroupBase> leaderboardGroups) {
super(name, startDate, endDate, venue, isPublic, id);
this.leaderboardGroups = leaderboardGroups;
this.imageSizes = new HashMap<URL, 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,13 +1,8 @@
package com.sap.sailing.domain.base;
import java.net.URL;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
import com.sap.sse.common.media.ImageDescriptor;
import com.sap.sse.common.media.ImageSize;
import com.sap.sse.common.media.MediaUtils;
/**
* An event is a group of {@link Regatta regattas} carried out at a common venue within a common time frame. For
@@ -51,19 +46,4 @@ public interface Event extends EventBase {
* leaderboard groups in <code>leaderboardGroups</code>.
*/
void setLeaderboardGroups(Iterable<LeaderboardGroup> leaderboardGroups);
/**
* For the images references by the image URLs in {@link #getImageURLs()}, {@link #getSponsorImageURLs()} and {@link #getLogoImageURL()}
* determines the image dimensions. The retrieval of the image size is started when the URL is added to this event, and the result is
* cached. Should the image change its size afterwards or change its availability status, this event won't notice unless the image is
* removed from this event and added again.<p>
*
* 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.
*
* @deprecated Use {@link MediaUtils#getImageDimensions(URL)} or simply use the dimensions given by {@link ImageDescriptor}
*/
@Deprecated
ImageSize getImageSize(URL imageURL) throws InterruptedException, ExecutionException;
}
@@ -34,15 +34,11 @@ import com.sap.sse.common.media.ImageSize;
public class EventImpl extends EventBaseImpl implements Event {
private static final long serialVersionUID = 855135446595485715L;
private static final Logger logger = Logger.getLogger(EventImpl.class.getName());
private final Set<Regatta> regattas;
private ConcurrentLinkedQueue<LeaderboardGroup> leaderboardGroups;
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) {
this(name, startDate, endDate, new VenueImpl(venueName), isPublic, id);
}
@@ -54,8 +50,6 @@ public class EventImpl extends EventBaseImpl implements Event {
super(name, startDate, endDate, venue, isPublic, id);
this.regattas = new HashSet<Regatta>();
this.leaderboardGroups = new ConcurrentLinkedQueue<>();
this.imageSizeFetchers = new ConcurrentHashMap<>();
this.executor = Executors.newCachedThreadPool();
}
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
@@ -63,8 +57,6 @@ public class EventImpl extends EventBaseImpl implements Event {
if (leaderboardGroups == null) {
leaderboardGroups = new ConcurrentLinkedQueue<>();
}
this.imageSizeFetchers = new ConcurrentHashMap<>();
this.executor = Executors.newCachedThreadPool();
}
@Override
@@ -106,86 +98,4 @@ public class EventImpl extends EventBaseImpl implements Event {
public boolean removeLeaderboardGroup(LeaderboardGroup leaderboardGroup) {
return leaderboardGroups.remove(leaderboardGroup);
}
private Future<ImageSize> getOrCreateImageSizeCalculator(final URL imageURL) {
Future<ImageSize> imageSizeFetcher = imageSizeFetchers.get(imageURL);
if (imageSizeFetcher == null) {
imageSizeFetcher = executor.submit(new Callable<ImageSize>() {
@Override
public ImageSize call() throws IOException {
ImageSize result = null;
ImageInputStream in = null;
try {
URLConnection conn = imageURL.openConnection();
in = ImageIO.createImageInputStream(conn.getInputStream());
final Iterator<ImageReader> readers = ImageIO.getImageReaders(in);
if (readers.hasNext()) {
ImageReader reader = readers.next();
try {
reader.setInput(in);
result = new ImageSizeImpl(reader.getWidth(0), reader.getHeight(0));
} finally {
reader.dispose();
}
}
} catch (IOException ioe) {
logger.log(Level.SEVERE, "Stale image link "+imageURL+" for event "+getName()+". Please double-check and replace or remove.", ioe);
throw ioe;
} finally {
if (in != null) {
in.close();
}
}
return result;
}
});
imageSizeFetchers.put(imageURL, imageSizeFetcher);
}
return imageSizeFetcher;
}
@Override
public ImageSize getImageSize(URL imageURL) throws InterruptedException, ExecutionException {
Future<ImageSize> imageSizeCalculator = getOrCreateImageSizeCalculator(imageURL);
return imageSizeCalculator.get();
}
private void refreshImageSizeFetcher(URL imageURL) {
if (imageURL != null) {
removeImageSizeFetcher(imageURL);
getOrCreateImageSizeCalculator(imageURL);
}
}
private void removeImageSizeFetcher(URL imageURL) {
if (imageURL != null) {
imageSizeFetchers.remove(imageURL);
}
}
@Override
public void setImageURLs(Iterable<URL> imageURLs) {
super.setImageURLs(imageURLs);
if (imageURLs != null) {
for (URL imageURL : imageURLs) {
refreshImageSizeFetcher(imageURL);
}
}
}
@Override
public void setSponsorImageURLs(Iterable<URL> sponsorImageURLs) {
super.setSponsorImageURLs(sponsorImageURLs);
if (sponsorImageURLs != null) {
for (URL imageURL : sponsorImageURLs) {
refreshImageSizeFetcher(imageURL);
}
}
}
@Override
public void setLogoImageURL(URL logoImageURL) {
super.setLogoImageURL(logoImageURL);
refreshImageSizeFetcher(logoImageURL);
}
}
@@ -75,11 +75,11 @@ public class ImagesListComposite extends Composite {
imagesControlsPanel.setSpacing(5);
panel.add(imagesControlsPanel);
Button addPhotoBtn = new Button("Add photo");
Button addPhotoBtn = new Button("Add gallery photo");
addPhotoBtn.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
openCreateImageDialog(null);
openCreateImageDialog(MediaTagConstants.GALLERY);
}
});
imagesControlsPanel.add(addPhotoBtn);
@@ -10,7 +10,8 @@ import com.sap.sse.common.media.MimeType;
public final class MediaConstants {
public static final List<String> imageTagSuggestions = Arrays.asList(new String[] { MediaTagConstants.STAGE, MediaTagConstants.TEASER, MediaTagConstants.SPONSOR, MediaTagConstants.LOGO });
public static final List<String> imageTagSuggestions = Arrays.asList(new String[] { MediaTagConstants.STAGE, MediaTagConstants.TEASER,
MediaTagConstants.SPONSOR, MediaTagConstants.LOGO, MediaTagConstants.GALLERY });
public static final List<String> videoTagSuggestions = Arrays.asList(new String[] { MediaTagConstants.LIVESTREAM, MediaTagConstants.HIGHLIGHT,MediaTagConstants.FEATURED });
public static final Set<MimeType> SUPPORTED_VIDEO_TYPES = new HashSet<>(Arrays.asList(MimeType.youtube, MimeType.vimeo, MimeType.mp4));
@@ -92,6 +92,7 @@ import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.common.media.ImageDescriptor;
import com.sap.sse.common.media.ImageDescriptorImpl;
import com.sap.sse.common.media.MediaTagConstants;
import com.sap.sse.common.media.MimeType;
import com.sap.sse.common.media.VideoDescriptor;
import com.sap.sse.common.media.VideoDescriptorImpl;
@@ -340,11 +341,12 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest
Event event = new EventImpl(eventName, eventStartDate, eventEndDate, venue, /*isPublic*/ true, UUID.randomUUID());
ImageDescriptor image1 = new ImageDescriptorImpl(imageURL, createdAt);
image1.addTag(MediaTagConstants.GALLERY);
event.addImage(image1);
ImageDescriptor image2 = new ImageDescriptorImpl(sponsorImageURL, createdAt);
event.addImage(image2);
image2.addTag("Sponsor");
image2.addTag(MediaTagConstants.SPONSOR);
VideoDescriptor video1 = new VideoDescriptorImpl(videoURL, MimeType.mp4, createdAt);
event.addVideo(video1);
@@ -354,9 +356,9 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest
DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE);
final Event loadedEvent = dof.loadEvent(eventName);
assertEquals(2, Util.size(loadedEvent.getImages()));
assertEquals(1, Util.size(loadedEvent.getVideos()));
assertEquals(1, Util.size(loadedEvent.getImageURLs()));
assertEquals(1, Util.size(loadedEvent.getSponsorImageURLs()));
assertEquals(1, Util.size(loadedEvent.getVideos()));
assertEquals(1, Util.size(loadedEvent.getVideoURLs()));
}
@@ -22,12 +22,10 @@ import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
import com.sap.sailing.server.gateway.serialization.impl.EventBaseJsonSerializer;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.common.media.ImageDescriptor;
import com.sap.sse.common.media.ImageDescriptorImpl;
import com.sap.sse.common.media.ImageSize;
import com.sap.sse.common.media.MediaUtils;
import com.sap.sse.common.media.MimeType;
import com.sap.sse.common.media.VideoDescriptor;
import com.sap.sse.common.media.VideoDescriptorImpl;
@@ -99,31 +97,36 @@ public class EventBaseJsonDeserializer implements JsonDeserializer<EventBase> {
}
private void readImageAndVideoURLsFromLegacyServer(JSONObject eventJson, StrippedEventImpl event) throws JsonDeserializationException {
URL logoImageURL = null;
List<URL> imageURLs = new ArrayList<URL>();
List<URL> sponsorImageURLs = new ArrayList<URL>();
List<URL> videoURLs = new ArrayList<URL>();
String logoImageURLAsString = (String) eventJson.get(EventBaseJsonSerializer.FIELD_LOGO_IMAGE_URL);
if (logoImageURLAsString != null) {
try {
event.setLogoImageURL(new URL(logoImageURLAsString));
logoImageURL = new URL(logoImageURLAsString);
} catch (MalformedURLException e) {
throw new JsonDeserializationException("Error deserializing logo image URL for event "+event.getName(), e);
}
}
if (eventJson.get(EventBaseJsonSerializer.FIELD_IMAGE_URLS) != null) {
try {
event.setImageURLs(getURLsFromStrings(Helpers.getNestedArraySafe(eventJson, EventBaseJsonSerializer.FIELD_IMAGE_URLS)));
imageURLs = getURLsFromStrings(Helpers.getNestedArraySafe(eventJson, EventBaseJsonSerializer.FIELD_IMAGE_URLS));
} catch (MalformedURLException e) {
throw new JsonDeserializationException("Error deserializing image URLs for event "+event.getName(), e);
}
}
if (eventJson.get(EventBaseJsonSerializer.FIELD_VIDEO_URLS) != null) {
try {
event.setVideoURLs(getURLsFromStrings(Helpers.getNestedArraySafe(eventJson, EventBaseJsonSerializer.FIELD_VIDEO_URLS)));
videoURLs = getURLsFromStrings(Helpers.getNestedArraySafe(eventJson, EventBaseJsonSerializer.FIELD_VIDEO_URLS));
} catch (MalformedURLException e) {
throw new JsonDeserializationException("Error deserializing video URLs for event "+event.getName(), e);
}
}
if (eventJson.get(EventBaseJsonSerializer.FIELD_SPONSOR_IMAGE_URLS) != null) {
try {
event.setSponsorImageURLs(getURLsFromStrings(Helpers.getNestedArraySafe(eventJson, EventBaseJsonSerializer.FIELD_SPONSOR_IMAGE_URLS)));
sponsorImageURLs = getURLsFromStrings(Helpers.getNestedArraySafe(eventJson, EventBaseJsonSerializer.FIELD_SPONSOR_IMAGE_URLS));
} catch (MalformedURLException e) {
throw new JsonDeserializationException("Error deserializing sponsor image URLs for event "+event.getName(), e);
}
@@ -145,6 +148,7 @@ public class EventBaseJsonDeserializer implements JsonDeserializer<EventBase> {
}
}
}
event.setMediaURLs(imageURLs, sponsorImageURLs, videoURLs, logoImageURL);
}
private ImageDescriptor loadImage(JSONObject imageJson) {
@@ -214,16 +218,7 @@ public class EventBaseJsonDeserializer implements JsonDeserializer<EventBase> {
return video;
}
private ImageDescriptor migrateImageURLtoImage(URL url, TimePoint createdAt, ImageSize size) {
ImageDescriptorImpl image = new ImageDescriptorImpl(url, createdAt);
Pair<Integer, Integer> imageDimensions = MediaUtils.getImageDimensions(url);
if (imageDimensions != null) {
image.setSize(imageDimensions);
}
return image;
}
private Iterable<URL> getURLsFromStrings(JSONArray strings) throws MalformedURLException {
private List<URL> getURLsFromStrings(JSONArray strings) throws MalformedURLException {
List<URL> result = new ArrayList<URL>();
if (strings != null) {
for (Object string : strings) {
@@ -1,6 +1,7 @@
package com.sap.sse.common.media;
public interface MediaTagConstants {
static final String GALLERY = "Gallery";
static final String STAGE = "Stage";
static final String LOGO = "Logo";
static final String TEASER = "Teaser";