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

com.nedap.archie.rminfo.MetaModels Maven / Gradle / Ivy

There is a newer version: 3.12.0
Show newest version
package com.nedap.archie.rminfo;

import com.nedap.archie.aom.Archetype;
import com.nedap.archie.aom.CPrimitiveObject;
import com.nedap.archie.aom.profile.AomProfile;
import com.nedap.archie.aom.profile.AomProfiles;
import com.nedap.archie.base.MultiplicityInterval;
import org.openehr.bmm.core.BmmModel;
import org.openehr.bmm.persistence.validation.BmmDefinitions;
import org.openehr.bmm.v2.validation.BmmRepository;
import org.openehr.bmm.v2.validation.BmmValidationResult;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * MetaModel class that provides some opertaions for archetype validation and flattener that is either based on
 * an implementation-derived model (ModelInfoLookup) or BMM
 *
 * To use, select a model first using the selectModel() method. Then you can use any of the methods from MetaModelInterface
 * or obtain the underlying models directly. Trying to use the MetaModelInterface methods without selecting a model will
 * result in a NoModelSelectedException being thrown.
 *
 * By default the MetaModels uses the RM version from the archetype. It is possible to override this version either for
 * the entire MetaModels, or for a specific call, with the overrideModelVersion() method, and the two-parameter
 * selectModel() method.
 *
 * Note that this class is NOT thread-safe and is to be used by a single thread only.
 *
 */
public class MetaModels implements MetaModelInterface {

    private final ReferenceModels models;
    private final BmmRepository bmmRepository;
    private AomProfiles aomProfiles;

    private MetaModel selectedModel;
    private AomProfile selectedAomProfile;

    /**
     * Allows to set a specific RM version for a specific RM model, so that one is used instead of the one in the archetype
     */
    private Map overriddenMetaModelVersions = new ConcurrentHashMap<>();


    public MetaModels(ReferenceModels models, BmmRepository repository) {
        this.models = models;
        this.bmmRepository = repository;
        aomProfiles = new AomProfiles();
    }

    public MetaModels(ReferenceModels models, BmmRepository repository, AomProfiles profiles) {
        this.models = models;
        this.bmmRepository = repository;
        aomProfiles = profiles;
    }

    /**
     * Indicate that the model version for the given package by the given publisher should be fixed
     * to a specific version. Useful for validating archetypes against new RM versions, for example OpenEHR
     * RM 1.0.2 archetypes against 1.0.4
     * @param rmPublisher the publisher of the RM
     * @param rmPackage the package of the RM to override the version for
     * @param version the version that should be chosen
     */
    public void overrideModelVersion(String rmPublisher, String rmPackage, String version) {
        this.overriddenMetaModelVersions.put(
                BmmDefinitions.publisherQualifiedRmClosureName(rmPublisher, rmPackage),
                version
        );
    }

    /**
     * Remove the overriden model version for the given package
     * @param rmPublisher The publisher of the package
     * @param rmPackage the RM Package to remove the model version for
     */
    public void removeOverridenModelVersion(String rmPublisher, String rmPackage) {
        this.overriddenMetaModelVersions.remove(BmmDefinitions.publisherQualifiedRmClosureName(rmPublisher, rmPackage));
    }


    public String getOverriddenModelVersion(String rmPublisher, String rmPackage) {
        return this.overriddenMetaModelVersions.get(BmmDefinitions.publisherQualifiedRmClosureName(rmPublisher, rmPackage));
    }

    /**
     * Select a meta model based on an archetype
     * @param archetype the archetype to find the model for
     * @throws ModelNotFoundException when no BMM and no ModelInfoLookup model has been found matching the archetype
     */
    public void selectModel(Archetype archetype) throws ModelNotFoundException { ;
        String overriddenVersion = getOverriddenModelVersion(archetype.getArchetypeId().getRmPublisher(), archetype.getArchetypeId().getRmPackage());
        selectModel(archetype, overriddenVersion == null ? archetype.getRmRelease(): overriddenVersion);
    }

    /**
     * Select a model based on an archetype, but override the RM Release with the given rm release version
     * @param archetype the archetype to find the model for
     * @param rmVersion the version of the reference model you want to check with.
     * @throws ModelNotFoundException
     */
    public void selectModel(Archetype archetype, String rmVersion) throws ModelNotFoundException { ;
        selectModel(archetype.getArchetypeId().getRmPublisher(), archetype.getArchetypeId().getRmPackage(), rmVersion);
    }

