VIVO-42 support for union ranges and other related improvements

This commit is contained in:
brianjlowe 2013-08-26 11:19:40 -04:00
parent e96b3968d7
commit d618f8f51a
12 changed files with 211 additions and 106 deletions

View file

@ -3,6 +3,8 @@
package edu.cornell.mannlib.vitro.webapp.beans;
import java.text.Collator;
import java.util.ArrayList;
import java.util.List;
import org.openrdf.model.impl.URIImpl;
@ -91,6 +93,9 @@ public class VClass extends BaseResourceBean implements Comparable<VClass>
public Float getSearchBoost() { return searchBoost; }
public void setSearchBoost( Float boost ){ searchBoost = boost;}
public boolean isUnion() { return false; }
public List<VClass> getUnionComponents() { return new ArrayList<VClass>(); }
/**
* Default constructor
*/

View file

@ -24,6 +24,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup;
import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.ModelAccess;
import edu.cornell.mannlib.vitro.webapp.dao.VClassDao;
import edu.cornell.mannlib.vitro.webapp.dao.VClassGroupDao;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
@ -44,7 +45,7 @@ public class VclassEditController extends BaseEditController {
EditProcessObject epo = super.createEpo(request, FORCE_NEW);
request.setAttribute("epoKey", epo.getKey());
VClassDao vcwDao = request.getUnfilteredWebappDaoFactory().getVClassDao();
VClassDao vcwDao = ModelAccess.on(getServletContext()).getBaseWebappDaoFactory().getVClassDao();
VClass vcl = (VClass)vcwDao.getVClassByURI(request.getParameter("uri"));
if (vcl == null) {
@ -140,8 +141,8 @@ public class VclassEditController extends BaseEditController {
HashMap formSelect = new HashMap(); // tells the JSP what select lists are populated, and thus should be displayed
request.setAttribute("formSelect",formSelect);
// if supported, we want to show only the asserted superclasses and subclasses. Don't want to see anonymous classes, restrictions, etc.
VClassDao vcDao = request.getUnfilteredAssertionsWebappDaoFactory().getVClassDao();
// if supported, we want to show only the asserted superclasses and subclasses.
VClassDao vcDao = ModelAccess.on(getServletContext()).getBaseWebappDaoFactory().getVClassDao();
List superURIs = vcDao.getSuperClassURIs(vcl.getURI(),false);
List superVClasses = new ArrayList();
Iterator superURIit = superURIs.iterator();

View file

@ -925,8 +925,10 @@ public class JenaBaseDao extends JenaBaseDaoCon {
return null;
if (vitroURIStr.indexOf(PSEUDO_BNODE_NS)==0) {
String idStr = vitroURIStr.split("#")[1];
log.debug("Trying to get bnode " + idStr);
RDFNode rdfNode = ontModel.getRDFNode(Node.createAnon(AnonId.create(idStr)));
if ( (rdfNode != null) && (rdfNode.canAs(OntClass.class)) ) {
log.debug("found it");
cls = rdfNode.as(OntClass.class);
}
} else {

View file

@ -282,8 +282,6 @@ public class ObjectPropertyStatementDaoJena extends JenaBaseDao implements Objec
if("desc".equalsIgnoreCase( sortDirection ) ){
queryString = queryString.replaceAll(" ASC\\(", " DESC(");
}
log.debug("Query string for object property " + propertyUri + ": " + queryString);
Query query = null;
try {
@ -297,10 +295,12 @@ public class ObjectPropertyStatementDaoJena extends JenaBaseDao implements Objec
QuerySolutionMap initialBindings = new QuerySolutionMap();
initialBindings.add("subject", ResourceFactory.createResource(subjectUri));
initialBindings.add("property", ResourceFactory.createResource(propertyUri));
if (rangeUri != null) {
if (rangeUri != null && !rangeUri.startsWith(VitroVocabulary.PSEUDO_BNODE_NS)) {
initialBindings.add("objectType", ResourceFactory.createResource(rangeUri));
}
log.debug("Query string for object property " + propertyUri + ": " + queryString);
// Run the SPARQL query to get the properties
List<Map<String, String>> list = new ArrayList<Map<String, String>>();
DatasetWrapper w = dwf.getDatasetWrapper();
@ -350,13 +350,13 @@ public class ObjectPropertyStatementDaoJena extends JenaBaseDao implements Objec
Model constructedModel = ModelFactory.createDefaultModel();
for (String queryString : constructQueries) {
queryString = queryString.replace("?subject", "<" + subjectUri + ">");
queryString = queryString.replace("?property", "<" + propertyUri + ">");
log.debug("CONSTRUCT query string for object property " +
propertyUri + ": " + queryString);
queryString = queryString.replace("?subject", "<" + subjectUri + ">");
queryString = queryString.replace("?property", "<" + propertyUri + ">");
// we no longer need this query object, but we might want to do this
// query parse step to improve debugging, depending on the error returned
// through the RDF API

View file

@ -16,6 +16,7 @@ import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.hp.hpl.jena.ontology.IntersectionClass;
import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntProperty;
@ -348,7 +349,7 @@ public class PropertyDaoJena extends JenaBaseDao implements PropertyDao {
Statement statement = stmtIter.next();
if ( statement.getSubject().canAs(OntClass.class) ) {
classURISet.addAll(getRelatedClasses(statement.getSubject().as(OntClass.class)));
classURISet.addAll(getRestrictedClasses(statement.getSubject().as(OntClass.class)));
} else {
log.warn("getClassesWithRestrictionOnProperty: Unexpected use of onProperty: it is not applied to a class");
}
@ -381,9 +382,7 @@ public class PropertyDaoJena extends JenaBaseDao implements PropertyDao {
}
/**
* Finds all named superclasses, subclasses and equivalent classes of
* the given class.
*
* Find named classes to which a restriction "applies"
* @param resourceURI identifier of a class
* @return set of class URIs
*
@ -391,13 +390,12 @@ public class PropertyDaoJena extends JenaBaseDao implements PropertyDao {
* the ontology model.
*/
public HashSet<String> getRelatedClasses(OntClass ontClass) {
public HashSet<String> getRestrictedClasses(OntClass ontClass) {
HashSet<String> classSet = new HashSet<String>();
List<OntClass> classList = ontClass.listEquivalentClasses().toList();
classList.addAll(ontClass.listSubClasses().toList());
classList.addAll(ontClass.listSuperClasses().toList());
Iterator<OntClass> it = classList.iterator();
@ -406,6 +404,8 @@ public class PropertyDaoJena extends JenaBaseDao implements PropertyDao {
if (!oc.isAnon()) {
classSet.add(oc.getURI());
} else {
classSet.addAll(getRestrictedClasses(oc));
}
}
@ -621,6 +621,28 @@ public class PropertyDaoJena extends JenaBaseDao implements PropertyDao {
return classes;
}
private List<Restriction> getRelatedRestrictions(OntClass ontClass) {
List<Restriction> relatedRestrictions = new ArrayList<Restriction>();
if (ontClass.isRestriction()) {
relatedRestrictions.add(ontClass.as(Restriction.class));
} else if (ontClass.isIntersectionClass()) {
IntersectionClass inter = ontClass.as(IntersectionClass.class);
Iterator<? extends OntClass> operIt = inter.listOperands();
while (operIt.hasNext()) {
relatedRestrictions.addAll(getRelatedRestrictions(operIt.next()));
}
} else {
List<OntClass> superClasses = listSuperClasses(ontClass);
superClasses.addAll(listEquivalentClasses(ontClass));
for (OntClass sup : superClasses) {
if (!sup.equals(ontClass)) {
relatedRestrictions.addAll(getRelatedRestrictions(sup));
}
}
}
return relatedRestrictions;
}
public List<PropertyInstance> getAllPropInstByVClasses(List<VClass> vclasses) {
List<PropertyInstance> propInsts = new ArrayList<PropertyInstance>();
@ -651,55 +673,52 @@ public class PropertyDaoJena extends JenaBaseDao implements PropertyDao {
String VClassURI = vclass.getURI();
OntClass ontClass = getOntClass(ontModel,VClassURI);
if (ontClass != null) {
List<OntClass> relatedClasses = new ArrayList<OntClass>();
relatedClasses.addAll(listEquivalentClasses(ontClass));
relatedClasses.addAll(listSuperClasses(ontClass));
for (OntClass relatedClass : relatedClasses) {
// find properties in restrictions
if (relatedClass.isRestriction() && relatedClass.canAs(Restriction.class)) {
// TODO: check if restriction is something like
// maxCardinality 0 or allValuesFrom owl:Nothing,
// in which case the property is NOT applicable!
Restriction rest = relatedClass.as(Restriction.class);
OntProperty onProperty = rest.getOnProperty();
if (onProperty != null) {
Resource[] ranges = new Resource[2];
if (rest.isAllValuesFromRestriction()) {
ranges[0] = (rest.asAllValuesFromRestriction()).getAllValuesFrom();
} else if (rest.isSomeValuesFromRestriction()) {
ranges[1] = (rest.asSomeValuesFromRestriction()).getSomeValuesFrom();
}
updatePropertyRangeMap(applicableProperties, onProperty.getURI(), ranges);
}
}
}
List<Resource> propertyList =
getPropertiesWithAppropriateDomainFor(VClassURI);
for (Resource prop : propertyList) {
if (prop.getNameSpace() != null
&& !NONUSER_NAMESPACES.contains(
prop.getNameSpace()) ) {
StmtIterator rangeSit = prop.listProperties(
RDFS.range);
Resource rangeRes = null;
while (rangeSit.hasNext()) {
Statement s = rangeSit.nextStatement();
if (s.getObject().isURIResource()) {
rangeRes = (Resource) s.getObject();
}
}
Resource[] ranges = new Resource[2];
ranges[0] = rangeRes;
updatePropertyRangeMap(
applicableProperties, prop.getURI(), ranges);
}
}
if (ontClass == null) {
continue;
}
}
List<Restriction> relatedRestrictions = getRelatedRestrictions(ontClass);
for (Restriction rest : relatedRestrictions) {
// find properties in restrictions
// TODO: check if restriction is something like
// maxCardinality 0 or allValuesFrom owl:Nothing,
// in which case the property is NOT applicable!
OntProperty onProperty = rest.getOnProperty();
if (onProperty != null) {
Resource[] ranges = new Resource[2];
if (rest.isAllValuesFromRestriction()) {
ranges[0] = (rest.asAllValuesFromRestriction()).getAllValuesFrom();
} else if (rest.isSomeValuesFromRestriction()) {
ranges[1] = (rest.asSomeValuesFromRestriction()).getSomeValuesFrom();
}
updatePropertyRangeMap(applicableProperties, onProperty.getURI(), ranges);
}
}
List<Resource> propertyList =
getPropertiesWithAppropriateDomainFor(VClassURI);
for (Resource prop : propertyList) {
if (prop.getNameSpace() != null
&& !NONUSER_NAMESPACES.contains(
prop.getNameSpace()) ) {
StmtIterator rangeSit = prop.listProperties(
RDFS.range);
Resource rangeRes = null;
while (rangeSit.hasNext()) {
Statement s = rangeSit.nextStatement();
if (s.getObject().isURIResource()) {
rangeRes = (Resource) s.getObject();
}
}
Resource[] ranges = new Resource[2];
ranges[0] = rangeRes;
updatePropertyRangeMap(
applicableProperties, prop.getURI(), ranges);
}
}
}
} catch (Exception e) {
log.error("Unable to get applicable properties " +
"by examining property restrictions and domains", e);

View file

@ -2,10 +2,15 @@
package edu.cornell.mannlib.vitro.webapp.dao.jena;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.UnionClass;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
@ -376,4 +381,27 @@ public class VClassJena extends VClass {
}
}
}
@Override
public boolean isUnion() {
return this.cls.isUnionClass();
}
//TODO consider anonymous components
@Override
public List<VClass> getUnionComponents() {
List<VClass> unionComponents = new ArrayList<VClass>();
if (isUnion()) {
UnionClass union = this.cls.as(UnionClass.class);
Iterator<? extends OntClass> opIt = union.listOperands();
while(opIt.hasNext()) {
OntClass component = opIt.next();
if (!component.isAnon()) {
unionComponents.add(new VClassJena(component, this.webappDaoFactory));
}
}
}
return unionComponents;
}
}

View file

@ -624,8 +624,10 @@ public class PelletListener implements ModelChangedListener {
if ( (additionModel.size() > 0) || (removalModel.size()>0) ) {
if (!isSynchronizing) {
if (foreground) {
log.debug("Running Pellet in foreground.");
(new PelletSynchronizer()).run();
} else {
log.debug("Running Pellet in background.");
new Thread(new PelletSynchronizer(), "PelletListener.PelletSynchronizer").start();
}
}

View file

@ -58,7 +58,13 @@ public class EditConfigurationUtils {
}
public static VClass getRangeVClass(VitroRequest vreq) {
return vreq.getWebappDaoFactory().getVClassDao().getVClassByURI(getRangeUri(vreq));
// This needs a WebappDaoFactory with no filtering/RDFService
// funny business because it needs to be able to retrieve anonymous union
// classes by their "pseudo-bnode URIs".
// Someday we'll need to figure out a different way of doing this.
WebappDaoFactory ctxDaoFact = ModelAccess.on(
vreq.getSession().getServletContext()).getWebappDaoFactory();
return ctxDaoFact.getVClassDao().getVClassByURI(getRangeUri(vreq));
}
//get individual

View file

@ -27,13 +27,13 @@ public class IndividualsViaObjectPropetyOptions implements FieldOptions {
private static final String LEFT_BLANK = "";
private String subjectUri;
private String predicateUri;
private String rangeUri;
private List<VClass> rangeTypes;
private String objectUri;
private String defaultOptionLabel;
public IndividualsViaObjectPropetyOptions(String subjectUri,
String predicateUri, String rangeUri, String objectUri) throws Exception {
String predicateUri, List<VClass> rangeTypes, String objectUri) throws Exception {
super();
if (subjectUri == null || subjectUri.equals("")) {
@ -45,7 +45,7 @@ public class IndividualsViaObjectPropetyOptions implements FieldOptions {
this.subjectUri = subjectUri;
this.predicateUri = predicateUri;
this.rangeUri = rangeUri;
this.rangeTypes = rangeTypes;
this.objectUri = objectUri;
}
@ -78,8 +78,8 @@ public class IndividualsViaObjectPropetyOptions implements FieldOptions {
//get all vclasses applicable to the individual subject
HashSet<String> vclassesURIs = getApplicableVClassURIs(subject, wDaoFact);
if (rangeUri != null) {
vclassesURIs = filterToSubclassesOfRange(vclassesURIs, rangeUri, wDaoFact);
if (!rangeTypes.isEmpty()) {
vclassesURIs = filterToSubclassesOfRange(vclassesURIs, rangeTypes, wDaoFact);
}
if (vclassesURIs.size() == 0) {
@ -117,9 +117,13 @@ public class IndividualsViaObjectPropetyOptions implements FieldOptions {
private HashSet<String> getApplicableVClassURIs(Individual subject, WebappDaoFactory wDaoFact) {
HashSet<String> vclassesURIs = new HashSet<String>();
if (rangeUri != null) {
log.debug("individualsViaObjectProperty using rangeUri " + rangeUri);
vclassesURIs.add(rangeUri);
if (!rangeTypes.isEmpty()) {
StringBuffer rangeBuff = new StringBuffer();
for (VClass rangeType : rangeTypes) {
vclassesURIs.add(rangeType.getURI());
rangeBuff.append(rangeType.getURI()).append(", ");
}
log.debug("individualsViaObjectProperty using rangeUri " + rangeBuff.toString());
return vclassesURIs;
}
@ -144,13 +148,15 @@ public class IndividualsViaObjectPropetyOptions implements FieldOptions {
}
private HashSet<String> filterToSubclassesOfRange(HashSet<String> vclassesURIs,
String rangeUri,
List<VClass> rangeTypes,
WebappDaoFactory wDaoFact) {
HashSet<String> filteredVClassesURIs = new HashSet<String>();
VClassDao vcDao = wDaoFact.getVClassDao();
for (String vclass : vclassesURIs) {
if (vclass.equals(rangeUri) || vcDao.isSubClassOf(vclass, rangeUri)) {
filteredVClassesURIs.add(vclass);
for (VClass rangeType : rangeTypes) {
if (vclass.equals(rangeType.getURI()) || vcDao.isSubClassOf(vclass, rangeType.getURI())) {
filteredVClassesURIs.add(vclass);
}
}
}
return filteredVClassesURIs;

View file

@ -99,41 +99,60 @@ public class DefaultObjectPropertyFormGenerator implements EditConfigurationGene
return getDefaultObjectEditConfiguration(vreq, session);
}
protected List<String> getRangeTypes(VitroRequest vreq) {
WebappDaoFactory wDaoFact = vreq.getWebappDaoFactory();
List<String> types = new ArrayList<String>();
protected List<VClass> getRangeTypes(VitroRequest vreq) {
// This first part needs a WebappDaoFactory with no filtering/RDFService
// funny business because it needs to be able to retrieve anonymous union
// classes by their "pseudo-bnode URIs".
// Someday we'll need to figure out a different way of doing this.
WebappDaoFactory ctxDaoFact = ModelAccess.on(
vreq.getSession().getServletContext()).getWebappDaoFactory();
List<VClass> types = new ArrayList<VClass>();
Individual subject = EditConfigurationUtils.getSubjectIndividual(vreq);
String predicateUri = EditConfigurationUtils.getPredicateUri(vreq);
String rangeUri = EditConfigurationUtils.getRangeUri(vreq);
if (rangeUri != null) {
types.add(rangeUri);
VClass rangeVClass = ctxDaoFact.getVClassDao().getVClassByURI(rangeUri);
if (!rangeVClass.isUnion()) {
types.add(rangeVClass);
} else {
for (VClass unionComponent : rangeVClass.getUnionComponents()) {
types.add(unionComponent);
}
}
return types;
}
WebappDaoFactory wDaoFact = vreq.getWebappDaoFactory();
//Get all vclasses applicable to subject
List<VClass> vClasses = subject.getVClasses();
HashSet<String> typesHash = new HashSet<String>();
HashMap<String, VClass> typesHash = new HashMap<String, VClass>();
for(VClass vclass: vClasses) {
List<VClass> rangeVclasses = wDaoFact.getVClassDao().getVClassesForProperty(vclass.getURI(),predicateUri);
if(rangeVclasses != null) {
for(VClass range: rangeVclasses) {
//a hash will keep a unique list of types and so prevent duplicates
typesHash.add(range.getURI());
typesHash.put(range.getURI(), range);
}
}
}
types.addAll(typesHash);
types.addAll(typesHash.values());
return types;
}
private boolean tooManyRangeOptions(VitroRequest vreq, HttpSession session ) throws SolrServerException {
List<String> types = getRangeTypes(vreq);
List<VClass> rangeTypes = getRangeTypes(vreq);
SolrServer solrServer = SolrSetup.getSolrServer(session.getServletContext());
List<String> types = new ArrayList<String>();
//empty list means the range is not set to anything, force Thing
if(types.size() == 0 ){
types = new ArrayList<String>();
types.add(VitroVocabulary.OWL_THING);
}
if(types.size() == 0 ){
types.add(VitroVocabulary.OWL_THING);
} else {
for (VClass vclass : rangeTypes) {
if (vclass.getURI() != null) {
types.add(vclass.getURI());
}
}
}
long count = 0;
for( String type:types){
@ -184,7 +203,7 @@ public class DefaultObjectPropertyFormGenerator implements EditConfigurationGene
this.setSparqlQueries(editConfiguration);
//set fields
setFields(editConfiguration, vreq, EditConfigurationUtils.getPredicateUri(vreq), EditConfigurationUtils.getRangeUri(vreq));
setFields(editConfiguration, vreq, EditConfigurationUtils.getPredicateUri(vreq), getRangeTypes(vreq));
// No need to put in session here b/c put in session within edit request dispatch controller instead
//placing in session depends on having edit key which is handled in edit request dispatch controller
@ -358,7 +377,7 @@ public class DefaultObjectPropertyFormGenerator implements EditConfigurationGene
setFields(editConfiguration, vreq, predicateUri, null);
}
protected void setFields(EditConfigurationVTwo editConfiguration, VitroRequest vreq, String predicateUri, String rangeUri) throws Exception {
protected void setFields(EditConfigurationVTwo editConfiguration, VitroRequest vreq, String predicateUri, List<VClass> rangeTypes) throws Exception {
FieldVTwo field = new FieldVTwo();
field.setName("objectVar");
@ -370,7 +389,7 @@ public class DefaultObjectPropertyFormGenerator implements EditConfigurationGene
field.setOptions( new IndividualsViaObjectPropetyOptions(
subjectUri,
predicateUri,
rangeUri,
rangeTypes,
objectUri));
}else{
field.setOptions(null);
@ -441,14 +460,22 @@ public class DefaultObjectPropertyFormGenerator implements EditConfigurationGene
formSpecificData.put("editMode", getEditMode(vreq).toString().toLowerCase());
//We also need the type of the object itself
List<String> types = getRangeTypes(vreq);
List<VClass> types = getRangeTypes(vreq);
//if types array contains only owl:Thing, the search will not return any results
//In this case, set an empty array
if(types.size() == 1 && types.get(0).equals(VitroVocabulary.OWL_THING) ){
types = new ArrayList<String>();
if(types.size() == 1 && types.get(0).getURI().equals(VitroVocabulary.OWL_THING) ){
types = new ArrayList<VClass>();
}
formSpecificData.put("objectTypes", StringUtils.join(types, ","));
StringBuffer typesBuff = new StringBuffer();
for (VClass type : types) {
if (type.getURI() != null) {
typesBuff.append(type.getURI()).append(",");
}
}
formSpecificData.put("objectTypes", typesBuff.toString());
log.debug("autocomplete object types : " + formSpecificData.get("objectTypes"));
//Get label for individual if it exists
if(EditConfigurationUtils.getObjectIndividual(vreq) != null) {
@ -464,15 +491,15 @@ public class DefaultObjectPropertyFormGenerator implements EditConfigurationGene
editConfiguration.setFormSpecificData(formSpecificData);
}
private Object rangeIndividualsExist(HttpSession session, List<String> types) throws SolrServerException {
private Object rangeIndividualsExist(HttpSession session, List<VClass> types) throws SolrServerException {
SolrServer solrServer = SolrSetup.getSolrServer(session.getServletContext());
boolean rangeIndividualsFound = false;
for( String type:types){
for( VClass type:types){
//solr for type count.
SolrQuery query = new SolrQuery();
query.setQuery( VitroSearchTermNames.RDFTYPE + ":" + type);
query.setQuery( VitroSearchTermNames.RDFTYPE + ":" + type.getURI());
query.setRows(0);
QueryResponse rsp = solrServer.query(query);

View file

@ -129,6 +129,7 @@ public abstract class RDFServiceJena extends RDFServiceImpl implements RDFServic
Resource s2 = (Resource) n;
// now run yet another describe query
String smallerTree = makeDescribe(s2);
log.info(smallerTree);
Query smallerTreeQuery = QueryFactory.create(smallerTree);
QueryExecution qe3 = QueryExecutionFactory.create(
smallerTreeQuery, tree);
@ -184,7 +185,7 @@ public abstract class RDFServiceJena extends RDFServiceImpl implements RDFServic
}
queryBuff.append("} \n");
log.debug(queryBuff.toString());
log.info(queryBuff.toString());
Query construct = QueryFactory.create(queryBuff.toString());
// make a plain dataset to force the query to be run in a way that

View file

@ -525,15 +525,23 @@ public class EditConfigurationTemplateModel extends BaseTemplateModel {
if( subjectVClasses == null ) {
vclasses = wdf.getVClassDao().getAllVclasses();
} else if (rangeClass != null) {
List<VClass> rangeVClasses = new ArrayList<VClass>();
vclasses = new ArrayList<VClass>();
vclasses.add(rangeClass);
List<String> subURIs = wdf.getVClassDao().getSubClassURIs(rangeClass.getURI());
for (String subClassURI : subURIs) {
VClass subClass = wdf.getVClassDao().getVClassByURI(subClassURI);
if (subClass != null) {
vclasses.add(subClass);
}
}
if (!rangeClass.isUnion()) {
rangeVClasses.add(rangeClass);
} else {
rangeVClasses.addAll(rangeClass.getUnionComponents());
}
for(VClass rangeVClass : rangeVClasses) {
vclasses.add(rangeVClass);
List<String> subURIs = wdf.getVClassDao().getSubClassURIs(rangeVClass.getURI());
for (String subClassURI : subURIs) {
VClass subClass = wdf.getVClassDao().getVClassByURI(subClassURI);
if (subClass != null) {
vclasses.add(subClass);
}
}
}
} else {
//this hash is used to make sure there are no duplicates in the vclasses
//a more elegant method may look at overriding equals/hashcode to enable a single hashset of VClass objects