Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: project vs product (thanks to discussions with rfscholte)
Page properties
Status 
Status
titleDRAFT
Version 
Issue(s) 
Sources 
Developer(s) Stephen Connolly

Status

This RFC is currently in the DRAFT state. Nothing in this RFC has been agreed or confirmed.

...

OPEN QUESTION: do we deploy the newer modelVersion POM as the groupId:artifactId::version::pom or as groupId:artifactId::version:build:pom? The first form ensures that the POM cannot be used as a parent by modelVersion 4.0.0 projects as they will blow up immediately, however there has been an established practice of using <packaging>pom</packaging> for projects that produce non-standard artifacts and want to opt-out of the standard lifecycle binding, and thus we would break consumption of those "side" artifacts by legacy clients. Perhaps the solution is to follow the second form (i.e. it gets deployed with <classifier>build</classifier> and either put a Maven enforcer execution into the modelVersion 4.0.0 POM or use the <prerequisites> tag to try and at least alert that the parent is invalid.

Project Dependency Trees

<project> element

The project dependency trees model consists of a top level <project> tag and three types of immediate children elements:

Open Questions

  • Hervé Boutemy: Should we move away from the term Project for this document but use Product, as Software Product in Agile?
    Issue: a "project" is either a "Top Level Project" (ex: Maven), either a "mono-module project" (ex: shared-utils), either one "module of a multi-module project" (ex: maven-artifact module of Maven core)
    And even see Wikipedia "Project (disambiguation)" article: "Project, a temporary endeavor undertaken to create a unique product or service"
    A build file (pom.xml when used by Maven to build an artifact) or description of attributes of an artifact (pom.xml when in repository) is clearly not temporary: in agile methodology, this issue has been fixed by having a product, with a product manager.

Project Dependency Trees

<project> element

The project dependency trees model consists of a top level <project> tag and three types of immediate children elements:

Code Block
languagexml
<project modelVersion="..." groupId="..." artifactId="..." [platformId="..."] version="...">
  <generator ...
Code Block
languagexml
<project modelVersion="..." groupId="..." artifactId="..." [platformId="..."] version="...">
  <generator .../>
  <information .../>
  <license .../>
  <artifacts .../>
</project>

...

Code Block
languagexml
<requires groupId="..." artifactId="..." [platformId="..."] version="..." range="..." type="..." [classifier="..."] [modelVersion="..."]>
  <component .../>
  <license .../>
  <provides .../>
  <requires .../>
  <supports .../>
  <including>
    ...
  </including>
  <excluding>
    ...
  </excluding>
</requires>

The following are mandatory elements:

...

  • platformId attribute - the platformId of the dependency
  • classifier attribute - the classifier of the dependency
  • modelVersion attribute - if the dependency's Project Dependency Tree uses a modelVersion less than or equal to the modelVersion of the root project tag in this Project Dependency Tree then this attribute must be omitted, otherwise the tag will contain the modelVersion of the dependency's Project Dependency Tree. The presence of this attribute is an indicator to the consumer that the contained elements were the result of an XSLT transformation of the dependency's tree and thus, if the consumer understands this newer modelVersion then a more correct view of the dependency tree could be obtained by fetching and parsing the dependency's Project Dependency Tree directly and substituting the parsed contents.
  • license elements - there can be any number of these, they reflect the license terms of the dependency as detailed from the dependency's tree.
  • component elements - there can be any number of these. If present they are a hint to the consumer about type specific components that are present within the dependency and that may need to be considered during conflict resolution. For example, with a JAR artifact, the components may be Java 9+ module identifiers. Consumers may ignore the component elements if they choose.
  • provides elements - there can be any number of these. If present they indicate that this dependency embeds equivalent content to the named dependency. The exact meaning of "embeds" is dependent on the type of artifact and the type of dependency.
  • requires elements - there can be any number of these. If present they indicate that the dependency has a mandatory transitive dependency.
  • supports element - there can be any number of these. If present they indicate that the dependency has an optional transitive dependency.  

<supports> element

  • including element - there can be at most one of these. If present it indicates that the dependency has been augmented by its consumer to "correct" the dependency tree.
  • excluding element - there can be at most one of these. If present it indicates that the dependency has been augmented by its consumer to "correct" the dependency tree.

<supports> element

The supports element indicates The supports element indicates an optional transitive dependency.

...

  • platformId attribute - the platformId of the dependency
  • version attribute - the version of the dependency that was resolved at build time and is the recommended default version of the dependency to use. 
  • classifier attribute - the classifier of the dependency

Example

The following is a pseudo-example of a Project Dependency Tree

  • - the classifier of the dependency

<including> element

The including element indicates that a dependency has been augmented by its immediate consumer.

Code Block
languagexml
<including>
  <component .../>
  <provides .../>
  <requires .../>
  <supports .../>
</including>

There are no mandatory elements

The following are optional elements:

  • component elements - there can be any number of these. If present they are a hint to the consumer about type specific components that are present within the dependency and that may need to be considered during conflict resolution. For example, with a JAR artifact, the components may be Java 9+ module identifiers. Consumers may ignore the component elements if they choose.
  • provides elements - there can be any number of these. If present they indicate that this dependency embeds equivalent content to the named dependency. The exact meaning of "embeds" is dependent on the type of artifact and the type of dependency.
  • requires elements - there can be any number of these. If present they indicate that the dependency has a mandatory transitive dependency.
  • supports element - there can be any number of these. If present they indicate that the dependency has an optional transitive dependency.  

<excluding> element

The including element indicates that a dependency has been augmented by its immediate consumer.

Code Block
languagexml
<excluding>
  <component .../>
  <provides .../>
  <requires .../>
  <supports .../>
</excluding>

There are no mandatory elements

The following are optional elements:

  • component elements - there can be any number of these. If present they indicate that this dependency and its transitive dependency tree - from the point of view of the immediate parent - should have the corresponding <component> elements expunged. The id can be either exact match or * style wildcard matches.
  • provides elements - there can be any number of these. If present they indicate that this dependency and its transitive dependency tree - from the point of view of the immediate parent - should have the corresponding <provides> elements expunged. The groupIdartifactId, etc coordinates can be either exact matches or * style wildcard matches.
  • requires elements - there can be any number of these. If present they indicate that this dependency and its transitive dependency tree - from the point of view of the immediate parent - should have the corresponding <requires> elements expunged. The groupIdartifactId, etc coordinates can be either exact matches or * style wildcard matches.
  • supports element - there can be any number of these. If present they indicate that this dependency and its transitive dependency tree - from the point of view of the immediate parent - should have the corresponding <supports> elements expunged. The groupIdartifactId, etc coordinates can be either exact matches or * style wildcard matches.  

Example

The following is a pseudo-example of a Project Dependency Tree

Code Block
languagexml
 <project modelVersion="..." groupId="..." artifactId="..." [platformId="..."] version="...">
    <generator name="Apache Maven" version="5.0.0" url="http://maven.apache.org"/>
    <information>
        <!-- container for descriptive information -->
        [<name>...</name>]
        [<description>...</description>]
        ...
    </information>
    <license spdx="..."/>
    <license spdx="..."/>
    ...
    <license spdx="..."/>
    <artifacts [platformId="..."]>
        <artifact type="..." [classifier="..."]>
            <information>
                <!-- optional element if need to override root level information for specific artifacts -->
            </information>
            <!-- 
              components are internal packaging constructs used by the packaging type but requiring more general validation
              e.g. for Java 9+ the ids could be the module ids if we wanted to validate that the module ids were unique in the
              effective tree.
            -->
            <component id="..."/>
            <component id="..."/>
            ...
            <component id="..."/>
            <!--
              If the artifact has a different set of licenses from those defined at the project level, we define the licenses
              of this artifact here. Otherwise we defer to the licenses defined at the top level of the project.
    
Code Block
languagexml
 <project modelVersion="..." groupId="..." artifactId="..." [platformId="..."] version="...">
    <generator name="Apache Maven" version="5.0.0" url="http://maven.apache.org"/>
    <information>
        <!-- container forlicensing descriptiveis information -->
        [<name>...</name>]
a top level concern, and legitimately can vary per artifact. Let's not solve license compatibility, 
              rather  [<description>...</description>]leverage https://spdx.org/
        ...
    </information>
-->
       <license spdx="..."/>
    <license spdx="..."/>
        ...
    <license spdx="..."/>
           <artifacts [platformId="..."]>
          <artifact type="..." [classifier  <license spdx="..."]/>
            <information><!--
              provides  <!-- optional element if need to override root level information for specific artifacts -->is a marker that we have duplication of content. This could be because we are much like the many servlet-api jar
            </information>
  files where there are many GAV's of the   <!-- 
       same javax.servlet:servlet-api:3.0 thus we could have the case where
 
       components are internal packaging constructs used by the packaging type but requiring more general validation org.jboss.spec.javax.servlet:jboss-servlet-api_3.0_spec:jar:1.0.2.Final PROVIDES javax.servlet:servlet-api:3.0
              e.g. for Java 9+ the ids could be the module ids if we wanted to validate that the module ids were unique in the
org.jboss.spec.javax.servlet:jboss-servlet-api_3.0_spec:jar:1.0.1.Final PROVIDES javax.servlet:servlet-api:3.0
              org.jboss.spec.javax.servlet:jboss-servlet-api_3.0_spec:jar:1.0.0.Final PROVIDES javax.servlet:servlet-api:3.0
               effective tree.
 org.mortbay.jetty:servlet-api-3.0:jar:7.0.0pre2 PROVIDES javax.servlet:servlet-api:3.0
 
           -->
   similarly
 
        <component id="..."/>
            <component id="..."/>
            ...
      org.slf4j:log4j-over-slf4j:jar:1.7.21 PROVIDES log4j:log4j:[1.0,2)
 
      <component id="..."/>
       The consumer of the tree <!--
can then decide if/when/how to collapse redundant nodes as they see fit.
 
  If the artifact has a different set of licenses from those defined atTODO: thedecide projectoptionality level,of weversion defineand therange licensesattributes
            -->
  of this artifact here. Otherwise we defer to the licenses defined at the top level of the project.<provides groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]>
              licensing is a top level concern, and legitimately can vary per artifact. Let's not solve license compatibility, <!-- no elements here as we have "rebundled" hence implicitly promoted up one level-->
              rather leverage https://spdx.org/</provides>
            -->
            <license spdx<provides groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]/>
            <license spdx="..."/>
            <provides groupId="...
            <license spdx" artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]/>
            <!--
              providesrequires isare athe marker that we have duplication of contentmandatory dependencies. This is couldeffectively bea becauserecursive weartifact arewhere muchthe likeGAV theis manynot servlet-apiinherited jarand
              files where there are many GAV's ofwe have discarded the sameinformation javax.servlet:servlet-api:3.0 thus we could have the case where
 
  section. If you want those details, fetch that project's dependencies trees.
            org.jboss.spec.javax.servlet:jboss-servlet-api_3.0_spec:jar:1.0.2.Final PROVIDES javax.servlet:servlet-api:3.0
