Hi Dan, Many thanks, helps a lot.
Mike On 7 May 2012, at 18:40, Dan Haywood <[email protected]> wrote: > On Saturday, 5 May 2012, Mike Burton wrote: > >> Hi Dan, >> >> Thanks for the update, good work, worth eating a few bits of eggshell:-) >> >> Could you list/ clarify meanings of your canonical string for symbols #~! >> etc please- I'm confused by difference between ~ and # eg >> CUS:123~NME:2~CTY:LON >> > > > > Hi Mike, > > First off, I made two slight mistakes in my first email: # should have been > $ throughout, and CUS:123#NME:2 should have been CUS:123~NME:2. > > Thus: > > CUS:123 - persistent root > !CUS:123 - transient root > CUS:123$items - collection of persistent root > !CUS:123$items - collection of transient root > CUS:123~NME:2 - aggregated object within persistent root > !CUS:123~NME:2 - aggregated object within transient root > CUS:123~NME:2~CTY:LON - aggregated object within aggregated object > within root > CUS:123~NME:2$items - collection of an aggregated object within > root > CUS:123~NME:2~CTY:LON$streets - collection of an aggregated object within > aggregated object within root > > > I wonder whether that is what caused your confusion? Otherwise, and to > answer the question, though: > > There's no intrinsic "meaning" to the symbols, other than to distinguish > the parts of the OID. The ~ is the prefix for each aggregated object, > while $ is the prefix for a collection, if any. I chose "~" because it's > easy to see, I chose "$" because it is used as a separator in Java (outer > vs inner class bytecode). > > > A more useful answer, though , might be for me to explain why OIDs are so > important. > > Within Isis we use an OID as the identifier of an ObjectAdapter, which in > turn is a wrapper around the pojo. The main responsibility of an > ObjectAdapter is to manage the "resolve state", ie lazy loading of an > object. It's also used in dirty tracking: whether an object needs to be > saved to the object store. The ObjectAdapter also points to the > corresponding ObjectSpecification which describes the structure of the > object: ObjectAdapter is like java.lang.Object, while ObjectSpecification > is like java.lang.Class. Also: an OID is a value object (equals, hashCode > etc). > > OIDs are important because they are provide an immutable handle to an > object. This is useful for webapps, eg to use in links and forms, and its > useful for the JSON (restful) viewer, eg in URLs. It's also useful for > object stores, because they can (or rather, will now be able to) use the > OID's string form to represent a reference between an object or the > contents of a collection. > > OIDs are also more generally useful in supporting workflows: an OID is > bookmarkable, so could be added into a favourites list, o (as we do on the > big Irish project), can be converted into a barcode, which is great for > handling incoming communications/correspondence that's been scanned. > > ~~~ > We've had the concept of "CollectionOid"s for a while in Isis: if a > Customer has a collection of Order's, then the CollectionOid is the ID for > the java.util.List that holds a Customer's Order pojos. The "AggregateOid" > is newer, introduced to support NoSQL databases and the more general DDD > concept of an aggregate root. Each AggregateOid has a localId, which is > unique within the aggregate; or in other words it is globally unique in > conjunction with the parent Oid. > > ~~ > The string format I'm suggesting here tries to reflect the "nesting" of > objects of both aggregated entities and of collections: > > CUS:123 is the RootOid for a simple root aggregate; it's a CUS(tomer), > id=123. > > CUS:123~NME:1 is an AggregateOid for the N(a)ME of a customer, with > localId=1. In other words, this is modelling the fact that a customer > might have several names or aliases, this being the OID of one of those > names. Note that we don't know how the name object is related to its > "owning" customer; but that's the responsibility of the > ObjectAdapter/ObjectSpecification to furnish that information. > > CUS:123$items is the CollectionOid of a the "items" collection of customer > id=123. We don't know what type of thing are stored in the "items" > collection; but that's not the responsibility of an Oid: such info can be > found from the ObjectSpecification for the Customer type. Again, we also > don't know what the content of the "items" collection is: but that is the > responsibility of the ObjectAdapter. > > > ~~~ > Lastly, in case it's not obvious, the "CUS" is the abbreviated object type > (as per @ObjectType annotation). If there is no such annotation, then the > object type is taken to be the fully-qualified class name. > > > HTH, > Dan > > > >> >> Mike Burton >> ( iPhone) >> >> >> On 5 May 2012, at 10:13, Dan Haywood <[email protected]> wrote: >> >>> Hello all, >>> >>> First, just to say that I *know* the build is broken, and it's a pretty >>> poor show on my part to let it happen, but it's a little bit of breaking >>> eggs to make an omelette. >>> >>> Second, wanted to update on my current thinking on OIDs ... because this >> is >>> what I'm currently working on and what I intend to commit as soon as I >> can >>> (hopefully this coming week). >>> >>> Already committed: >>> * our OIDs are now immutable >>> * we have three types of OID: >>> - RootOid, which is the OID of a root entity (implementation: is >>> RootOidDefault). >>> - AggregateOid, which is an aggregated entity that is persisted within >> a >>> root entity (eg part of a JSON doc in MongoDB). >>> - CollectionOid, which wraps a List or Set of a root entity >>> - The RootOidDefault was refactored from SerialOid, but it now has an >>> "objectType" (eg "CUS" for customer), so is self-describing. >>> - The CollectionOid also existed previously, and wraps a List or Set for >> an >>> entity >>> - The AggregatedOid we also had a version of; it has a localId to >>> distinguish it from other aggregates of its type (within its parent root) >>> - Both CollectionOid and AggregatedOid have a parentOid >>> >>> >>> Not yet committed: >>> >>> The first thing I've added to AggregateOid is its own objectType, and so >>> that has also led me to introduce a TypedOid interface: both >> RootOidDefault >>> and AggregatedOid implement TypedOid. And so from there we can say that >>> parents (of either AggregateOids or of CollectionOids) are always >> TypedOids. >>> >>> With this change to AggregateOid, we can now say that all OIDs contain >>> enough information to fully recreate them as objects: we do know the type >>> of the object to instantiate and its unique identity. That isn't to say >>> there's enough information to determine how these objects are wired back >>> together again, but that's a responsibility of the object store to >> persist >>> this additional structural information. >>> >>> ~~~ >>> Following on from this, I've been working on a string format for each of >>> these three types. Currently we have numerous incompatible ways of >>> memo-izing OIDs: the XML object store does it one way, the NOSQL object >>> store another, the SQL OS object store another, the "*Mapping" classes >> for >>> the scimpi and HTML viewers (for storing the states of transient objects >> in >>> the Http session) in another, the Memento utility class in yet another, >> the >>> JSON viewer (in its URLs) yet another. It's all very complex and messy. >>> >>> Having a standard canonical string form would therefore simplify things >>> enormously. >>> >>> I've just been writing the unit tests for this, and I've come up with the >>> following: >>> >>> CUS:123 - persistent root >>> !CUS:123 - transient root >>> CUS:123#items - collection of persistent root >>> !CUS:123#items - collection of transient root >>> CUS:123#NME:2 - aggregated object within persistent root >>> !CUS:123~NME:2 - aggregated object within transient root >>> CUS:123~NME:2~CTY:LON - aggregated object within aggregated >> object >>> within root >>> CUS:123~NME:2#items - collection of an aggregated object within >>> root >>> CUS:123~NME:2~CTY:LON#streets - collection of an aggregated object within >>> aggregated object within root >>> >>> I've pasted in the unit tests for this below, so you can see the tests in >>> all its glory. >>> >>> Note how this allows for aggregates to be embedded within aggregates >> (even >>> though I'm not sure that any of the object stores could handle this yet). >>> >>> OK, that's it for now. Wanted to put this out there for reaction; as >> usual >>> with these things, I'll assume silence = consensus. >>> >>> Dan >>> ~~~~~~ >>> >>> >>> package org.apache.isis.core.metamodel.adapter.oid; >>> >>> import
