<?xml version='1.0' encoding='iso-8859-1'?>
<!-- XÖV-Profil 1.4.0 - XÖV-Prüfanweisungen (Empfehlungen) -->

<invariants xmlns="http://www.osci.de/xoev/invariants" level="recommendation">
  
  <rule name='NDR-5: Detaillierte Struktur des UML-Modells'>
    
  <invariant context='Model' name='BasisdatentypenSchemaDefined'>
    <body><![CDATA[
      self = self.hlpXModel() implies
        ((self.ownedMember->select(e|e.oclIsTypeOf(Package))->select(p|
          p.oclAsType(Package).extension_xsdSchema.isDefined() and p.name = 'Basisdatentypen' and p.owner=self))
        ->notEmpty())				
    ]]></body>
    <documentation>
      Das «xsdXModel»-UML-Modell des XÖV-Standards enthält ein «xsdSchema»-UML-Paket mit dem Namen 
      "Basisdatentypen".
    </documentation>
  </invariant>
	  
  <invariant context='Model' name='BaukastenSchemaDefined'>
    <body><![CDATA[
     self = self.hlpXModel() implies
      (self.ownedMember->select(e|e.oclIsTypeOf(Package))->select(p|
        p.oclAsType(Package).extension_xsdSchema.isDefined() and 
        p.name = 'Baukasten' and p.owner = self))
      ->notEmpty()			
    ]]></body>
    <documentation>
      Das «xsdXModel»-UML-Modell des XÖV-Standards enthält ein «xsdSchema»-UML-Paket mit dem Namen 
      "Baukasten".
    </documentation>
  </invariant>
	  
  <invariant context='Model' name='NachrichtenOrFachmodulePackageDefined'>
    <body><![CDATA[
      self = self.hlpXModel() implies
       (self.ownedMember->select(e|e.oclIsTypeOf(Package))->select(p|
         not(p.oclAsType(Package).extension_xsdSchema.isDefined()) and (p.name = 'Nachrichten' or p.name = 'Fachmodule') and p.owner=self))
       ->notEmpty()
    ]]></body>
    <documentation>
      Das «xsdXModel»-UML-Modell des XÖV-Standards enthält ein UML-Paket mit dem Namen "Nachrichten" 
      oder "Fachmodule".
    </documentation>
  </invariant>
	
  <invariant context='Model' name='AtLeastOneHauptgruppenSchemaDefined'>
    <body><![CDATA[
      self = self.hlpXModel() implies
      ((self.ownedMember->select(e|e.oclIsTypeOf(Package))->any(p|
        not(p.oclAsType(Package).extension_xsdSchema.isDefined()) and 
		(p.name = 'Nachrichten' or p.name = 'Fachmodule') and p.owner=self).oclAsType(Package).nestedPackage
	    ->select(p1|p1.extension_xsdSchema.isDefined and not(p1.name = 'Nachrichtentypen')))->notEmpty())							
    ]]></body>
    <documentation>
      Das «xsdXModel»-UML-Modell des XÖV-Standards enthält ein UML-Paket mit dem Namen "Nachrichten"
      oder "Fachmodule", das mindestens ein «xsdSchema»-Paket als Hauptgruppe mit beliebigem Namen 
      enthält.
    </documentation>
  </invariant>
   
  <invariant context='Class' name='ExclusivelyHauptgruppenPackagesWithMessages'>
    <body><![CDATA[
      self.extension_xsdMessage.isDefined() and 		  
      self.hlpIsPartOfXModel() implies
        (self.hlpOwningSchema().owner.oclAsType(NamedElement).name = 'Nachrichten' 
         or self.hlpOwningSchema().owner.oclAsType(NamedElement).name = 'Fachmodule') and
        self.hlpOwningSchema().owner.owner = self.hlpXModel() 
    ]]></body>
    <documentation>
      Ausschließlich «xsdSchema»-UML-Pakete innerhalb des UML-Pakets "Nachrichten" bzw. "Fachmodule" 
      enthalten «xsdMessage»-UML-Klassen.
    </documentation>
  </invariant>
	   
  <invariant context='Package' name='NoHauptgruppenPackagesWithoutMessages'>
    <body><![CDATA[
      self.hlpIsMessagePackage() and 
      self.extension_xsdSchema.isDefined and 
      self.hlpIsPartOfXModel() implies
        self.hlpOwnedTypes()->exists(t | t.oclAsType(Class).extension_xsdMessage.isDefined)
    ]]></body>
    <documentation>
      «xsdSchema»-UML-Pakete innerhalb des UML-Pakets "Nachrichten" bzw. "Fachmodule" enthalten 
      mindestens eine «xsdMessage»-UML-Klasse.
    </documentation> 
  </invariant>
  </rule>  
  <rule name='NDR-7: XML-Wildcard-Elemente mit Namensraum'>
    
  <invariant context='Class' name='AnyContentsWithNamespace'>
    <body><![CDATA[
      self.extension_xsdAnyContents.isDefined() and
      self.hlpIsPartOfXModel() implies
        self.extension_xsdAnyContents.namespace.isDefined() and 
        self.extension_xsdAnyContents.namespace <> ''
    ]]></body>
    <documentation>
      Wildcard-Elemente (UML-Klassen mit dem Stereotyp «xsdAnyContents») haben einen Namensraum 
      ("namespace").
    </documentation>
  </invariant>
  </rule>  
  <rule name='NDR-15: Groß- und Kleinschreibung von (und in zusammengesetzten) Namen'>
	  
  <invariant context='Classifier' name='TypeNameStartsWithUpperCaseLetter'>
    <body><![CDATA[
      self.extension_xsdNamedType.isDefined and 
      self.hlpIsPartOfXModel() implies
        self.hlpUpperCaseLetters()->includes(self.name.substring(1, 1))
    ]]></body>
    <documentation>
      Namen von UML-Klassen und UML-Enumerationen mit dem Stereotyp «xsdNamedType» beginnen mit einem Großbuchstaben.
    </documentation> 
  </invariant>
	  
 <invariant context='Property' name='ElementOrAttributeNameStartsWithLowerCaseLetter'>
    <body><![CDATA[
      (self.extension_xsdElement.isDefined or self.extension_xsdAttribute.isDefined) and 
      not self.isReference() and
	  self.hlpIsPartOfXModel() implies
        self.hlpLowerCaseLetters()->includes(self.name.substring(1, 1))
    ]]></body>
    <documentation>
      Namen von UML-Klasseneigenschaften mit dem Stereotyp «xsdElement» und «xsdAttribute» beginnen mit 
      einem Kleinbuchstaben.
    </documentation> 
  </invariant>

  <invariant context='Class' name='GlobalElementNameStartsWithLowerCaseLetter'>
    <body><![CDATA[
      not self.isPartOfAdapter() and
      self.extension_xsdGlobalElement.isDefined and 
      self.hlpIsPartOfXModel() implies
        self.hlpLowerCaseLetters()->includes(self.name.substring(1, 1))
    ]]></body>
    <documentation>
      Namen von UML-Klassen mit dem Stereotyp «xsdGlobalElement» beginnen mit einem Kleinbuchstaben.
    </documentation> 
  </invariant>
  </rule>	
  <rule name='NDR-16: Namensstruktur von Nachrichten'>	
	  
  <invariant context='Class' name='PrefixForMessages'>
    <body><![CDATA[
      if (self.extension_xsdMessage.isDefined() 
	   and self.hlpIsPartOfXModel()) then
	    let nameParts = self.hlpSplitString(Tuple{aString=self.name, splitChar='.'}) in
          nameParts->size() >= 2
      else
        true
      endif      
    ]]></body>
    <documentation>
      Für Namen von UML-Klassen mit dem Stereotyp «xsdMessage» existiert ein mit einem Punkt 
      abgetrennter Präfix.
    </documentation> 
  </invariant>
	  
  <invariant context='Class' name='PrefixForMessagesEqualsSchemaPackageName'>
    <body><![CDATA[
      let groupName = self.hlpOwningSchema().name in
      let prefix = self.hlpSplitString(Tuple{aString=self.name, splitChar='.'})->first() in
      self.extension_xsdMessage.isDefined() and 
      self.hlpIsPartOfXModel() implies
        if (prefix.size() = 1) then
          prefix.substring(1,1).toLower()
        else
          prefix.substring(1, 1).toLower().concat(prefix.substring(2, prefix.size()))
        endif
        =
        if (groupName.size() = 1) then
          groupName.substring(1,1).toLower()
        else
          groupName.substring(1, 1).toLower().concat(groupName.substring(2, groupName.size()))
        endif
    ]]></body>
    <documentation>
      Der Namens-Präfix einer UML-Klasse mit dem Stereotyp «xsdGlobalElement» ist identisch mit dem 
      Namen seines Hauptgruppen-«xsdSchema»-UML-Pakets (Hinweis: die Anfangsbuchstaben der 
      UML-Klasse und des UML-Pakets dürfen sich unterscheiden, z.B. "hamsterzuchtregister.hamstergeburtsmeldung.0101" und "Hamsterzuchtregister").
    </documentation> 
  </invariant>
  </rule>  
  <rule name='NDR-17: Eindeutige versionsübergreifende Nummern in Namen von Nachrichten'>
	 
  <invariant context='Class' name='MessagesWithNumericalSuffix'>
    <body><![CDATA[
      let nameSeq:Sequence(String) = self.hlpSplitString(Tuple{aString=self.name, splitChar='.'}) in
      let suffixIndex:Sequence(Integer) = Sequence{1..nameSeq->last().size()} in
      let digits:Set(String) = self.hlpDigits() in
      self.extension_xsdMessage.isDefined and
      self.hlpIsPartOfXModel() implies
        suffixIndex->forAll(i | 
          digits->includes(nameSeq->last().substring(i, i)))
    ]]></body>
    <documentation>
      In Namens-Suffixen von UML-Klassen mit dem Stereotyp «xsdMessage» treten nach dem letzten 
      abgrenzenden Punkt nur Ziffern auf.
    </documentation> 
  </invariant>
	  
  <invariant context='Model' name='MessageSuffixUnique'>
    <body><![CDATA[
      if (self = self.hlpXModel()) then
        Class.allInstances()->select(c | 
          c.extension_xsdMessage.isDefined()and c.hlpIsPartOfXModel() )
          ->isUnique(c |
            (c.hlpSplitString(Tuple{aString=c.name, splitChar='.'})
            ->last()).concat(c.hlpOwningSchema().hlpPackageNamespace()))
      else
        true
      endif
    ]]></body>
    <documentation>
      Nachrichtennummern (numerisch Namens-Suffix einer UML-Klasse mit 
      dem Stereotyp «xsdMessage») sind in einem Namensraum eindeutig zu 
      definieren. 
    </documentation> 
  </invariant>
  </rule>	
  <rule name='NDR-18: Namen von XML-Schema-Dateien'>
	
  <invariant context='Package' name='SchemaFileNameIncludesStandardName'>
    <body><![CDATA[
      let pro:String = self.hlpProjectName() in	
      let sf:String = self.extension_xsdSchema.schemaFile in
        self.extension_xsdSchema.isDefined and 
        sf.isDefined and 
        sf <> '' and         
        self.hlpIsPartOfXModel() implies 
          sf.size >= pro.size and Sequence{1 .. (sf.size)}->exists(i|
            sf.substring(i,i+pro.size-1)=pro)
    ]]></body>
    <documentation>
      Der Name einer XML-Schema-Datei enthält über die Eigenschaft 
      "schemaFile" des «xsdSchema»-UML-Pakets den Namen des 
      «xsdXModel»-UML-Modells zum XÖV-Standard in Kleinbuchstabem. 
    </documentation>
  </invariant>
  
  <invariant context='Package' name='SchemaLocationIncludesStandardName'>
    <body><![CDATA[
      let pro:String = self.hlpProjectName() in	
      let sl:String = self.extension_xsdSchema.schemaLocation in
	  let deploy:Boolean = self.hlpOwningModel().extension_xsdXModel.deployment in
	  let slb:String = self.hlpOwningModel().extension_xsdXModel.schemaLocationBase in
      deploy and self.hlpIsPartOfXModel() and self.extension_xsdSchema.isDefined() implies 
        (sl.isDefined() or slb.isDefined()) and
        (sl.isDefined() implies 
          sl.size >= pro.size and 
          Sequence{1 .. (sl.size)}->exists(i| sl.substring(i,i+pro.size-1)=pro))
    ]]></body>
    <documentation>
      Der Name einer XML-Schema-Datei enthält über die Eigenschaft  
      "schemaLocation" (Stereotyp «xsdSchema») bzw. 
      "schemaLocationBase" (Stereotyp «xsdXModel») den Namen des 
      «xsdXModel»-UML-Modells zum XÖV-Standard für den Fall, das die 
      Eigenschaft "deployment" des «xsdXModel»-UML-Modells den Wert 
      "true" aufweist. 
    </documentation>
  </invariant>
  </rule>
  <rule name='NDR-20: Dokumentation der Rechtsgrundlagen'>
    
  <invariant context='Class' name='LegalBasisDocumentedForMessages'>
    <body><![CDATA[
      self.extension_xsdMessage.isDefined() and 
	  self.hlpIsPartOfXModel() 
       implies
        self.extension_xsdMessage.rechtsgrundlagen->exists(r|r<>'')
    ]]></body>
    <documentation>
      Die rechtlichen Grundlagen einer Nachricht sind über die 
      Eigenschaft "rechtsgrundlagen" im Stereotyp «xsdMessage» zu 
      dokumentieren. 
    </documentation>
  </invariant>
  </rule>  
  <rule name='NDR-21: Codenamen für Codelisten-Einträge'>
    
  <invariant context='EnumerationLiteral' name='CodeNamesDefined'>
    <body><![CDATA[
      self.extension_xsdCodeListEntry.isDefined() and
	  self.hlpIsPartOfXModel() implies
        self.extension_xsdCodeListEntry.name.isDefined() and self.extension_xsdCodeListEntry.name <> ''
    ]]></body>
    <documentation>
      Einem UML-EnumerationLiteral mit Stereotyp «xsdCodeListEntry» ist für die Eigenschaft "name" immer 
      ein Wert zugeordnet.
    </documentation>
  </invariant>
  </rule>  
  <rule name='NDR-27: Verwendung von Original-Namespace-Präfixen bei Schema-Importen'>
    
  <invariant context='Dependency' name='ImportPrefixEqualsImportedSchema'>
    <body><![CDATA[
      self.extension_xsdImport.isDefined() and
	  self.hlpIsPartOfXModel() implies
        (self.extension_xsdImport.prefix.isUndefined() or self.extension_xsdImport.prefix = '')
    ]]></body>
    <documentation>
      Für eine «xsdImport»-UML-Abhängigkeit ist der Wert für die Eigenschaft "prefix" nicht belegt.
    </documentation>
  </invariant>
  </rule>    
  
  <rule name='NDR-XX: Abzustimmen'>
    <invariant context='Property' name='RefsShouldBeUnnamed'>
      <body><![CDATA[
        self.extension_xsdElement.isDefined() and
		self.extension_xsdElement.isRef and
	    self.hlpIsPartOfXModel() implies
          self.name.isUndefined() or self.name = ''
      ]]></body>
      <documentation>Die Namen von Attributen, die auf globale Elemente verweisen haben keinen Einfluss auf die Schemata.
	  Daher brauchen sie nicht benannt werden, da der Name meistens dem Namen des Elements entsprechen würde und das Modell dadurch unübersichtlicher macht.
      </documentation>
     </invariant>
	 
	 <invariant context='Property' name='GlobalElementAttributesShouldBeRefs'>
      <body><![CDATA[
        self.extension_xsdElement.isDefined() and
		self.type.oclAsType(Class).extension_xsdGlobalElement.isDefined() and 
		self.hlpIsPartOfXModel() implies
		  self.extension_xsdElement.isRef
      ]]></body>
      <documentation>Globale Elemente sollten per Verweis eingebunden werden und nicht als anonymer Typ.
Dies kann über die Eigenschaft isRef des Stereotyps «xsdElement» eingestellt werden.</documentation>
     </invariant>
	 
	 <invariant context='Property' name='GroupAttributesShouldBeRefs'>
      <body><![CDATA[
        self.extension_xsdElement.isDefined() and
		self.type.oclAsType(Class).extension_xsdGroup.isDefined() and 
		self.hlpIsPartOfXModel() implies
		  self.extension_xsdElement.isRef
      ]]></body>
      <documentation>Elementgruppen sollten per Verweis eingebunden werden und nicht als anonymer Typ.
Dies kann über die Eigenschaft isRef des Stereotyps «xsdElement» eingestellt werden.</documentation>
     </invariant>
  </rule>
</invariants>
