|
Hi All,
[Alternative Subject lines: "An Id by any other Name" and "To Id, or
not to Id" :) ]
One of libSBML's strengths is that, to the extent possible, it
abstracts away the differences among various SBML levels and version.
Unfortunately, it fails at this abstraction when it comes to L1 object
names versus L2 object ids. The problem is one of both syntax and
semantics and is created by the following:
- In L1, the object name field is meant to hold a unique
identifier and has a syntax restricted to alphanumeric
characters and underscores (but may not start with a number).
(Objects do not have an id field.)
- In L2, the object id field takes the place of the L1 name field.
That is, it is meant to hold a unique identifier and has a
syntax restricted to alphanumeric characters and underscores
(but may not start with a number). The object name field is
meant to hold a human readable name for the object and has a
nearly unrestricted syntax.
As a result, when using the current libSBML object model, if you would
like to get or set an object's unique identifier, in L1 you say
get/setName() while in L2 you say get/setId(). If you would like to
get or set object's human readable name, you must work with an L2 model
(there is no equivalent in L1) and say get/setName().
I would like to avoid propagating special-case operations like the
above to your user-level code. While a perfect solution is not
possible, I'd like to propose a practical, nearly optimal solution.
Indeed, this solution would immediately simplify code internal to
libSBML as well, in particular the implementation of both the libSBML
validator and L2 to L1 conversion.
The basic idea is to allow each SBML object to "know" its SBML level
designation and change the behavior of get/setId() and get/setName()
accordingly. In particular:
- If L1, get/setId() and get/setName() reference the object's
id field.
- If L2, get/setId() references the object's id field while
get/setName() references the object's name field.
The level designation of each object will be read-only and will be
determined / set whenever an object is added to a container. That is,
an object will inherit the level designation of its parent. Objects
created through constructors will have an initial SBML level of 2.
With this scheme in place:
- get/setId() could (and should) always be used to refer to
an object's unique identifier, regardless of SBML level.
- get/setName() would refer to an object's human readable name in
L2 (as usual) but could still be used to mean unique identifier
in L1 (for backward compatibility with old code).
The only major issue I see with this solution is that human readable
names will be lost if an L2 object is added to or converted to an L1
model, but as far as I can tell this situation is unavoidable.
(Note: By "know its SBML level designation" I don't mean to say
anything specific about the implementation. Initially, SBase will
likely store an additional level field, however, the implementation may
change later so that SBML objects point to their parent container
object).
Does anyone see a problem with this scheme? Are there any objections?
Thanks.
Ben
|