//The MIT License // // Copyright (c) 2004 Mindswap Research Group, University of Maryland, College Park // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. package org.mindswap.swoop.annotea; import java.io.ByteArrayOutputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.io.StringReader; import java.io.StringWriter; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.apache.xerces.impl.dv.util.Base64; import org.mindswap.swoop.SwoopModel; import org.mindswap.swoop.change.ChangeLog; import org.mindswap.swoop.change.OntologyChangeRenderer; import org.mindswap.swoop.utils.owlapi.CorrectedRDFRenderer; import org.semanticweb.owl.io.RendererException; import org.semanticweb.owl.io.vocabulary.XMLSchemaSimpleDatatypeVocabulary; import org.semanticweb.owl.model.OWLClass; import org.semanticweb.owl.model.OWLDataFactory; import org.semanticweb.owl.model.OWLDataProperty; import org.semanticweb.owl.model.OWLDataValue; import org.semanticweb.owl.model.OWLException; import org.semanticweb.owl.model.OWLIndividual; import org.semanticweb.owl.model.OWLObjectProperty; import org.semanticweb.owl.model.OWLOntology; import org.semanticweb.owl.model.OWLProperty; import org.semanticweb.owl.model.change.AddDataPropertyInstance; import org.semanticweb.owl.model.change.AddEntity; import org.semanticweb.owl.model.change.AddImport; import org.semanticweb.owl.model.change.AddIndividualClass; import org.semanticweb.owl.model.change.AddObjectPropertyInstance; import org.semanticweb.owl.model.change.ChangeVisitor; import org.semanticweb.owl.model.change.OntologyChange; import org.semanticweb.owl.model.helper.OWLBuilder; /** * @author ronwalf * * The base Annotea description. */ public class Description implements Serializable { protected URL location = null; protected URI[] annotates = null; protected String body = null; protected String bodyType = null; protected String author = null; protected String created = null; protected OWLClass annotationType = null; protected List ontologyChangeSet = null; protected String annotatedEntityDefinition = null; final static String separator = "|"; /** * Generate a new Description, one with an unknown location. */ public Description() { } public Description(URL location) { setLocation(location); } /** * Build an OWL Ontology to wrap annotation instance * It imports the default Annotea Ontology that defines class * - Annotation and properties - body, author, created etc * We then create an instance of Annotation and fill its properties with * values from description * @return * @throws AnnoteaException */ public OWLOntology buildOntology() throws AnnoteaException { OWLOntology ontology = null; try { // create new ontology URI ont_uri = new URI(""); OWLBuilder builder = new OWLBuilder(); builder.createOntology(ont_uri, ont_uri); ontology = builder.getOntology(); OntologyChange change = null; // import standard annotea ontology change = new AddImport(ontology, Annotea.annoteaOntology, null); change.accept((ChangeVisitor) ontology); // create a new OWL instance OWLDataFactory dataFact = ontology.getOWLDataFactory(); OWLIndividual annotInstance = dataFact.getOWLIndividual(new URI("#Inst")); change = new AddEntity(ontology, annotInstance, null); change.accept((ChangeVisitor) ontology); // set instance type as annotea:Annotation OWLClass annotClass = (OWLClass) Annotea.annoteaMap.get("Annotation"); change = new AddIndividualClass(ontology, annotInstance, annotClass, null); change.accept((ChangeVisitor) ontology); // add properties to annotation instance // add annotates if (annotates!=null) { for (int i=0; i<annotates.length; i++) { OWLIndividual annotatesInd = dataFact.getOWLIndividual(annotates[i]); this.addAnnotationProperty("annotates", 2, annotatesInd, null, ontology, annotInstance); } } // add author if (author!=null) { this.addAnnotationProperty("author", 1, author, "string", ontology, annotInstance); } // add created if (created!=null) { this.addAnnotationProperty("created", 1, created, "string", ontology, annotInstance); } // add annotation type if (annotationType!=null) { change = new AddIndividualClass(ontology, annotInstance, annotationType, null); change.accept((ChangeVisitor) ontology); } // add entity definition string if (annotatedEntityDefinition!=null) { this.addAnnotationProperty("entityDefinition", 1, annotatedEntityDefinition, "string", ontology, annotInstance); } // add ontology change set if (ontologyChangeSet!=null) { if (SwoopModel.changeSharingMethod==SwoopModel.JAVA_SER) { // Serialize java object representing change set // and encode it to base-64 string. finally, put it as value // of a dataproperty AnnoteaNS+"hasChangeSet" ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(byteStream); out.writeObject(ontologyChangeSet); out.close(); String changeSetStr = Base64.encode(byteStream.toByteArray()); // System.out.println("Change set size:"+changeSetStr.length()); this.addAnnotationProperty("hasChangeSetJAVA", 1, changeSetStr, "string", ontology, annotInstance); } else { // SERIALIZE CHANGE LOGS IN RDF/XML USING OWLAPI ONTOLOGY OntologyChangeRenderer changeRenderer = new OntologyChangeRenderer(new ChangeLog(null, null)); OWLOntology owlapiOntology = changeRenderer.serializeOntologyChanges(ontologyChangeSet); CorrectedRDFRenderer rdfRenderer = new CorrectedRDFRenderer(); StringWriter st = new StringWriter(); rdfRenderer.renderOntology(owlapiOntology, st); String rdfxml = st.toString(); // TESTING: // System.out.println("OWL ChangeSet Ontology:---"); // System.out.println(rdfxml); rdfxml = this.stripHTML(rdfxml); this.addAnnotationProperty("hasChangeSetRDF", 1, rdfxml, "string", ontology, annotInstance); } } // now create an anonymous instance for the body //OWLIndividual bodyInstance = dataFact.getOWLIndividual(null); Random r = new Random(System.currentTimeMillis()); OWLIndividual bodyInstance = dataFact.getAnonOWLIndividual(new URI("http://" + Long.toString(r.nextLong()))); change = new AddEntity(ontology, bodyInstance, null); change.accept((ChangeVisitor) ontology); // add httpBody value = html text from body if (body!=null) { this.addAnnotationProperty("Body", 1, body, "string", ontology, bodyInstance); } // add httpContentType if (bodyType!=null) { this.addAnnotationProperty("ContentType", 1, bodyType, "string", ontology, bodyInstance); } // add httpContentLength if (body!=null) { this.addAnnotationProperty("ContentLength", 1, String.valueOf(body.length()), "int", ontology, bodyInstance); } // set annotInstance.body = httpBody this.addAnnotationProperty("body", 2, bodyInstance, null, ontology, annotInstance); } catch (Exception e) { e.printStackTrace(); throw new AnnoteaException(e); } return ontology; } /** * Add a single annotation property instance * @param propName - name of the annotea property (body, author, created..) * @param propType - type of annotea property (1-Data, 2-Object) * @param propValue - value of the annotea property * @param valueDatatype - xsd of value, if its a data-value * @param ourOntology - our new ontology containing single annotation instance (to be posted to server) * @param annotInstance - annotation instance in ourOntology */ protected void addAnnotationProperty(String propName, int propType, Object propValue, String valueDatatype, OWLOntology ourOntology, OWLIndividual instance) { // get annotea property OWLProperty annoteaProp = null; OntologyChange change = null; try { switch (propType) { case 1: // data property annoteaProp = (OWLDataProperty) Annotea.INSTANCE.annoteaMap.get(propName); // create data property value String xsd = XMLSchemaSimpleDatatypeVocabulary.XS; URI xsdType = new URI(xsd+valueDatatype); OWLDataValue propDataVal = ourOntology.getOWLDataFactory().getOWLConcreteData(xsdType, "EN", propValue); change = new AddDataPropertyInstance(ourOntology, instance, (OWLDataProperty) annoteaProp, propDataVal, null); break; case 2: // object property annoteaProp = (OWLObjectProperty) Annotea.INSTANCE.annoteaMap.get(propName); change = new AddObjectPropertyInstance(ourOntology, instance, (OWLObjectProperty) annoteaProp, (OWLIndividual) propValue, null); break; } change.accept((ChangeVisitor) ourOntology); } catch (Exception e) { e.printStackTrace(); } } public URI[] getAnnotates() { return annotates; } public String getBody() { return body; } public String getBodyType() { return bodyType; } public URL getLocation() { return location; } public void setAnnotates(URI[] annotated) { this.annotates = annotated; } public void setBody(String body) { this.body = body; } public void setBody(String body, String type) { setBody(body); setBodyType(type); } public void setBodyType(String type) { this.bodyType = type; } public void setLocation(URL location) { this.location = location; } public String getAuthor() { return this.author; } public String getCreated() { return this.created; } public void setAuthor(String author) { this.author = author; } public void setCreated(String created) { this.created = created; } public OWLClass getAnnotationType() { return this.annotationType; } public void setAnnotationType(OWLClass type) { this.annotationType = type; } public List getOntologyChangeSet() { return this.ontologyChangeSet; } public void setOntologyChangeSet(List changeSet) { this.ontologyChangeSet = new ArrayList(changeSet); } protected String stripHTML(String html) { html = html.replaceAll("&", "&"); html = html.replaceAll("<", "<"); html = html.replaceAll(">", ">"); return html; } public String getAnnotatedEntityDefinition() { return annotatedEntityDefinition; } public void setAnnotatedEntityDefinition(String annotatedEntityDefinition) { this.annotatedEntityDefinition = annotatedEntityDefinition; } public boolean equals(Object obj) { if (obj instanceof Description) { Description desc = (Description) obj; boolean match = true; if (desc.annotatedEntityDefinition!=null && this.annotatedEntityDefinition!=null) { if (!desc.annotatedEntityDefinition.equals(this.annotatedEntityDefinition)) match = false; } if (desc.annotates!=null && this.annotates!=null) { if (!desc.annotates.equals(this.annotates)) match = false; } if (desc.annotationType!=null && this.annotationType!=null) { try { if (!desc.annotationType.equals(this.annotationType)) match = false; } catch (Exception e) { e.printStackTrace(); } } if (desc.author!=null && this.author!=null) { if (!desc.author.equals(this.author)) match = false; } if (desc.body!=null && this.body!=null) { if (!desc.body.equals(this.body)) match = false; } if (desc.bodyType!=null && this.bodyType!=null) { if (!desc.bodyType.equals(this.bodyType)) match = false; } if (desc.created!=null && this.created!=null) { if (!desc.created.equals(this.created)) match = false; } if (desc.location!=null && this.location!=null) { if (!desc.location.equals(this.location)) match = false; } if (desc.ontologyChangeSet!=null && this.ontologyChangeSet!=null) { if (!desc.ontologyChangeSet.equals(this.ontologyChangeSet)) match = false; } return match; } return false; } /* * Serialize the Description object into a String * Dont write all its components, only those needed to represent * SwoopChange objects i.e. author of change, date, comment on change, * uris the change refers to and serialized version of the change object */ public String serializeIntoString(SwoopModel swoopModel) throws OWLException { String ser = ""; ser = "AUTHOR={"+ this.author + "}"+separator; ser += "DATE={"+ this.created + "}"+separator; ser += "COMMENT={" + this.annotatedEntityDefinition + "}"+separator; ser += "BODY={" + this.body + "}"+separator; ser += "URIS = {"; for (int i=0; i<this.annotates.length; i++) { ser += this.annotates[i].toString() + ","; } ser += "}"+separator; if (this.ontologyChangeSet.size()>0) { // serialize changes in RDF/XML and add them in the BODY ChangeLog clog = new ChangeLog(null, swoopModel); OntologyChangeRenderer oc = new OntologyChangeRenderer(clog); OWLOntology changeOnt = oc.serializeOntologyChanges(this.ontologyChangeSet); CorrectedRDFRenderer rdfRend = new CorrectedRDFRenderer(); StringWriter st = new StringWriter(); try { rdfRend.renderOntology(changeOnt, st); } catch (RendererException e) { e.printStackTrace(); } ser += "CHANGE={" + st.toString() + "}"+separator; } return ser; } /* * Deserialize a description string into Description object */ public void deserializeFromString(String ser, SwoopModel swoopModel) throws OWLException { String[] parts = splitString(ser); this.author = this.getBracketed(parts[0]); this.created = this.getBracketed(parts[1]); this.annotatedEntityDefinition = this.getBracketed(parts[2]); this.body = this.getBracketed(parts[3]); String uris = this.getBracketed(parts[4]); String[] uriparts = uris.split(","); this.annotates = new URI[uriparts.length]; for (int i=0; i<uriparts.length; i++) { try { this.annotates[i] = new URI(uriparts[i]); } catch (URISyntaxException e) { e.printStackTrace(); } } String body = this.getBracketed(parts[5]); // deserialize body to get change set ChangeLog clog = new ChangeLog(null, swoopModel); OntologyChangeRenderer oc = new OntologyChangeRenderer(clog); OWLOntology changeOnt = swoopModel.loadOntologyInRDF(new StringReader(body), URI.create("")); this.ontologyChangeSet = oc.deserializeOntologyChanges(changeOnt); } private String getBracketed(String part) { return part.substring(part.indexOf("{")+1, part.lastIndexOf("}")); } private String[] splitString(String str) { List parts = new ArrayList(); int pointer = 0; while (str.indexOf(separator, pointer)>=0) { String part = str.substring(pointer, str.indexOf(separator, pointer)); pointer = str.indexOf(separator, pointer)+1; parts.add(part); } Object[] obj = parts.toArray(); String[] spl = new String[obj.length]; for (int i=0; i<obj.length; i++) { spl[i] = obj[i].toString(); } return spl; } }