<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- XÖV-Profil 1.4.0 - Hilfsoperationen für XÖV-Prüfanweisungen und XÖV-Übersetzungsanweisungen - DocBook-Teil -->

<additionalOperations xmlns="http://www.osci.de/xoev/operations">

  <operation context='Classifier' name='hlpDocBookTitle'>
    <result type='String'/>
    <body>
      if self.extension_xsdTitled.title.isDefined and
         self.extension_xsdTitled.title &lt;&gt; '' then
           self.extension_xsdTitled.title
      else
        self.name
      endif
    </body>
    <documentation>
      Falls diese Klasse das 'title'-Attribut gesetzt hat wird dieser
      Wert geliefert, andernfalls der Name der Klasse.
    </documentation>
  </operation>

  <operation context='Classifier' name='hlpDocBookTemplateDirectory'>
    <result type='String'/>
    <body>
      if self.oclIsTypeOf(Enumeration) then
		  'enumeration'
	  else if self.hlpIsSimpleType() then
		  'simpleType'
	  else if self.getGlobalElementType().isDefined() then
		  'typedGlobalElement'
	  else if self.oclIsTypeOf(Class) and self.oclAsType(Class).extension_xsdAnyContents.isDefined() then
		  'anyContents'
	  else if self.isElementGroup() then
		  'elementGroup'
	  else if self.isAttributeGroup() then
	      'attributeGroup'
	  else
		  'generic'
	  endif endif endif endif endif endif
    </body>
    <documentation>
      Liefert für einen Classifer je nach Typ (Class oder Enumeration) und 
	  angewendeten Stereotypen (xsdNamedType, etc.) das Verzeichnis, in dem
	  spezifische Templates liegen, die die allgemeine Generierung beeinflussen.
    </documentation>
  </operation>
  
  <operation context='Classifier' name='getKind'>
    <result type='String'/>
    <body><![CDATA[
	  let c:Class = self.oclAsType(Class) in
	  if self.hlpIsEnumeration() then
	    'Enumeration'
	  else if c.extension_xsdNamedType.isDefined() then
	    'benannter Typ'
	  else if c.extension_xsdGlobalElement.isDefined() then 
		'globales Element' 
	  else if c.isElementGroup() then 
		'Elementgruppe'
	  else if c.isAttributeGroup() then
	    'Attributgruppe'
	  else
	    'anonymer Typ'
	  endif endif endif endif endif
	]]></body>
    <documentation>
      Liefert die textuelle Beschreibung der Objektart.
    </documentation>
  </operation>
  					
  <operation context='Element' name='hlpDocBookId'>
    <result type='String'/>
    <body>
      if self.hlpIsEnumeration() then        
		let n1 : String = self.oclAsType(Enumeration).name in
        let prefix : String = self.oclAsType(Enumeration).hlpPrefixForType(self.hlpOwningPackage()) in
        if prefix.isDefined then
          prefix.concat('-').concat(n1)
        else
          n1
        endif
      else
		  if self.oclIsTypeOf(Class) then
			let c:Class = self.oclAsType(Class) in
			let prefix : String = self.oclAsType(Class).hlpPrefixForType(self.hlpOwningPackage()) in
			   if c.extension_xsdMessage.isDefined then
				 prefix.concat('-').concat(c.hlpDocBookMessageId())
			   else
				 prefix.concat('-').concat(c.hlpDocBookTypeId())
			   endif
		  else
			if self.oclIsTypeOf(Package) then
				let prefix : String = self.oclAsType(Package).hlpPackagePrefix() in
				prefix.concat('-').concat(self.oclAsType(Package).name)
			else
				'FEHLERHAFTE DOCBOOK ID'
			endif
		  endif
      endif
    </body>
  </operation>

  <operation context='Element' name='hlpDocumentation'>
    <result type='String'/>
    <body><![CDATA[
      let d:String =
            if self.oclIsKindOf(Property) and
               self.ownedComment->isEmpty then
                self.oclAsType(Property).type.hlpDocumentation()
            else
              self.ownedComment->iterate(comment; allComments:String = '' |
              if comment.body.substring(1,1) <> '<' then  allComments.concat('<para>').concat(comment.body).concat('</para>') else allComments.concat(comment.body) endif )
            endif
          in if d.isDefined and d<>'' then d  else ''          
             endif    
    ]]></body>
    <documentation>
      Liefert den Inhalt aller Dokumentationselemente eines Elements
      als einen String zurück. Bei Properties ohne eigene Dokumentation
      wird die Dokumentation des Typs herangezogen.
    </documentation>
  </operation>

  <operation context='Enumeration' name='hlpDocBookTitle'>
    <result type='String'/>
    <body>
      if self.extension_xsdTitled.title.isDefined and
         self.extension_xsdTitled.title &lt;&gt; '' then
           self.extension_xsdTitled.title
      else
        self.name
      endif
    </body>
    <documentation>
      Falls diese Enumeration das 'title'-Attribut gesetzt hat wird dieser
      Wert geliefert, andernfalls der Name der Enumeration.
    </documentation>
  </operation>  

  <operation context='Property' name='hlpDocBookTitle'>
    <result type='String'/>
    <body>
      if self.extension_xsdTitled.title.isDefined and
         self.extension_xsdTitled.title &lt;&gt; '' then
           self.extension_xsdTitled.title
      else
        self.name
      endif
    </body>
    <documentation>
      Falls diese Klasseneigenschaft das 'title'-Attribut gesetzt hat wird dieser
      Wert geliefert, andernfalls der Name der Klasseneigenschaft.
    </documentation>
  </operation>  

  <operation context='Type' name='hlpDocBookMessageId'>
    <result type='String'/>
    <body>
      self.internNameBeforeFirstDot().
        concat('.').
        concat(self.hlpDocBookNachrichtenNummer())
     </body>
    <documentation>
      Die ID, die dieser Nachrichten-Typ im DocBook Dokument erhalten
      soll. Hierfuer wird der Teilstring bis zum ersten Punkt mit der
      Nachrichtennummer konkateniert.
    </documentation>
  </operation>

  <operation context='Type' name='hlpDocBookNachrichtenNummer'>
    <result type='String'/>
    <body>
      self.internStringAfterLastDot()
    </body>
    <documentation>
      Liefert die Nummer einer Nachricht.
    </documentation>
  </operation>   

  <operation context='Type' name='hlpDocBookTypeId'>
    <result type='String'/>
    <body>
      self.name.toLower()
    </body>
    <documentation>
      Die ID, den dieser Typ im DocBook Dokument erhalten soll.
    </documentation>
  </operation> 

  <operation context='Type' name='hlpTypeName'>
    <result type='String'/>
    <body>
      self.name
    </body>
    <documentation>
	    Liefert den lokalen Namen eines Elementes.
    </documentation>
  </operation>

  <operation context='Type' name='getReferenceName'>
	<result type='String'/>
	<param name='referringPackage' type='Package'/>
    <body><![CDATA[
	    let prefix:String = 
		  if referringPackage.isDefined() then 
		    self.hlpPrefixForType(referringPackage).concat(':') 
		  else
		    '' 
		  endif
		in
          if self.hlpOwningPackage().name='W3C Data Types' then
		    self.hlpPrefixForType(oclUndefined(Package)).concat(self.name)
		  else if self.oclAsType(Classifier).extension_xsdNamedType.isDefined() or
		          self.oclAsType(Class).extension_xsdGroup.isDefined() or
				  self.oclAsType(Classifier).extension_xsdGlobalElement.isDefined() then
            prefix.concat(self.name)
		  else
		     ''
		  endif endif
    ]]></body>
    <documentation>
      Liefert den Namen, über den ein Typ, Element, eine Gruppe etc. referenziert wird.
	  Falls der Typ nicht referenziert werden kann, wird ein leerer String zurückgegeben.
	  Der Parameter referringPackage darf null sein, dann wird kein Präfix berechnet.
    </documentation>
  </operation>
  
  <operation context='Property' name='hlpPosition' >
    <result type='Integer'/>
    <body>              
        if self.extension_xsdElement.isDefined then
          self.extension_xsdElement.position
        else
          oclUndefined(Integer)
        endif     
    </body>
  </operation>

  <operation context='Element' name='hlpIsEnumeration' >
    <result type='Boolean'/>
    <body>
      self.oclIsTypeOf(Enumeration)
    </body>
  </operation>

  <operation context='Element' name='hlpProjectRootpath'>
    <result type='String'/>
    <body>
      self.hlpXModel().extension_xsdXModel.rootpath
    </body>
    <documentation>
    </documentation>
  </operation>

  <operation context='NamedElement' name='hlpLevelInHierarchy'>
    <result type='String'/>
	<body>		
		Sequence{1 .. self.qualifiedName.size-1}->iterate(i; result : String = '' |
		  if (self.qualifiedName.substring(i,i+1)='::') then
			result.concat('x')
		  else
			result
		  endif)
    </body>    
    <documentation>
      Ebene der Hierarchie im Modell.
    </documentation>
  </operation>

  <operation context='NamedElement' name='hlpIsValidPrefix'>
    <result type='Boolean'/>
	<param name='prefix' type='String'/>
    <body>
      let validChars : Set(String) = 
        self.hlpLowerCaseLetters()
        ->union(self.hlpUpperCaseLetters())
        ->union(self.hlpDigits())->including('.')
      in
	  let validFirstChars : Set(String) =
	    self.hlpLowerCaseLetters()
        ->union(self.hlpUpperCaseLetters())
	  in
	  validFirstChars->includes(prefix.substring(1, 1)) and
	  if prefix.size() = 1 then
        true
      else
        Sequence{2 .. prefix.size}->forAll(i|
        validChars->includes(prefix.substring(i,i)))
	  endif
    </body>
    <documentation>
      Ist der Name dieses Elements ein gültiger Präfix im Sinne von XÖV? 
    </documentation>
  </operation>

  <operation context='Package' name='hlpAllImportDependencies'>
    <result type='Set(Dependency)'/>
    <body>
      self.hlpImportDependencies()-&gt;asSet-&gt;union(
        self.hlpAllIncludedPackages()-&gt;collect(p| 
          p.hlpImportDependencies())-&gt;flatten)-&gt;asSet
    </body>
    <documentation>
      Liefert alle «xsdImport»-Dependencies für dieses Paket, inklusive 
      der «xsdImport»-Dependencies aller über «xsdInclude» transitiv 
      eingebundenen Pakete. 
    </documentation>
  </operation>

  <operation context='Package' name='hlpAllVisibleTypes'>
    <result type='Set(Classifier)'/>
    <body>
      self.hlpOwnedTypes()-&gt;union(
      self.hlpIncludedPackages().hlpAllIncludedVisibleTypes()-&gt;asSet)-&gt;union(
      self.hlpImportDependencies().hlpImportedPackage().hlpOwnedTypes()-&gt;asSet)
    </body>
    <documentation>
      Alle Schema-Typen, die aus diesem xsdSchema-Paket sichtbar sind.
    </documentation>
  </operation>

  <operation context='Package' name='hlpAllIncludedVisibleTypes'>
    <result type='Set(Classifier)'/>
    <body>
      self.hlpOwnedTypes()-&gt;union(
      self.hlpIncludedPackages().hlpAllIncludedVisibleTypes()-&gt;asSet)
    </body>
    <documentation>
      Alle Schema-Typen, die aus diesem xsdSchema-Paket sichtbar sind.
    </documentation>
  </operation>

  <operation context='Package' name='hlpPackageSchemaLocation'>
    <result type='String'/>
    <body><![CDATA[
	  if self.extension_xsdSchema.isDefined then
		  let location:String = self.extension_xsdSchema.schemaLocation in
		  if location.isDefined and location <> '' then
			location
		  else
			let locationBase:String = self.hlpOwningModel().extension_xsdXModel.schemaLocationBase in
			let file:String = self.extension_xsdSchema.schemaFile in
			if locationBase.substring(locationBase.size-1, locationBase.size) = '/' then
				locationBase.concat(file)
			else
				locationBase.concat('/').concat(file)
			endif
		  endif
	  else
	    oclUndefined(String)
	  endif
      ]]>
    </body>
    <documentation>
      Die SchemaLocation des Pakets (definiert über xsdSchema) oder des 
      Projekts (definiert über xsdXModel) 
    </documentation>
  </operation>

  <operation context='Property' name='hlpIsCode'>
    <result type='Boolean'/>
    <body>
      self.type.hlpIsCode()
    </body>
    <documentation>
      Ist der Typ dieser Property von Code abgeleitet?
    </documentation>
  </operation>

  <operation context='Type' name='hlpIsCode'>
    <result type='Boolean'/>
    <body>
      let sc : Classifier = self.hlpTopMostSuperType() in
      let c : Classifier = if sc.isDefined then sc else self.oclAsType(Classifier) endif in
        c.name='Code'
    </body>
    <documentation>
      Ist dieser Typ von Code abgeleitet?
    </documentation>
  </operation>
  
   <operation context='Type' name='hlpIsPartOfXOEVProfile'>
    <result type='Boolean'/>
    <body>
      let profilname='XOEV-Profil' in 
        self.hlpOwningPackage().name=profilname or
        self.hlpOwningPackage().hlpOwningPackage().name=profilname
    </body>
    <documentation>
      Ist dieser Typ Teil des XOEV-Profils?
    </documentation>
  </operation>
  
  <operation context='NamedElement' name='hlpMakeRelativePath'>
	<result type='String'/>
	<param name='params' type='Tuple(source:String,target:String)'/>
    <body><![CDATA[
	   let sSource = self.hlpSplitString(Tuple{aString=params.source,splitChar='/'}) in
	   let sTarget = self.hlpSplitString(Tuple{aString=params.target,splitChar='/'}) in
       
	   let diffPos = Sequence{1..sSource->size() - 1}->iterate(i;res:Tuple(pos:Integer,diff:Boolean)=Tuple{pos=0,diff=false}|
	      if (sSource->subSequence(1, i).toLower() = sTarget->subSequence(1, i).toLower() and not res.diff) then
		    Tuple{pos=i,diff=false}
		  else
		    Tuple{pos=res.pos,diff=true}
		  endif
	   ).pos + 1 in
	   Sequence{diffPos..sSource->size() - 1}->iterate(i;res:String=''| res.concat('../')).concat(
	     Sequence{diffPos..sTarget->size() - 1}->iterate(i;res:String=''| res.concat(sTarget->at(i).concat('/')))).concat(sTarget->last())
	]]>	 
	</body>
  </operation>
  

</additionalOperations>
