Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
94d9fb0
Replace MetaModels class with MetaModelProviders (#690)
J3173 Jun 12, 2025
8160ea7
Bump jacksonVersion from 2.19.0 to 2.19.1 (#691)
dependabot[bot] Jun 16, 2025
f2e883f
Correctly flatten TemporalAmount (#692)
MattijsK Jul 3, 2025
3011de2
Update Archie to v3.15.0 (#693)
MattijsK Jul 3, 2025
29a0b0c
Fix NullPointerException in FlatJsonGenerator.buildPathsAndValuesInne…
J3173 Jul 21, 2025
10fd652
Bump org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0 (#695)
dependabot[bot] Jul 28, 2025
b3119e0
Bump jacksonVersion from 2.19.1 to 2.19.2 (#700)
dependabot[bot] Jul 28, 2025
07c0111
Bump commons-io:commons-io from 2.19.0 to 2.20.0 (#701)
dependabot[bot] Jul 28, 2025
84717b1
Bump org.apache.commons:commons-text from 1.13.1 to 1.14.0 (#703)
dependabot[bot] Jul 28, 2025
9cadbc5
Update release configuration for central.sonatype (#694)
MattijsK Aug 8, 2025
b554cb3
Add GitHub Actions to Dependabot configuration (#713)
J3173 Sep 8, 2025
33f9868
Update Gradle to version 8.14.3 and fix deprecated features (#715)
J3173 Sep 15, 2025
c8f059b
Use Gradle Version Catalog (#716)
J3173 Sep 16, 2025
8566fd3
Don't include exception information in validation errors (#719)
J3173 Sep 18, 2025
828713d
Reformat Gradle files (#721)
J3173 Sep 22, 2025
d86be8b
Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0 (#722)
dependabot[bot] Oct 21, 2025
72d2390
Bump com.google.guava:guava from 33.4.8-jre to 33.5.0-jre (#720)
dependabot[bot] Oct 21, 2025
57a6072
Forwards compatibility of ResourceDescription.lifecycleState: also de…
MattijsK Nov 5, 2025
a3ac4e6
Bump jacksonVersion from 2.19.2 to 2.20.0 (#705)
dependabot[bot] Nov 26, 2025
f0d8154
Bump jackson from 2.20.0 to 2.20.1 (#728)
dependabot[bot] Dec 1, 2025
0732ba9
Bump org.apache.commons:commons-lang3 from 3.19.0 to 3.20.0 (#727)
dependabot[bot] Dec 1, 2025
b11af70
Bump commons-io:commons-io from 2.20.0 to 2.21.0 (#726)
dependabot[bot] Dec 1, 2025
cc04a76
Update Archie to 3.16.0 (#729)
MattijsK Dec 2, 2025
9e735cb
Bump org.apache.commons:commons-text from 1.14.0 to 1.15.0 (#730)
dependabot[bot] Dec 29, 2025
60b8d3f
Create AttributeAccessor utility class (#732)
J3173 Jan 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,9 @@ updates:
interval: daily
time: "11:00"
open-pull-requests-limit: 10
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: daily
time: "11:00"
open-pull-requests-limit: 10
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ You can depend on parts of Archie, or the entire library at once. If you want th

```gradle
dependencies {
compile 'com.nedap.healthcare.archie:archie-all:3.14.0'
compile 'com.nedap.healthcare.archie:archie-all:3.16.0'
}
```

Expand All @@ -28,11 +28,11 @@ or if you use maven, in your pom.xml
<dependency>
<groupId>com.nedap.healthcare.archie</groupId>
<artifactId>archie-all</artifactId>
<version>3.14.0</version>
<version>3.16.0</version>
</dependency>
```

If you want to depend on just the AOM and BMM, without any reference model implementation, depend on com.nedap.healthcare.archie:tools:3.14.0 and com.nedap.healthcare.archie:referencemodels:3.14.0 instead
If you want to depend on just the AOM and BMM, without any reference model implementation, depend on com.nedap.healthcare.archie:tools:3.16.0 and com.nedap.healthcare.archie:referencemodels:3.16.0 instead


## Build
Expand Down Expand Up @@ -137,7 +137,7 @@ InMemoryFullArchetypeRepository repository = new InMemoryFullArchetypeRepository
for(Archetype archetype:allArchetypes) {
repository.addArchetype(archetype);
}
repository.compile(BuiltinReferenceModels.getMetaModels());
repository.compile(BuiltinReferenceModels.getMetaModelProvider());

for(ValidationResult result:repository.getAllValidationResults()) {
... your code here
Expand All @@ -149,7 +149,7 @@ The validation result contains the validation result, listing any errors in the

### Reference model metadata

You may have noticed a call to ```BuiltinReferenceModels.getMetaModels()```. This retrieves the metadata for the reference models, which are needed to validate and flatten archetypes. Archie contains two types of metamodels: BMM, and reflection based metadata.
You may have noticed a call to ```BuiltinReferenceModels.getMetaModelProvider()```. This retrieves the metadata for the reference models, which are needed to validate and flatten archetypes. Archie contains two types of metamodels: BMM, and reflection based metadata.
The BMM models are a file containing metadata in a form defined by the openEHR specifications.
The reflection based metadata contains ModelInfoLookup classes. They are derived from an implementation of a reference model. Note that the ModelInfoLookup classes are only added if you depended on them. If you depended on archie-all, you're all set.

Expand All @@ -162,7 +162,7 @@ Note that ADL 2 operational templates is fundamentally different from the ADL 1.
To create an Operational Template:

```java
Flattener flattener = new Flattener(repository, BuiltinReferenceModels.getMetaModels()).createOperationalTemplate(true);
Flattener flattener = new Flattener(repository, BuiltinReferenceModels.getMetaModelProvider()).createOperationalTemplate(true);
OperationalTemplate template = (OperationalTemplate) flattener.flatten(sourceArchetype);
```

Expand Down Expand Up @@ -221,7 +221,7 @@ The inverse operation of flattening archetypes is diffing. This is useful if you
```java
Archetype flatChild, flatParent; //for how to parse and flatten, see elsewhere in the readme

Differentiator differentiator = new Differentiator(BuiltinReferenceModels.getMetaModels());
Differentiator differentiator = new Differentiator(BuiltinReferenceModels.getMetaModelProvider());
Archetype diffed = differentiator.differentiate(flatChild, flatParent);
```

Expand Down Expand Up @@ -391,7 +391,7 @@ If you want to do this yourself, The RMObjectCreator creates empty reference mod

Setting primitive object values works in a similar way, with ```creator.set(...)```, or by setting them explicitly on the reference model object directly.

Notice the call to ```ArchieRMInfoLookup.getInstance()```, which obtains the metadata about the reference model implementation. It can also be obtained from the result of ```BuiltinReferenceModels.getMetaModels()```, or you can define your own to make Archie work with your own reference model implementation.
Notice the call to ```ArchieRMInfoLookup.getInstance()```, which obtains the metadata about the reference model implementation. It can also be obtained from the result of ```BuiltinReferenceModels.getMetaModelProvider()```, or you can define your own to make Archie work with your own reference model implementation.

### Parsing JSON

Expand Down Expand Up @@ -456,10 +456,10 @@ Starting from version 0.7, Archie can import ADL 1.4 files, and convert them to

```java
ADL14ConversionConfiguration conversionConfiguration = new ADL14ConversionConfiguration();
ADL14Converter converter = new ADL14Converter(BuiltinReferenceModels.getMetaModels(), conversionConfiguration);
ADL14Converter converter = new ADL14Converter(BuiltinReferenceModels.getMetaModelProvider(), conversionConfiguration);

List<Archetype> archetypes = new ArrayList<>();
ADL14Parser parser = new ADL14Parser(BuiltinReferenceModels.getMetaModels());
ADL14Parser parser = new ADL14Parser(BuiltinReferenceModels.getMetaModelProvider());

for(String file:fileNames) {
try(InputStream stream = new FileInputStream(file)) {
Expand Down
2 changes: 1 addition & 1 deletion adlchecker/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ run {
args = ['archetypes', '--lint']//, '--outputFlat']
}

mainClassName='com.nedap.archie.adlchecker.AdlChecker'
mainClassName = 'com.nedap.archie.adlchecker.AdlChecker'
14 changes: 7 additions & 7 deletions aom/build.gradle
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
description = "An OpenEHR archetype object model implementation, plus parser"

dependencies {
api project(':grammars')
api project(':base')
api project(':odin')
api project(':utils')
api project(':bmm')
api project(':openehr-terminology')
}
api project(':grammars')
api project(':base')
api project(':odin')
api project(':utils')
api project(':bmm')
api project(':openehr-terminology')
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import com.nedap.archie.aom.CAttribute;
import com.nedap.archie.aom.CObject;
import com.nedap.archie.base.MultiplicityInterval;
import com.nedap.archie.rminfo.MetaModel;
import com.nedap.archie.rminfo.MetaModelProvider;
import com.nedap.archie.rminfo.MetaModels;

/**
Expand All @@ -17,24 +19,32 @@
*/
public class ADL14DefaultMultiplicitiesSetter {

private final MetaModels metaModels;
private final MetaModelProvider metaModelProvider;

/**
* @deprecated Use {@link #ADL14DefaultMultiplicitiesSetter(MetaModelProvider)} instead.
*/
@Deprecated
public ADL14DefaultMultiplicitiesSetter(MetaModels metaModels) {
this.metaModels = metaModels;
this((MetaModelProvider) metaModels);
}

public ADL14DefaultMultiplicitiesSetter(MetaModelProvider metaModelProvider) {
this.metaModelProvider = metaModelProvider;
}

public void setDefaults(Archetype archetype) {
metaModels.selectModel(archetype);
correctItemsMultiplicities(archetype.getDefinition());
MetaModel metaModel = metaModelProvider.selectAndGetMetaModel(archetype);
correctItemsMultiplicities(metaModel, archetype.getDefinition());
}

private void correctItemsMultiplicities(CObject cObject) {
private void correctItemsMultiplicities(MetaModel metaModel, CObject cObject) {
for (CAttribute attribute : cObject.getAttributes()) {
for (CObject child : attribute.getChildren()) {
if (child.getOccurrences() == null && metaModels.isMultiple(cObject.getRmTypeName(), attribute.getRmAttributeName())) {
if (child.getOccurrences() == null && metaModel.isMultiple(cObject.getRmTypeName(), attribute.getRmAttributeName())) {
child.setOccurrences(new MultiplicityInterval(1, 1));
}
correctItemsMultiplicities(child);
correctItemsMultiplicities(metaModel, child);
}
}

Expand Down
22 changes: 17 additions & 5 deletions aom/src/main/java/com/nedap/archie/adl14/ADL14NodeIDConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import com.nedap.archie.base.Cardinality;
import com.nedap.archie.paths.PathSegment;
import com.nedap.archie.query.APathQuery;
import com.nedap.archie.rminfo.MetaModel;
import com.nedap.archie.rminfo.MetaModelProvider;
import com.nedap.archie.rminfo.MetaModels;
import com.nedap.archie.rules.*;

Expand All @@ -33,7 +35,8 @@ public class ADL14NodeIDConverter {
private final ADL14TermConstraintConverter termConstraintConverter;
private final PreviousConversionApplier previousConversionApplier;
private final ADL2ConversionResult conversionResult;
private final MetaModels metaModels;
private final MetaModelProvider metaModelProvider;
private final MetaModel metaModel;

private IdCodeGenerator idCodeGenerator;

Expand All @@ -45,8 +48,17 @@ public class ADL14NodeIDConverter {
private final Map<String, ValueSet> createdValueSets = new LinkedHashMap<>();
private final Map<String, String> newCodeToOldCodeMap = new LinkedHashMap<>();

/**
* @deprecated Use {@link #ADL14NodeIDConverter(MetaModelProvider, Archetype, Archetype, ADL14ConversionConfiguration, ADL2ConversionLog, ADL2ConversionResult)} instead.
*/
@Deprecated
public ADL14NodeIDConverter(MetaModels metaModels, Archetype archetype, Archetype flatParentArchetype, ADL14ConversionConfiguration configuration, ADL2ConversionLog oldLog, ADL2ConversionResult conversionResult) {
this.metaModels = metaModels;
this((MetaModelProvider) metaModels, archetype, flatParentArchetype, configuration, oldLog, conversionResult);
}

public ADL14NodeIDConverter(MetaModelProvider metaModelProvider, Archetype archetype, Archetype flatParentArchetype, ADL14ConversionConfiguration configuration, ADL2ConversionLog oldLog, ADL2ConversionResult conversionResult) {
this.metaModelProvider = metaModelProvider;
this.metaModel = metaModelProvider.getMetaModel(archetype);
this.conversionConfiguration = configuration;
this.archetype = archetype;
this.flatParentArchetype = flatParentArchetype;
Expand All @@ -61,7 +73,7 @@ public ADL14ConversionConfiguration getConversionConfiguration() {
}

public ADL2ConversionLog convert() {
metaModels.selectModel(archetype);
metaModelProvider.selectAndGetMetaModel(archetype); // For backwards compatibility

correctItemsCardinality(archetype.getDefinition());
List<String> unnecessaryCodes = findUnnecessaryCodes(archetype.getDefinition(),
Expand Down Expand Up @@ -123,7 +135,7 @@ private List<String> findUnnecessaryCodes(CObject cObject, Map<String, Archetype
ArchetypeTerm term = originalLanguageTermDefinitions.get(code);
if (term != null && term.getText() != null && term.getText().length() < 19
&& term.getDescription() != null && term.getDescription().contains("@ internal @")) {
if (!cObject.isRootNode() && !parentIsMultiple(cObject, flatParentArchetype, metaModels)) {
if (!cObject.isRootNode() && !parentIsMultiple(cObject, flatParentArchetype, metaModel)) {
result.add(code);
}
}
Expand Down Expand Up @@ -245,7 +257,7 @@ private void generateMissingNodeIds(CObject cObject) {
synthesizeNodeId(cObject, path);
conversionResult.getLog().addWarningWithLocation(ADL14ConversionMessageCode.WARNING_SPECIALIZED_FIRST_MATCHING_CHILD, cObject.path());
} else if (cAttributeInParent.getChildren().size() == 1 || cObject.getParent().getChildren().size() == 1) {
if (this.metaModels.rmTypesConformant(cObject.getRmTypeName(), cAttributeInParent.getChildren().get(0).getRmTypeName())) {
if (this.metaModel.rmTypesConformant(cObject.getRmTypeName(), cAttributeInParent.getChildren().get(0).getRmTypeName())) {
//this replaces a parent node, so a specialisation. add id code and possibly a term
createSpecialisedNodeId(cObject, path, Arrays.asList(cAttributeInParent.getChildren().get(0)));
} else {
Expand Down
26 changes: 18 additions & 8 deletions aom/src/main/java/com/nedap/archie/adl14/ADL14Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import com.nedap.archie.antlr.errors.ArchieErrorListener;
import com.nedap.archie.aom.Archetype;
import com.nedap.archie.aom.utils.ArchetypeParsePostProcessor;
import com.nedap.archie.rminfo.MetaModel;
import com.nedap.archie.rminfo.MetaModelProvider;
import com.nedap.archie.rminfo.MetaModels;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
Expand All @@ -29,7 +31,7 @@
*/
public class ADL14Parser {

private final MetaModels metaModels;
private final MetaModelProvider metaModelProvider;
private ANTLRParserErrors errors;

private Lexer lexer;
Expand All @@ -44,8 +46,16 @@ public class ADL14Parser {
*/
private boolean logEnabled = true;

/**
* @deprecated Use {@link #ADL14Parser(MetaModelProvider)} instead.
*/
@Deprecated
public ADL14Parser(MetaModels models) {
this.metaModels = models;
this((MetaModelProvider) models);
}

public ADL14Parser(MetaModelProvider metaModelProvider) {
this.metaModelProvider = metaModelProvider;
}

public Archetype parse(String adl, ADL14ConversionConfiguration conversionConfiguration) throws ADLParseException {
Expand Down Expand Up @@ -75,13 +85,13 @@ public Archetype parse(CharStream stream, ADL14ConversionConfiguration conversio
walker.walk(listener, tree);
result = listener.getArchetype();
ArchetypeParsePostProcessor.fixArchetype(result);
if (metaModels != null) {
metaModels.selectModel(result);
if (metaModels.getSelectedBmmModel() != null) {
ModelConstraintImposer imposer = new BMMConstraintImposer(metaModels.getSelectedBmmModel());
if (metaModelProvider != null) {
MetaModel metaModel = metaModelProvider.selectAndGetMetaModel(result);
if (metaModel.getBmmModel() != null) {
ModelConstraintImposer imposer = new BMMConstraintImposer(metaModel.getBmmModel());
imposer.setSingleOrMultiple(result.getDefinition());
} else if (metaModels.getSelectedModelInfoLookup() != null) {
ModelConstraintImposer imposer = new ReflectionConstraintImposer(metaModels.getSelectedModelInfoLookup());
} else if (metaModel.getModelInfoLookup() != null) {
ModelConstraintImposer imposer = new ReflectionConstraintImposer(metaModel.getModelInfoLookup());
imposer.setSingleOrMultiple(result.getDefinition());
}
}
Expand Down
35 changes: 24 additions & 11 deletions aom/src/main/java/com/nedap/archie/adlparser/ADLParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import com.nedap.archie.antlr.errors.ArchieErrorListener;
import com.nedap.archie.aom.Archetype;
import com.nedap.archie.aom.utils.ArchetypeParsePostProcessor;
import com.nedap.archie.rminfo.MetaModel;
import com.nedap.archie.rminfo.MetaModelProvider;
import com.nedap.archie.rminfo.MetaModels;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
Expand All @@ -29,7 +31,7 @@
*/
public class ADLParser {

private final MetaModels metaModels;
private final MetaModelProvider metaModelProvider;
private final ModelConstraintImposer modelConstraintImposer;
private ANTLRParserErrors errors;

Expand All @@ -46,7 +48,7 @@ public class ADLParser {
private boolean logEnabled = true;

public ADLParser() {
this.metaModels = null;
this.metaModelProvider = null;
this.modelConstraintImposer = null;
}

Expand All @@ -59,17 +61,28 @@ public ADLParser() {
@Deprecated
public ADLParser(ModelConstraintImposer modelConstraintImposer) {
this.modelConstraintImposer = modelConstraintImposer;
this.metaModels = null;
this.metaModelProvider = null;
}


/**
* Creates an ADLParser with MetaModel knowledge. This is used to set the isSingle and isMultiple fields correctly
* in the future, this will be used for more model-specific options, such as defined C_PRIMITIVE_OBJECTS and more
* @param models
* @deprecated Use {@link #ADLParser(MetaModelProvider)} instead.
*/
@Deprecated
public ADLParser(MetaModels models) {
this.metaModels = models;
this((MetaModelProvider) models);
}

/**
* Creates an ADLParser with MetaModel knowledge. This is used to set the isSingle and isMultiple fields correctly
* in the future, this will be used for more model-specific options, such as defined C_PRIMITIVE_OBJECTS and more
* @param metaModelProvider the provider for meta models
*/
public ADLParser(MetaModelProvider metaModelProvider) {
this.metaModelProvider = metaModelProvider;
this.modelConstraintImposer = null;
}

Expand All @@ -95,7 +108,7 @@ public Archetype parse(CharStream stream) throws ADLParseException {
tree = parser.adl(); // parse

try {
ADLListener listener = new ADLListener(errors, metaModels);
ADLListener listener = new ADLListener(errors, metaModelProvider);
walker = new ParseTreeWalker();
walker.walk(listener, tree);
result = listener.getArchetype();
Expand All @@ -104,13 +117,13 @@ public Archetype parse(CharStream stream) throws ADLParseException {

if (modelConstraintImposer != null && result.getDefinition() != null) {
modelConstraintImposer.imposeConstraints(result.getDefinition());
} else if (metaModels != null) {
metaModels.selectModel(result);
if (metaModels.getSelectedBmmModel() != null) {
ModelConstraintImposer imposer = new BMMConstraintImposer(metaModels.getSelectedBmmModel());
} else if (metaModelProvider != null) {
MetaModel metaModel = metaModelProvider.selectAndGetMetaModel(result);
if (metaModel.getBmmModel() != null) {
ModelConstraintImposer imposer = new BMMConstraintImposer(metaModel.getBmmModel() );
imposer.setSingleOrMultiple(result.getDefinition());
} else if (metaModels.getSelectedModelInfoLookup() != null) {
ModelConstraintImposer imposer = new ReflectionConstraintImposer(metaModels.getSelectedModelInfoLookup());
} else if (metaModel.getModelInfoLookup() != null) {
ModelConstraintImposer imposer = new ReflectionConstraintImposer(metaModel.getModelInfoLookup());
imposer.setSingleOrMultiple(result.getDefinition());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,18 @@ public ReflectionConstraintImposer(ModelInfoLookup classLookup) {
this.lookup = new MetaModel(classLookup, null);
}

/**
* @deprecated Use {@link #ReflectionConstraintImposer(MetaModel)} instead
*/
@Deprecated
public ReflectionConstraintImposer(MetaModelInterface metaModel) {
this.lookup = metaModel;
}

public ReflectionConstraintImposer(MetaModel metaModel) {
this.lookup = metaModel;
}

private CAttribute createCAttribute(String typeId, String attributeName) {
CAttribute attribute = new CAttribute();

Expand Down
Loading