Grundlagen OCL
Produktlinie
Standard
|Expert
Betriebsart
CLOUD ABO
|ON-PREMISES
Module
Leistung & CRM
Budget & Teilprojekt
Fremdkosten
Ressourcenplanung
Business Intelligence
Die Navigation und Abfrage im Vertec Objektmodell erfolgt über eine objektorientierte Abfragesprache namens OCL. Eine komplette Sprachdefinition können Sie als PDF-File über folgenden Link downloaden: OCL Manual .
OCL steht für object constraint language und wurde ursprünglich im Rahmen des UML Standards entwickelt, um Gültigkeitsbedingungen für Objektmodelle zu formulieren. Aufgrund seiner objektorientierten Möglichkeiten lässt sich OCL aber auch als Abfragesprache einsetzen.
Der Vertec Kern beinhaltet einen OCL Interpreter, der OCL Ausdrücke als Text verarbeitet und die Ergebnisdaten aus den Vertec Objekten zurückliefert. Der OCL Interpreter benutzt zur Überprüfung und Auswertung von Ausdrücken Informationen aus dem Vertec Modell .
OCL wird in Vertec an verschiedensten Orten verwendet:
Eine OCL-Expression wird immer aufgrund eines bestimmten Objekts ausgewertet und liefert ein Ergebnis eines bestimmten Typs. Mögliche Typen von Ergebnissen sind:
Für die Anzeige von Ergebnissen, z.B. in Listenspalten, wird das Ergebnis automatisch in einen String verwandelt. Bei Zahlen und Strings ist diese Umwandlung einfach. Booleans werden als "Y" (yes) oder "N" (no) dargestellt. Bei Objekten erscheint die Standard-Stringdarstellung, welche von der Objektklasse abhängig ist (bei Projekten z.B. der Code). Die Darstellung von Listen als String zeigt die Grösse der Liste an.
Bei Expressions in Expression-Ordnern muss der Ergebnistyp zwingend eine Liste von Objekten sein.
Auf die laufende Vertec-Session kann in OCL via
TimSession.allInstances->first
zugegriffen werden. Eine Vertec Session hat folgende Attribute:
Resultat | App | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
.login |
Liefert aktuell eingeloggten Bearbeiter zurück. Siehe dazu auch den Artikel Aktueller Benutzer in Expressions . |
||||||||||||||||
.instanceName |
Eine Datenbank-Section kann im Vertec.ini-File einen Wert namens InstanceName enthalten. Auf der Oberfläche der Vertec Desktop App wird dies dann entsprechend angezeigt, siehe dazu den Abschnitt Instanz-Name zur Kennzeichnung von Test-Installationen. Für den Zugriff via OCL gibt es dafür das Attribut namens InstanceName: TimSession.allInstances->first.instanceName |
||||||||||||||||
.hasGui |
Der Operator hasGui bietet die Möglichkeit, aus OCL Expressions oder Scripts zu bestimmen, ob der Client fähig ist, benutzerspezifische Dialoge anzuzeigen, also ob es sich beim Client um eine der full-featured Apps handelt.
Rückgabewert ist entweder
Es ist wichtig, dass Scripts - insbesondere Eventscripts - keine Dialoge anzeigen, wenn dies auf dem verwendeten Client nicht möglich ist, da dies sonst Vertec blockieren kann. |
||||||||||||||||
.appType |
Ab Version 6.0. Der Operator AppType bietet die Möglichkeit, aus OCL Expressions oder Scripts zu bestimmen, in welcher App man sich befindet.
Liefert einen String zurück mit folgenden möglichen Werten:
|
||||||||||||||||
.checkfeature(featurecode: string) | Prüft, ob ein bestimmtes Feature lizenziert ist.
Die Featurecodes sind gemäss Vertec Featurematrix (z.B. Rückgabewert ist False oder True. |
Ein Member ist eine Eigenschaft eines Objekts. Das ist entweder eine Verknüpfung (association) zu einem oder mehreren anderen Objekten oder ein Datenfeld (attribute) des Objekts.
Ausgehend von einem Objekt kann ein Membername für den Zugriff auf ein Member angegeben werden. Falls eine solche Member-Referenz nicht am Anfang einer Expression steht, muss sie durch einen Punkt abgetrennt werden. Membernamen müssen immer klein geschrieben werden. Beispiele: code
in einer Listenexpression einer Projektliste zeigt den Projektcode in der entsprechenden Spalte an; kunde.name
, ebenfalls in einer Projektliste, zeigt jeweils den Namen des Kunden an. Hier handelt es sich um eine Verknüpfungsreferenz (kunde) mit anschliessender Attribut Referenz (Attribute name
der Klasse Adresseintrag
).
Durch Aneinanderreihen von Member-Referenzen in einer OCL-Expression können beliebige Verknüpfungen im Vertec Objektmodell abgefragt werden.
Bei m:n Verknüpfungen gibt es jeweils eine Link-Tabelle. Der Zugriff darauf erfolgt über den kleingeschriebenen Klassennamen der Link-Tabelle. Hier als Beispiel ein Ausschnitt aus dem UML Modell Bearbeiter:
Um herauszufinden, wie die entsprechende Link-Tabelle heisst, sehen Sie bitte im entsprechenden UML Modell nach oder wenden sich an Ihren Vertec Betreuer.
Eine etwas spezielle Art von Members in Vertec sind berechnete Listen Attribute. Im OCL Editor werden diese als Typ ObjectList
dargestellt. Eine sogenannte Derived ObjectList berechnet ihren Wert zu Laufzeit. Sie enthalten im Gegensatz zu Derived Attributes keine einzelnen Werte, sondern geben eine Liste zurück.
Ein Beispiel ist die Liste leistungen auf einem Projekt. Im Modell gibt es auf dem Projekt eigentlich nur zwei Listen: offeneLeistungen und verrechneteLeistungen. Die Liste der leistungen, also alle offenen und verrechneten zusammen, wird zu Laufzeiten berechnet.
Die Listen liefern Typinformationen in OCL und können wie folgt augerufen werden:
<Proj>.leistungen.wertext->sum
Eine Klassenliste ist die Liste aller Objekte eines bestimmten Typs (Klasse), z.B. alle Projekte oder alle Bearbeiter einer Vertec Installation.
OCL unterscheidet zwischen Gross- und Kleinschreibung. Alles Grossgeschriebene versucht der OCL Interpreter als Klassennamen (Metatyp) zu verstehen. Auf einer Klasse kennt OCL den Operator allInstances
, welcher eine Liste aller Instanzen der Klasse ergibt. Projekt->allInstances
liefert z.B. eine Liste aller Projekte.
Da Klassenlisten ziemlich häufig Verwendung finden, gibt es in Vertec eine Abkürzung dafür. Wird ein Klassenname klein geschrieben, dann wird dies direkt als Klassenliste interpretiert. projekt
bedeutet daher ebenfalls die Liste aller Projekte.
Klassenlisten werden vor allem als Ausgangspunkt für Expressions von Expression Ordnern verwendet. Die meisten vordefinierten Expressionordner in Vertec (z.B. Stammdaten Bearbeiter) enthalten eine simple Klassenliste als OCL-Expression.
Achtung: Bei Klassenlisten ist etwas Vorsicht geboten, denn es gibt Vertec Klassen, welche sehr viele Objekte umfassen können. Bei Angabe einer Klassenliste in OCL werden alle Objekte der betreffenden Klasse in den Arbeitsspeicher geladen. Insbesondere bei den Klassen OffeneLeistung oder VerrechneteLeistung kann dies zu hohem Speicherbedarf und schlechter Performance führen.
Die nachfolgenden Operatoren führen gewisse Transformationen auf OCL Werten durch. Ein Operator wird innerhalb einer Expression durch einen vorangestellten Pfeil (->) abgetrennt. Falls keine Verwechslungsgefahr mit einem Member besteht, wird auch ein Punkt als Trennzeichen akzeptiert.
Basierend auf einer Liste existieren in OCL verschiedene Operatoren, welche die Liste modifizieren. Weitere, hier nicht erwähnte Operatoren, erscheinen jeweils in "verfügbare Felder" im OCL Expression Editor .
->size | Der size Operator liefert die Grösse (Anzahl Einträge) einer Liste, zum Beispiel als Listenspalte in einer Liste von Adresseinträgen gibt projekte->size die Anzahl Projekte eines jeden Kunden an. |
->select | Der select Operator erlaubt es, den Inhalt einer Liste aufgrund einer Bedingung zu filtern. adresseintrag->select(projekte->size > 0) als Expression eines Expressionordners liefert alle Adressen, die Projekte zugeordnet haben (d.h. Kunden sind). Das Argument des select Operators muss einen logischen (Wahr/Falsch) Wert ergeben. |
->reject | Der Operator reject ist sozusagen das Gegenteil des select Operators. Es werden damit alle Einträge aus der Liste ausgeschlossen, die der Expression entsprechen. So gibt beispielsweise die Expression projektbearbeiter->reject(name='Administrator') eine Liste zurück, die alle Projektbearbeiter ausser dem Administrator enthält. |
->first |
Der first Operator liefert aus einer Liste den ersten Eintrag. Am häufigsten kommt der first Operator zur Anwendung, wenn aufgrund einer Selektion ein Objekt als Ergebnis verwendet werden soll. Da der ->select Operator eine Liste als Ergebnis liefert, muss darauf noch ->first angewendet werden, damit das Ergebnis ein einzelnes Objekt ist. Beispiel: phasen->select(code= 'OFFERTE')->first.offeneleistungen->sizezeigt in einer Liste von Projekten die Anzahl offener Leistungen der Phase "OFFERTE" an. |
->orderby | Mit dem orderby Operator können Listen sortiert werden. adresseintrag->orderby(projekte->size) ordnet die Liste der Adresseinträge nach der Anzahl der Projekte, bei denen sie Kunden sind. |
->orderdescending |
Mit dem orderdescending Operator können Listen absteigend sortiert werden (sonst gleich wie ->orderby): adresseintrag->orderdescending(projekte->size)Anmerkung: Als Expression in einem Expression-Ordner verwendet haben diese Operatoren keine Bedeutung, da die Liste die Sortierung selber vornimmt. |
->orderMulti |
Der Operator orderMulti erlaubt das Sortieren einer Liste nach verschiedenen Sortierkriterien. Er kann in einer OCL-Expression auf einer Liste angewandt werden und erwartet einen String als Argument. Dieser String enthält die verschiedenen Sortierkriterien als einzelne OCL-Expressions, getrennt durch Semikolons: projekt->ordermulti('projektleiter.name;code.asstring')als Expression eines Expressionordners liefert sie eine Liste aller Projekte, sortiert in erster Linie nach dem Namen des Projektleiters, in zweiter Linie nach dem Projektcode. Diese Sortierung wird in der Listenanzeige allerdings nur sichtbar, wenn Sie die Sortierung auf Listenspalten entfernen. Doppelklicken Sie auf eine sortierte Listenspalte, bis diese keinen Sortierpfeil mehr anzeigt. |
ordermulti mit Zusatzfeldern |
Will man nach Zusatzfeldern sortieren, hat man das Problem, dass man in der Expression keine Hochkommas verwenden kann. Bei den Zusatzfeldern erfordert das einen Umweg über die interne ID des Zusatzfelds (Einstellungen > Zusatzfelder > rechte Maustaste > Eigenschaften > interne ID): projekt->ordermulti('projektleiter.name;zusatzfelder ->select(metaZusatzfeld.boldID=<interne ID>)->first.wert') Je nach Feld-Typ können Sie den Wert wie folgt abfragen: .wert .wertBlob .wertBoolean .wertInteger .wertCurrency .wertDatum .wertObject |
->asSet | Ausgehend von einer Liste kann auch eine Member-Referenz angegeben werden. Die Member-Referenz wird dann auf jedem Objekt der Liste angewendet. So ist das Ergebnis eine Liste mit Elementen des Member-Typs. Beispiel projekt.kunde liefert in einem Expressionordner eine Liste aller Kunden. Der Nachteil dieser Liste ist, dass die Kunden zum Teil doppelt erscheinen, da die Expression projektweise alle Kunden zusammenträgt. Dies lässt sich durch die Anwendung des asSet Operators beheben, welcher eine Liste in eine Menge (im Sinne der Mengenlehre) umwandelt: projekt.kunde->asSet liefert eine eindeutige (distinct) Liste aller Kunden. |
->asSequence | Macht aus einem Objekt (oder einer Liste) eine Liste, welche das einzelne Objekt (oder im Falle der Ausführung auf einer Liste die Elemente der Liste) enthält. |
->asBag | Liefert die Liste mit allen Einträgen, also auch die Doppelten (im Gegensatz zu asSet, siehe oben). Da der Aufruf einer Liste im Vertec sowieso eine Collection mit allen Einträgen zurückliefert, ist die explizite Angabe von asBag unnötig. |
->union |
Der union Operator erlaubt die Zusammenfassung zweier Listen in einer. Er kann in einer OCL-Expression auf einer Liste angewandt werden und erwartet eine weitere Liste (Collection) als Argument: offeneLeistungen->union(verrechneteLeistungen)als Expression auf einem Projekt liefert alle offenen und verrechneten Leistungen des Projekts. Mit dieser Liste kann normal weitergearbeitet werden. Als Typ wird immer die gemeinsame Basisklasse verwendet, dessen Attribute zur Verfügung stehen. Das obige Beispiel liefert also eine Liste mit Einträgen vom Typ Leistung. Bei einer Expression projekt->union(adresseintrag) wäre die gemeinsame Basisklasse z.B. UserEintrag. |
->collect | Der collect Operator erlaubt es, mittels Variable einen komplexen Teilausdruck nur einmal zu formulieren, aber mehrfach zu verwenden.
Zum Beispiel will man die Summe der Honorarnoten (netto) des jeweils letzten Jahres anzeigen: rechnungen->select(datum.year=date.year-1)->collect(umsatz+vorschussbetrag-vorschusseffektiv)->sumohne den Collect-Operator müsste man die ganze '->select'-Expression für jeden Wert (umsatz, vorschussbetrag etc) wiederholen. Man kann auch noch einen Schritt weitergehn, indem man den Wert, der aus dem collect resultiert, einer Variable zuweist und damit weiterarbeitet. Als Beispiel nehmen wir eine Liste von Projekten. Jedes Projekt befindet sich (in diesem Beispiel) entweder in einem Ordner "Kundenprojekte" oder in einem Ordner "Interne Projekte" oder in einem Ordner "Auftragsprojekte". Diese Ordner sind jeweils Unterordner des Ordners "Projektkategorie". In der Liste möchten wir nun entweder 1, 2, oder 3 anzeigen, je nachdem, in welchem Ordner sich das Projekt in der Liste befindet: ordner->select(parentordner.bezeichnung='Projektkategorie') ->first.bezeichnung.substring(1,1)->asSet->collect(x|if x ='K'then '1'else if x='I'then'2'else if x='A'then'3' else'Keine Angabe'endif endif endif)->first Die Expression geht von einem Projekt aus (jedes Projekt in der Liste). ordner bedeutet also die Ordner, in denen sich das Projekt befindet. Wir suchen zuerst den Unterordner des Ordners Projektkategorie. Von diesem nehmen wir den ersten Buchstaben (bezeichnung.substring(1,1)). Das ist nun ein einzelner Buchstabe, entweder "K" oder "I" oder "A". Da der Collect-Operator nur auf einer Liste ausgeführt werden kann, fügen wir ein ->asSet an. Nun kommt der ->collect Operator dran: Anstatt für jede if Abfrage den ganzen ordner->select(...) Abschnitt zu wiederholen, kann einfach die Variable x mehrfach eingesetzt werden. Das x in der Klammer bezieht sich auf den aktuellen Wert. Das ist ja im Moment unser einzelner Buchstabe. Nun können wir über das x diesen Buchstaben abfragen und je nachdem den gewünschten Wert einsetzen. Das Ganze ist nun noch immer eine Liste. Wir möchten aber den einzelnen Wert im Feld anzeigen. Deshalb fügen wir wieder ein ->first an. |
->append(obj) | Gibt die Liste zurück, die das obj am Schluss noch angehängt hat |
->at(i) | Gibt das Objekt an der Stelle i zurück. Der Index i beginnt mit 1. |
->count(obj) | Gibt an, wieviele Male obj in der Liste enthalten ist. |
->difference(list2) | Gibt die Liste zurück, die der ursprünglichen Liste ohne die Elemente von list2 entspricht. |
->excluding(obj) | Gibt die Liste zurück, aus der das obj entfernt wurde. |
->includes(obj) | Gibt an, ob obj in der Liste enthalten ist |
->includesAll(list2) | Gibt an, ob alle Objekte in list2 in der Liste enthalten sind. |
->including(obj) | Dasselbe wie ->append |
->intersection(list2) | Gibt die Schnittmenge der beiden Listen zurück, das heisst eine Liste aller Objekte, die in beiden Listen enthalten sind. |
->isEmpty | True, wenn keine Liste oder Länge der liste=0, sonst False. |
->prepend(obj) | Gibt die Liste zurück, bei der das obj am Anfang eingesetzt ist. |
->subsequence(start, stop) | Gibt eine Liste von Index start bis und mit Index stop zurück. Die Indizes sind 1 basiert und werden automatisch auf gültige Werte korrigiert (d.h. stop kann auch grösser als die Listenlänge sein, ohne dass es Fehler gibt). |
->symmetricDifference(list2) | Gibt eine Liste mit allen Elementen der Liste, welche nicht in liste2 sind, sowie alle Elemente von liste2, welche nicht in der Liste sind, zurück. |
->sum | Summiert die Zahlenwerte einer Liste und gibt die Summe zurück. |
Häufig stellt sich die Aufgabe, eine Zeichenfolge in einen Datumswert umzuwandeln, eine Zahl in eine Zeichenfolge umzuwandeln, etc. Nachfolgend eine Liste der verfügbaren Konvertierungsoperatoren:
->asString (auch .asString) | Wandelt eine Zahl oder Datumswert in eine Zeichenfolge (String) um. |
->dateToFloat | Wandelt einen Datumswert in eine Zahl um (die Zahl sagt Ihnen wenig: (Anzahl Tage seit 1.1.1900). Diese Operation wird vor allem für das Rechnen mit Datumswerten verwendet (z.B. 30 Tage zum heutigen Datum dazuzählen, siehe Beispiel weiter unten). |
->floatToDate |
Wandelt eine Zahl in ein Datum um. Die folgenden Expression zählt zum datum des Eintrags (z.B. einer Leistung) 31 Tage dazu: (datum->dateToFloat+31)->floatToDate |
->strToDate |
Wandelt einen String in ein Datum um. Dieser Operator ist dann nützlich, wenn man mit einem Datum arbeiten muss, das vorher nicht bekannt oder nur als String vorhanden ist (z.B. wenn vom Benutzer ein Datum abgefragt wird). Die Verwendung von strToDate ist heikel, denn es nimmt Bezug auf die aktuellen Ländereinstellungen. Ein strToDate mit einem Stringliteral von '01.09.2020' geht schief, wenn ein Client z.B. ein US Datumsformat verwendet. In der Web App bezieht sich das dann nicht mal auf das lokale Windows, sondern auf die Einstellungen im Web Browser (z.B. "English"). In fixen OCL Expressions sollte deshalb stattdessen der Operator |
->stringToFloat | Wandelt eine Zeichenfolge in ein Zahl um. Ist die Zeichenfolge keine Zahl, wird 0 ausgegeben. |
->stringToList |
Stellt einen String als Liste dar. Einzelne Wörter werden getrennt bei der Wortgrenze oder bei einem Delimeter. Wörter innerhalb doppelter Anführungszeichen gelten als ein Wort.
Gibt den Namen des eingeloggten Bearbeiters als Liste zurück. So kann beispielsweise über
nur der Nachname angezeigt werden. |
->isEmpty | Der Operator ->isEmpty gibt zurück, ob ein Linkmember leer ist. So gibt die Expression projektleiter->isEmpty , ausgeführt auf einem Projekt, mit einem boolschen Wert (wahr, falsch) zurück, ob ein Projektleiter zugeordnet ist (falsch) oder nicht (wahr). |
.isNull/.notNull | Oft ist es nützlich, einen Nullwert zu erkennen. Ab Version 5.5 muss das nicht mehr über einen String-Vergleich geschehen, sondern kann über die OCL Operatoren isNull und notNull abgefragt werden.
Beispiel: statt
kann man nun
ausführen. Anmerkung: Diese Operatoren sind nicht zu verwechseln mit dem isEmpty-Operatoren, welcher eine Verknüpfung abfragt. Um beispielsweise zu wissen, ob ein Projekt einen Kunden zugeordnet hat, kann nicht mit isNull abgefragt werden, sondern mit kunde->isEmpty. |
.asnull/.null | Ab Vertec 6.2.0.4. Der OCL Null Operator ermöglich es, für beliebige Attribute-Typen Null-Werte zu erhalten.
Dies ist nützlich, um bei Zahlenwerten statt 0 nichts darzustellen, ohne dafür die ganze Expression in einen String umwandeln zu müssen. So können Expressions der Art: if usespesen then spesenint.asstring else '' endifdurch folgende Expression ersetzt werden: if usespesen then spesenint else spesenint.asnull endif Das OCL eine statisch und streng typisierte Sprache ist, müssen auch ein Null-Wert einen Typ haben, damit die Gültigkeit der Expression festgestellt werden kann. Deshalb wurde ein
|
->listToString |
Durch diesen Operator können Listen in Strings dargestellt werden. So liefert die Expression:
ausgeführt auf einem Projekt (z.B. via Listeneinstellungen) die Liste der Phasen-Codes, mit "," getrennt. |
.toLower/.toUpper | Sehr häufig ist das Resultat einer Expression ein string (Zeichenfolge). Mit dem Operator .toLower wird die Zeichenfolge in Kleinbuchstaben verwandelt, mit dem Operator .toUpper in Grossbuchstaben. |
.asHMString | Interpretiert eine Zahl als Anzahl Minuten und formatiert sie als Stunden:Minuten. Es werden auch negative Zeitwerte unterstützt. |
.asTimeString | Interpretiert eine Zahl als Anzahl Minuten und formatiert sie als Tageszeit. Negative Werte werden nicht dargstellt. |
.asMinuteString | Interpretiert eine Zahl als Anzahl Minuten und formatiert sie gemäss Format in den Systemeinstellungen. Es werden auch negative Zeitwerte unterstützt. |
.asStringBy Language(<Sprache>) |
Fragt die entsprechende Sprachversion eines Members ab. Dies gilt für alle MLStrings, das sind Werte, die für die verschiedenen Sprachen jeweils ein eigenes Feld haben (Beispiele sind Tätigkeiten, Spesen- und Auslagetypen). Zum Beispiel bei Auslagetypen auf einer Rechnung: Wenn man die französische Bezeichnung des Typs haben möchte, kann dies mit folgender Expression geschehen: text.asStringByLanguage('FR')
Mögliche Sprachen / Parameter sind 'DE', 'DD' (ab 6.5.0.9), 'FR', 'IT', 'EN' oder 'NV'. |
.pad(Anzahl,Platzhalter) |
Der .pad-Operator füllt einen Integer-Wert bis zur Anzahl angegebenen Zeichen mit dem als Platzhalter angegebenen Zeichen auf. Das Ergebnis ist ein String. Dies ist zum Beispiel dann nützlich, wenn man für eine alphanumerische Sortierung führende Nullen braucht.
|
abs |
Dieser Operator gibt den absoluten Wert einer Zahl zurück. (-2.8).abs = 2.8 |
floor |
Abrundungsfunktion. Gibt von einer reellen Zahl die nächstliegende kleinere Ganzzahl zurück. (-2.8).floor = -3 |
round |
Rundet einen Zahlenwert nach der "round-to-even" Regel auf die nächste Ganzzahl und gibt diese als Resultat zurück. (-2.8).round = -3 Auf fünf Rappen runden:
Runden auf zwei Nachkommastellen:
Aufrunden ab dem 5er:
Siehe zu diesem Thema auch Runden in Scripts. |
length |
Dieser Operator gibt die Anzahl Zeichen einer Zeichenfolge zurück. Zum Beispiel gibt die Expression adresseintrag->select(standardplz.length=4) alle Adressen mit einer vierstelligen PLZ zurück. |
substring(Anfang, Ende) | Dieser Operator schneidet aus einer Zeichenfolge die Zeichen zwischen "Anfang" (beginnend bei 1) und "Ende" aus. So liefert die Expression code->substring(1,1), ausgeführt auf einem Projekt, den ersten Buchstaben des Projektcodes. Ein anderes Beispiel: Sie möchten das Erfassungsjahr des aktuellen Eintrags anzeigen. Vertec speichert das Erfassungsdatum im Member "creationdatetime" ab. Die folgende Expression nimmt das "creationdatetime", wandelt es in einen string um und setzt die hintersten 4 Zeichen: creationdatetime->asstring->substring(7,10). Diese Methode kann natürlich auch für das aktuelle Systemdatum benutzt werden (Expression now, kann z.B. im Zusammenhang mit Speicherpfaden bei Word-Reports wertvoll sein, siehe entsprechende Artikel) |
replaceString |
Die Syntax lautet wie folgt: <string>->replaceString(substring, replacement)Sie geben darin den Teil an, den Sie ersetzen möchten (substring) sowie den Teil, durch den er ersetzt werden soll (replacement). Rückgabewert ist wieder ein String. Sie möchten beispielsweise in einem Text alle Meyer durch Maier ersetzen: <text>->replaceString('Meyer', 'Maier')Der Replace-String ist Case-Sensitiv, das heisst, er beachtet die Gross/Klein-Schreibung. |
replaceRegex |
Die Syntax lautet wie folgt: <string>->replaceRegex(template, replacement)Hier kann ein regulärer Ausdruck, eine sogenannte Regular Expression, angegeben werden, sowohl für den Teil, den Sie ersetzen möchten (template) wie auch für den Teil, der ersetzt werden soll (replacement). Rückgabewert ist wieder ein String. Ein kleines Beispiel, was damit möglich ist: In einem Text sind Bezeichnung der Art <Abschnitt>:<Kapitel> vorhanden, z.B. 2:15 oder 3:10. Diese Bezeichnungen sollen getauscht werden, sodass sie als 15:2 bzw. 10:3 dargestellt werden. Dies kann mit folgender Expression geschehen: <text>->replaceRegex('([0-9]*):([0-9]*)', '$2:$1') |
translate |
Ab Vertec 6.4.0.20. Übersetzt einen String-Wert in die aktuelle Vertec Oberflächensprache . Beispiel: if projekte->size > 0 then 'Client'.translate else 'Address'.translate endif auf einer Adressliste zeigt in der Spalte folgendes Resultat bei Deutsch: |
Auf UserEintrag (alle Objekte, welche in Ordnern abgelegt werden können, z.B. Leistungen, Projekte, Adressen, Bearbeiter, Aktivitäten etc.) gibt es folgende Operatoren:
Operator | Beschreibung |
---|---|
->hasBIDataRight: boolean ab Vertec 6.4.0.14: ->hasBIDataRight('Kennzahl'): boolean |
Mit diesem Operator kann überprüft werden, ob der aktuell eingeloggte Benutzer auf dem angegebenen Objekt BI Berechtigung hat. Mit Einführung der Berechtigungen auf den Kennzahlen mit Version 6.4.0.14 wurde dieser OCL Operator geändert. Ab dann muss als Parameter ein String mit dem internen Namen der Kennzahl angegeben werden. Beispiel: projekt->hasBiDataRight('MinutesExt') prüft, ob der aktuell eingeloggte Benutzer auf dem angegebenen Projekt das Recht auf die MinutesExt Kennzahl hat. Dies ist nicht rückwärtskompatibel. Die entsprechenden Aufrufe müssen angepasst werden. |
->hastag(tagname): boolean |
Ab Version 6.1.0.10. Fragt ab, ob das Objekt einen Tag dieses Namens gesetzt hat. Weitere Informationen finden Sie im Artikel über Tags auf User-Einträgen. |
->keystring(key): string ->keybool(key): boolean ->keydate(key): datetime oder empty ->keyint(key): integer oder 0 ->keycurr(key): currency oder 0.00 |
Ab Version 6.1.0.10. Operatoren zur typisierten Abfrage von Key-Values auf dem Objekt. Weitere Informationen finden Sie im Artikel über Key-Values auf User-Einträgen. |
Speziell für die Klasse Projektbearbeiter
gibt es folgende Operatoren:
Operator | Beschreibung | ab Version |
---|---|---|
->getSollzeit(von, bis) |
Sollzeit in der Periode (minuten) |
|
->getArbeitszeit(von, bis) |
Arbeitszeit in der Periode (minuten). Berechnet aus der Summe aller vorhandenen Leistungen plus der Ferien, die als Abwesenheiten erfasst wurden. |
|
->getUeberzeitvortrag(datum) |
liefert den Ueberzeitsaldo per Datum-1, ausser auf Datum ist ein Vortrag erfasst, dann wird dieser Vortrag geliefert. |
|
->getUeberzeitvortragDatum(datum) |
liefert Datum des letzten Ueberzeitvortrags vor Datum |
5.4 |
->getUeberzeitsaldo(datum) |
liefert Ueberzeitsaldo per Datum |
5.4 |
->getFerienVorgabe(von,bis) |
Ferienguthaben innerhalb Periode |
|
->getFerienBezug(von,bis) |
Ferienbezug, sowohl Abwesenheiten als auch Ferienleistungen |
5.4 |
->getFerienVortrag(datum) |
liefert den Feriensaldo per Datum-1, ausser auf Datum ist ein Vortrag erfasst, dann wird dieser Vortrag geliefert. |
|
->getFerienVortragdatum(datum): |
liefert Datum des letzten Ferienvortrags vor Datum |
5.4 |
->getFerienStart(datum) |
liefert Startdatum für Berechnung des Ferienguthabens. Ist der nächste Ferien-Stichtag nach dem letzen Vortrag |
5.4 |
->getFerienEnd(datum) |
liefert Enddatum für Berechnung des Ferienguthabens. Ist das nächst Ferienperiode-Ende |
5.4 |
->getFerienSaldo(datum) |
liefert FerienSaldo per Datum |
5.4 |
->getFeriensaldoAbgegrenzt(datum) |
Berechnet den abgegrenzten Feriensaldo per Datum unter Berücksichtigung des Ferienguthabens bis zum Datum. Beispiel: Gegeben ist ein Ferienguthaben von 200 Stunden pro Jahr, vorgegeben von der Gruppe. Der Ferienstichtag ist der 01.01. Auf diesen Stichtag wurde dem Mitarbeiter ein Ferienvortrag von 20 Stunden gutgeschrieben. Das bedeutet: Der Mitarbeiter hat ein gesamtes Ferienguthaben für das Jahr 2013 von 220 Stunden. Nun möchte ich den Feriensaldo dieses Mitarbeiters berechnen per 31. März 2013. Es gibt folgende Varianten:
|
5.8 |
->getLohn(von,bis) |
Lohn innerhalb der angegebenen Periode |
5.4 |
->getGemeinkosten(von,bis) |
Gemeinkosten innerhalb der angegebenen Periode |
5.4 |
->getSollzeitVorgabe(von, bis) |
Berechnet die Sollzeit von, bis nur aufgrund der Vorgaben, ohne Berücksichtigung von Feiertagen. Eintritt / Austritt wird berücksichtigt. | 5.4.0.21 |
->getSollzeitGroupVorgabe(von, bis) |
Berechnet die Sollzeit von, bis aufgrund der Gruppen-Vorgaben des Bearbeiters. Das ergibt die Sollzeit, wenn der Mitarbeiter 100% arbeiten würde. | 5.4.0.21 |
->getSollzeitOnlyGroupAbw(von, bis) |
Berechnet die Sollzeit eines Mitarbeiters unter Berücksichtigung nur der gruppenbasierten Abwesenheiten (Feiertage etc.). Abwesenheiten werden im Unterschied zum GetSollzeit Operator nur von den Gruppen berücksichtigt. Auf dem Mitarbeiter erfasste Abwesenheiten werden nicht berücksichtigt. Der Beschäftigungsgrad des Mitarbeiters wird berücksichtigt. |
5.8 |
->getBeschaeftigungsgrad(datum) |
Liefert den Beschäftigungsgrad des Mitarbeiters zu einem bestimmten Datum. Die Berechnung des Beschäftigungsgrads erfolgt unabhängig davon, ob der Mitarbeiter am Stichdatum Sollzeit hat oder nicht. Ausschlaggebend ist das Verhältnis der Wochensollzeiten von Bearbeiter und Gruppe. |
5.4.0.21 |
->getAbwesenheitFrei(Abwesenheitstyp, von, bis) |
Operator zum Bestimmen der Frei-Zeit eines bestimmten Abwesenheitstyps. Beispiel: Bearbeiter->getAbwesenheitFrei('Feiertag', encodedate(2013, 1, 1), encodedate(2013, 1, 31)) Die Berechnung geschieht wie folgt:
Wird ein nicht existierender oder ein falscher (nicht Frei) Abwesenheitstyp angegeben, ist das Resultat 0. Versionen vor 5.8 Zur Abfrage des Abwesenheitstyps wird in Versionen vor 5.8 die (sprachabhängige) Bezeichnung verwendet. Werden am gleichen Tag mehrere Abwesenheiten erfasst, kann Vertec den Einfluss der einzelnen Abwesenheit nicht eindeutig bestimmen, da die Abwesenheitstypen keine Sortierung bezüglich Wichtigkeit kennen. Wenn man also am Ostermontag ("Feiertag") auch noch krank ist ("Krankheit"), dann stimmt zwar die Sollzeit, aber dieser Operator gibt sowohl bei "Feiertag" als auch bei "Krankheit" jeweils 0 an, da der andere Abwesenheitstyp auch den ganzen Tag belegt. Versionen ab 5.8 Zur Abfrage des Abwesenheitstyps wird in Versionen ab 5.8 der (sprachunabhängige) Code verwendet. Ab dieser Version haben Abwesenheitstypen ein Attribut Priorität. Dieses wird im Falle von überlappenden Abwesenheiten beachtet. Es werden beliebig viele überlappende Einträge berücksichtigt und die "Sichtbarkeit" der in Frage kommenden Abwesenheiten bestimmt sich durch den Prioritätswert auf ihrem Typ. Falls die Prioritäten gleich sind, werden die folgenden Prioritätsregeln angewendet:
|
5.7 |
->getFerienbezugAbw(von, bis) |
Operator für die Berechnung des Ferienbezugs unter Berücksichtigung von nur als Abwesenheiten erfassten Ferien. Beispiel: Bearbeiter->getFerienbezugAbw(encodedate(2012, 1, 1), encodedate(2012, 1, 31)) Als Resultat werden die Abwesenheiten der Art Ferien in der entsprechenden Periode zurückgeliefert, in Minuten (Integer). Für die normale Ferienberechnung kann der Operator |
5.7 |
->getSollzeitGroup(von, bis) |
Dieser Operator liefert die Sollzeit für die Gruppe (100%), unter Berücksichtigung von Abwesenheiten auf der Gruppe. Beispiel: Bearbeiter->getSollzeitGroup(encodedate(2012, 1, 1), encodedate(2012, 1, 31)) Als Resultat wird die entsprechende Sollzeit zurückgeliefert, in Minuten (Integer). |
5.7 |
->currentAbwesenheiten(datum) |
Dieser Operator liefert eine Liste von Abwesenheiten, die für den angegebenen Tag zur Anwendung kommen. Beispiel: Bearbeiter->currentAbwesenheiten(encodedate(2012,6,11)) liefert eine Liste der für diesen Bearbeiter für den 11.06.2012 erfassten Abwesenheiten. |
5.7 |
->getTrackingUsers |
Der Operator getTrackingUsers liefert für einen Bearbeiter eine Liste aller Bearbeiter, für die er Leistungen, Spesen und Auslagen erfassen darf. Das wird im Bearbeiter-Auswahlfeld auf Leistungen, Spesen und Auslagen verwendet und kann auch über OCL abgefragt werden. Beispiel: TimSession.allinstances->first.login->getTrackingUsers Liefert für den aktuell eingeloggten Bearbeiter die Liste aller Bearbeiter, für die er erfassen darf. |
6.0 |
getPresenceEntries(datum) |
Gibt eine Liste der Präsenzzeit-Einträge eines Tages für den Bearbeiter aus. |
6.2 |
OCL Operatoren sind eine Art, mit Ressourcenplandaten zu arbeiten. Es gibt jedoch eine Vielzahl von weiteren Möglichkeiten. Diese sind im Artikel OCL, Python, Custom Renderer und List Controller rund um die Ressourcenplanung beschrieben.
.getResPlanMinuten(Datum von, Datum bis) |
Steht auf Projekt- und Planungsbearbeitern zur Verfügung. Gibt die verplante Zeit für den Bearbeiter für die angegebene Periode in Minuten zurück. |
.getResRsrcMinuten(Datum von, Datum bis) |
Steht auf Projekt- und Planungsbearbeitern zur Verfügung. Gibt die Ressourcenzeit für den Bearbeiter für die angegebene Periode in Minuten zurück. Das ist nicht die noch verfügbare Zeit, sondern die gesamte Ressourcenplan-relevante Sollzeit. Der Unterschied zur Sollzeit ist, dass nur Abwesenheiten vom Typ "Frei" die Sollzeit beeinflussen, von der Ressourcenzeit hingegen werden alle Arten von Abwesenheiten (Frei, Ferien, Kompensation) abgezogen (siehe dazu auch die Tabelle über die Arbeitszeit-Ausnahmen im Artikel Abwesenheiten). |
Sollen die effektiven Kompensationsabwesenheiten pro Bearbeiter für einen bestimmten Zeitraum ermittelt werden, kann dies wie folgt geschehen:
getSollzeit(von, bis) - getResRsrcMinuten(von, bis) - getferienbezug(von, bis)
So werden die arbeitsfreien Tage (Samstag, Sonntag, Feiertage etc.) automatisch mitberücksichtigt.
Beispiel für die Ermittlung der Kompensationszeit für den Monat Juli:
self.getSollzeit(encodeDate(2013,07,01),encodeDate(2013,07,31)) - self.getResRsrcMinuten(encodeDate(2013,07,01),encodeDate(2013,07,31)) - self.getFerienbezug(encodeDate(2013,07,01),encodeDate(2013,07,31))
Abwesenheiten vom Typ Frei beeinflussen die Sollzeit (Minus).
Abwesenheiten vom Typ Frei, Ferien und Kompensation sowie die als Leistungen erfassten Ferien beeinflussen die Ressourcenzeit (Minus).
Die Abwesenheiten vom Typ Frei heben sich somit auf. Es bleiben Ferien und Kompensation übrig. Darum müssen noch die Ferien abgezogen werden. Der Zeitunterschied ist die Kompensationszeit.
Für die Abfrage von Systemeinstellungen gibt es ab Vertec 6.7.0.16 die OCL Operatoren:
Diese liefern den in der Systemeinstellung hinterlegten Wert bzw. das Objekt zurück.
Detaillierte Informationen dazu finden Sie im Artikel Properties via OCL .
Es gibt ab Version 6.0 OCL Operatoren für die Abfrage von Berechtigungen. Grundsätzlich gibt es 3 Arten von Berechtigungen:
Die folgenden Operatoren für Berechtigungsabfragen liefern einen Boolean (Wahr/Falsch) Wert zurück.
Die Rechte auf einzelnen Members werden auf dem Objekt abgefragt und der Name des Members als Argument übergeben:
Operator | Rechtname |
---|---|
Object->isMemberReadable(memberName) | rtRead |
Object->isMemberWritable(memberName) | rtWrite |
Operator | Rechtname |
---|---|
Class->isCreatable | rtCreate |
Object->isDeletable | rtDelete |
Object->isExecutable | rtExecute (Reports und Scripts) |
Object->isViewable | rtSingleForm (darf das Objekt in eigenem Fenster gezeigt werden?) |
Bei der Abfrage der User-Rechte muss der Name des entsprechenden Rechts übergeben werden:
User->hasRight(rightname)
Rechtnamen für hasRight | Standard Benutzerrecht |
---|---|
'admin' | Super |
'supervisor' | Projekt Administrator |
'manager' | Projekt Leiter |
'selftracking' | Projekt Zeiterfasser |
'folderlinks_admin' | Ordner-Links Administrator |
'folderlinks_user' | Ordner-Links User |
'address_admin' | Adress Administrator |
'address_user' | Adress User |
'benchmarking' | Benchmarking |
'treeview' | Baumansicht |
'systemproperties' | Systemeinstellungen |
'trackingcontroller' | Projekt Fremderfasser |
'book' | Rechnungen buchen |
'book_creditor' | Kreditoren buchen |
'benchmarking_no_users' | Benchmarking ohne Bearbeiterzahlen |
'teamleader' | Teamleiter |
'export' | Exportieren |
'sqlquery' | SQL Query |
Falls ein unbekannter Recht-Namen angegeben wird, gibt der hasRight-Operator False zurück.
Projekteinträge ist der Sammelbegriff für Leistungen, Spesen und Auslagen. Diese wiederum teilen sich auf in offen und verrechnet. Die Zuordnungen zu Projekten, Phasen und Bearbeitern ist im Modell jeweils auf der untersten Ebene definiert, also auf den offenen oder verrechneten Leistungen bzw. Spesen oder Auslagen.
Für den einfachen Zugriff auf Projekt, Phase und Bearbeiter gibt es ab Version 5.7 deshalb folgende Operatoren:
Operator | Beschreibung |
---|---|
getProjekt |
Liefert das Projekt zurück, auf welches die Leistung, Spese oder Auslage erfasst wurde. |
getPhase |
Liefert die Projektphase zurück, der die Leistung, Spese oder Auslage zugeordnet ist. |
getBearbeiter |
Liefert den Projektbearbeiter zurück, welcher die Leistung, Spese oder Auslage erfasst hat. |
Beispielsweise eine Liste von Bearbeitern aufgrund von Leistungen einer Rechnung:
leistungen.getBearbeiter->asSet
Bei Vertec Versionen vor 5.7 sind beim Zugriff auf eine Liste mit allgemeinerem Typ (Leistung, Spesen, Auslagen) Casts notwendig. Beispielsweise eine Liste von Bearbeitern aufgrund von Leistungen einer Rechnung:
leistungen->collect(if oclIsTypeOf (VerrechneteLeistung) then oclAsType (VerrechneteLeistung).bearbeiter else oclAsType(OffeneLeistung).bearbeiter endif)->asSet
phaseGetProjekt |
In Versionen vor 6.3 haben die Subphasen einer Projektphase keine direkte Verbindung zum Projekt, dem sie zugehören. Der OCL Operator phaseGetProjekt liefert für eine beliebige Phase oder Subphase das Projekt:
Ab Vertec 6.3 kann dafür auch das Member |
usereintrag->getLinks(rolle) | Gibt eine Liste von Objekten zurück, die unter dieser Rolle mit dem Eintrag verlinkt sind. Projektbearbeiter->getLinks('archiveintraege') |
Für die Optimierung von kundenspezifischen Auswertungen mit Expressionordnern und Listenspalten oder zur Verwendung in benutzerdefinierten Berichten steht die beschleunigte Summierung und Gruppierung in Form eines OCL Operators groupLeistungen
zu Verfügung. Alle Informationen zu den Leistungssummen-Operatoren finden Sie im Artikel über Leistungssummen.
date |
der date Operator liefert das aktuelle Datum. |
now |
der now Operator liefert das aktuelle Datum inkl. Zeit |
dateToFloat |
verwandelt einen Datum/Zeit Wert in eine Fliesskommazahl. Der ganzzahlige Anteil ist die Anzahl Tage seit dem 30.12.1899. Der Bruchteil gibt die Uhrzeit an. |
floatToDate |
verwandelt eine Zahl in einen Datum/Zeit Wert. |
dateToStrGerman |
Ab Vertec 6.2. Gibt das Datum in deutschem Datumsformat als String zurück.
Es braucht an gewissen Orten manchmal Datumswerte im deutschen Format, unabhängig von aktuellen Regionaleinstellungen (siehe z.B. von/bis-Argumente bei groupLeistungen Operatoren). argobject.eval('creationdatetime.datetostrgerman') |
year |
berechnet das Jahr eines Datumswertes. |
month |
berechnet den Monat (1-12) eines Datumswertes. |
day |
berechnet den Tag des Monats eines Datumswertes. |
hours |
gibt die Stunden des Zeitwertes als integer zurück. |
minutes |
gibt die Minuten des Zeitwertes als integer zurück. |
seconds |
gibt die Sekunden des Zeitwertes als integer zurück. |
milliseconds |
gibt die Millisekunden des Zeitwertes als integer zurück. |
incMonth(anzahl) |
zählt Anzahl Monate zu einem Datum hinzu. Man kann damit auch retour zählen: date.incMonth(-1) zählt zum Beispiel vom aktuellen Datum einen Monat zurück. Hinweis: Liegt das Datum am Monatsende und haben die jeweiligen Monate unterschiedliche Anzahl Tage, wird der letzte Tag des gesuchten Monats genommen. Beispiel: |
incDay(anzahl) |
zählt Anzahl Tage zu einem Datum hinzu. Man kann damit auch retour zählen: date.incDay(-10) zählt zum Beispiel vom aktuellen Datum zehn Tage zurück. |
firstOfYear |
berechnet für ein Datum das Datum des ersten Tag des Jahres (1. Januar). |
lastOfYear |
berechnet für ein Datum das Datum des letzten Tag des Jahres (31. Dezember). |
firstOfQuarter |
berechnet den ersten Tag des Quartals. |
lastOfQuarter |
berechnet den letzten Tag des Quartals. Beispiel: self->groupleistungenP(date.firstOfQuarter.asstring, date.lastOfQuarter.asstring, '')->collect(minutenintoffen+minutenintverrechnet)->sumals Spaltenexpression in einer Projektliste zeigt den erfassten Aufwand (offen) im aktuellen Quartal an. |
firstOfMonth |
berechnet den ersten Tag des Monats. |
lastOfMonth |
berechnet den letzten Tag des Monats. |
mondayOfWeek |
berechnet das Datum des Montags einer Woche. |
encodeDate
|
berechnet ein Datum aufgrund von Zahlenwerten für Jahr, Monat und Tag. Beispiel: Ordner mit allen Rechnungen, die im Jahr 2012 erstellt wurden: rechnung->select((datum >= encodeDate(2012,01,01)) and (datum <= encodeDate(2012,12,31))) |
formatdatetime
|
Formatiert Datum und Zeit gemäss Formatstring (ab Version 5.2.0.15).
Beispiel: creationdatetime.formatdatetime('c')-> '16.10.2010 15:24:31'Der Formatstring kann folgendes enthalten:
|
An gewissen Orten gibt es OCL Variablen, mit welchen auf bestimmte Objekte zugegriffen werden kann. Es sind dies die folgenden:
OCL Variable | Verwendung |
---|---|
varLogin |
In Expressions auf Berechtigungen
kann auf das aktuelle Login über die Variable varLogin zugegriffen werden. |
varContainer |
Ab Vertec 6.4.0.21. Zugriff in OCL Expressions in Listen auf den Container (Ordner oder LinkContainer). Neben den Spalten-Expressions in der Liste haben auch die ListExpression und GhostRowListExpression eines Controls Zugriff auf diese Context-Variable. |
varContext |
Ab Vertec 6.6.0.1. Zugriff in OCL Expressions zur Anpassung von Listeneinstellungen. Enthält den aktuell im Baum ausgewählten Eintrag. Für Container ist der Wert identisch mit varContainer (siehe oben).
Die Variable ermöglicht insbesondere in der Ressourcenplanung die Anpassung von Listen in Abhängigkeit davon, ob eine Ressourcenplanungsansicht für Einzelobjekte oder Listen angezeigt wird. Sie steht auch in sowie List Controllern und Custom Renderern zur Verfügung. Damit die OCL Variable hier einfach verwendet werden kann, steht bei beiden die self.evalocl() Methode zur Verfügung, welche diesen spezifischen OCL Evaluator verwendet. Die OCL Variable ist nur in diesem Evaluator definiert. |
varParent |
Ab Vertec 6.4.0.21. Zugriff in OCL Expressions in Listen auf das Objekt, dem der Container gehört (Parent-Objekt des Link-Containers). Neben den Spalten-Expressions in der Liste haben auch die ListExpression und GhostRowListExpression eines Controls Zugriff auf diese Context-Variable. |
varStartDate | Ab Vertec 6.6.0.1 für die Verwendung in Ressourcenplanungstabellen. Enthält das Start-Datum der aktuellen Ressourcenplanungsansicht:
Sie ist verfügbar in Ressourcenplanungsansichten und den zugehörigen List Controllern sowie in den Custom Renderern. Damit die OCL Variable in List Controllern und Custom Renderern einfach verwendet werden kann, steht bei beiden die self.evalocl() Methode zur Verfügung, welche diesen spezifischen OCL Evaluator verwendet. Die OCL Variable ist nur in diesem Evaluator definiert. Die Container Variablen varContainer und varParent enthalten im Fall eines Einzelobjekts |
varEndDate | Ab Vertec 6.6.0.1 für die Verwendung in Ressourcenplanungstabellen. Enthält das End-Datum der Ressourcenplanungsansicht:
Sie ist verfügbar in Ressourcenplanungsansichten und den zugehörigen List Controllern sowie in den Custom Renderern. Damit die OCL Variable in List Controllern und Custom Renderern einfach verwendet werden kann, steht bei beiden die self.evalocl() Methode zur Verfügung, welche diesen spezifischen OCL Evaluator verwendet. Die OCL Variable ist nur in diesem Evaluator definiert. Die Container Variablen varContainer und varParent enthalten im Fall eines Einzelobjekts |
varView |
Ab Vertec 6.6.0.1. Gibt die Art der Listenansicht an. Mögliche Werte sind:
(varView='default') or (varView='bi') . |
var<Feldname> |
Ab Vertec 6.1. Zugriff auf Abfrageparameter in Spalten von SQL- und Expression Ordnern . |
Vergleiche von 2 Werten (meist eine Member-Referenz und eine Konstante) kommen in OCL-Expressions häufig vor, meist als Bedingung in einem select
Operator.
Die einfachste Form eines Vergleichs ist der Identitätsvergleich in Form eines "=" Zeichens:
projekt->select(code='ABC')
liefert eine Liste aller Projekte, deren Code genau dem String ABC entspricht. Normalerweise sollte diese Liste nur ein Projekt umfassen.
Weitere Möglichkeiten für Vergleiche bieten die bekannten Operatoren für grösser, kleiner oder ungleich (<, >, <>). Vergleiche lassen sich mit Strings und mit Zahlen durchführen.
Auch Booleans (Wahr/Falsch Werte) können verglichen werden.
Will man einen Boolean Wert auf true abfragen, dann geschieht dies implizit (if aktiv then..
oder bearbeiter->select(aktiv)
etc.)
Die folgenden Boolean-Operatoren geben alle oder zurück und dienen dazu, Werte abzufragen, Listen zu filtern etc.
and |
Logisches UND, das heisst, beide Elemente, die mit AND zusammengehängt werden, müssen erfüllt sein. rechnung->select((datum >= encodeDate(2012,01,01)) and (datum <= encodeDate(2012,12,31))) |
or |
Logisches OR, das heisst, mindestens eines der beiden Elemente, welche mit OR zusammengehängt werden, muss erfüllt sein. |
xor |
Kontravalentes OR, das heisst, genau eines der beiden Elemente ist erfüllt, entweder das eine oder das andere; weder sind beide zugleich wahr noch beide zugleich falsch. |
not |
Mit dem not Operator werden Boolean-Elemente auf false abgefragt. bearbeiter->select(not aktiv) |
implies |
Ergibt |
Für Stringvergleiche (oder auch: Zeichenketten-Vergleiche) gibt es zusätzlich die Möglichkeit, Teilstrings zu berücksichtigen. Zu diesem Zweck gibt es die folgenden Vergleichs-Operatoren:
sqlLike |
Er hat eigentlich nichts mit SQL zu tun, ausser dass das Format des Musterstrings der Konvention im SQL Standard entspricht. sqllike verwendet für den Vergleich einen Musterstring, der Platzhalterzeichen umfassen kann. Das folgende Beispiel liefert alle Projekte, deren Code mit "AB" beginnt: projekt->select(code->sqllike('AB%')) |
sqlLikeCaseInsensitive |
Ist gleich wie der vorherige sqllike, jedoch ohne die Gross-/Kleinschreibung zu beachten.
Als Platzhalter können folgende Zeichen verwendet werden:
|
regExpMatch |
Ist der universellste Operator der drei. Er erwartet eine sogenannte Regular Expression (Regulärer Ausdruck). In Vertec können die folgenden grundlegenden Elemente verwendet werden, Gross-/Kleinschreibung wird dabei nicht beachtet:
., *, +, [, ], ^, $, -, \ |
Eine OCL-Expression kann auch Bedingungen enthalten. Da eine Expression aber immer einen bestimmten Wert haben muss, sind im Gegensatz zu Programmiersprachen nur if ... then ... else ... endif
Konstruktionen möglich. Ein Beispiel für eine if Bedingung folgt im nächsten Abschnitt über Typ Operatoren.
Um herauszufinden, von welchem Typ (Klasse) ein Objekt ist, kann oclType
verwendet werden. In einer Listenspalte zum Beispiel kann so der Typ des jeweiligen Eintrags angezeigt werden. Ein Beispiel dafür ist die Spalte Datentyp in der Standardsuche von Vertec.
Fragt man oclType in Expressions oder einem Script ab, muss oclType.asstring
abgefragt werden, da der oclType selbst None ist. Die Listenspalten machen das automatisch, an anderen Orten muss dies jedoch explizit geschehen.
Eine ganze Reihe von Operatoren in OCL dient zur Konvertierung von Objekttypen. Natürlich kann der Typ eines Objekts nicht wirklich verändert werden, OCL ist ausschliesslich eine Abfragesprache. Es kann jedoch sein, dass eine Typkonvertierung angegeben werden muss, damit eine OCL-Expression gültig ist.
Ein Beispiel dafür sind Listen von Adresseinträgen. Die Klasse Adresseintrag ist die Basisklasse für die Klassen Person, Paar, Firma, Kontakt, EinfacheAdresse. In den meisten Fällen sind Listen von Adresseinträge vom Typ Collection(Adresseintrag). Nun soll in einer Adressliste das Vornamen-Attribut eines Personen Objekts dargestellt werden. Die OCL-Expression vorname
in den Spalteneinstellungen einer Adressliste führt zur Fehlermeldung "vorname is not a member of Adresseintrag".
Um die gewünschte Information (allerdings nur bei Personen) trotzdem anzuzeigen, könnte folgende Expression angegeben werden:
if oclIsTypeOf(Person) then oclAsType(Person).vorname else '' endif
Die Expression bezieht sich auf das jeweilige Objekt in der Liste und enthält gleich zwei Typoperatoren. oclIsTypeOf
prüft, ob das Objekt von einem bestimmten Typ ist, und oclAsType
bringt den OCL Interpreter dazu, diesen Adresseintrag als Person zu betrachten und das Member vorname zu akzeptieren.
Möchte man wissen, ob ein Objekt ein Adresseintrag ist (egal, ob Person, Firma etc.), dann kann man das abfragen mit oclIsKindOf
. Zum Beispiel möchte man in einer Liste mit gemischten Objekten den Namen anzeigen, wenn es eine Adresse ist:
if oclIsKindOf(Adresseintrag) then name.asstring else '' endif
Attribute vom Typ TypeList
- das sind die "Klassen" Attribute zum Beispiel auf Ordnern, Scripts, Reports etc. - enthalten eine Liste von Klassen. Die oben genannten Operatoren funktionieren jedoch nur auf einem einzelnen Objekt. Um herauszufinden, ob eine bestimmte Klasse enthalten ist, gibt es ab Vertec 6.7.0.15 den Operator containsType
auf diesen TypeList Attributen. Damit kann abgefragt werden, ob eine bestimmte Klasse darin enthalten ist:
ordner.types.containsType(Projekt)
Ab Vertec Version 6.3.0.12. Mit den OCL Call Operatoren können bestimmte Python Methoden aus OCL aufgerufen werden. Das ermöglicht es, Ergänzungen zur Business-Logik in Python zu schreiben und diese an verschiedenen Orten anstelle der fest eingebauten Business-Logik verwenden zu können, z.B. in Scripts und für die Darstellung in Berichten.
Da OCL statisch und streng typisiert ist, braucht es für jede benötigte Kombination aus Rückgabewert und Argumenten einen separaten OCL Operator. Folgende stehen zur Verfügung:
Die OCL Operatoren werden auf BusinessclassesRoot angewendet und haben alle als erstes Argument den Namen der implementierenden Python-Funktion. Dieser Name wird in der Form <Modul>.<Funktionsnamen>
angegeben.
Es wird ein Script-Modul namens customlogic angelegt, darin eine Funktion mit der Signatur
def percentofcompletion(project, eff_date)
Der Aufruf in OCL würde dann wie folgt aussehen:
proj->callCurrDate('customlogic.percentofcompletion', somedate)
, das Ergebnis der OCL Expression ist ein Currency
Wert.
Der Name des verwendeten Call Operators enthält den Typ des Rückgabewertes und der Argumente (Rückgabewert Currency "Curr", Argument "Date").
Wichtig zu wissen ist, dass es sich bei den Call Operatoren um Abfragen handelt, welche zum Zeitpunkt der Abfrage den ensprechenden Python Code ausführen und dann das Resultat anzeigen. Ändern sich im Hintergrund die Daten, dann hat dies keinen Effekt auf die Resultate der Call Operatoren. Diese werden nicht automatisch neu berechnet, das angezeigte Resultat ist also nur zum Zeitpunkt der Ausführung sicher gültig.
Das führt dazu, dass die Call Operatoren nicht geeignet sind an Orten, wo mit dynamischen Daten gearbeitet werden soll, z.B. zur Anzeige in einer Seite.
Für Listenspalten empfehlen wir, anstelle von Call Operatoren die Custom Renderer zu verwenden, welche subscribed sind, auch Schreibzugriffe erlauben sowie die Möglichkeit bieten, eine Vielzahl von Parametern zu setzen.
Die Call Operatoren eignen sich in folgenden Fällen:
Zudem sollen mittels Call Operatoren keine Daten verändert, sondern nur Daten gelesen werden. Sie dienen nicht dazu, Vorgänge auszulösen wie beispielsweise in einem Eventscript, sondern rein für den Lesezugriff.