->
            <requires groupId="..."   org.jboss.spec.javax.servlet:jboss-servlet-api_3.0_spec:jar:1.0.1.Final PROVIDES javax.servlet:servlet-api:3.0artifactId="..." [platformId="..."] version="..." range="..." type="..." [classifier="..."]>
              org.jboss.spec.javax.servlet:jboss-servlet-api_3.0_spec:jar:1.0.0.Final PROVIDES javax.servlet:servlet-api:3.0
  <component id="..."/>
                <license org.mortbay.jetty:servlet-api-3.0:jar:7.0.0pre2 PROVIDES javax.servlet:servlet-api:3.0
 
spdx:id="..."/>
                <provides groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."]  similarly
 
type="..." [classifier="..."]/>
                <requires org.slf4j:log4j-over-slf4j:jar:1.7.21 PROVIDES log4j:log4j:[1.0,2)
 groupId="..." artifactId="..." [platformId="..."] version="..." range="..." type="..." [classifier="..."]>
              The consumer of the tree can then decide if/when/how to collapse redundant nodes as they see fit ...
 
              TODO: decide optionality of version and range attributes </requires>
            -->
            <provides <supports groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]>
                <!-- no elements here as we have "rebundled" hence implicitly promoted up one level--..."]/>
            </provides>requires>
            <provides<requires groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]/>>
                ...
            </requires>
            ...
            <provides<requires groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]/>
                <!--...
            </requires>
  requires are the mandatory dependencies. This is effectively a recursive artifact<!--
 where the GAV is not inherited and
       supports are the optional dependencies. We list wherethem wehere haveto discardedaid thein informationconflict sectionresolution. We do Ifnot youinclude wanta thosenested details,tree
 fetch that project's dependencies trees.
         as a consumer -->
