chenejac / VIVOTestMigrationJIRAClosed

0 stars 0 forks source link

VIVO-625: Can enter one statement but not more than one for property "documentation for" #774

Closed chenejac closed 6 years ago

chenejac commented 10 years ago

Jon Corson-Rikert (Migrated from VIVO-625) said:

Scenario: create a Service; create a Protocol and link the Protocol to the Service using the "documentation for service" property (scires:documentationFor). One statement can be added successfully, and viewed in both directions, but when trying to add a 2nd statement, I see the message "the range class for this property does not exist in the system."

The property is mislabeled -- the range is a union of Instrument or Service or Reagent or Research Project or Biological Specimen or Software or Database -- I have correct the label to "documentation for project or resource" in initialTBoxAnnotations.n3.

This property uses the default object property form, but that checks out doing the same type of action with other properties (I tested geographic focus)

chenejac commented 10 years ago

Jon Corson-Rikert said:

I'm also seeing an error with bibo:translator, again from the same sample Protocol individual. Bibo:translator has no range class specified, [and creating a restriction on its domain (Information Content Entity) is not enough to get past the error.] -- take that back -- I had not refreshed the page. Setting an "all values from" restriction on the domain class is enough to make the property behave. But having no range and no applicable restriction does generate the error.

As soon as I do specify a range for the bibo:translator property, everything behaves normally, including being able to add multiple statements. So somehow the tests have to pick up the case where there's a restriction supplying the range vs. the property definition itself.

chenejac commented 10 years ago

Jon Corson-Rikert said:

In case it's relevant, I see this message multiple times in the vivo.all.log:

2013-12-06 16:30:37,485 ERROR [PropertyDaoJena] com.hp.hpl.jena.ontology.ConversionException: Cannot convert node http://purl.org/dc/terms/contributor to OntProperty com.hp.hpl.jena.ontology.ConversionException: Cannot convert node http://purl.org/dc/terms/contributor to OntProperty at com.hp.hpl.jena.ontology.impl.OntPropertyImpl$1.wrap(OntPropertyImpl.java:69) at com.hp.hpl.jena.enhanced.EnhNode.convertTo(EnhNode.java:142) at com.hp.hpl.jena.enhanced.EnhNode.convertTo(EnhNode.java:22) at com.hp.hpl.jena.enhanced.Polymorphic.asInternal(Polymorphic.java:54) at com.hp.hpl.jena.enhanced.EnhNode.as(EnhNode.java:97) at com.hp.hpl.jena.ontology.impl.OntResourceImpl$ObjectAsMapper.map1(OntResourceImpl.java:1607) at com.hp.hpl.jena.ontology.impl.OntResourceImpl$ObjectAsMapper.map1(OntResourceImpl.java:1601) at com.hp.hpl.jena.util.iterator.Map1Iterator.next(Map1Iterator.java:35) at com.hp.hpl.jena.util.iterator.WrappedIterator.next(WrappedIterator.java:68) at com.hp.hpl.jena.util.iterator.UniqueExtendedIterator.nextIfNew(UniqueExtendedIterator.java:61) at com.hp.hpl.jena.util.iterator.UniqueExtendedIterator.hasNext(UniqueExtendedIterator.java:69) at com.hp.hpl.jena.util.iterator.WrappedIterator.hasNext(WrappedIterator.java:64) at com.hp.hpl.jena.util.iterator.FilterIterator.hasNext(FilterIterator.java:43) at edu.cornell.mannlib.vitro.webapp.dao.jena.PropertyDaoJena.getSuperPropertyURIs(PropertyDaoJena.java:189) at edu.cornell.mannlib.vitro.webapp.controller.edit.PropertyEditController.doPost(PropertyEditController.java:202) at edu.cornell.mannlib.vitro.webapp.controller.edit.PropertyEditController.doGet(PropertyEditController.java:235) at javax.servlet.http.HttpServlet.service(HttpServlet.java:621) at javax.servlet.http.HttpServlet.service(HttpServlet.java:728) at edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet.service(VitroHttpServlet.java:70) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at edu.cornell.mannlib.vitro.webapp.filters.PageRoutingFilter.doNonDisplayPage(PageRoutingFilter.java:110) at edu.cornell.mannlib.vitro.webapp.filters.PageRoutingFilter.doFilter(PageRoutingFilter.java:101) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at edu.cornell.mannlib.vitro.webapp.filters.RequestModelsPrep.doFilter(RequestModelsPrep.java:115) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at edu.cornell.mannlib.vitro.webapp.filters.URLRewriterFilter.doFilter(URLRewriterFilter.java:38) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at edu.cornell.mannlib.vitro.webapp.filters.JSessionStripFilter.doFilter(JSessionStripFilter.java:60) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at edu.cornell.mannlib.vitro.webapp.filters.CachingResponseFilter.produceBasicResponse(CachingResponseFilter.java:322) at edu.cornell.mannlib.vitro.webapp.filters.CachingResponseFilter.doFilter(CachingResponseFilter.java:115) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at edu.cornell.mannlib.vitro.webapp.i18n.selection.LocaleSelectionFilter.doFilter(LocaleSelectionFilter.java:63) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at edu.cornell.mannlib.vitro.webapp.filters.CharsetEncodingFilter.doFilter(CharsetEncodingFilter.java:25) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at edu.cornell.mannlib.vitro.webapp.filters.SessionTimeoutLimitingFilter.doFilter(SessionTimeoutLimitingFilter.java:39) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at edu.cornell.mannlib.vitro.webapp.filters.StartupStatusDisplayFilter.doFilter(StartupStatusDisplayFilter.java:64) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:724)

