/* * This software is Copyright 2005,2006,2007,2008 Langdale Consultants. * Langdale Consultants can be contacted at: http://www.langdale.com.au */ package au.com.langdale.profiles; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import au.com.langdale.kena.OntModel; import au.com.langdale.kena.OntResource; import com.hp.hpl.jena.graph.FrontsNode; import com.hp.hpl.jena.graph.Node; import au.com.langdale.kena.ResIterator; import au.com.langdale.kena.Resource; import au.com.langdale.util.NSMapper; import com.hp.hpl.jena.vocabulary.OWL; import com.hp.hpl.jena.vocabulary.RDF; import com.hp.hpl.jena.vocabulary.RDFS; /** * Transform a profile model to match a base model. An <code>NSMapper</code> is * used to map references in profile to entities in the base model. */ public class Remapper implements Runnable { private OntModel profileModel, baseModel; private NSMapper mapper; public Remapper(OntModel profileModel, OntModel baseModel) { this.profileModel = profileModel; this.baseModel = baseModel; mapper = new NSMapper(baseModel); } public void run() { int classes = 0; try { Iterator it = profileModel.listSubjectsWithProperty(RDFS.subClassOf).toSet().iterator(); while( it.hasNext()) { OntResource subject = (OntResource) it.next(); subject.addProperty(RDF.type, OWL.Class); handleClass(subject); classes += 1; } } catch (RuntimeException e) { // TODO Auto-generated catch block e.printStackTrace(); } log("Remapped " + classes + " classes."); } private void handleClass(OntResource clss) { int local_parents = 0; int anon_parents = 0; int foreign_parents = 0; int restricts = 0; boolean envelope = false; Set props = new HashSet(); Set defined = new HashSet(); Set bases = new HashSet(); ResIterator it = clss.listProperties(RDFS.subClassOf); while( it.hasNext()) { OntResource node = it.nextResource(); if( node.isURIResource()) { if( clss.isURIResource() && node.getNameSpace().equals(clss.getNameSpace())) { local_parents += 1; } else if( node.getNameSpace().equals(MESSAGE.NS)) { // it is an envelope definition if(node.equals(MESSAGE.Message)) envelope = true; } else { // inferred that the parent is a base and clss is its profile bases.add(node); foreign_parents += 1; } } else if( node.isAnon() ) { anon_parents += 1; if(node.isClass()) { restricts += 1; rebaseRestriction(clss, props, defined, node); } } else { log("removed invalid superclass node", node); it.remove(); // not a resource } } if( foreign_parents + anon_parents > 0 && !envelope) rebaseClass(clss, bases); log( "properties: total=" + props.size() + " type restricted=" + defined.size(), clss); log( "superclasses: restrictions=" + restricts + " foreign=" + foreign_parents + " local=" + local_parents + " anon=" + (anon_parents-restricts), clss); props.removeAll(defined); defineRanges(clss, props); } private void rebaseClass(OntResource clss, Set bases) { Resource base = null; for (Iterator it = bases.iterator(); it.hasNext();) { OntResource cand = (OntResource) it.next(); Resource mapped = mapper.map(cand, OWL.Class); if( cand.equals(mapped)) base = cand; else if(base == null ) base = mapped; } if( base == null && clss.isURIResource()) base = mapper.map(clss.getLocalName(), OWL.Class); if( base == null) { log("could not find base class for", clss); return; } for (Iterator ir = bases.iterator(); ir.hasNext();) { OntResource cand = (OntResource) ir.next(); if( ! cand.equals(base)) clss.removeSuperClass(cand); } clss.addSuperClass(base); log("rebased profile class", clss); rebaseEnumeration( clss, base ); } private void rebaseEnumeration( OntResource clss, Resource base ) { OntResource list = clss.getOneOf(); if( list == null ) return; if( list.isList()) { int count = 0; Set buf = list.listResourceElements().toSet(); for( Iterator it = buf.iterator(); it.hasNext();) { OntResource node = (OntResource) it.next(); Resource mapped = mapper.map(node, base); if( ! node.equals(mapped)) { list = list.remove(node); if(mapped != null) list = list.cons(mapped); else log("could not find enumeration value", node); count++; } } if(count > 0) { clss.setOneOf(list); log("rebased " + count + " enumeration values", clss); } } else { log("invalid enumeration", clss); } } private void rebaseRestriction(OntResource clss, Set props, Set defined, OntResource restrict) { Resource base = null; ResIterator it = restrict.listProperties(OWL.onProperty); while( it.hasNext()) { OntResource node = it.nextResource(); if( node.isURIResource()) { Resource mapped = mapper.map(node, OWL.ObjectProperty); if( mapped == null ) mapped = mapper.map(node, OWL.DatatypeProperty); if( node.equals(mapped)) base = node; else if(base == null ) base = mapped; } else { log("ignoring malformed restriction for property", node); } } if( base != null ) { OntResource prop = base.inModel(baseModel); restrict.setOnProperty(prop); if( restrict.isAllValuesFromRestriction()) defined.add(prop); else props.add(prop); } else { log("incomplete restriction for class", clss); } } private void defineRanges(OntResource clss, Set props) { Iterator it = props.iterator(); while( it.hasNext()) { OntResource prop = (OntResource) it.next(); OntResource child; if( prop.hasRDFType(OWL.ObjectProperty)) child = profileModel.createClass(); else child = profileModel.createIndividual(RDFS.Datatype); String label = prop.getLabel(null); if( label == null) label = prop.getLocalName(); child.setLabel(label, null); OntResource restrict = profileModel.createAllValuesFromRestriction(null, prop, child); clss.addSuperClass(restrict); } } private void log(String string, Node node) { log(string + ": " + node); } private void log(String string, FrontsNode symbol) { log(string, symbol.asNode()); } private void log(String item) { System.out.println(item); } }