All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.nedap.archie.adl14.ADL14Converter Maven / Gradle / Ivy

Go to download

tools that operate on the archie reference models and archetype object model

The newest version!
package com.nedap.archie.adl14;

import com.nedap.archie.adl14.log.ADL2ConversionLog;
import com.nedap.archie.adl14.log.ADL2ConversionRunLog;
import com.nedap.archie.terminology.OpenEHRTerminologyAccess;
import com.nedap.archie.terminology.TerminologyAccess;
import com.nedap.archie.aom.Archetype;
import com.nedap.archie.aom.ResourceDescription;
import com.nedap.archie.aom.Template;
import com.nedap.archie.aom.TemplateOverlay;
import com.nedap.archie.aom.utils.ArchetypeParsePostProcesser;
import com.nedap.archie.diff.Differentiator;
import com.nedap.archie.flattener.Flattener;
import com.nedap.archie.flattener.InMemoryFullArchetypeRepository;
import com.nedap.archie.rminfo.MetaModels;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;

public class ADL14Converter {

    private final MetaModels metaModels;
    private TerminologyAccess terminologyAccess = OpenEHRTerminologyAccess.getInstance();
    private final ADL14ConversionConfiguration conversionConfiguration;
    private InMemoryFullArchetypeRepository existingRepository;

    public ADL14Converter(MetaModels metaModels, ADL14ConversionConfiguration conversionConfiguration) {
        this.metaModels = metaModels;
        this.conversionConfiguration = conversionConfiguration;
    }


    /**
     * Set the base repository for this converter. If you don't set it yourself, the converter will create an empty repository.
     * The archetypes in the repository will be used as base archetypes, but will not be converted themselves. Please
     * note that this repository will be modified, it will have all the converted archetypes added to it!
     *
     * @param existingRepository the existing repository to use
     */
    public void setExistingRepository(InMemoryFullArchetypeRepository existingRepository) {
        this.existingRepository = existingRepository;
    }

    public ADL2ConversionResultList convert(List archetypes) {
        return convert(archetypes, null);
    }

    public ADL2ConversionResultList convert(List archetypes, ADL2ConversionRunLog previousConversion) {
        ADL2ConversionResultList resultList = new ADL2ConversionResultList();

        InMemoryFullArchetypeRepository repository = existingRepository;
        if(repository == null) {
            repository = new InMemoryFullArchetypeRepository();
        }
        List unprocessed = new ArrayList<>(archetypes);

        List templateOverlays = new ArrayList<>();
        for(Archetype ar:unprocessed) {
            //ADL 1.4 does not really have templates. This code is here for the Better Care template conversion
            //also it can be used to write our own template converter later.
            //So add the overlays in the right order here
            if(ar instanceof Template) {
                Template t = (Template) ar;
                for(TemplateOverlay overlay:t.getTemplateOverlays()) {
                    templateOverlays.add(overlay);
                    overlay.setRmRelease(t.getRmRelease());
                }
            }
        }
        unprocessed.addAll(templateOverlays);

        //process the archetypes ordered by specialization level
        unprocessed.sort(Comparator.comparingInt(a -> a.specializationDepth()));

        Differentiator differentiator = new Differentiator(metaModels);
        for(Archetype archetype:unprocessed) {

            ADL2ConversionResult result = null;
            try {
                if (archetype.getParentArchetypeId() != null) {

                    Archetype parent = repository.getArchetype(archetype.getParentArchetypeId());
                    if(parent == null) {
                        throw new RuntimeException(MessageFormat.format("Cannot find parent {0} for archetype {1}", archetype.getParentArchetypeId(), archetype.getArchetypeId()));
                    }
                    Archetype flatParent = new Flattener(repository, metaModels).flatten(parent);
                    result = convert(archetype, flatParent, previousConversion);
                    if (result.getArchetype() != null) {
                        if(conversionConfiguration.isApplyDiff()) {
                            result.setArchetype(differentiator.differentiate(result.getArchetype(), flatParent, true));
                        } else {
                            result.setArchetype(differentiator.differentiate(result.getArchetype(), flatParent, false));
                        }
                    }
                    resultList.addConversionResult(result);
                } else {
                    result = convert(archetype, previousConversion);
                    resultList.addConversionResult(result);
                }
                if(result != null && result.getArchetype() != null && result.getArchetype().getArchetypeId() != null) {
                    repository.addArchetype(result.getArchetype());
                }
            } catch (Exception e) {
                result = new ADL2ConversionResult(archetype.getArchetypeId().toString(), e);
                resultList.addConversionResult(result);
            }
        }


        return resultList;
    }


    private ADL2ConversionResult convert(Archetype archetype,  ADL2ConversionRunLog previousConversion) {
        return convert(archetype, null, previousConversion);
    }

    private ADL2ConversionResult convert(Archetype archetype, Archetype flatParent, ADL2ConversionRunLog previousConversion) {
        ADL2ConversionLog previousLog = previousConversion == null ? null : previousConversion.getConversionLog(archetype.getArchetypeId().getSemanticId());
        Archetype convertedArchetype = archetype.clone();
        new ADL14DescriptionConverter().convert(convertedArchetype);
        setCorrectVersions(convertedArchetype);
        convertHeader(convertedArchetype);
        addDefaultMultiplicities(convertedArchetype);


        ADL2ConversionResult result = new ADL2ConversionResult(convertedArchetype);
        ADL14NodeIDConverter adl14NodeIDConverter = new ADL14NodeIDConverter(this.metaModels, convertedArchetype, flatParent, conversionConfiguration, previousLog, result);
        ADL2ConversionLog conversionLog = adl14NodeIDConverter.convert();//fixes archetype in place
        result.setConversionLog(conversionLog);

        //ADL 1.4 has cardinality, existence and occurrences always present, in ADL 2 they can be removed if same as default.
        //so remove them
        new DefaultRmStructureRemover(metaModels, true).removeRMDefaults(convertedArchetype);
        //set some values that are not directly in ODIN or ADL
        ArchetypeParsePostProcesser.fixArchetype(convertedArchetype);

        return result;

    }

    private void convertHeader(Archetype convertedArchetype) {
        if(convertedArchetype.getUid() != null) {
            //if UID is in OID syntax, move it to the description
            if(convertedArchetype.getUid().matches("[0-9]+(\\.[0-9]+)+")) {
                moveOidToMetadata(convertedArchetype, convertedArchetype.getUid(), "oid");
                convertedArchetype.setUid(null);
            }
        }
        if(convertedArchetype.getBuildUid() != null) {
            if(convertedArchetype.getBuildUid().matches("[0-9]+\\.([0-9]+)+")) {
                moveOidToMetadata(convertedArchetype, convertedArchetype.getBuildUid(), "build_oid");
                convertedArchetype.setBuildUid(null);
            }
        }
    }

    private void addDefaultMultiplicities(Archetype convertedArchetype) {
        new ADL14DefaultMultiplicitiesSetter(metaModels).setDefaults(convertedArchetype);
    }

    private void moveOidToMetadata(Archetype convertedArchetype, String oid, String oidFieldName) {
        if(convertedArchetype.getDescription() == null) {
            convertedArchetype.setDescription(new ResourceDescription());
        }
        if(convertedArchetype.getDescription().getOtherDetails() == null) {
            convertedArchetype.getDescription().setOtherDetails(new LinkedHashMap<>());
        }
        convertedArchetype.getDescription().getOtherDetails().put(oidFieldName, oid);
    }


    private void setCorrectVersions(Archetype result) {
        result.setAdlVersion("2.0.6");
        result.setRmRelease(conversionConfiguration.getRmRelease());
        if(result.getArchetypeId().getMinorVersion() == null) {
            result.getArchetypeId().setReleaseVersion(result.getArchetypeId().getReleaseVersion() + ".0.0");
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy