<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2016 CERN and GSI
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see http://www.gnu.org/licenses/.-->

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:include schemaLocation="shared.xsd" />
    
	<xs:element name="SILECS-Design">
		<xs:annotation>
			<xs:documentation>A SILECS configuration contains the class designs, the memory mapping and the hardware distribution for a given set of PLCs.</xs:documentation>
			<xs:appinfo>
				<doc>
				The SILECS configuration defines the data structure and the communication parameters required for the interconnection of the PLCs and the Front-End clients. It consists of 3 parts:
				&lt;ol&gt;
				&lt;li&gt; Design: to define the structure of the exchanged data
				&lt;li&gt; Mapping: to define the PLC memory mapping and the protocol parameters
				&lt;li&gt; Generation: to define a the hardware on which we will deployed the different Mapping
				&lt;/ol&gt;
				Generally under the responsability of a unique expert entity, an SILECS configuration is done for a set of classes and PLCs in the scope of a particular project or set of equipments.
				</doc>
			</xs:appinfo>
		</xs:annotation>
		<xs:complexType>
			<xs:sequence>
				<xs:element name="Information">
					<xs:complexType>
						<xs:sequence>
							<xs:element name="Owner">
								<xs:annotation>
									<xs:documentation>Owner is the one who created the class. He has write-access on the Design document and can deploy the corresponding class course. Owner can add Editors and Users on his class.</xs:documentation>
									<xs:appinfo>
										<doc>Owner is the one who created the class. He has write-access on the Design document and can deploy the corresponding class course. Owner can add Editors and Users on his class.</doc>
									</xs:appinfo>
								</xs:annotation>
								<xs:complexType>
									<xs:attribute name="user-login" type="xs:string" use="required"/>
								</xs:complexType>
							</xs:element>
							<xs:choice maxOccurs="unbounded">
								<xs:element name="Editor" minOccurs="0" maxOccurs="unbounded">
									<xs:annotation>
										<xs:documentation>Editor has write-access on the Design document and can deploy the corresponding class. He cannot add Editors or Users on the class.</xs:documentation>
										<xs:appinfo>
											<doc>Editor has write-access on the Design document and can deploy the corresponding class. He cannot add Editors or Users on the class.</doc>
										</xs:appinfo>
									</xs:annotation>
									<xs:complexType>
										<xs:attribute name="user-login" type="xs:string" use="required"/>
									</xs:complexType>
								</xs:element>
								<xs:element name="User" minOccurs="0" maxOccurs="unbounded">
									<xs:annotation>
										<xs:documentation>User has read-only access on the Design document but can deploy the corresponding class. He cannot add Editors or Users on the class.</xs:documentation>
										<xs:appinfo>
											<doc>User has read-only access on the Design document but can deploy the corresponding class. He cannot add Editors or Users on the class.</doc>
										</xs:appinfo>
									</xs:annotation>
									<xs:complexType>
										<xs:attribute name="user-login" type="xs:string" use="required"/>
									</xs:complexType>
								</xs:element>
							</xs:choice>
						</xs:sequence>
					</xs:complexType>
				</xs:element>
				<xs:element name="SILECS-Class">
					<xs:annotation>
						<xs:documentation>The Class node contains the definition of a particular class</xs:documentation>
						<xs:appinfo>
							<doc>
										The Class node contains the definition of a particular class. Designing a class means: 
										&lt;ol&gt;
										&lt;li&gt; Defining a unique class name in the scope of the all configuration
										&lt;li&gt; Providing list of variables which will be exchanged with the target PLC   
										&lt;li&gt; Identifying coherent groups of variables according to their nature and access mode
										&lt;/ol&gt;
										The SILECS tool assists the expert in specifying the data blocks from this abstract point of view.
										</doc>
						</xs:appinfo>
					</xs:annotation>
					<xs:complexType>
					    <xs:sequence>
                           <xs:element name="Setting-Block" type="Setting-BlockType" minOccurs="0" maxOccurs="unbounded"/>
                           <xs:element name="Acquisition-Block" type="Acquisition-BlockType" minOccurs="0" maxOccurs="unbounded"/>
                           <xs:element name="Command-Block" type="Command-BlockType" minOccurs="0" maxOccurs="unbounded"/>
                           <xs:element name="Description" type="xs:string" minOccurs="0"/>
						</xs:sequence>
						<xs:attribute name="name" type="SilecsClassNameType" use="required"/>
						<xs:attribute name="version" type="VersionType" use="required"/>
						<xs:attribute name="domain" use="required">
							<xs:annotation>
								<xs:documentation>Defines the domain of use of the class: Operation or Test</xs:documentation>
							</xs:annotation>
							<xs:simpleType>
								<xs:restriction base="xs:string">
									<xs:enumeration value="TEST"/>
									<xs:enumeration value="OPERATIONAL"/>
								</xs:restriction>
							</xs:simpleType>
						</xs:attribute>
					</xs:complexType>
					<xs:unique name="Register-name-has-to-be-unique-per-class">
						<xs:selector xpath="Block/Register"/>
						<xs:field xpath="@name"/>
					</xs:unique>
					<xs:unique name="Block-name-has-to-be-unique-per-class">
						<xs:selector xpath="Block"/>
						<xs:field xpath="@name"/>
					</xs:unique>
					<xs:unique name="Property-name-has-to-be-unique-per-class">
                        <xs:selector xpath="Block"/>
                        <xs:field xpath="@fesaPropertyName"/>
                    </xs:unique>
                    <xs:unique name="Field-name-has-to-be-unique-per-class">
                        <xs:selector xpath="Block/Register"/>
                        <xs:field xpath="@fesaFieldName"/>
                    </xs:unique>
				</xs:element>
			</xs:sequence>
			<xs:attribute name="silecs-version" type="VersionType" use="required"/>
			<xs:attribute name="created" type="xs:string" use="required"/>
			<xs:attribute name="updated" type="xs:string" use="required"/>
		</xs:complexType>
	</xs:element>


