forked from nedap/archie
/
ADL14Converter.java
183 lines (153 loc) · 8.39 KB
/
ADL14Converter.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
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<Archetype> archetypes) {
return convert(archetypes, null);
}
public ADL2ConversionResultList convert(List<Archetype> archetypes, ADL2ConversionRunLog previousConversion) {
ADL2ConversionResultList resultList = new ADL2ConversionResultList();
InMemoryFullArchetypeRepository repository = existingRepository;
if(repository == null) {
repository = new InMemoryFullArchetypeRepository();
}
List<Archetype> unprocessed = new ArrayList<>(archetypes);
List<Archetype> 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");
}
}
}