/*******************************************************************************
* Copyright 2014 Miami-Dade County
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.sharegov.cirm;
import static org.sharegov.cirm.OWL.fullIri;
import static org.sharegov.cirm.OWL.owlClass;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import org.semanticweb.owlapi.model.AddAxiom;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLDataProperty;
import org.semanticweb.owlapi.model.OWLDataPropertyAssertionAxiom;
import org.semanticweb.owlapi.model.OWLDataRange;
import org.semanticweb.owlapi.model.OWLDatatype;
import org.semanticweb.owlapi.model.OWLEntity;
import org.semanticweb.owlapi.model.OWLIndividual;
import org.semanticweb.owlapi.model.OWLLiteral;
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLObjectPropertyAssertionAxiom;
import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyChange;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.model.RemoveAxiom;
import org.semanticweb.owlapi.reasoner.BufferingMode;
import org.semanticweb.owlapi.reasoner.OWLReasoner;
import org.semanticweb.owlapi.vocab.OWL2Datatype;
import org.sharegov.cirm.event.ClearOWLEntityCacheForSrTypeModification;
import org.sharegov.cirm.rest.OWLIndividuals;
import org.sharegov.cirm.utils.GenUtils;
import org.sharegov.cirm.utils.ThreadLocalStopwatch;
import mjson.Json;
/**
*
* @author chirino, hilpold
*
* Utility wrapper over Meta Ontology operations
*
*/
public class MetaOntology
{
private static String PREFIX = "legacy:";
public static final int RESOLVE_ALL_IRI_MAX_DEPTH = 5;
/*
* Generic Ontology handling functions.
*/
public static void setPrefix(String p){
PREFIX = p;
}
public static List<OWLOntologyChange> getReplaceObjectAnnotationChanges (String individualID, String newAnnotationContent){
OWLOntology O = OWL.ontology();
//get the individual
OWLEntity entity = OWL.dataFactory().getOWLNamedIndividual(OWL.fullIri(PREFIX + individualID));
String existingLabel = OWL.getEntityLabel(entity);
//create existing annotation
OWLAnnotationAssertionAxiom toRemove = OWL.dataFactory().getOWLAnnotationAssertionAxiom(
entity.getIRI(), OWL.dataFactory().getOWLAnnotation(OWL.annotationProperty("http://www.w3.org/2000/01/rdf-schema#label"), OWL.dataFactory().getOWLLiteral(existingLabel)));
//create new annotation
OWLAnnotationAssertionAxiom toAdd = OWL.dataFactory().getOWLAnnotationAssertionAxiom(
entity.getIRI(), OWL.dataFactory().getOWLAnnotation(OWL.annotationProperty("http://www.w3.org/2000/01/rdf-schema#label"), OWL.dataFactory().getOWLLiteral(newAnnotationContent)));
RemoveAxiom removeAxiom = new RemoveAxiom(O, toRemove);
AddAxiom addAxiom = new AddAxiom(O, toAdd);
List<OWLOntologyChange> changes = new ArrayList<OWLOntologyChange>();
changes.add(removeAxiom);
changes.add(addAxiom);
return changes;
}
public static <Type> OWLLiteral createTypedLiteral (Type value){
OWLOntologyManager manager = OWL.manager();
OWLDataFactory factory = manager.getOWLDataFactory();
if (value instanceof Boolean) {
return factory.getOWLLiteral((Boolean) value);
} else if (value instanceof String){
return factory.getOWLLiteral((String) value);
} else if (value instanceof Integer){
return factory.getOWLLiteral((Integer) value);
} else if (value instanceof Float){
return factory.getOWLLiteral((Float) value);
} else if (value instanceof Double){
return factory.getOWLLiteral((Double) value);
} else {
throw new RuntimeException("Invalid parameter tyoe: " + value.getClass().toString());
}
}
public static <Type> List<OWLOntologyChange> getReplaceIndividualLiteralPropertyChanges (String individualID, String propertyID, Type newValue) {
List<OWLOntologyChange> changes = getRemoveIndividualPropertyChanges(individualID, propertyID);
changes.add(getIndividualLiteralAddAxiom (individualID, propertyID, newValue));
return changes;
}
public static <Type> AddAxiom getIndividualLiteralAddAxiom (String individualID, String propertyID, Type newValue){
OWLOntology O = OWL.ontology();
String ontologyIri = Refs.defaultOntologyIRI.resolve();
if (O == null) {
throw new RuntimeException("Ontology not found: " + ontologyIri);
}
OWLOntologyManager manager = OWL.manager();
OWLDataFactory factory = manager.getOWLDataFactory();
OWLNamedIndividual individual = factory.getOWLNamedIndividual(OWL.fullIri(PREFIX + individualID));
OWLDataProperty property = factory.getOWLDataProperty(OWL.fullIri(PREFIX + propertyID));
OWLLiteral newLiteralValue = createTypedLiteral(newValue);
OWLDataPropertyAssertionAxiom addAssertion = factory.getOWLDataPropertyAssertionAxiom(property, individual, newLiteralValue);
return new AddAxiom(O, addAssertion);
}
public static List <RemoveAxiom> getIndividualLiteralRemoveAxioms (String individualID, String propertyID){
OWLOntology O = OWL.ontology();
String ontologyIri = Refs.defaultOntologyIRI.resolve();
if (O == null) {
throw new RuntimeException("Ontology not found: " + ontologyIri);
}
OWLOntologyManager manager = OWL.manager();
OWLDataFactory factory = manager.getOWLDataFactory();
OWLNamedIndividual individual = factory.getOWLNamedIndividual(OWL.fullIri(PREFIX + individualID));
OWLDataProperty property = factory.getOWLDataProperty(OWL.fullIri(PREFIX + propertyID));
Set<OWLLiteral> propValues = OWL.reasoner().getDataPropertyValues(individual, property);
List<RemoveAxiom> result = new ArrayList<RemoveAxiom>();
if (propValues.isEmpty()){
// Axioms not found
return result;
}
for (OWLLiteral value : propValues) {
OWLDataPropertyAssertionAxiom removeAssertion = factory.getOWLDataPropertyAssertionAxiom(property, individual, value);
result.add(new RemoveAxiom(O, removeAssertion));
}
return result;
}
public static List<OWLOntologyChange> getRemoveIndividualPropertyChanges (String individualID, String propertyID){
List<RemoveAxiom> axioms = getIndividualLiteralRemoveAxioms (individualID, propertyID);
List<OWLOntologyChange> result = new ArrayList<OWLOntologyChange>();
if (axioms.isEmpty()){
return result;
}
for (RemoveAxiom axiom : axioms) {
result.add(axiom);
}
return result;
}
public static List <RemoveAxiom> getIndividualObjectPropertyRemoveAxioms (String individualID, String propertyID){
OWLOntology O = OWL.ontology();
String ontologyIri = Refs.defaultOntologyIRI.resolve();
if (O == null) {
throw new RuntimeException("Ontology not found: " + ontologyIri);
}
OWLOntologyManager manager = OWL.manager();
OWLDataFactory factory = manager.getOWLDataFactory();
OWLNamedIndividual individual = factory.getOWLNamedIndividual(OWL.fullIri(PREFIX + individualID));
OWLObjectPropertyExpression property = factory.getOWLObjectProperty(OWL.fullIri(PREFIX + propertyID));
Set <OWLNamedIndividual> propObjects = OWL.reasoner().getObjectPropertyValues(individual, property).getFlattened();
List<RemoveAxiom> result = new ArrayList<RemoveAxiom>();
if (propObjects.isEmpty()){
// Axioms not found
return result;
}
for (OWLNamedIndividual value : propObjects) {
OWLObjectPropertyAssertionAxiom removeAssertion = factory.getOWLObjectPropertyAssertionAxiom(property, individual, value);
result.add(new RemoveAxiom(O, removeAssertion));
}
return result;
}
public static List<OWLOntologyChange> getRemoveIndividualObjectPropertyChanges (String individualID, String propertyID){
List<RemoveAxiom> axioms = getIndividualObjectPropertyRemoveAxioms (individualID, propertyID);
List<OWLOntologyChange> result = new ArrayList<OWLOntologyChange>();
if (axioms.isEmpty()){
return result;
}
for (RemoveAxiom axiom : axioms) {
result.add(axiom);
}
return result;
}
public static List<OWLOntologyChange> getRemoveIndividualObjectPropertyChanges (String individualID){
OWLOntology O = OWL.ontology();
String ontologyIri = Refs.defaultOntologyIRI.resolve();
if (O == null) {
throw new RuntimeException("Ontology not found: " + ontologyIri);
}
OWLOntologyManager manager = OWL.manager();
OWLDataFactory factory = manager.getOWLDataFactory();
OWLIndividual individual = factory.getOWLNamedIndividual(fullIri(PREFIX + individualID));
return getRemoveOnlyPropertiesIndividualChanges (individual);
}
public static List<OWLOntologyChange> getRemoveIndividualObjectPropertyReferenceChanges (String parentID, String propertyID, String individualID){
OWLOntology O = OWL.ontology();
String ontologyIri = Refs.defaultOntologyIRI.resolve();
if (O == null) {
throw new RuntimeException("Ontology not found: " + ontologyIri);
}
OWLOntologyManager manager = OWL.manager();
OWLDataFactory factory = manager.getOWLDataFactory();
OWLNamedIndividual newInd = OWL.individual(PREFIX + individualID);
OWLIndividual parent = factory.getOWLNamedIndividual(fullIri(PREFIX + parentID));
OWLObjectProperty property = factory.getOWLObjectProperty(fullIri(PREFIX + propertyID));
List<OWLOntologyChange> result = new ArrayList<OWLOntologyChange>();
result.add(new RemoveAxiom(O, factory.getOWLObjectPropertyAssertionAxiom(property, parent, newInd)));
return result;
}
/*
* create a list of changes to be commited in order to create a new new individual
*
*/
public static List<OWLOntologyChange> getCreateIndividualObjectFromJsonChanges (Json data){
String ontologyIri = Refs.defaultOntologyIRI.resolve();
OWLOntology O = OWL.ontology(ontologyIri);
if (O == null) {
throw new RuntimeException("Ontology not found: " + ontologyIri);
}
OWLOntologyManager manager = OWL.manager();
OWLDataFactory factory = manager.getOWLDataFactory();
List<OWLOntologyChange> result = new ArrayList<OWLOntologyChange>();
if (data.isObject()){
if (!data.has("iri")){
throw new RuntimeException("root iri not found : " + data.toString());
}
String iri = getIdFromUri(data.at("iri").asString());
String prefix = correctedPrefix (iri);
OWLNamedIndividual newInd = OWL.individual(prefix + iri);
result.addAll(makeObjectIndividual (newInd, data, O, manager, factory));
}
if (data.isArray()){
for (Json e: data.asJsonList()){
if (e.isObject()){
if (!e.has("iri")){
throw new IllegalArgumentException("Cannot find iri property for question: "+ e.asString());
}
} else {
throw new IllegalArgumentException("element is not an object: "+ e.asString());
}
String iri = getIdFromUri(e.at("iri").asString());
String prefix = correctedPrefix (iri);
OWLNamedIndividual newInd = OWL.individual(prefix + iri);
result.addAll(makeObjectIndividual (newInd, e, O, manager, factory));
}
}
return result;
}
/*
* function creates a new named individual using properties described on the json structure and attach it to the parent on property described by propertyID.
*
*/
public static List<OWLOntologyChange> getAddIndividualObjectFromJsonChanges (String parentID, String propertyID, Json data){
String ontologyIri = Refs.defaultOntologyIRI.resolve();
OWLOntology O = OWL.ontology(ontologyIri);
if (O == null) {
throw new RuntimeException("Ontology not found: " + ontologyIri);
}
OWLOntologyManager manager = OWL.manager();
OWLDataFactory factory = manager.getOWLDataFactory();
List<OWLOntologyChange> result = new ArrayList<OWLOntologyChange>();
if (data.isObject()){
if (!data.has("iri")){
throw new RuntimeException("root iri not found : " + data.toString());
}
String iri = getIdFromUri(data.at("iri").asString());
String prefix = correctedPrefix (iri);
OWLNamedIndividual newInd = OWL.individual(prefix + iri);
result.addAll(makeObjectIndividual (newInd, data, O, manager, factory));
OWLIndividual parent = factory.getOWLNamedIndividual(fullIri(PREFIX + parentID));
OWLObjectProperty property = factory.getOWLObjectProperty(fullIri(PREFIX + propertyID));
result.add(new AddAxiom(O, factory.getOWLObjectPropertyAssertionAxiom(property, parent, newInd)));
}
if (data.isArray()){
for (Json e: data.asJsonList()){
if (e.isObject()){
if (!e.has("iri")){
throw new IllegalArgumentException("Cannot find iri property for question: "+ e.asString());
}
} else {
throw new IllegalArgumentException("element is not an object: "+ e.asString());
}
String iri = getIdFromUri(e.at("iri").asString());
String prefix = correctedPrefix (iri);
OWLNamedIndividual newInd = OWL.individual(prefix + iri);
result.addAll(makeObjectIndividual (newInd, e, O, manager, factory));
OWLIndividual parent = factory.getOWLNamedIndividual(fullIri(PREFIX + parentID));
OWLObjectProperty property = factory.getOWLObjectProperty(fullIri(PREFIX + propertyID));
result.add(new AddAxiom(O, factory.getOWLObjectPropertyAssertionAxiom(property, parent, newInd)));
}
}
return result;
}
public static List<OWLOntologyChange> getAddIndividualObjectProperty (String parentID, String propertyID, String propertyValue){
String ontologyIri = Refs.defaultOntologyIRI.resolve();
OWLOntology O = OWL.ontology(ontologyIri);
List<OWLOntologyChange> result = new ArrayList<OWLOntologyChange>();
result.add(new AddAxiom(O, getObjectPropertyAxiom( O, parentID, propertyID, propertyValue) ));
return result;
}
public static List<OWLOntologyChange> getRemoveIndividualObjectProperty (String parentID, String propertyID, String propertyValue){
String ontologyIri = Refs.defaultOntologyIRI.resolve();
OWLOntology O = OWL.ontology(ontologyIri);
List<OWLOntologyChange> result = new ArrayList<OWLOntologyChange>();
result.add(new RemoveAxiom(O, getObjectPropertyAxiom( O, parentID, propertyID, propertyValue) ));
return result;
}
public static OWLNamedIndividual getMetaIndividual (String individualID){
OWLOntologyManager manager = OWL.manager();
OWLDataFactory factory = manager.getOWLDataFactory();
return factory.getOWLNamedIndividual(fullIri(PREFIX + individualID));
}
public static OWLAxiom getObjectPropertyAxiom(OWLOntology O, String parentID, String propertyID, String objectPropertyValue){
String ontologyIri = Refs.defaultOntologyIRI.resolve();
if (O == null) {
throw new RuntimeException("Ontology not found: " + ontologyIri);
}
OWLOntologyManager manager = OWL.manager();
OWLDataFactory factory = manager.getOWLDataFactory();
OWLIndividual existingInd = factory.getOWLNamedIndividual(fullIri(PREFIX + objectPropertyValue));
OWLIndividual parent = factory.getOWLNamedIndividual(fullIri(PREFIX + parentID));
OWLObjectProperty property = factory.getOWLObjectProperty(fullIri(PREFIX + propertyID));
return factory.getOWLObjectPropertyAssertionAxiom(property, parent, existingInd);
}
/*
* function creates a new named idividual using properties described on the newData json structure and replace it to the parent on property described by propertyID by removing the object represented by oldData.
*
*/
public static List<OWLOntologyChange> getAddReplaceIndividualObjectPropertyFromJsonChanges (String parentID, String propertyID, Json newData, Json oldData){
OWLOntology O = OWL.ontology();
String ontologyIri = Refs.defaultOntologyIRI.resolve();
if (O == null) {
throw new RuntimeException("Ontology not found: " + ontologyIri);
}
if (!newData.has("iri")){
throw new RuntimeException("root iri not found : " + newData.toString());
}
OWLOntologyManager manager = OWL.manager();
OWLDataFactory factory = manager.getOWLDataFactory();
OWLIndividual newInd = factory.getOWLNamedIndividual(fullIri(PREFIX + newData.at("iri").asString()));
OWLIndividual oldInd = factory.getOWLNamedIndividual(fullIri(PREFIX + oldData.at("iri").asString()));
List<OWLOntologyChange> result = getRemoveAllPropertiesIndividualChanges (oldInd);
result.addAll(makeObjectIndividual (newInd, newData, O, manager, factory));
OWLIndividual parent = factory.getOWLNamedIndividual(fullIri(PREFIX + parentID));
OWLObjectProperty property = factory.getOWLObjectProperty(fullIri(PREFIX + propertyID));
result.add(new AddAxiom(O, factory.getOWLObjectPropertyAssertionAxiom(property, parent, newInd)));
return result;
}
private static boolean isIdenticalOppositeAxion (OWLOntologyChange a, OWLOntologyChange b){
return (a.getAxiom().equals(b.getAxiom()) && a.getClass() != b.getClass());
}
private static boolean isIdenticalAxion (OWLOntologyChange a, OWLOntologyChange b){
return (a.getAxiom().equals(b.getAxiom()) && a.getClass() == b.getClass());
}
public static List<OWLOntologyChange> clearChanges (List<OWLOntologyChange> changes){
// Mark duplicates
List<Integer> toRemove = new ArrayList<>();
int lim = changes.size();
for (int i=0; i<lim; i++){
if (!toRemove.contains(i)){
for (int j=i+1;j<lim; j++){
if (!toRemove.contains(j)){
if (isIdenticalAxion(changes.get(i), changes.get(j))){
toRemove.add(j);
}
}
}
}
}
// Filter the results
for (int i=lim-1; i>-1; i--){
if (toRemove.contains(i)){
changes.remove(i);
}
}
lim = changes.size();
toRemove.clear();
for (int i=0; i<lim; i++){
if (!toRemove.contains(i)){
for (int j=0;j<lim; j++)
if (i!=j){
if (!toRemove.contains(j)){
if (isIdenticalOppositeAxion(changes.get(i), changes.get(j))){
toRemove.add(i);
toRemove.add(j);
continue;
}
}
}
}
}
for (int i=lim-1; i>-1; i--){
if (toRemove.contains(i)){
changes.remove(i);
}
}
lim = changes.size();
toRemove.clear();
for (int i=0; i<lim; i++){
OWLOntologyChange changex = changes.get(i);
if (changex.getClass().toString().contains("Add")){
for (OWLOntology o : OWL.ontologies()) {
if (o.containsAxiom(changex.getAxiom())) {
toRemove.add(i);
}
}
}
}
for (int i=lim-1; i>-1; i--){
if (toRemove.contains(i)){
changes.remove(i);
}
}
return changes;
}
public static List<OWLOntologyChange> getRemoveAllPropertiesIndividualChanges (OWLIndividual individual){
List<OWLOntologyChange> L = new ArrayList<OWLOntologyChange>();
for (OWLOntology O: OWL.ontologies()){
for (OWLAxiom a : O.getDeclarationAxioms((OWLEntity)individual)) L.add(new RemoveAxiom(O, a));
for (OWLAxiom a : O.getReferencingAxioms((OWLEntity)individual)) L.add(new RemoveAxiom(O, a));
for (OWLAxiom a : O.getDataPropertyAssertionAxioms(individual)) L.add(new RemoveAxiom(O, a));
for (OWLAxiom a : O.getObjectPropertyAssertionAxioms(individual)) L.add(new RemoveAxiom(O, a));
for (OWLAxiom a : O.getAnnotationAssertionAxioms(((OWLEntity) individual).getIRI())) L.add(new RemoveAxiom(O, a));
for (OWLAxiom a : O.getClassAssertionAxioms(individual)) L.add(new RemoveAxiom(O, a));
}
return L;
}
public static List<OWLOntologyChange> getRemoveOnlyPropertiesIndividualChanges (OWLIndividual individual){
List<OWLOntologyChange> L = new ArrayList<OWLOntologyChange>();
for (OWLOntology O: OWL.ontologies()){
for (OWLAxiom a : O.getDeclarationAxioms((OWLEntity)individual)) L.add(new RemoveAxiom(O, a));
for (OWLAxiom a : O.getDataPropertyAssertionAxioms(individual)) L.add(new RemoveAxiom(O, a));
for (OWLAxiom a : O.getObjectPropertyAssertionAxioms(individual)) L.add(new RemoveAxiom(O, a));
for (OWLAxiom a : O.getAnnotationAssertionAxioms(((OWLEntity) individual).getIRI())) L.add(new RemoveAxiom(O, a));
for (OWLAxiom a : O.getClassAssertionAxioms(individual)) L.add(new RemoveAxiom(O, a));
}
return L;
}
protected static PropertyDescriptor findPropertyIri(String iriFragment) {
PropertyDescriptor result = new PropertyDescriptor();
Json prefixes = Json.array().add("legacy:").add("mdc:").add("legacy:");
for (Json prefix : prefixes.asJsonList()) {
IRI propIri = fullIri(prefix.asString() + iriFragment);
OWLOntology o = OWL.ontology();
if (o.containsObjectPropertyInSignature(propIri, true)) {
result.setIri(propIri);
result.setType(PropertyType.OBJECT);
return result;
} else if (o.containsDataPropertyInSignature(propIri, true)) {
result.setIri(propIri);
result.setType(PropertyType.DATA);
return result;
} else if (o.containsAnnotationPropertyInSignature(propIri, true)) {
result.setIri(propIri);
result.setType(PropertyType.ANNOTATION);
return result;
} // else try other prefix -
// FIX
}
return null;
}
protected static String getClassPrefix (String iriFragment){
Json prefixes = Json.array().add("mdc:").add(":").add("legacy:");
for (Json prefix : prefixes.asJsonList()) {
IRI propIri = fullIri(prefix.asString() + iriFragment);
for (OWLOntology o : OWL.ontologies()) {
if (o.containsClassInSignature(propIri)) {
return prefix.asString();
}
}
}
return null;
}
protected static String detectIndividualPrefix (String iriFragment){
Json prefixes = Json.array().add("mdc:").add(":").add("legacy:");
for (Json prefix : prefixes.asJsonList()) {
IRI propIri = fullIri(prefix.asString() + iriFragment);
for (OWLOntology o : OWL.ontologies()) {
if (o.containsIndividualInSignature(propIri)) {
return prefix.asString();
}
}
}
return null;
}
protected static String correctedPrefix (String iriFragment){
String detected = detectIndividualPrefix(iriFragment);
if (detected == null){
return "legacy:";
} else {
return detected;
}
}
protected static void handleClassesArray (Json result, Json e){
if (!result.isArray()) result = Json.array();
if (e.isArray()){
for (Json v: e.asJsonList()){
handleClassesArray(result, v);
}
}
else if (e.isString()){
result.add(e.asString());
}
}
public static List<OWLOntologyChange> addNewClassAssertion (OWLIndividual parent, Json e, OWLOntology O, OWLDataFactory factory){
List<OWLOntologyChange> result = new ArrayList<OWLOntologyChange>();
Json classes = Json.array();
handleClassesArray (classes, e);
for (Json v: classes.asJsonList()){
String classPrefix = getClassPrefix(v.asString());
if (classPrefix == null) throw new RuntimeException("Undeclared OWL class: " + v.asString());
result.add(new AddAxiom(O, factory.getOWLClassAssertionAxiom(owlClass(fullIri(classPrefix + v.asString())),parent)));
}
return result;
}
/*
* Refactored code coming from BOntology class
*
*/
protected static List<OWLOntologyChange> makeObjectIndividual (OWLIndividual parent, Json properties, OWLOntology O, OWLOntologyManager manager, OWLDataFactory factory){
List<OWLOntologyChange> result = new ArrayList<OWLOntologyChange>();
if (properties.asJsonMap().containsKey("reference")) {
return result;
}
result.addAll(getRemoveOnlyPropertiesIndividualChanges(parent));
for (Map.Entry<String, Json> e : properties.asJsonMap().entrySet())
{
String key = e.getKey();
Json value = e.getValue();
if (key.equals("label") || key.equals("iri") || key.equals("type") || key.equals("extendedTypes") || key.equals("transient$protected") || key.equals("comment"))
{
if (key.equals("type") || key.equals("extendedTypes")){
result.addAll(addNewClassAssertion (parent, e.getValue(), O, factory));
} else if (key.equals("label")){
result.add(new AddAxiom(O,factory.getOWLAnnotationAssertionAxiom(((OWLEntity) parent).getIRI(),
factory.getOWLAnnotation(OWL.annotationProperty("http://www.w3.org/2000/01/rdf-schema#label"),
factory.getOWLLiteral(value.asString())))));
} else if (key.equals("comment")){
result.add(new AddAxiom(O,factory.getOWLAnnotationAssertionAxiom(((OWLEntity) parent).getIRI(),
factory.getOWLAnnotation(OWL.annotationProperty("http://www.w3.org/2000/01/rdf-schema#comment"),
factory.getOWLLiteral(value.asString())))));
}
continue;
}
PropertyDescriptor pd = findPropertyIri(key);
if (pd == null) throw new RuntimeException("Unknown OWL property or annotation for key: " + key);
if (pd.getType() == PropertyType.UNKNOWN) throw new RuntimeException("Undeclared OWL property or annotation: " + pd.getIri());
IRI propIri = pd.getIri();
if (pd.getType() == PropertyType.OBJECT)
{
if (value.isArray())
{
for (int i = 0; i < e.getValue().asList().size(); i++)
{
result.addAll(addObjectProperty(parent, OWL.dataFactory().getOWLObjectProperty(propIri), value.at(i), O, manager, factory));
}
}
else
result.addAll(addObjectProperty(parent, OWL.dataFactory().getOWLObjectProperty(propIri), value, O, manager, factory));
}
else if (pd.getType() == PropertyType.DATA)
{
if (value.isArray())
{
for (int i = 0; i < e.getValue().asList().size(); i++)
{
result.addAll(addDataProperty(parent, OWL.dataFactory().getOWLDataProperty(propIri), value.at(i), O, manager, factory));
}
}
else
result.addAll(addDataProperty(parent, OWL.dataFactory().getOWLDataProperty(propIri), value, O, manager, factory));
}
else if (pd.getType() == PropertyType.ANNOTATION){
// TO-DO
}
}
return result;
}
protected static List<OWLOntologyChange> addObjectProperty(OWLIndividual ind, OWLObjectProperty prop, Json value, OWLOntology O, OWLOntologyManager manager, OWLDataFactory factory)
{
List<OWLOntologyChange> result = new ArrayList<OWLOntologyChange>();
if (value.isObject())
{
if (value.has("iri")){
String iri = value.at("iri").asString();
if (iri.contains("#")){
iri = getIdFromUri(iri);
}
String prefix = correctedPrefix(iri);
OWLNamedIndividual object = factory.getOWLNamedIndividual(fullIri(prefix + iri));
result.add(new AddAxiom(O, factory.getOWLObjectPropertyAssertionAxiom(prop, ind, object)));
result.addAll(setPropertiesFor(object, value, O, manager, factory));
}
else
{
throw new RuntimeException("Missing iri on Object Property: " + value.asString());
}
}
else{
String iri = value.asString();
if (iri.contains("#")){
iri = getIdFromUri(iri);
}
String prefix = correctedPrefix(iri);
OWLNamedIndividual object = factory.getOWLNamedIndividual(fullIri(prefix + iri));
result.add(new AddAxiom(O, factory.getOWLObjectPropertyAssertionAxiom(prop, ind, object)));
}
return result;
}
protected static List<OWLOntologyChange> setPropertiesFor(OWLNamedIndividual individual, Json properties, OWLOntology O, OWLOntologyManager manager, OWLDataFactory factory)
{
// Remove all data and object properties currently declared on the ontology.
List<OWLOntologyChange> L = new ArrayList<OWLOntologyChange>();
// L.addAll(getRemoveOnlyPropertiesIndividualChanges(individual));
L.addAll(makeObjectIndividual(individual, properties, O, manager, factory));
return L;
}
protected static OWL2Datatype getDataPropertyType (OWLIndividual individual, OWLDataProperty property){
for (OWLOntology O: OWL.ontologies()){
for (OWLAxiom a : O.getDataPropertyAssertionAxioms(individual)) {
Set <OWLDataProperty> p = a.getDataPropertiesInSignature();
if (p.contains(property)){
Set <OWLDatatype> s = a.getDatatypesInSignature();
for (OWLDatatype type: s){
return type.getBuiltInDatatype();
}
}
}
}
return null;
}
protected static List<OWLOntologyChange> addDataProperty(OWLIndividual ind, OWLDataProperty prop, Json value, OWLOntology O, OWLOntologyManager manager, OWLDataFactory factory)
{
List<OWLOntologyChange> result = new ArrayList<OWLOntologyChange>();
OWLLiteral literal;
String valueStr;
OWL2Datatype xsdType;
if (value.isObject())
{
String typeStr = value.at("type").asString();
if (value.at("literal").isArray())
throw new RuntimeException(
"The value of the dataProperty cannot be an Array, individual is: "
+ ind.asOWLNamedIndividual().getIRI()
+ " property is: " + prop.getIRI()
+ " value is: " + value.at("literal"));
valueStr = value.at("literal").asString();
xsdType = OWL2Datatype.getDatatype(OWL.fullIri(PREFIX + typeStr));// IRI.create(typeStr));
if (xsdType == null)
throw new IllegalArgumentException(
"Unable to read type for Json value." + value);
}
else
{
xsdType = getDataPropertyType(ind, prop);
if (!value.isNull())
{
//TODO: add asString() in BooleanJson function and remove this if condition
if(value.isBoolean())
valueStr = value.toString();
else
valueStr = value.asString();
}
else
{
valueStr = null;
}
}
if (valueStr == null || valueStr.isEmpty())
{
System.err.println("Empty or null string JSON detected. No BO axiom created. Individual was: "
+ ind + " dataproperty was: " + prop);
return result;
}
literal = toLiteral(factory, prop, valueStr, xsdType);
if (literal == null)
literal = factory.getOWLLiteral(valueStr);
OWLAxiom axiom = factory.getOWLDataPropertyAssertionAxiom(prop, ind, literal);
result.add(new AddAxiom(O, axiom));
return result;
}
private static OWLLiteral toLiteral(OWLDataFactory factory, OWLDataProperty prop, String value, OWL2Datatype builtinDatatype)
{
// Parse out if the value is an ISO date and convert it to the format XML datafactory accepts.
if (builtinDatatype == null || builtinDatatype.equals(OWL2Datatype.XSD_DATE_TIME_STAMP))
{
try { return dateLiteral(factory, GenUtils.parseDate(value), OWL2Datatype.XSD_DATE_TIME_STAMP); }
catch (Throwable t) { }
}
//TODO we could validate here, if the value string matches the builtinDatatype.
if (builtinDatatype != null){
return factory.getOWLLiteral(value, builtinDatatype);
}
Set<OWLDataRange> ranges = prop.getRanges(OWL.ontologies());
for (OWLDataRange range : ranges)
{
if (range instanceof OWLDatatype)
{
return factory.getOWLLiteral(value, (OWLDatatype)range);
}
}
return null;
}
private static OWLLiteral dateLiteral(OWLDataFactory factory, Date date, OWL2Datatype d)
{
OWLLiteral result = factory.getOWLLiteral("", d);
if(date == null)
return result;
try
{
//see:
//http://download.oracle.com/javase/6/docs/api/javax/xml/datatype/XMLGregorianCalendar.html#getXMLSchemaType()
Calendar c = Calendar.getInstance();
c.setTime(date);
XMLGregorianCalendar x = DatatypeFactory.newInstance().newXMLGregorianCalendar();
if(c instanceof GregorianCalendar)
if(DatatypeConstants.DATE.getNamespaceURI().equals(d.getIRI().toString()))
{
x.setYear(c.get(Calendar.YEAR));
x.setMonth(c.get(Calendar.MONTH));
x.setDay(c.get(Calendar.DAY_OF_MONTH));
result = factory.getOWLLiteral(x.toXMLFormat(),d);
}
else
result = factory.getOWLLiteral(DatatypeFactory.newInstance().newXMLGregorianCalendar((GregorianCalendar)c).toXMLFormat(), d);
}
catch(Exception e)
{
String msg = "Exception occured while attempting to extract a xsd date value";
throw new RuntimeException(msg);
}
return result;
}
/*
* Utility functions
*
*/
public static String getOntologyFromUri(String uri){
return uri.substring(uri.lastIndexOf("/")+1,uri.indexOf("#"));
}
public static String getOntologyFromIdentifier(String uri){
return uri.replace("http:", "").substring(uri.lastIndexOf("/")+1,uri.indexOf(":"));
}
public static String getIndividualOntologyPrefix(String id){
if (id.replace("http:", "").contains(":")) return getOntologyFromIdentifier(id);
else if (id.contains("#")) return getOntologyFromUri(id);
return id;
}
public static String getIdFromUri(String uri)
{
return uri.substring(uri.indexOf("#")+1, uri.length());
}
public static String getIdFromIdentifier(String uri)
{
return uri.replace("http:", "").substring(uri.indexOf(":")+1, uri.length());
}
public static String getIndividualIdentifier(String id){
if (id.replace("http:", "").contains(":")) return getIdFromIdentifier(id);
else if (id.contains("#")) return getIdFromUri(id);
return id;
}
/**
* Clears caches, synchronizes the reasoner and always tests reasoner consistency.
* Synchronization will be conducted only, if the reasoner is in buffering mode.
*
*
* TODO hilpold find the right class for this method.
*
*/
public static void clearCacheAndSynchronizeReasoner() {
synchronized (OWL.reasoner()) {
ThreadLocalStopwatch.startTop("START clearCache");
clearCache();
ThreadLocalStopwatch.now("END clearCache");
ThreadLocalStopwatch.now("START syncReasoner");
synchronizeReasoner();
ThreadLocalStopwatch.now("END syncReasoner");
}
}
/**
* Clears all underlying cache.
*/
public static void clearCache() {
synchronized (OWL.reasoner()) {
ClearOWLEntityCacheForSrTypeModification c = new ClearOWLEntityCacheForSrTypeModification();
c.apply(null, null, null);
}
}
/**
* Synchronizes the reasoner.
* Applies all changes since reasoner initialization to the reasoner.
*/
public static void synchronizeReasoner() {
synchronized (OWL.reasoner()) {
OWLReasoner reasoner = OWL.reasoner();
if (reasoner.getBufferingMode().equals(BufferingMode.BUFFERING)) {
reasoner.flush();
}
if (!reasoner.isConsistent()) throw new IllegalStateException("Reasoner is not consistent. Axioms leading to inconsistency must have been applied since server start or the last call of this method.");
}
}
/**
* Simple method to check if a Json is a fullIRI.
* TODO This needs improvement.
* @param iriCandidate
* @return
*/
public static boolean isFullIriString(Json iriCandidate) {
return iriCandidate.isString()
&& iriCandidate.asString().contains("#")
&& iriCandidate.asString().startsWith("http://");
}
public static boolean isTargetObject (Json candidate, String targetOntology){
if (candidate.isArray()) return true;
Json iriCandidate = null;
if (candidate.isObject() && candidate.has("iri")) {
iriCandidate = candidate.at("iri");
} else {
iriCandidate = candidate;
}
return isFullIriString(iriCandidate) && iriCandidate.isString() && iriCandidate.asString().contains(targetOntology);
}
public static Json getSerializedOntologyObject (String fullIRI){
String individualID = getIndividualIdentifier(fullIRI);
String individualOntology = correctedPrefix(individualID);
OWLIndividuals q = new OWLIndividuals();
Json S = Json.nil();
try {
S = q.doInternalQuery("{" + individualOntology + individualID + "}");
} catch (Exception e) {
System.out.println("Error while querying the Ontology for "+ individualOntology + individualID);
System.out.println("Querying individual's endpoint instead...");
try {
S = q.getOWLIndividualByName(individualOntology + individualID);
System.out.println("Resolved: "+ individualOntology + individualID);
} catch (Exception ex){
System.out.println("Unable to resolve Object: " + individualOntology + individualID);
ex.printStackTrace();
}
}
if (!S.isNull()){
if (S.isArray()){
for (Json ind: S.asJsonList()){
return ind;
}
} else{
return S;
}
}
return S;
}
public static Json resolveIRIs(Json j, String targetOntology){
if (targetOntology == null) targetOntology = "#";
Map<String, Json> objectMap = new ConcurrentHashMap<String, Json>();
Map<String, Boolean> resolutionMap = new ConcurrentHashMap<String, Boolean>();
Json result = j.dup();
mapJsonObject(result, objectMap, targetOntology, 1);
resolveEmptyObjects(objectMap, targetOntology);
String error = "";
if (!checkAllObjects(objectMap, error, targetOntology)){
throw new IllegalArgumentException("Unable to resolve object: " + error);
}
expandJson(result, objectMap, resolutionMap, targetOntology, 1);
return result;
}
private static void mapJsonObject(Json j, Map<String, Json> map, String targetOntology, int depth){
if (j.isObject()) {
Map<String,Json> properties = j.asJsonMap();
for (Map.Entry<String, Json> propKeyValue : properties.entrySet()) {
Json value = propKeyValue.getValue();
if (propKeyValue.getKey().equals("iri")){
if (!map.containsKey(value.asString()) || (map.containsKey(value.asString()) && map.get(value.asString()) == Json.nil())){
map.put(value.asString(), j.dup());
}
} else if (isFullIriString(value)) {
if (!map.containsKey(value.asString())){
if (isTargetObject(value, targetOntology)) {
map.put(value.asString(), Json.nil());
} else {
map.put(value.asString(), value);
}
}
}
if (isTargetObject(value, targetOntology)) {
mapJsonObject(value, map, targetOntology, depth+1);
}
}
} else if (j.isArray()) {
ListIterator<Json> arrayIt = j.asJsonList().listIterator();
while(arrayIt.hasNext()) {
Json elem = arrayIt.next();
if (isFullIriString(elem)) {
if (!map.containsKey(elem.asString())){
if (isTargetObject(elem, targetOntology)) {
map.put(elem.asString(), Json.nil());
} else {
map.put(elem.asString(), elem);
}
}
}
if (isTargetObject(elem, targetOntology)) {
mapJsonObject(elem, map, targetOntology, depth+1);
}
}
} else {
// nothing to do for primitives
}
}
private static void resolveEmptyObjects(Map<String, Json> map, String targetOntology){
boolean newObjects;
do {
newObjects = false;
for (Map.Entry<String, Json> propKeyValue : map.entrySet()) {
if (propKeyValue.getValue().isNull()){
Json value = getSerializedOntologyObject(propKeyValue.getKey());
if (value.isNull()){
throw new IllegalArgumentException("Unable to serialize invividual legacy: " + propKeyValue.getKey());
}
propKeyValue.setValue(value);
if (isTargetObject(value, targetOntology)) {
mapJsonObject(propKeyValue.getValue(), map, targetOntology, 1);
newObjects = true;
}
}
}
}while(newObjects);
}
private static boolean checkAllObjects(Map<String, Json> map, String failedIRI, String targetOntology){
for (Map.Entry<String, Json> propKeyValue : map.entrySet()) {
if (isTargetObject(Json.object().set("iri", propKeyValue.getKey()), targetOntology))
if (propKeyValue.getValue().isNull()||!propKeyValue.getValue().isObject()){
failedIRI = propKeyValue.getKey();
return false;
}
}
return true;
}
private static void expandJson(Json j, Map<String, Json> objectMap, Map<String, Boolean> resolutionMap, String targetOntology, int depth){
if (j.isObject() && isTargetObject(j, targetOntology)) {
if (!j.has("iri")){
throw new IllegalArgumentException("Object missing IRI property: " + j.asString());
}
if (resolutionMap.containsKey(j.at("iri").asString())){
if (resolutionMap.get(j.at("iri").asString())){
// would like to empty j before adding the extended object.
// the line bellow clears the object but null point exception is triggered when trying to use the object after.
// j.asJsonMap().clear();
j.with(objectMap.get(j.at("iri").asString()).dup());
return;
} else {
j.set("reference", true).set("type", "ObjectReference");
//System.out.println("Recursive Definition detected for individual: " + j.at("iri").asString());
return;
}
} else {
resolutionMap.put(j.at("iri").asString(), false);
}
Map<String,Json> properties = j.asJsonMap();
for (Map.Entry<String, Json> propKeyValue : properties.entrySet()) {
if (!propKeyValue.getKey().equals("iri")&&isFullIriString(propKeyValue.getValue())&&isTargetObject(propKeyValue.getValue(), targetOntology)) {
if (!isObjectOnMap(propKeyValue.getValue().asString(), objectMap)){
throw new IllegalArgumentException("Object missing on the map: " + propKeyValue.getValue().asString());
}
propKeyValue.setValue(objectMap.get(propKeyValue.getValue().asString()).dup());
}
expandJson(propKeyValue.getValue(), objectMap, resolutionMap, targetOntology, depth+1);
}
objectMap.put(j.at("iri").asString(), j.dup());
resolutionMap.put(j.at("iri").asString(), true);
} else if (j.isArray()) {
ListIterator<Json> arrayIt = j.asJsonList().listIterator();
while(arrayIt.hasNext()) {
Json elem = arrayIt.next();
if (isFullIriString(elem)&&isTargetObject(elem, targetOntology)) {
if (!isObjectOnMap(elem.asString(), objectMap)){
throw new IllegalArgumentException("Object missing on the map: " + elem.asString());
}
elem = objectMap.get(elem.asString()).dup();
}
expandJson(elem, objectMap, resolutionMap, targetOntology, depth+1);
arrayIt.set(elem);
}
} else {
// nothing to do for primitives
}
}
private static boolean isObjectOnMap(String objectIRI, Map<String, Json> map){
return map.containsKey(objectIRI);
}
protected static boolean individualExists (String individualID){
Json prefixes = Json.array().add("mdc:").add(":").add("legacy:");
for (Json prefix : prefixes.asJsonList()) {
IRI propIri = fullIri(prefix.asString() + individualID);
for (OWLOntology o : OWL.ontologies()) {
if (o.containsIndividualInSignature(propIri)) {
return true;
}
}
}
return false;
}
protected static Json expandRealtedObjects (String id, Json obj){
if (obj.isArray()) {
return expandArray(id, obj);
} else if (obj.isObject()){
return expandObject(id, obj);
}
return obj;
}
private static Json expandArray(String id, Json arr){
ListIterator<Json> arrayIt = arr.asJsonList().listIterator();
while(arrayIt.hasNext()) {
Json elem = arrayIt.next();
if (isFullIriString(elem) && elem.asString().contains("#" + id)) {
elem = getSerializedOntologyObject(elem.asString());
}
elem = expandRealtedObjects(id, elem);
arrayIt.set(elem);
}
return arr;
}
private static Json expandObject(String id, Json obj){
Map<String,Json> properties = obj.asJsonMap();
for (Map.Entry<String, Json> propKeyValue : properties.entrySet()) {
if (!propKeyValue.getKey().equals("iri") && isFullIriString(propKeyValue.getValue()) && propKeyValue.getValue().asString().contains("#" + id)) {
propKeyValue.setValue(getSerializedOntologyObject(propKeyValue.getValue().asString()));
}
propKeyValue.setValue(expandRealtedObjects(id, propKeyValue.getValue()));
}
return obj;
}
public static Json cloneSerializedIndividual(String donor, String dolly){
if (individualExists(dolly)) {
throw new IllegalArgumentException(dolly + " is already present on the Ontology.");
}
String donorPrefix = correctedPrefix(donor);
Json serializedDonor = expandRealtedObjects (donor, getSerializedOntologyObject(donorPrefix + donor));
String strDonor = serializedDonor.toString();
String regex = "\\(?\\b(http://|www[.])[-A-Za-z0-9+&@#/%?=~_()|!:,.;]*[-A-Za-z0-9+&@#/%=~_()|]";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(strDonor);
while(m.find()) {
String urlStr = m.group();
String newIri = urlStr.replace("#" + donor, "#" + dolly);
strDonor = strDonor.replace(urlStr, newIri);
}
return Json.read(strDonor);
}
}