package com.github.windbender.domain;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;
import javax.persistence.Table;
import org.eclipse.jetty.util.log.Log;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.drew.lang.GeoLocation;
import com.drew.metadata.exif.ExifSubIFDDirectory;
import com.drew.metadata.exif.GpsDirectory;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.github.windbender.core.LatLonPair;
import com.github.windbender.resources.ImageResource;
import com.github.windbender.service.TimeZoneGetter;
import com.sun.jersey.api.ConflictException;
@NamedNativeQueries({
@NamedNativeQuery(
name = "com.github.windbender.ImageRecord.FindAllOrderByTime",
query = "select * from images order by imageTime,id",
resultClass = ImageRecord.class
)
})
@Entity
@Table(name="images")
public class ImageRecord implements Comparable<ImageRecord>{
static Logger log = LoggerFactory.getLogger(ImageRecord.class);
String id;
@Id
@Column(name="id")
public String getId() {
return id;
}
DateTime datetime;
DateTime uploadTime;
@JsonIgnore
double lat;
@JsonIgnore
double lon;
String originalFileName;
Long cameraID;
@Column(name="camera_id", nullable=true)
public Long getCameraID() {
return cameraID;
}
public void setCameraID(long cameraID) {
this.cameraID = cameraID;
}
Integer userID;
private void setUserId(Integer userId2) {
this.userID = userId2;
}
@Column(name="user_id", nullable=true)
public Integer getUserId() {
return this.userID;
}
public int compareTo(ImageRecord other) {
int x = this.datetime.compareTo(other.datetime);
if (x !=0) return x;
x = this.id.compareTo(other.getId());
return x;
}
public static ImageRecord makeImageFromExif(TimeZoneGetter timeZoneGetter, ExifSubIFDDirectory directory,
GpsDirectory gpsDirectory, String filename, long cameraId, String latStr, String lonStr, Integer userId) {
Double lat = null;
if(latStr != null) {
try {
lat = Double.parseDouble(latStr);
} catch (NumberFormatException e) {
}
}
Double lon = null;
if(lonStr != null) {
try {
lon = Double.parseDouble(lonStr);
} catch (NumberFormatException e) {
}
}
Date date = new Date();
if(directory != null) {
date = directory.getDate(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL);
}
GeoLocation location = null;
if(gpsDirectory != null) {
location = gpsDirectory.getGeoLocation();
}
ImageRecord ir = new ImageRecord();
if( (location != null) && (Math.abs(location.getLatitude()) > 0.001) && (Math.abs(location.getLongitude()) > 0.001) ) {
ir.setLat( location.getLatitude());
ir.setLon(location.getLongitude());
} else {
if((lat == null) || (lon == null) ) throw new ConflictException("sorry either image must have EXIF based GPS info, or you must supply it on the upload form");
if(lat != null)
ir.setLat( lat );
if(lon != null)
ir.setLon( lon );
}
ir.setOriginalFileName(filename);
ir.setCameraID(cameraId);
ir.setUserId(userId);
String stripped = filename.toUpperCase().replaceAll("[A-Z]", "").replaceAll("[^0-9]","");
Long seq = 0l;
try {
int endIndex = stripped.length();
String lastPart = stripped.substring(endIndex-3, endIndex);
seq =Long.parseLong(lastPart);
} catch (NumberFormatException e) {
}catch (StringIndexOutOfBoundsException e) {
}
long millis = date.getTime() + seq;
LatLonPair location2 = new LatLonPair(ir.getLat(),ir.getLon());
DateTimeZone dtz = timeZoneGetter.getTimeZone(location2);
DateTime imgTime = (new DateTime(millis)).withZoneRetainFields(dtz);
ir.setDatetime(imgTime);
long temp = ir.getLat() != +0.0d ? Double.doubleToLongBits(ir.getLat()) : 0L;
int locationHash = (int) (temp ^ (temp >>> 32));
temp = ir.getLon() != +0.0d ? Double.doubleToLongBits(ir.getLon()) : 0L;
locationHash = 31 * locationHash + (int) (temp ^ (temp >>> 32));
long timeMillis = ir.getDatetime().getMillis();
String id = "id"+locationHash+":"+timeMillis+":"+seq;
log.info("we set datetime on "+id+" to "+imgTime);
ir.setId(id);
ir.setUploadTime(new DateTime());
return ir;
}
private void setDateTimeViaMillis(long millis) {
datetime = new DateTime(millis);
}
@JsonIgnore
@Column(name="lat", nullable=true)
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
@JsonIgnore
@Column(name="lon", nullable=true)
public double getLon() {
return lon;
}
public void setLon(double lon) {
this.lon = lon;
}
@Column(name="imageTime", nullable=false)
public DateTime getDatetime() {
return datetime;
}
public void setDatetime(DateTime datetime) {
this.datetime = datetime;
}
@Column(name="filename", nullable=false)
public String getOriginalFileName() {
return originalFileName;
}
public void setOriginalFileName(String originalFileName) {
this.originalFileName = originalFileName;
}
public void setId(String id) {
this.id = id;
}
@JsonIgnore
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="event_id")
public ImageEvent getEvent() {
return event;
}
public ImageEvent event;
public void setEvent(ImageEvent event) {
this.event = event;
}
@Column(name="upload_time", nullable=false)
public DateTime getUploadTime() {
return uploadTime;
}
public void setUploadTime(DateTime uploadTime) {
this.uploadTime = uploadTime;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((cameraID == null) ? 0 : cameraID.hashCode());
result = prime * result
+ ((datetime == null) ? 0 : datetime.hashCode());
result = prime * result + ((id == null) ? 0 : id.hashCode());
long temp;
temp = Double.doubleToLongBits(lat);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(lon);
result = prime * result + (int) (temp ^ (temp >>> 32));
result = prime
* result
+ ((originalFileName == null) ? 0 : originalFileName.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ImageRecord other = (ImageRecord) obj;
if (cameraID == null) {
if (other.cameraID != null)
return false;
} else if (!cameraID.equals(other.cameraID))
return false;
if (datetime == null) {
if (other.datetime != null)
return false;
} else if (!datetime.equals(other.datetime))
return false;
if (event == null) {
if (other.event != null)
return false;
} else if (!event.equals(other.event))
return false;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (Double.doubleToLongBits(lat) != Double.doubleToLongBits(other.lat))
return false;
if (Double.doubleToLongBits(lon) != Double.doubleToLongBits(other.lon))
return false;
if (originalFileName == null) {
if (other.originalFileName != null)
return false;
} else if (!originalFileName.equals(other.originalFileName))
return false;
return true;
}
}