    /**
     * Select a model based on an publisher, package and rm release version. Will NOT take into account overriden RM
     * versions, use the other selectModel() methods for that.
     * @param rmPublisher RM Publisher
     * @param rmPackage RM Package
     * @param rmRelease the version of the reference model you want to check with.
     * @throws ModelNotFoundException
     */
    public void selectModel(String rmPublisher, String rmPackage, String rmRelease) throws ModelNotFoundException {
        ModelInfoLookup selectedModel = null;
        BmmModel selectedBmmModel = null;
        RMObjectMapperProvider objectMapperProvider = null;
        if(models != null) {
             selectedModel = models.getModel(rmPublisher, rmPackage);
             objectMapperProvider = models.getRmObjectMapperProvider(rmPublisher, rmPackage);
        }
        if(bmmRepository != null) {
            BmmValidationResult validationResult = bmmRepository.getModelByClosure(BmmDefinitions.publisherQualifiedRmClosureName(rmPublisher, rmPackage) + "_" +  rmRelease);
            selectedBmmModel = validationResult == null ? null : validationResult.getModel();
        }

        this.selectedAomProfile = getAomProfileWithSchemaId(selectedBmmModel);
        if(this.selectedAomProfile == null) {
            this.selectedAomProfile = getAomProfileOnPublisher(rmPublisher);
        }

        if(selectedModel == null && selectedBmmModel == null) {
            throw new ModelNotFoundException(String.format("model for %s.%s version %s not found", rmPublisher, rmPackage, rmRelease));
        }
        this.selectedModel = new MetaModel(selectedModel, selectedBmmModel, selectedAomProfile, objectMapperProvider);

    }

    private AomProfile getAomProfileWithSchemaId(BmmModel selectedBmmModel) {
        if(selectedBmmModel != null) {
            for (AomProfile profile : aomProfiles.getProfiles()) {
                if (profile.getRmSchemaPattern().stream().anyMatch(pat -> selectedBmmModel.getSchemaId().matches(pat))) {
                    return profile;
                }
            }
        }
        return null;
    }

    private AomProfile getAomProfileOnPublisher(String rmPublisher) {
        for(AomProfile profile:aomProfiles.getProfiles()) {
           if(profile.getProfileName().equalsIgnoreCase(rmPublisher)) {
                return profile;
            }
        }
        return null;
    }

    public ModelInfoLookup getSelectedModelInfoLookup() {
        return selectedModel == null ? null : selectedModel.getSelectedModel();
    }

    public BmmModel getSelectedBmmModel() {
        return selectedModel == null ? null : selectedModel.getSelectedBmmModel();
    }

    public MetaModel getSelectedModel() {
        return selectedModel;
    }

    public ReferenceModels getReferenceModels() {
        return models;
    }

    public BmmRepository getBmmRepository() {
        return bmmRepository;
    }

    public boolean isMultiple(String typeName, String attributeName) {
        checkThatModelHasBeenSelected();
        return selectedModel.isMultiple(typeName, attributeName);
    }

    public boolean rmTypesConformant(String childTypeName, String parentTypeName) {
        checkThatModelHasBeenSelected();
        return selectedModel.rmTypesConformant(childTypeName, parentTypeName);
    }

    public boolean typeNameExists(String typeName) {
        checkThatModelHasBeenSelected();
        return selectedModel.typeNameExists(typeName);
    }

    public boolean attributeExists(String rmTypeName, String propertyName) {
        checkThatModelHasBeenSelected();
        return selectedModel.attributeExists(rmTypeName, propertyName);
   }

    @Override
    public boolean isNullable(String typeId, String attributeName) {
        checkThatModelHasBeenSelected();
        return selectedModel.isNullable(typeId, attributeName);
    }


    public boolean typeConformant(String rmTypeName, String rmAttributeName, String childConstraintTypeName) {
        checkThatModelHasBeenSelected();
        return selectedModel.typeConformant(rmTypeName, rmAttributeName, childConstraintTypeName);

    }

    public boolean hasReferenceModelPath(String rmTypeName, String path) {
        checkThatModelHasBeenSelected();
        return selectedModel.hasReferenceModelPath(rmTypeName, path);
    }

    public MultiplicityInterval referenceModelPropMultiplicity(String rmTypeName, String rmAttributeName) {
        checkThatModelHasBeenSelected();
        return selectedModel.referenceModelPropMultiplicity(rmTypeName, rmAttributeName);
    }

    public boolean validatePrimitiveType(String rmTypeName, String rmAttributeName, CPrimitiveObject cObject) {
        checkThatModelHasBeenSelected();
        return selectedModel.validatePrimitiveType(rmTypeName, rmAttributeName, cObject);
    }

    private void checkThatModelHasBeenSelected() throws NoModelSelectedException {
        if(selectedModel == null) {
            throw new NoModelSelectedException("Please call the selectModel() method before trying to use MetaModels");
        }

    }

    public boolean isOrdered(String rmTypeName, String rmAttributeName) {
        checkThatModelHasBeenSelected();
        return selectedModel.isOrdered(rmTypeName, rmAttributeName);
    }

    public AomProfiles getAomProfiles() {
        return aomProfiles;
    }

    public AomProfile getSelectedAomProfile() {
        return selectedAomProfile;
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy