Skip to content

openmrs/openmrs-module-metadataexport

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Metadata Export

Active development / experimental. This module is an early proof of concept. APIs, output format, and behaviour will change without notice, and not everything described here is fully verified yet. Not for production use.

Description

Initializer (openmrs-module-initializer) can load a configuration/ content package into OpenMRS, but it cannot produce one. This module does the reverse: it reads metadata out of a running, populated OpenMRS instance and writes it back out in the Initializer format, so a configuration can be captured from a server and replayed elsewhere.

It is export only. It never imports or applies metadata; loading remains Initializer's job.

Currently supported domains:

  • Concepts (names, descriptions, class/datatype/version, numeric, complex, answers, members, mappings, attributes)
  • Concept sources (name, description, HL7 code, unique ID)
  • Encounter types (name, description, view/edit privileges)
  • Privileges (name, description)
  • Concept classes (name, description)

Planned domains (openmrs-core metadata, not yet supported):

  • Tier 1 — flat metadata, no dependencies: visit types, encounter roles, person attribute types, global properties, relationship types, patient identifier types, location tags
  • Tier 2 — with reference/ordering dependencies: roles, locations, attribute types, order types
  • Tier 3 — concept-dependent: drugs, order frequencies, programs/workflows/states, concept sets, concept reference ranges

Domains backed by add-on modules (IDGen, appointments, queues, billing, OCL, MetadataSharing, FHIR, forms) and non-exportable Initializer domains (Liquibase, JSON key-values, system tasks) are out of scope.

How it works

On module startup the activator runs an export on a daemon thread (so it has full read access and does not block startup). It writes to:

<OpenMRS application data directory>/metadata_export/configuration/<domain>/...

The export is built in two separated stages:

  1. Selection. Starting from seed objects, a Selector walks each object's dependencies to a fixpoint, producing an ExportManifest (the set of objects to export, bucketed by domain). This is what makes a package self-contained: for example, exporting a concept set also pulls in its members.
  2. Export. Each DomainExporter writes its bucket in its own format. The service holds a registry of these and contains no per-domain logic.

Requirements

The Initializer module must be installed (declared in config.xml require_modules); this module reuses its Domain and CSV header definitions.

Adding a new domain

Supporting a new metadata type is a new class plus one line in the registry, never a new method on the service.

  1. Write a DomainExporter and annotate it @Component so it is discovered automatically. For a CSV domain, extend CsvDomainExporter<T>:
@Component
public class EncounterTypeDomainExporter extends CsvDomainExporter<EncounterType> {

    public Domain getDomain()               { return Domain.ENCOUNTER_TYPES; }

    public boolean handles(OpenmrsObject o) { return o instanceof EncounterType; }

    public Collection<EncounterType> getAllInstances() {
        return Context.getEncounterService().getAllEncounterTypes();
    }

    // Objects from OTHER domains this one references, for cross-domain closure. Empty if none.
    public Collection<? extends OpenmrsObject> getDependencies(EncounterType t) {
        return Collections.emptyList();
    }

    protected List<BaseLineExporter<EncounterType>> chain() {
        return Arrays.asList(new EncounterTypeLineExporter());
    }

    protected String fileName() { return "encounterTypes.csv"; }
}
  1. Write the line exporter(s). Each writes header to value pairs into an ExportLine; it is the inverse of Initializer's matching BaseLineProcessor.fill(...). Reuse Initializer's header constants where they are public so the two sides cannot drift. For the primary exporter of a domain, extend MetadataLineExporter<T>: it writes the uuid and the void/retire short-circuit for you, so export only handles the live, domain-specific columns:
public class EncounterTypeLineExporter extends MetadataLineExporter<EncounterType> {
    public void export(EncounterType t, ExportLine line) {
        line.put(BaseLineProcessor.HEADER_NAME, t.getName());
        line.put(BaseLineProcessor.HEADER_DESC, t.getDescription());
    }
}

Exporters that only contribute extra columns to an existing row (not the primary one) extend BaseLineExporter<T> directly instead.

A CSV domain may emit more than one file by overriding partition(instances) (the default is one file). A non-CSV domain (for example forms as JSON) skips CsvDomainExporter and implements DomainExporter directly, writing whatever files it likes in export(bucket, context).

That is all. Because the exporter is a @Component, it is registered automatically; there is no list to edit. Selection, closure, routing, and writing are handled by the framework.

Known limitations

  • Concept description UUIDs and index-term names are not round-trip-able (Initializer format/loader limitations), so they are not preserved or re-loadable.
  • Selection currently exports all instances of the registered domains; instance-level seed selection is not yet exposed.
  • Cross-domain closure only pulls in objects whose domain has a registered exporter.

Building from source

Java 8+ and Maven. mvn clean package produces omod/target/metadataexport-*.omod. Code formatting is handled by Spotless during the build (mvn spotless:apply to format manually).

Installation

Build the .omod, then either upload it via Administration > Manage Modules or drop it into the OpenMRS application data directory's modules/ folder and restart. Ensure the Initializer module is also installed.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages