<?xml version="1.0" encoding="UTF-8"?>
<!-- $Id: sitemap.xsd,v 1.1 2007/09/19 15:50:51 malo_pichot Exp $ -->
<xs:schema version="1.0" targetNamespace="http://apache.org/cocoon/sitemap/1.0" xmlns:map="http://apache.org/cocoon/sitemap/1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <!-- The 'sitemap' root element -->
    <xs:element name="sitemap">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="components" type="map:componentsType" minOccurs="0"/>
                <xs:element name="views" type="map:viewsType" minOccurs="0"/>
                <xs:element name="resources" type="map:resourcesType" minOccurs="0"/>
                <xs:element name="action-sets" type="map:action-setsType" minOccurs="0"/>
                <xs:element name="pipelines" type="map:pipelinesType"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <!-- ====== General types ====== -->
    <!--
    Additional types can be used for more strict validation.
    E.g.: 
        - Java class reference type (Pattern or regexp for: org.apache.cocoon.*)
        - Mime-types (Enumeration: text/html, text/xml, etc.)
        - Status codes (Pattern, regexp or enumeration: 3??, 4??, 5??)
        etc. 
    -->
    <!-- ====== Component configuration types ====== -->
    <xs:attributeGroup name="componentAttributes">
        <xs:attribute name="name" type="xs:NMTOKEN" use="required"/>
        <xs:attribute name="src" type="xs:string" use="required"/>
        <!-- FIXME (KP): Can a label be used with matchers, actions, readers or serializers? -->
        <xs:attribute name="label" type="xs:string" use="optional"/>
        <!-- Only for LogEnabled components -->
        <xs:attribute name="logger" type="xs:string" use="optional"/>
        <!-- Only for Poolable components -->
        <xs:attribute name="pool-max" type="xs:unsignedLong" use="optional"/>
        <xs:attribute name="pool-min" type="xs:unsignedLong" use="optional"/>
        <xs:attribute name="pool-grow" type="xs:unsignedLong" use="optional"/>
    </xs:attributeGroup>
    <!-- Base type for all configurable components: /map:sitemap/map:components/*/* -->
    <xs:complexType name="componentType">
        <!-- Component custom configuration parameters -->
        <xs:sequence minOccurs="0" maxOccurs="unbounded">
            <xs:any namespace="##other"/>
        </xs:sequence>
        <xs:attributeGroup ref="map:componentAttributes"/>
    </xs:complexType>
    <!-- Sitemap component types -->
    <!-- 
        Serializers have additional 'mime-type' attribute. 
        Other components use the 'componentType' directly.
    -->
    <xs:complexType name="serializerType">
        <xs:complexContent>
            <xs:extension base="map:componentType">
                <xs:attribute name="mime-type" type="xs:string" use="optional"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <!-- Sitemap component lists -->
    <xs:complexType name="componentListType">
        <xs:attribute name="default" type="xs:NMTOKEN" use="optional"/>
        <xs:attribute name="label" type="xs:string" use="optional"/>
    </xs:complexType>
    <xs:complexType name="generatorsType">
        <xs:complexContent>
            <xs:extension base="map:componentListType">
                <xs:sequence minOccurs="0">
                    <xs:element name="generator" type="map:componentType" minOccurs="0" maxOccurs="unbounded"/>
                </xs:sequence>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="transformersType">
        <xs:complexContent>
            <xs:extension base="map:componentListType">
                <xs:sequence minOccurs="0">
                    <xs:element name="transformer" type="map:componentType" minOccurs="0" maxOccurs="unbounded"/>
                </xs:sequence>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="readersType">
        <xs:complexContent>
            <xs:extension base="map:componentListType">
                <xs:sequence minOccurs="0">
                    <xs:element name="reader" type="map:componentType" minOccurs="0" maxOccurs="unbounded"/>
                </xs:sequence>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="serializersType">
        <xs:complexContent>
            <xs:extension base="map:componentListType">
                <xs:sequence minOccurs="0">
                    <xs:element name="serializer" type="map:serializerType" minOccurs="0" maxOccurs="unbounded"/>
                </xs:sequence>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="matchersType">
        <xs:complexContent>
            <xs:extension base="map:componentListType">
                <xs:sequence minOccurs="0">
                    <xs:element name="matcher" type="map:componentType" minOccurs="0" maxOccurs="unbounded"/>
                </xs:sequence>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="selectorsType">
        <xs:complexContent>
            <xs:extension base="map:componentListType">
                <xs:sequence minOccurs="0">
                    <xs:element name="selector" type="map:componentType" minOccurs="0" maxOccurs="unbounded"/>
                </xs:sequence>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <!-- FIXME (KP): Can 'actions' have a 'default' attribute? -->
    <xs:complexType name="actionsType">
        <xs:sequence>
            <xs:element name="action" type="map:componentType" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>
    <!-- 'Config' postfix used to differentiate from pipelines type -->
    <xs:complexType name="pipelinesConfigType">
        <xs:complexContent>
            <xs:extension base="map:componentListType">
                <xs:sequence minOccurs="0">
                    <xs:element name="pipe" type="map:componentType" minOccurs="0" maxOccurs="unbounded"/>
                </xs:sequence>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <!-- Sitemap component configuration: /map:sitemap/map:componenets-->
    <xs:complexType name="componentsType">
        <xs:all>
            <xs:element name="generators" type="map:generatorsType" minOccurs="0"/>
            <xs:element name="transformers" type="map:transformersType" minOccurs="0"/>
            <xs:element name="readers" type="map:readersType" minOccurs="0"/>
            <xs:element name="serializers" type="map:serializersType" minOccurs="0"/>
            <xs:element name="selectors" type="map:selectorsType" minOccurs="0"/>
            <xs:element name="matchers" type="map:matchersType" minOccurs="0"/>
            <xs:element name="actions" type="map:actionsType" minOccurs="0"/>
            <xs:element name="pipes" type="map:pipelinesConfigType" minOccurs="0"/>
        </xs:all>
    </xs:complexType>
    <!-- ====== Non component nor pipeline declarations: action-sets, views, resources.
    /map:sitemap/*[name()!='map:pipelines' and name() != 'map:components'] ====== -->
    <!-- /map:sitemap/map:action-sets -->
    <xs:complexType name="action-setsType">
        <xs:sequence>
            <xs:element name="action-set" type="map:action-setType"/>
        </xs:sequence>
    </xs:complexType>
    <!-- /map:sitemap/map:action-sets/map:action-set -->
    <xs:complexType name="action-setType">
        <xs:sequence>
            <xs:element name="act" type="map:actConfigType" maxOccurs="unbounded"/>
        </xs:sequence>
        <xs:attribute name="name" type="xs:string" use="required"/>
    </xs:complexType>
    <!-- /map:sitemap/map:action-sets/map:action-set/map:act -->
    <xs:complexType name="actConfigType">
        <xs:attribute name="action" type="xs:string" use="required"/>
        <xs:attribute name="type" type="xs:string" use="required"/>
    </xs:complexType>
    <!-- /map:sitemap/map:resources -->
    <xs:complexType name="resourcesType">
        <xs:sequence>
            <xs:element name="resource" type="map:resourceType" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>
    <!-- /map:sitemap/map:resources/map:resource -->
    <xs:complexType name="resourceType">
        <xs:complexContent>
            <xs:extension base="map:pipelineContentType">
                <xs:attribute name="name" type="xs:string" use="required"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <!-- /map:sitemap/map:views -->
    <xs:complexType name="viewsType">
        <xs:sequence>
            <xs:element name="view" type="map:viewType" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>
    <!-- /map:sitemap/map:views/map:view -->
    <xs:complexType name="viewType">
        <xs:complexContent>
            <xs:extension base="map:noGenerationPipelineType">
                <xs:sequence>
                    <xs:group ref="map:transformingComponents"/>
                    <xs:group ref="map:outputtingComponents"/>
                </xs:sequence>
                <xs:attribute name="name" type="xs:NMTOKEN" use="required"/>
                <xs:attribute name="from-label" type="xs:NMTOKEN" use="optional"/>
                <xs:attribute name="from-position" type="xs:NMTOKEN" use="optional"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <!-- This type is used as base for 'view' and 'handle-errors' types -->
    <xs:complexType name="noGenerationPipelineType">
        <xs:complexContent>
            <xs:restriction base="map:pipelineContentType">
                <xs:choice>
                    <xs:group ref="map:singletonComponents" maxOccurs="1"/>
                    <xs:group ref="map:generatingComponents" maxOccurs="1"/>
                </xs:choice>
            </xs:restriction>
        </xs:complexContent>
    </xs:complexType>
    <!-- ====== Pipeline content types: /map:sitemap/map:pipelines//* ====== -->
    <!-- //map:parameter -->
    <xs:complexType name="parameterType">
        <xs:attribute name="name" type="xs:string" use="required"/>
        <xs:attribute name="type" type="xs:string" use="optional"/>
        <xs:attribute name="value" type="xs:string" use="required"/>
    </xs:complexType>
    <xs:complexType name="parametrizedContent">
        <xs:sequence>
            <xs:element name="parameter" type="map:parameterType" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>
    <!-- A pipeline can contain the following elements.
       Direct:
           - generate
           - aggregate
           - mount
           - redirect-to
           - transform
           - serialize
           - read
       Indirect:
           - act
           - match
           - select

        1. There can be no direct elements if one of the 'mount' | 'redirect-to' | 'read' is present.
        2. If first element is one of the generating types: 'generate' | 'aggregate' | 'call' then
        the last element must be one of the outputting types: 'serialize' | 'call'.
        3. Indirect elements can appear more then once in any order, but should not break
        generate -> transform -> serialize pipelines.
   -->
    <xs:complexType name="pipelineContentType">
        <xs:complexContent>
            <xs:extension base="map:parametrizedContent">
                <xs:group ref="map:pipelineContent"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <xs:group name="pipelineContent">
        <xs:choice>
            <xs:group ref="map:singletonComponents" minOccurs="0"/>
            <xs:group ref="map:indirectComponents" minOccurs="0" maxOccurs="unbounded"/>
            <xs:group ref="map:plainPipeline" minOccurs="0"/>
            <xs:group ref="map:generatingComponents" minOccurs="0"/>
            <xs:group ref="map:transformingComponents" minOccurs="0" maxOccurs="unbounded"/>
            <xs:group ref="map:outputtingComponents" minOccurs="0"/>
        </xs:choice>
    </xs:group>
    <!-- Helper groups -->
    <xs:group name="plainPipeline">
        <xs:choice>
            <xs:sequence>
                <xs:choice>
                    <xs:group ref="map:indirectComponents" minOccurs="0" maxOccurs="unbounded"/>
                    <xs:group ref="map:generatingComponents"/>                
                </xs:choice>
                <xs:choice maxOccurs="unbounded">
                    <xs:group ref="map:indirectComponents"/>
                    <xs:group ref="map:transformingComponents"/>                
                </xs:choice>
                <xs:choice>
                    <xs:group ref="map:indirectComponents" minOccurs="0" maxOccurs="unbounded"/>
                    <xs:group ref="map:outputtingComponents"/>      
                </xs:choice>
            </xs:sequence>
            <xs:group ref="map:singletonComponents" />
        </xs:choice>
    </xs:group>
    <xs:group name="singletonComponents">
        <xs:choice>
            <xs:element name="mount" type="map:mountType"/>
            <xs:element name="redirect-to" type="map:redirect-toType"/>
            <xs:element name="read" type="map:readType"/>
        </xs:choice>
    </xs:group>
    <xs:group name="generatingComponents">
        <xs:choice>
            <xs:element name="generate" type="map:generateType"/>
            <xs:element name="aggregate" type="map:aggregateType"/>
            <xs:element name="call" type="map:callType"/>
        </xs:choice>
    </xs:group>
    <xs:group name="transformingComponents">
        <xs:choice>
            <xs:element name="transform" type="map:transformType" maxOccurs="unbounded"/>
            <xs:element name="call" type="map:callType" minOccurs="0" maxOccurs="unbounded"/>
        </xs:choice>
    </xs:group>
    <xs:group name="outputtingComponents">
        <xs:choice>
            <xs:element name="serialize" type="map:serializeType" minOccurs="0"/>
            <xs:element name="call" type="map:callType" minOccurs="0"/>
        </xs:choice>
    </xs:group>
    <xs:group name="indirectComponents">
        <xs:choice>
            <xs:element name="match" type="map:matchType"/>
            <xs:element name="act" type="map:actType"/>
            <xs:element name="select" type="map:selectType"/>
        </xs:choice>
    </xs:group>
    <!-- end of helper groups -->
    <!-- /map:sitemap/map:pipelines/map:pipeline//map:act -->
    <xs:complexType name="actType">
        <xs:complexContent>
            <xs:extension base="map:pipelineContentType">
                <xs:sequence>
                    <xs:element name="parameter" type="map:parameterType" minOccurs="0" maxOccurs="unbounded"/>
                </xs:sequence>
                <xs:attribute name="type" type="xs:string"/>
                <xs:attribute name="set" type="xs:string"/>                
                <xs:attribute name="src" type="xs:string"/>                                
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="aggregateType">
        <xs:sequence>
            <xs:element name="part" maxOccurs="unbounded">
                <xs:complexType > <!-- name="partType" -->
                    <xs:attribute name="element" type="xs:string" use="optional"/>
                    <xs:attribute name="ns" type="xs:string" use="optional"/>
                    <xs:attribute name="prefix" type="xs:string" use="optional"/>
                    <xs:attribute name="src" type="xs:string" use="required"/>             
                    <xs:attribute name="strip-root" type="xs:boolean" use="optional"/>
                    <xs:attribute name="label" type="xs:string" use="optional"/>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
        <xs:attribute name="element" type="xs:string" use="optional"/>
        <xs:attribute name="ns" type="xs:string" use="optional"/>
        <xs:attribute name="prefix" type="xs:string" use="optional"/>                
        <xs:attribute name="label" type="xs:string" use="optional"/>
    </xs:complexType>
    <xs:complexType name="callType">
        <xs:sequence>
            <xs:element name="parameter" type="map:parameterType" minOccurs="0"/>
        </xs:sequence>
        <xs:attribute name="resource" use="required" type="xs:NMTOKEN"/>
    </xs:complexType>
    <xs:complexType name="generateType">
        <xs:sequence>
            <xs:element name="parameter" type="map:parameterType" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
        <xs:attribute name="src" type="xs:string"/>
        <xs:attribute name="type" type="xs:NMTOKEN"/>
        <xs:attribute name="label" type="xs:string" use="optional"/>
    </xs:complexType>
    <xs:complexType name="handle-errorsType">
        <xs:complexContent>
            <xs:extension base="map:noGenerationPipelineType">
                <xs:sequence>
                    <xs:group ref="map:transformingComponents"/>
                    <xs:group ref="map:outputtingComponents"/>
                </xs:sequence>
                <xs:attribute name="type">
                    <xs:simpleType>
                        <xs:restriction base="xs:string">
                            <xs:pattern value="[2-5,9]0\d"/>
                        </xs:restriction>
                    </xs:simpleType>
                </xs:attribute>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="matchType">
        <xs:complexContent>
            <xs:extension base="map:pipelineContentType">
                <xs:attribute name="type" type="xs:string"/>
                <xs:attribute name="pattern" type="xs:string" use="required"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="mountType">
        <xs:attribute name="check-reload" use="required">
            <xs:simpleType>
                <xs:restriction base="xs:string">
                    <xs:enumeration value="yes"/>
                    <xs:enumeration value="no"/>
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
        <xs:attribute name="src" type="xs:string" use="required"/>
        <xs:attribute name="uri-prefix" type="xs:string" use="required"/>
        <xs:attribute name="language" type="xs:string"/>        
    </xs:complexType>
    <xs:complexType name="pipelineType">
        <xs:complexContent>
            <xs:extension base="map:pipelineContentType">
                <xs:sequence>
                    <xs:element name="handle-errors" type="map:handle-errorsType" minOccurs="0"/>
                </xs:sequence>
                <xs:attribute name="id" type="xs:string"/>
                <xs:attribute name="internal-only" type="xs:boolean"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="pipelinesType">
        <xs:sequence>
            <xs:element name="global-parameters" minOccurs="0"/>
            <xs:element name="component-configurations" minOccurs="0"/>
            <xs:element name="pipeline" type="map:pipelineType" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="readType">
        <xs:attribute name="mime-type" type="xs:string" use="required"/>
        <xs:attribute name="src" type="xs:string" use="required"/>
    </xs:complexType>
    <xs:complexType name="redirect-toType">
        <xs:attribute name="uri" type="xs:string" use="required"/>
        <xs:attribute name="session" type="xs:boolean" />        
    </xs:complexType>
    <xs:complexType name="selectType">
        <xs:sequence>        
            <xs:element name="parameter" type="map:parameterType" minOccurs="0" maxOccurs="unbounded"/>        
            <xs:element name="when" maxOccurs="unbounded">
                <xs:complexType>
                    <xs:complexContent>
                        <xs:extension base="map:pipelineContentType">
                            <xs:attribute name="test" type="xs:string"/>
                        </xs:extension>
                    </xs:complexContent>
                </xs:complexType>
            </xs:element>
            <xs:element name="otherwise" minOccurs="0" type="map:pipelineContentType" />
        </xs:sequence>
        <xs:attribute name="type" type="xs:NMTOKEN"/>
    </xs:complexType>
    <xs:complexType name="serializeType">
        <xs:attribute name="type" type="xs:NMTOKEN"/>
        <xs:attribute name="status-code" type="xs:short"/>
        <xs:attribute name="mime-type" type="xs:string"/>
    </xs:complexType>
    <xs:complexType name="transformType">
        <xs:sequence>
            <xs:element name="parameter" type="map:parameterType" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
        <xs:attribute name="src" type="xs:string"/>
        <xs:attribute name="type" type="xs:NMTOKEN"/>
        <xs:attribute name="label" type="xs:string" use="optional"/>
    </xs:complexType>
</xs:schema>
