- From: Stephan Zednik <zednis@rpi.edu>
- Date: Thu, 28 Mar 2013 10:06:37 -0600
- To: "Hua, Hook (388C)" <hook.hua@jpl.nasa.gov>
- Cc: Luc Moreau <l.moreau@ecs.soton.ac.uk>, "public-prov-wg@w3.org" <public-prov-wg@w3.org>
The proposed solutions leads to the possibility of multiple documentBundles being in a given document. <prov:document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:prov="http://www.w3.org/ns/prov#" xmlns:ex="http://example.com/ns/ex#"> <prov:documentBundle> <!-- statements --> </prov:documentBundle> <prov:documentBundle> <!-- statements --> </prov:documentBundle> <prov:documentBundle> <!-- statements --> </prov:documentBundle> </prov:document> This is an interesting scenario we had not accounted for previously. These document bundles are differentiated from regular bundles in that they do not support the prov:id attribute. This element also does not have a corresponding concept in PROV-N. I think this could cause confusion. I do not know how to justify/explain an xml document with multiple documentBundles. I think I prefer to option to enforce ordering of bundle constructors, non-bundle prov-statements, and xsd:any (see following) over introducing a documentBundle element that is not clearly differentiated from the existing bundleConstructor and which does not correspond to a concept from the DM or any other serialization. <xs:complexType name="Document"> <xs:sequence> <xs:group ref="prov:documentElements" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="bundleContent" type="prov:BundleConstructor" minOccurs="0" maxOccurs="unbounded"/> <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> Also, I like the idea of leaving the schema as it is if a jaxb binding file can provide a solution and detailing that jaxb-specific solution in a FAQ entry, but I agree that making a change to the schema to prevent this issue from occurring would probably be the better and more visible solution. --Stephan On Mar 28, 2013, at 9:04 AM, Stephan Zednik <zednis@rpi.edu> wrote: > Hi Hook, > > Thanks for looking into this. I would like to test out the proposed solution and I will provide feedback by the EOD. > > Luc, would the proposed solution resolve this issue? > > --Stephan > > On Mar 28, 2013, at 4:40 AM, "Hua, Hook (388C)" <hook.hua@jpl.nasa.gov> wrote: > >> Hi Luc and Stephan, >> >> Somehow, with jaxb-ri-2.2.6, the removal of xsd:any still generates >> JAXBElements. >> >> Hopefully we may not need to modify the xsd:any support nor use customized >> bindings mapping for JAXB. In looking into it further, I believe I have >> found a more upstream cause and a potentially cleaner solution. >> >> Given that we have the following unfriendly XML binding mapping: >> >> ------------------------------------------------------ >> <xs:element name="document" type="prov:Document" /> >> >> <xs:complexType name="Document"> >> <xs:sequence maxOccurs="unbounded"> >> <xs:group ref="prov:documentElements" minOccurs="0"/> >> <xs:element name="bundleContent" type="prov:BundleConstructor" >> minOccurs="0"/> >> <xs:any namespace="##other" processContents="lax" minOccurs="0" /> >> </xs:sequence> >> </xs:complexType> >> >> --------- >> >> >> public class Document { >> @XmlElementRefs({ >> @XmlElementRef(name = "wasRevisionOf", namespace = >> "http://www.w3.org/ns/prov#", type = JAXBElement.class, required = false), >> @XmlElementRef(name = "activity", namespace = >> "http://www.w3.org/ns/prov#", type = JAXBElement.class, required = false), >> @XmlElementRef(name = "collection", namespace = >> "http://www.w3.org/ns/prov#", type = JAXBElement.class, required = false), >> @XmlElementRef(name = "bundle", namespace = >> "http://www.w3.org/ns/prov#", type = JAXBElement.class, required = false), >> @XmlElementRef(name = "wasQuotedFrom", namespace = >> "http://www.w3.org/ns/prov#", type = JAXBElement.class, required = false), >> @XmlElementRef(name = "wasInvalidatedBy", namespace = >> "http://www.w3.org/ns/prov#", type = JAXBElement.class, required = false), >> ... >> }) >> @XmlAnyElement(lax = true) >> protected List<Object> entityAndActivityAndWasGeneratedBy; >> ... >> ------------------------------------------------------ >> >> It appears that to help retain a round-trip marshalling/unmarshalling of >> our prov:Document, the unbounded sequence of its elements (including >> prov:BundleConstructor) must be uniquely distinguished by JAXB. The >> repeating sequences are treated as a List<Object> of generic JAXBElements, >> where the JAXBElemnt's QName is used to distinguish elements with >> different names. So the culprit may be the unbounded sequence. >> >> <xs:sequence maxOccurs="unbounded"> >> <xs:group ref="prov:documentElements" minOccurs="0"/> >> <xs:element name="bundleContent" type="prov:BundleConstructor" >> minOccurs="0"/> >> <xs:any namespace="##other" processContents="lax" minOccurs="0" /> >> </xs:sequence> >> >> >> >> >> What if we move the unbounded occurrence into a wrapper complex type and >> keep the sequence singular? Below, I've introduced a "prov:DocumentBundle" >> wrapper complex type in which to apply the unbounded occurrence to. Then >> in "prov:DocumentBundle", maintain the same subelements as before, but as >> one occurrence of the sequence. Running it through JAXB now generates the >> cleaner prov-typed List elements. No customized bindings for JAXB needed. >> No removal of xsd:any needed. >> >> >> ------------------------------------------------------ >> <xs:element name="document" type="prov:Document" /> >> >> <xs:complexType name="DocumentBundle"> >> <xs:sequence> >> <xs:group ref="prov:documentElements" minOccurs="0"/> >> <xs:element name="bundleContent" type="prov:BundleConstructor" >> minOccurs="0"/> >> <xs:any namespace="##other" processContents="lax" minOccurs="0" /> >> </xs:sequence> >> </xs:complexType> >> >> <xs:complexType name="Document"> >> <xs:sequence> >> <xs:element name="documentBundle" type="prov:DocumentBundle" >> minOccurs="0" maxOccurs="unbounded"/> >> </xs:sequence> >> </xs:complexType> >> >> --------- >> >> public class Document { >> protected DocumentBundle documentBundle; >> ... >> >> public class DocumentBundle { >> protected List<Entity> entity; >> protected List<Activity> activity; >> protected List<Generation> wasGeneratedBy; >> protected List<Usage> used; >> protected List<Communication> wasInformedBy; >> protected List<Start> wasStartedBy; >> protected List<End> wasEndedBy; >> protected List<Invalidation> wasInvalidatedBy; >> ... >> ------------------------------------------------------ >> >> We could also rename the wrapper "prov:DocumentBundle" to something else >> reduce possible confusion with prov:Bundle and prov:BundleConstructor. >> >> >> >> I think we need to understand that this approach introduces another >> indirection artifact in the PROV-XML encoding. Would this be an acceptable >> compromise approach around the JAXBElement issue? >> >> --Hook >> >> >> >> >> >> >> >> >> On 3/21/13 8:49 AM, "Stephan Zednik" <zednis@rpi.edu> wrote: >> >>> >>> >>> On Mar 21, 2013, at 5:26 AM, Luc Moreau <l.moreau@ecs.soton.ac.uk> wrote: >>> >>>> H Hook, >>>> >>>> Thanks for this analysis. >>>> >>>> In this specific instance, I think that it is the element >>>> <xs:any namespace="##other" processContents="lax" minOccurs="0" /> >>>> occurring inside >>>> <xs:sequence maxOccurs="unbounded"> >>>> that causes these jaxb elements to be generated. >>>> >>>> If you were to remove xsd:any there, jaxbElements would no longer be >>>> generated. >>>> >>>> While we want to allow the possibility of elements from other schemas, >>>> do we >>>> really want to allow them any where inside a document/bundle? >>> >>> We want to provide for elements from other schemas but I don't think we >>> formally identified what areas we intend to allow non-prov elements in >>> before we added this functionality to the schema. >>> >>> What if we made a FAQ entry about OXM mappings with PROV-XML and created >>> a customized schema or bindings file specifically for JAXB code >>> generation? This would allow us to work on asynchronously with the >>> document and past the note publication, it would also allow us to >>> introduce JAXB-specific solutions that I do not think make sense in the >>> official schema or note. >>> >>> --Stephan >>> >>>> >>>> Luc >>>> >>>> >>>> On 03/21/2013 11:09 AM, Hua, Hook (388C) wrote: >>>>> Hi Luc, >>>>> >>>>> I'm using jaxb-ri-2.2.6 against our latest prov*.xsd and seeing >>>>> slightly >>>>> different bindings with JAXBElement: >>>>> >>>>> public class Document { >>>>> @XmlElementRefs({ >>>>> @XmlElementRef(name = "hadPrimarySource", namespace = >>>>> "http://www.w3.org/ns/prov#", type = JAXBElement.class, required = >>>>> false), >>>>> @XmlElementRef(name = "agent", namespace = >>>>> "http://www.w3.org/ns/prov#", type = JAXBElement.class, required = >>>>> false), >>>>> @XmlElementRef(name = "activity", namespace = >>>>> "http://www.w3.org/ns/prov#", type = JAXBElement.class, required = >>>>> false), >>>>> @XmlElementRef(name = "organization", namespace = >>>>> "http://www.w3.org/ns/prov#", type = JAXBElement.class, required = >>>>> false), >>>>> @XmlElementRef(name = "softwareAgent", namespace = >>>>> "http://www.w3.org/ns/prov#", type = JAXBElement.class, required = >>>>> false), >>>>> .... >>>>> >>>>> >>>>> >>>>> Some findings: >>>>> >>>>> >>>>> (1) JAXB's generation of JAXBElement<T> classes seems to be a wrapper >>>>> approach to preserve sufficient information in the schema for >>>>> round-trip >>>>> marshaling & unmarshalling of values in XML instances. More >>>>> specifically, >>>>> it wraps the data with a QName and a nillable flag [1]. >>>>> >>>>> It appears that the a frequent cause of JAXB producing JAXBElement<T> >>>>> is >>>>> its attempt to preserve elements with both minOccurs=0 and >>>>> nillable=true. >>>>> JAXB needs to distinguish between the two cases where: >>>>> >>>>> a. element missing, minOccurs=0, then jaxbElement==null >>>>> b. element present, xsi:nil=true, then jaxbElement.isNil()==true >>>>> >>>>> It would not be possible to distinguish between these two states if the >>>>> bindings were the raw types. >>>>> >>>>> >>>>> >>>>> (2) It would be possible to customize the JAXB bindings [2] to ignore >>>>> the >>>>> full round-trip requirement. The "generateElementProperty=false" >>>>> customization option "can be used to generate an alternate developer >>>>> friendly but lossy binding" [3]. >>>>> >>>>> I tried variations of a "bindings.xjb" customization file: >>>>> >>>>> <jaxb:bindings version="2.1" >>>>> xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" >>>>> xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" >>>>> xmlns:xs="http://www.w3.org/2001/XMLSchema"> >>>>> <jaxb:bindings schemaLocation="prov-core.xsd" >>>>> node="//xs:complexType[@name='Document']"> >>>>> <jaxb:globalBindings generateElementProperty="false" /> >>>>> </jaxb:bindings> >>>>> </jaxb:bindings> >>>>> >>>>> $ xjc.sh -d BINDINGS -b bindings.xjb prov.xsd >>>>> >>>>> But none truly eliminated the JAXBElement<T> from the bindings. >>>>> >>>>> >>>>> >>>>> (3) Nowhere in our prov-core.xsd do we define minOccurs=0 in >>>>> conjunction >>>>> with nillable=true. In my attempts with JAXB, I'm seeing JAXBElements >>>>> appearing in the bindings for the (a) Document class and (b) >>>>> BundledConstructor class. Both types leverage the prov:documentElements >>>>> grouping. >>>>> >>>>> <xs:element name="document" type="prov:Document" /> >>>>> <xs:complexType name="Document"> >>>>> <xs:sequence maxOccurs="unbounded"> >>>>> <xs:group ref="prov:documentElements" minOccurs="0"/> >>>>> <xs:element name="bundleContent" type="prov:BundleConstructor" >>>>> minOccurs="0"/> >>>>> <xs:any namespace="##other" processContents="lax" minOccurs="0" /> >>>>> </xs:sequence> >>>>> </xs:complexType> >>>>> >>>>> It's unclear if there is some nillable-like affect that triggers JAXB >>>>> to >>>>> generate the JAXBElements. >>>>> >>>>> >>>>> >>>>> (4) On the upside, JAXB does provide an ObjectFactory class as part of >>>>> the >>>>> generated bindings that define creational factory methods to generate >>>>> the >>>>> JAXBElement instances. For example: >>>>> >>>>> public JAXBElement<Usage> createUsed(Usage value) >>>>> >>>>> Still, I agree that it is not as clean. >>>>> >>>>> >>>>> --Hook >>>>> >>>>> >>>>> [1] http://docs.oracle.com/javaee/5/api/javax/xml/bind/JAXBElement.html >>>>> [2] >>>>> >>>>> http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/1.5/tut >>>>> ori >>>>> al/doc/JAXBUsing4.html#wp148515 >>>>> [3] >>>>> >>>>> http://docs.oracle.com/cd/E17802_01/webservices/webservices/reference/tu >>>>> tor >>>>> ials/wsit/doc/DataBinding5.html >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> On 3/8/13 4:20 AM, "Provenance Working Group Issue Tracker" >>>>> <sysbot+tracker@w3.org> wrote: >>>>> >>>>>> PROV-ISSUE-648: Can schema be made a bit more jaxb friendly? [XML >>>>>> Serialization] >>>>>> >>>>>> http://www.w3.org/2011/prov/track/issues/648 >>>>>> >>>>>> Raised by: Luc Moreau >>>>>> On product: XML Serialization >>>>>> >>>>>> >>>>>> Hi >>>>>> >>>>>> I have ported the ProvToolbox and the ProvValidator to the new XML >>>>>> schema. >>>>>> I just wanted to report on my experience with the schema and JAXB. >>>>>> Obviously, others may have better experience with JAXB and may be able >>>>>> to help on some of the issues I encountered. >>>>>> >>>>>> Everything worked fine, except: >>>>>> - <xs:element ref="prov:internalElement abstract=true/> >>>>>> - extensibility <xs:any namespace="##other"/> in Document and Bundle >>>>>> >>>>>> >>>>>> These two constructs, while processable by JAXB, are not >>>>>> JAXB-friendly. >>>>>> >>>>>> Indeed, JAXB compiles the schema in a list containing all possible >>>>>> statements. >>>>>> >>>>>> protected List<Object> entityAndActivityAndWasGeneratedBy; >>>>>> >>>>>> However, the presence on an abstract element and an <any/> element >>>>>> result >>>>>> in the >>>>>> content of that list to be of type: >>>>>> >>>>>> >>>>>> @XmlElementRefs({ >>>>>> @XmlElementRef(name = "used", namespace = >>>>>> "http://www.w3.org/ns/prov#", type = JAXBElement.class), >>>>>> @XmlElementRef(name = "wasAssociatedWith", namespace = >>>>>> "http://www.w3.org/ns/prov#", type = JAXBElement.class), >>>>>> @XmlElementRef(name = "person", namespace = >>>>>> "http://www.w3.org/ns/prov#", type = JAXBElement.class), >>>>>> @XmlElementRef(name = "entity", namespace = >>>>>> "http://www.w3.org/ns/prov#", type = JAXBElement.class), >>>>>> @XmlElementRef(name = "wasInfluencedBy", namespace = >>>>>> "http://www.w3.org/ns/prov#" >>>>>> .... >>>>>> }) >>>>>> >>>>>> @XmlAnyElement(lax = true) >>>>>> protected List<Object> entityAndActivityAndWasGeneratedBy; >>>>>> >>>>>> where all data structures are wrapped up in this unpleasant >>>>>> JAXBElement. >>>>>> >>>>>> Without these features, we get a much more natural mapping: >>>>>> @XmlElements({ >>>>>> @XmlElement(name = "entity", namespace = >>>>>> "http://www.w3.org/ns/prov#", type = Entity.class), >>>>>> @XmlElement(name = "activity", namespace = >>>>>> "http://www.w3.org/ns/prov#", type = Activity.class), >>>>>> @XmlElement(name = "wasGeneratedBy", namespace = >>>>>> "http://www.w3.org/ns/prov#", type = WasGeneratedBy.class), >>>>>> @XmlElement(name = "used", namespace = >>>>>> "http://www.w3.org/ns/prov#", type = Used.class), >>>>>> @XmlElement(name = "wasInformedBy", namespace = >>>>>> "http://www.w3.org/ns/prov#", type = WasInformedBy.class), >>>>>> ... >>>>>> }) >>>>>> >>>>>> So, how I did I solve the problem? I inserted the extension schemas >>>>>> into >>>>>> the schema file, and hence got rid of the abstract element. I am ok >>>>>> with >>>>>> this. We could possible provide the utility to that transformation. >>>>>> >>>>>> For the extensibility, I used a different definition. It happens to >>>>>> parse prov-xml compliant xml. When serializing, it puts all >>>>>> extensibility elements at the end. This is not a satisfactory >>>>>> solution, and is likely to be dependent of the jaxb implementation >>>>>> (though I am not entirely sure). >>>>>> >>>>>> >>>>>> <xs:complexType name="Document"> >>>>>> <xs:sequence> >>>>>> <xs:choice maxOccurs="unbounded"> >>>>>> <xs:group ref="prov:documentElements"/> >>>>>> <xs:element name="bundleContent" type="prov:NamedBundle"/> >>>>>> </xs:choice> >>>>>> <xs:any namespace="##other" processContents="lax" minOccurs="0" >>>>>> maxOccurs="unbounded"/> >>>>>> </xs:sequence> >>>>>> </xs:complexType> >>>>>> >>>>>> Can something be done to make the XML schema a bit more jaxb friendly, >>>>>> while still keeping the same flexibility? Thoughts welcome. >>>>>> >>>>>> Cheers, >>>>>> Luc >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>> >>>>> >>>> >>>> -- >>>> Professor Luc Moreau >>>> Electronics and Computer Science tel: +44 23 8059 4487 >>>> University of Southampton fax: +44 23 8059 2865 >>>> Southampton SO17 1BJ email: l.moreau@ecs.soton.ac.uk >>>> United Kingdom http://www.ecs.soton.ac.uk/~lavm >>>> >>>> >>>> >>> >>> >> >> > > >
Received on Thursday, 28 March 2013 16:06:55 UTC