added support for image sizes on Event / EventImpl

This commit is contained in:
Axel Uhl committed 2014-07-10 09:13:25 +02:00
1 parent b6014f2ca0
commit 6440068d0c
4 files changed
+146 -3

No files matched your search

@@ -1,6 +1,9 @@
package com.sap.sailing.domain.base;
import java.awt.Dimension;
import java.net.URL;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
@@ -46,5 +49,16 @@ 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.
*/
Dimension getImageSize(URL imageURL) throws InterruptedException, ExecutionException;
}
@@ -1,12 +1,26 @@
package com.sap.sailing.domain.base.impl;
import java.awt.Dimension;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.Regatta;
@@ -22,6 +36,9 @@ public class EventImpl extends EventBaseImpl implements Event {
private ConcurrentLinkedQueue<LeaderboardGroup> leaderboardGroups;
private transient ConcurrentHashMap<URL, Future<Dimension>> 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);
}
@@ -33,6 +50,8 @@ 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 {
@@ -40,6 +59,7 @@ public class EventImpl extends EventBaseImpl implements Event {
if (leaderboardGroups == null) {
leaderboardGroups = new ConcurrentLinkedQueue<>();
}
this.imageSizeFetchers = new ConcurrentHashMap<>();
}
@Override
@@ -81,4 +101,95 @@ public class EventImpl extends EventBaseImpl implements Event {
public boolean removeLeaderboardGroup(LeaderboardGroup leaderboardGroup) {
return leaderboardGroups.remove(leaderboardGroup);
}
private Future<Dimension> getOrCreateImageSizeCalculator(final URL imageURL) {
Future<Dimension> imageSizeFetcher = imageSizeFetchers.get(imageURL);
if (imageSizeFetcher == null) {
imageSizeFetcher = executor.submit(new Callable<Dimension>() {
@Override
public Dimension call() throws IOException {
Dimension 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 Dimension(reader.getWidth(0), reader.getHeight(0));
} finally {
reader.dispose();
}
}
} finally {
if (in != null) {
in.close();
}
}
return result;
}
});
imageSizeFetchers.put(imageURL, imageSizeFetcher);
}
return imageSizeFetcher;
}
@Override
public Dimension getImageSize(URL imageURL) throws InterruptedException, ExecutionException {
Future<Dimension> imageSizeCalculator = getOrCreateImageSizeCalculator(imageURL);
return imageSizeCalculator.get();
}
@Override
public void addImageURL(URL imageURL) {
super.addImageURL(imageURL);
imageSizeFetchers.remove(imageURL);
getOrCreateImageSizeCalculator(imageURL);
}
@Override
public void removeImageURL(URL imageURL) {
super.removeImageURL(imageURL);
imageSizeFetchers.remove(imageURL);
}
@Override
public void setImageURLs(Iterable<URL> imageURLs) {
super.setImageURLs(imageURLs);
for (URL imageURL : imageURLs) {
imageSizeFetchers.remove(imageURL);
getOrCreateImageSizeCalculator(imageURL);
}
}
@Override
public void addSponsorImageURL(URL sponsorImageURL) {
super.addSponsorImageURL(sponsorImageURL);
imageSizeFetchers.remove(sponsorImageURL);
getOrCreateImageSizeCalculator(sponsorImageURL);
}
@Override
public void removeSponsorImageURL(URL sponsorImageURL) {
super.removeSponsorImageURL(sponsorImageURL);
imageSizeFetchers.remove(sponsorImageURL);
}
@Override
public void setSponsorImageURLs(Iterable<URL> sponsorImageURLs) {
super.setSponsorImageURLs(sponsorImageURLs);
for (URL imageURL : sponsorImageURLs) {
imageSizeFetchers.remove(imageURL);
getOrCreateImageSizeCalculator(imageURL);
}
}
@Override
public void setLogoImageURL(URL logoImageURL) {
super.setLogoImageURL(logoImageURL);
imageSizeFetchers.remove(logoImageURL);
getOrCreateImageSizeCalculator(logoImageURL);
}
}