/* * ResourceMapJena.java * * Copyright (c) 2008, Hewlett-Packard Company and Massachusetts * Institute of Technology. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of the Hewlett-Packard Company nor the name of the * Massachusetts Institute of Technology nor the names of their * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ package org.dspace.foresite.jena; import org.dspace.foresite.ResourceMap; import org.dspace.foresite.Agent; import org.dspace.foresite.Aggregation; import org.dspace.foresite.Triple; import org.dspace.foresite.OREException; import org.dspace.foresite.OREFactory; import org.dspace.foresite.ReMSerialisation; import org.dspace.foresite.AggregatedResource; import org.dspace.foresite.DateParser; import org.dspace.foresite.OREParserException; import org.dspace.foresite.Vocab; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.ArrayList; import java.util.regex.Pattern; import java.util.regex.Matcher; import java.net.URI; import java.net.URISyntaxException; import java.text.SimpleDateFormat; import java.text.ParseException; import java.text.DateFormat; import javax.xml.bind.DatatypeConverter; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.Resource; import com.hp.hpl.jena.rdf.model.StmtIterator; import com.hp.hpl.jena.rdf.model.Statement; import com.hp.hpl.jena.rdf.model.Literal; import com.hp.hpl.jena.rdf.model.Selector; import com.hp.hpl.jena.rdf.model.SimpleSelector; import com.hp.hpl.jena.rdf.model.RDFNode; import com.hp.hpl.jena.rdf.model.ModelFactory; import com.hp.hpl.jena.vocabulary.DC; import com.hp.hpl.jena.vocabulary.DCTerms; import com.hp.hpl.jena.vocabulary.RDF; /** * @Author Richard Jones */ public class ResourceMapJena extends OREResourceJena implements ResourceMap { public ResourceMapJena() { // allow OREResourceJena to construct the model for us super(); } /////////////////////////////////////////////////////////////////// // Methods from OREResourceJena /////////////////////////////////////////////////////////////////// public void empty() { } public void detach() throws OREException { //To change body of implemented methods use File | Settings | File Templates. } /////////////////////////////////////////////////////////////////// // Methods from ResourceMap /////////////////////////////////////////////////////////////////// public void initialise(URI uri) throws OREException { // FIXME: are we 100% sure that this is a valid way of determining // protocol-based-ness. See RFC3986 for reference. // // we need to ensure that the URI is protocol based String ident = uri.toString(); String rx = ".+://.+"; Pattern p = Pattern.compile(rx); Matcher m = p.matcher(ident); if (!m.matches()) { throw new OREException("Illegal URI: " + uri.toString() + "; ResourceMap requires a protocol-based URI"); } res = model.createResource(uri.toString()); res.addProperty(RDF.type, ORE.ResourceMap); } public boolean isAuthoritative() throws OREException { StmtIterator itr = res.listProperties(OREX.isAuthoritativeFor); if (itr.hasNext()) { return true; } return false; } public void setAuthoritative(boolean authoritative) throws OREException { if (authoritative) { Selector selector = new SimpleSelector(null, ORE.isDescribedBy, res); StmtIterator itr = model.listStatements(selector); if (itr.hasNext()) { Statement statement = itr.nextStatement(); res.addProperty(OREX.isAuthoritativeFor, statement.getSubject()); } } else { res.removeAll(OREX.isAuthoritativeFor); } } public List getCreators() { List agents = new ArrayList(); StmtIterator itr = res.listProperties(DC.creator); while (itr.hasNext()) { Statement statement = itr.nextStatement(); Agent agent = JenaOREFactory.createAgent((Resource) statement.getObject()); agents.add(agent); } return agents; } public void setCreators(List creators) { this.clearCreators(); for (Agent creator : creators) { this.addCreator(creator); } } public void addCreator(Agent creator) { Resource resource = ((AgentJena) creator).getResource(); res.addProperty(DC.creator, resource); this.addResourceToModel(resource); } // FIXME: if creators are shared, then there will be problems with the // resulting REM. Therefore need to check for shared creators public void clearCreators() { List creators = this.getCreators(); for (Agent creator : creators) { Model cModel = ((AgentJena) creator).getModel(); StmtIterator itr = cModel.listStatements(); model.remove(itr); } } public Date getCreated() throws OREException { try { // SimpleDateFormat sdf = new SimpleDateFormat(JenaOREConstants.dateFormat); StmtIterator itr = res.listProperties(DCTerms.created); if (itr.hasNext()) { Statement statement = itr.nextStatement(); String value = ((Literal) statement.getObject()).getLexicalForm(); Date created = DateParser.parse(value); return created; } return null; } catch (OREParserException e) { throw new OREException(e); } } public void setCreated(Date created) { Calendar cal = Calendar.getInstance(); cal.setTime(created); String date = DatatypeConverter.printDateTime(cal); res.addProperty(DCTerms.created, model.createTypedLiteral(date, JenaOREConstants.dateTypedLiteral)); } public Date getModified() throws OREException { try { //SimpleDateFormat sdf = new SimpleDateFormat(JenaOREConstants.dateFormat); StmtIterator itr = res.listProperties(DCTerms.modified); if (itr.hasNext()) { Statement statement = itr.nextStatement(); String value = ((Literal) statement.getObject()).getLexicalForm(); Date modified = DateParser.parse(value); return modified; } return null; } catch (OREParserException e) { throw new OREException(e); } } public void setModified(Date modified) { Calendar cal = Calendar.getInstance(); cal.setTime(modified); String date = DatatypeConverter.printDateTime(cal); res.addProperty(DCTerms.modified, model.createTypedLiteral(date, JenaOREConstants.dateTypedLiteral)); } public void removeModified() throws OREException { res.removeAll(DCTerms.modified); } public String getRights() { Statement statement = res.getProperty(DC.rights); if (statement != null) { return statement.getString(); } return null; } public void setRights(String rights) { res.addProperty(DC.rights, model.createTypedLiteral(rights)); } public void removeRights() { res.removeAll(DC.rights); } public void setTypes(List types) { super.setTypes(types); // ensure that the required type is still set Selector selector = new SimpleSelector(res, RDF.type, ORE.ResourceMap); StmtIterator itr = model.listStatements(selector); if (!itr.hasNext()) { res.addProperty(RDF.type, ORE.ResourceMap); } } public void clearTypes() { // leave it to OREResource to handle type clearance super.clearTypes(); // ensure that the required type is still set res.addProperty(RDF.type, ORE.ResourceMap); } public Vocab getOREType() throws OREException { return Vocab.ore_ResourceMap; } // FIXME: this must only create one aggregation ever, or throw and error! public Aggregation createAggregation(URI uri) throws OREException { Aggregation agg = OREFactory.createAggregation(uri); this.setAggregation(agg); ((AggregationJena) agg).setModel(model, uri); return agg; } public Aggregation getAggregation() throws OREException { try { StmtIterator itr = res.listProperties(ORE.describes); if (itr.hasNext()) { Statement statement = itr.nextStatement(); String resURI = ((Resource) statement.getObject()).getURI(); Aggregation aggregation = JenaOREFactory.createAggregation(model, new URI(resURI)); return aggregation; } return null; } catch (URISyntaxException e) { throw new OREException(e); } } public void setAggregation(Aggregation aggregation) throws OREException { try { ReMSerialisation serialisation = new ReMSerialisation(); serialisation.setURI(new URI(res.getURI())); StmtIterator itr = res.listProperties(DC.format); String mime = "application/octet-stream"; if (itr.hasNext()) { Statement statement = itr.nextStatement(); mime = ((Literal) statement.getObject()).getLexicalForm(); } serialisation.setMimeType(mime); aggregation.addReMSerialisation(serialisation); // FIXME: I don't think we need all of this code, hence the comments // Resource resource = ((AggregationJena) aggregation).getResource(); Model aModel = ((AggregationJena) aggregation).getModel(); // res.addProperty(ORE.describes, resource); this.addModelToModel(aModel); } catch (URISyntaxException e) { throw new OREException(e); } } public void removeAggregation() throws OREException { AggregationJena agg = (AggregationJena) this.getAggregation(); // FIXME: how do we ensure that we successfully recursively remove the aggregation? // can we do it with Jena, or do we need to utilise our own API. I think the // latter! // agg.empty(); } public List getAggregatedResources() throws OREException { Aggregation agg = this.getAggregation(); return agg.getAggregatedResources(); } // FIXME: how do we actually do this? public List doSparql(String sparql) { return null; } public ResourceMap copy() throws OREException { Model model = this.getModel(); StmtIterator itr = model.listStatements(); Model nModel = ModelFactory.createDefaultModel(); nModel.add(itr); ResourceMap nrem = JenaOREFactory.createResourceMap(nModel, this.getURI()); return nrem; } /////////////////////////////////////////////////////////////////// // methods from OREResourceJena /////////////////////////////////////////////////////////////////// public void setModel(Model model, URI resourceURI) throws OREException { // verify that the URI for the resource map is not already in use for another // part of the object Resource subject = model.createResource(resourceURI.toString()); Selector aggSelector = new SimpleSelector(subject, ORE.aggregates, (RDFNode) null); Selector proxySelector = new SimpleSelector(subject, ORE.proxyFor, (RDFNode) null); StmtIterator aggItr = model.listStatements(aggSelector); StmtIterator proxyItr = model.listStatements(proxySelector); if (aggItr.hasNext() || proxyItr.hasNext()) { throw new OREException("ResourceMap may not have the same URI as an Aggregation or Proxy"); } // now go back and build the resource map in the super class super.setModel(model, resourceURI); } }