OCL
Einführung
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.
Verwendungen von OCL
OCL wird in Vertec an verschiedensten Orten verwendet:
- Listeneinstellungen
- Expressionordner
- Scripts
- Reports
- HTML Templates (Vertec Web)
- Zugriff auf Vertec via COM-Schnittstelle.
Eine OCL-Expression wird immer aufgrund eines bestimmten Objekts ausgewertet und liefert ein Ergebnis eines bestimmten Typs. Mögliche Typen von Ergebnissen sind:
- Zahl
- String (Zeichenkette)
- Boolean (logischer bzw. Ja / Nein Wert)
- Objekt
- Liste von Zahlen, Strings, Booleans oder Objekten
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.
Member
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.
Listen (ObjectList)
Eine etwas spezielle Art von Members in Vertec sind berechnete Listen Attribute. Im OCL Editor werden diese als Typ ObjectList dargestellt. Wird innerhalb einer Expression eine Member-Referenz auf eine solche Liste verwendet, dann muss zusätzlich der Operator list darauf angewendet werden.
Zum Beispiel sind Leistungen einer Projektphase über die Verknüpfungen offeneLeistungen und verrechneteLeistungen zugeordnet. Zusätzlich existiert noch die berechnete Liste leistungen welche den kombinierten Inhalt der beiden Verknüpfungen angibt. Für die Anzeige der Anzahl aller Leistungen auf einer Projektphase (Listenspalte einer Phasenliste) eignet sich folgende Expression:
leistungen.list->size
Klassenlisten
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 in 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.
Operatoren
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.
Listenoperatoren
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 Listen-spalte 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:
zeigt 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 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 oderMulti 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:
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 Je nach Feld-Typ können Sie den Wert wie folgt abfragen:
|
| ->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 Erbebnis 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 Mengelehre) umwandelt: projekt.kunde->asSet liefert eine eindeutige Liste aller Kunden. |
| ->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:
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 |
| ->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:
ohne 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:
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 |
| ->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. |
Die Listenoperatoren ->exists und ->forAll funktionieren nicht.
Konvertierungsoperatoren
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:
|
| ->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. in Scripts, wenn vom Benutzer ein Datum abgefragt wird). Ansonsten sollte der Operator encodeDate verwendet werden, der weiter unten beschrieben wird (also nicht '01.09.2010'->strToDate, sondern encodeDate(2010,09,01)) |
| >stringToFloat | wandelt eine Zeichenfolge in ein Zahl um. Ist die Zeichenfolge keine Zahl, wird 0 ausgegeben. |
| ->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. |
| ->listToString |
Durch diesen Operator können Listen in Strings dargestellt werden. So liefert die Expression: phasen.code->listToString(',') 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 | Verfügbar ab Version 5.2.0.23. 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 standardmässig 'DE', 'FR', 'IT', 'EN'. Wenn unter Einstellungen > Sprachen weitere Sprachen hinzugefügt wurden, wird davon jeweils die |
| .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. Hier im Beispiel wird das aktuelle Jahr entsprechend angezeigt: (date.year-2000).pad(2,'0') / ergibt 06 |
Stringbearbeitungsoperatoren
| ->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" 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') |
Bearbeiteroperatoren
Im Zusammenhang mit Sollzeiten und Vorgaben gibt es speziell für den Datentyp Projektbearbeiter eine Reihe von älteren (vor Version 5.4) und neueren (ab Version 5.4) Bearbeiteroperatoren. Die bisherigen Operatoren können auch in den neueren Versionen weiterverwendet werden.
|
->getSollzeit(von, bis) |
Sollzeit in der Periode (minuten) |
bisher |
|
->getArbeitszeit(von, bis) |
Arbeitszeit in der Periode (minuten). Berechnet aus der Summe aller vorhandenen Leistungen plus der Ferien, die als Abwesenheiten erfasst wurden. |
bisher |
|
->getUeberzeitvortrag(datum) |
liefert den Ueberzeitsaldo per Datum-1, ausser auf Datum ist ein Vortrag erfasst, dann wird dieser Vortrag geliefert. |
bisher |
|
->getUeberzeitvortragDatum(datum) |
liefert Datum des letzten Ueberzeitvortrags vor Datum |
neu |
|
->getUeberzeitsaldo(datum) |
liefert Ueberzeitsaldo per Datum |
neu |
|
->getFerienVorgabe(von,bis) |
Ferienguthaben innerhalb Periode |
bisher |
|
->getFerienBezug(von,bis) |
Ferienbezug, sowohl Abwesenheiten als auch Ferienleistungen |
neu |
|
->getFerienVortrag(datum) |
liefert den Feriensaldo per Datum-1, ausser auf Datum ist ein Vortrag erfasst, dann wird dieser Vortrag geliefert. |
bisher |
|
->getFerienVortragdatum(datum): |
liefert Datum des letzten Ferienvortrags vor Datum |
neu |
|
->getFerienStart(datum) |
liefert Startdatum für Berechnung des Ferienguthabens. Ist der nächste Ferien-Stichtag nach dem letzen Vortrag |
neu |
|
->getFerienEnd(datum) |
liefert Enddatum für Berechnung des Ferienguthabens. Ist das nächst Ferienperiode-Ende |
neu |
|
->getFerienSaldo(datum) |
liefert FerienSaldo per Datum |
neu |
|
->getLohn(von,bis) |
Lohn innerhalb der angegebenen Periode |
neu |
|
->getGemeinkosten(von,bis) |
Gemeinkosten innerhalb der angegebenen Periode |
neu |
| ->getSollzeitVorgabe(von, bis) | Berechnet die Sollzeit von, bis nur aufgrund der Vorgaben, ohne Berücksichtigung von Feiertagen. Eintritt / Austritt wird berücksichtigt. | ab 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. | ab 5.4.0.21 |
| ->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. |
ab 5.4.0.21 |
Beispiel
<Projektbearbeiter>->getFeriensaldo(encodeDate(2010,07,31))
liefert das Ferienguthaben per 31.07.2010 dieses Mitarbeiters.
OCL Operatoren für Ressourcenplanung
| .getResPlanMinuten(von, bis) | Gibt die verplante Zeit für den Bearbeiter für die angegebene Periode (von, bis Datum) in Minuten zurück. |
| .getResRsrcMinuten(von, bis) | Gibt die Ressourcenzeit für den Bearbeiter für die angegebene Periode (von, bis Datum) 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 Feiertage- und Ferienkalender). |
Operatoren für Links
| usereintrag->getLinks(rolle) | Gibt eine Liste von Objekten zurück, die unter dieser Rolle mit dem Eintrag verlinkt sind. Projektbearbeiter->getLinks('archiveintraege') |
Leistungssummenoperatoren
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. Die Summierung via OCL ist nur in Zusammenhang mit der Lizenzoption Benchmarking verfügbar. Alle Informationen zu den Leistungssummen-Operatoren finden Sie im Artikel über Leistungssummen.
Datumsoperatoren
| date | der date Operator liefert das aktuelle Datum. |
| 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. |
| 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 Milisekunden 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. |
| 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, |
| firstOfMonth | berechnet den ersten Tag des Monats. |
| lastOfMonth | berechnet den letzten Tag des Monats. |
| mondayOfWeek | berechnet das Datum des Montags einer Woche. |
| encodeDate (year, month, day) |
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 (formatstring) |
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:
|
Vergleiche
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. Für Booleans sind Vergleiche nicht sinnvoll, da ein Boolean Wert an und für sich schon in einer Bedingung angegeben werden kann:
projekt->select(aktiv.asstring='Y')
funktioniert zwar, ist aber umständlicher als die einfachere Formulierung projekt->select(aktiv).
String-Vergleiche
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: ., *, +, [, ], ^, $, -, \ |
Bedingungen
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.
Typ Operatoren
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, 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.
| erstellt: | 20.06.2003 |
|---|---|
| geändert: | 07.05.2012: Expression bei encodeDate korrigiert. |
| Produktlinien: | Standard, Expert |
| Module: | Leistung & CRM |