chenejac commented 10 years ago

Huda Khan said:

When debugging, I found that the blank node uri for the range class changes between the first and second time you try to add the property (which shouldn't be an issue because blank nodes don't have set uris) but the second time, no vclass is returned for the range uri and the error message is shown.

chenejac commented 10 years ago

Huda Khan said:

On further debugging, it appears that, after you delete the first statement, the rangeUri is again what it was before the statement was added and then the range class is found again.

chenejac commented 10 years ago

Huda Khan said:

The GroupedPropertyList code checks to see if the populated list already contains properties from the all possible properties list - in this case it essentially uses a copy of the information of the statement that already exists.

ObjectPropertyDaoJena uses this line "ObjectProperty newProperty = getObjectPropertyByURI(uri);"to get the object property - which appears to be creating a new local model with the relevant statements and then passing back the desired object property for that uri from the model. At this point, the blank node used to represent the range class has a different URI than the one being utilized by the page when it actually works. This might be the reason the code is failing to bring up the vclass for the range class (because the local model would give a different uri for the blank node than the model being used by the system). (The last two statements are hypotheses).

chenejac commented 10 years ago

Brian Lowe said:

That copying that happens in ObjectPropertyDaoJena is bnode-id-preserving when used with a language-neutral DAO factory. I think the problem is that the populated object property list comes from a language-filtering DAO factory, which breaks anything to do with blank nodes, and the moreRestrictiveRange() method is probably returning false when it can't determine what the rangeVClassURI of "op" is supposed to point to.

The easiest solution is probably to change moreRestrictiveRange() to look up the range VClass for both op and piOp by their URIs, and return true when piOp.getRangeVClassURI() corresponds to a found node and op.getRangeVClassURI() doesn't. This should ensure that the editable form of the property gets merged into the list.

chenejac commented 10 years ago

Huda Khan said:

Thanks Brian! I will try that out.

chenejac commented 10 years ago

Huda Khan said:

I tried it out and it appears to work fine. I tried to keep some of the basic logic of the method the same while including the changes you suggested. Here is the new method:

    WebappDaoFactory wadf) {
    if(piOp.getRangeVClassURI() == null) {
        return false;
    } else if (op.getRangeVClassURI() == null) {
        return (piOp.getRangeVClassURI() != null);
    } else {
        //Check and see if the range vclass exists for the possible piOp and populated op properties,
        //because for populated properties, if the range class is a union,
        //blank nodes will be broken and the code should instead use the existing or piOp range class uri
        VClass piOpRangeClass = wadf.getVClassDao().getVClassByURI(piOp.getRangeVClassURI());
        VClass opRangeClass = wadf.getVClassDao().getVClassByURI(op.getRangeVClassURI());
        //if the possible range class exists but the populated one does not, then return true to allow the possible
        //class to be utilized
        if(piOpRangeClass != null && opRangeClass == null) return true;
        return (wadf.getVClassDao().isSubClassOf(
                piOp.getRangeVClassURI(), op.getRangeVClassURI()));
    }
}

Let me know if anything here needs to be changed.

chenejac commented 10 years ago

Huda Khan said:

The code has been updated so that when a property is already populated (i.e. a statement already exists), the range class uri for the populated property does not have a corresponding vclass being returned (which is the case for blank nodes which are used to represent unions), but the range class uri for the property (i.e. the information for the property used when there are no existing statements) is returning a vclass, then the latter range uri is used.