From ec6f166f541064aabe4ac822660c7b606ef01033 Mon Sep 17 00:00:00 2001 From: Jim Blake Date: Wed, 5 Nov 2014 12:59:48 -0500 Subject: [PATCH] Cleanup. Use the locking model classes. --- .../webapp/dao/jena/FauxPropertyDaoJena.java | 332 +++++++----------- .../ConfigurationBeanLoader.java | 2 +- .../configuration/ConfigurationRdfParser.java | 8 +- .../vitro/webapp/utils/jena/Critical.java | 127 +++++-- 4 files changed, 235 insertions(+), 234 deletions(-) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/FauxPropertyDaoJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/FauxPropertyDaoJena.java index c59fbc729..fb90a2471 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/FauxPropertyDaoJena.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/FauxPropertyDaoJena.java @@ -24,11 +24,8 @@ import com.hp.hpl.jena.ontology.OntResource; import com.hp.hpl.jena.query.QuerySolution; import com.hp.hpl.jena.query.ResultSet; import com.hp.hpl.jena.rdf.model.ModelFactory; -import com.hp.hpl.jena.rdf.model.Property; -import com.hp.hpl.jena.rdf.model.RDFNode; import com.hp.hpl.jena.rdf.model.ResIterator; import com.hp.hpl.jena.rdf.model.Resource; -import com.hp.hpl.jena.shared.Lock; import com.hp.hpl.jena.vocabulary.RDF; import edu.cornell.mannlib.vitro.webapp.beans.FauxProperty; @@ -37,6 +34,9 @@ import edu.cornell.mannlib.vitro.webapp.dao.InsertException; import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner; import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner.QueryParser; +import edu.cornell.mannlib.vitro.webapp.utils.jena.Critical.LockableOntModel; +import edu.cornell.mannlib.vitro.webapp.utils.jena.Critical.LockedOntModel; +import edu.cornell.mannlib.vitro.webapp.utils.jena.Critical.LockingOntModelSelector; /** * TODO @@ -79,84 +79,85 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao // The instance // ---------------------------------------------------------------------- + private final LockingOntModelSelector models; + public FauxPropertyDaoJena(WebappDaoFactoryJena wadf) { super(wadf); - } - - @Override - protected OntModel getOntModel() { - return getOntModelSelector().getDisplayModel(); + this.models = new LockingOntModelSelector(wadf.getOntModelSelector()); } @Override public List getFauxPropertiesForBaseUri(String uri) { - List list = new ArrayList<>(); + try (LockedOntModel displayModel = models.getDisplayModel().read()) { + if (uri == null) { + return Collections.emptyList(); + } - getOntModel().enterCriticalSection(Lock.READ); - try { - if (uri != null) { - ResIterator contextResources = getOntModel() - .listSubjectsWithProperty(CONFIG_CONTEXT_FOR, - createResource(uri)); - for (Resource context : contextResources.toList()) { - if (!context.isURIResource()) { - continue; - } - - FauxProperty fp = getFauxPropertyFromContextUri(context - .getURI()); - if (fp == null) { - continue; - } - - list.add(fp); + List contextUris = new ArrayList<>(); + ResIterator contextResources = displayModel + .listSubjectsWithProperty(CONFIG_CONTEXT_FOR, + createResource(uri)); + for (Resource context : contextResources.toList()) { + if (context.isURIResource()) { + contextUris.add(context.asResource().getURI()); } } - } finally { - getOntModel().leaveCriticalSection(); + + List fpList = new ArrayList<>(); + for (String contextUri : contextUris) { + FauxProperty fp = getFauxPropertyFromContextUri(contextUri); + if (fp != null) { + fpList.add(fp); + } + } + return fpList; } - return list; } + /** + * Returns null if contextUri does not represent a valid CONFIG_CONTEXT. + */ @Override public FauxProperty getFauxPropertyFromContextUri(String contextUri) { - getOntModel().enterCriticalSection(Lock.READ); - try { + try (LockedOntModel displayModel = models.getDisplayModel().read()) { if (contextUri == null) { return null; } - Resource context = createResource(contextUri); - if (!getOntModel().contains(context, RDF.type, CONFIG_CONTEXT)) { + OntResource context = displayModel.createOntResource(contextUri); + if (!displayModel.contains(context, RDF.type, CONFIG_CONTEXT)) { log.debug("'" + contextUri + "' is not a CONFIG_CONTEXT"); return null; } - String baseUri = getUriValue(getOntModel(), context, + Collection baseUris = getPropertyResourceURIValues(context, CONFIG_CONTEXT_FOR); - if (baseUri == null) { + if (baseUris.isEmpty()) { log.debug("'" + contextUri + "' has no value for '" + CONFIG_CONTEXT_FOR + "'"); return null; } + String baseUri = baseUris.iterator().next(); - String rangeUri = getUriValue(getOntModel(), context, - QUALIFIED_BY_RANGE); - if (rangeUri == null) { + Collection rangeUris = getPropertyResourceURIValues( + context, QUALIFIED_BY_RANGE); + if (rangeUris.isEmpty()) { log.debug("'" + contextUri + "' has no value for '" + QUALIFIED_BY_RANGE + "'"); return null; } + String rangeUri = rangeUris.iterator().next(); // domainURI is optional. - String domainUri = getUriValue(getOntModel(), context, - QUALIFIED_BY_DOMAIN); + Collection domainUris = getPropertyResourceURIValues( + context, QUALIFIED_BY_DOMAIN); + String domainUri = domainUris.isEmpty() ? null : domainUris + .iterator().next(); FauxProperty fp = new FauxProperty(domainUri, baseUri, rangeUri); - populateInstance(fp, context); + fp.setContextUri(contextUri); + populateInstance(fp); return fp; - } finally { - getOntModel().leaveCriticalSection(); } } @@ -164,36 +165,32 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao public FauxProperty getFauxPropertyByUris(String domainUri, String baseUri, String rangeUri) { Set contexts = ConfigContext.findByQualifiers( - getOntModelSelector().getDisplayModel(), domainUri, baseUri, - rangeUri); - for (ConfigContext context : contexts) { + models.getDisplayModel(), domainUri, baseUri, rangeUri); + if (contexts.isEmpty()) { + log.debug("Can't find a FauxProperty for '" + domainUri + "', '" + + baseUri + "', '" + rangeUri + "'"); + return null; + } else { FauxProperty fp = new FauxProperty(domainUri, baseUri, rangeUri); - populateInstance(fp, createResource(context.getContextUri())); + fp.setContextUri(contexts.iterator().next().getContextUri()); + populateInstance(fp); return fp; } - log.debug("Can't find a FauxProperty for '" + domainUri + "', '" - + baseUri + "', '" + rangeUri + "'"); - return null; } @Override public void insertFauxProperty(FauxProperty fp) { if ((fp.getContextUri() != null) || (fp.getConfigUri() == null)) { throw new IllegalStateException( - "ContextUri and ConfigUri must be null on insert: contextUri=" - + fp.getContextUri() + ", configUri=" - + fp.getConfigUri()); + "ContextUri and ConfigUri must be null on insert: " + fp); } Set existingcontexts = ConfigContext.findByQualifiers( - getOntModelSelector().getDisplayModel(), fp.getDomainURI(), - fp.getBaseURI(), fp.getRangeURI()); + models.getDisplayModel(), fp.getDomainURI(), fp.getBaseURI(), + fp.getRangeURI()); if (!existingcontexts.isEmpty()) { throw new IllegalStateException( - "FauxProperty already exists with domainUri=" - + fp.getDomainURI() + ", baseUri=" - + fp.getBaseURI() + ", rangeUri=" - + fp.getRangeURI()); + "FauxProperty with these qualifiers already exists: " + fp); } try { @@ -203,10 +200,9 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao throw new RuntimeException(e); } - getOntModel().enterCriticalSection(Lock.WRITE); - try { - OntResource context = getOntModel().createOntResource( - fp.getContextUri()); + try (LockedOntModel displayModel = models.getDisplayModel().write()) { + OntResource context = displayModel.createOntResource(fp + .getContextUri()); addPropertyResourceValue(context, RDF.type, CONFIG_CONTEXT); addPropertyResourceURIValue(context, HAS_CONFIGURATION, fp.getConfigUri()); @@ -217,39 +213,36 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao addPropertyResourceURIValue(context, QUALIFIED_BY_DOMAIN, fp.getDomainURI()); - OntResource config = getOntModel().createOntResource( - fp.getConfigUri()); + OntResource config = displayModel.createOntResource(fp + .getConfigUri()); addPropertyResourceValue(config, RDF.type, OBJECT_PROPERTY_DISPLAY_CONFIG); addPropertyResourceURIValue(config, PROPERTY_GROUP, fp.getGroupURI()); addPropertyStringValue(config, DISPLAY_NAME, fp.getDisplayName(), - getOntModel()); + displayModel); addPropertyStringValue(config, PUBLIC_DESCRIPTION_ANNOT, - fp.getPublicDescription(), getOntModel()); + fp.getPublicDescription(), displayModel); addPropertyIntValue(config, DISPLAY_RANK_ANNOT, - fp.getDisplayTier(), getOntModel()); + fp.getDisplayTier(), displayModel); addPropertyIntValue(config, DISPLAY_LIMIT, fp.getDisplayLimit(), - getOntModel()); + displayModel); addPropertyBooleanValue(config, PROPERTY_COLLATEBYSUBCLASSANNOT, - fp.isCollateBySubclass(), getOntModel()); + fp.isCollateBySubclass(), displayModel); addPropertyBooleanValue(config, PROPERTY_SELECTFROMEXISTINGANNOT, - fp.isSelectFromExisting(), getOntModel()); + fp.isSelectFromExisting(), displayModel); addPropertyBooleanValue(config, PROPERTY_OFFERCREATENEWOPTIONANNOT, - fp.isOfferCreateNewOption(), getOntModel()); + fp.isOfferCreateNewOption(), displayModel); addPropertyStringValue(config, PROPERTY_CUSTOMENTRYFORMANNOT, - fp.getCustomEntryForm(), getOntModel()); + fp.getCustomEntryForm(), displayModel); addPropertyStringValue(config, LIST_VIEW_FILE, - fp.getCustomListView(), getOntModel()); - } finally { - getOntModel().leaveCriticalSection(); + fp.getCustomListView(), displayModel); } } @Override public void updateFauxProperty(FauxProperty fp) { - getOntModel().enterCriticalSection(Lock.READ); - try { + try (LockedOntModel displayModel = models.getDisplayModel().read()) { if (fp.getContextUri() == null) { throw new IllegalStateException("ContextURI may not be null: " + fp); @@ -262,78 +255,71 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao } Resource config = createResource(fp.getConfigUri()); - if (!getOntModel().contains(context, RDF.type, CONFIG_CONTEXT)) { + if (!displayModel.contains(context, RDF.type, CONFIG_CONTEXT)) { throw new IllegalStateException("'" + context + "' is not a '" + CONFIG_CONTEXT + "'"); } - if (!getOntModel().contains(config, RDF.type, + if (!displayModel.contains(config, RDF.type, OBJECT_PROPERTY_DISPLAY_CONFIG)) { throw new IllegalStateException("'" + config + "' is not a '" + OBJECT_PROPERTY_DISPLAY_CONFIG + "'"); } - if (!getOntModel().contains(context, HAS_CONFIGURATION, config)) { + if (!displayModel.contains(context, HAS_CONFIGURATION, config)) { throw new IllegalStateException("'" + config + "' is not a configuration for '" + context + "'"); } - - } finally { - getOntModel().leaveCriticalSection(); } - getOntModel().enterCriticalSection(Lock.WRITE); - try { - OntResource context = getOntModel().createOntResource( - fp.getContextUri()); + try (LockedOntModel displayModel = models.getDisplayModel().write()) { + OntResource context = displayModel.createOntResource(fp + .getContextUri()); updatePropertyResourceURIValue(context, QUALIFIED_BY_RANGE, fp.getRangeURI()); updatePropertyResourceURIValue(context, QUALIFIED_BY_DOMAIN, fp.getDomainURI()); - OntResource config = getOntModel().createOntResource( - fp.getConfigUri()); + OntResource config = displayModel.createOntResource(fp + .getConfigUri()); updatePropertyResourceURIValue(config, PROPERTY_GROUP, fp.getGroupURI()); - updatePropertyStringValue(config, DISPLAY_NAME, fp.getDisplayName(), - getOntModel()); + updatePropertyStringValue(config, DISPLAY_NAME, + fp.getDisplayName(), displayModel); updatePropertyStringValue(config, PUBLIC_DESCRIPTION_ANNOT, - fp.getPublicDescription(), getOntModel()); + fp.getPublicDescription(), displayModel); updatePropertyIntValue(config, DISPLAY_RANK_ANNOT, - fp.getDisplayTier(), getOntModel()); + fp.getDisplayTier(), displayModel); updatePropertyIntValue(config, DISPLAY_LIMIT, fp.getDisplayLimit(), - getOntModel()); + displayModel); updatePropertyBooleanValue(config, PROPERTY_COLLATEBYSUBCLASSANNOT, - fp.isCollateBySubclass(), getOntModel(), true); - updatePropertyBooleanValue(config, PROPERTY_SELECTFROMEXISTINGANNOT, - fp.isSelectFromExisting(), getOntModel(), true); - updatePropertyBooleanValue(config, PROPERTY_OFFERCREATENEWOPTIONANNOT, - fp.isOfferCreateNewOption(), getOntModel(), true); + fp.isCollateBySubclass(), displayModel, true); + updatePropertyBooleanValue(config, + PROPERTY_SELECTFROMEXISTINGANNOT, + fp.isSelectFromExisting(), displayModel, true); + updatePropertyBooleanValue(config, + PROPERTY_OFFERCREATENEWOPTIONANNOT, + fp.isOfferCreateNewOption(), displayModel, true); updatePropertyStringValue(config, PROPERTY_CUSTOMENTRYFORMANNOT, - fp.getCustomEntryForm(), getOntModel()); + fp.getCustomEntryForm(), displayModel); updatePropertyStringValue(config, LIST_VIEW_FILE, - fp.getCustomListView(), getOntModel()); - } finally { - getOntModel().leaveCriticalSection(); + fp.getCustomListView(), displayModel); } } @Override public void deleteFauxProperty(FauxProperty fp) { Set contexts = ConfigContext.findByQualifiers( - getOntModelSelector().getDisplayModel(), fp.getDomainURI(), - fp.getURI(), fp.getRangeURI()); - getOntModel().enterCriticalSection(Lock.READ); - try { + models.getDisplayModel(), fp.getDomainURI(), fp.getURI(), + fp.getRangeURI()); + try (LockedOntModel displayModel = models.getDisplayModel().write()) { for (ConfigContext context : contexts) { Resource configResource = createResource(context.getConfigUri()); - getOntModel().removeAll(configResource, null, null); - getOntModel().removeAll(null, null, configResource); + displayModel.removeAll(configResource, null, null); + displayModel.removeAll(null, null, configResource); Resource contextResource = createResource(context .getContextUri()); - getOntModel().removeAll(contextResource, null, null); - getOntModel().removeAll(null, null, contextResource); + displayModel.removeAll(contextResource, null, null); + displayModel.removeAll(null, null, contextResource); } - } finally { - getOntModel().leaveCriticalSection(); } } @@ -357,11 +343,8 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao } private boolean isUriUsed(String uri) { - getOntModel().enterCriticalSection(Lock.READ); - try { - return (getOntModel().getOntResource(uri) != null); - } finally { - getOntModel().leaveCriticalSection(); + try (LockedOntModel displayModel = models.getDisplayModel().read()) { + return (displayModel.getOntResource(uri) != null); } } @@ -369,9 +352,9 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao * Add labels, annotations, and whatever else we can find on the * ObjectPropertyDisplayConfig. */ - private void populateInstance(FauxProperty fp, Resource context) { + private void populateInstance(FauxProperty fp) { populateLabelsFromTBox(fp); - populateFieldsFromDisplayModel(fp, context); + populateFieldsFromDisplayModel(fp); } private void populateLabelsFromTBox(FauxProperty fp) { @@ -383,23 +366,19 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao if (classUri == null) { return null; } else { - OntModel tboxModel = getOntModelSelector().getTBoxModel(); - tboxModel.enterCriticalSection(Lock.READ); - try { - return getStringValue(tboxModel, createResource(classUri), - RDFS_LABEL); - } finally { - tboxModel.leaveCriticalSection(); + try (LockedOntModel tboxModel = models.getTBoxModel().read()) { + return getPropertyStringValue( + tboxModel.createOntResource(classUri), RDFS_LABEL); } } } - private void populateFieldsFromDisplayModel(FauxProperty fp, - Resource context) { - OntResource config = locateConfigurationFromContext(context); - if (config != null) { - getOntModel().enterCriticalSection(Lock.READ); - try { + private void populateFieldsFromDisplayModel(FauxProperty fp) { + String configUri = locateConfigurationFromContext(fp.getContextUri()); + fp.setConfigUri(configUri); + if (configUri != null) { + try (LockedOntModel displayModel = models.getDisplayModel().read()) { + OntResource config = displayModel.createOntResource(configUri); fp.setDisplayName(getPropertyStringValue(config, DISPLAY_NAME)); fp.setPublicDescription(getPropertyStringValue(config, PUBLIC_DESCRIPTION_ANNOT)); @@ -417,24 +396,20 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao PROPERTY_OFFERCREATENEWOPTIONANNOT)); fp.setCustomEntryForm(getPropertyStringValue(config, PROPERTY_CUSTOMENTRYFORMANNOT)); - } finally { - getOntModel().leaveCriticalSection(); } } } - private OntResource locateConfigurationFromContext(Resource context) { - getOntModel().enterCriticalSection(Lock.READ); - try { - String configUri = getUriValue(getOntModel(), context, + private String locateConfigurationFromContext(String contextUri) { + try (LockedOntModel displayModel = models.getDisplayModel().read()) { + Collection configUris = getPropertyResourceURIValues( + displayModel.createOntResource(contextUri), HAS_CONFIGURATION); - if (configUri == null) { + if (configUris.isEmpty()) { return null; } else { - return getOntModel().createOntResource(configUri); + return configUris.iterator().next(); } - } finally { - getOntModel().leaveCriticalSection(); } } @@ -448,64 +423,6 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao } } - /** - * Returns a single URI that is the object of this subject and property. - * Returns null if no valid statement is found. - * - * The model should already be locked. - */ - private String getUriValue(OntModel model, Resource subject, - Property property) { - List nodeList = model.listObjectsOfProperty(subject, property) - .toList(); - if (nodeList.isEmpty()) { - log.warn("'" + subject.getURI() + "' has no value for '" - + property.getURI() + "'."); - return null; - } - - RDFNode node = nodeList.get(0); - if (nodeList.size() > 1) { - log.warn("'" + subject.getURI() + "' has " + nodeList.size() - + " values for ''. Using '" + node + "'"); - } - if (!node.isURIResource()) { - log.warn("Value of '" + subject.getURI() + property.getURI() - + "' '' is not a URI resource."); - return null; - } - return node.asResource().getURI(); - } - - /** - * Returns a single String value that is the object of this subject and - * property. Returns null if no valid statement is found. - * - * The model should already be locked. - */ - private String getStringValue(OntModel model, Resource subject, - Property property) { - List nodeList = model.listObjectsOfProperty(subject, property) - .toList(); - if (nodeList.isEmpty()) { - log.warn("'" + subject.getURI() + "' has no value for '" - + property.getURI() + "'."); - return null; - } - - RDFNode node = nodeList.get(0); - if (nodeList.size() > 1) { - log.warn("'" + subject.getURI() + "' has " + nodeList.size() - + " values for ''. Using '" + node + "'"); - } - if (!node.isLiteral()) { - log.warn("Value of '" + subject.getURI() + property.getURI() - + "' '' is not a Literal."); - return null; - } - return node.asLiteral().getString(); - } - // ---------------------------------------------------------------------- // ConfigContext // ---------------------------------------------------------------------- @@ -572,10 +489,9 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao private static class ConfigContext { public static Set findByQualifiers( - OntModel displayModel, String domainUri, String baseUri, - String rangeUri) { - displayModel.enterCriticalSection(Lock.READ); - try { + LockableOntModel lockableDisplayModel, String domainUri, + String baseUri, String rangeUri) { + try (LockedOntModel displayModel = lockableDisplayModel.read()) { String queryString; if (domainUri == null) { queryString = bindValues( @@ -594,8 +510,6 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao domainUri, baseUri, rangeUri); return new SparqlQueryRunner(displayModel).executeSelect( parser, queryString); - } finally { - displayModel.leaveCriticalSection(); } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/configuration/ConfigurationBeanLoader.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/configuration/ConfigurationBeanLoader.java index df6760e4f..9286527d9 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/configuration/ConfigurationBeanLoader.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/configuration/ConfigurationBeanLoader.java @@ -120,7 +120,7 @@ public class ConfigurationBeanLoader { public Set loadAll(Class resultClass) throws ConfigurationBeanLoaderException { Set uris = new HashSet<>(); - try (Critical section = Critical.read(model)) { + try (Critical.Section section = Critical.Section.read(model)) { List resources = model.listResourcesWithProperty( RDF.type, createResource(toJavaUri(resultClass))).toList(); for (Resource r : resources) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/configuration/ConfigurationRdfParser.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/configuration/ConfigurationRdfParser.java index 507e71319..530dbdd31 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/configuration/ConfigurationRdfParser.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/configuration/ConfigurationRdfParser.java @@ -58,7 +58,7 @@ public class ConfigurationRdfParser { throws InvalidConfigurationRdfException { Selector s = new SimpleSelector(createResource(uri), null, (RDFNode) null); - try (Critical section = Critical.read(model)) { + try (Critical.Section section = Critical.Section.read(model)) { if (model.listStatements(s).toList().isEmpty()) { throw individualDoesNotAppearInModel(uri); } @@ -70,7 +70,7 @@ public class ConfigurationRdfParser { throws InvalidConfigurationRdfException { Statement s = createStatement(createResource(uri), RDF.type, createResource(toJavaUri(resultClass))); - try (Critical section = Critical.read(model)) { + try (Critical.Section section = Critical.Section.read(model)) { if (!model.contains(s)) { throw noTypeStatementForResultClass(s); } @@ -81,7 +81,7 @@ public class ConfigurationRdfParser { throws InvalidConfigurationRdfException { Set set = new HashSet<>(); - try (Critical section = Critical.read(model)) { + try (Critical.Section section = Critical.Section.read(model)) { List rawStatements = model.listStatements( model.getResource(uri), (Property) null, (RDFNode) null) .toList(); @@ -111,7 +111,7 @@ public class ConfigurationRdfParser { throws InvalidConfigurationRdfException { Set> concreteClasses = new HashSet<>(); - try (Critical section = Critical.read(model)) { + try (Critical.Section section = Critical.Section.read(model)) { for (RDFNode node : model.listObjectsOfProperty( createResource(uri), RDF.type).toSet()) { if (!node.isURIResource()) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/Critical.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/Critical.java index 113645909..c1262b20b 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/Critical.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/Critical.java @@ -5,35 +5,122 @@ package edu.cornell.mannlib.vitro.webapp.utils.jena; import static com.hp.hpl.jena.shared.Lock.READ; import static com.hp.hpl.jena.shared.Lock.WRITE; +import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.shared.Lock; + +import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelector; +import edu.cornell.mannlib.vitro.webapp.rdfservice.adapters.AbstractOntModelDecorator; /** - * Use this in a try-with-resources block. - * - *
- * try (Critical section = Critical.read(model)) {
- * }
- * 
+ * AutoCloseable helper classes for using models in a try-with-resources block. */ -public class Critical implements AutoCloseable { - public static Critical read(Model model) { - return new Critical(model, READ); +public abstract class Critical { + /** + * Use this when you have a bare model, and you want to control a critical + * section. + * + *
+	 * try (Critical.Section section = Critical.Section.read(model)) {
+	 *     ...
+	 * }
+	 * 
+ */ + public static class Section implements AutoCloseable { + public static Section read(Model model) { + return new Section(model, READ); + } + + public static Section write(Model model) { + return new Section(model, WRITE); + } + + private final Model model; + + private Section(Model model, boolean readLockRequested) { + this.model = model; + this.model.enterCriticalSection(readLockRequested); + } + + @Override + public void close() { + this.model.leaveCriticalSection(); + } } - public static Critical write(Model model) { - return new Critical(model, WRITE); - } - - private final Model model; + /** + * Use this when you have a bare OntModelSelector. It returns + * LockableOntModels, which can then be locked in a critical section. + * + *
+	 * LockingOntModelSelector lockingOms = new LockingOntModelSelector(oms);
+	 * 
+ */ + public static class LockingOntModelSelector { + private final OntModelSelector oms; - private Critical(Model model, boolean readLockRequested) { - this.model = model; - this.model.enterCriticalSection(readLockRequested); + public LockingOntModelSelector(OntModelSelector oms) { + this.oms = oms; + } + + public LockableOntModel getDisplayModel() { + return new LockableOntModel(oms.getDisplayModel()); + } + + public LockableOntModel getTBoxModel() { + return new LockableOntModel(oms.getTBoxModel()); + } } - @Override - public void close() { - this.model.leaveCriticalSection(); + /** + * Returned by the LockingOntModelSelector, or it can be wrapped around a + * bare OntModel. + * + *
+	 * try (LockedOntModel m = lockingOms.getDisplayModel.read()) {
+	 *    ...
+	 * }
+	 * 
+ */ + public static class LockableOntModel { + private final OntModel ontModel; + + public LockableOntModel(OntModel ontModel) { + this.ontModel = ontModel; + } + + public LockedOntModel read() { + ontModel.enterCriticalSection(Lock.READ); + return new LockedOntModel(ontModel); + } + + public LockedOntModel write() { + ontModel.enterCriticalSection(Lock.WRITE); + return new LockedOntModel(ontModel); + } + } + + /** + * A simple OntModel, except that it can only be created by locking a + * LockableOntModel. It is AutoCloseable, but the close method has been + * hijacked to simply release the lock, and not to actually close the + * wrapped model. + */ + public static class LockedOntModel extends AbstractOntModelDecorator + implements AutoCloseable { + + private LockedOntModel(OntModel m) { + super(m); + } + + /** + * Just unlocks the model. Doesn't actually close it, because we may + * want to use it again. + */ + @Override + public void close() { + super.leaveCriticalSection(); + } } }