IBM Doors DXL: Tipps und Tricks

Zahlen an String konkatenieren

Zahlen oder andere Datentypen die in einen String gecastet werden sollen müssen mit leerem String abgeschlossen werden:

real zahl = 4.555;
print "Die Zahl lautet: " zahl " ";

Jedes Attribut sollte bei einem String-Vergleich immer mit Doppelanführungszeichen abgeschlossen werden.

Substrings in DXL

Auf Abschnitte aus einem String zugreifen:

string ganzerString = "Hello world";
string meinSubstring = ganzerString[0:6];
string vonVierBisEnde = ganzerString[4:];
print meinSubstring " " vonVierBisEnde;

Es können auch Funktionen und Variablen in die eckigen Stringklammern geschrieben werden.

int i=2;
string einString = "Hello world";
print einString[i: (length(einString)-4)];

Strings unterliegen der lexikographischen Ordnung

if("Hallo" > "hallo") print "Hallo ist groesser uppercase first";

Ist ein Teilstring enthalten indexOf

string einString = „Hello world“;
if (matches(„Hello“,einString))
{
print „Is drinn!“;
}

Type conversions von String

string eineZahl= „12.3“
int iType = intOf(eineZahl);
real rType = realOf(eineZahl);
char cType = charOf(iType); // Konvertiert in den Ascii-Wert

Datumsvergleich

Date heute = today();
Date einDatum = „1/1/2000 0:0:0“;
if(heute>einDatum)
{
print „Das Jahr 2000 ist vorbei!“;
}

FOR-Schleifen

for i in 0 : 100 do
{
   print "Hello world! " i "";
}

for (x=0; x<100; x++)
{
   print "Hello world";
}

Ausschalten von Skript Timeout

Folgendes Statement im Kopf der Schleife setzt den Skript-Timeout auf unendlich:

pragma runLim,0 // 0 bedeutet unendlich

Iterations- und Ablaufssteuerungsbefehle

halt: Das gesamte DXL Programm wird abgebrochen
continue: Vergiss den Rest der Schleife und beginne mit nächster Iteration
break: Brich die Schleife komplett ab

Left Trim in DXL

string leftTrim(string einString)
{
   int dieLetztePosition=-1;
   for (x=0; x<length(einString); x++)
   {
      if( einString[x:x] != " " )
      {
        dieLetztePosition=x;
         break;
      }
   }

   return einString[dieLetztePosition:];
}


print leftTrim("    Hello world!");

Bibliothek gängiger String-Funktionen wie in JAVA

DXL ist sehr rudimentär was String Manipulationen angeht.

Ich empfehle meine String Bibliothek mit den gängigsten String Functions zu verwenden:

Zum Beitrag über String Functions

Call by reference und Call by Value

a: Call by Value
b: Call by Reference

Bei Call by Reference wird die Zahl nach der Übergabe auch im Context außerhalb des FUnktionsaufrufs geändert.

void myfunction (int a, int<b)
{
   b=a+100;
   a=b+1;
   return(a);
}

Durch statisches Array iterieren

string biers[]={"Becks", "Licher", "Jever", "Heineken"};

// sortiere die Biers lexikographisch
sort(biers);

int i=0;
for (i=0; i<sizeof(biers); i++)
{
   print biers[i] "\n";
}

Dynamische Arrays

Dynamische Arrays sind in DXL immer 2-dimensional.

// Eine Spalte, eine Zeile array
Array einArray = create(1,1);

put(einArray, "Huhuhuhu", 0,0);
// Das Array passt sich automatisch an
put(a,23,10,10);

string huhuString = (string get(einString,0,0));
real eineZahl = (real get(10,10));

// Speicher wieder freigeben
delete(einArray);

Anmerkung zu dyn. Arrays:

Es gibt die Möglichkeit ein statisches Array dynamisch zu alloziieren, allerdings nicht zur Laufzeit anzupassen.

int hallo = 10;
int i;

string test[hallo];

for (i=0; i<10; i++)
{
	test[i]=i "";
}

for (i=0; i<10; i++)
{
	print test[i] "\n";
}

Da ein dynamisches Array allemöglichen Datentypen enthalten kann, gibt es hier keine Standardfunktion um dieses zur sortieren. Die eingetragenen Daten können von beliebigem Typ sein ; z.B. kann auf (1,1) ein String stehen, auf (2,1) ein Object, auf (3,1) eine Attributdefinition etc. Man könnte die Spalte in ein Standard-Array (z.B. string myArray) wie im obigen Beispiel übertragen, darin sortieren und danach zurückkopieren.

