<?xml version=“1.0”?> <grammar xmlns=“relaxng.org/ns/structure/1.0” datatypeLibrary=“www.w3.org/2001/XMLSchema-datatypes” ns=“riddl.org/ns/description/1.0”>

<include href="../../common/relaxng-modular.rng"/>
<include href="../../common/datatypes-1_0.rng"/>

<start>
  <element name="description">
    <ref name="riddl-description"/>
      </element>
</start>

<define name="riddl-description">
  <attribute name="datatypeLibrary">
    <data type="anyURI"/>
  </attribute>
  <ref name="riddl-description-other-atts"/>
  <zeroOrMore>
    <choice>
      <element name="message">
        <ref name="riddl-description-other-atts"/>
        <ref name="riddl-message"/>
      </element>
      <element name="transformation">
        <ref name="riddl-description-other-atts"/>
        <ref name="riddl-transformation"/>
      </element>
    </choice>
  </zeroOrMore>
  <element name="resource">
    <ref name="riddl-resource-dynamic"/>
  </element>
</define>

<define name="riddl-message">
  <ref name="riddl-att-name"/>
  <zeroOrMore>
    <ref name="riddl-header"/>
  </zeroOrMore>
  <zeroOrMore>
    <ref name="riddl-message-content"/>
  </zeroOrMore>
</define>

<define name="riddl-transformation">
  <ref name="riddl-att-name"/>
  <oneOrMore>
    <choice>
      <element name="add_header">
        <oneOrMore>
          <ref name="riddl-header"/>
        </oneOrMore>
      </element>
      <element name="add_as_first">
        <oneOrMore>
          <ref name="riddl-parameter"/>
        </oneOrMore>
      </element>
      <element name="add_as_last">
        <oneOrMore>
          <ref name="riddl-parameter"/>
        </oneOrMore>
      </element>
      <element name="add_before">
        <ref name="riddl-att-name-star"/>
        <oneOrMore>
          <ref name="riddl-parameter"/>
        </oneOrMore>
      </element>
      <element name="add_after">
        <ref name="riddl-att-name-star"/>
        <oneOrMore>
          <ref name="riddl-parameter"/>
        </oneOrMore>
      </element>
      <element name="remove_each">
        <ref name="riddl-att-col-remove"/>
      </element>
      <element name="remove_first">
        <ref name="riddl-att-col-remove"/>
      </element>
      <element name="remove_last">
        <ref name="riddl-att-col-remove"/>
      </element>
    </choice>
  </oneOrMore>
</define>

<define name="riddl-header">
  <element name="header">
    <ref name="riddl-att-name"/>
    <choice>
      <ref name="riddl-fixed"/>
      <ref name="data"/>
    </choice>
  </element>
</define>

<define name="riddl-message-content">
  <choice>
    <ref name="riddl-zeroOrMore"/>
    <ref name="riddl-oneOrMore"/>
    <ref name="riddl-optional"/>
    <ref name="riddl-choice"/>
    <ref name="riddl-parameter"/>
  </choice>
</define>
<define name="riddl-message-content-trimmed">
  <choice>
    <ref name="riddl-zeroOrMore"/>
    <ref name="riddl-oneOrMore"/>
    <ref name="riddl-choice"/>
    <ref name="riddl-group"/>
    <ref name="riddl-parameter"/>
  </choice>
</define>

<define name="riddl-zeroOrMore">
  <element name="zeroOrMore">
    <ref name="riddl-description-others"/>
    <oneOrMore>
      <ref name="riddl-message-content"/>
    </oneOrMore>
  </element>
</define>
<define name="riddl-oneOrMore">
  <element name="oneOrMore">
    <ref name="riddl-description-others"/>
    <oneOrMore>
      <ref name="riddl-message-content"/>
    </oneOrMore>
  </element>
</define>
<define name="riddl-optional">
  <element name="optional">
    <ref name="riddl-description-others"/>
    <oneOrMore>
      <ref name="riddl-message-content"/>
    </oneOrMore>
  </element>
</define>
<define name="riddl-choice">
  <element name="choice">
    <ref name="riddl-description-others"/>
    <oneOrMore>
      <ref name="riddl-message-content-trimmed"/>
    </oneOrMore>
  </element>
</define>
<define name="riddl-group">
  <element name="group">
    <ref name="riddl-description-others"/>
    <oneOrMore>
      <ref name="riddl-message-content"/>
    </oneOrMore>
  </element>
