8.2.7. DomeinFile identifiers

A model is identified by a URI:

  model URI = 'model:' '//' Authority '#' LocalModelName

  Authority = dot-separated string parts

  LocalModelName = a string compatible with Couchdb filename rules

We derive a name from that model URI to store a DomeinFile locally on a users PDR:

  DomeinFileName = Authority_ '-' LocalModelName.json

  Authority_ = Underscore-separated string parts

This is a name that is compatible with Couchdb file name rules. Why don’t we just use the LocalModelName? Well, that may identify the model uniquely within the repository for a given namespace, but not so locally, where the end user collects models from all kinds of domains. There may very well be a model called 'Automotive' in two separate domains:

  • model://bigcars.com#Automotive

  • model://hobbies.org#Automotive

Were we to store both under the name Automotive, this would cause no problem in the repository databases models_bigcars_com and models_hobbies_org on their respective servers, but it would cause a name conflict for an end user who wants to use both models because their filenames would both be Automotive.json.

Why do we replace "#" with "-"? Both characters are allowed in URNs and thus in URLs and even in Couchdb file names, but in URLs the hash sign has a special interpretation: it separates the resource (file) name from an anchor. Hence, when we ask for a resource like https://perspectives.domains/models_perspectives_domains/perspectives_domains#System.json, Couchdb is requested to provide https://perspectives.domains/models_perspectives_domains/perspectives_domains which does not exist.

We treat DomeinFiles as instances of classes Persistent and Cachable. The Persistent class requires its identifiers to be in the form specified as ResourceIdentifiers in module Perspectives.ResourceIdentifiers. These are strings that can be parsed into a DecomposedResourceIdentifier instance.

We achieve this for DomeinFiles by having a scheme 'model:' (along with loc:, def:, remote: and public:). This means that

  • we can identify a DomeinFile with its full model URI w.r.t. Persistent and friends (in other words: the _id member contains the model URI);

  • the actual files are stored with a name in the form specified above as DomeinFileName (but we never handle that name as such outside class Persistent and the module Perspectives.ResourceIdentifiers).

Couchdb particulars: we serialise the DomeinFile using generic encoding. This results in a JSON structure with a member "contents" and a member "tag". However, Couchdb expects the members "_id" and "_rev", too. Just before storing the file, we add both members to the serialization. Both members are also part of the "contents". There is the following relation between both:

  • the inner "_rev" is always one behind the outer "_rev" (this is because Couchdb sets it on updating: Couchdb is in the lead. On retrieving the resource from Couchdb, we quickly set the inner "_rev" to the outers value);

  • the inner "_id" is the model URI, the outer "_id" is the DomeinFileName as defined above.

The model: scheme is implemented in such a way that all models are stored in a local database with a name that is composed from the system identifier and the suffix "_models".

Class Cacheable will just store the DomeinFile under the full model URI.

To prevent misunderstandings: we should never reach out to a model in a repository using classes Persistent and Cacheable.

8.2.7.1. Looking up a type

Consequently, when we have to look up, say, a context type, we split its identifier at the '$' character. The left part is a model URI. This we can send to getPerspectEntiteit directly and we will receive a DomeinFile either from cache or from the database.

8.2.7.2. Saving a DomeinFile

Likewise, when we add a new model to our local set of copies, we can use saveEntiteit with the model URI to store it.