r3 - 21 Jul 2005 - 15:06:48 - HeikkiToivonenYou are here: OSAF >  Journal Web  >  ContributorNotes > KatieParlanteNotes > KatieParlante20050701
looking at the "addressing" issue... how do you find something in the repository? queries? address of well known item or collection/set? when should you use what technique? how can we make the common cases simpler/more readable? what are the common cases?

uses of queries to discover all items of a given class

  • use case: find all items of a kind, (or most items of a kind, filtered by some criteria)
  • examples: all active webdav accounts, all certificates (to put in a sidebar collection), all active shares, all rss feeds (for updating), all flickr collections, all shared collections, all attribute editors, etc.
  • advantages: a parcel can create a new item of the given kind, and it will be discovered by the query. The parcel author does not need to know to place the item in a particular data structure or location in the repository. An "active" attribute can be used to hide instances that shouldn't be found by the query.
  • issues
    • we also see code to store the query/results in some well-known place -- this code can be sort of awkward, or inconsistent. It would be great to offer a cleaner api for this common case.
    • it would be cool to have a shorter/easier way to refer to the Kinds in the query string

Example where the query is stored under "//Queries", found several places:

ALL_CERTS_QUERY = u'for i in "//parcels/osaf/framework/certstore/schema/Certificate" where True'
def _allCertificatesQuery(repView):
  qName = 'allCertificatesQuery'
  q = repView.findPath('//Queries/%s' %(qName))
  if q is None:
    p = repView.findPath('//Queries')
    k = repView.findPath('//Schema/Core/Query')
    q = Query.Query(qName, p, k, ALL_CERTS_QUERY)
    notificationItem = repView.findPath('//parcels/osaf/framework/certstore/schema/dummyCertNotification')
    q.subscribe(notificationItem, 'handle', True, True)
  return q

Example using an item collection instead of a query directly:

  <contentModel:ItemCollection itsName="AttributeEditors">
    <_rule value="for i inevery '//parcels/osaf/framework/attributeEditors/AttributeEditor' where True"/>
  </contentModel:ItemCollection>
...
  for ae in wx.GetApp().UIRepositoryView.findPath('//parcels/osaf/framework/attributeEditors/AttributeEditors'):
    _TypeToEditorClasses[ae.itsName] = ae.className

Example using iterItems:

    for share in Share.iterItems(view):
        if share.active:
            syncShare(share)

uses of query to find matching items

  • use case: find one (or a few) items given a string that matches an attribute (full or partial)
  • examples: lookahead match for locations and email addresses, find a tag item given its name

Example:

  for aLoc in Calendar.Location.iterItems(view):
    if aLoc.displayName[0:keysTyped] == controlValue:
      if existingLocation is None:
        existingLocation = aLoc
      else:
        # We found a second candidate - we won't complete
        existingLocation = None
        break

Example using ALL_CERTS_QUERY above:

def _isInRepository(repView, pem):
  q = _allCertificatesQuery(repView)
  for cert in q:
    if cert.pemAsString() == pem:
      return True

questions

  • any reason to avoid iterItems? If you look at the certstore example, _isInRepository could use iterItems instead. The sidebar collection/set could be created with a rule, and never call the query code above. (Right now _isInRepository() is called and each cert is added to the collection specifically -- presumably to work with an early crippled version of ItemCollection).
  • I'm not seeing any examples where pulling up the query itself by name is that useful. Either you have a case where what you want is really a set/collection with a rule, or you just want to execute the query ephemerally, and something like iterItems is much more readable.

Before using iterItems or KindQuery? you should consider performance.

With certificates, for example, it is common to iterate over the results of various certificate queries (some effectively just kind queries) while adding/removing/changing of certificates happens rarely. So it makes sense to make it fast to get all the wanted certificates and iterate over it, at the expense of making changes a little slower.

In the case of certificates, this:

    qName = 'allCertificatesQuery'
    q = repView.findPath('//Queries/%s' %(qName))

    if q is None:
        # This is only executed once for the lifetime of the repository
        p = repView.findPath('//Queries')
        k = repView.findPath('//Schema/Core/Query')
        q = Query.Query(qName, p, k, ALL_CERTS_QUERY)
        notificationItem = repView.findPath('//parcels/osaf/framework/certstore/schema/dummyCertNotification')
        q.subscribe(notificationItem, 'handle', True, True)

    for cert in q:
        #do something

takes only about 7-8% of the time it takes to do this:

    for cert in Certificate.iterItems(repView):
        #do something

Of course, if your code is not on performance critical path, using the latter form is much nicer.

-- HeikkiToivonen - 21 Jul 2005

Edit | WYSIWYG | Attach | Printable | Raw View | Backlinks: Web, All Webs | History: r3 < r2 < r1 | More topic actions
 
Open Source Applications Foundation
Except where otherwise noted, this site and its content are licensed by OSAF under an Creative Commons License, Attribution Only 3.0.
See list of page contributors for attributions.