|
Important |
|---|---|
|
Advice is given to print at least the class diagram of the PetStore UML model so you can quickly reference the model while studying the code examples provided in this section. |
|
In the current version of pyswarm your application is not provided as daemon or service. Assume a Python module that needs an object of our Adm component class. It needs to import the appropriate files, instances them, and calls the desired procedures. By doing so the Python modules of which your application consists are loaded and as soon as the client module finished its job our modules are disappearing again. There is no service running all the time in the background and waiting for calls like a daemon is used to do.
First in any client module we need to import the Adm module. The path starts with the system package petstore, via node package internet, sub-package contacts, logic-component package adm, and then the logic-component module adm which has the Adm class. (Note that package names start with lower-case letter while class-names with upper-case letter.)
from petstore.internet.contacts.adm.adm import *
Instantiate new object of the logic-component class. The class has the same name as the package and the module of the logic-component.
comp = Adm()
|
Note |
|---|---|
|
See Section 3.1, “ Logic Component ” with the API of logic-components. |
|
On the component object create an Operation object:
oOp = comp.createOp()
Operation objects are used for read/write access in all parts of the application. If an Operation is modifying data --which is a write access-- it can be considered as a transaction, having a begin and an end . Due to PostgreSQL write operations are transaction safe. But the Operation object contains additional information, making them available in all modules envolved during its represented transaction.
If we are finished with a transaction, that has processed read-only operations we just close it:
oOp.close()
In order to apply any write activity up to any point of a client code, we need to tell the Operation object to commit the changes to the database which is responsible for persistent storage. This is easily done by calling the method commit() on the Operation object:
oOp.commit() # commit the Operation, so the write access is executed.
|
Note |
|---|---|
|
This is an ACID transaction: if any single sup-operation fails the entire transaction is reverted as if nothing happened. The transaction is isolated and no changes will be visible to other transactions before it has been commited successfully. |
|
As last step we close the Operation object as we already have seen for the read operations:
oOp.close() # close the Operation object
|
Note |
|---|---|
|
See Section 3.2, “ Operation ” with the API of Operations. These methods must be called only inside client implementations. |
|
The component offers a method to retrieve primary object: getPrimaryEntity().
prime = comp.getPrimaryEntity(oOp)
The Operation object has to be provided as parameter as in almost all methods.
if prime:
# do something
If the primary object has been returned, we can proceed to work with this object or accessing the arrangement of other business objects in the component.
Each persistent business object has an entityID (short: EID) which is unique in the logic-component. You can get it as long type value by the method EID() or as string (actually unicode) value by strEID(). Use the string if you want to print the EID or to concetanate EID with other string:
prime.strEID(oOp)
The primary object is an AddressBook and we have modelled a composition-type association from AddressBook to Address.
For each association role a getter method has been generated. The method name is a conjunction of get and the name of the opposite association-role which represents the class of which we want to retrieve object(s). Since we apply the method on primary object which is an AddressBook and we want to get the associated Address objects, we use the opposite association-role AddressesOfAddressBook, which results to the getter name getAddressesOfAddressBook().
addresses = prime.getAddressesOfAddressBook(oOp)
The oOp parameter has to be provided.
Such a method returns a collection of associated objects, more concrete a collector. Collections are not in any case result of an association, but collectors are.
You can call special methods on collections, e.g. for counting:
lCountA = addresses.count(oOp, None, None)
The method count() on a collection counts the objects found in the collection. The quantity returned is a long type. count() offers you two optional parameters to filter the collection, effecting the quantity that is count. Here both parameters are not set.
The first parameter after oOp is the classifier . Provide a string with the name of a sub-class of the opposite role's class to restrict which objects should be count. Since Address has a plenty of sub-classes, you can use one of them to classify the collection you want to count, e.g. 'Telephone' to get all associated Telephone objects counted, or 'ZipAddress' for all ZipAddress objects, which itself can be either GeoAddress or PoboxAddress objects. Example:
lCountA = addresses.count(oOp, 'ZipAddress', None)
The last parameter is used for criteria. Provide a string with criteria filter as you probably know from SQL WHERE clauses. Thus you can filter all objects with a specific attribute value. If classifying ZipAddresses it could be counting all objects with the zipCode='11122'. Please note that we need to unmask ' and " characters with a backslash \.
lCountA = addresses.count(oOp, 'ZipAddress', '\"zipCode\"=\'11122\'')
You can also use AND or OR combinations, also in conjunction with priorizing brackets, e.g "locationName"='Munich' AND ("zipCode"='11122' OR "zipCode"='222333')
You can also use UPPER( value ) or LOWER( value ) to compare values case-insensitive, e.g. LOWER("name")=LOWER('LinDA')
Another example worth to try out are LIKE comparisons, e.g. "subject" LIKE '%a' which applies to all entries where the subject value's last character is the lower character 'a'.
lCountA = addresses.count(oOp, None, '\"subject\" LIKE \'%a\'')
According to the example with retrieving associated Address objects, but here Recipient objects:
addressees = prime.getRecipientsOfAddressBook(oOp)
lCountR = addressees.count(oOp)
Note that you can leave away the parameters if you don't need. But if you leave away strClassifier paremter, but want to use the criteria, you need to name the parameter. Try this:
lCountR = addressees.count(oOp, strCriteria='\"name\" LIKE \'%a\'')
You can retrieve objects from a collection page by page, where each page contains objects of the collection:
pageR = addressees.getPage(oOp)
If only the oOp parameter is provided, the returned page will contain all objects in the collection, sorted by their EID ascending.
The first two parameters after oOp , here not used, are the same as in count(). strClassifier for classifying which type of objects you want in the page, and strCriteria to filter based on attribute values. Usage is same as in count().
The third parameter is strOrdering , which allows you to get the objects ordered, e.g. sorted descending by a given attribute, e.g. the entityID.
pageR = addressees.getPage(oOp, strOrdering='\"entityID\" DESC')
Or combine sorting by multiple attributes, seperate by colon:
pageR = addressees.getPage(oOp, strOrdering='\"name\" ASC, \"entityID\" DESC')
The fourth parameter is nPageSize , for the number of objects to be retrieved per page, e.g. 5 - if set to None or not provided it will retrieve a page with all objects in collection to the page.
Finally the fifth parameter nPage is used to specify the page-number of a page with objects you want to retrieve from collection. Only makes sense as far as nPageSize is not None and nPageSize is less than the count() number if the same filter is applied in getPage() and count().
You can access the objects in a page by a for loop on the page:
for addressee in pageR:
print 'Addressee.Name:', addressee.getName(oOp), '(Addresse.EID:',
|
Note |
|---|---|
|
As more concrete you classified a collection to a sub-class, as more attributes and operations are available on the objects in the page. |
|
An example of an write activity during an operation would be the calling of the auto-logic method newRecipient() which will create a new Recipient object:
newAddressee = prime.newRecipient(oOp, strName)
Note that the method signature is slightly different from that what you have modelled: it expects automatically the oOp parameter. Since the oOp parameter is required for all busines operations in an pyswarm application you don't specifiy oOp in your model and it will be always inserted as first parameter automatically by pyswarm SDK generator.
Another write operation is insert() which inserts an entity object to a collector.
addressees = prime.getRecipientsOfAddressBook(oOp)
addressees.insert(oOp, newAddressee)
This would associate the new Recipient object newAddressee with the primary object prime (an AddressBook object).
Dear reader, we are finished with this tutorial. pyswarm is in strong development and this tutorial is the first tutorial written for pyswarm. Nevertheless I hope that it was helpful for you.
Please also see Chapter 6, Community .
Thank you.