Merged
Conversation
This is the Jena facility for watching changes to a graph. Support is limited at the moment; specifically - Transactions are not respected. - While removals fire for inferred statements, additions do not. Some of this can be worked around.
This will be particularly important when we are regenerating structured config entries.
Currently this only updates _Object Registration_; it is also very crude and always recalculates all possible entries. This is due to the limitations of the ModelChangedListener interface. It may be possible to optimise in the future.
In the current JS ConfigDB we store the rank of each object individually. In this RDF version we are deriving it from member relations, but this means the top rank class has no rank as well as no class. Given that nothing should be depending on the numerical ranks anyway I don't mind making this change.
All config changes which happen within a single transaction can and should share the same starting Instant. However we don't want to allocation an Instant to a txn unless it needs one. Refactor the RequestHandler classes to accomodate this. We need to special-case the Object Registration entry for the Instant: if the Instant is not created until we start processing config updates, it will not be caught by the initial pass.
Generate _General info_ entries as well. For the moment these are still two hardcoded functions; it should be possible to generalise them.
Map the results of a Query into JSON, using the typing information from the RDF to decide how to decode. This will only map to a single flat JSON object at this point. The mapping between Application and Query is still hardcoded for Registration and Info for now. In order to generate the correct Registration output we need some facilities for defaulting optional or nonexistent values. This can be handled fairly cleanly in the SPARQL provided we can identify a namespace of variable names which are not valid as JSON object keys.
We are going to need to maintain a permanent but changing list of mappings for the structured apps. The AppUpdater object lives for a single request so it is not a suitable place to hold this information.
I'm trying not to pull too much into the RDF rather than using the existing dump files; there is a lot of information in there and I don't really want to just rewrite it all in Turtle. But I want a structured app other than Info, and I can't use Registration because that will need to be special-cased on set in any case.
This is still limited to a few hardcoded Apps with handwritten SPARQL queries. Updates to Registration will have to be handled specially.
This mostly consists of validation; only the class and deleted fields can be changed for now.
Blank nodes behave strangely within SPARQL INSERTS: the spec says that blank nodes in inserted triples must be new blank nodes distinct from any other. Jena's mechanism for substitution into queries does not override this, so if an existing blank is substituted into an INSERT the inserted triples reference a new blank instead. This means we cannot practically use blank nodes at all. For now, create FP nodes under an ACS namespace. There are three sensible options here: urn:uuid, an ACS namespace, and a namespace local to the installation. Using urn:uuid causes issues with relative URL resolution rules. Using a local namespace may be a better idea in the long run, although ideally we would want to keep ACS objects under the ACS prefix.
If we are not going to create config entries as blanks node, they need IRIs; if they are going to have IRIs they need UUIDs generating and might as well be F+ objects. Create a class Document ⊂ Individual and make ConfigEntry a subclass. * Use the ConfigEntry's own UUID for the etag. * Remove the Instant handling for now. Ideally it would come back later applied to all Individuals but we don't need it for now. * Config entries are now F+ objects so they have Registration entries. We must not generate these for Registration entries or we have an infinite loop. These could be supplied virtually as they are immutable. * Delete orphaned structured config entries. * Adjust some of the namespacing and use relative URLs within the Turtle rather than a plethora of namespaces.
c4f71ff to
e56d40c
Compare
KavanPrice
requested changes
Mar 31, 2026
acs-metadb/src/main/java/uk/co/amrc/factoryplus/metadb/db/AppMapper.java
Outdated
Show resolved
Hide resolved
Contributor
|
The move to this |
KavanPrice
approved these changes
Apr 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Start work on the mapping from structured RDF into the existing JSON config entries. Create a framework in which certain Apps are classified as Structured application, which means their JSON config entries are backed by RDF structure. Support pushing updates to the JSON back into the RDF, and regenerating the JSON when the RDF has changed.
For now only Object registration, General info and Sparkplug address are supported as Structured apps, and their mappings are hard-coded. Long-term these should be generated from some form of schema entry.
The regeneration code is rather simple-minded and regenerates all possible config entries on any change. This could be optimised in the future but the Jena ModelChangedListener facility is not as helpful as it could be so it will not be entirely straightforward, especially where config entries make use of the class structure. We must generate entries eagerly because we need to (eventually) support push notify.