<xs:complexType name="FesaCodegenType-ServerOnly">
    <xs:sequence>
    </xs:sequence>
</xs:complexType>
    
<xs:complexType name="FesaBlockCodegenConfigType">
    <xs:sequence>
        <xs:element name="Server" minOccurs="0">
	        <xs:complexType>
		       <xs:attribute name="fesaPropertyName" type="BlockNameType" use="required">
			        <xs:annotation>
			            <xs:appinfo>Defines the name of the generated Fesa-Property.</xs:appinfo>
			        </xs:annotation>
		       </xs:attribute>
		    </xs:complexType>
        </xs:element>
        <xs:element name="RealTime" minOccurs="0">
            <xs:complexType>
               <xs:attribute name="fesaRTActionName" type="BlockNameType" use="required">
                    <xs:annotation>
                        <xs:appinfo>Defines the name of the generated Fesa-RT-Action.</xs:appinfo>
                    </xs:annotation>
               </xs:attribute>
            </xs:complexType>
        </xs:element>
    </xs:sequence>
</xs:complexType>
            
<xs:complexType name="BlockType">
	<xs:sequence>
	    <xs:element name="Description" type="xs:string" minOccurs="0"/>
	    <xs:element name="Fesa-Codegen-Config" type="FesaBlockCodegenConfigType" minOccurs="0"/>
	</xs:sequence>
	<xs:attribute name="name" type="BlockNameType" use="required">
	    <xs:annotation>
	        <xs:appinfo>
	            Defines the name of the block that must be unique in all the class.
	            Must not exceed 12 characters.
	        </xs:appinfo>
	    </xs:annotation>
	</xs:attribute>
</xs:complexType>

<xs:complexType name="Setting-BlockType">
    <xs:complexContent>
        <xs:extension base="BlockType">
	        <xs:sequence>
		        <xs:element name="Setting-Register" type="Setting-RegisterType" minOccurs="0" maxOccurs="unbounded">
		            <xs:annotation>
		                <xs:appinfo>
		                    <doc>PLC Register which can be setted and read back by Silecs. The PLC should not modify it's value.</doc>
		                </xs:appinfo>
		            </xs:annotation>
		        </xs:element>
                <xs:element name="Volatile-Register" type="Volatile-RegisterType" minOccurs="0" maxOccurs="unbounded">
                    <xs:annotation>
                        <xs:appinfo>
                            <doc>PLC Register which can be set by both, Silecs and the PLC</doc>
                        </xs:appinfo>
                    </xs:annotation>
                </xs:element>
	        </xs:sequence>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