would only pull them in if the consumer already has its own <requires groupId="..." artifactId="..." [platformId="..."] version="..." range="..." type="..." [classifier="..."]>a requires for them, so we really only
              need to validate <componentthe id="..."/>
range. 
 
              TODO: decide optionality <license spdx:id="..."/>of range attribute
              TODO: decide <provides groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]/>
    if we want a version attribute 
            -->
            <requires<supports groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]>
                    ...
                </requires>
    ..."]/>
            <supports groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]/>
            </requires>
            <requires<supports groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]/>
            <including>
    ...
             </requires>
       <component id="..."/>
     ...
           <provides <requires groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]>
                ...
            </requires>
            <!--
      />
        supports are the optional dependencies. We list them here to aid in conflict resolution. We do not include a nested tree
<requires groupId="..." artifactId="..." [platformId="..."] version="..." range="..." type="..." [classifier="..."]>
                   as a...
 consumer would only pull them in if the consumer already has its own a requires for them, so we really only
</requires>
                <supports   need to validate the range. 
 groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]/>
            </including>
  TODO: decide optionality of range attribute
     <excluding>
         TODO: decide if we want a version attribute 
 <component id="..."/>
           -->
            <supports <provides groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]/>
                <supports<requires groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]/>
                <supports groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]/>
            </excluding>
        </artifact>
        <artifact ...>
            ...
        </artifact>
        ...
        <artifact ...>
            ...
        </artifact>
    </artifacts>
    <!-- if the project does not specify a platformId then we can include additional platform details that were part of the atomic deployment -->
    <artifacts platformId="...">
        ...
    </artifacts>
        ...
    <artifacts platformId="...">
        ...
    </artifacts>
