/* * 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.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import au.com.langdale.profiles.ProfileClass.PropertyInfo; import au.com.langdale.xmi.UML; import au.com.langdale.kena.OntModel; import au.com.langdale.kena.OntResource; import au.com.langdale.kena.ResIterator; import com.hp.hpl.jena.vocabulary.OWL; import com.hp.hpl.jena.vocabulary.RDFS; /** * Add or remove a profile class from the profile class hierarchy with side effects. */ public class Refactory extends ProfileUtility { private OntModel model; private ProfileMap map; private String namespace; private OntModel profileModel; public Refactory(OntModel profileModel, OntModel fullModel) { this.profileModel = profileModel; this.model = fullModel; this.namespace = profileModel.getValidOntology().getURI() + "#"; } public OntModel getModel() { return model; } public String getNamespace() { return namespace; } public void refresh() { map = null; } private void add(OntResource clss, OntResource base, boolean link) { if( map != null) map.add(base, clss); if(link) linkToHierarchy(base, clss); } private void linkToHierarchy(OntResource base, OntResource clss) { if( map == null ) buildMap(); Set supers = map.findRelatedProfiles(base, false, true); Set subs = map.findRelatedProfiles(base, true, false); Set affected = new HashSet(); Map profiles = new HashMap(); // consider each super profile Iterator jt = supers.iterator(); while (jt.hasNext()) { OntResource parent = (OntResource) jt.next(); // inherit it clss.addSuperClass(parent); // unlink its sub profiles and mark them Iterator it = subs.iterator(); while (it.hasNext()) { OntResource sub = (OntResource) it.next(); if( sub.hasSuperClass(parent)) { sub.removeSuperClass(parent); affected.add(sub); } } } // consider each sub profile Iterator it = subs.iterator(); while (it.hasNext()) { OntResource sub = (OntResource) it.next(); ProfileClass subprof = new ProfileClass(sub, namespace); // mark it if has no supers Iterator kt = subprof.getSuperClasses(); if( ! kt.hasNext()) { affected.add(sub); } // build a profileclass for any marked sub profile if( affected.contains(sub)) profiles.put(sub, subprof); } // TODO: we could move properties around //PropertyAccumulator props = new PropertyAccumulator(); // relink sub profiles Iterator ht = affected.iterator(); while (ht.hasNext()) { OntResource sub = (OntResource) ht.next(); ProfileClass subprof = (ProfileClass) profiles.get(sub); subprof.addSuperClass(clss); //removeProps(subprof, base, props); } //addProps(profile, props); } public void remove(OntResource clss) { if( map != null) map.removeProfile(clss); // super profiles to be inherited by sub profiles Set supers = asSet(new ProfileClass(clss, namespace).getSuperClasses()); // TODO: properties to be duplicated in sub profiles //PropertyAccumulator props = new PropertyAccumulator(); //collectProps(profile, props); // consider sub profiles Set subs = clss.listSubClasses(true).toSet(); Iterator it = subs.iterator(); while (it.hasNext()) { OntResource sub = (OntResource) it.next(); // unlink superclass sub.removeSuperClass(clss); // aquire its properties //addProps(new ProfileClass(sub), props); // link its superclasses Iterator jt = supers.iterator(); while (jt.hasNext()) sub.addSuperClass((OntResource) jt.next()); } } private void buildMap() { map = new ProfileMap(); Iterator it = ProfileClass.getProfileClasses(profileModel, model); while (it.hasNext()) { ProfileClass profile = (ProfileClass) it.next(); map.add(profile.getBaseClass(), profile.getSubject()); } } public void setByReference() { Iterator it = ProfileClass.getProfileClasses(profileModel, model); while (it.hasNext()) { ProfileClass profile = (ProfileClass) it.next(); setByReference(profile); } } private void setByReference(ProfileClass profile) { Iterator it = profile.getProperties(); while (it.hasNext()) { OntResource prop = (OntResource) it.next(); if( prop.isObjectProperty()) { PropertyInfo info = profile.getPropertyInfo(prop); info.createProfileClass().setReference(true); } } } public void setConcrete() { Iterator it = ProfileClass.getProfileClasses(profileModel, model); while (it.hasNext()) { ProfileClass profile = (ProfileClass) it.next(); profile.setStereotype(UML.concrete, shouldBeConcrete(profile)); } } private boolean shouldBeConcrete(ProfileClass profile) { if( profile.isEnumerated()) return false; ResIterator it = profile.getSubject().listSubClasses(false); while( it.hasNext()) { OntResource sub = it.nextResource(); if(! sub.equals(OWL.Nothing) && ! sub.isAnon() && ! sub.equals(profile.getSubject())) { return false; } } return true; } public static Set asSet(Iterator it) { Set result = new HashSet(); while (it.hasNext()) result.add(it.next()); return result; } public OntResource findOrCreateNamedProfile(OntResource base) { OntResource clss = findNamedProfile(base); if( clss == null ) { clss = getModel().createClass(getNamespace() + base.getLocalName()); clss.addSuperClass(base); add(clss, base, true); } return clss; } private OntResource findNamedProfile(OntResource base) { if( map == null) buildMap(); return map.chooseBestProfile(base); } public Collection findRelatedProfiles(OntResource base, boolean subclass, boolean unique) { if( map == null) buildMap(); return map.findRelatedProfiles(base, subclass, unique); } public OntResource createProfileClass(OntResource base) { String uri = getNamespace() + base.getLocalName(); OntResource probe = getModel().createResource(uri); int ix = 1; while( probe.isClass()) { probe = getModel().createResource(uri + ix); ix++; } OntResource child = getModel().createClass(probe.getURI()); child.addSuperClass(base); add(child, base, ix == 1); return child; } public void createDefaultRange(ProfileClass prof, OntResource prop) { OntResource range = prop.getRange(); if(range != null && range.isClass() && ! range.isDatatype()) { OntResource child = findOrCreateNamedProfile(range); prof.getPropertyInfo(prop).createProfileClass().addUnionMember(child); } } public void createAllProperties(ProfileClass profile, boolean required) { ResIterator it = getModel().listSubjectsWithProperty(RDFS.domain, profile.getBaseClass()); while( it.hasNext()) { OntResource prop = it.nextResource(); if( prop.isFunctionalProperty()) { profile.createAllValuesFrom(prop, required); createDefaultRange(profile, prop); } } } public void createCompleteProfile(OntResource base, boolean required) { createAllProperties(createProfileClass(base), required); } public void createAllProperties(OntResource clss, boolean required) { createAllProperties(new ProfileClass(clss, getNamespace()), required); } }