<xs:complexType name="Acquisition-BlockType">
    <xs:complexContent>
        <xs:extension base="BlockType">
             <xs:sequence>
                <xs:element name="Acquisition-Register" type="Acquisition-RegisterType" minOccurs="0" maxOccurs="unbounded">
                    <xs:annotation>
                        <xs:appinfo>
                            <doc>PLC Register which is only read out by Silecs</doc>
                        </xs:appinfo>
                    </xs:annotation>
                </xs:element>
            </xs:sequence>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

<xs:complexType name="Command-BlockType">
    <xs:complexContent>
        <xs:extension base="BlockType">
             <xs:sequence>
                <xs:element name="Setting-Register" type="Setting-RegisterType" minOccurs="0" maxOccurs="unbounded">
                    <xs:annotation>
                        <xs:appinfo>
                            <doc>PLC Register which can be setted by Silecs. The PLC should not modify it's value.</doc>
                        </xs:appinfo>
                    </xs:annotation>
                </xs:element>
                <xs:element name="Volatile-Register" type="Volatile-RegisterType" minOccurs="0" maxOccurs="unbounded">
                    <xs:annotation>
                        <xs:appinfo>
                            <doc>PLC Register which can be set by both, Silecs and the PLC</doc>
                        </xs:appinfo>
                    </xs:annotation>
                </xs:element>
            </xs:sequence>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

<xs:complexType name="RegisterType">
    <xs:sequence>
        <xs:element name="Description" type="xs:string" minOccurs="0"/>
    </xs:sequence>
    <xs:attribute name="name" type="RegisterNameType" use="required">
        <xs:annotation>
            <xs:appinfo>
                <doc>Name must be unique and must respect the following standard:  [_A-Za-z]+[_A-Za-z0-9]*</doc>
            </xs:appinfo>
        </xs:annotation>
    </xs:attribute>
    <xs:attribute name="format" type="FormatType" use="required">
        <xs:annotation>
            <xs:appinfo>
                <doc>
                    &lt;table border = "1"&gt;
                        &lt;tr&gt;
                            &lt;th align="center"&gt; Hardware types &lt;/th&gt;
                            &lt;th align="center"&gt; Client process types &lt;/th&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td align="center"&gt; uint8 / byte &lt;/td&gt;
                            &lt;td align="center"&gt; uint8_t &lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td align="center"&gt; int8 / char &lt;/td&gt;
                            &lt;td align="center"&gt; int8_t &lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td align="center"&gt; uint16 / word &lt;/td&gt;
                            &lt;td align="center"&gt; uint16_t &lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td align="center"&gt; int16 / int &lt;/td&gt;
                            &lt;td align="center"&gt; int16_t &lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td align="center"&gt; uint32 / dword &lt;/td&gt;
                            &lt;td align="center"&gt; uint32_t &lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td align="center"&gt; int32 / dint &lt;/td&gt;
                            &lt;td align="center"&gt; int32_t &lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td align="center"&gt; uint64 &lt;/td&gt;
                            &lt;td align="center"&gt; uint64_t &lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td align="center"&gt; int64 &lt;/td&gt;
                            &lt;td align="center"&gt; int64_t &lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td align="center"&gt; float32 / real &lt;/td&gt;
                            &lt;td align="center"&gt; float &lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td align="center"&gt; float64 &lt;/td&gt;
                            &lt;td align="center"&gt; double &lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td align="center"&gt; date / dt &lt;/td&gt;
                            &lt;td align="center"&gt; double &lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td align="center"&gt; string / char[] &lt;/td&gt;
                            &lt;td align="center"&gt; string &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/table&gt;
                </doc>
            </xs:appinfo>
        </xs:annotation>
    </xs:attribute>
    <xs:attribute name="array-dim1" type="DimensionType" use="optional" default="1">
        <xs:annotation>
            <xs:appinfo>
                <doc>
                    specify register dimension.
                    &lt;br/&gt; if array-dim1 = 1 the register is a scalar. If array-dim1 > 1 the register is an array.
                </doc>
            </xs:appinfo>
        </xs:annotation>
    </xs:attribute>
    <xs:attribute name="array-dim2" type="DimensionType" use="optional" default="1">
        <xs:annotation>
            <xs:appinfo>
                <doc>
                    specify second register dimension.
                    &lt;br/&gt; if array-dim2 = 1 the register is monodimensional. If array-dim2 > 1 the register is bidimensional.
                </doc>
            </xs:appinfo>
        </xs:annotation>
    </xs:attribute>
    <xs:attribute name="string-len" type="LengthType" use="optional">
        <xs:annotation>
            <xs:appinfo>
                <doc>specify length of string. If not specified, default value is 64.</doc>
            </xs:appinfo>
        </xs:annotation>
    </xs:attribute>
    <xs:attribute name="generateFesaValueItem" type="xs:boolean" use="required">
        <xs:annotation>
            <xs:appinfo>
                Defines if the code-generation will generate a FESA-Value-Item for this Register
            </xs:appinfo>
        </xs:annotation>
    </xs:attribute>
    <xs:attribute name="fesaFieldName" type="RegisterNameType" use="optional">
        <xs:annotation>
            <xs:appinfo>Defines the name of the generated Fesa-Field. If not set, the Registername will be used.</xs:appinfo>
        </xs:annotation>
    </xs:attribute>
