123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961 |
- MODULE Models; (** AUTHOR "staubesv"; PURPOSE "Models"; *)
- IMPORT
- Streams, Locks, Types, Strings, XML, Texts, TextUtilities, Repositories, XMLObjects;
- CONST
- Ok* = Types.Ok;
- (** Notification mode *)
- NoNotifications* = 0; (** No notification of listeners upon changes *)
- OnChanged* = 1; (** Notify listeners when model value has changed after releasing the write lock *)
- InitialStringSize = 128;
- AttributeName = "name";
- TYPE
- (**
- Base class of models.
- Services:
- - Abstract interface for generic read/write access
- - Recursive reader/writer lock
- - Notification of listeners
- - Internalization/externalization
- *)
- Model* = OBJECT(Repositories.Component)
- VAR
- changed : BOOLEAN;
- notificationMode : SHORTINT;
- lock : Locks.RWLock;
- PROCEDURE &Init*; (** protected *)
- BEGIN
- Init^;
- notificationMode := OnChanged;
- changed := FALSE;
- NEW(lock);
- END Init;
- (** Generic access to data of the model using type conversion *)
- (** Generically set data of model. Implicit type conversion if necessary and possible *)
- PROCEDURE SetGeneric*(CONST value : Types.Any; VAR res : LONGINT); (** abstract *)
- END SetGeneric;
- (** Generically get data of model. Implicit type conversion if necessary and possible *)
- PROCEDURE GetGeneric*(VAR value : Types.Any; VAR res : LONGINT); (** abstract *)
- END GetGeneric;
- (** Locking (Recursive reader/writer lock) *)
- (** Acquire read lock. *)
- PROCEDURE AcquireRead*;
- BEGIN
- lock.AcquireRead;
- END AcquireRead;
- (** Release read lock *)
- PROCEDURE ReleaseRead*;
- BEGIN
- lock.ReleaseRead;
- END ReleaseRead;
- (** Returns TRUE if the caller holds a read lock, FALSE otherwise *)
- PROCEDURE HasReadLock*() : BOOLEAN;
- BEGIN
- RETURN lock.HasReadLock();
- END HasReadLock;
- (** Acquire write lock *)
- PROCEDURE AcquireWrite*;
- BEGIN
- lock.AcquireWrite;
- END AcquireWrite;
- (** Release write lock. If the data has changed, all listeners will be notified when the last
- writer releases its lock *)
- PROCEDURE ReleaseWrite*;
- VAR notifyListeners : BOOLEAN;
- BEGIN
- (* If the last writer releases the lock and the model data has changed, we have to notify interested listeners *)
- IF (lock.GetWLockLevel() = 1) THEN
- IF (notificationMode = OnChanged) THEN
- notifyListeners := changed;
- changed := FALSE;
- ELSE
- notifyListeners := FALSE;
- END;
- ELSE
- notifyListeners := FALSE;
- END;
- lock.ReleaseWrite;
- IF notifyListeners THEN
- onChanged.Call(SELF);
- END;
- END ReleaseWrite;
- (** Returns TRUE if the caller holds the writer lock, FALSE otherwise *)
- PROCEDURE HasWriteLock*() : BOOLEAN;
- BEGIN
- RETURN lock.HasWriteLock();
- END HasWriteLock;
- (** Change notification *)
- (** Set how the model notifies listeners upon value changes *)
- PROCEDURE SetNotificationMode*(mode : SHORTINT);
- BEGIN
- ASSERT((mode = NoNotifications) OR (mode = OnChanged));
- lock.AcquireWrite;
- IF (notificationMode # mode) THEN
- notificationMode := mode;
- END;
- (* the release of the write lock will cause notification if model value has changed and
- notification was disabled before *)
- lock.ReleaseWrite;
- END SetNotificationMode;
- (** Indicate that the value of the model has changed. Listeners will be notified when the writer lock
- is released. Caller must hold write lock! *)
- PROCEDURE Changed*; (** protected *)
- BEGIN
- ASSERT(HasWriteLock());
- changed := TRUE;
- END Changed;
- (** Internalization and externalization *)
- PROCEDURE AddContent*(content : XML.Content); (** overwrite, protected *)
- VAR string : Types.String; res : LONGINT;
- BEGIN
- IF (content # NIL) & (content IS XML.Element) & (content(XML.Element).GetName()^="VALUE") THEN
- content := content(XML.Element).GetFirst();
- END;
- IF (SELF IS Container) THEN
- AddContent^(content);
- ELSIF (content # NIL) & (content IS XML.ArrayChars) THEN
- (* This violates the XML document structure. Could be fixed by allowing XML.ArrayChars SET and GET
- procedures that dynamically set/get the model data as string *)
- string.value := content(XML.ArrayChars).GetStr();
- IF (string.value # NIL) THEN
- SetGeneric(string, res); (* ignore res *)
- END;
- ELSIF (content # NIL) THEN AddContent^(content);
- ELSE (* empty content, does not have to add content *)
- END;
- END AddContent;
- (** Write current data value of model to stream <w> at indention level <level>. Caller must hold read lock *)
- PROCEDURE WriteValue*(w : Streams.Writer; level : LONGINT);
- BEGIN
- ASSERT(w # NIL);
- ASSERT(HasReadLock());
- END WriteValue;
- (** Externalize model to stream <w> at indention level <level> *)
- PROCEDURE Write*(w: Streams.Writer; context: ANY; level : LONGINT); (** overwrite *)
- VAR name : Strings.String; enum: XMLObjects.Enumerator; c: ANY;
- BEGIN
- IF (SELF IS Container) THEN
- Write^(w, context, level);
- ELSE
- (* Hmm... this violates the idea of XML.Element as container *)
- AcquireRead;
- name := GetName();
- w.Char('<'); w.String(name^); WriteAttributes(w, context, level); w.Char('>');
- NewLine(w,level+1);
- w.String("<VALUE>");
- WriteValue(w, level + 1);
- w.String("</VALUE>");
- enum := GetContents();
- WHILE enum.HasMoreElements() DO
- c := enum.GetNext();
- c(XML.Content).Write(w, context, level+1);
- END;
- NewLine(w,level);
- w.String("</"); w.String(name^); w.Char('>');
- ReleaseRead;
- END;
- END Write;
- END Model;
- TYPE
- Boolean* = OBJECT(Model)
- VAR
- value : BOOLEAN;
- PROCEDURE &Init*;
- BEGIN
- Init^;
- SetNameAsString(StrBoolean);
- value := FALSE;
- SetGenerator("Models.GenBoolean");
- END Init;
- PROCEDURE Set*(value : BOOLEAN);
- BEGIN
- AcquireWrite;
- IF (SELF.value # value) THEN
- SELF.value := value;
- Changed;
- END;
- ReleaseWrite;
- END Set;
- PROCEDURE Get*() : BOOLEAN;
- VAR value : BOOLEAN;
- BEGIN
- AcquireRead;
- value := SELF.value;
- ReleaseRead;
- RETURN value;
- END Get;
- PROCEDURE SetGeneric*(CONST value : Types.Any; VAR res : LONGINT);
- VAR newValue : BOOLEAN;
- BEGIN
- Types.GetBoolean(value, newValue, res);
- IF (res = Types.Ok) THEN Set(newValue); END;
- END SetGeneric;
- PROCEDURE GetGeneric*(VAR value : Types.Any; VAR res : LONGINT);
- VAR currentValue : BOOLEAN;
- BEGIN
- currentValue := Get();
- Types.SetBoolean(value, currentValue, res);
- END GetGeneric;
- PROCEDURE WriteValue*(w : Streams.Writer; level : LONGINT); (** protected *)
- BEGIN
- WriteValue^(w, level);
- IF value THEN w.String("TRUE"); ELSE w.String("FALSE"); END;
- END WriteValue;
- END Boolean;
- TYPE
- Integer* = OBJECT(Model)
- VAR
- value : LONGINT;
- PROCEDURE &Init*;
- BEGIN
- Init^;
- SetNameAsString(StrInteger);
- value := 0;
- SetGenerator("Models.GenInteger");
- END Init;
- PROCEDURE Set*(value : LONGINT);
- BEGIN
- AcquireWrite;
- IF (SELF.value # value) THEN
- SELF.value := value;
- Changed;
- END;
- ReleaseWrite;
- END Set;
- PROCEDURE Get*() : LONGINT;
- VAR value : LONGINT;
- BEGIN
- AcquireRead;
- value := SELF.value;
- ReleaseRead;
- RETURN value;
- END Get;
- PROCEDURE Add*(value : LONGINT);
- BEGIN
- IF (value # 0) THEN
- AcquireWrite;
- SELF.value := SELF.value + value;
- Changed;
- ReleaseWrite;
- END;
- END Add;
- PROCEDURE SetGeneric*(CONST value : Types.Any; VAR res : LONGINT);
- VAR newValue : LONGINT;
- BEGIN
- Types.GetInteger(value, newValue, res);
- IF (res = Types.Ok) THEN Set(newValue); END;
- END SetGeneric;
- PROCEDURE GetGeneric*(VAR value : Types.Any; VAR res : LONGINT);
- VAR currentValue : LONGINT;
- BEGIN
- currentValue := Get();
- Types.SetInteger(value, currentValue, res);
- END GetGeneric;
- PROCEDURE WriteValue*(w : Streams.Writer; level : LONGINT); (** protected *)
- BEGIN
- WriteValue^(w, level);
- w.Int(value, 0);
- END WriteValue;
- END Integer;
- TYPE
- Real* = OBJECT(Model)
- VAR
- value : REAL;
- PROCEDURE &Init*;
- BEGIN
- Init^;
- SetNameAsString(StrReal);
- value := 0.0;
- SetGenerator("Models.GenReal");
- END Init;
- PROCEDURE Set*(value : REAL);
- BEGIN
- AcquireWrite;
- IF (SELF.value # value) THEN
- SELF.value := value;
- Changed;
- END;
- ReleaseWrite;
- END Set;
- PROCEDURE Get*() : REAL;
- VAR value : REAL;
- BEGIN
- AcquireRead;
- value := SELF.value;
- ReleaseRead;
- RETURN value;
- END Get;
- PROCEDURE SetGeneric*(CONST value : Types.Any; VAR res : LONGINT);
- VAR newValue : REAL;
- BEGIN
- Types.GetReal(value, newValue, res);
- IF (res = Types.Ok) THEN Set(newValue); END;
- END SetGeneric;
- PROCEDURE GetGeneric*(VAR value : Types.Any; VAR res : LONGINT);
- VAR currentValue : REAL;
- BEGIN
- currentValue := Get();
- Types.SetReal(value, currentValue, res);
- END GetGeneric;
- PROCEDURE WriteValue*(w : Streams.Writer; level : LONGINT); (** protected *)
- BEGIN
- WriteValue^(w, level);
- w.Float(value, 15); (*8 decimal, 'E-', 2 expo, decimal point, leading space*)
- END WriteValue;
- END Real;
- TYPE
- Longreal* = OBJECT(Model)
- VAR
- value : LONGREAL;
- PROCEDURE &Init*;
- BEGIN
- Init^;
- SetNameAsString(StrLongreal);
- value := 0.0;
- SetGenerator("Models.GenLongreal");
- END Init;
- PROCEDURE Set*(value : LONGREAL);
- BEGIN
- AcquireWrite;
- IF (SELF.value # value) THEN
- SELF.value := value;
- Changed;
- END;
- ReleaseWrite;
- END Set;
- PROCEDURE Get*() : LONGREAL;
- VAR value : LONGREAL;
- BEGIN
- AcquireRead;
- value := SELF.value;
- ReleaseRead;
- RETURN value;
- END Get;
- PROCEDURE SetGeneric*(CONST value : Types.Any; VAR res : LONGINT);
- VAR newValue : LONGREAL;
- BEGIN
- Types.GetLongreal(value, newValue, res);
- IF (res = Types.Ok) THEN Set(newValue); END;
- END SetGeneric;
- PROCEDURE GetGeneric*(VAR value : Types.Any; VAR res : LONGINT);
- VAR currentValue : LONGREAL;
- BEGIN
- currentValue := Get();
- Types.SetLongreal(value, currentValue, res);
- END GetGeneric;
- PROCEDURE WriteValue*(w : Streams.Writer; level : LONGINT); (** protected *)
- BEGIN
- WriteValue^(w, level);
- w.Float(value, 24); (* leading space, decimal point, 16 digits, 5 expo *)
- END WriteValue;
- END Longreal;
- TYPE
- Char* = OBJECT(Model)
- VAR
- value : CHAR;
- PROCEDURE &Init*;
- BEGIN
- Init^;
- SetNameAsString(StrChar);
- value := 0X;
- SetGenerator("Models.GenChar");
- END Init;
- PROCEDURE Set*(value : CHAR);
- BEGIN
- AcquireWrite;
- IF (SELF.value # value) THEN
- SELF.value := value;
- Changed;
- END;
- ReleaseWrite;
- END Set;
- PROCEDURE Get*() : CHAR;
- VAR value : CHAR;
- BEGIN
- AcquireRead;
- value := SELF.value;
- ReleaseRead;
- RETURN value;
- END Get;
- PROCEDURE SetGeneric*(CONST value : Types.Any; VAR res : LONGINT);
- VAR newValue : CHAR;
- BEGIN
- Types.GetChar(value, newValue, res);
- IF (res = Types.Ok) THEN Set(newValue); END;
- END SetGeneric;
- PROCEDURE GetGeneric*(VAR value : Types.Any; VAR res : LONGINT);
- VAR currentValue : CHAR;
- BEGIN
- currentValue := Get();
- Types.SetChar(value, currentValue, res);
- END GetGeneric;
- PROCEDURE WriteValue*(w : Streams.Writer; level : LONGINT); (** protected *)
- BEGIN
- WriteValue^(w, level);
- IF IsPrintableCharacter(value) THEN
- w.Char(value);
- ELSE
- w.String("0x"); w.Int(ORD(value), 0); (*? TBD Support in Types.Mod *)
- END;
- END WriteValue;
- END Char;
- TYPE
- (** 0X-terminated string (no Unicode support here! *)
- String* = OBJECT(Model)
- VAR
- value : Strings.String; (* {value # NIL} *)
- PROCEDURE &Init*;
- BEGIN
- Init^;
- NEW(value, InitialStringSize);
- SetNameAsString(StrString);
- SetGenerator("Models.GenString");
- END Init;
- PROCEDURE Set*(value : Strings.String);
- BEGIN
- ASSERT(value # NIL); (*? CHECK *)
- AcquireWrite;
- IF (value # SELF.value) THEN
- SELF.value := value;
- Changed;
- END;
- ReleaseWrite;
- END Set;
- PROCEDURE Get*() : Strings.String;
- VAR value : Strings.String;
- BEGIN
- AcquireRead;
- value := SELF.value;
- ReleaseRead;
- ASSERT(value # NIL);
- RETURN value;
- END Get;
- PROCEDURE SetAOC*(CONST value : ARRAY OF CHAR);
- VAR length : LONGINT;
- BEGIN
- length := 0;
- WHILE (length < LEN(value)) & (value[length] # 0X) DO INC(length); END;
- AcquireWrite;
- IF (length+1 > LEN(SELF.value^)) THEN
- SELF.value := Strings.NewString(value);
- Changed;
- ELSIF (SELF.value^ # value) THEN
- COPY(value, SELF.value^);
- Changed;
- END;
- ASSERT(SELF.value # NIL);
- ReleaseWrite;
- END SetAOC;
- PROCEDURE GetAOC*(VAR value : ARRAY OF CHAR);
- BEGIN
- AcquireRead;
- COPY(SELF.value^, value);
- ReleaseRead;
- END GetAOC;
- PROCEDURE SetGeneric*(CONST value : Types.Any; VAR res : LONGINT);
- VAR newValue : Strings.String;
- BEGIN
- Types.GetString(value, newValue, res);
- IF (res = Types.Ok) THEN Set(newValue); END;
- END SetGeneric;
- PROCEDURE GetGeneric*(VAR value : Types.Any; VAR res : LONGINT);
- VAR currentValue : Strings.String;
- BEGIN
- currentValue := Get();
- Types.SetString(value, currentValue, res);
- END GetGeneric;
- PROCEDURE WriteValue*(w : Streams.Writer; level : LONGINT); (** protected *)
- VAR res : LONGINT;
- BEGIN
- WriteValue^(w, level);
- XML.UTF8ToStream(value^, w, res); (* ignore res *)
- END WriteValue;
- END String;
- TYPE
- Set* = OBJECT(Model)
- VAR
- value : SET;
- PROCEDURE &Init*;
- BEGIN
- Init^;
- SetNameAsString(StrSet);
- value := {};
- SetGenerator("Models.GenSet");
- END Init;
- PROCEDURE Set*(value : SET);
- BEGIN
- AcquireWrite;
- IF (SELF.value # value) THEN
- SELF.value := value;
- Changed;
- END;
- ReleaseWrite;
- END Set;
- PROCEDURE Get*() : SET;
- VAR value : SET;
- BEGIN
- AcquireRead;
- value := SELF.value;
- ReleaseRead;
- RETURN value;
- END Get;
- PROCEDURE Include*(element : LONGINT);
- BEGIN
- AcquireWrite;
- IF ~(element IN SELF.value) THEN
- INCL(SELF.value, element);
- Changed;
- END;
- ReleaseWrite;
- END Include;
- PROCEDURE Exclude*(element : LONGINT);
- BEGIN
- AcquireWrite;
- IF (element IN SELF.value) THEN
- EXCL(SELF.value, element);
- Changed;
- END;
- ReleaseWrite;
- END Exclude;
- PROCEDURE Contains*(element : LONGINT) : BOOLEAN;
- VAR result : BOOLEAN;
- BEGIN
- AcquireRead;
- result := element IN SELF.value;
- ReleaseRead;
- RETURN result;
- END Contains;
- PROCEDURE SetGeneric*(CONST value : Types.Any; VAR res : LONGINT);
- VAR newValue : SET;
- BEGIN
- Types.GetSet(value, newValue, res);
- IF (res = Types.Ok) THEN Set(newValue); END;
- END SetGeneric;
- PROCEDURE GetGeneric*(VAR value : Types.Any; VAR res : LONGINT);
- VAR currentValue : SET;
- BEGIN
- currentValue := Get();
- Types.SetSet(value, currentValue, res);
- END GetGeneric;
- PROCEDURE WriteValue*(w : Streams.Writer; level : LONGINT); (** protected *)
- BEGIN
- WriteValue^(w, level);
- w.Set(value);
- END WriteValue;
- END Set;
- TYPE
- (*? would make more sense to Texts.UnicodeText to be the model itself *)
- Text* = OBJECT(Model)
- VAR
- value : Texts.Text; (* {value # NIL} *)
- PROCEDURE &Init*;
- BEGIN
- Init^;
- SetNameAsString(StrText);
- NEW(value); value.onTextChanged.Add(OnTextChanged);
- SetGenerator("Models.GenText");
- END Init;
- PROCEDURE AcquireRead*;
- BEGIN
- value.AcquireRead;
- END AcquireRead;
- PROCEDURE ReleaseRead*;
- BEGIN
- value.ReleaseRead;
- END ReleaseRead;
- PROCEDURE HasReadLock*() : BOOLEAN;
- BEGIN
- RETURN value.HasReadLock();
- END HasReadLock;
- PROCEDURE AcquireWrite*;
- BEGIN
- value.AcquireWrite;
- END AcquireWrite;
- PROCEDURE ReleaseWrite*;
- BEGIN
- value.ReleaseWrite;
- onChanged.Call(SELF); (*? TBD only call when text has changed *)
- END ReleaseWrite;
- PROCEDURE HasWriteLock*() : BOOLEAN;
- BEGIN
- RETURN value.HasWriteLock();
- END HasWriteLock;
- (* will copy text! *)
- PROCEDURE Set*(value : Texts.Text);
- BEGIN
- AcquireWrite;
- IF (SELF.value # value) THEN
- SELF.value.Delete(0, SELF.value.GetLength());
- value.AcquireRead;
- SELF.value.CopyFromText(value, 0, value.GetLength(), 0);
- value.ReleaseRead;
- Changed;
- END;
- ReleaseWrite;
- END Set;
- PROCEDURE SetReference*(value: Texts.Text);
- BEGIN
- SELF.value := value;
- AcquireWrite;
- Changed;
- ReleaseWrite;
- END SetReference;
- PROCEDURE Get*() : Texts.Text;
- VAR value : Texts.Text;
- BEGIN
- AcquireRead;
- value := SELF.value;
- ReleaseRead;
- RETURN value;
- END Get;
- PROCEDURE OnTextChanged(sender, data : ANY);
- BEGIN
- Changed;
- END OnTextChanged;
- PROCEDURE SetAsString*(CONST string : ARRAY OF CHAR);
- BEGIN
- value.AcquireWrite;
- value.Delete(0, value.GetLength());
- TextUtilities.StrToText(value, 0, string);
- ReleaseWrite;
- END SetAsString;
- PROCEDURE GetAsString*(VAR string : ARRAY OF CHAR);
- BEGIN
- AcquireRead;
- TextUtilities.TextToStr(value, string);
- ReleaseRead;
- END GetAsString;
- PROCEDURE SetGeneric*(CONST value : Types.Any; VAR res : LONGINT);
- VAR newValue : Texts.Text;
- BEGIN
- Types.GetText(value, newValue, res);
- IF (res = Types.Ok) THEN Set(newValue); END;
- END SetGeneric;
- PROCEDURE GetGeneric*(VAR value : Types.Any; VAR res : LONGINT);
- VAR currentValue : Texts.Text;
- BEGIN
- currentValue := Get();
- Types.SetText(value, currentValue, res);
- END GetGeneric;
- PROCEDURE WriteValue*(w : Streams.Writer; level : LONGINT); (** protected *)
- BEGIN
- WriteValue^(w, level);
- (* TBD *)
- END WriteValue;
- END Text;
- TYPE
- Container* = OBJECT(Model)
- PROCEDURE &Init*;
- BEGIN
- Init^;
- SetNameAsString(StrContainer);
- SetGenerator("Models.GenContainer");
- END Init;
- PROCEDURE FindModel(CONST name : ARRAY OF CHAR) : Model;
- VAR result : Model; string : Strings.String; content : XML.Content;
- BEGIN
- result := NIL;
- (*? locking!!! *)
- content := GetFirst();
- WHILE (result = NIL) & (content # NIL) DO
- IF (content IS Model) THEN
- string := content(Model).GetAttributeValue(AttributeName);
- IF (string # NIL) & (string^ = name) THEN result := content(Model); END;
- END;
- content := GetNext(content);
- END;
- RETURN result;
- END FindModel;
- PROCEDURE FindModelByName(CONST fullname : ARRAY OF CHAR) : Model;
- VAR curModel : Model; name : ARRAY 32 OF CHAR; i, j : LONGINT; done : BOOLEAN;
- BEGIN
- curModel := SELF;
- done := FALSE;
- i := 0; j := 0;
- WHILE ~done & (curModel # NIL) & (i < LEN(fullname)) & (j < LEN(name)) DO
- IF (fullname[i] = ".") OR (fullname[i] = 0X) THEN
- name[j] := 0X;
- IF (curModel IS Container) THEN
- curModel := curModel(Container).FindModel(name);
- ELSE
- curModel := NIL;
- END;
- done := (fullname[i] = 0X);
- j := 0;
- ELSE
- name[j] := fullname[i];
- INC(j);
- END;
- INC(i);
- END;
- RETURN curModel;
- END FindModelByName;
- PROCEDURE SetField*(CONST name : ARRAY OF CHAR; CONST value : Types.Any; VAR res : LONGINT);
- VAR model : Model;
- BEGIN
- model := FindModelByName(name);
- IF (model # NIL) & ~(model IS Container) THEN
- model.SetGeneric(value, res);
- ELSE
- res := 192;
- END;
- END SetField;
- PROCEDURE GetField*(CONST name : ARRAY OF CHAR; VAR value : Types.Any; VAR res : LONGINT);
- VAR model : Model;
- BEGIN
- model := FindModelByName(name);
- IF (model # NIL) & ~(model IS Container) THEN
- model.GetGeneric(value, res);
- ELSE
- res := 192;
- END;
- END GetField;
- END Container;
- VAR
- StrBoolean, StrInteger, StrReal, StrLongreal, StrChar, StrString, StrSet, StrText, StrContainer : Strings.String;
- PROCEDURE NewLine*(w : Streams.Writer; level : LONGINT);
- BEGIN
- ASSERT(w # NIL);
- w.Ln; WHILE level > 0 DO w.Char(09X); DEC(level) END
- END NewLine;
- (* Helper procedures *)
- PROCEDURE IsPrintableCharacter(ch : CHAR) : BOOLEAN;
- BEGIN
- RETURN (" " < ch) & (ORD(ch) < 128);
- END IsPrintableCharacter;
- (* global helper procedures *)
- PROCEDURE GetReal*(m: Model; VAR r: LONGREAL): BOOLEAN;
- VAR real: Types.Longreal; res: LONGINT;
- BEGIN
- IF m = NIL THEN RETURN FALSE END;
- m.GetGeneric(real, res);
- IF (res = Ok) THEN
- r := real.value; RETURN TRUE
- ELSE RETURN FALSE
- END;
- END GetReal;
- PROCEDURE GetInteger*(m: Model; VAR i: LONGINT): BOOLEAN;
- VAR int: Types.Integer; res: LONGINT;
- BEGIN
- IF m = NIL THEN RETURN FALSE END;
- m.GetGeneric(int, res);
- IF (res = Ok) THEN
- i := int.value; RETURN TRUE
- ELSE RETURN FALSE
- END;
- END GetInteger;
- PROCEDURE SetReal*(m: Model; r: LONGREAL);
- VAR real: Types.Longreal; res: LONGINT;
- BEGIN
- IF m = NIL THEN RETURN END;
- real.value := r;
- m.SetGeneric(real, res);
- END SetReal;
- (** Generator procedures *)
- PROCEDURE GenBoolean*() : XML.Element;
- VAR boolean : Boolean;
- BEGIN
- NEW(boolean); RETURN boolean;
- END GenBoolean;
- PROCEDURE GenInteger*() : XML.Element;
- VAR integer : Integer;
- BEGIN
- NEW(integer); RETURN integer;
- END GenInteger;
- PROCEDURE GenReal*() : XML.Element;
- VAR real : Real;
- BEGIN
- NEW(real); RETURN real;
- END GenReal;
- PROCEDURE GenLongreal*() : XML.Element;
- VAR longReal : Longreal;
- BEGIN
- NEW(longReal); RETURN longReal;
- END GenLongreal;
- PROCEDURE GenChar*() : XML.Element;
- VAR char : Char;
- BEGIN
- NEW(char); RETURN char;
- END GenChar;
- PROCEDURE GenString*() : XML.Element;
- VAR string : String;
- BEGIN
- NEW(string); RETURN string;
- END GenString;
- PROCEDURE GenSet*() : XML.Element;
- VAR set : Set;
- BEGIN
- NEW(set); RETURN set;
- END GenSet;
- PROCEDURE GenText*() : XML.Element;
- VAR text : Text;
- BEGIN
- NEW(text); RETURN text;
- END GenText;
- PROCEDURE GenContainer*() : XML.Element;
- VAR container : Container;
- BEGIN
- NEW(container); RETURN container;
- END GenContainer;
- PROCEDURE InitStrings;
- BEGIN
- StrBoolean := Strings.NewString("Boolean");
- StrInteger := Strings.NewString("Integer");
- StrReal := Strings.NewString("Real");
- StrLongreal := Strings.NewString("Longreal");
- StrChar := Strings.NewString("Char");
- StrString := Strings.NewString("String");
- StrSet := Strings.NewString("Set");
- StrText := Strings.NewString("Text");
- StrContainer := Strings.NewString("Container");
- END InitStrings;
- BEGIN
- InitStrings;
- END Models.
|