Class ContextRepository
Context entities that coordinates
the Redis cache and the OrientDB database.
Read strategy: Redis-first with database fallback.
Redis is checked first for performance; on a miss the authoritative
OrientDB source is queried via ContextManagement.
Write strategy: The database write is delegated to
ContextManagement; afterwards the appropriate Redis cache entry is
invalidated or updated so that subsequent reads stay consistent.
This class has zero auth logic. The policy decision (which role the
caller holds, whether metadata should be included) is always made externally and passed in
as plain parameters. The raw readRaw/allRaw variants return unfiltered data
for internal callers (e.g. InstanceEnvironmentRegistry,
EntityManagement, RelationManagement, JsonQuery).
The filtered read(UUID, int, ContextProjection, ContextLifecycle)
variant applies the visibility rules supplied by
ContextPolicyEnforcementPoint.
- Author:
- Luca Frosini (ISTI - CNR)
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final recordProjection settings computed by the caller (typically the PEP). -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionall(boolean polymorphic, ContextRepository.ContextProjection projection, int limit, int offset, org.gcube.informationsystem.resourceregistry.api.rest.ContextLifecycle lifecycle) Returns a paginated, filtered list of all contexts as aPageResult.allRawUnbounded(boolean polymorphic, org.gcube.informationsystem.resourceregistry.api.rest.ContextLifecycle lifecycle) Returns the raw, unfiltered JSON array of every context matching the given lifecycle, with no pagination cap.changeState(UUID uuid, String json) Applies the validated tracked fields of a Context merge patch and refreshes either the affected cache entry or the complete cached tree after structural changes.Creates the context identified byuuidwith the provided JSON representation.Creates a Context, optionally preserving themetadataobject already present in the submitted JSON instead of autofilling it from the current caller and clock.Creates a Context, choosing whether the additional fields take part in the idempotency comparison of a repeated creation.voidLogically deletes the Context identified byuuidand invalidates the complete Context cache so the next read rebuilds it at the new authoritative version.org.gcube.com.fasterxml.jackson.databind.node.ObjectNodefilterContextNode(org.gcube.com.fasterxml.jackson.databind.node.ObjectNode ctx, ContextRepository.ContextProjection projection) Applies context visibility projection to a raw context JSON object.org.gcube.informationsystem.contexts.reference.entities.ContextgetContextByPath(String path) Returns theContextidentified by the given path (e.g.org.gcube.informationsystem.contexts.reference.entities.ContextgetContextByPath(String path, org.gcube.informationsystem.resourceregistry.api.rest.ContextLifecycle lifecycle) Returns theContextidentified by the given path — its current path or, failing that, one of its previous paths.getDescendantEffectiveStates(UUID contextUUID) Resolves theeffectiveStateof all descendants (recursive children) for a given context, in a single bulk lookup.getDescendantUUIDs(UUID contextUUID) Resolves all descendants (recursive children) UUIDs for a given context.getParentUUID(UUID uuid) Resolves the UUID of the parent of the given context by reading its raw JSON representation directly.getParentUUID(UUID uuid, org.gcube.informationsystem.resourceregistry.api.rest.ContextLifecycle lifecycle) Resolves a Context's parent strictly within the requested lifecycle topology.getPreviousPaths(UUID uuid) Returns the set of previous paths for the given context UUID.booleanReturns the current status of the cache bypass flag.static booleanisRepresentationField(String field) Returns whether a top-level field belongs to the Context representation; any other field is an additional field, read and written by the global managers only.query(String jsonQuery, ContextRepository.ContextProjection projection, int limit, int offset, org.gcube.informationsystem.resourceregistry.api.rest.ContextLifecycle lifecycle) Executes a JSON query against the Context collection, returning a paginated, role-filteredPageResult.read(UUID uuid, int depth, ContextRepository.ContextProjection projection) Returns the filtered JSON array for the context identified byuuid, applying the visibility rules described byprojection.read(UUID uuid, int depth, ContextRepository.ContextProjection projection, org.gcube.informationsystem.resourceregistry.api.rest.ContextLifecycle lifecycle) Returns a filtered JSON array for a context read, with optional hierarchical context routing for cemetery-capable reads.org.gcube.informationsystem.contexts.reference.entities.ContextreadAsContext(UUID uuid) Returns the deserializedContextfor the given UUID.org.gcube.informationsystem.contexts.reference.entities.ContextreadAsContext(UUID uuid, org.gcube.informationsystem.resourceregistry.api.rest.ContextLifecycle lifecycle) Returns the deserialized Context for the given UUID within the requested lifecycle topology.readContextPath(UUID uuid) Returns the full context path (e.g.readHistory(UUID uuid, org.gcube.informationsystem.resourceregistry.api.rest.ContextLifecycle lifecycle) Reads the reverse-chronological audit trail of the Context identified byuuid.protected StringreadRaw(UUID uuid, org.gcube.informationsystem.resourceregistry.api.rest.ContextLifecycle lifecycle) Returns the raw canonical JSON for the context identified byuuid, restricted to the given lifecycle scope.resolveContextUUIDByPath(String path, org.gcube.informationsystem.resourceregistry.api.rest.ContextLifecycle lifecycle) Resolves the UUID of a context by path, with optional hierarchical context routing.voidsetCacheBypass(boolean bypass) Sets the cache bypass flag.voidWarms up the entire context cache by loading all live contexts from the database and saving them to Redis.
-
Constructor Details
-
ContextRepository
public ContextRepository()Public constructor to instantiate ContextRepository.
-
-
Method Details
-
setCacheBypass
public void setCacheBypass(boolean bypass) Sets the cache bypass flag. Used exclusively during unit/integration testing to verify data symmetry with and without Redis.- Parameters:
bypass- true to bypass the cache, false to enable normal Redis-first behavior
-
isCacheBypass
public boolean isCacheBypass()Returns the current status of the cache bypass flag.- Returns:
- true if cache is bypassed, false otherwise
-
isRepresentationField
Returns whether a top-level field belongs to the Context representation; any other field is an additional field, read and written by the global managers only.- Parameters:
field- the top-level field name- Returns:
trueif the field is one of the representation
-
warmUpCache
public void warmUpCache() throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryExceptionWarms up the entire context cache by loading all live contexts from the database and saving them to Redis.- Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if database read or caching fails
-
readRaw
protected String readRaw(UUID uuid, org.gcube.informationsystem.resourceregistry.api.rest.ContextLifecycle lifecycle) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Returns the raw canonical JSON for the context identified byuuid, restricted to the given lifecycle scope. Redis is checked first (unlesslifecyclerequires a cemetery-aware read); on a miss the database is queried.- Parameters:
uuid- the UUID of the context to readlifecycle- the lifecycle scope to read within (LIVE, DELETED, or ALL)- Returns:
- raw JSON string
- Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if the context cannot be found or read
-
read
public String read(UUID uuid, int depth, ContextRepository.ContextProjection projection) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Returns the filtered JSON array for the context identified byuuid, applying the visibility rules described byprojection.- Parameters:
uuid- the UUID of the context to readdepth- requested traversal depth (0, positive integer, or-1for unlimited)projection- projection settings for the response- Returns:
- filtered JSON array string
- Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if the root context cannot be found or read
-
read
public String read(UUID uuid, int depth, ContextRepository.ContextProjection projection, org.gcube.informationsystem.resourceregistry.api.rest.ContextLifecycle lifecycle) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Returns a filtered JSON array for a context read, with optional hierarchical context routing for cemetery-capable reads.- Parameters:
uuid- the UUID of the context to readdepth- the depth of descendants to expandprojection- the visibility projection to applylifecycle- the context lifecycle configuration (LIVE, DELETED, ALL, DEFAULT)- Returns:
- JSON representation of the requested context hierarchy
- Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if the lookup fails
-
readAsContext
public org.gcube.informationsystem.contexts.reference.entities.Context readAsContext(UUID uuid) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Returns the deserializedContextfor the given UUID. Delegates toreadRaw(UUID, ContextLifecycle)(Redis-first, database fallback), falling back to an uncached cemetery-aware (ALL) lookup if the LIVE lookup fails — e.g. when walking the ancestor chain of an already-deleted target Context (seeContextPolicyEnforcementPoint#resolveParentUUIDFromExistingContext(UUID)).- Parameters:
uuid- the UUID of the context to read- Returns:
- deserialized
Context - Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if the context cannot be found or deserialized
-
readAsContext
public org.gcube.informationsystem.contexts.reference.entities.Context readAsContext(UUID uuid, org.gcube.informationsystem.resourceregistry.api.rest.ContextLifecycle lifecycle) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Returns the deserialized Context for the given UUID within the requested lifecycle topology.- Parameters:
uuid- the UUID of the Context to readlifecycle- the lifecycle topology in which the Context must exist- Returns:
- the matching Context
- Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if the Context cannot be found or deserialized
-
allRawUnbounded
public String allRawUnbounded(boolean polymorphic, org.gcube.informationsystem.resourceregistry.api.rest.ContextLifecycle lifecycle) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Returns the raw, unfiltered JSON array of every context matching the given lifecycle, with no pagination cap. Intended for internal system-wide consumers that must capture the complete persisted state (e.g. System Dump) — never exposed through a role-filtered REST endpoint.- Parameters:
polymorphic- whether to include subclasses of Contextlifecycle- the lifecycle filter to apply- Returns:
- raw JSON array string containing every matching context
- Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if contexts cannot be read
-
all
public PageResult all(boolean polymorphic, ContextRepository.ContextProjection projection, int limit, int offset, org.gcube.informationsystem.resourceregistry.api.rest.ContextLifecycle lifecycle) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Returns a paginated, filtered list of all contexts as aPageResult.Uses the "peek +1" strategy: requests
limit + 1items from the backing store and drops the extra item from the returned page when present. Visibility filtering viafilterContextNode(ObjectNode, ContextProjection)is applied to each entry before building the response JSON.- Parameters:
polymorphic- whether to include subclasses of Contextprojection- projection settings for each context entrylimit- effective page size (>= 1)offset- zero-based start index (>= 0)lifecycle- the lifecycle filter to apply- Returns:
- a
PageResultwith the page JSON and pagination state - Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if contexts cannot be read
-
query
public PageResult query(String jsonQuery, ContextRepository.ContextProjection projection, int limit, int offset, org.gcube.informationsystem.resourceregistry.api.rest.ContextLifecycle lifecycle) throws org.gcube.informationsystem.resourceregistry.api.exceptions.queries.InvalidQueryException, org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Executes a JSON query against the Context collection, returning a paginated, role-filteredPageResult.Unlike
all(boolean, ContextProjection, int, int, ContextLifecycle), this always queries the database directly (Redis is a plain UUID-keyed cache, not indexed by arbitrary properties, so it cannot serve an arbitrary JSON query). Uses the same "peek +1" pagination strategy: requestslimit + 1items fromContextManagement.query(String)and drops the extra item from the returned page when present. Complete Context results are filtered viafilterContextNode(ObjectNode, ContextProjection); flat_emitprojection rows retain their query-defined shape after privacy masking.- Parameters:
jsonQuery- the JSON query payload describing the Context search criteriaprojection- projection settings for each context entrylimit- effective page size (>= 1)offset- zero-based start index (>= 0)lifecycle- the lifecycle filter to apply (selects the environment opened byContextManagement)- Returns:
- a
PageResultwith the page JSON and pagination state - Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.queries.InvalidQueryException- if the query is invalid or syntactically incorrectorg.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if contexts cannot be read
-
readContextPath
public String readContextPath(UUID uuid) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Returns the full context path (e.g./gcube/devsec/devVRE) for the given UUID by reading the context and returning its persistentpathfield.- Parameters:
uuid- the UUID of the context- Returns:
- the path string, or
nullif not found - Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if the path cannot be resolved
-
getContextByPath
public org.gcube.informationsystem.contexts.reference.entities.Context getContextByPath(String path) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Returns theContextidentified by the given path (e.g./gcube/devsec/devVRE).- Parameters:
path- the fully-qualified context path- Returns:
- the matching
Context - Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if no context matches the path
-
getContextByPath
public org.gcube.informationsystem.contexts.reference.entities.Context getContextByPath(String path, org.gcube.informationsystem.resourceregistry.api.rest.ContextLifecycle lifecycle) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Returns theContextidentified by the given path — its current path or, failing that, one of its previous paths. Live contexts are resolved from Redis first; a miss, and any lifecycle reaching the cemetery, is read from the database. A live Context and deleted ones may hold the same path: withContextLifecycle.ALLa live Context, matched by its current or by a previous path, always wins over a deleted one.- Parameters:
path- the fully-qualified context pathlifecycle- the context lifecycle configuration (LIVE, DELETED, ALL, DEFAULT)- Returns:
- the matching
Context - Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if no context matches the path
-
resolveContextUUIDByPath
public UUID resolveContextUUIDByPath(String path, org.gcube.informationsystem.resourceregistry.api.rest.ContextLifecycle lifecycle) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Resolves the UUID of a context by path, with optional hierarchical context routing.- Parameters:
path- the fully-qualified context pathlifecycle- the context lifecycle configuration (LIVE, DELETED, ALL, DEFAULT)- Returns:
- the resolved
UUIDof the context - Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if the path cannot be resolved to a context
-
getPreviousPaths
public Set<String> getPreviousPaths(UUID uuid) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Returns the set of previous paths for the given context UUID.- Parameters:
uuid- the context UUID- Returns:
- the set of previous paths, or an empty set if none
- Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if the lookup fails
-
getDescendantUUIDs
public Set<String> getDescendantUUIDs(UUID contextUUID) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Resolves all descendants (recursive children) UUIDs for a given context. Delegates to the appropriate cache or database layer to preserve distributed coherence.- Parameters:
contextUUID- the parent context UUID- Returns:
- a set of descendant UUID strings
- Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if the lookup fails
-
getDescendantEffectiveStates
public Map<String,org.gcube.informationsystem.contexts.reference.ContextState> getDescendantEffectiveStates(UUID contextUUID) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Resolves theeffectiveStateof all descendants (recursive children) for a given context, in a single bulk lookup. MirrorsgetDescendantUUIDs(UUID)exactly (same cache-first, DB-fallback strategy) but keeps each descendant'seffectiveStateinstead of discarding it.- Parameters:
contextUUID- the parent context UUID- Returns:
- a map of descendant UUID string to its
effectiveState - Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if the lookup fails
-
create
public ContextCreationResult create(UUID uuid, String json) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Creates the context identified byuuidwith the provided JSON representation.To adhere strictly to HTTP PUT idempotency:
- If the context does not exist, a new context is created and registered.
- If the context already exists, the incoming representation is compared with the existing one.
If their persisted creation fields are identical, the existing representation is returned (no-op).
Otherwise, a
AlreadyPresentException(409 Conflict) is thrown.
- Parameters:
uuid- the UUID of the context to createjson- the JSON representation of the context- Returns:
- the
ContextCreationResultwrapping the resulting context JSON (from the database) and whether a brand new Context was registered - Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if the operation fails, or if a different representation already exists
-
create
public ContextCreationResult create(UUID uuid, String json, boolean preservePassedMetadata) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Creates a Context, optionally preserving themetadataobject already present in the submitted JSON instead of autofilling it from the current caller and clock. Used exclusively by System Restore to reproduce the original audit trail of a dumped Context.- Parameters:
uuid- the UUID of the context to createjson- the JSON representation of the contextpreservePassedMetadata-trueto preserve submitted metadata,falseto autofill- Returns:
- the
ContextCreationResultwrapping the resulting context JSON (from the database) and whether a brand new Context was registered - Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if the operation fails, or if a different representation already exists
-
create
public ContextCreationResult create(UUID uuid, String json, boolean preservePassedMetadata, boolean compareAdditionalFields) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Creates a Context, choosing whether the additional fields take part in the idempotency comparison of a repeated creation. They do for a caller that reads and writes them; for any other caller the stored ones are ignored by the comparison and left untouched.- Parameters:
uuid- the UUID of the context to createjson- the JSON representation of the contextpreservePassedMetadata-trueto preserve submitted metadata,falseto autofillcompareAdditionalFields- whether the additional fields are part of the idempotency comparison- Returns:
- the
ContextCreationResultwrapping the resulting context JSON (from the database) and whether a brand new Context was registered - Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if the operation fails, or if a different representation already exists
-
readHistory
public String readHistory(UUID uuid, org.gcube.informationsystem.resourceregistry.api.rest.ContextLifecycle lifecycle) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Reads the reverse-chronological audit trail of the Context identified byuuid.- Parameters:
uuid- the UUID of the contextlifecycle- the context lifecycle configuration (LIVE, DELETED, ALL, DEFAULT)- Returns:
- JSON array string of history events, newest first
- Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if the operation fails
-
getParentUUID
public UUID getParentUUID(UUID uuid) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Resolves the UUID of the parent of the given context by reading its raw JSON representation directly.Context.getParent()cannot be used for this: the information-system-model annotates it@JsonGetter-only (serialization side) with an explicit@JsonIgnoreonsetParent(UUID), so it is never populated byElementMapper.unmarshal(java.lang.Class<El>, java.io.Reader)regardless of what the source JSON contains.Tries the cached LIVE lookup first (the common case, e.g. resolving the
InstanceEnvironmentparent chain for a still-live Context during a normal delete). Falls back to an uncached cemetery-aware (ALL) lookup only if that fails, so that the same resolution also works when the target Context is already in the cemetery (e.g. purging an already-deleted Context, whose ownInstanceEnvironmentteardown still needs to resolve its parent chain).- Parameters:
uuid- the UUID of the context whose parent to resolve- Returns:
- the parent's UUID, or
nullif the context has no parent - Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if the context cannot be read
-
getParentUUID
public UUID getParentUUID(UUID uuid, org.gcube.informationsystem.resourceregistry.api.rest.ContextLifecycle lifecycle) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Resolves a Context's parent strictly within the requested lifecycle topology.- Parameters:
uuid- the UUID of the Context whose parent to resolvelifecycle- the lifecycle topology in which the target must exist- Returns:
- the parent's UUID, or
nullwhen the target is a Root Context - Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if the target cannot be read in that topology
-
changeState
public String changeState(UUID uuid, String json) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Applies the validated tracked fields of a Context merge patch and refreshes either the affected cache entry or the complete cached tree after structural changes.- Parameters:
uuid- the UUID of the context whose state is being changedjson- the validated JSON merge patch containing only tracked fields- Returns:
- the resulting context JSON (from the database)
- Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if the operation fails
-
delete
public void delete(UUID uuid) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException Logically deletes the Context identified byuuidand invalidates the complete Context cache so the next read rebuilds it at the new authoritative version.- Parameters:
uuid- the UUID of the live Context to move to the cemetery- Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- if the operation fails
-
filterContextNode
public org.gcube.com.fasterxml.jackson.databind.node.ObjectNode filterContextNode(org.gcube.com.fasterxml.jackson.databind.node.ObjectNode ctx, ContextRepository.ContextProjection projection) Applies context visibility projection to a raw context JSON object.Policy:
historyis always hidden in standard REST responses.state/effectiveStateare always preserved.- Non-privileged responses remove additional custom properties.
- Metadata is removed when not requested, or privacy-masked for non-privileged users when requested.
- Parameters:
ctx- the context JSON node to filterprojection- the projection settings to apply- Returns:
- the filtered context JSON node
-