castor
  1. castor
  2. CASTOR-217

Castor code generator has problems with xml schema groups

    Details

    • Type: Bug Bug
    • Status: Open Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 0.9.4
    • Fix Version/s: None
    • Component/s: XML code generator
    • Labels:
      None
    • Environment:
      Operating System: Windows 2000
      Platform: PC
    • Bugzilla Id:
      1072
    • Number of attachments :
      0

      Description

      When I try to generate code based on the IMS Global Learning Consortium content
      packaging schema (http://www.imsproject.org/xsd/imscp_rootv1p1p2.xsd), I get
      problems with the following part of the schema:

      <xsd:group name="grp.any">
      <xsd:annotation>
      <xsd:documentation>Any namespaced element from any namespace may be inc
      luded within an "any" element. The namespace for the imported element
      must be defined in the instance, and the schema must be imported. </xsd:docume
      ntation>
      </xsd:annotation>
      <xsd:sequence>
      <xsd:any namespace="##other" processContents="strict" minOccurs="0" max
      Occurs="unbounded"/>
      </xsd:sequence>
      </xsd:group>

      When I try and unmarshall a document, the resulting exception is:

      Unmarshalling failed: ValidationException: error-if-this-is-used is a
      required field.; - location of error: XPATH:
      manifest/organizations/organization/item at
      org.exolab.castor.xml.FieldValidator.validate(Unknown Source) at
      org.exolab.castor.xml.util.XMLClassDescriptorImpl.validate(Unknown Source) at
      org.exolab.castor.xml.util.XMLClassDescriptorImpl.validate(Unknown Source) at
      org.exolab.castor.xml.Validator.validate(Unknown Source) at
      org.exolab.castor.xml.FieldValidator.validate(Unknown Source) at
      org.exolab.castor.xml.util.XMLClassDescriptorImpl.validate(Unknown Source) at
      org.exolab.castor.xml.util.XMLClassDescriptorImpl.validate(Unknown Source) at
      org.exolab.castor.xml.Validator.validate(Unknown Source) at
      org.exolab.castor.xml.FieldValidator.validate(Unknown Source) at
      org.exolab.castor.xml.util.XMLClassDescriptorImpl.validate(Unknown Source) at
      org.exolab.castor.xml.util.XMLClassDescriptorImpl.validate(Unknown Source) at
      org.exolab.castor.xml.Validator.validate(Unknown Source) at
      org.exolab.castor.xml.FieldValidator.validate(Unknown Source) at
      org.exolab.castor.xml.util.XMLClassDescriptorImpl.validate(Unknown Source) at
      org.exolab.castor.xml.util.XMLClassDescriptorImpl.validate(Unknown Source) at
      org.exolab.castor.xml.Validator.validate(Unknown Source) at
      org.exolab.castor.xml.UnmarshalHandler.endElement(Unknown Source) at
      org.apache.xerces.parsers.SAXParser.endElement(SAXParser.java:1392) at
      org.apache.xerces.validators.common.XMLValidator.callEndElement
      (XMLValidator.java:1550) at
      org.apache.xerces.framework.XMLDocumentScanner$ContentDispatcher.dispatch
      (XMLDocumentScanner.java:1149) at
      org.apache.xerces.framework.XMLDocumentScanner.parseSome
      (XMLDocumentScanner.java:381) at org.apache.xerces.framework.XMLParser.parse
      (XMLParser.java:1098) at org.exolab.castor.xml.Unmarshaller.unmarshal(Unknown
      Source) at org.exolab.castor.xml.Unmarshaller.unmarshal(Unknown Source) at
      org.exolab.castor.xml.Unmarshaller.unmarshal(Unknown Source) at
      com.sun.elearning.lms_.upload_.schemabinding.imscp.Manifest.unmarshal

      It seems that castor generates a 'dummy' XMLFieldDescriptor instance for the
      group, with the name 'error-if-this-is-used'. Unfortunately, the
      XMLFieldDescriptor has it's 'required' attribute set to true, so during
      validation, castor wants there to be an element of that name and complains.

      I've tried to fix my own build of castor by modifying the
      org.exolab.castor.xml.schema.Group class to set it's 'minOccurs' attribute to
      0, rather than the default of 1. This prevents the 'required' attribute from
      being set and everything seems to be fine, but I'm not sure if this is really a
      valid fix.

      This problem appears to be generation time only - the code from my modified
      generator works fine with the normal version of castor.

        Activity

        Hide
        simon.bates added a comment -

        Created an attachment (id=234)
        Grp_anyDescriptor.java generated for <xsd:group name="grp.any">

        Show
        simon.bates added a comment - Created an attachment (id=234) Grp_anyDescriptor.java generated for <xsd:group name="grp.any">
        Hide
        simon.bates added a comment -

        Arnaud,

        Thank you very much for your response.

        I think the solution that would match the schema most closely to my mind would
        be that an instance of Grp_any is created at unmarshalling and that
        Grp_any.getAnyObjectCount() returns 0. For example:

        Manifest manifest = Manifest.unmarshal(someReader);
        Metadata metadata = manifest.getMetadata();
        Grp_any a = metadata.getGrp_any();

        for the following XML:

        <manifest>
        <metadata>
        </metadata>
        </manifest>

        a.getAnyObjectCount() would return 0.

        I would be happy to have a go at implementing this is you think it is the
        correct approach and if you could maybe give me a pointer to how this might be done.

        Regards,
        Simon.

        Show
        simon.bates added a comment - Arnaud, Thank you very much for your response. I think the solution that would match the schema most closely to my mind would be that an instance of Grp_any is created at unmarshalling and that Grp_any.getAnyObjectCount() returns 0. For example: Manifest manifest = Manifest.unmarshal(someReader); Metadata metadata = manifest.getMetadata(); Grp_any a = metadata.getGrp_any(); for the following XML: <manifest> <metadata> </metadata> </manifest> a.getAnyObjectCount() would return 0. I would be happy to have a go at implementing this is you think it is the correct approach and if you could maybe give me a pointer to how this might be done. Regards, Simon.
        Hide
        simon.bates added a comment -

        Created an attachment (id=235)
        Descriptor generated for metadataType that references a grp.any group

        Show
        simon.bates added a comment - Created an attachment (id=235) Descriptor generated for metadataType that references a grp.any group
        Hide
        simon.bates added a comment -

        Is a possible solution to modify the source code generator so that:

        In the case that a class contains a group with a minOccurs of 1 and that group
        itself can be empty
        then
        the containing class creates an instance of the class representing the group in
        its constructor?

        For example rather than:

        public ManifestType()

        { super(); _manifestList = new Vector(); }

        could we generate:

        public ManifestType()

        { super(); _manifestList = new Vector(); _grp_any = new ca.utoronto.atrc.tile.imscp.Grp_any(); }

        and if so is this a good solution?

        I started looking into this. It looks like the "_manifestList = new Vector();"
        line is added by
        org.exolab.castor.builder.CollectionInfo.generateInitializerCode which is called
        by org.exolab.castor.builder.SourceFactory.handleField

        Is it feasible to modify the source generator so that SourceFactory.handleField
        adds a line to the constructor that creates a instance of a group as for
        _manifestList above when it is called on a group with minOccurs=1 that can be empty?

        Thanks a lot.

        Show
        simon.bates added a comment - Is a possible solution to modify the source code generator so that: In the case that a class contains a group with a minOccurs of 1 and that group itself can be empty then the containing class creates an instance of the class representing the group in its constructor? For example rather than: public ManifestType() { super(); _manifestList = new Vector(); } could we generate: public ManifestType() { super(); _manifestList = new Vector(); _grp_any = new ca.utoronto.atrc.tile.imscp.Grp_any(); } and if so is this a good solution? I started looking into this. It looks like the "_manifestList = new Vector();" line is added by org.exolab.castor.builder.CollectionInfo.generateInitializerCode which is called by org.exolab.castor.builder.SourceFactory.handleField Is it feasible to modify the source generator so that SourceFactory.handleField adds a line to the constructor that creates a instance of a group as for _manifestList above when it is called on a group with minOccurs=1 that can be empty? Thanks a lot.
        Hide
        simon.bates added a comment -

        Created an attachment (id=245)
        ManifestType.java that contains a Grp_any

        Show
        simon.bates added a comment - Created an attachment (id=245) ManifestType.java that contains a Grp_any

          People

          • Assignee:
            Unassigned
            Reporter:
            Jack Honeghan-Bates
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated: