Class ConverterContext
Purposes
An object of this class serves mostly three purposes:
- providing
IConverterobjects as needed; - allow dereferencing “global” LinkML objects;
- providing a resolution/compaction service for CURIEs.
Provider of IConverter objects
The context holds a list of all the known LinkML classes and types, along
with their respective converter objects. So whenever converting an object of
type Foo is required, the appropriate converter needed for such a
conversion can be obtained from the context (through either
getConverter(Class) or getConverter(Slot)).
The context has built-in knowledge of LinkML’s basic scalar types. For the
other types (classes or enumerations), the client code can provide its own
converters through the addConverter(IConverter) method. In the
absence of an explicitly registered converter for a type, the context will
automatically provide a default. It is expected that in most cases, the
default converter should be enough.
Dereferencing global LinkML objects
“Dereferencing” is what must happen when converting the value of a LinkML
slot that (1) is expected to contain a globally unique object (an object
belonging to a class that has an identifier slot) and (2) is not
“inlined”. In such a case, in JSON/YAML serialisations the slot will actually
contain only the identifier of the object, the actual object
expectedly being represented elsewhere in the instance data. Dereferencing is
the process of finding the global object corresponding to a given identifier,
so that it can be assigned to the slot.
One problem that may arise when dereferencing is that an identifier may point to a global object that has not been parsed and converted yet, depending on (1) where the global object is defined and (2) the order in which we process the JSON/YAML tree. For example, when parsing/converting a LinkML schema: when parsing a class definition, we are likely to encounter a reference to a slot definition, but we may not have parsed that slot definition yet. (And we cannot solve that problem simply by ensuring that we always parse slot definitions first, because slot definitions may in turn contains references to a class definitions.)
This context object maintains a cache (implemented by the ObjectCache
class) of all the global objects, and will take care of resolving references
to those objects – either immediately if possible (if the referenced object
has been seen before and therefore is already in the cache), or in a
post-parsing finalisation step (when we are sure that all objects contained
in the parsed document have been seen, so all references should be
resolvable).
CURIE resolution
It is expected that short identifiers, otherwise known as “CURIEs”, will be used a lot within LinkML instance data. This context object acts as a prefix manager to help automatically resolve CURIEs into their full-length form (when deserialising) and conversely compact IRIs into their short form (when serialising).
Lifecycle
As can be inferred from the duties outlined in the previous section, the converter object has a central role throughout the LinkML-Java runtime. One such object must be created before doing virtually anything with LinkML instance data.
The same converter object must be used for all operations pertaining to the same set of LinkML instance data, even if the instance data is physically spread over several JSON or YAML files. For example, when parsing a LinkML schema, the same context must be used for the root schema and for all the imported schemas, if any.
Conversely, in most cases it will not be desirable to reuse an existing context to manipulate instance data that are not related to the instance data for which the existing context has already been used.
Of note, once instance data have been parsed, the parsed objects are self-sufficient; that is, they do not require the context to be kept around. However, if the data is to be serialised back, it might be a good idea to reuse the same context for serialisation as the one that was used for deserialisation, because it will ensure that the same prefixes are used for the compaction of CURIEs.
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoidaddConverter(Class<?> type) Deprecated.voidaddConverter(IConverter converter) Registers a pre-built converter.voidRegisters a prefix.Compacts an IRI into a shortened identifier (“CURIE“).voidPerforms all delayed assignments.voidfinalizeAssignments(boolean failOnMissing) Performs all delayed assignments, optionally failing if an assignment refers to a missing object.getConverter(Class<?> type) Gets the converter for objects of the given type.getConverter(Slot slot) Gets the converter for the type of object expected by the given slot.<T> TDereferences a global object, optionally creating it if does not already exist.Dereferences a global object and assigns it to a slot on another object.voidDereferences several global objects and assigns them to a list.Resolves a shortened identifier (“CURIE”) into a full-length IRI.voidSets a custom provider for converters of complex objects.
-
Constructor Details
-
ConverterContext
public ConverterContext()
-
-
Method Details
-
setDefaultObjectConverterProvider
Sets a custom provider for converters of complex objects.The default provider systematically creates a
ObjectConverterinstance whenever a converter for a given type is required. Setting a custom provider is intended to allow client code to override that behaviour (typically, to use a custom subclass ofObjectConverterinstead).- Parameters:
provider- The custom provider to use.
-
addConverter
Deprecated.Use eitheraddConverter(IConverter)with an explicitly instantiatedObjectConverter, orgetConverter(Class)(which will automatically trigger the registration of a newly instantiated converter if needed).Registers a converter for objects of the given class.- Parameters:
type- The class for which to register a converter. A default converter will be automatically created.
-
addConverter
Registers a pre-built converter.This may be used to override the default converter that would normally be automatically instantiated the first time a converter for a given type is requested through
getConverter(Class).- Parameters:
converter- The converter to register.
-
getConverter
Gets the converter for objects of the given type.If no converter able to handle the type has been previously registered, then the context will attempt to automatically instantiate and register a default converter. The default converter will be either:
- the custom converter as indicated by a
Converterannotation on the type (or any parent type); - the default
EnumConverterif the type is an enumeration type; - the default
ObjectConverterif the type is anything else.
- Parameters:
type- The type to query.- Returns:
- The registered converter for the type.
- Throws:
LinkMLRuntimeException- If the type is configured to use a custom converter that could not be instantiated.
- the custom converter as indicated by a
-
getConverter
Gets the converter for the type of object expected by the given slot.This is mostly equivalent to calling
getConverter(Class)on the “inner type” of the slot, except that it takes into account anyConverterannotation carried by the slot.- Parameters:
slot- The slot for which a converter is needed.- Returns:
- The appropriate converter.
- Throws:
LinkMLRuntimeException- If the slot (or its type) is configured to use a custom converter, but the custom converter could not be instantiated.
-
addPrefix
Registers a prefix. Any prefix declared here will become resolvable by theresolve(String)method, or conversely usable by thecompact(String)method.One of the responsibilities of the
ConverterContextis to provide a prefix resolution service, so that any shortened identifier (“CURIE“) found within LinkML instance data can be resolved into a full-length identifier.This method is used internally throughout LinkML-Java to feed the prefix resolution service. Client code may also use it as needed to provide its own prefixes (for example, if the client code has out-of-band knowledge of which prefixes will be used within the instance data it will manipulate).
- Parameters:
name- The prefix name.prefix- The corresponding IRI prefix.
-
resolve
-
compact
-
getObject
Dereferences a global object, optionally creating it if does not already exist.- Type Parameters:
T- The type of object to dereference.- Parameters:
type- The type of object to dereference.name- The name to resolve into a dereferenced object.create- Iftrue, a new object of the given type and with the given name will be created and added to the global context if an object with that name did not already exist.- Returns:
- The dereferenced object, or
nullif the object did not already exist andcreateisfalse. - Throws:
LinkMLRuntimeException- If the object type is not suitable for global objects, or if we cannot create the object as needed.
-
getObject
Dereferences a global object and assigns it to a slot on another object.If the desired object does not exist in the context, the assignment will take place when the
finalizeAssignments()method is called.- Parameters:
slot- The slot to which to assign the dereferenced object.name- The name to resolve into a dereferenced object.target- The object to which to assign the dereferenced object.- Returns:
- The dereferenced object, or
nullif the object does not exist in the context at the time this method is called. - Throws:
LinkMLRuntimeException- If the object type is not suitable for global objects, or if the retrieved object cannot be assigned to the slot.
-
getObjects
public void getObjects(Class<?> type, List<String> names, List<Object> target) throws LinkMLRuntimeException Dereferences several global objects and assigns them to a list.If any of the referenced objects does not exist in the context, it will be assigned to the target list when the
finalizeAssignments()method is called.- Parameters:
type- The type of the objects to dereference.names- The names to resolve into dereferenced objects.target- The list to which the dereferenced objects should be assigned.- Throws:
LinkMLRuntimeException- If the object type is not suitable for global objects.
-
finalizeAssignments
Performs all delayed assignments.A delayed assignment is an assignment requested through the
getObject(Slot, String, Object)orgetObjects(Class, List, List)methods, which could not be performed at the time that method was called because the requested object was not known to the context yet.If a referenced object is still unknown when delayed assignments are performed, an empty object of the desired type and with the referenced identifier will be automatically created. Use
finalizeAssignments(boolean)to treat missing references as an error instead.It is safe to call this method repeatedly – delayed assignments that were already performed by a previous call will not be repeated.
- Throws:
LinkMLRuntimeException- If an assignment cannot be performed.
-
finalizeAssignments
Performs all delayed assignments, optionally failing if an assignment refers to a missing object.- Parameters:
failOnMissing- Iftrueand a delayed assignment refers to an object that is either unknown in the global context, or of a different type than expected, this will be treated as a fatal error.- Throws:
LinkMLRuntimeException- If an assignment cannot be performed (including for an invalid reference, iffailOnMissingistrue.
-
addConverter(IConverter)with an explicitly instantiatedObjectConverter, orgetConverter(Class)(which will automatically trigger the registration of a newly instantiated converter if needed).