</project>

...

Here is a draft XML schema:

TODO: Add the including and excluding elements to the schema

Code Block
languagexml
 <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" >
  <xsd:simpleType name=”coordinate”>
    <xsd:restriction base=”xsd:string”>
      <!-- TODO add pattern for groupId/artifactId/platformId/version/type/classifier valid values -->
    </xsd:restriction>
  </xsd:simpleType>
  <xs:element name="project">
    <xs:annotation>
      <xs:documentation source="version">5.0.0+</xs:documentation>
      <xs:documentation source="description">
        The <code>&lt;project&gt;</code> element is the root of the project
        dependency trees.
      </xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:attribute name="modelVersion" type="xs:string"/>
      <xs:attribute name="groupId" type="coordinate"/>
      <xs:attribute name="artifactId" type="coordinate"/>
      <xs:attribute name="version" type="coordinate"/>
      <xs:attribute name="platformId" type="coordinate" use="optional"/>
      <xs:all>
        <xs:element ref="generator" minOccurs="1" maxOccurs="1"/>
        <xs:element ref="information" minOccurs="0" maxOccurs="1"/>
        <xs:element ref="license" minOccurs="0" maxOccurs="unbounded"/>
        <xs:element ref="artifacts" minOccurs="1" maxOccurs="unbounded"/>
      </xs:all>
    </xs:complexType>
  </xs:element>
  <xs:element name="generator">
    <xs:annotation>
      <xs:documentation source="version">5.0.0+</xs:documentation>
      <xs:documentation source="description">
        The <code>&lt;generator&gt;</code> element identifies the build tool
        responsible for creating this document
      </xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:attribute name="name" type="xs:string"/>
      <xs:attribute name="version" type="xs:string"/>
      <xs:attribute name="url" type="xs:string"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="information">
    <xs:annotation>
      <xs:documentation source="version">5.0.0+</xs:documentation>
      <xs:documentation source="description">
        The <code>&lt;information&gt;</code> element is a container for 
        descriptive information about either all the artifacts in a project or 
        a specific artifact.
      </xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:all>
        <xs:element name="name" type="xs:string" maxOccurs="1"/>
        <xs:element name="description" type="xs:string" maxOccurs="1"/>
        <!-- TODO add additional elements -->
      </xs:all>
    </xs:complexType>
  </xs:element>
  <xs:element name="license" xmlns:spdx="http://spdx.org/rdf/terms#">
    <xs:annotation>
      <xs:documentation source="version">5.0.0+</xs:documentation>
      <xs:documentation source="description">
        The <code>&lt;license&gt;</code> element defines one of the licenses
        under which the artifacts are made available. Where a license is 
        attached to the <code>&lt;project&gt;</code> element this defines the 
        default licenses for all artifacts in the project. Where a license is 
        attached to an <code>&lt;artifact&gt;</code> element this signifies 
        that the specific artifact is covered by the 
        <code>&lt;license&gt;</code> elements defined within that 
        <code>&lt;artifact&gt;</code> element. Licenses are identified using 
        the <a href="http://spdx.org">SPDX</a> identifiers
     </xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:attribute name="spdx" type="xs:string"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="artifacts">
    <xs:annotation>
      <xs:documentation source="version">5.0.0+</xs:documentation>
      <xs:documentation source="description">
        The <code>&lt;artifacts&gt;</code> element is a container for 
        details of artifacts. When the <code>&lt;artifacts&gt;</code> attribute
        is missing, then the artifacts listed are not platform specific.
        The <code>&lt;artifacts&gt;</code> must be unique with respect to their
        <code>&lt;platformId&gt;</code>, i.e. it cannot be repeated.
        If the <code>&lt;project&gt;</code> element has a 
        <code>&lt;platformId&gt;</code> then there must be only one
        <code>&lt;artifacts&gt;</code> element and it must have the matching
        <code>&lt;platformId&gt;</code>.
      </xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:attribute name="platformId" type="coordinate" use="optional"/>
      <xs:sequence>
        <xs:element ref="artifact" minOccurs="1" maxOccurs="unbounded"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="artifact">
    <xs:annotation>
      <xs:documentation source="version">5.0.0+</xs:documentation>
      <xs:documentation source="description">
        The <code>&lt;artifact&gt;</code> element represents an artifact
        associated with the project.
      </xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:attribute name="type" type="coordinate"/>
      <xs:attribute name="classifier" type="coordinate" use="optional"/>
      <xs:all>
        <xs:element ref="information" minOccurs="0" maxOccurs="1"/>
        <xs:element ref="license" minOccurs="0" maxOccurs="unbounded"/>
        <xs:element ref="component" minOccurs="0" maxOccurs="unbounded"/>
        <xs:element ref="provides" minOccurs="0" maxOccurs="unbounded"/>
        <xs:element ref="requires" minOccurs="0" maxOccurs="unbounded"/>
        <xs:element ref="supports" minOccurs="0" maxOccurs="unbounded"/>
      </xs:all>
    </xs:complexType>
  </xs:element>
  <xs:element name="component">
    <xs:annotation>
      <xs:documentation source="version">5.0.0+</xs:documentation>
      <xs:documentation source="description">
        The <code>&lt;component&gt;</code> element represents a type specific
        component that is present within the artifact. For example a "jar"
        artifact might list the Java 9+ modules that are included within
        the "jar". Other file types can use the component according to the
        conventions of that file type. The component information is intended
        to assist build time tools in conflict detection when resolving
        the composite dependency tree according to the build tools
        dependency resolution strategy.
      </xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:attribute name="id" type="xs:string"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="provides">
    <xs:annotation>
      <xs:documentation source="version">5.0.0+</xs:documentation>
      <xs:documentation source="description">
        The <code>&lt;provides&gt;</code> element represents a semantic
        equivalence with another artifact. There are several ways the element
        can be used.
        <nl>
          <li>
            When an artifact directly includes the same content as another 
            project's artifacts, for example there are some "jar" files that 
            will embed other artifacts to produce a so-called "uber-jar".
          </li>
          <li>
            When an artifact re-implements the API of another project's 
            artifact. For example: log4j-over-slf4j reimplements the log4j
            API.
          </li> 
          <li>
            When a set of projects are co-operating to provide multiple
            implementations of a "virtual" project artifact. For example:
            slf4j-log4j, slf4j-jul, and logback could all be considered
            as providing a slf4j-impl virtual project artifact. There would
            be no actual project at the slf4j-impl coordinates, but
            slf4j-api could declare a requirement on the "virtual" project
            artifact in order to ensure that an implementation is available
            to consumers of the API
          </li>
        </nl>
      </xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:attribute name="groupId" type="coordinate"/>
      <xs:attribute name="artifactId" type="coordinate"/>
      <xs:attribute name="platformId" type="coordinate" use="optional"/>
      <xs:attribute name="version" type="coordinate"/>
      <xs:attribute name="range" type="xs:string"/>
      <xs:attribute name="type" type="coordinate"/>
      <xs:attribute name="classifier" type="coordinate" use="optional"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="requires">
    <xs:annotation>
      <xs:documentation source="version">5.0.0+</xs:documentation>
      <xs:documentation source="description">
        The <code>&lt;requires&gt;</code> element represents a hard dependency
        on another project's artifact. If the <code>&lt;version&gt;</code>
        attribute is missing then this indicates that the dependency is
        a virtual dependency, and there must be no child elements.
        The <code>&lt;modelVersion&gt;</code> attribute must only be present
        if the dependent project's <code>&lt;modelVersion&gt;</code> is newer
        than the <code>&lt;modelVersion&gt;</code> specified on the root 
        <code>&lt;project&gt;</code> element. The presence of this element
        indicates that the child information was the result of an XSLT
        transformation of a newer <code>&lt;modelVersion&gt;</code> and
        indicates that a build tool understanding the newer 
        <code>&lt;modelVersion&gt;</code> may want to fetch the dependencies
        tree and process it directly in order to obtain the most correct
        model of the dependency.
      </xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:attribute name="groupId" type="coordinate"/>
      <xs:attribute name="artifactId" type="coordinate"/>
      <xs:attribute name="platformId" type="coordinate" use="optional"/>
      <xs:attribute name="version" type="coordinate" use="optional"/>
      <xs:attribute name="range" type="xs:string"/>
      <xs:attribute name="type" type="coordinate"/>
      <xs:attribute name="classifier" type="coordinate" use="optional"/>
      <xs:attribute name="modelVersion" type="xs:string" use="optional"/>
      <xs:all>
        <xs:element ref="license" minOccurs="0" maxOccurs="unbounded"/>
        <xs:element ref="component" minOccurs="0" maxOccurs="unbounded"/>
        <xs:element ref="provides" minOccurs="0" maxOccurs="unbounded"/>
        <xs:element ref="requires" minOccurs="0" maxOccurs="unbounded"/>
        <xs:element ref="supports" minOccurs="0" maxOccurs="unbounded"/>
      </xs:all>
    </xs:complexType>
  </xs:element>
  <xs:element name="supports">
    <xs:annotation>
      <xs:documentation source="version">5.0.0+</xs:documentation>
      <xs:documentation source="description">
        The <code>&lt;supports&gt;</code> element represents a soft dependency
        on another project's artifact. This element is provided in order to
        allow build time tools to perform conflict resolution when determining
        the effective tree from multiple dependencies.
      </xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:attribute name="groupId" type="coordinate"/>
      <xs:attribute name="artifactId" type="coordinate"/>
      <xs:attribute name="platformId" type="coordinate" use="optional"/>
      <xs:attribute name="version" type="coordinate"/>
      <xs:attribute name="range" type="xs:string"/>
      <xs:attribute name="type" type="coordinate"/>
      <xs:attribute name="classifier" type="coordinate" use="optional"/>
    </xs:complexType>
  </xs:element>
</xs:schema>

...