Class ConverterContext


  • public class ConverterContext
    extends Object
    Global context for converting LinkML objects (as parsed from a JSON/YAML document) into their corresponding Java objects, and the other way round.

    Purposes

    An object of this class serves mostly three purposes:

    • providing IConverter objects 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 Detail

      • ConverterContext

        public ConverterContext()
    • Method Detail

      • addConverter

        @Deprecated
        public void addConverter​(Class<?> type)
        Deprecated.
        Use either addConverter(IConverter) with an explicitly instantiated ObjectConverter, or getConverter(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

        public void addConverter​(IConverter converter)
        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

        public IConverter getConverter​(Class<?> type)
                                throws LinkMLRuntimeException
        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 Converter annotation on the type (or any parent type);
        • the default EnumConverter if the type is an enumeration type;
        • the default ObjectConverter if 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.
      • getConverter

        public IConverter getConverter​(Slot slot)
                                throws LinkMLRuntimeException
        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 any Converter annotation 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

        public void addPrefix​(String name,
                              String prefix)
        Registers a prefix. Any prefix declared here will become resolvable by the resolve(String) method, or conversely usable by the compact(String) method.

        One of the responsibilities of the ConverterContext is 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

        public String resolve​(String name)
        Resolves a shortened identifier (“CURIE”) into a full-length IRI.
        Parameters:
        name - The shortened identifier to resolve.
        Returns:
        The resolved IRI, or the original string if (1) it was not a shortened identifier to begin with or (2) the prefix is unknown.
      • compact

        public String compact​(String iri)
        Compacts an IRI into a shortened identifier (“CURIE“).
        Parameters:
        iri - The IRI to shorten.
        Returns:
        The shortened identifier, or the original string if there no known suitable prefix for the given IRI.
      • getObject

        public <T> T getObject​(Class<T> type,
                               String name,
                               boolean create)
                        throws LinkMLRuntimeException
        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 - If true, 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 null if the object did not already exist and create is false.
        Throws:
        LinkMLRuntimeException - If the object type is not suitable for global objects, or if we cannot create the object as needed.
      • getObject

        public Object getObject​(Slot slot,
                                String name,
                                Object target)
                         throws LinkMLRuntimeException
        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 null if 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

        public void finalizeAssignments()
                                 throws LinkMLRuntimeException
        Performs all delayed assignments.

        A delayed assignment is an assignment requested through the getObject(Slot, String, Object) or getObjects(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

        public void finalizeAssignments​(boolean failOnMissing)
                                 throws LinkMLRuntimeException
        Performs all delayed assignments, optionally failing if an assignment refers to a missing object.
        Parameters:
        failOnMissing - If true and 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, if failOnMissing is true.