Class DefaultMappings

java.lang.Object
org.openehealth.ipf.commons.map.DefaultMappings
All Implemented Interfaces:
Mappings
Direct Known Subclasses:
SpringMappings

public class DefaultMappings extends Object implements Mappings
In-memory Mappings implementation, backed by one forward and one reverse index per mapping. Both indices are built once, when the mapping is registered, and are never rebuilt afterwards — which is what keeps loading a second mapping source from disturbing the mappings loaded from the first.

Reads are lock-free against an immutable snapshot; registration is serialized, and validates each mapping against what is already registered - which is what lets a lookup follow delegations and composites without checking them again.

This is the extension point for wiring the mapping service into a container: a subclass may add whatever way of naming a source that container prefers and calls load(URL). See SpringMappings in ipf-commons-spring, which takes Spring Resources.

Since:
6.0
  • Constructor Details

    • DefaultMappings

      public DefaultMappings()
      Applies every discovered MappingFunctionProvider, so that a mapping file shipped with the functions it names works without any configuration.
  • Method Details

    • functions

      public MappingFunctions functions()
      Specified by:
      functions in interface Mappings
      Returns:
      read access to the registered functions; register them with registerFunction(String, java.util.function.Function)
    • registerFunction

      public void registerFunction(String name, Function<String,String> function)
      Registers a function that Unmatched.Computed fallbacks can name, replacing any registered before under that name. Register it before loading a source that names it: a source naming an unknown function is rejected as it is read.
      Parameters:
      name - function name
      function - the function; it must tolerate a null argument
    • load

      public void load(URL url)
      Reads a mapping source and registers everything it contains.
      Parameters:
      url - location of the source; the MappingLoader is selected by its file extension
    • load

      public void load(URL url, String format)
      Reads a mapping source in a format named explicitly, for a source whose name does not identify one - a ConceptMap fetched over HTTP, a file called gender.xml - or where the file extension is not the loader the caller wants.
      Parameters:
      url - location of the source
      format - a format id such as xml or conceptmap-r4-json, or null to select the loader by file extension
    • load

      public void load(URL url, MappingLoader loader)
      Reads a mapping source with an explicitly provided loader, which need not be one the ServiceLoader can see.
    • register

      public void register(Mapping mapping, URI source)
      Registers a single mapping, validating it against the model's constraints.
      Parameters:
      mapping - the mapping to register
      source - where it was read from, for diagnostics; may be null
    • clear

      public void clear()
      Forgets every mapping. The functions stay registered: they are configuration, which mapping sources loaded afterwards refer to just as before.
    • mapping

      public Optional<Mapping> mapping(String mapping)
      Specified by:
      mapping in interface Mappings
      Parameters:
      mapping - mapping name
      Returns:
      the mapping itself, or empty if no mapping of that name is registered
    • mappingNames

      public Set<String> mappingNames()
      Specified by:
      mappingNames in interface Mappings
      Returns:
      the names of all registered mappings, in registration order
    • mappingsFor

      public List<Mapping> mappingsFor(String keySystem, String valueSystem)
      Description copied from interface: Mappings
      Finds mappings by the code systems they translate between, rather than by name.

      A caller holding a code to translate knows which code system it is in and which one it wants, not what the mapping happens to be called - which is the shape of FHIR's ConceptMap/$translate, and the only way to reach a mapping read from a source that names itself, such as a ConceptMap resource. Either argument may be null for "any", so passing only a key system finds every mapping that translates out of it.

      This is a scan over the registered mappings, not an index: resolve the mapping once and keep it, rather than calling this per message.

      Specified by:
      mappingsFor in interface Mappings
      Parameters:
      keySystem - identifier of the key code system, or null for any
      valueSystem - identifier of the value code system, or null for any
      Returns:
      the matching mappings, in registration order
    • lookup

      public Optional<String> lookup(String mapping, String key)
      Description copied from interface: Mappings
      Looks up a key without applying the mapping's unmatched behavior.
      Specified by:
      lookup in interface Mappings
      Parameters:
      mapping - mapping name
      key - left side of the mapping
      Returns:
      the value declared for that key, empty if the mapping declares no entry for it
    • lookupReverse

      public Optional<String> lookupReverse(String mapping, String value)
      Description copied from interface: Mappings
      Looks up a value without applying the mapping's reverse unmatched behavior.
      Specified by:
      lookupReverse in interface Mappings
      Parameters:
      mapping - mapping name
      value - right side of the mapping
      Returns:
      the key declared for that value, empty if the mapping declares no invertible entry for it
    • unmatched

      public Optional<String> unmatched(String mapping, String key)
      Description copied from interface: Mappings
      Applies a mapping's unmatched behavior to a key, without looking the key up first.
      Specified by:
      unmatched in interface Mappings
      Parameters:
      mapping - mapping name
      key - left side of the mapping
      Returns:
      the fallback value, empty if the mapping declares no fallback
    • reverseUnmatched

      public Optional<String> reverseUnmatched(String mapping, String value)
      Description copied from interface: Mappings
      Applies a mapping's reverse unmatched behavior to a value, without looking it up first.
      Specified by:
      reverseUnmatched in interface Mappings
      Parameters:
      mapping - mapping name
      value - right side of the mapping
      Returns:
      the fallback key, empty if the mapping declares no reverse fallback
    • translate

      public Optional<Translation> translate(String mapping, String key)
      Description copied from interface: Mappings
      Maps a key like Mappings.map(String, String), and says which code system the answer belongs to and how it is displayed - what a caller needs to build a coded value from it.

      The system is that of the mapping which actually answered: a composite answers with the system of the part that had the answer, a delegating fallback with that of the mapping delegated to. An identity fallback answers with the key itself, and so with the key system.

      The default implementation knows none of that and answers with the mapping's value system and no display; DefaultMappings overrides it.

      Specified by:
      translate in interface Mappings
      Parameters:
      mapping - mapping name
      key - left side of the mapping
      Returns:
      the mapped value with its system and display, falling back to the mapping's unmatched behavior
    • translateReverse

      public Optional<Translation> translateReverse(String mapping, String value)
      Description copied from interface: Mappings
      Maps a value back like Mappings.mapReverse(String, String), and says which code system the answer belongs to and how it is displayed.
      Specified by:
      translateReverse in interface Mappings
      Parameters:
      mapping - mapping name
      value - right side of the mapping
      Returns:
      the key mapping to that value with its system and display, falling back to the mapping's reverse unmatched behavior
      See Also:
    • keySystem

      public Optional<String> keySystem(String mapping)
      Specified by:
      keySystem in interface Mappings
      Parameters:
      mapping - mapping name
      Returns:
      formal identifier of the key code system, empty if the mapping declares none
    • valueSystem

      public Optional<String> valueSystem(String mapping)
      Specified by:
      valueSystem in interface Mappings
      Parameters:
      mapping - mapping name
      Returns:
      formal identifier of the value code system, empty if the mapping declares none
    • keys

      public Set<String> keys(String mapping)
      Specified by:
      keys in interface Mappings
      Parameters:
      mapping - mapping name
      Returns:
      the keys this mapping translates, in declaration order. A key declared only by a Equivalence.DISJOINT entry is not among them, because it does not translate. The keys of a mapping this one delegates to follow its own, since a lookup asks that mapping for every key this one does not declare; keys that only a fallback such as identity answers are not listed. For a composite they are the keys of all its parts. Changes to the set do not change the mapping
    • values

      public Collection<String> values(String mapping)
      Specified by:
      values in interface Mappings
      Parameters:
      mapping - mapping name
      Returns:
      the values this mapping translates to, in declaration order. Changes to the collection do not change the mapping
      See Also:
    • setAllowOverride

      public void setAllowOverride(boolean allowOverride)
      Whether an existing mapping may be overridden to a mapping definition registered later
    • setAllowReverseCollisions

      public void setAllowReverseCollisions(boolean allowReverseCollisions)
      Whether a mapping may register two invertible entries sharing a value, in which case the last one declared wins the reverse index. Off by default: a value with two inverses is a load-time error, since the alternative is a reverse lookup that silently answers whichever key happened to be written last.