Clover coverage report -
Coverage timestamp: Fri Nov 19 2004 13:41:51 PST
file stats: LOC: 336   Methods: 14
NCLOC: 270   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
Translator.java 65.4% 72.9% 78.6% 69.9%
coverage coverage
 1    package photospace.meta;
 2   
 3    import java.text.*;
 4    import java.util.*;
 5    import org.apache.commons.logging.*;
 6    import com.drew.lang.*;
 7    import com.drew.metadata.*;
 8    import com.drew.metadata.exif.*;
 9    import com.hp.hpl.jena.rdf.model.*;
 10    import com.hp.hpl.jena.vocabulary.*;
 11    import photospace.meta.rdf.*;
 12    import photospace.space.*;
 13   
 14    public class Translator
 15    implements java.io.Serializable
 16    {
 17    private static final Log log = LogFactory.getLog(Translator.class);
 18   
 19    private String baseUrl = "http://localhost";
 20   
 21  0 public Model toRss(CollectionMeta collection, String link)
 22    {
 23  0 String viewBase = baseUrl + "/web/view?view=media&path=";
 24   
 25  0 Model rdf = getDefaultModel();
 26  0 Resource channel = rdf.createResource(link, RSS.channel);
 27  0 channel.addProperty(RSS.title, collection.getLabel());
 28  0 channel.addProperty(RSS.link, channel.getURI());
 29  0 if (getDescription(collection) != null) channel.addProperty(RSS.description, getDescription(collection));
 30  0 if (collection.getCreator() != null) channel.addProperty(DC.creator, collection.getCreator());
 31  0 if (collection.getCreated() != null) channel.addProperty(DC.date, DATE_FORMAT.format(collection.getCreated()));
 32  0 Seq items = rdf.createSeq();
 33  0 channel.addProperty(RSS.items, items);
 34  0 Meta[] files = collection.getFiles();
 35  0 for (int i = 0; i < files.length; i++)
 36    {
 37  0 Meta meta = files[i];
 38  0 Resource item = rdf.createResource(getUri(meta), RSS.item);
 39  0 items.add(item);
 40  0 item.addProperty(RSS.title, meta.getLabel());
 41  0 item.addProperty(RSS.link, viewBase + meta.getPath());
 42  0 if (getDescription(meta) != null) item.addProperty(RSS.description, getDescription(meta));
 43  0 if (meta.getCreator() != null) item.addProperty(DC.creator, meta.getCreator());
 44  0 if (meta.getCreated() != null) item.addProperty(DC.date, DATE_FORMAT.format(meta.getCreated()));
 45  0 if (meta.getPosition().getLatitude() != null) item.addProperty(GeoVocab.LAT, meta.getPosition().getLatitude());
 46  0 if (meta.getPosition().getLongitude() != null) item.addProperty(GeoVocab.LONG, meta.getPosition().getLongitude());
 47  0 if (meta.getPosition().getAltitude() != null) item.addProperty(GeoVocab.ALT, meta.getPosition().getAltitude());
 48    }
 49  0 return rdf;
 50    }
 51   
 52  0 private String getDescription(Meta meta)
 53    {
 54  0 if (! (meta instanceof PhotoMeta)) return meta.getDescription();
 55  0 String desc = "<img border='0' src='" + baseUrl + "/image" + meta.getPath() + "?w=400&h=400'><br/>";
 56  0 if (meta.getDescription() != null) desc += meta.getDescription();
 57  0 return desc;
 58    }
 59   
 60  1 public Model toRdf(CollectionMeta collection, int depth)
 61    {
 62  0 if (depth < 1) return toRdf(collection);
 63   
 64  1 Model rdf = getDefaultModel();
 65  1 addSubject(collection, rdf, 0, depth);
 66  1 return rdf;
 67    }
 68   
 69  1 private void addSubject(CollectionMeta collection, Model rdf, int current, int depth)
 70    {
 71  1 addSubject(collection, rdf);
 72   
 73  0 if (current == depth) return;
 74   
 75  1 Meta[] files = collection.getFiles();
 76  1 for (int i = 0; i < files.length; i++)
 77    {
 78  1 Meta meta = files[i];
 79  0 if (meta instanceof CollectionMeta) addSubject((CollectionMeta) meta, rdf, ++current, depth);
 80  1 else addSubject(meta, rdf);
 81    }
 82    }
 83   
 84  9 public Model toRdf(Meta meta)
 85    {
 86  9 Model rdf = getDefaultModel();
 87  9 addSubject(meta, rdf);
 88  9 return rdf;
 89    }
 90   
 91  11 private void addSubject(Meta meta, Model rdf)
 92    {
 93  11 Resource subject;
 94  4 if (getUri(meta) == null) subject = rdf.createResource();
 95  7 else subject = rdf.createResource(getUri(meta));
 96   
 97  7 if (meta.getPath() != null) subject.addProperty(SpaceVocab.PATH, meta.getPath());
 98    //subject.addProperty(RDF.type, SpaceVocab.ASSET);
 99   
 100  11 if (meta instanceof PhotoMeta)
 101    {
 102  9 subject.addProperty(DC.type, Meta.PHOTO);
 103  9 subject.addProperty(DC.format, "image/jpeg");
 104    }
 105  0 else if (meta instanceof SearchResult) subject.addProperty(DC.type, Meta.SEARCH);
 106  2 else if (meta instanceof FolderMeta) subject.addProperty(DC.type, Meta.FOLDER);
 107    // todo: add support for creating RDF for other types
 108  0 else throw new IllegalStateException("Not sure what to do with " + meta);
 109   
 110  2 if (meta.getTitle() != null) subject.addProperty(DC.title, meta.getTitle());
 111  6 if (meta.getDescription() != null) subject.addProperty(DC.description, meta.getDescription());
 112  0 if (meta.getCreator() != null) subject.addProperty(DC.creator, meta.getCreator());
 113  6 if (meta.getCreated() != null) subject.addProperty(DC.date, df[0].format(meta.getCreated()));
 114   
 115   
 116  4 if (meta.getUpdated() != null) subject.addProperty(SpaceVocab.UPDATED, df[0].format(meta.getUpdated()));
 117  0 if (meta.getRating() != null) subject.addProperty(SpaceVocab.RATING, meta.getRating());
 118  0 if (meta.getRatingCount() != null) subject.addProperty(SpaceVocab.RATING_COUNT, meta.getRatingCount());
 119  0 if (meta.getViewCount() != null) subject.addProperty(SpaceVocab.VIEW_COUNT, meta.getViewCount());
 120   
 121  11 if (meta.getHasPosition())
 122    {
 123  6 Position pos = meta.getPosition();
 124   
 125  6 Resource point = rdf.createResource(GeoVocab.POINT);
 126  6 subject.addProperty(DC.coverage, point);
 127  6 if (pos.getLatitude() != null) point.addProperty(GeoVocab.LAT, pos.getLatitude().doubleValue());
 128  6 if (pos.getLongitude() != null) point.addProperty(GeoVocab.LONG, pos.getLongitude().doubleValue());
 129  0 if (pos.getAltitude() != null) point.addProperty(GeoVocab.ALT, pos.getAltitude().doubleValue());
 130    }
 131   
 132  11 if (meta.getLabels().length != 0)
 133    {
 134  4 Resource labels = rdf.createBag();
 135  4 subject.addProperty(DC.subject, labels);
 136  4 for (int i = 0; i < meta.getLabels().length; i++)
 137    {
 138  12 labels.addProperty(RDF.value, meta.getLabels()[i]);
 139    }
 140    }
 141   
 142  11 if (meta instanceof MediaMeta)
 143    {
 144  9 MediaMeta asset = (MediaMeta) meta;
 145   
 146  7 if (asset.getDevice() != null) subject.addProperty(TechVocab.CAMERA, asset.getDevice());
 147    }
 148   
 149  11 if (meta instanceof PhotoMeta)
 150    {
 151  9 PhotoMeta photo = (PhotoMeta) meta;
 152   
 153  6 if (photo.getShutterSpeed() != null) subject.addProperty(TechVocab.SHUTTER_SPEED, photo.getShutterSpeed());
 154  6 if (photo.getAperture() != null) subject.addProperty(TechVocab.APERTURE, photo.getAperture());
 155  6 if (photo.getFocalLength() != null) subject.addProperty(TechVocab.FOCAL_LENGTH, photo.getFocalLength());
 156  6 if (photo.getExposureBias() != null) subject.addProperty(TechVocab.EXPOSURE_BIAS, photo.getExposureBias());
 157  6 if (photo.getMeteringMode() != null) subject.addProperty(TechVocab.METERING_MODE, photo.getMeteringMode());
 158  6 if (photo.getSensingMethod() != null) subject.addProperty(TechVocab.SENSING_METHOD, photo.getSensingMethod());
 159  6 if (photo.getFlash() != null) subject.addProperty(TechVocab.FLASH, photo.getFlash());
 160    }
 161    }
 162   
 163  18 private String getUri(Meta meta)
 164    {
 165  4 if (meta.getPath() == null) return null;
 166  14 return baseUrl + meta.getPath();
 167    }
 168   
 169  10 private Model getDefaultModel()
 170    {
 171  10 Model rdf = ModelFactory.createDefaultModel();
 172  10 rdf.setNsPrefix("geo", GeoVocab.getURI());
 173  10 rdf.setNsPrefix("tech", TechVocab.getURI());
 174  10 rdf.setNsPrefix("content", ContentVocab.getURI());
 175  10 rdf.setNsPrefix("space", SpaceVocab.getURI());
 176  10 return rdf;
 177    }
 178   
 179  8 public Meta fromRdf(Model rdf) throws ParseException
 180    {
 181   
 182  8 Resource subject = getAsset(rdf);
 183   
 184  0 if (!subject.hasProperty(DC.type)) throw new IllegalStateException("RDF does not define meta type.");
 185   
 186  8 Meta meta;
 187   
 188  8 String rdfType = subject.getProperty(DC.type).getString();
 189  7 if (Meta.PHOTO.equals(rdfType)) meta = new PhotoMeta();
 190  1 else if (Meta.FOLDER.equals(rdfType)) meta = new FolderMeta();
 191    // todo: add support for reading RDF for other types
 192  0 else throw new IllegalStateException("Not sure what to do with RDF type: " + rdfType);
 193   
 194  6 if (subject.hasProperty(SpaceVocab.PATH)) meta.setPath(subject.getProperty(SpaceVocab.PATH).getString());
 195   
 196  0 if (subject.hasProperty(DC.title)) meta.setTitle(subject.getProperty(DC.title).getString());
 197  6 if (subject.hasProperty(DC.description)) meta.setDescription(subject.getProperty(DC.description).getString());
 198  0 if (subject.hasProperty(DC.creator)) meta.setCreator(subject.getProperty(DC.creator).getString());
 199  6 if (subject.hasProperty(DC.date)) meta.setCreated(parseDate(subject.getProperty(DC.date).getString()));
 200   
 201  5 if (subject.hasProperty(SpaceVocab.UPDATED)) meta.setUpdated(parseDate(subject.getProperty(SpaceVocab.UPDATED).getString()));
 202  0 if (subject.hasProperty(SpaceVocab.RATING)) meta.setRating(new Double(subject.getProperty(SpaceVocab.RATING).getDouble()));
 203  0 if (subject.hasProperty(SpaceVocab.RATING_COUNT)) meta.setRatingCount(new Integer(subject.getProperty(SpaceVocab.RATING_COUNT).getInt()));
 204  0 if (subject.hasProperty(SpaceVocab.VIEW_COUNT)) meta.setViewCount(new Integer(subject.getProperty(SpaceVocab.VIEW_COUNT).getInt()));
 205   
 206  8 if (subject.hasProperty(DC.coverage))
 207    {
 208  6 Resource point = subject.getProperty(DC.coverage).getResource();
 209  6 if (point.hasProperty(GeoVocab.LAT)) meta.getPosition().setLatitude(new Double(point.getProperty(GeoVocab.LAT).getDouble()));
 210  6 if (point.hasProperty(GeoVocab.LONG)) meta.getPosition().setLongitude(new Double(point.getProperty(GeoVocab.LONG).getDouble()));
 211  0 if (point.hasProperty(GeoVocab.ALT)) meta.getPosition().setAltitude(new Double(point.getProperty(GeoVocab.ALT).getDouble()));
 212    }
 213   
 214  8 if (subject.hasProperty(DC.subject))
 215    {
 216  5 Set labels = new HashSet();
 217  5 for (StmtIterator i = subject.getProperty(DC.subject).getResource().listProperties(RDF.value); i.hasNext(); )
 218    {
 219  10 labels.add(i.nextStatement().getString());
 220    }
 221  5 meta.setLabels((String[]) labels.toArray(new String[] {}));
 222    }
 223   
 224  8 if (meta instanceof MediaMeta)
 225    {
 226  7 MediaMeta media = (MediaMeta) meta;
 227   
 228  6 if (subject.hasProperty(TechVocab.CAMERA)) media.setDevice(subject.getProperty(TechVocab.CAMERA).getString());
 229    }
 230   
 231  8 if (meta instanceof PhotoMeta)
 232    {
 233  7 PhotoMeta photo = (PhotoMeta) meta;
 234   
 235  6 if (subject.hasProperty(TechVocab.SHUTTER_SPEED)) photo.setShutterSpeed(subject.getProperty(TechVocab.SHUTTER_SPEED).getString());
 236  6 if (subject.hasProperty(TechVocab.APERTURE)) photo.setAperture(subject.getProperty(TechVocab.APERTURE).getString());
 237  6 if (subject.hasProperty(TechVocab.FOCAL_LENGTH)) photo.setFocalLength(subject.getProperty(TechVocab.FOCAL_LENGTH).getString());
 238  6 if (subject.hasProperty(TechVocab.EXPOSURE_BIAS)) photo.setExposureBias(subject.getProperty(TechVocab.EXPOSURE_BIAS).getString());
 239  6 if (subject.hasProperty(TechVocab.METERING_MODE)) photo.setMeteringMode(subject.getProperty(TechVocab.METERING_MODE).getString());
 240  6 if (subject.hasProperty(TechVocab.SENSING_METHOD)) photo.setSensingMethod(subject.getProperty(TechVocab.SENSING_METHOD).getString());
 241  6 if (subject.hasProperty(TechVocab.FLASH)) photo.setFlash(subject.getProperty(TechVocab.FLASH).getString());
 242    }
 243   
 244  8 return meta;
 245    }
 246   
 247    /*
 248    * This is a bit of a hack.
 249    * todo: figure out how to get the Resource out by RDF.type
 250    */
 251  8 private Resource getAsset(Model rdf)
 252    {
 253  8 return rdf.listSubjectsWithProperty(DC.type).nextResource();
 254    }
 255   
 256  7 public PhotoMeta fromExif(Metadata exif)
 257    throws MetadataException
 258    {
 259  7 PhotoMeta photo = new PhotoMeta();
 260  7 Directory dir = exif.getDirectory(ExifDirectory.class);
 261  0 if (dir.containsTag(ExifDirectory.TAG_ARTIST)) photo.setCreator(dir.getString(ExifDirectory.TAG_ARTIST));
 262  7 if (dir.containsTag(ExifDirectory.TAG_DATETIME_ORIGINAL)) photo.setCreated(dir.getDate(ExifDirectory.TAG_DATETIME_ORIGINAL));
 263  7 if (dir.containsTag(ExifDirectory.TAG_USER_COMMENT)) photo.setDescription(dir.getString(ExifDirectory.TAG_USER_COMMENT));
 264   
 265  7 if (dir.containsTag(ExifDirectory.TAG_MODEL)) photo.setDevice(dir.getDescription(ExifDirectory.TAG_MODEL));
 266  7 if (dir.containsTag(ExifDirectory.TAG_EXPOSURE_TIME)) photo.setShutterSpeed(dir.getRational(ExifDirectory.TAG_EXPOSURE_TIME).toSimpleString(false) + " sec");
 267  7 if (dir.containsTag(ExifDirectory.TAG_APERTURE)) photo.setAperture(dir.getDescription(ExifDirectory.TAG_APERTURE));
 268  7 if (dir.containsTag(ExifDirectory.TAG_FOCAL_LENGTH)) photo.setFocalLength(dir.getDescription(ExifDirectory.TAG_FOCAL_LENGTH));
 269  7 if (dir.containsTag(ExifDirectory.TAG_EXPOSURE_BIAS)) photo.setExposureBias(dir.getDescription(ExifDirectory.TAG_EXPOSURE_BIAS));
 270  7 if (dir.containsTag(ExifDirectory.TAG_METERING_MODE)) photo.setMeteringMode(dir.getDescription(ExifDirectory.TAG_METERING_MODE));
 271  7 if (dir.containsTag(ExifDirectory.TAG_SENSING_METHOD)) photo.setSensingMethod(dir.getDescription(ExifDirectory.TAG_SENSING_METHOD));
 272  7 if (dir.containsTag(ExifDirectory.TAG_FLASH)) photo.setFlash(dir.getDescription(ExifDirectory.TAG_FLASH));
 273   
 274  7 Directory gps = exif.getDirectory(GpsDirectory.class);
 275  7 if (gps.containsTag(GpsDirectory.TAG_GPS_LATITUDE) && gps.containsTag(GpsDirectory.TAG_GPS_LATITUDE_REF))
 276    {
 277  7 photo.getPosition().setLatitude(getDegrees(gps.getRationalArray(GpsDirectory.TAG_GPS_LATITUDE),
 278    gps.getString(GpsDirectory.TAG_GPS_LATITUDE_REF)));
 279    }
 280  7 if (gps.containsTag(GpsDirectory.TAG_GPS_LONGITUDE) && gps.containsTag(GpsDirectory.TAG_GPS_LONGITUDE_REF))
 281    {
 282  7 photo.getPosition().setLongitude(getDegrees(gps.getRationalArray(GpsDirectory.TAG_GPS_LONGITUDE),
 283    gps.getString(GpsDirectory.TAG_GPS_LONGITUDE_REF)));
 284    }
 285  7 if (gps.containsTag(GpsDirectory.TAG_GPS_ALTITUDE))
 286    {
 287  0 photo.getPosition().setAltitude(new Double(gps.getDouble(GpsDirectory.TAG_GPS_ALTITUDE)));
 288    }
 289   
 290  7 return photo;
 291    }
 292   
 293    /*
 294    Not sure what to do about the T in this:
 295    use http://www.w3.org/TR/NOTE-datetime
 296    format: YYYY[-MM[-DD[Thh:mm[:ss[.sTZD]]]]]
 297    example: 1999-10-01T17:53
 298    if TZD is omitted the timezone is UTC
 299    */
 300    public static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SZ");
 301    private static final DateFormat[] df =
 302    {
 303    DATE_FORMAT,
 304    new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S"),
 305    new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"),
 306    new SimpleDateFormat("yyyy-MM-dd'T'HH:mm"),
 307    new SimpleDateFormat("yyyy-MM-dd"),
 308    new SimpleDateFormat("yyyy-MM"),
 309    new SimpleDateFormat("yyyy")
 310    };
 311   
 312  11 private Date parseDate(String date)
 313    {
 314  16 for (int i = 0; i < df.length; i++)
 315    {
 316  16 try { return df[i].parse(date); }
 317    catch (ParseException e) {}
 318    }
 319  0 log.warn("Unable to parse date string from RDF: " + date);
 320   
 321  0 return null;
 322    }
 323   
 324  14 private Double getDegrees(Rational[] degreesArray, String reference)
 325    {
 326  14 double decimalDegrees = degreesArray[0].doubleValue() + degreesArray[1].doubleValue()/60 + degreesArray[2].doubleValue()/3600;
 327  14 boolean negative = reference.equals("S") || reference.equals("W");
 328  14 return new Double((negative ? -1 : 1) * Math.round(decimalDegrees * 100000d) / 100000d);
 329    }
 330   
 331  0 public void setBaseUrl(String baseUrl)
 332    {
 333  0 if (baseUrl.endsWith("/")) baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
 334  0 this.baseUrl = baseUrl;
 335    }
 336    }