<?xml version="1.0"?>
<!-- XSD for CS (CDM <-> Storage) space mapping. -->
<xs:schema xmlns:tns="http://schemas.microsoft.com/ado/2009/11/mapping/cs"
           attributeFormDefault="unqualified"
           elementFormDefault="qualified"
           targetNamespace="http://schemas.microsoft.com/ado/2009/11/mapping/cs"
           xmlns:csmsl="http://schemas.microsoft.com/ado/2009/11/mapping/cs"
           xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:annotation>
    <xs:documentation xml:lang="en">
      Common Data Model Schema Definition Language.
      Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the MIT license.  See License.txt in the project root for license information.
    </xs:documentation>
  </xs:annotation>

  <!-- Root Level element for CS mapping -->
  <xs:element name="Mapping" type="csmsl:TMapping"/>

  <!-- Type of root level mapping elements -->
  <xs:complexType name="TMapping">
    <!-- Top level mapping element can have Alias elements followed by one EntityContainerMapping element. -->
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded" name="Alias" type="csmsl:TAlias"/>
      <xs:element name="EntityContainerMapping" type="csmsl:TEntityContainerMapping"/>
    </xs:sequence>
    <!-- Space represents the space that the mapping occurs. For CS mapping it always has to be "C-S"-->
    <xs:attribute name="Space" type="csmsl:TSpace" use="required" fixed="C-S" />
  </xs:complexType>

  <!-- Type for Alias element -->
  <xs:complexType name="TAlias">
    <xs:attribute name="Key" type="csmsl:TSimpleIdentifier" use="required" />
    <xs:attribute name="Value" type="xs:string" use="required" />
  </xs:complexType>

  <!-- Type for EntityContainerMapping element-->
  <xs:complexType name="TEntityContainerMapping">
    <xs:choice minOccurs="0" maxOccurs="unbounded">
      <xs:element name="EntitySetMapping" type="csmsl:TEntitySetMapping"/>
      <xs:element name="AssociationSetMapping" type="csmsl:TAssociationSetMapping"/>
      <xs:element name="FunctionImportMapping" type="csmsl:TFunctionImportMapping"/>
    </xs:choice>
    <xs:attribute name="CdmEntityContainer" type="csmsl:TSimpleIdentifier" use="required" />
    <xs:attribute name="StorageEntityContainer" type="xs:string" use="required" />
    <xs:attribute name="GenerateUpdateViews" type="xs:boolean" use="optional" />
  </xs:complexType>

  <!-- Type for FunctionImportMapping element -->
  <xs:complexType name="TFunctionImportMapping">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded" name="ResultMapping" type="csmsl:TFunctionImportMappingResultMapping"/>
    </xs:sequence>
    <xs:attribute name="FunctionName" type="xs:string" use="required"/>
    <xs:attribute name="FunctionImportName" type="csmsl:TSimpleIdentifier" use="required"/>
  </xs:complexType>

  <!-- Type for FunctionImportMapping/ResultMapping element -->
  <xs:complexType name="TFunctionImportMappingResultMapping">
    <xs:choice>
      <xs:element maxOccurs="unbounded" name="EntityTypeMapping" type="csmsl:TFunctionImportEntityTypeMapping"/>
      <xs:element name="ComplexTypeMapping" type="csmsl:TFunctionImportComplexTypeMapping"/>
    </xs:choice>
  </xs:complexType>

  <!-- Type for (FunctionMapping|FunctionImportMapping)/EntityTypeMapping element -->
  <xs:complexType name="TFunctionImportEntityTypeMapping">
    <xs:choice minOccurs="0" maxOccurs="unbounded">
      <xs:element name="ScalarProperty" type="csmsl:TScalarProperty" />
      <xs:element name="Condition" type="csmsl:TFunctionImportCondition" />
    </xs:choice>
    <xs:attribute name="TypeName" type="xs:string" use="required" />
  </xs:complexType>

  <!-- Type for FunctionImportMapping/Condition element-->
  <xs:complexType name="TFunctionImportCondition">
    <xs:attribute name="Value" type="xs:string" use="optional" />
    <xs:attribute name="ColumnName" type="xs:string" use="required" />
    <xs:attribute name="IsNull" type="xs:boolean" use="optional" />
  </xs:complexType>

  <!-- Type for FunctionImportMapping/ComplexTypeMapping element -->
  <xs:complexType name="TFunctionImportComplexTypeMapping">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded" name="ScalarProperty" type="csmsl:TScalarProperty" />
    </xs:sequence>
    <xs:attribute name="TypeName" type="xs:string" use="required" />
  </xs:complexType>

  <!-- Type for EntitySet mapping element -->
  <xs:complexType name="TEntitySetMapping">
    <xs:choice>
      <xs:choice>
        <xs:sequence>
          <xs:element name="QueryView" type="csmsl:TQueryView" minOccurs="0" maxOccurs="unbounded"/>
          <xs:element name="EntityTypeMapping" type="csmsl:TEntityTypeMapping" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
        <xs:sequence>
          <xs:element name="MappingFragment" type="csmsl:TMappingFragment" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
      </xs:choice>
      <xs:group ref="csmsl:TPropertyGroup"/>
    </xs:choice>
    <xs:attribute name="Name" type="csmsl:TSimpleIdentifier" use="required" />
    <xs:attribute name="TypeName" type="xs:string" use="optional" />
    <xs:attribute name="StoreEntitySet" type="xs:string" use="optional" />
    <xs:attribute name="MakeColumnsDistinct" type="xs:boolean" use="optional" />
  </xs:complexType>

  <!-- Type for AssociationSetMapping element -->
  <xs:complexType name="TAssociationSetMapping">
    <xs:sequence>
      <xs:element name="QueryView" type="xs:string" minOccurs="0" />
      <xs:element name="EndProperty" type="csmsl:TEndProperty" minOccurs="0" maxOccurs="2"/>
      <xs:element name="Condition" type="csmsl:TCondition" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="ModificationFunctionMapping" type="csmsl:TAssociationSetModificationFunctionMapping" minOccurs="0" />
    </xs:sequence>
    <xs:attribute name="Name" type="csmsl:TSimpleIdentifier" use="required" />
    <xs:attribute name="TypeName" type="csmsl:TQualifiedName" use="optional" />
    <xs:attribute name="StoreEntitySet" type="xs:string" use="optional" />
  </xs:complexType>

  <!-- Type for QueryView element -->
  <xs:complexType name="TQueryView">
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute name="TypeName" type="xs:string" use="optional" />
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>

  <!-- Type for EntityTypeMapping element-->
  <xs:complexType name="TEntityTypeMapping">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded" name="MappingFragment" type="csmsl:TMappingFragment"/>
      <xs:element minOccurs="0" name="ModificationFunctionMapping" type="csmsl:TEntityTypeModificationFunctionMapping"/>
    </xs:sequence>
    <xs:attribute name="TypeName" type="xs:string" use="required" />
  </xs:complexType>

  <!-- Type for MappingFragment element -->
  <xs:complexType name="TMappingFragment">
    <xs:group ref="csmsl:TPropertyGroup"  />
    <xs:attribute name="StoreEntitySet" type="xs:string" use="required" />
    <xs:attribute name="MakeColumnsDistinct" type="xs:boolean" use="optional" />
  </xs:complexType>

  <!-- Type for EntityTypeMapping/ModificationFunctionMapping element -->
  <xs:complexType name="TEntityTypeModificationFunctionMapping">
    <xs:all>
      <xs:element minOccurs="0" name="DeleteFunction" type="csmsl:TEntityTypeModificationFunction"/>
      <xs:element minOccurs="0" name="InsertFunction" type="csmsl:TEntityTypeModificationFunctionWithResult"/>
      <xs:element minOccurs="0" name="UpdateFunction" type="csmsl:TEntityTypeModificationFunctionWithResult"/>
    </xs:all>
  </xs:complexType>

  <!-- Type for AssociationSetMapping/ModificationFunctionMapping element -->
  <xs:complexType name="TAssociationSetModificationFunctionMapping">
    <xs:all>
      <xs:element minOccurs="0" name="DeleteFunction" type="csmsl:TAssociationSetModificationFunction"/>
      <xs:element minOccurs="0" name="InsertFunction" type="csmsl:TAssociationSetModificationFunction"/>
    </xs:all>
  </xs:complexType>

  <!-- Type for entity type DeleteFunction -->
  <xs:complexType name="TEntityTypeModificationFunction">
    <xs:group ref="csmsl:TEntityTypeModificationFunctionMappingPropertyGroup"  />
    <xs:attribute name="FunctionName" type="xs:string" use="required"/>
    <xs:attribute name="RowsAffectedParameter" type="xs:string" use="optional"/>
  </xs:complexType>

  <!-- Extensions to modification function for entity type InsertFunction and UpdateFunction -->
  <xs:complexType name="TEntityTypeModificationFunctionWithResult">
    <xs:complexContent>
      <xs:extension base="csmsl:TEntityTypeModificationFunction">
        <xs:group ref="csmsl:TResultBindingGroup"  />
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <!-- Type for association set DeleteFunction and InsertFunction -->
  <xs:complexType name="TAssociationSetModificationFunction">
    <xs:group ref="csmsl:TAssociationSetModificationFunctionMappingPropertyGroup"  />
    <xs:attribute name="FunctionName" type="xs:string" use="required"/>
    <xs:attribute name="RowsAffectedParameter" type="xs:string" use="optional"/>
  </xs:complexType>

  <!-- Grouping for entity type function mappings -->
  <xs:group name="TEntityTypeModificationFunctionMappingPropertyGroup">
    <xs:sequence>
      <xs:choice maxOccurs="unbounded">
        <xs:element minOccurs="0" name="ScalarProperty" type="csmsl:TModificationFunctionMappingScalarProperty"/>
        <xs:element minOccurs="0" name="AssociationEnd" type="csmsl:TModificationFunctionMappingAssociationEnd"/>
        <xs:element minOccurs="0" name="ComplexProperty" type="csmsl:TModificationFunctionMappingComplexProperty"/>
      </xs:choice>
    </xs:sequence>
  </xs:group>

  <!-- Grouping for entity type function mappings -->
  <xs:group name="TAssociationSetModificationFunctionMappingPropertyGroup">
    <xs:sequence>
      <xs:choice maxOccurs="unbounded">
        <xs:element name="EndProperty" type="csmsl:TModificationFunctionMappingEndProperty"/>
      </xs:choice>
    </xs:sequence>
  </xs:group>

  <!-- Type for function mapping end property -->
  <xs:complexType name="TModificationFunctionMappingEndProperty">
    <xs:group ref="csmsl:TModificationFunctionMappingAssociationEndPropertyGroup"  />
    <xs:attribute name="Name" type="csmsl:TSimpleIdentifier" use="required"/>
  </xs:complexType>

  <!-- Type for function mapping scalar property -->
  <xs:complexType name="TModificationFunctionMappingScalarProperty">
    <xs:attribute name="ParameterName" type="xs:string" use="required"/>
    <xs:attribute name="Name" type="csmsl:TSimpleIdentifier" use="required"/>
    <xs:attribute name="Version" type="csmsl:TVersion" use="optional"/>
  </xs:complexType>

  <!-- Type for function mapping result binding -->
  <xs:complexType name="TResultBinding">
    <xs:attribute name="ColumnName" type="xs:string" use="required"/>
    <xs:attribute name="Name" type="csmsl:TSimpleIdentifier" use="required"/>
  </xs:complexType>

  <!-- Type for function mapping association end -->
  <xs:complexType name="TModificationFunctionMappingAssociationEnd">
    <xs:group ref="csmsl:TModificationFunctionMappingAssociationEndPropertyGroup"  />
    <xs:attribute name="AssociationSet" type="csmsl:TSimpleIdentifier" use="required"/>
    <xs:attribute name="From" type="csmsl:TSimpleIdentifier" use="required"/>
    <xs:attribute name="To" type="csmsl:TSimpleIdentifier" use="required"/>
  </xs:complexType>

  <!-- Grouping for property bindings in function mapping end property -->
  <xs:group name="TModificationFunctionMappingAssociationEndPropertyGroup">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded" name="ScalarProperty" type="csmsl:TModificationFunctionMappingScalarProperty"/>
    </xs:sequence>
  </xs:group>

  <!-- Type for function mapping complex property -->
  <xs:complexType name="TModificationFunctionMappingComplexProperty">
    <xs:group ref="csmsl:TModificationFunctionMappingComplexPropertyPropertyGroup"  />
    <xs:attribute name="Name" type="csmsl:TSimpleIdentifier" use="required"/>
    <xs:attribute name="TypeName" type="xs:string" use="required"/>
  </xs:complexType>

  <!-- Grouping for result bindings in function mappings -->
  <xs:group name="TResultBindingGroup">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded" name="ResultBinding" type="csmsl:TResultBinding"/>
    </xs:sequence>
  </xs:group>

  <!-- Grouping for property bindings in function mapping association end -->
  <xs:group name="TModificationFunctionMappingComplexPropertyPropertyGroup">
    <xs:sequence>
      <xs:choice maxOccurs="unbounded">
        <xs:element minOccurs="0" name="ScalarProperty" type="csmsl:TModificationFunctionMappingScalarProperty"/>
        <xs:element minOccurs="0" name="ComplexProperty" type="csmsl:TModificationFunctionMappingComplexProperty"/>
      </xs:choice>
    </xs:sequence>
  </xs:group>

  <!-- Grouping these elements so that they can be reused
       These elements represent the property group
       that can either directly reside unser EntitySet, EntityType
       or MappingFragment-->
  <xs:group name="TPropertyGroup">
    <xs:sequence>
      <xs:choice maxOccurs="unbounded">
        <xs:element minOccurs="0" name="ComplexProperty" type="csmsl:TComplexProperty"/>
        <xs:element minOccurs="0" name="ScalarProperty" type="csmsl:TScalarProperty"/>
        <xs:element minOccurs="0" name="Condition" type="csmsl:TCondition"/>
      </xs:choice>
    </xs:sequence>
  </xs:group>

  <!-- Type for Condition Element-->
  <xs:complexType name="TCondition">
    <xs:attribute name="Value" type="xs:string" use="optional" />
    <xs:attribute name="Name" type="csmsl:TSimpleIdentifier" use="optional" />
    <xs:attribute name="ColumnName" type="xs:string" use="optional" />
    <xs:attribute name="IsNull" type="xs:boolean" use="optional" />
  </xs:complexType>

  <!-- Type for End Property Elements in Association Maps -->
  <xs:complexType name="TEndProperty">
    <xs:sequence>
      <xs:element maxOccurs="unbounded" name="ScalarProperty" type="csmsl:TScalarProperty"/>
    </xs:sequence>
    <xs:attribute name="Name" type="csmsl:TSimpleIdentifier" use="required" />
  </xs:complexType>

  <!-- Type for Complex Property Map elements-->
  <xs:complexType name="TComplexProperty">
    <xs:sequence>
      <xs:choice maxOccurs="unbounded">
        <xs:element name="ScalarProperty" type="csmsl:TScalarProperty"/>
        <xs:element name="ComplexProperty" type="csmsl:TComplexProperty"/>
        <xs:element name="ComplexTypeMapping" type="csmsl:TComplexTypeMapping"/>
        <xs:element name="Condition" type="csmsl:TCondition"/>
      </xs:choice>
    </xs:sequence>
    <xs:attribute name="Name" type="csmsl:TSimpleIdentifier" use="required" />
    <xs:attribute name="TypeName" type="xs:string" use="optional" />
    <xs:attribute name="IsPartial" type="xs:boolean" use="optional" />
  </xs:complexType>

  <!-- Type for Complex Type mapping element-->
  <xs:complexType name="TComplexTypeMapping">
    <xs:sequence>
      <xs:choice maxOccurs="unbounded">
        <xs:element name="ScalarProperty" type="csmsl:TScalarProperty"/>
        <xs:element name="ComplexProperty" type="csmsl:TComplexProperty"/>
        <xs:element name="Condition" type="csmsl:TCondition"/>
      </xs:choice>
    </xs:sequence>
    <xs:attribute name="TypeName" type="xs:string" use="optional" />
    <xs:attribute name="IsPartial" type="xs:boolean" use="optional" />
  </xs:complexType>

  <!-- Type for ScalarProperty Element-->
  <xs:complexType name="TScalarProperty">
    <xs:attribute name="Name" type="csmsl:TSimpleIdentifier" use="required" />
    <xs:attribute name="ColumnName" type="xs:string" use="required" />
  </xs:complexType>

  <!--Definition for SimpleIdentifier
      This is the same definition that is being used in the CSDL XSD
      -->
  <xs:simpleType name="TSimpleIdentifier">
    <xs:restriction base="xs:token">
      <!-- The below pattern represents the allowed identifiers in ECMA specification -->
      <xs:pattern value="[\p{L}\p{Nl}][\p{L}\p{Nl}\p{Nd}\p{Mn}\p{Mc}\p{Pc}\p{Cf}]{0,}"/>
    </xs:restriction>
  </xs:simpleType>

  <!--Definition for QualifiedName. QualifiedName is SimpleIdentifiers with '.'
      allowed. This is the same definition that is being used in the CSDL XSD
      -->
  <xs:simpleType name="TQualifiedName">
    <xs:restriction base="xs:token">
      <!-- The below pattern represents the allowed identifiers in ECMA specification plus the '.' for namespace qualification  -->
      <xs:pattern value="[\p{L}\p{Nl}][\p{L}\p{Nl}\p{Nd}\p{Mn}\p{Mc}\p{Pc}\p{Cf}]{0,}(\.[\p{L}\p{Nl}][\p{L}\p{Nl}\p{Nd}\p{Mn}\p{Mc}\p{Pc}\p{Cf}]{0,}){0,}"/>
    </xs:restriction>
  </xs:simpleType>

  <!--Definition for Version, which can 'original' or 'current' as its value-->
  <xs:simpleType name="TVersion">
    <xs:restriction base="xs:token">
      <xs:enumeration value="Original"/>
      <xs:enumeration value="Current"/>
    </xs:restriction>
  </xs:simpleType>

  <!-- Type fopr Space or Type Attribute -->
  <xs:simpleType name="TSpace">
    <xs:restriction base="xs:token">
      <xs:enumeration value="C-S" />
    </xs:restriction>
  </xs:simpleType>
</xs:schema>