/*
* Copyright (c) 2005 Aetrion LLC.
*/
package com.googlecode.flickrjandroid.photos;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.Locale;
import com.googlecode.flickrjandroid.FlickrException;
import com.googlecode.flickrjandroid.people.User;
import com.googlecode.flickrjandroid.tags.Tag;
/**
* Class representing metadata about a Flickr photo. Instances do not actually contain the photo data, however you can obtain the photo data by calling {@link PhotosInterface#getImage(Photo, int)} or
* {@link PhotosInterface#getImageAsStream(Photo, int)}.
*
* @author Anthony Eden
* @version $Id: Photo.java,v 1.28 2009/07/23 21:49:35 x-mago Exp $
*/
public class Photo {
public static final long serialVersionUID = 12L;
private static final ThreadLocal<DateFormat> DATE_FORMATS = new ThreadLocal<DateFormat>() {
protected synchronized DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
}
};
private static final String DEFAULT_ORIGINAL_IMAGE_SUFFIX = "_o.jpg";
private static final String SMALL_SQUARE_IMAGE_SUFFIX = "_s.jpg";
private static final String SMALL_IMAGE_SUFFIX = "_m.jpg";
private static final String THUMBNAIL_IMAGE_SUFFIX = "_t.jpg";
private static final String MEDIUM_IMAGE_SUFFIX = ".jpg";
private static final String LARGE_IMAGE_SUFFIX = "_b.jpg";
private static final String LARGE_SQUARE_IMAGE_SUFFIX = "_q.jpg";
private Size squareSize;
private Size smallSize;
private Size thumbnailSize;
private Size mediumSize;
private Size largeSize;
private Size originalSize;
private Size largeSquareSize;
private String id;
private User owner;
private String secret;
private String farm;
private String server;
private boolean favorite;
private String license;
private boolean primary;
private String title;
private String description;
private boolean publicFlag;
private boolean friendFlag;
private boolean familyFlag;
private Date dateAdded;
private Date datePosted;
private Date dateTaken;
private Date lastUpdate;
private String takenGranularity;
private Permissions permissions;
private Editability editability;
private int comments = -1;
private int views = -1;
private int favorites = -1;
private int rotation;
private Collection<Note> notes;
private Collection<Tag> tags;
private Collection<String> machineTags;
private Collection<PhotoUrl> urls;
private String iconServer;
private String iconFarm;
private String url;
private GeoData geoData;
private String originalFormat;
private String originalSecret;
private String placeId;
private String media;
private String mediaStatus;
private String pathAlias;
private int originalWidth;
private int originalHeight;
public Photo() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public User getOwner() {
return owner;
}
public void setOwner(User owner) {
this.owner = owner;
}
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public String getFarm() {
return farm;
}
public void setFarm(String farm) {
this.farm = farm;
}
public String getServer() {
return server;
}
public void setServer(String server) {
this.server = server;
}
public boolean isFavorite() {
return favorite;
}
public void setFavorite(boolean favorite) {
this.favorite = favorite;
}
public String getLicense() {
return license;
}
public void setLicense(String license) {
this.license = license;
}
public boolean isPrimary() {
return primary;
}
public void setPrimary(boolean primary) {
this.primary = primary;
}
public void setPrimary(String primary) {
setPrimary("1".equals(primary));
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isPublicFlag() {
return publicFlag;
}
public void setPublicFlag(boolean publicFlag) {
this.publicFlag = publicFlag;
}
public boolean isFriendFlag() {
return friendFlag;
}
public void setFriendFlag(boolean friendFlag) {
this.friendFlag = friendFlag;
}
public boolean isFamilyFlag() {
return familyFlag;
}
public void setFamilyFlag(boolean familyFlag) {
this.familyFlag = familyFlag;
}
public Date getDateAdded() {
return dateAdded;
}
public void setDateAdded(Date dateAdded) {
this.dateAdded = dateAdded;
}
public void setDateAdded(long dateAdded) {
setDateAdded(new Date(dateAdded));
}
public void setDateAdded(String dateAdded) {
if (dateAdded == null || "".equals(dateAdded))
return;
setDateAdded(Long.parseLong(dateAdded) * (long) 1000);
}
public Date getDatePosted() {
return datePosted;
}
public void setDatePosted(Date datePosted) {
this.datePosted = datePosted;
}
public void setDatePosted(long datePosted) {
setDatePosted(new Date(datePosted));
}
public void setDatePosted(String datePosted) {
if (datePosted == null || "".equals(datePosted))
return;
setDatePosted(Long.parseLong(datePosted) * (long) 1000);
}
public Date getDateTaken() {
return dateTaken;
}
public void setDateTaken(Date dateTaken) {
this.dateTaken = dateTaken;
}
public void setDateTaken(String dateTaken) {
if (dateTaken == null || "".equals(dateTaken))
return;
try {
setDateTaken(((DateFormat) DATE_FORMATS.get()).parse(dateTaken));
} catch (ParseException e) {
// TODO: figure out what to do with this error
e.printStackTrace();
}
}
public Date getLastUpdate() {
return lastUpdate;
}
public void setLastUpdate(Date lastUpdate) {
this.lastUpdate = lastUpdate;
}
public void setLastUpdate(String lastUpdateStr) {
if (lastUpdateStr == null || "".equals(lastUpdateStr))
return;
long unixTime = Long.parseLong(lastUpdateStr);
setLastUpdate(new Date(unixTime * 1000L));
}
public String getTakenGranularity() {
return takenGranularity;
}
public void setTakenGranularity(String takenGranularity) {
this.takenGranularity = takenGranularity;
}
public Permissions getPermissions() {
return permissions;
}
public void setPermissions(Permissions permissions) {
this.permissions = permissions;
}
public Editability getEditability() {
return editability;
}
public void setEditability(Editability editability) {
this.editability = editability;
}
public int getComments() {
return comments;
}
public void setComments(int comments) {
this.comments = comments;
}
public void setComments(String comments) {
if (comments != null)
setComments(Integer.parseInt(comments));
}
public Collection<Note> getNotes() {
return notes;
}
public void setNotes(Collection<Note> notes) {
this.notes = notes;
}
public Collection<Tag> getTags() {
return tags;
}
public void setTags(Collection<Tag> tags) {
this.tags = tags;
}
public void setMachineTags(Collection<String> machineTags) {
this.machineTags = machineTags;
}
public Collection<String> getMachineTags() {
return machineTags;
}
/**
*
* @return List of {@link PhotoUrl}
*/
public Collection<PhotoUrl> getUrls() {
return urls;
}
/**
*
* @param urls
* List of {@link PhotoUrl}
*/
public void setUrls(Collection<PhotoUrl> urls) {
this.urls = urls;
}
/**
* Sets the number of views for this Photo. For un-authenticated calls this value is not available and will be set to -1.
*
* @param views
*/
public void setViews(String views) {
if (views != null) {
try {
setViews(Integer.parseInt(views));
} catch (NumberFormatException e) {
setViews(-1);
}
}
}
/**
*
* @param views
*/
public void setViews(int views) {
this.views = views;
}
/**
* Number of views. Set to -1 if the value is not available.
*
* @return Number of views
*/
public int getViews() {
return views;
}
/**
* @return the favorites
*/
public int getFavorites() {
return favorites;
}
/**
* @param favorites
* the favorites to set
*/
public void setFavorites(int favorites) {
this.favorites = favorites;
}
/**
* Set the degrees of rotation. Value will be set to -1, if not available.
*
* @param rotation
*/
public void setRotation(String rotation) {
if (rotation != null) {
try {
setRotation(Integer.parseInt(rotation));
} catch (NumberFormatException e) {
setRotation(-1);
}
}
}
public void setRotation(int rotation) {
this.rotation = rotation;
}
public int getRotation() {
return rotation;
}
public String getIconServer() {
return iconServer;
}
public void setIconServer(String iconServer) {
this.iconServer = iconServer;
}
public String getIconFarm() {
return iconFarm;
}
public void setIconFarm(String iconFarm) {
this.iconFarm = iconFarm;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public GeoData getGeoData() {
return geoData;
}
public void setGeoData(GeoData geoData) {
this.geoData = geoData;
}
public boolean hasGeoData() {
return geoData != null;
}
public String getOriginalFormat() {
return originalFormat;
}
public void setOriginalFormat(String originalFormat) {
this.originalFormat = originalFormat;
}
public String getOriginalSecret() {
return originalSecret;
}
public void setOriginalSecret(String originalSecret) {
this.originalSecret = originalSecret;
}
/**
* Get an InputStream for the original image. Callers must close the stream upon completion.
*
* @deprecated
* @see PhotosInterface#getImageAsStream(Photo, int)
* @return The InputStream
* @throws IOException
*/
public InputStream getOriginalAsStream() throws IOException, FlickrException {
if (originalFormat != null) {
return getOriginalImageAsStream("_o." + originalFormat);
}
return getOriginalImageAsStream(DEFAULT_ORIGINAL_IMAGE_SUFFIX);
}
/**
* Get the original image URL.
*
* @return The original image URL
*/
public String getOriginalUrl() throws FlickrException {
if (originalSize == null) {
if (originalFormat != null) {
return getOriginalBaseImageUrl() + "_o." + originalFormat;
}
return getOriginalBaseImageUrl() + DEFAULT_ORIGINAL_IMAGE_SUFFIX;
} else {
return originalSize.getSource();
}
}
/**
* @deprecated
* @see PhotosInterface#getImageAsStream(Photo, int)
* @return The InputStream
* @throws IOException
*/
public InputStream getSmallSquareAsInputStream() throws IOException {
return getImageAsStream(SMALL_SQUARE_IMAGE_SUFFIX);
}
public String getSmallSquareUrl() {
if (squareSize == null) {
return getBaseImageUrl() + SMALL_SQUARE_IMAGE_SUFFIX;
} else {
return squareSize.getSource();
}
}
public String getLargeSquareUrl() {
if (largeSquareSize == null) {
return getBaseImageUrl() + LARGE_SQUARE_IMAGE_SUFFIX;
} else {
return largeSquareSize.getSource();
}
}
/**
* @deprecated
* @see PhotosInterface#getImageAsStream(Photo, int)
* @return The InputStream
* @throws IOException
*/
public InputStream getThumbnailAsInputStream() throws IOException {
return getImageAsStream(THUMBNAIL_IMAGE_SUFFIX);
}
public String getThumbnailUrl() {
if (thumbnailSize == null) {
return getBaseImageUrl() + THUMBNAIL_IMAGE_SUFFIX;
} else {
return thumbnailSize.getSource();
}
}
/**
* @deprecated
* @see PhotosInterface#getImageAsStream(Photo, int)
* @return The InputStream
* @throws IOException
*/
public InputStream getSmallAsInputStream() throws IOException {
return getImageAsStream(SMALL_IMAGE_SUFFIX);
}
public String getSmallUrl() {
if (smallSize == null) {
return getBaseImageUrl() + SMALL_IMAGE_SUFFIX;
} else {
return smallSize.getSource();
}
}
/**
* @deprecated
* @see PhotosInterface#getImageAsStream(Photo, int)
* @return The InputStream
* @throws IOException
*/
public InputStream getMediumAsStream() throws IOException {
return getImageAsStream(MEDIUM_IMAGE_SUFFIX);
}
public String getMediumUrl() {
if (mediumSize == null) {
return getBaseImageUrl() + MEDIUM_IMAGE_SUFFIX;
} else {
return mediumSize.getSource();
}
}
/**
* @deprecated
* @see PhotosInterface#getImageAsStream(Photo, int)
* @return The InputStream
* @throws IOException
*/
public InputStream getLargeAsStream() throws IOException {
return getImageAsStream(LARGE_IMAGE_SUFFIX);
}
public String getLargeUrl() {
if (largeSize == null) {
return getBaseImageUrl() + LARGE_IMAGE_SUFFIX;
} else {
return largeSize.getSource();
}
}
/**
* Get an image as a stream. Callers must be sure to close the stream when they are done with it.
*
* @deprecated
* @see PhotosInterface#getImageAsStream(Photo, int)
* @param suffix
* The suffix
* @return The InputStream
* @throws IOException
*/
private InputStream getImageAsStream(String suffix) throws IOException {
StringBuffer buffer = getBaseImageUrl();
buffer.append(suffix);
return _getImageAsStream(buffer.toString());
}
/**
*
* @deprecated
* @see PhotosInterface#getImageAsStream(Photo, int)
* @param suffix
* @return InoutStream
* @throws IOException
* @throws FlickrException
*/
private InputStream getOriginalImageAsStream(String suffix) throws IOException, FlickrException {
StringBuffer buffer = getOriginalBaseImageUrl();
buffer.append(suffix);
return _getImageAsStream(buffer.toString());
}
private InputStream _getImageAsStream(String urlStr) throws IOException {
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.connect();
return conn.getInputStream();
}
private StringBuffer getBaseImageUrl() {
StringBuffer buffer = new StringBuffer();
buffer.append(_getBaseImageUrl());
buffer.append(getSecret());
return buffer;
}
private StringBuffer getOriginalBaseImageUrl() throws FlickrException, NullPointerException {
StringBuffer buffer = new StringBuffer();
buffer.append(_getBaseImageUrl());
if (getOriginalSecret().length() > 8) {
buffer.append(getOriginalSecret());
} else {
throw new FlickrException("0", "OriginalUrl not available because of missing originalsecret.");
}
return buffer;
}
private StringBuffer _getBaseImageUrl() {
StringBuffer buffer = new StringBuffer();
buffer.append("https://farm");
buffer.append(getFarm());
buffer.append(".static.flickr.com/");
buffer.append(getServer());
buffer.append("/");
buffer.append(getId());
buffer.append("_");
return buffer;
}
/**
* @return A placeId
* @see com.gmail.yuyang226.flickr.places.PlacesInterface#resolvePlaceId(String)
*/
public String getPlaceId() {
return placeId;
}
public void setPlaceId(String placeId) {
this.placeId = placeId;
}
public String getMedia() {
return media;
}
public void setMedia(String media) {
this.media = media;
}
public String getMediaStatus() {
return mediaStatus;
}
public void setMediaStatus(String mediaStatus) {
this.mediaStatus = mediaStatus;
}
public int getOriginalWidth() {
return originalWidth;
}
public void setOriginalWidth(String originalWidth) {
try {
setOriginalWidth(Integer.parseInt(originalWidth));
} catch (NumberFormatException ex) {
}
}
public void setOriginalWidth(int originalWidth) {
this.originalWidth = originalWidth;
}
public int getOriginalHeight() {
return originalHeight;
}
public void setOriginalHeight(String originalHeight) {
try {
setOriginalHeight(Integer.parseInt(originalHeight));
} catch (NumberFormatException ex) {
}
}
public void setOriginalHeight(int originalHeight) {
this.originalHeight = originalHeight;
}
/**
* Set sizes to override the generated URLs of the different sizes.
*
* @param sizes
* @see com.gmail.yuyang226.flickr.photos.PhotosInterface#getSizes(String)
*/
public void setSizes(Collection<Size> sizes) {
Iterator<Size> it = sizes.iterator();
while (it.hasNext()) {
Size size = (Size) it.next();
if (size.getLabel() == Size.SMALL) {
smallSize = size;
} else if (size.getLabel() == Size.SQUARE) {
squareSize = size;
} else if (size.getLabel() == Size.THUMB) {
thumbnailSize = size;
} else if (size.getLabel() == Size.MEDIUM) {
mediumSize = size;
} else if (size.getLabel() == Size.LARGE) {
largeSize = size;
} else if (size.getLabel() == Size.ORIGINAL) {
originalSize = size;
} else if (size.getLabel() == Size.LARGE_SQUARE) {
largeSquareSize = size;
}
}
}
public Size getSquareSize() {
return squareSize;
}
public Size getSmallSize() {
return smallSize;
}
public Size getThumbnailSize() {
return thumbnailSize;
}
public Size getMediumSize() {
return mediumSize;
}
public Size getLargeSize() {
return largeSize;
}
public Size getLargeSquareSize() {
return largeSquareSize;
}
public Size getOriginalSize() {
return originalSize;
}
/**
* @return the pathAlias
*/
public String getPathAlias() {
return pathAlias;
}
/**
* @param pathAlias
* the pathAlias to set
*/
public void setPathAlias(String pathAlias) {
this.pathAlias = pathAlias;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((title == null) ? 0 : title.hashCode());
result = prime * result + ((url == null) ? 0 : url.hashCode());
return result;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Photo))
return false;
Photo other = (Photo) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (title == null) {
if (other.title != null)
return false;
} else if (!title.equals(other.title))
return false;
if (url == null) {
if (other.url != null)
return false;
} else if (!url.equals(other.url))
return false;
return true;
}
}