﻿<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns="http://www.bphx.com/report-mapping/2010-04-27"
  targetNamespace="http://www.bphx.com/report-mapping/2010-04-27"
  elementFormDefault="qualified">


  <xs:annotation>
    <xs:documentation>
      An xml schema annotations documenting a report layout, and 
      mapping its data in to xml.
    </xs:documentation>
  </xs:annotation>

  <xs:group name="view-definition">
    <xs:choice>
      <xs:element ref="page"/>
      <xs:element ref="row"/>
      <xs:element ref="iterator"/>
      <xs:element ref="data"/>
      <xs:element ref="expression"/>
    </xs:choice>
  </xs:group>

  <xs:element name="view">
    <xs:annotation>
      <xs:documentation>
        A view reference.
        Either ref or nested view is required.
      </xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:complexContent>
        <xs:extension base="view">
          <xs:attribute name="ref" type="xs:IDREF" use="optional"/>
        </xs:extension>
      </xs:complexContent>
    </xs:complexType>
  </xs:element>

  <xs:element name="page" type="page-or-row">
    <xs:annotation>
      <xs:documentation>
        Defines page view of the input view.

        Output view contains only page body data attached.
      </xs:documentation>
    </xs:annotation>
  </xs:element>

  <xs:element name="row" type="page-or-row">
    <xs:annotation>
      <xs:documentation>
        This view can be used with schema items with multiple occurences.

        Output view on each iteration is defined by head, body, foot
        elements.
      </xs:documentation>
    </xs:annotation>
  </xs:element>

  <xs:element name="iterator" type="iterator-or-data">
    <xs:annotation>
      <xs:documentation>
        This view can be used with schema items with multiple occurences.

        Output view on each iteration is defined by boundary expressions.
      </xs:documentation>
    </xs:annotation>
  </xs:element>

  <xs:element name="data" type="data">
    <xs:annotation>
      <xs:documentation>
        Output view is defined by a boundary expressions.
      </xs:documentation>
    </xs:annotation>
  </xs:element>

  <xs:element name="expression">
    <xs:annotation>
      <xs:documentation>
        A view that is evaluated from expression.
      </xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:complexContent>
        <xs:extension base="view">
          <xs:sequence>
            <xs:element name="value" type="unary-expression"/>
          </xs:sequence>
        </xs:extension>
      </xs:complexContent>
    </xs:complexType>
  </xs:element>

  <xs:complexType name="view">
    <xs:annotation>
      <xs:documentation>
        A base type for a view, optionally referring to base view either through
        nested view definition or with ref attribute.
      </xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:group ref="view-definition" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            Optional base view definition.
          </xs:documentation>
        </xs:annotation>
      </xs:group>
      <xs:group ref="var">
        <xs:annotation>
          <xs:documentation>
            Optional variable declarations.
          </xs:documentation>
        </xs:annotation>
      </xs:group>
      <xs:element name="condition" minOccurs="0" type="condition">
        <xs:annotation>
          <xs:documentation>
            Optional condition defining whether view is not empty.
            If not specified then view is not empty.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
    </xs:sequence>

    <xs:attribute name="name" type="xs:ID" use="optional">
      <xs:annotation>
        <xs:documentation>
          Optioanl view name.
          Top level nameless view name is considered as current view.
        </xs:documentation>
      </xs:annotation>
    </xs:attribute>
  </xs:complexType>

  <xs:group name="var">
    <xs:sequence>
      <xs:element name="var" minOccurs="0" maxOccurs="unbounded">
        <xs:annotation>
          <xs:documentation>
            Optional variable definitions.
          </xs:documentation>
        </xs:annotation>
        <xs:complexType>
          <xs:complexContent>
            <xs:extension base="unary-expression">
              <xs:attribute name="name" type="xs:ID"/>
            </xs:extension>
          </xs:complexContent>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:group>

  <xs:complexType name="page-or-row">
    <xs:complexContent>
      <xs:extension base="view">
        <xs:sequence>
          <xs:element name="head" type="page-or-row-part" minOccurs="0">
            <xs:annotation>
              <xs:documentation>
                If head is not specified then it does not exist.
              </xs:documentation>
            </xs:annotation>
          </xs:element>
          <xs:element name="body" type="page-or-row-part" minOccurs="0">
            <xs:annotation>
              <xs:documentation>
                If body is not specified then it occupies the space 
                between head and foot.
              </xs:documentation>
            </xs:annotation>
          </xs:element>
          <xs:element name="foot" type="page-or-row-part" minOccurs="0">
            <xs:annotation>
              <xs:documentation>
                If foot is not specified then it does not exist.
              </xs:documentation>
            </xs:annotation>
          </xs:element>
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="page-or-row-part">
    <xs:sequence>
      <xs:group ref="var"/>
      <xs:group ref="condition" minOccurs="1"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="iterator-or-data">
    <xs:annotation>
      <xs:documentation>
        Defines view with boundary defined either with expression elements or
        with literal attribures.
      </xs:documentation>
    </xs:annotation>
    <xs:complexContent>
      <xs:extension base="view">
        <xs:sequence>
          <xs:element name="left" type="unary-expression" minOccurs="0"/>
          <xs:element name="top" type="unary-expression" minOccurs="0"/>
          <xs:element name="right" type="unary-expression" minOccurs="0"/>
          <xs:element name="bottom" type="unary-expression" minOccurs="0"/>
          <xs:element name="width" type="unary-expression" minOccurs="0"/>
          <xs:element name="height" type="unary-expression" minOccurs="0"/>
        </xs:sequence>

        <xs:attribute name="left" type="xs:integer" use="optional"/>
        <xs:attribute name="top" type="xs:integer" use="optional"/>
        <xs:attribute name="right" type="xs:integer" use="optional"/>
        <xs:attribute name="bottom" type="xs:integer" use="optional"/>
        <xs:attribute name="width" type="xs:integer" use="optional"/>
        <xs:attribute name="height" type="xs:integer" use="optional"/>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="data">
    <xs:annotation>
      <xs:documentation>
        A data subview.
      </xs:documentation>
    </xs:annotation>
    <xs:complexContent>
      <xs:extension base="iterator-or-data">
        <xs:attribute name="normalize-space" type="xs:boolean"
          default="false" use="optional">
          <xs:annotation>
            <xs:documentation>
              True to normalize spaces, and false to pass data as is.
            </xs:documentation>
          </xs:annotation>
        </xs:attribute>

        <xs:attribute name="replace" type="xs:string" use="optional">
          <xs:annotation>
            <xs:documentation>
              Optional replace pattern.
            </xs:documentation>
          </xs:annotation>
        </xs:attribute>

        <xs:attribute name="replacement" type="xs:string" use="optional">
          <xs:annotation>
            <xs:documentation>
              Optional replacement value.
            </xs:documentation>
          </xs:annotation>
        </xs:attribute>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:group name="expression">
    <xs:choice>
      <xs:element name="integer">
        <xs:annotation>
          <xs:documentation>
            Integer literal position expression.
          </xs:documentation>
        </xs:annotation>
        <xs:complexType>
          <xs:complexContent>
            <xs:extension base="expression">
              <xs:attribute name="value" type="xs:integer" use="required"/>
            </xs:extension>
          </xs:complexContent>
        </xs:complexType>
      </xs:element>

      <xs:element name="var-ref">
        <xs:annotation>
          <xs:documentation>
            A variable reference expression.
          </xs:documentation>
        </xs:annotation>
        <xs:complexType>
          <xs:complexContent>
            <xs:extension base="expression">
              <xs:attribute name="name" type="xs:IDREF" use="required"/>
            </xs:extension>
          </xs:complexContent>
        </xs:complexType>
      </xs:element>

      <xs:element name="match-property">
        <xs:complexType>
          <xs:complexContent>
            <xs:extension base="expression">
              <xs:group ref="match-condition" minOccurs="1"/>
              
              <xs:attribute name="name" use="required">
                <xs:annotation>
                  <xs:documentation>
                    Match property.
                  </xs:documentation>
                </xs:annotation>
                <xs:simpleType>
                  <xs:restriction base="xs:string">
                    <xs:enumeration value="left"/>
                    <xs:enumeration value="right"/>
                    <xs:enumeration value="width"/>
                  </xs:restriction>
                </xs:simpleType>
              </xs:attribute>
            </xs:extension>
          </xs:complexContent>
        </xs:complexType>
      </xs:element>

      <xs:element name="view-property">
        <xs:complexType>
          <xs:complexContent>
            <xs:extension base="expression">
              <xs:attribute name="ref" type="xs:IDREF" use="required">
                <xs:annotation>
                  <xs:documentation>
                    A view refernece.
                  </xs:documentation>
                </xs:annotation>
              </xs:attribute>

              <xs:attribute name="name" use="required">
                <xs:annotation>
                  <xs:documentation>
                    View property.
                      index - index of occurence (1 based);
                      row - index of row in the base view (1 based);
                      local-row - index inside occurence (1 based);
                      part-row - index inside view part (1 based).
                  </xs:documentation>
                </xs:annotation>
                <xs:simpleType>
                  <xs:restriction base="xs:string">
                    <xs:enumeration value="index"/>
                    <xs:enumeration value="row"/>
                    <xs:enumeration value="local-row"/>
                    <xs:enumeration value="part-row"/>
                  </xs:restriction>
                </xs:simpleType>
              </xs:attribute>
            </xs:extension>
          </xs:complexContent>
        </xs:complexType>
      </xs:element>

      <xs:element name="add" type="binary-expression"/>
      <xs:element name="sub" type="binary-expression"/>
      <xs:element name="mul" type="binary-expression"/>
      <xs:element name="div" type="binary-expression"/>
      <xs:element name="min" type="binary-expression"/>
      <xs:element name="max" type="binary-expression"/>
      <xs:element name="condition" type="ternary-expression"/>
    </xs:choice>
  </xs:group>

  <xs:group name="match-condition">
    <xs:sequence>
      <xs:element name="match" type="match-condition">
        <xs:annotation>
          <xs:documentation>
            Match supports following properties:
            succeeds - value is 1 if match succeeds, and 0 otherwise;
            left - left match position;
            right - right match position.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
    </xs:sequence>
  </xs:group>
  
  <xs:complexType name="expression">
    <xs:annotation>
      <xs:documentation>
        A position expression.
      </xs:documentation>
    </xs:annotation>
  </xs:complexType>

  <xs:complexType name="unary-expression">
    <xs:complexContent>
      <xs:extension base="expression">
        <xs:group ref="expression" minOccurs="1"/>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="binary-expression">
    <xs:complexContent>
      <xs:extension base="expression">
        <xs:group ref="expression" minOccurs="2" maxOccurs="2"/>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="ternary-expression">
    <xs:complexContent>
      <xs:extension base="expression">
        <xs:group ref="expression" minOccurs="3" maxOccurs="3"/>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:group name="condition">
    <xs:annotation>
      <xs:documentation>
        Condition elements.
      </xs:documentation>
    </xs:annotation>
    <xs:choice>
      <xs:element name="not" type="unary-condition"/>
      <xs:element name="and" type="binary-condition"/>
      <xs:element name="or" type="binary-condition"/>
      <xs:element name="lt" type="binary-expression-condition"/>
      <xs:element name="le" type="binary-expression-condition"/>
      <xs:element name="eq" type="binary-expression-condition"/>
      <xs:element name="ge" type="binary-expression-condition"/>
      <xs:element name="gt" type="binary-expression-condition"/>
      <xs:element name="ne" type="binary-expression-condition"/>

      <xs:group ref="match-condition"/>
    </xs:choice>
  </xs:group>

  <xs:complexType name="condition">
    <xs:annotation>
      <xs:documentation>
        A basic condition expression.
      </xs:documentation>
    </xs:annotation>
  </xs:complexType>

  <xs:complexType name="unary-condition">
    <xs:complexContent>
      <xs:extension base="condition">
        <xs:group ref="condition" minOccurs="1"/>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="binary-condition">
    <xs:complexContent>
      <xs:extension base="condition">
        <xs:group ref="condition" minOccurs="2" maxOccurs="2"/>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="binary-expression-condition">
    <xs:complexContent>
      <xs:extension base="condition">
        <xs:group ref="expression" minOccurs="2" maxOccurs="2"/>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="match-condition">
    <xs:complexContent>
      <xs:extension base="condition">
        <xs:sequence>
          <xs:element name="row" type="unary-expression" minOccurs="1">
            <xs:annotation>
              <xs:documentation>
                Optional view match row.                
              </xs:documentation>
            </xs:annotation>
          </xs:element>
        </xs:sequence>
        
        <xs:attribute name="regex" type="xs:string" use="required">
          <xs:annotation>
            <xs:documentation>
              A regular expression.
            </xs:documentation>
          </xs:annotation>
        </xs:attribute>
        <xs:attribute name="flags" type="xs:string" use="optional">
          <xs:annotation>
            <xs:documentation>
              A regular flags.
            </xs:documentation>
          </xs:annotation>
        </xs:attribute>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

</xs:schema>