/*
* Copyright (c) 2005 Aetrion LLC.
*/
package com.googlecode.flickr2twitter.com.aetrion.flickr.photos;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import com.googlecode.flickr2twitter.com.aetrion.flickr.people.User;
import com.googlecode.flickr2twitter.com.aetrion.flickr.tags.Tag;
import com.googlecode.flickr2twitter.com.aetrion.flickr.util.StringUtilities;
import com.googlecode.flickr2twitter.impl.flickr.FlickrBaseEncoder;
import com.googlecode.flickr2twitter.model.IGeoItem;
import com.googlecode.flickr2twitter.model.IPhoto;
import com.googlecode.flickr2twitter.model.IShortUrl;
import com.googlecode.flickr2twitter.model.Item;
import com.googlecode.flickr2twitter.model.ItemGeoData;
/**
* 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 extends Item implements IPhoto, IGeoItem, IShortUrl{
private static final long serialVersionUID = 12L;
private static final ThreadLocal<SimpleDateFormat> DATE_FORMATS = new ThreadLocal<SimpleDateFormat>() {
protected synchronized SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
};
private boolean publicFlag;
private Date dateAdded;
private Date datePosted;
private Date dateTaken;
private Date lastUpdate;
private String url;
private ItemGeoData geoData;
private Collection<Tag> tags;
public Photo() {
}
public boolean isPublicFlag() {
return publicFlag;
}
public void setPublicFlag(boolean publicFlag) {
this.publicFlag = publicFlag;
}
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(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 getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public ItemGeoData getGeoData() {
return geoData;
}
public void setGeoData(ItemGeoData geoData) {
this.geoData = geoData;
}
public boolean hasGeoData() {
return geoData != null;
}
/**
* @return the tags
*/
public Collection<Tag> getTags() {
return tags;
}
/**
* @param tags the tags to set
*/
public void setTags(Collection<Tag> tags) {
this.tags = tags;
}
/**
* @see java.lang.Object#equals(java.lang.Object)
* @see <a href="http://www.ibm.com/developerworks/library/j-dyn0603/">http://www.ibm.com/developerworks/library/j-dyn0603/</a>
*/
@Override
public boolean equals(Object obj) {
if ((obj == null) || (obj.getClass() != this.getClass())) {
return false;
}
// object must be Photo at this point
Photo test = (Photo) obj;
Class<?> cl = this.getClass();
Method[] method = cl.getMethods();
for (int i = 0; i < method.length; i++) {
Matcher m = StringUtilities.getterPattern.matcher(method[i].getName());
if (m.find() && !method[i].getName().equals("getClass")) {
try {
Object res = method[i].invoke(this, (Object[])null);
Object resTest = method[i].invoke(test, (Object[])null);
String retType = method[i].getReturnType().toString();
if (retType.indexOf("class") == 0) {
if (res != null && resTest != null) {
//System.out.println("class: " + method[i].getName());
if (!res.equals(resTest)) return false;
} else {
if (res == null && resTest == null) {
// nop
} else if (res == null || resTest == null) {
// one is set and one is null
return false;
}
}
} else if (retType.equals("int")) {
if (!((Integer) res).equals(((Integer)resTest))) return false;
} else if (retType.equals("boolean")) {
if (!((Boolean) res).equals(((Boolean)resTest))) return false;
} else if (retType.equals("interface java.util.Collection")) {
if (res != null && resTest != null) {
List<?> col = (List<?>) res;
List<?> colTest = (List<?>) resTest;
if (col.size() != colTest.size()) return false;
for (int j = 0; j < col.size(); j++) {
Object tobj1 = col.get(j);
Object tobj2 = colTest.get(j);
if (tobj1 instanceof PhotoUrl) {
PhotoUrl url1 = (PhotoUrl) tobj1;
PhotoUrl url2 = (PhotoUrl) tobj2;
if (!url1.equals(url2)) return false;
} else {
System.out.println("Photo unhandled object: " + tobj1.getClass().getName());
}
}
} else {
if (res == null && resTest != null) return false;
if (res != null && resTest == null) return false;
}
} else {
System.out.println("Photo#equals() missing type " + method[i].getName() + "|" +
method[i].getReturnType().toString());
}
} catch (IllegalAccessException ex) {
System.out.println("equals " + method[i].getName() + " " + ex);
} catch (InvocationTargetException ex) {
//System.out.println("equals " + method[i].getName() + " " + ex);
} catch (Exception ex) {
System.out.println("equals " + method[i].getName() + " " + ex);
}
}
}
return true;
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int hash = 1;
Class<?> cl = this.getClass();
Method[] method = cl.getMethods();
for (int i = 0; i < method.length; i++) {
Matcher m = StringUtilities.getterPattern.matcher(method[i].getName());
if (m.find() && !method[i].getName().equals("getClass")) {
Object res = null;
try {
res = method[i].invoke(this, (Object[])null);
} catch (IllegalAccessException ex) {
System.out.println("Photo hashCode " + method[i].getName() + " " + ex);
} catch (InvocationTargetException ex) {
//System.out.println("hashCode " + method[i].getName() + " " + ex);
}
if (res != null) {
if (res instanceof Boolean) {
Boolean bool = (Boolean) res;
hash += bool.hashCode();
} else if (res instanceof Integer) {
Integer inte = (Integer) res;
hash += inte.hashCode();
} else if (res instanceof String) {
String str = (String) res;
hash += str.hashCode();
} else if (res instanceof GeoData) {
GeoData edit = (GeoData) res;
hash += edit.hashCode();
} else if (res instanceof Permissions) {
Permissions perm = (Permissions) res;
hash += perm.hashCode();
} else if (res instanceof User) {
User user = (User) res;
hash += user.hashCode();
} else if (res instanceof ArrayList<?>) {
ArrayList<?> list = (ArrayList<?>) res;
hash += list.hashCode();
} else {
System.out.println("Photo hashCode unrecognised object: " + res.getClass().getName());
}
}
}
}
return hash;
}
/* (non-Javadoc)
* @see com.googlecode.flickr2twitter.model.IShortUrl#getShortUrl()
*/
@Override
public String getShortUrl() {
return FlickrBaseEncoder.getShortUrl(this);
}
}