OpenMRS has a mechanism to map concepts to external sources (
concept_map tables); however, OpenMRS does not yet have a means to map metadata to external sources. We have tried using UUIDs to uniquely (and globally) specify metadata across systems; however, this has failed us in several ways: (1) UUIDs end up needing to be manually entered by developers and implementers; (2) there are many cases where metadata created separately (with different UUIDs) are actually referring to the same thing; and, (3) modules introducing their own metadata have a difficult time properly working with existing metadata.
The goal of Metadata Mapping is to solve many of the problems around metadata management by providing an easy & explicit way for metadata within a system (encounter types, location, etc.) to be mapped to external vocubularies.
Use case examples:
A "1.0" version of Metadata Mapping would include a
MetadataService within openmrs-core (could be introduced by a module initially or for the foreseeable future) and REST API endpoints to manage & search metadata mappings.
The following design is based on the proposal of the Design Forum 2015-06-22:
Note that in this diagram, the one-to-one mapping between
openmrs_metadata, for example, indicates an inheritance in object design terms: MetadataSource inherits the fields of OpenmrsMetadata. In the database schema, this relationship will be implemented so that the relation
metadata_source, for example, includes all the columns of
metadata_sourceis used to define a unique source (authority) for each namespace of metadata terms.
nameshould be fully qualified and universally unique.
metadata_term_mappingtable provides both the term and its mapping to local metadata.
codeshould be unique within the given source.
metadata_classrefers to the Java class for the metadata.
metadata_referenceis a unique reference to the metadata within the class (e.g., uuid)
metadata_setis used to define relating grouping of metadata similar to what OpenMRS has traditionally done within global properties and similar to FHIR's ValueSet for metadata terms.
sort_weightis used to optionally give members of a metadata set a reliable sequence.
The common operations for metadata mapping will include these use cases:
Location location = metadataService.getItem(Location.class, "SOME-SOURCE", "CODE"); // should be implemented as: generic <T> getItem(T type, String source, String code);
List<VisitType> visitTypes = metadataService.getItems(VisitType.class, "SOME-SOURCE"); // should be implemented as: generic <T> getItems(T type, String source);
List<VisitType> visitTypes = metadataSerivce .getItems(VisitType.class, "SOME-SOURCE", "CODE"); // should be implemented as: generic <T> getItems(T type, String source, String code); // source = metadataSet.source.name, code = metadataSet.code
List<MetadataTermMapping> termMappings = metadataService.getMetadataTermMappings(location); metadataService.retireMapping(termMappings.get(0), "some reason");
MetadataSource source = metadataService.getSourceByName("SOME-SOURCE"); MetadataTermMapping termMapping = new MetadataTermMapping(source, "CODE", location); metadataService.saveMetadataTermMapping(termMapping);
List<MetadataTermMapping> termMappings = Arrays.asList(mapping1, mapping2, mapping3); metadataService.saveMetadataTermMappings(termMappings);
MetadataTermMapping termMapping = metadataService.getMetadataTermMapping(mappingSource, "CODE");
List<MetadataTermMapping> termMappings = metadataService.getMetadataTermMappings(source);
MetadataTermMapping termMapping = metadataService.getMetadataTermMappingByUuid(String uuid);
MetadataSource source = metadataService.getMetadataSourceByUuid(String uuid);