<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<!-- $Id: sitemap-2.1-draft.xsd,v 1.2 2004/03/06 06:16:54 antonio Exp $ -->
<xs:schema version="1.0" targetNamespace="http://apache.org/cocoon/sitemap/2.0" xmlns:map="http://apache.org/cocoon/sitemap/2.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>
