Assigned to: raff
Background
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.
...
Data Model Design
The following design was proposed on is based on the proposal of the Design Forum 2015-06-22:
Gliffy |
---|
name | Metadata Mapping Table Design |
---|
|
Note that in this diagram, the one-to-one mapping between metadata_source
and 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 openmrs_metadata
.
Notes on data model design
...
metadata_source
is used to define a unique source (authority) for each namespace of metadata terms.name
should be fully qualified and universally unique.
metadata_term
table _mapping
table provides both the term and its mapping to local metadata.code
should be unique within the given source.metadata_class
refers to the Java class for the metadata.metadata_reference
is a unique reference to the metadata within the class (e.g., uuid)
metadata_set
is 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_weight
is used to optionally give members of a metadata set a reliable sequence.
...
Fetch a location with the given source and code:
Code Block |
---|
|
Location location = metadataService.getItem(Location.class, "SOME-SOURCE", "CODE"); |
...
// should be implemented as: generic <T> getItem(T type, String source, String code); |
Fetch all visit types from the given source:
Code Block |
---|
|
List<VisitType> visitTypes = metadataService.getItems(VisitType.class, "SOME-SOURCE");
// should be implemented as: generic <T> getItems(T type, String source); |
Fetch all visit types for the given set:
Code Block |
---|
|
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 |
Retire term:
...
Code Block |
---|
|
List<MetadataTermMapping> termMappings = metadataService.getMetadataTermMappings(location); |
...
metadataService.retireMapping( |
...
termMappings.get(0), "some reason"); |
Create term:
Code Block |
---|
|
MetadataSource source = metadataService.getSourceByName("SOME-SOURCE"); |
...
MetadataTermMapping termMapping = new MetadataTermMapping(source, "CODE", location); |
...
...
...
Create terms in bulk:
...
Code Block |
---|
|
List<MetadataTermMapping> termMappings = Arrays.asList(mapping1, mapping2, mapping3); |
...
...
saveMetadataTermMappings( |
...
Get term by source and code:
...
Code Block |
---|
|
MetadataTermMapping termMapping = metadataService. |
...
getMetadataTermMapping(mappingSource, "CODE"); |
Get terms by source:
...
Code Block |
---|
|
List<MetadataTermMapping> termMappings = metadataService.getMetadataTermMappings(source); |
Get term by uuid:
...
Code Block |
---|
|
MetadataTermMapping termMapping = metadataService. |
...
getMetadataTermMappingByUuid(String uuid); |
Get source by uuid:
...
Code Block |
---|
|
MetadataSource source = metadataService.getMetadataSourceByUuid(String uuid); |
...
MetadataTermMapping, MetadataSource, MetadataSet should support all CRUD operations.