2
0

Models.Mod 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961
  1. MODULE Models; (** AUTHOR "staubesv"; PURPOSE "Models"; *)
  2. IMPORT
  3. Streams, Locks, Types, Strings, XML, Texts, TextUtilities, Repositories, XMLObjects;
  4. CONST
  5. Ok* = Types.Ok;
  6. (** Notification mode *)
  7. NoNotifications* = 0; (** No notification of listeners upon changes *)
  8. OnChanged* = 1; (** Notify listeners when model value has changed after releasing the write lock *)
  9. InitialStringSize = 128;
  10. AttributeName = "name";
  11. TYPE
  12. (**
  13. Base class of models.
  14. Services:
  15. - Abstract interface for generic read/write access
  16. - Recursive reader/writer lock
  17. - Notification of listeners
  18. - Internalization/externalization
  19. *)
  20. Model* = OBJECT(Repositories.Component)
  21. VAR
  22. changed : BOOLEAN;
  23. notificationMode : SHORTINT;
  24. lock : Locks.RWLock;
  25. PROCEDURE &Init*; (** protected *)
  26. BEGIN
  27. Init^;
  28. notificationMode := OnChanged;
  29. changed := FALSE;
  30. NEW(lock);
  31. END Init;
  32. (** Generic access to data of the model using type conversion *)
  33. (** Generically set data of model. Implicit type conversion if necessary and possible *)
  34. PROCEDURE SetGeneric*(CONST value : Types.Any; VAR res : LONGINT); (** abstract *)
  35. END SetGeneric;
  36. (** Generically get data of model. Implicit type conversion if necessary and possible *)
  37. PROCEDURE GetGeneric*(VAR value : Types.Any; VAR res : LONGINT); (** abstract *)
  38. END GetGeneric;
  39. (** Locking (Recursive reader/writer lock) *)
  40. (** Acquire read lock. *)
  41. PROCEDURE AcquireRead*;
  42. BEGIN
  43. lock.AcquireRead;
  44. END AcquireRead;
  45. (** Release read lock *)
  46. PROCEDURE ReleaseRead*;
  47. BEGIN
  48. lock.ReleaseRead;
  49. END ReleaseRead;
  50. (** Returns TRUE if the caller holds a read lock, FALSE otherwise *)
  51. PROCEDURE HasReadLock*() : BOOLEAN;
  52. BEGIN
  53. RETURN lock.HasReadLock();
  54. END HasReadLock;
  55. (** Acquire write lock *)
  56. PROCEDURE AcquireWrite*;
  57. BEGIN
  58. lock.AcquireWrite;
  59. END AcquireWrite;
  60. (** Release write lock. If the data has changed, all listeners will be notified when the last
  61. writer releases its lock *)
  62. PROCEDURE ReleaseWrite*;
  63. VAR notifyListeners : BOOLEAN;
  64. BEGIN
  65. (* If the last writer releases the lock and the model data has changed, we have to notify interested listeners *)
  66. IF (lock.GetWLockLevel() = 1) THEN
  67. IF (notificationMode = OnChanged) THEN
  68. notifyListeners := changed;
  69. changed := FALSE;
  70. ELSE
  71. notifyListeners := FALSE;
  72. END;
  73. ELSE
  74. notifyListeners := FALSE;
  75. END;
  76. lock.ReleaseWrite;
  77. IF notifyListeners THEN
  78. onChanged.Call(SELF);
  79. END;
  80. END ReleaseWrite;
  81. (** Returns TRUE if the caller holds the writer lock, FALSE otherwise *)
  82. PROCEDURE HasWriteLock*() : BOOLEAN;
  83. BEGIN
  84. RETURN lock.HasWriteLock();
  85. END HasWriteLock;
  86. (** Change notification *)
  87. (** Set how the model notifies listeners upon value changes *)
  88. PROCEDURE SetNotificationMode*(mode : SHORTINT);
  89. BEGIN
  90. ASSERT((mode = NoNotifications) OR (mode = OnChanged));
  91. lock.AcquireWrite;
  92. IF (notificationMode # mode) THEN
  93. notificationMode := mode;
  94. END;
  95. (* the release of the write lock will cause notification if model value has changed and
  96. notification was disabled before *)
  97. lock.ReleaseWrite;
  98. END SetNotificationMode;
  99. (** Indicate that the value of the model has changed. Listeners will be notified when the writer lock
  100. is released. Caller must hold write lock! *)
  101. PROCEDURE Changed*; (** protected *)
  102. BEGIN
  103. ASSERT(HasWriteLock());
  104. changed := TRUE;
  105. END Changed;
  106. (** Internalization and externalization *)
  107. PROCEDURE AddContent*(content : XML.Content); (** overwrite, protected *)
  108. VAR string : Types.String; res : LONGINT;
  109. BEGIN
  110. IF (content # NIL) & (content IS XML.Element) & (content(XML.Element).GetName()^="VALUE") THEN
  111. content := content(XML.Element).GetFirst();
  112. END;
  113. IF (SELF IS Container) THEN
  114. AddContent^(content);
  115. ELSIF (content # NIL) & (content IS XML.ArrayChars) THEN
  116. (* This violates the XML document structure. Could be fixed by allowing XML.ArrayChars SET and GET
  117. procedures that dynamically set/get the model data as string *)
  118. string.value := content(XML.ArrayChars).GetStr();
  119. IF (string.value # NIL) THEN
  120. SetGeneric(string, res); (* ignore res *)
  121. END;
  122. ELSIF (content # NIL) THEN AddContent^(content);
  123. ELSE (* empty content, does not have to add content *)
  124. END;
  125. END AddContent;
  126. (** Write current data value of model to stream <w> at indention level <level>. Caller must hold read lock *)
  127. PROCEDURE WriteValue*(w : Streams.Writer; level : LONGINT);
  128. BEGIN
  129. ASSERT(w # NIL);
  130. ASSERT(HasReadLock());
  131. END WriteValue;
  132. (** Externalize model to stream <w> at indention level <level> *)
  133. PROCEDURE Write*(w: Streams.Writer; context: ANY; level : LONGINT); (** overwrite *)
  134. VAR name : Strings.String; enum: XMLObjects.Enumerator; c: ANY;
  135. BEGIN
  136. IF (SELF IS Container) THEN
  137. Write^(w, context, level);
  138. ELSE
  139. (* Hmm... this violates the idea of XML.Element as container *)
  140. AcquireRead;
  141. name := GetName();
  142. w.Char('<'); w.String(name^); WriteAttributes(w, context, level); w.Char('>');
  143. NewLine(w,level+1);
  144. w.String("<VALUE>");
  145. WriteValue(w, level + 1);
  146. w.String("</VALUE>");
  147. enum := GetContents();
  148. WHILE enum.HasMoreElements() DO
  149. c := enum.GetNext();
  150. c(XML.Content).Write(w, context, level+1);
  151. END;
  152. NewLine(w,level);
  153. w.String("</"); w.String(name^); w.Char('>');
  154. ReleaseRead;
  155. END;
  156. END Write;
  157. END Model;
  158. TYPE
  159. Boolean* = OBJECT(Model)
  160. VAR
  161. value : BOOLEAN;
  162. PROCEDURE &Init*;
  163. BEGIN
  164. Init^;
  165. SetNameAsString(StrBoolean);
  166. value := FALSE;
  167. SetGenerator("Models.GenBoolean");
  168. END Init;
  169. PROCEDURE Set*(value : BOOLEAN);
  170. BEGIN
  171. AcquireWrite;
  172. IF (SELF.value # value) THEN
  173. SELF.value := value;
  174. Changed;
  175. END;
  176. ReleaseWrite;
  177. END Set;
  178. PROCEDURE Get*() : BOOLEAN;
  179. VAR value : BOOLEAN;
  180. BEGIN
  181. AcquireRead;
  182. value := SELF.value;
  183. ReleaseRead;
  184. RETURN value;
  185. END Get;
  186. PROCEDURE SetGeneric*(CONST value : Types.Any; VAR res : LONGINT);
  187. VAR newValue : BOOLEAN;
  188. BEGIN
  189. Types.GetBoolean(value, newValue, res);
  190. IF (res = Types.Ok) THEN Set(newValue); END;
  191. END SetGeneric;
  192. PROCEDURE GetGeneric*(VAR value : Types.Any; VAR res : LONGINT);
  193. VAR currentValue : BOOLEAN;
  194. BEGIN
  195. currentValue := Get();
  196. Types.SetBoolean(value, currentValue, res);
  197. END GetGeneric;
  198. PROCEDURE WriteValue*(w : Streams.Writer; level : LONGINT); (** protected *)
  199. BEGIN
  200. WriteValue^(w, level);
  201. IF value THEN w.String("TRUE"); ELSE w.String("FALSE"); END;
  202. END WriteValue;
  203. END Boolean;
  204. TYPE
  205. Integer* = OBJECT(Model)
  206. VAR
  207. value : LONGINT;
  208. PROCEDURE &Init*;
  209. BEGIN
  210. Init^;
  211. SetNameAsString(StrInteger);
  212. value := 0;
  213. SetGenerator("Models.GenInteger");
  214. END Init;
  215. PROCEDURE Set*(value : LONGINT);
  216. BEGIN
  217. AcquireWrite;
  218. IF (SELF.value # value) THEN
  219. SELF.value := value;
  220. Changed;
  221. END;
  222. ReleaseWrite;
  223. END Set;
  224. PROCEDURE Get*() : LONGINT;
  225. VAR value : LONGINT;
  226. BEGIN
  227. AcquireRead;
  228. value := SELF.value;
  229. ReleaseRead;
  230. RETURN value;
  231. END Get;
  232. PROCEDURE Add*(value : LONGINT);
  233. BEGIN
  234. IF (value # 0) THEN
  235. AcquireWrite;
  236. SELF.value := SELF.value + value;
  237. Changed;
  238. ReleaseWrite;
  239. END;
  240. END Add;
  241. PROCEDURE SetGeneric*(CONST value : Types.Any; VAR res : LONGINT);
  242. VAR newValue : LONGINT;
  243. BEGIN
  244. Types.GetInteger(value, newValue, res);
  245. IF (res = Types.Ok) THEN Set(newValue); END;
  246. END SetGeneric;
  247. PROCEDURE GetGeneric*(VAR value : Types.Any; VAR res : LONGINT);
  248. VAR currentValue : LONGINT;
  249. BEGIN
  250. currentValue := Get();
  251. Types.SetInteger(value, currentValue, res);
  252. END GetGeneric;
  253. PROCEDURE WriteValue*(w : Streams.Writer; level : LONGINT); (** protected *)
  254. BEGIN
  255. WriteValue^(w, level);
  256. w.Int(value, 0);
  257. END WriteValue;
  258. END Integer;
  259. TYPE
  260. Real* = OBJECT(Model)
  261. VAR
  262. value : REAL;
  263. PROCEDURE &Init*;
  264. BEGIN
  265. Init^;
  266. SetNameAsString(StrReal);
  267. value := 0.0;
  268. SetGenerator("Models.GenReal");
  269. END Init;
  270. PROCEDURE Set*(value : REAL);
  271. BEGIN
  272. AcquireWrite;
  273. IF (SELF.value # value) THEN
  274. SELF.value := value;
  275. Changed;
  276. END;
  277. ReleaseWrite;
  278. END Set;
  279. PROCEDURE Get*() : REAL;
  280. VAR value : REAL;
  281. BEGIN
  282. AcquireRead;
  283. value := SELF.value;
  284. ReleaseRead;
  285. RETURN value;
  286. END Get;
  287. PROCEDURE SetGeneric*(CONST value : Types.Any; VAR res : LONGINT);
  288. VAR newValue : REAL;
  289. BEGIN
  290. Types.GetReal(value, newValue, res);
  291. IF (res = Types.Ok) THEN Set(newValue); END;
  292. END SetGeneric;
  293. PROCEDURE GetGeneric*(VAR value : Types.Any; VAR res : LONGINT);
  294. VAR currentValue : REAL;
  295. BEGIN
  296. currentValue := Get();
  297. Types.SetReal(value, currentValue, res);
  298. END GetGeneric;
  299. PROCEDURE WriteValue*(w : Streams.Writer; level : LONGINT); (** protected *)
  300. BEGIN
  301. WriteValue^(w, level);
  302. w.Float(value, 15); (*8 decimal, 'E-', 2 expo, decimal point, leading space*)
  303. END WriteValue;
  304. END Real;
  305. TYPE
  306. Longreal* = OBJECT(Model)
  307. VAR
  308. value : LONGREAL;
  309. PROCEDURE &Init*;
  310. BEGIN
  311. Init^;
  312. SetNameAsString(StrLongreal);
  313. value := 0.0;
  314. SetGenerator("Models.GenLongreal");
  315. END Init;
  316. PROCEDURE Set*(value : LONGREAL);
  317. BEGIN
  318. AcquireWrite;
  319. IF (SELF.value # value) THEN
  320. SELF.value := value;
  321. Changed;
  322. END;
  323. ReleaseWrite;
  324. END Set;
  325. PROCEDURE Get*() : LONGREAL;
  326. VAR value : LONGREAL;
  327. BEGIN
  328. AcquireRead;
  329. value := SELF.value;
  330. ReleaseRead;
  331. RETURN value;
  332. END Get;
  333. PROCEDURE SetGeneric*(CONST value : Types.Any; VAR res : LONGINT);
  334. VAR newValue : LONGREAL;
  335. BEGIN
  336. Types.GetLongreal(value, newValue, res);
  337. IF (res = Types.Ok) THEN Set(newValue); END;
  338. END SetGeneric;
  339. PROCEDURE GetGeneric*(VAR value : Types.Any; VAR res : LONGINT);
  340. VAR currentValue : LONGREAL;
  341. BEGIN
  342. currentValue := Get();
  343. Types.SetLongreal(value, currentValue, res);
  344. END GetGeneric;
  345. PROCEDURE WriteValue*(w : Streams.Writer; level : LONGINT); (** protected *)
  346. BEGIN
  347. WriteValue^(w, level);
  348. w.Float(value, 24); (* leading space, decimal point, 16 digits, 5 expo *)
  349. END WriteValue;
  350. END Longreal;
  351. TYPE
  352. Char* = OBJECT(Model)
  353. VAR
  354. value : CHAR;
  355. PROCEDURE &Init*;
  356. BEGIN
  357. Init^;
  358. SetNameAsString(StrChar);
  359. value := 0X;
  360. SetGenerator("Models.GenChar");
  361. END Init;
  362. PROCEDURE Set*(value : CHAR);
  363. BEGIN
  364. AcquireWrite;
  365. IF (SELF.value # value) THEN
  366. SELF.value := value;
  367. Changed;
  368. END;
  369. ReleaseWrite;
  370. END Set;
  371. PROCEDURE Get*() : CHAR;
  372. VAR value : CHAR;
  373. BEGIN
  374. AcquireRead;
  375. value := SELF.value;
  376. ReleaseRead;
  377. RETURN value;
  378. END Get;
  379. PROCEDURE SetGeneric*(CONST value : Types.Any; VAR res : LONGINT);
  380. VAR newValue : CHAR;
  381. BEGIN
  382. Types.GetChar(value, newValue, res);
  383. IF (res = Types.Ok) THEN Set(newValue); END;
  384. END SetGeneric;
  385. PROCEDURE GetGeneric*(VAR value : Types.Any; VAR res : LONGINT);
  386. VAR currentValue : CHAR;
  387. BEGIN
  388. currentValue := Get();
  389. Types.SetChar(value, currentValue, res);
  390. END GetGeneric;
  391. PROCEDURE WriteValue*(w : Streams.Writer; level : LONGINT); (** protected *)
  392. BEGIN
  393. WriteValue^(w, level);
  394. IF IsPrintableCharacter(value) THEN
  395. w.Char(value);
  396. ELSE
  397. w.String("0x"); w.Int(ORD(value), 0); (*? TBD Support in Types.Mod *)
  398. END;
  399. END WriteValue;
  400. END Char;
  401. TYPE
  402. (** 0X-terminated string (no Unicode support here! *)
  403. String* = OBJECT(Model)
  404. VAR
  405. value : Strings.String; (* {value # NIL} *)
  406. PROCEDURE &Init*;
  407. BEGIN
  408. Init^;
  409. NEW(value, InitialStringSize);
  410. SetNameAsString(StrString);
  411. SetGenerator("Models.GenString");
  412. END Init;
  413. PROCEDURE Set*(value : Strings.String);
  414. BEGIN
  415. ASSERT(value # NIL); (*? CHECK *)
  416. AcquireWrite;
  417. IF (value # SELF.value) THEN
  418. SELF.value := value;
  419. Changed;
  420. END;
  421. ReleaseWrite;
  422. END Set;
  423. PROCEDURE Get*() : Strings.String;
  424. VAR value : Strings.String;
  425. BEGIN
  426. AcquireRead;
  427. value := SELF.value;
  428. ReleaseRead;
  429. ASSERT(value # NIL);
  430. RETURN value;
  431. END Get;
  432. PROCEDURE SetAOC*(CONST value : ARRAY OF CHAR);
  433. VAR length : LONGINT;
  434. BEGIN
  435. length := 0;
  436. WHILE (length < LEN(value)) & (value[length] # 0X) DO INC(length); END;
  437. AcquireWrite;
  438. IF (length+1 > LEN(SELF.value^)) THEN
  439. SELF.value := Strings.NewString(value);
  440. Changed;
  441. ELSIF (SELF.value^ # value) THEN
  442. COPY(value, SELF.value^);
  443. Changed;
  444. END;
  445. ASSERT(SELF.value # NIL);
  446. ReleaseWrite;
  447. END SetAOC;
  448. PROCEDURE GetAOC*(VAR value : ARRAY OF CHAR);
  449. BEGIN
  450. AcquireRead;
  451. COPY(SELF.value^, value);
  452. ReleaseRead;
  453. END GetAOC;
  454. PROCEDURE SetGeneric*(CONST value : Types.Any; VAR res : LONGINT);
  455. VAR newValue : Strings.String;
  456. BEGIN
  457. Types.GetString(value, newValue, res);
  458. IF (res = Types.Ok) THEN Set(newValue); END;
  459. END SetGeneric;
  460. PROCEDURE GetGeneric*(VAR value : Types.Any; VAR res : LONGINT);
  461. VAR currentValue : Strings.String;
  462. BEGIN
  463. currentValue := Get();
  464. Types.SetString(value, currentValue, res);
  465. END GetGeneric;
  466. PROCEDURE WriteValue*(w : Streams.Writer; level : LONGINT); (** protected *)
  467. VAR res : LONGINT;
  468. BEGIN
  469. WriteValue^(w, level);
  470. XML.UTF8ToStream(value^, w, res); (* ignore res *)
  471. END WriteValue;
  472. END String;
  473. TYPE
  474. Set* = OBJECT(Model)
  475. VAR
  476. value : SET;
  477. PROCEDURE &Init*;
  478. BEGIN
  479. Init^;
  480. SetNameAsString(StrSet);
  481. value := {};
  482. SetGenerator("Models.GenSet");
  483. END Init;
  484. PROCEDURE Set*(value : SET);
  485. BEGIN
  486. AcquireWrite;
  487. IF (SELF.value # value) THEN
  488. SELF.value := value;
  489. Changed;
  490. END;
  491. ReleaseWrite;
  492. END Set;
  493. PROCEDURE Get*() : SET;
  494. VAR value : SET;
  495. BEGIN
  496. AcquireRead;
  497. value := SELF.value;
  498. ReleaseRead;
  499. RETURN value;
  500. END Get;
  501. PROCEDURE Include*(element : LONGINT);
  502. BEGIN
  503. AcquireWrite;
  504. IF ~(element IN SELF.value) THEN
  505. INCL(SELF.value, element);
  506. Changed;
  507. END;
  508. ReleaseWrite;
  509. END Include;
  510. PROCEDURE Exclude*(element : LONGINT);
  511. BEGIN
  512. AcquireWrite;
  513. IF (element IN SELF.value) THEN
  514. EXCL(SELF.value, element);
  515. Changed;
  516. END;
  517. ReleaseWrite;
  518. END Exclude;
  519. PROCEDURE Contains*(element : LONGINT) : BOOLEAN;
  520. VAR result : BOOLEAN;
  521. BEGIN
  522. AcquireRead;
  523. result := element IN SELF.value;
  524. ReleaseRead;
  525. RETURN result;
  526. END Contains;
  527. PROCEDURE SetGeneric*(CONST value : Types.Any; VAR res : LONGINT);
  528. VAR newValue : SET;
  529. BEGIN
  530. Types.GetSet(value, newValue, res);
  531. IF (res = Types.Ok) THEN Set(newValue); END;
  532. END SetGeneric;
  533. PROCEDURE GetGeneric*(VAR value : Types.Any; VAR res : LONGINT);
  534. VAR currentValue : SET;
  535. BEGIN
  536. currentValue := Get();
  537. Types.SetSet(value, currentValue, res);
  538. END GetGeneric;
  539. PROCEDURE WriteValue*(w : Streams.Writer; level : LONGINT); (** protected *)
  540. BEGIN
  541. WriteValue^(w, level);
  542. w.Set(value);
  543. END WriteValue;
  544. END Set;
  545. TYPE
  546. (*? would make more sense to Texts.UnicodeText to be the model itself *)
  547. Text* = OBJECT(Model)
  548. VAR
  549. value : Texts.Text; (* {value # NIL} *)
  550. PROCEDURE &Init*;
  551. BEGIN
  552. Init^;
  553. SetNameAsString(StrText);
  554. NEW(value); value.onTextChanged.Add(OnTextChanged);
  555. SetGenerator("Models.GenText");
  556. END Init;
  557. PROCEDURE AcquireRead*;
  558. BEGIN
  559. value.AcquireRead;
  560. END AcquireRead;
  561. PROCEDURE ReleaseRead*;
  562. BEGIN
  563. value.ReleaseRead;
  564. END ReleaseRead;
  565. PROCEDURE HasReadLock*() : BOOLEAN;
  566. BEGIN
  567. RETURN value.HasReadLock();
  568. END HasReadLock;
  569. PROCEDURE AcquireWrite*;
  570. BEGIN
  571. value.AcquireWrite;
  572. END AcquireWrite;
  573. PROCEDURE ReleaseWrite*;
  574. BEGIN
  575. value.ReleaseWrite;
  576. onChanged.Call(SELF); (*? TBD only call when text has changed *)
  577. END ReleaseWrite;
  578. PROCEDURE HasWriteLock*() : BOOLEAN;
  579. BEGIN
  580. RETURN value.HasWriteLock();
  581. END HasWriteLock;
  582. (* will copy text! *)
  583. PROCEDURE Set*(value : Texts.Text);
  584. BEGIN
  585. AcquireWrite;
  586. IF (SELF.value # value) THEN
  587. SELF.value.Delete(0, SELF.value.GetLength());
  588. value.AcquireRead;
  589. SELF.value.CopyFromText(value, 0, value.GetLength(), 0);
  590. value.ReleaseRead;
  591. Changed;
  592. END;
  593. ReleaseWrite;
  594. END Set;
  595. PROCEDURE SetReference*(value: Texts.Text);
  596. BEGIN
  597. SELF.value := value;
  598. AcquireWrite;
  599. Changed;
  600. ReleaseWrite;
  601. END SetReference;
  602. PROCEDURE Get*() : Texts.Text;
  603. VAR value : Texts.Text;
  604. BEGIN
  605. AcquireRead;
  606. value := SELF.value;
  607. ReleaseRead;
  608. RETURN value;
  609. END Get;
  610. PROCEDURE OnTextChanged(sender, data : ANY);
  611. BEGIN
  612. Changed;
  613. END OnTextChanged;
  614. PROCEDURE SetAsString*(CONST string : ARRAY OF CHAR);
  615. BEGIN
  616. value.AcquireWrite;
  617. value.Delete(0, value.GetLength());
  618. TextUtilities.StrToText(value, 0, string);
  619. ReleaseWrite;
  620. END SetAsString;
  621. PROCEDURE GetAsString*(VAR string : ARRAY OF CHAR);
  622. BEGIN
  623. AcquireRead;
  624. TextUtilities.TextToStr(value, string);
  625. ReleaseRead;
  626. END GetAsString;
  627. PROCEDURE SetGeneric*(CONST value : Types.Any; VAR res : LONGINT);
  628. VAR newValue : Texts.Text;
  629. BEGIN
  630. Types.GetText(value, newValue, res);
  631. IF (res = Types.Ok) THEN Set(newValue); END;
  632. END SetGeneric;
  633. PROCEDURE GetGeneric*(VAR value : Types.Any; VAR res : LONGINT);
  634. VAR currentValue : Texts.Text;
  635. BEGIN
  636. currentValue := Get();
  637. Types.SetText(value, currentValue, res);
  638. END GetGeneric;
  639. PROCEDURE WriteValue*(w : Streams.Writer; level : LONGINT); (** protected *)
  640. BEGIN
  641. WriteValue^(w, level);
  642. (* TBD *)
  643. END WriteValue;
  644. END Text;
  645. TYPE
  646. Container* = OBJECT(Model)
  647. PROCEDURE &Init*;
  648. BEGIN
  649. Init^;
  650. SetNameAsString(StrContainer);
  651. SetGenerator("Models.GenContainer");
  652. END Init;
  653. PROCEDURE FindModel(CONST name : ARRAY OF CHAR) : Model;
  654. VAR result : Model; string : Strings.String; content : XML.Content;
  655. BEGIN
  656. result := NIL;
  657. (*? locking!!! *)
  658. content := GetFirst();
  659. WHILE (result = NIL) & (content # NIL) DO
  660. IF (content IS Model) THEN
  661. string := content(Model).GetAttributeValue(AttributeName);
  662. IF (string # NIL) & (string^ = name) THEN result := content(Model); END;
  663. END;
  664. content := GetNext(content);
  665. END;
  666. RETURN result;
  667. END FindModel;
  668. PROCEDURE FindModelByName(CONST fullname : ARRAY OF CHAR) : Model;
  669. VAR curModel : Model; name : ARRAY 32 OF CHAR; i, j : LONGINT; done : BOOLEAN;
  670. BEGIN
  671. curModel := SELF;
  672. done := FALSE;
  673. i := 0; j := 0;
  674. WHILE ~done & (curModel # NIL) & (i < LEN(fullname)) & (j < LEN(name)) DO
  675. IF (fullname[i] = ".") OR (fullname[i] = 0X) THEN
  676. name[j] := 0X;
  677. IF (curModel IS Container) THEN
  678. curModel := curModel(Container).FindModel(name);
  679. ELSE
  680. curModel := NIL;
  681. END;
  682. done := (fullname[i] = 0X);
  683. j := 0;
  684. ELSE
  685. name[j] := fullname[i];
  686. INC(j);
  687. END;
  688. INC(i);
  689. END;
  690. RETURN curModel;
  691. END FindModelByName;
  692. PROCEDURE SetField*(CONST name : ARRAY OF CHAR; CONST value : Types.Any; VAR res : LONGINT);
  693. VAR model : Model;
  694. BEGIN
  695. model := FindModelByName(name);
  696. IF (model # NIL) & ~(model IS Container) THEN
  697. model.SetGeneric(value, res);
  698. ELSE
  699. res := 192;
  700. END;
  701. END SetField;
  702. PROCEDURE GetField*(CONST name : ARRAY OF CHAR; VAR value : Types.Any; VAR res : LONGINT);
  703. VAR model : Model;
  704. BEGIN
  705. model := FindModelByName(name);
  706. IF (model # NIL) & ~(model IS Container) THEN
  707. model.GetGeneric(value, res);
  708. ELSE
  709. res := 192;
  710. END;
  711. END GetField;
  712. END Container;
  713. VAR
  714. StrBoolean, StrInteger, StrReal, StrLongreal, StrChar, StrString, StrSet, StrText, StrContainer : Strings.String;
  715. PROCEDURE NewLine*(w : Streams.Writer; level : LONGINT);
  716. BEGIN
  717. ASSERT(w # NIL);
  718. w.Ln; WHILE level > 0 DO w.Char(09X); DEC(level) END
  719. END NewLine;
  720. (* Helper procedures *)
  721. PROCEDURE IsPrintableCharacter(ch : CHAR) : BOOLEAN;
  722. BEGIN
  723. RETURN (" " < ch) & (ORD(ch) < 128);
  724. END IsPrintableCharacter;
  725. (* global helper procedures *)
  726. PROCEDURE GetReal*(m: Model; VAR r: LONGREAL): BOOLEAN;
  727. VAR real: Types.Longreal; res: LONGINT;
  728. BEGIN
  729. IF m = NIL THEN RETURN FALSE END;
  730. m.GetGeneric(real, res);
  731. IF (res = Ok) THEN
  732. r := real.value; RETURN TRUE
  733. ELSE RETURN FALSE
  734. END;
  735. END GetReal;
  736. PROCEDURE GetInteger*(m: Model; VAR i: LONGINT): BOOLEAN;
  737. VAR int: Types.Integer; res: LONGINT;
  738. BEGIN
  739. IF m = NIL THEN RETURN FALSE END;
  740. m.GetGeneric(int, res);
  741. IF (res = Ok) THEN
  742. i := int.value; RETURN TRUE
  743. ELSE RETURN FALSE
  744. END;
  745. END GetInteger;
  746. PROCEDURE SetReal*(m: Model; r: LONGREAL);
  747. VAR real: Types.Longreal; res: LONGINT;
  748. BEGIN
  749. IF m = NIL THEN RETURN END;
  750. real.value := r;
  751. m.SetGeneric(real, res);
  752. END SetReal;
  753. (** Generator procedures *)
  754. PROCEDURE GenBoolean*() : XML.Element;
  755. VAR boolean : Boolean;
  756. BEGIN
  757. NEW(boolean); RETURN boolean;
  758. END GenBoolean;
  759. PROCEDURE GenInteger*() : XML.Element;
  760. VAR integer : Integer;
  761. BEGIN
  762. NEW(integer); RETURN integer;
  763. END GenInteger;
  764. PROCEDURE GenReal*() : XML.Element;
  765. VAR real : Real;
  766. BEGIN
  767. NEW(real); RETURN real;
  768. END GenReal;
  769. PROCEDURE GenLongreal*() : XML.Element;
  770. VAR longReal : Longreal;
  771. BEGIN
  772. NEW(longReal); RETURN longReal;
  773. END GenLongreal;
  774. PROCEDURE GenChar*() : XML.Element;
  775. VAR char : Char;
  776. BEGIN
  777. NEW(char); RETURN char;
  778. END GenChar;
  779. PROCEDURE GenString*() : XML.Element;
  780. VAR string : String;
  781. BEGIN
  782. NEW(string); RETURN string;
  783. END GenString;
  784. PROCEDURE GenSet*() : XML.Element;
  785. VAR set : Set;
  786. BEGIN
  787. NEW(set); RETURN set;
  788. END GenSet;
  789. PROCEDURE GenText*() : XML.Element;
  790. VAR text : Text;
  791. BEGIN
  792. NEW(text); RETURN text;
  793. END GenText;
  794. PROCEDURE GenContainer*() : XML.Element;
  795. VAR container : Container;
  796. BEGIN
  797. NEW(container); RETURN container;
  798. END GenContainer;
  799. PROCEDURE InitStrings;
  800. BEGIN
  801. StrBoolean := Strings.NewString("Boolean");
  802. StrInteger := Strings.NewString("Integer");
  803. StrReal := Strings.NewString("Real");
  804. StrLongreal := Strings.NewString("Longreal");
  805. StrChar := Strings.NewString("Char");
  806. StrString := Strings.NewString("String");
  807. StrSet := Strings.NewString("Set");
  808. StrText := Strings.NewString("Text");
  809. StrContainer := Strings.NewString("Container");
  810. END InitStrings;
  811. BEGIN
  812. InitStrings;
  813. END Models.