</xs:complexType>

<xs:complexType name="Acquisition-RegisterType">
    <xs:complexContent>
        <xs:extension base="RegisterType">
        </xs:extension>
    </xs:complexContent>
</xs:complexType>
<xs:complexType name="Setting-RegisterType">
    <xs:complexContent>
        <xs:extension base="RegisterType">
        </xs:extension>
    </xs:complexContent>
</xs:complexType>
<xs:complexType name="Volatile-RegisterType">
    <xs:complexContent>
        <xs:extension base="RegisterType">
        </xs:extension>
    </xs:complexContent>
</xs:complexType>
                                    
<xs:simpleType name="BlockNameType"> 
	<xs:restriction base="xs:string">
		<xs:minLength value="1"/>
		<xs:maxLength value="30"/>
		<!-- Siemens Support bezüglich der maximalen Zeichenlänge für PLC- Tags : S7-300/1200/1500er bei 128 Zeichen -->
		<!-- FESA PropertyNames have max. 30 characters. Since For each Block a prop is generated, we have to use this limit -->
		<xs:pattern value="[_A-Za-z]+[_A-Za-z0-9]*"/>
	</xs:restriction>
</xs:simpleType>
<xs:simpleType name="RegisterNameType">
	<xs:restriction base="xs:string">
		<xs:minLength value="1"/>
		<xs:maxLength value="60"/>
		<!-- FESA Fields have max. 60 characters. Since For each Register a field is generated, we have to use this limit -->
		<xs:pattern value="[_A-Za-z]+[_A-Za-z0-9]*"/>
	</xs:restriction>
</xs:simpleType>
<xs:simpleType name="FormatType">
	<xs:restriction base="xs:string">
		<xs:enumeration value="uint8"/>
		<xs:enumeration value="int8"/>
		<xs:enumeration value="uint16"/>
		<xs:enumeration value="int16"/>
		<xs:enumeration value="uint32"/>
		<xs:enumeration value="int32"/>
		<xs:enumeration value="uint64"/>
		<xs:enumeration value="int64"/>
		<xs:enumeration value="float32"/>
		<xs:enumeration value="float64"/>
		<xs:enumeration value="string"/>
		<xs:enumeration value="date"/>
		<xs:enumeration value="char"/>
		<xs:enumeration value="byte"/>
		<xs:enumeration value="word"/>
		<xs:enumeration value="dword"/>
		<xs:enumeration value="int"/>
		<xs:enumeration value="dint"/>
		<xs:enumeration value="real"/>
		<xs:enumeration value="dt"/>
	</xs:restriction>
</xs:simpleType>

<xs:simpleType name="DimensionType">
	<xs:restriction base="xs:unsignedInt">
		<xs:minInclusive value="1"/>
	</xs:restriction>
</xs:simpleType>
<xs:simpleType name="LengthType">
	<xs:restriction base="xs:unsignedInt">
		<xs:minInclusive value="2"/>
		<xs:maxInclusive value="254"/>
	</xs:restriction>
</xs:simpleType>

</xs:schema>