Es gibt keine Möglichkeit die Größe eines dynamischen Arrays (Anzahl Zeilen) zu ermitteln.
Da man aber das Array im Verlauf des Programms mit „put“ gefüllt hat, wurden dort zwangsläufig die maximalen Koordinaten verwendet; wenn man die größte Koordinate also nach der Befüllung speichert (typischerweise in globalen Variablen myMaxX, myMaxY), kann man sie apäter wieder nutzen.

Skip Listen

Skip Listen sind assoziative Arrays (PHP), HashMaps (Java) oder Dictionaries (C#) . Laut IBM sind dies sehr effiziente Datenstrukturen.

Skip idStringList = createString; // Für String Datentypen
Skip idList = create; // Für nicht-String Datentypen

// put Paramater: skip-list, key, value
put (idList, "234-22-2345", "Hallo");

// PUT liefert falls zurück falls der Wert schon vorhanden ist
put (idList, "123-45-6789", "Welt");

string gleichZuweisen;
// find nutzen um zu testen ob in Skip List vorhanden
if( find(idList, "234-22.2345", gleichZuweisen) )
{
   print gleichZuweisen;
   delete (idList, "234-22.2345");
}

put(idList "234-222-2222", "world");

Beispiel um Dubletten mit Skip-Listen rauzufiltern:

Skip myList = create;
int numList[] = {1,6,2,3,1,2,1,4,2,5,6,7,2,1,3,4,8};

int i;
for (i=0; i<sizeof(numList); i++)
{
   put (myList, numList[i], numList[i]);
}

// Iteration durch SkipList
for i in myList do 
{
   print i;
}

Iteration durch SkipList mit DxlObject.

Anmerkung: DxlObject eignet sich prima als Ersatz für ein Model/Value-Object. Hierzu folgendermaßen d


Skip result = create;
DxlObject obj = new();
obj->“alarm_id“ = „Bla!“; ….
put(result, alarm_id, obj);
….

// Iteration durch SkipList
for myIterator in result do 
{
   string keyValue = (string key(result));
   DxlObject currentObject = null;

   if(find(result, keyValue, currentObject))
   {
       // Just put the column names here.. it will work
       print (string currentObject->"alarm_id") " ";
       print (string currentObject->"subsystem") " ";
       print (string currentObject->"bitnumber") " ";
       print (string currentObject->"eqwinid") " ";
       print (string currentObject->"eqwintextid") " ";
       print (string currentObject->"eqwinhandling ") "\n";
   }
}

Current

Current ist eine Referenz auf das momentan selektierte / markierte Element und kann ein Project, Folder, Module oder Object sein.

Wenn man über mehrere Objekte eines Moduls iterierts muss es oft explizit das current gesetzt werden.

Project p = current;
Folder f = current;
Module m = current;
Object o = current;

current = f;

Über das Projekt iterieren

Project p = create("/Project1","");

for name in p do 
{
   print name;
}

current = folder "/" 

for itemRef in current  do 
{
   print name(itemRef) " " type(itemRef) " \n";
}

Unterschied zwischen Baseline und Baseline Set

Eine Baseline ist ein eingefrorener Stand für ein Modul. Ein Baseline Set ist ein eingefrorener Stand für die gesamte Maschine / das Projekt / alle Module des Projekts.

Zugriff auf Attribute eines Moduls

Module m = null;
m=read("/Projekt/Modul", true);

string modulName = m."Name";
string attributName = "Created On";
Date createdOn = m.attributeName;

Editieren von Modulattributen

current = folder("/New Family Car Project/Requirements");
Module m = edit("System Requirements", true);
m."Description" = "Capri Soft- System requirements";
save(m);
close(m);
refreshDBExplorer();

Link Beziehungen

ManyToMany beliebig viele Inlinks beliebig viele Outlinks
OneToMany beliebig viele Inlinks maximal ein Outlink
manyToOne beliebig viele Outlinks maximal ein Inlink
OneToOne maximal ein Outlink maximal ein Inlink

Zugriff auf Attribute

identifier(o): Die Doors-Containernummer (z.B. UR12)
number(o): Sagt was aus über die Stellung in der Hierarchie
level(o): Gibt die Tiefe der Schachtelung zurück
leaf(o): Gibt true zurück, wenn das Objekt keine Unterobjekte hat.

// Modul manuell öffnen und im Modul-Menü Tools -> "Edit DXL" 
Module m = current;

Object o;

for o in m do 
{
   print number(o) " \t\t"identifier(o) "    ";
   print o."Object Heading" " ";
   print o."Object Text" "\n"
}

Navigation durch Kindkapitel eines Objektes

Object erstesKind = first(o);
Object letztesKind = last(o);
Object vorherige = previous(o);
… next(o)
… first sibling(o)
… last sibling(o)
… next sibling(o)

Bsp.: Zähle alle Kinder eines Kapitels:

Module m = current;
Object oChild, o = current;

int count = 0;
for oChild in o do 
{
   count++;
}

print count " ";

Loop über alle Links jedes Linkmoduls

Folgendes Beispiel iteriert über die Outgoing links (->) jedes Linkmoduls („*“)

// Modul öffnen und auf Tools -> Edit DXL 
Module m = current;
Link derLink;
Object objekt ;
int linkAnzahl = 0;
Skip eindeutigeZielModule;

for objekt in m do
{
   for derLink in objekt->"*" do
   {
      linkAnzahl++;
      

      // Der Name des Ziel Moduls;
      print fullName target(derLink) " \n";

   }
}

print "Es gibt " linkAnzahl " Outgoing Links!";

Mit diesem Beispiel kann man sich die Outgoing Links in einem Layout DXL ausgeben lassen

Link lnk;
string textToShow = "";
bool isFirst = true;

for lnk in obj->"*" do
{
	string tmn=fullName target(lnk);

	if(!open module tmn)
	{
		read(tmn,false);
	}

	Object tgt = target(lnk);

	if(isFirst)
	{
		textToShow = identifier(tgt) "" textToShow ;
	}
	else
	{
		textToShow = identifier(tgt) "\n"  textToShow;
	}

	isFirst = false;

}

displayRich (textToShow "");

Bei Incoming Links muss das SourceModul immer geöffnet werden:

// Modul öffnen und auf Tools -> Edit DXL 

void handleInLinks(Object einObjekt)
{
   LinkRef eineLinkReferenz;
   string modulWoDerIncomingLinkHerkommt;

   print identifier(einObjekt) " \n";

   for eineLinkReferenz in einObjekt<-"*" do
   {
     modulWoDerIncomingLinkHerkommt= fullName source (eineLinkReferenz);
     print modulWoDerIncomingLinkHerkommt;

   }
}

Module m = current;

Link lnk;
LinkRef lref;
Object o;
int numLinks = 0;
string srcModuleName;

for o in current Module do 
{
   for lref in o<-"*" do
   {
     srcModuleName = fullName source (lref);

     if (!open module srcModuleName)
     {
        read(srcModuleName, false);
     }
   }
}

for o in m do
{
  handleInLinks(o);
}

Eine weitere Möglichkeit bietet das Iterieren über die Module der Inlinks. Man kann sie z.B. in einer Schleife öffnen.

string srcModName;
for srcModName in o<-"*" do
{
   print srcModName "\n";
}

// Voller Pfad der Module zu den IncomingLinks
ModName_ srcModRef
for srcModRef in o<-"*" do
{
    print fullName(srcModRef) "\n";
}

Hier ein Beispiel für ein Layout DXL, das alle Incoming Link Objekte ausgibt

LinkRef lRef;
Link aLink;
ModName_ srcModRef;
int inCount = 0;

Object anObj = obj;

for lRef in anObj <- "*" do { 

 string smn = fullName(source(lRef)) 

  if (! open(module(smn))) { 
      oMod = read(smn, false) 
   } 
} 

for aLink in anObj <- "*" do 
{ 
         Object src = source aLink;
          displayRich( identifier(src) "");
}

Alle Attribute eines Moduls ausgeben

Module m=read("System Requirements", false);

AttrDef adRec;

for adRec in m do 
{
   if(!adRec.system)
   {
      print adRec.typeName " attribute: " adRec.name " \n";
   }
}

Rechnen in Layout DXL

Wenn man auf einer Spaltenüberschrift in einem Doors Modul rechte Maustaste -> Properties -> Layout DXL -> Browse öffnet, kann man in eine Spalte hinzufügen um z.B. zu rechnen.

Die Variable obj ist die aktuelle Zeile.

real cost, result;
int noPerDay;

cost = obj."Cost";
noPerDay = obj."No per day";
result = cost * realOf(noPerDay);
display result "";

Filtern und Sortieren

Filter und Sortierungen können miteinander verknüpft werden

Module m=read("Stakeholder Requirements", false);

Filter f, f1, f2;
Sort s1,s2,s;

s1 = descending("Cost");
s2 = ascending("Priority");

f1 = attribute "Cost" > "1000.0"
f2 = attribute "Cost" < "2000.0"
f3 = contains (attribute "Object Text", "shall", false);

// Filter verknüpfen
f = f1 << f2 << f3;

// Sortierungen verknüpfen
s = s1 << s2;

set(m,f);
set(m,s);
filtering on;

In Datei schreiben

Stream output = write("c:\\datafile.txt");
Object o;
real cost;

for o in current Module do
{
   cost = o."Cost";
   output << cost "\n";
}

Lesen…

print fileExists("C:\\meinedate.txt") " ";
Stream eingabe = read "C:\\meinedate.txt";

string costLine;

while(!end(eingabe))
{
   input >> costLine;
   print costLine "\n";
}
close(eingabe);

User Interfaces

DB: Dialog Box
DBE: Dialog Box Element

OnChange-Ereignisse über callback()-Funktion, die mit Set auf das DBE gesetzt wird. set(DBE dbe, callbackfkt)

DB bierDialogBox = create ("Bier Type", styleStandard);

string meineRadioButtonListe[] = {"Heineken", "Becks", "Krombacher", "Licher"};
DBE bierName=field(bierDialogBox, "Biername:", "Schnaps", 20,false);
DBE radioButton = radioBox (bierDialogBox, "Biersche:", meineRadioButtonListe, 0);
DBE datumFeld = date (bierDialogBox, 30, today, true);
DBE slider = slider (bierDialogBox, "", 5,0,10);

void printOrder(DB win)
{
   string customer = get bierName;
   int radioButtonNummer = get radioButton;
   string radioButtonStyle=meineRadioButtonListe[radioButtonNummer];
   print "Ein " radioButtonStyle " bier vom " customer "";
}

apply (bierDialogBox, "Print", printOrder);

show bierDialogBox;

History

Die History wird mit einer Baseline abgespeichert und beginnt von vorne. D.h. das History-Objekt ist auf einem gerade gebaselintem Modul leer.

Bsp.-Anwendungsfälle

  • Änderungsreports
  • Recherche über Änderungen

Discussions

Eine Chatähnliche Option sind Discussions. Sie werden in der Baseline abgelegt aber nicht ins Archiv eingepackt. Discussions setzen nur Leserechte voraus. Derjenige der die Discussion ausgelöst hat ist der einzige, der sie schließen kann.

Probleme mit Rechten: Kein Zugriff auf ein Objekt

Wenn man keine Zugriffsrechte auf ein Objekt hat kann mit

inherited(o);

Das Objekt auf die Rechte des parents gesetzt werden.

Einfaches isNumeric

bool isNumeric(string einString)
{
   int x;
   for (x=0; x<length(einString); x++)
   {
      if( (!isdigit(einString[x]) ) << (einString[x]!='.' ) << (einString[x]!='-' ) )
      {
		return false;
      }
   }
   return true;
}


string eineZahl = "12.345";
print isNumeric(eineZahl) "";

Installierte und unterstützte Codepages anzeigen

int d;

int installed=0;
int supported=0;

print "INSTALLED:\n";
for d in installedCodepages do
{
	print d "\n";
	installed++;
}
print "\n\n\nSUPPORTED:\n";
for d in supportedCodepages do
{
	print d "\n";
	supported++;
}

print "Installed: " installed "\n";
print "Supported: " supported "\n";

Über Björn Karpenstein

Diplom Informatiker, Programmierer, Musikbegeisterter
Dieser Beitrag wurde unter DXL, IBM DOORS veröffentlicht. Setze ein Lesezeichen auf den Permalink.

Ein Kommentar zu IBM Doors DXL: Tipps und Tricks

  1. TARHINI sagt:

    Sehr Geehrten Damen und Herren

    Ist es möglich ein Frei DXL editor zum üben haben als ich Kein Lizenz für Doors habe.

    Ich möchte Filters für ein Paar Anforderungen schaffen. Gibt es ein Beispiel zu nehmen?

    Ich bedanke mich Ihnen im Voraus

    Mit Freundlichen Grüssen
    Hicham TARHINI

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.