</define>
<define name="riddl-parameter">
  <element name="parameter">
    <ref name="riddl-att-name-star"/>
    <ref name="riddl-description-others"/>
    <choice>
      <ref name="riddl-fixed"/>
      <ref name="data"/>
      <group>
        <attribute name="mimetype">
          <data type="string">
            <param name="pattern">(([\c]+|\*)/[\c\+]+)|([\c]+/([\c\+]+|\*))|\*</param>
          </data>
        </attribute>
        <optional>
          <attribute name="handler">
            <data type="anyURI"/>
          </attribute>
        </optional>
        <optional>
          <ref name="any"/>
        </optional>
      </group>
    </choice>
  </element>
</define>

<define name="riddl-fixed">
  <optional>
    <attribute name="fixed">
      <data type="string"/>
    </attribute>
  </optional>
</define>

<define name="riddl-resource-attributes">
  <optional>
    <attribute name="pattern">
      <data type="anyURI"/>
    </attribute>
  </optional>
  <optional>
    <attribute name="role">
      <data type="anyURI"/>
    </attribute>
  </optional>
  <ref name="riddl-description-others"/>
</define>

<define name="riddl-resource-recursive-choice">
<!--
  It was a choice when no resources inside recursive resources were allowed.
  Beacause i doubted that worked.
  But it works just fine.
  Maybe its bad for facades but i cant find cases for that.
  Please report them if you find them.
  <choice>
    <attribute name="recursive">
      <data type="boolean"/>
    </attribute>
    <group>
      <ref name="riddl-resource-sub"/>
    </group>
  </choice-->
  <optional>
    <attribute name="recursive">
      <data type="boolean"/>
    </attribute>
  </optional>
  <ref name="riddl-resource-sub"/>
</define>

<define name="riddl-resource-dynamic">
  <ref name="riddl-resource-attributes"/>
  <ref name="riddl-resource-content"/>
  <ref name="riddl-resource-recursive-choice"/>
</define>
<define name="riddl-resource-named">
  <ref name="riddl-resource-attributes"/>
  <attribute name="relative">
    <ref name="riddl-datatype-relpath"/>
  </attribute>
  <ref name="riddl-resource-content"/>
  <ref name="riddl-resource-recursive-choice"/>
</define>

<define name="riddl-resource-sub">
  <!-- One dynamic resources, multiple named ones, before or after the dynamic -->
  <zeroOrMore>
    <element name="resource">
      <ref name="riddl-resource-named"/>
    </element>
  </zeroOrMore>
  <optional>
    <element name="resource">
      <ref name="riddl-resource-dynamic"/>
    </element>
  </optional>
  <zeroOrMore>
    <element name="resource">
      <ref name="riddl-resource-named"/>
    </element>
  </zeroOrMore>
</define>

<define name="riddl-resource-content">
  <zeroOrMore>
    <choice>
      <element name="post">
        <ref name="riddl-atts-request"/>
        <ref name="riddl-description-others"/>
      </element>
      <element name="get">
        <ref name="riddl-atts-request"/>
        <ref name="riddl-description-others"/>
      </element>
      <element name="put">
        <ref name="riddl-atts-request"/>
        <ref name="riddl-description-others"/>
      </element>
      <element name="patch">
        <ref name="riddl-atts-request"/>
        <ref name="riddl-description-others"/>
      </element>
      <element name="delete">
        <ref name="riddl-atts-request"/>
        <ref name="riddl-description-others"/>
      </element>
      <element name="request">
        <ref name="riddl-att-method"/>
        <ref name="riddl-atts-request"/>
        <ref name="riddl-description-others"/>
      </element>
      <element name="websocket">
        <empty/>
      </element>
      <element name="sse">
        <empty/>
      </element>
    </choice>
  </zeroOrMore>
</define>

<define name="riddl-description-others">
  <zeroOrMore>
    <element>
      <anyName>
        <except>
          <nsName/>
          <nsName ns=""/>
          <nsName ns="http://riddl.org/ns/description/1.0/"/>
        </except>
      </anyName>
      <zeroOrMore>
        <choice>
          <attribute>
            <anyName/>
          </attribute>
          <text/>
          <ref name="any"/>
        </choice>
      </zeroOrMore>
    </element>
  </zeroOrMore>
</define>

<define name="riddl-description-other-atts">
  <zeroOrMore>
    <attribute>
      <anyName>
        <except>
          <nsName/>
          <nsName ns=""/>
          <nsName ns="http://riddl.org/ns/description/1.0/"/>
        </except>
      </anyName>
    </attribute>
  </zeroOrMore>
</define>

</grammar>