|
<< Click to Display Table of Contents >> Navigation: PUM - Modellierung und Codeerzeugung > Strukturen und Muster > LicenseList Structure |
Diese Struktur ermöglicht die Abfrage von Lizenzinformationen (auch mehrere). Die Aufgabe des Entwicklers besteht darin, die verschiedene Quellen zu ermitteln oder zu erschaffen und diese Informationen pro Lizenz in drei Attributen zu verdichten (in 2 String Infos und einem Datums-Attribut). Wenn weitere Attribute gewünscht werden - Modell einfach erweitern.
Diese Struktur fügt nur API-Strukturen ein und einen API-Call:
•API-Model: xxxAPILicenseInfo
oName der Lizenz
oInfos über die Lizenz
oAblaufdatum der Lizenz
•API-Call: SystemLicenseListRead
Die API-Informationen werden über eine CRUD-Struktur ermittelt - wobei nur der (R)ead-Teil zu implementieren ist ...
Anbei eine Beispielimplementierung des READ-Calls (in Smalltalk):
apiSystemLicenseListRead: aTSTAPIPRLicenseListStore options: aMSKRestCallOptions
| aTSTAPILicenseListStoreRL aTSTAPILicenseInfo totalAPIResultList sortedTotalAPIResultList selectedAPIResultList gsLicenseInfo |
"
Der Parameter aTSTAPIPRLicenseListStore wird nicht wirklich benötigt - aber man
kann sich vorstellen, den Call später zu parametrisieren. Außerdem benötigt man
den Parameter als Paging-Information
"
"
Wir checken ggfs. ob der Benutzer den Call überhaupt machen darf ... der
eigentliche Check muss entsprechend kodiert werden: isAllowedToRetrieveLicenseInfo
"
aMSKRestCallOptions getUser isAllowedToRetrieveLicenseInfo
ifFalse:[
"Wir nutzen die vordefinierte Access Denied Exception"
TSTEnumErrorDefinition errCodeAccessDeniedThrowSignal: aMSKRestCallOptions
].
"
In allen PageRequests gibt es die folgende Reihenfolgen
a) Ermittlung der Komplettmenge
b) Filterung der Komplettmenge
c) Sortierung der Komplettmenge
d) Eventuelles Paging ausführen
Dieses Beispiel ist besonders, denn die Rückgabeobjekte werden nicht von persistenten
Objekten abgeleitet. Daher entfällt hier das Filtern. Die Sortierung muss manuell
vorgenommen werden
"
"
Zuerst die komplette Menge erstellen. Hier wird das manuell zusammengestellt - hier
könnte man auch die Sortierung direkt mit einbinden ...
"
totalAPIResultList := OrderedCollection new.
totalAPIResultList
add: ((TSTAPILicenseInfo newInitialized setAllAttributesToNil)
setName: 'Anwendung xyz' ;
setInfo: ' ... gültig bis x/2023 ... ';
":-), immer vorm ablaufen ..."
setDeathDate: (Date today);
yourself.
self retrieveGemstoneLicenseInformation ifNotNil: [ :aGsLicenseInfo | totalAPIResultList add: aGsLicenseInfo ].
"
Wir könnten nun noch sortieren ... um einheitliche Rückgabelisten zu erzwingen
"
sortedTotalAPIResultList := SortedCollection sortBlock: [ :a :b | a getName < b getName ].
sortedTotalAPIResultList addAll: totalAPIResultList.
"
Und dann noch ggfs. Paging
"
selectedAPIResultList := sortedTotalAPIResultList
mskRestStart: aTSTAPIPRLicenseListStore getStart
limit: aTSTAPIPRLicenseListStore getLimit
page: aTSTAPIPRLicenseListStore getPage.
"Wir bauen die Rückgabestruktur zusammen"
^(self restAnswerClass
okRequestFor: aMSKRestCallOptions restCallInstance
result: (TSTAPILicenseListStoreRL withAPIList: selectedAPIResultList total: totalAPIResultList))
"Wir ändern keine Daten - daher kann man auf ein Commit verzichten, und einfach ein Abort erzwingen"
successWithoutCommitCall;
yourself
Anbei eine Beispielimplementierung, um die Gemstone Lizenz auszulesen und eine geeignete Instanz zur weiteren Benutzung zurückzugeben:
retrieveGemstoneLicenseInformation
| aTSTAPILicenseInfo licensePath aGSFile writeStream collectData sunsetData |
licensePath := (System gemEnvironmentVariable: 'GEMSTONE'),'/seaside/etc/gemstone.key'.
(GsFile existsOnServer: licensePath) isNil ifTrue:[ ^nil ].
(aGSFile := GsFile openReadOnServer: licensePath) isNil ifTrue:[ ^nil ].
writeStream := WriteStream on: Unicode16 new.
collectData := false.
[ aGSFile atEnd ] whileFalse: [
| singleLine |
singleLine := aGSFile nextLine.
((singleLine _findString: 'Sunset date' startingAt: 1 ignoreCase: true) > 2)
ifTrue: [ sunsetData := singleLine ].
collectData
ifTrue:[
(singleLine _findString: 'Customer name:' startingAt: 1 ignoreCase: true) > 2
ifTrue:[ collectData := false ].
]
ifFalse:[
collectData := (singleLine _findString: 'GemStone version:' startingAt: 1 ignoreCase: true) > 2
].
collectData
ifTrue:[ writeStream nextPutAll: singleLine ]
].
aGSFile close.
aTSTAPILicenseInfo := TSTAPILicenseInfo new initialize.
aTSTAPILicenseInfo
setName: 'Gemstone DB'
setInfo: writeStream contents.
sunsetData notNil ifTrue:[
| readStream newString |
readStream := ReadStream on: sunsetData.
readStream upTo: $: .
newString := readStream upToEnd trimBlanks.
readStream := ReadStream on: newString.
newString := (readStream upTo: $ ) trimBlanks.
aTSTAPILicenseInfo
setDeathDate: (Date fromString: newString usingFormat: #( 2 1 3 $/ 1 1 ))
].
^aTSTAPILicenseInfo