An instance of this class represents the XML form element. See the definition of the form element in the
schema.
In much of this program, the structure of objects follows
the XML structure fairly closely. For example, where the
XML has a note-set root element with day-notes children, the object structure has a
BirdNoteSet root with DayNotes children. However, in the BirdForm class,
we deviate from that structure. A Sighting instance is similar but not identical to a floc element in the XML.
In the XML, the floc element is optional,
and used only when multiple sightings of the same kind of
bird differ in their ages, sexes, locality codes, or
other details. It would have been more consistent to
design the schema such that the form
element carried the species code, and the rest had to be
wrapped in a floc element that would carry
age, sex, and other data. However, since the vast majority
of records have only one floc element, and
since the initial XML file creation was done by hand (using
emacs), the schema's single-sighting pattern allows the floc level to be omitted.
In any case, each BirdForm instance has one
or more Sighting instance children. An XML
form element with no floc
children will be translated into a BirdForm
instance with one Sighting child, while an
XML form element with three floc children will be translated into a BirdForm instance with three Sighting children.
Note that the schema allows both form and floc elements to carry loc-group and sighting-notes content. The internal representation
depends on whether this is the single-sighting or multi-sighting
case.
For the single-sighting case, any age-sex-group, loc-group or
sighting-notes content from to the form element is attached to the single Sighting child instance.
For the multi-sighting case, the form element
cannot contain any age-sex-group content, but
any loc-group or sighting-notes
content from the form element is attached to
the BirdForm instance. Each child floc element is made into a child Sighting instance that carries any age-sex-group, loc-group or sighting-notes content from that element.
For more discussion about potential differences between XML
as read and XML as written, see BirdForm-writeNode.
# - - - - - c l a s s B i r d F o r m
class BirdForm:
"""Represents one or more sightings of a single kind of bird.
Exports:
BirdForm(dayNotes, birdId, notable=None):
[ (dayNotes is a DayNotes instance) and
(birdId is an abbr.BirdId instance) and
(notable is true iff the sighting is notable) ->
dayNotes +:= a new BirdForm instance with those values,
containing no sightings
return that instance ]
.dayNotes: [ as passed to constructor, read-only ]
.birdId: [ as passed to constructor, read-only ]
.notable: [ as passed to constructor, read-only ]
We also pass through the .txKey attribute
of self.birdId.
.txKey: [ passthrough, equals .birdId.txKey ]
Sightings are added and retrieving using these methods:
.__len__(self): [ return number of sightings in self ]
.__getitem__(self, n):
[ n is an integer ->
if n is the index of a sighting in self ->
return that as a Sighting instance
else -> raise KeyError ]
.addSighting(sighting):
[ sighting is a Sighting instance ->
self := self with sighting added ]
.genSightings():
[ generate sightings in self as a sequence of Sighting
instances in the order they were added ]
Because the schema allows elements such as loc-detail and desc to be attached
to either the form element or the floc element, we have to implement inheritance.
For example, if the parent form has a loc-detail describing the precise location of the
sighting, it applies to each of its child floc elements, unless the child
overrides it with its own loc-detail
element. Hence, these next attributes represent items that
can occur either here in a BirdForm instance
or in the child Sighting instances or both.
They are designated as read/write attributes, intended to
be set or retrieved by direct attribute references from
outside the class.
.locGroup:
[ if self has locality information ->
a LocGroup instance representing the locality
else -> None ]
.sightNotes:
[ if self has any sighting notes ->
a SightNotes instance representing those notes
else -> None ]
We also provide a .getLoc() method to
find the effective locality data, using inheritance from
the parent DayNotes instance for locality
attributes not defined at this level. Compare this to
the .locGroup attribute, which describes
only the locality data directly provided at the form level.
.getLoc():
[ return the effective locality data for self as a
Loc instance ]
The class has the usual node reader and writer functions.
There may be one or multiple “sightings,”
stored in the instance's ._sightingList
attribute.
BirdForm.readNode(txny, dayNotes, node): # Static method
[ (txny is a bird taxonomy as a txny.Txny instance) and
(dayNotes is the parent DayNotes instance) and
(node is an et.Element) ->
if node is an rnc.FORM_N node conforming to
birdnotes.rnc and txny ->
dayNotes +:= a new BirdForm instance representing node
return that instance
else -> raise IOError ]
.writeNode(parent):
[ parent is an et.Element ->
parent := parent with a new rnc.FORM_N node
added representing self
return that new node ]
Additional internal state:
State/Invariants:
._sightingList:
[ a list containing the Sighting instances in self
in the order they were added ]
"""