blob: ddebdac17920b0e4d2f7020aea0358af2d9704f6 [file] [log] [blame]
/**
* Copyright: NEHTA 2015
* Author: Joerg Kiegeland, Distributed Models Pty Ltd
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.mdht.uml.cda.core.util;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EEnumLiteral;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.impl.BasicEObjectImpl;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.ExtendedMetaData;
import org.eclipse.emf.ecore.util.FeatureMap;
import org.eclipse.emf.ecore.util.FeatureMapUtil;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.ecore.xmi.impl.GenericXMLResourceFactoryImpl;
import org.eclipse.emf.ecore.xmi.impl.XMLHelperImpl;
import org.eclipse.emf.ecore.xml.type.AnyType;
import org.eclipse.emf.ecore.xml.type.XMLTypeDocumentRoot;
import org.eclipse.mdht.uml.cda.CDAFactory;
import org.eclipse.mdht.uml.cda.core.profile.TextValue;
import org.eclipse.mdht.uml.term.core.profile.CodeSystemConstraint;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Generalization;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Type;
/**
* Creates clinical documents that can be used as positive (valid CDA documents) or negative (violating certain CDA constraints) test XML files.
*/
public class ClinicalDocumentCreator {
private static final String PLUGIN = "org.openhealthtools.mdht.uml.cda.core";
/**
* The package of {@link #ecoreClinicalDocument}
*/
private EPackage cda_ecore;
/**
* a map from initialized EObject instances to the UML class they were initialized from
*/
private Map<Object, Property> initialized = new HashMap<Object, Property>();
/**
* The clinical document that is initialized
*/
private EObject aClinicalDocument;
/**
* The metamodel for {@link #aClinicalDocument}
*/
private EClass ecoreClinicalDocument;
/**
* The UML model that generated {@link #ecoreClinicalDocument}
*/
private Class umlClinicalDocument;
/**
* When the last two flushed clinical documents have the same contents, note this in the error console
*/
private String lastXML;
private File lastFile;
private Map<Classifier, Collection<Classifier>> specificsOf = new HashMap<Classifier, Collection<Classifier>>();
private List<ModelStatus> statuses;
private Collection<File> createdFiles = new HashSet<File>();
private CDASampler sampler = new CDASampler();
private boolean enableSampleData = false;
private boolean enableSampleDataExpansion;
public ClinicalDocumentCreator(Class umlClinicalDocument, ResourceSet resourceSet, List<ModelStatus> statuses) {
this.umlClinicalDocument = umlClinicalDocument;
this.statuses = statuses;
this.cda_ecore = (EPackage) resourceSet.getEObject(
URI.createURI("pathmap://CDA_MODEL/cda.uml/../cda.ecore#/"), true);
this.ecoreClinicalDocument = (EClass) cda_ecore.getEClassifier("ClinicalDocument");
for (EClass es : ecoreClinicalDocument.getESuperTypes()) {
if (es.eIsProxy()) {
ecoreClinicalDocument = null;
cda_ecore = null;
CDACommonUtils.addStatus(
statuses, IStatus.INFO, PLUGIN, 1, "Pathmap to CDA .ecore files not resolved: " +
((BasicEObjectImpl) es).eProxyURI() + ". Will not use any CDA extension!");
break;
}
}
}
private void createClinicalDocument() {
initialized.clear();
if (ecoreClinicalDocument != null) {
aClinicalDocument = EcoreUtil.create(ecoreClinicalDocument);
} else {
aClinicalDocument = CDAFactory.eINSTANCE.createClinicalDocument();
}
}
protected void discardClinicalDocument() {
aClinicalDocument = null;
}
/**
* Saves the currently constructed clinical document to the given file
*
* @param file
* @throws Exception
*/
public void flushClinicalDocument(File file) throws Exception {
try {
Map<String, Object> options = new HashMap<String, Object>();
// generate no indentation in e.g. "<title>Adverse Reactions</title>", i.e. keep it in one line
options.put(XMLResource.OPTION_EXTENDED_META_DATA, ExtendedMetaData.INSTANCE);
options.put(XMLResource.OPTION_ENCODING, "UTF-8");
String xml = XMLHelperImpl.saveString(options, Arrays.asList(aClinicalDocument), null, null);
// xml = xml.replace("typeCode=\"WIT\"", "typeCode=\"CAGNT\"");
xml = xml.replace("\"datatypes:", "\"");
xml = xml.replace("<cda:", "<");
xml = xml.replace("</cda:", "</");
xml = xml.replace("Extensions_3.0", "ext");
int index = xml.indexOf("<ClinicalDocument");
xml = xml.substring(0, index) +
"<ClinicalDocument xmlns:ext=\"http://ns.electronichealth.net.au/Ci/Cda/Extensions/3.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"urn:hl7-org:v3\">" +
xml.substring(xml.indexOf(">", index) + 1);
xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + xml;
file.getParentFile().mkdirs();
writeFile(xml, file);
} catch (Exception e) {
CDACommonUtils.addStatus(statuses, IStatus.ERROR, PLUGIN, 2, "Cannot serialize file " + file.getName(), e);
}
discardClinicalDocument();
}
/**
* @param file
* @param xml
* @throws IOException
*/
public void writeFile(String xml, File file) throws IOException {
CDACommonUtils.stringToFileIfGenerated(xml, file);
if (!createdFiles.add(file)) {
CDACommonUtils.addStatus(
statuses, IStatus.ERROR, PLUGIN, 11, "File name clash: this file is written more than once: " + file);
}
if (xml.equals(lastXML)) {
System.err.println("Equal files:");
System.err.println(lastFile);
System.err.println(file);
}
lastFile = file;
lastXML = xml;
}
/**
* Initializes a clinical document containing the given clazz while enforcing the mandatory property, skipping the prohibited property and making
* a difference to the diversify property
*
* @param clazz
* mandatory
* @param mandatoryProperty
* optional
* @param prohibitedProperty
* optional
* @param diversifyProperty
* optional
* @return If the mandatory property is not <code>null</code>, returns the instance created for it but <code>null</code> if no instance could be
* created for it; if the mandatory property is <code>null</code>, returns the instance created for clazz but <code>null</code> if no
* instance could be created for it. if <code>null</code> is returned, the possibly partially initialized clinical document is discarded.
*/
public Object initializePath(Class clazz, Property mandatoryProperty, Property prohibitedProperty,
Property diversifyProperty) {
int count = statuses.size();
createClinicalDocument();
List<Property> propertyPath = CDACommonUtils.getPropertyPath(clazz);
if (mandatoryProperty != null) {
propertyPath.add(mandatoryProperty);
}
Object result = initialize(
umlClinicalDocument, aClinicalDocument, propertyPath,
new HashSet<Property>(Arrays.asList(prohibitedProperty)), Arrays.asList(diversifyProperty), null, null);
if (mandatoryProperty != null) {
if (getInitializedByProperty(result) == mandatoryProperty) {
return result;
}
} else {
if (getInitializedByClass(result) == clazz) {
return result;
}
if (result == null && clazz == umlClinicalDocument) {
return aClinicalDocument;
}
}
if (count == statuses.size() && mandatoryProperty != null) {
CDACommonUtils.addStatus(
statuses, IStatus.WARNING, PLUGIN, 6,
CDACommonUtils.getUmlContextDoubled(mandatoryProperty) + " could not be initialized",
mandatoryProperty);
}
discardClinicalDocument();
return null;
}
/**
* Initializes only an instance for the given class, without embedding it into a clinical document
*
* @param clazz
* @return
*/
public EObject initializeSnippet(Class clazz, Collection<Property> mandatoryProperty) {
createClinicalDocument();
Classifier cdaChildClass = CDACommonUtils.getCDAType(clazz);
if (cdaChildClass == null) {
CDACommonUtils.addStatus(
statuses, IStatus.ERROR, PLUGIN, 9,
"Found no CDA base class for " + CDACommonUtils.getUmlContext(clazz), clazz);
return null;
}
EClass eClass = null;
for (EPackage ePackage : CDACommonUtils.getAllContents(
aClinicalDocument.eClass().eResource(), EPackage.class)) {
// look in the root package (named "cda") or its child extension package (not named "cda"!)
if ("cda".equals(ePackage.getName()) == "cda".equals(cdaChildClass.getNearestPackage().getName())) {
eClass = (EClass) ePackage.getEClassifier(cdaChildClass.getName());
}
}
if (eClass == null) {
CDACommonUtils.addStatus(
statuses, IStatus.ERROR, PLUGIN, 9, "Found no Runtime class for " + CDACommonUtils.getUmlContext(clazz),
clazz);
return null;
}
EObject eObject = EcoreUtil.create(eClass);
initialize(clazz, eObject, mandatoryProperty, new HashSet<Property>(), new HashSet<Property>(), null, null);
return eObject;
}
public EObject initializeSnippet(Class clazz) {
return initializeSnippet(clazz, Collections.<Property> emptyList());
}
/**
* Initializes a clinical document with the given mandatory properties
*
* @param mandatoryProperty
* if not all dependent properties are also included for a given property in this list, a given property may be not initialized
* @return
*/
public void initialize(Collection<Property> mandatoryProperty) {
createClinicalDocument();
initialize(
umlClinicalDocument, aClinicalDocument, mandatoryProperty, new HashSet<Property>(),
Collections.<Property> emptyList(), null, null);
}
protected Object initialize(Class parentClass, EObject parent, Collection<Property> mandatoryProperty,
Set<Property> prohibitedProperty, Collection<Property> diversifyProperty, Property parentProperty,
Object result) {
if (enableSampleData) {
sampler.mergeSampleXML(parentClass, parent);
}
Property oldProperty = initialized.put(parent, parentProperty);
if (oldProperty != null) {
CDACommonUtils.addStatus(
statuses, IStatus.WARNING, PLUGIN, 5,
"Double-initialization by " + CDACommonUtils.getUmlContext(parentProperty) + " and " +
CDACommonUtils.getUmlContext(oldProperty),
parentProperty, oldProperty);
}
String templateId = CDACommonUtils.getTemplateId(parentClass);
Property templateIdProperty = getTemplateIdProperty(parentClass);
if (templateId != null && templateIdProperty != null && !prohibitedProperty.contains(templateIdProperty)) {
EStructuralFeature templateIdFeatureFeature = parent.eClass().getEStructuralFeature("templateId");
EObject templateIdInstance = EcoreUtil.create((EClass) templateIdFeatureFeature.getEType());
templateIdInstance = setOrAdd(parent, templateIdFeatureFeature, templateIdInstance);
setOrAdd(
templateIdInstance, "root", templateId + (diversifyProperty.contains(templateIdProperty)
? "TYPO"
: ""));
String extension = CDAModelUtil.getTemplateVersion(parentClass);
if (extension != null) {
setOrAdd(templateIdInstance, "extension", extension);
}
initialized.put(templateIdInstance, templateIdProperty);
if (mandatoryProperty.contains(templateIdProperty) &&
(parentProperty == null || mandatoryProperty.contains(parentProperty))) {
result = templateIdInstance;
}
}
for (Property property : CDACommonUtils.allAttributes(parentClass)) {
if (property == templateIdProperty && templateId != null) {
// already initialized
continue;
}
result = initializeProperty(
property, parent, mandatoryProperty, prohibitedProperty, diversifyProperty, parentClass, result);
}
return result;
}
/**
* Creates another value for the given UML property besides the one already created (propertyInstance)
*
* @param property
* @param propertyInstance
* @return the new property value
*/
public Object repopulateProperty(Property property, EObject propertyInstance) {
initialized.remove(propertyInstance);
EObject parent = propertyInstance.eContainer();
Class parentClass = (Class) getInitializedByClass(parent);
return initializeProperty(
property, parent, Arrays.asList(property), new HashSet<Property>(), Collections.<Property> emptyList(),
parentClass, null);
}
/**
* @param property
* @param parent
* @param mandatoryProperty
* @param prohibitedProperty
* @param diversifyProperty
* @param needInit
* @param typeIdentifyingProperty
* @param result
* @return
*/
protected Object initializeProperty(Property property, EObject parent, Collection<Property> mandatoryProperty,
Set<Property> prohibitedProperty, Collection<Property> diversifyProperty, Class parentClass,
Object result) {
EStructuralFeature feature = getStructuralFeature(parent, property);
if (feature == null || prohibitedProperty.contains(property)) {
return result;
}
boolean structuralRequired = property.getLower() > 0 ||
CDACommonUtils.getPropertyForTypeCheck(parentClass) == property ||
CDACommonUtils.getPropertyForCodeOrClasscodeCheck(parentClass) == property ||
diversifyProperty.contains(property) || mandatoryProperty.contains(property);
sampler.descentProperty(property);
while (sampler.hasData() && (enableSampleDataExpansion || feature.getEType() instanceof EDataType) ||
structuralRequired) {
try {
if (feature.getEType() instanceof EDataType) {
EDataType eDataType = (EDataType) feature.getEType();
Object def = null;
String dv = sampler.getSample();
if (dv == null) {
dv = CDACommonUtils.getDefault(property);
}
try {
if (parent.eGet(feature) instanceof FeatureMap) {
def = getValueForFeaturemap(feature, dv);
} else if (dv != null) {
def = EcoreUtil.createFromString(eDataType, dv);
}
} catch (Exception e) {
CDACommonUtils.addStatus(
statuses, IStatus.ERROR, PLUGIN, 7,
"Cannot parse default value \"" + dv + "\" for property " +
CDACommonUtils.getUmlContextDoubled(property) + " as " +
(eDataType.getName() != null
? eDataType.getName()
: eDataType),
e, property);
}
Object val = null;
if (!diversifyProperty.contains(property) && def != null) {
try {
feature.setUnsettable(true);
} catch (Exception e) {
}
val = setOrAdd(parent, feature, def);
} else if (eDataType instanceof EEnum) {
EEnum eEnum = (EEnum) eDataType;
EEnumLiteral literal = eEnum.getEEnumLiteral(eEnum.getELiterals().size() - 1);
if (def != null && literal == def) {
literal = eEnum.getEEnumLiteral(eEnum.getELiterals().size() - 2);
}
if (literal != null) {
val = setOrAdd(parent, feature, literal.getInstance());
} else {
}
} else if (eDataType.getInstanceClass() != null &&
eDataType.getInstanceClass().isAssignableFrom(String.class)) {
val = setOrAdd(
parent, feature, def instanceof String
? ((String) def) + "TYPO"
: "testString");
} else if (eDataType.getInstanceClass() != null &&
eDataType.getInstanceClass().isAssignableFrom(Boolean.class)) {
val = setOrAdd(
parent, feature, def instanceof Boolean
? !((Boolean) def)
: true);
} else if (eDataType.getInstanceClass() != null &&
eDataType.getInstanceClass().isAssignableFrom(BigInteger.class)) {
val = setOrAdd(
parent, feature, def instanceof BigInteger
? ((BigInteger) def).add(BigInteger.valueOf(1))
: BigInteger.valueOf(999));
} else {
CDACommonUtils.addStatus(
statuses, IStatus.ERROR, PLUGIN, 8,
"Cannot initialize value for property " + CDACommonUtils.getUmlContextDoubled(property) +
" for datatype " + (eDataType.getName() != null
? eDataType.getName()
: eDataType),
property);
}
if (mandatoryProperty.contains(property)) {
initialized.put(val, property);
result = val;
}
} else {
if (!(property.getType() instanceof Class)) {
return result;
}
Class childClass = (Class) property.getType();
EObject child = null;
Object oldValue = parent.eGet(feature);
for (Object object : oldValue instanceof List
? (List<?>) oldValue
: Arrays.asList(oldValue)) {
if (getInitializedByClass(object) == childClass && property.getUpper() == 1) {
child = (EObject) object;
}
}
if (child == null) {
EClass eClass = (EClass) feature.getEType();
Classifier cdaChildClass = CDACommonUtils.getCDAType(childClass);
if (cdaChildClass == null) {
CDACommonUtils.addStatus(
statuses, IStatus.ERROR, PLUGIN, 9,
"Found no CDA base class for " + CDACommonUtils.getUmlContext(childClass), childClass);
return result;
}
if (!cdaChildClass.getName().equals(eClass.getName())) {
EClassifier eClass1 = eClass.getEPackage().getEClassifier(cdaChildClass.getName());
if (eClass1 != null) {
eClass = (EClass) eClass1;
}
}
if (diversifyProperty.contains(property) || eClass.isAbstract()) {
EClassifier otherClass = null;
for (Classifier classifier : getSpecific(childClass)) {
if (!classifier.isAbstract()) {
if (classifier.getName() != null &&
classifier.getName().equals(childClass.getName())) {
// makes no difference in serialization if same named, so don't allow it!
continue;
}
otherClass = eClass.getEPackage().getEClassifier(classifier.getName());
if (otherClass != null) {
break;
}
}
}
if (otherClass != null) {
eClass = (EClass) otherClass;
} else {
CDACommonUtils.addStatus(
statuses, IStatus.ERROR, PLUGIN, 10,
"Cannot find a different class other than " + eClass.getName(), property);
return result;
}
}
if (property.getLower() == 0) {
int level = 0;
EObject aParent = parent;
while (aParent != null) {
if (aParent.eClass() == eClass || level >= 10) {
// prevent endless recursion
return result;
}
aParent = aParent.eContainer();
level++;
}
}
child = EcoreUtil.create(eClass);
child = setOrAdd(parent, feature, child);
}
CodeSystemConstraint codeSystemConstraint = CDACommonUtils.getCodeSystemConstraint(property);
if (codeSystemConstraint != null && codeSystemConstraint.getCode() != null) {
setOrAdd(
child, "code", codeSystemConstraint.getCode() + (diversifyProperty.contains(property)
? "TYPO"
: ""));
}
if (codeSystemConstraint != null && CDACommonUtils.getCodeSystem(codeSystemConstraint) != null) {
setOrAdd(child, "codeSystem", CDACommonUtils.getCodeSystem(codeSystemConstraint));
}
if (codeSystemConstraint != null && codeSystemConstraint.getDisplayName() != null) {
setOrAdd(child, "displayName", codeSystemConstraint.getDisplayName());
}
EStructuralFeature mixedFeature = child.eClass().getEStructuralFeature("mixed");
Object mixed = mixedFeature != null
? child.eGet(mixedFeature)
: null;
if (mixed instanceof FeatureMap) {
String text = sampler.getSample();
if (text == null) {
TextValue textValue = CDACommonUtils.getTextValue(property);
text = textValue != null
? textValue.getValue()
: null;
}
if (text != null) {
text = text.trim() + (diversifyProperty.contains(property)
? "TYPO"
: "");
FeatureMapUtil.addText((FeatureMap) mixed, text);
}
}
if (mandatoryProperty.contains(property)) {
result = child;
}
// prohibitedProperty.add(property);
result = initialize(
childClass, child, mandatoryProperty, prohibitedProperty, diversifyProperty, property, result);
}
} finally {
sampler.ascentProperty();
}
structuralRequired = false;
sampler.descentProperty(property);
}
sampler.ascentProperty();
return result;
}
private Object getValueForFeaturemap(EStructuralFeature feature, String string) throws IOException {
if ("any".equals(feature.getName())) {
/**
* @see org.openhealthtools.mdht.uml.cda.operations.SectionOperations#createStrucDocText()
*/
Resource.Factory factory = new GenericXMLResourceFactoryImpl();
XMLResource resource = (XMLResource) factory.createResource(null);
resource.load(new URIConverter.ReadableInputStream("<text>" + string + "</text>"), null);
XMLTypeDocumentRoot root = (XMLTypeDocumentRoot) resource.getContents().get(0);
AnyType value = (AnyType) root.getMixed().getValue(0);
return value.getMixed();
}
return string;
}
public Type getInitializedByClass(Object object) {
if (object == aClinicalDocument) {
return umlClinicalDocument;
}
Property parentProperty = initialized.get(object);
if (parentProperty != null && object != null) {
return parentProperty.getType();
} else {
return null;
}
}
public Property getInitializedByProperty(Object object) {
return initialized.get(object);
}
private Collection<Classifier> getSpecific(Class clazz) {
if (specificsOf.isEmpty()) {
Iterator<Object> it = EcoreUtil.getAllContents(clazz.eResource().getResourceSet(), false);
while (it.hasNext()) {
Object eObject = it.next();
if (eObject instanceof Classifier) {
Classifier specific = (Classifier) eObject;
for (Generalization generalization : specific.getGeneralizations()) {
Classifier general = generalization.getGeneral();
Collection<Classifier> specifics = specificsOf.get(general);
if (specifics == null) {
specificsOf.put(general, specifics = new ArrayList<Classifier>());
}
if (!specifics.contains(specific)) {
specifics.add(specific);
}
}
}
}
}
if (specificsOf.get(clazz) != null) {
return specificsOf.get(clazz);
}
return Collections.emptyList();
}
/**
* @param parent
* @param property
* @return
*/
private EStructuralFeature getStructuralFeature(EObject parent, Property property) {
Property cdaProperty = CDACommonUtils.getCDAProperty(property);
if (cdaProperty != null && parent != null) {
EStructuralFeature feature = parent.eClass().getEStructuralFeature(cdaProperty.getName());
if (feature == null) {
CDACommonUtils.addStatus(
statuses, IStatus.WARNING, PLUGIN, 4,
"No Java/Ecore mapping for property " + CDACommonUtils.getUmlContextDoubled(property) + ")",
property);
}
return feature;
}
return null;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private <T> T setOrAdd(EObject eObject, EStructuralFeature feature, T value) {
try {
if (eObject.eGet(feature) instanceof FeatureMap && value instanceof String) {
FeatureMap featureMap = (FeatureMap) eObject.eGet(feature);
FeatureMapUtil.addText(featureMap, (String) value);
} else if (feature.isMany()) {
List list = (List) eObject.eGet(feature);
if (value instanceof List) {
list.addAll((List) value);
} else {
list.add(value);
}
} else {
eObject.eSet(feature, value);
}
} catch (ClassCastException cce) {
// Ignore error - this is the result of modeling issue
}
return value;
}
private <T> T setOrAdd(EObject eObject, String featureName, T value) {
return setOrAdd(eObject, eObject.eClass().getEStructuralFeature(featureName), value);
}
public void forgetLastFileContent() {
lastXML = null;
}
public Property getTemplateIdProperty(Class clazz) {
Property result = CDACommonUtils.findAttribute(clazz, "templateId");
if (result != null) {
result = CDACommonUtils.getCDAProperty(result);
}
return result;
}
/**
* @return the cda_ecore
*/
public EPackage getCdaEcore() {
return cda_ecore;
}
/**
* Removes trailing digits from the name
*
* @param name
* @return
*/
public static String withoutDigits(String name) {
while (!"".equals(name) && Character.isDigit(name.charAt(name.length() - 1))) {
name = name.substring(0, name.length() - 1);
}
return name;
}
public String toXMLString(EObject eObject, Class clazz) {
return toXMLString(eObject, clazz, new HashMap<String, Object>());
}
public String toXMLString(EObject eObject, Class clazz, Map<String, Object> options) {
// generate no indentation in e.g. "<title>Adverse Reactions</title>", i.e. keep it in one line
options.put(XMLResource.OPTION_EXTENDED_META_DATA, ExtendedMetaData.INSTANCE);
options.put(XMLResource.OPTION_ENCODING, "UTF-8");
String xml;
try {
xml = XMLHelperImpl.saveString(options, Arrays.asList(eObject), null, null);
} catch (Exception e1) {
e1.printStackTrace();
return null;
}
xml = xml.replace("\"datatypes:", "\"");
xml = xml.replace("<cda:", "<");
xml = xml.replace("</cda:", "</");
xml = xml.replace("Extensions_3.0", "ext");
xml = xml.replace("xmlns:cda=\"urn:hl7-org:v3\"", "xmlns=\"urn:hl7-org:v3\"");
String eName = eObject.eClass().getName();
if (!"ClinicalDocument".equals(eName)) {
String rootTag = withoutDigits(eName.substring(0, 1).toLowerCase() + eName.substring(1));
if (eObject.eContainmentFeature() != null) {
rootTag = eObject.eContainingFeature().getName();
} else if (clazz != null && CDACommonUtils.getOverallPropertyReference(clazz) != null) {
Property cdaProperty = CDACommonUtils.getCDAProperty(CDACommonUtils.getOverallPropertyReference(clazz));
if (cdaProperty != null) {
rootTag = cdaProperty.getName();
}
}
xml = xml.replace("<" + eName, "<" + rootTag);
xml = xml.replace("</" + eName, "</" + rootTag);
xml = xml.replace(" xmlns=\"urn:hl7-org:v3\"", "");
xml = xml.replace(" xmi:version=\"2.0\"", "");
xml = xml.replace(" xmlns:xmi=\"http://www.omg.org/XMI\"", "");
xml = xml.replace(" xmlns:datatypes=\"http://www.openhealthtools.org/mdht/uml/hl7/datatypes\"", "");
xml = xml.replace(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"", "");
} else {
xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + xml;
}
// int index = xml.indexOf("<"+eName);
// xml = xml.substring(0, index) +
// "<ClinicalDocument xmlns:ext=\"http://ns.electronichealth.net.au/Ci/Cda/Extensions/3.0\"
// xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"urn:hl7-org:v3\">"
// + xml.substring(xml.indexOf(">", index) + 1);
return xml;
}
public void enableSampleData(boolean value) {
enableSampleData = value;
}
public void enableSampleDataExpansion(boolean value) {
enableSampleDataExpansion = value;
}
public EObject getClinicalDocument() {
return aClinicalDocument;
}
public CDASampler getSampler() {
return sampler;
}
}