blob: bbf34bb169577d602306a5047939d23df5b28c6d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2012 David A Carlson and others.
* 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
*
* Contributors:
* David A Carlson (XMLmodeling.com) - initial API and implementation
* John T.E. Timm (IBM Corporation) - added support for contextDependent
* Christian W. Damus - factor out CDA base model dependencies (artf3350)
*
* $Id$
*******************************************************************************/
package org.eclipse.mdht.uml.cda.transform;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.mutable.MutableBoolean;
import org.eclipse.mdht.uml.cda.core.profile.ConformsTo;
import org.eclipse.mdht.uml.cda.core.util.CDAModelUtil;
import org.eclipse.mdht.uml.cda.core.util.CDAProfileUtil;
import org.eclipse.mdht.uml.cda.core.util.ICDAProfileConstants;
import org.eclipse.mdht.uml.transform.EcoreTransformUtil;
import org.eclipse.mdht.uml.transform.IBaseModelReflection;
import org.eclipse.mdht.uml.transform.TransformerOptions;
import org.eclipse.mdht.uml.transform.ecore.AnnotationsUtil;
import org.eclipse.mdht.uml.transform.ecore.IEcoreProfileReflection.ValidationSeverityKind;
import org.eclipse.mdht.uml.transform.ecore.IEcoreProfileReflection.ValidationStereotypeKind;
import org.eclipse.mdht.uml.transform.ecore.TransformAbstract;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.Constraint;
import org.eclipse.uml2.uml.Generalization;
import org.eclipse.uml2.uml.Interface;
import org.eclipse.uml2.uml.OpaqueExpression;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.UMLPackage;
import org.eclipse.uml2.uml.util.UMLUtil;
public class TransformTemplateIdentifier extends TransformAbstract {
private static final String REGISTRY_DELEGATE_NAME = "RegistryDelegate";
public TransformTemplateIdentifier(TransformerOptions options, IBaseModelReflection baseModelReflection) {
super(options, baseModelReflection);
}
@Override
public Object caseClass(Class umlClass) {
Stereotype hl7Template = CDAProfileUtil.getAppliedCDAStereotype(umlClass, ICDAProfileConstants.CDA_TEMPLATE);
if (hl7Template != null) {
addConstraint(umlClass, hl7Template);
addAnnotation(umlClass, hl7Template);
// addExtensionPoint(umlClass, hl7Template);
}
return umlClass;
}
private void addConstraint(Class umlClass, Stereotype hl7Template) {
MutableBoolean requiresParentId = new MutableBoolean(false);
String constraintName = createTemplateConstraintName(umlClass, requiresParentId);
Constraint constraint = umlClass.createOwnedRule(constraintName, UMLPackage.eINSTANCE.getConstraint());
constraint.getConstrainedElements().add(umlClass);
String templateId = (String) umlClass.getValue(hl7Template, ICDAProfileConstants.CDA_TEMPLATE_TEMPLATE_ID);
String templateVersion = (String) umlClass.getValue(hl7Template, ICDAProfileConstants.CDA_TEMPLATE_VERSION);
OpaqueExpression expression = (OpaqueExpression) constraint.createSpecification(
null, null, UMLPackage.eINSTANCE.getOpaqueExpression());
expression.getLanguages().add("OCL");
String versionBody = " and id.extension = '" + templateVersion + "'";
String body = "self.templateId->exists(id : datatypes::II | id.root = '" + templateId + "'" +
(StringUtils.isEmpty(templateVersion)
? ""
: versionBody) +
")";
String message = CDAModelUtil.getValidationMessage(umlClass);
if (message == null) {
message = "The template identifier for " + umlClass.getName() + " must be " + templateId;
}
if (requiresParentId.isTrue()) {
body = "self.templateId->exists(id : datatypes::II | id.root = '" + templateId + "'" +
" and id.extension.oclIsUndefined())";
message = "A compatible R1.1 templateId without an extension must be included " +
"in addition to the existing R2.1 templateId with an extension for " +
convertV2CamelCaseToHumanReadableExceptVersionSuffix(umlClass.getName(), 2) + " " + templateId +
":" + templateVersion + ". " + "When asserting this templateId, " +
"all C-CDA R2.1 document, section, and entry templates that had a previous version in C-CDA R1.1 SHALL include " +
"both the C-CDA R2.1 templateId and the C-CDA R1.1 templateId root without an extension. See C-CDA R2.1 Volume 1 - " +
"Design Considerations for additional detail (CONF:1198-32936, CONF:1198-32934, DSTU:757, DSTU:781).";
}
expression.getBodies().add(body);
addValidationError(umlClass, constraintName, message);
}
private String convertV2CamelCaseToHumanReadableExceptVersionSuffix(String camelCasedV2Template,
int versionSuffix) {
String versionNumber = String.valueOf(versionSuffix);
if (camelCasedV2Template.endsWith(versionNumber)) {
camelCasedV2Template = StringUtils.capitalize(
StringUtils.join(StringUtils.splitByCharacterTypeCamelCase(camelCasedV2Template), " "));
camelCasedV2Template = camelCasedV2Template.replaceFirst(" " + versionNumber, versionNumber);
}
return camelCasedV2Template;
}
protected String createTemplateConstraintName(Class template) {
return createTemplateConstraintName(template, new MutableBoolean(false));
}
protected String createTemplateConstraintName(Class template, MutableBoolean requiresParentId) {
String constraintName = null;
Generalization generalization = null;
ValidationSeverityKind severity = null;
// boolean requiresParentId = false;
if (template.getGeneralizations().size() > 0) {
// use the first generalization, assuming it is used for implementation class extension
generalization = template.getGeneralizations().get(0);
severity = getEcoreProfile().getValidationSeverity(generalization, ValidationStereotypeKind.ANY);
if (severity == null) {
severity = ValidationSeverityKind.ERROR;
}
}
// if general class is a template and conformsTo is ERROR severity
if ((severity == ValidationSeverityKind.ERROR) &&
CDAModelUtil.getTemplateId((Class) generalization.getGeneral()) != null) {
Stereotype stereotype = CDAProfileUtil.applyCDAStereotype(generalization, ICDAProfileConstants.CONFORMS_TO);
if (stereotype != null) {
ConformsTo conformsTo = (ConformsTo) generalization.getStereotypeApplication(stereotype);
requiresParentId.setValue(conformsTo.isRequiresParentId());
}
if (requiresParentId.isFalse()) {
// use constraint name of parent class
constraintName = createTemplateConstraintName((Class) generalization.getGeneral());
} else {
System.out.println("requiresParentId: " + template.getQualifiedName() + " = " + constraintName);
}
}
if (constraintName == null) {
constraintName = createConstraintName(template, "TemplateId");
}
return constraintName;
}
private void addAnnotation(Class umlClass, Stereotype hl7Template) {
String templateId = (String) umlClass.getValue(hl7Template, ICDAProfileConstants.CDA_TEMPLATE_TEMPLATE_ID);
String templateVersion = (String) umlClass.getValue(hl7Template, ICDAProfileConstants.CDA_TEMPLATE_VERSION);
Boolean contextDependent = false;
try {
contextDependent = (Boolean) umlClass.getValue(
hl7Template, ICDAProfileConstants.CDA_TEMPLATE_CONTEXT_DEPENDENT);
} catch (IllegalArgumentException e) {
}
AnnotationsUtil annotationsUtil = getEcoreProfile().annotate(umlClass);
annotationsUtil.setAnnotation("templateId.root", templateId);
if (!StringUtils.isEmpty(templateVersion)) {
annotationsUtil.setAnnotation("templateId.extension", templateVersion);
}
if (contextDependent) {
createRegistryDelegate(umlClass);
annotationsUtil.setAnnotation("contextDependent", "true");
}
annotationsUtil.saveAnnotations();
}
private void createRegistryDelegate(Class umlClass) {
org.eclipse.uml2.uml.Package umlPackage = umlClass.getNearestPackage();
Stereotype ePackage = EcoreTransformUtil.getEcoreStereotype(umlPackage, UMLUtil.STEREOTYPE__E_PACKAGE);
if (umlPackage.isStereotypeApplied(ePackage)) {
String prefix = (String) umlPackage.getValue(ePackage, UMLUtil.TAG_DEFINITION__PREFIX);
String name = prefix + "RegistryDelegate";
if (umlPackage.getOwnedType(name) == null) {
org.eclipse.uml2.uml.Package cdaPackage = getBaseModel(umlClass);
if (cdaPackage != null) {
Interface delegateInterface = (Interface) cdaPackage.getOwnedType(REGISTRY_DELEGATE_NAME);
if (delegateInterface != null) {
Class delegateClass = umlPackage.createOwnedClass(name, false);
delegateClass.createInterfaceRealization(null, delegateInterface);
AnnotationsUtil annotationsUtil = getEcoreProfile().annotate(umlPackage);
annotationsUtil.setAnnotation("registryDelegate", name);
annotationsUtil.saveAnnotations();
}
}
}
}
}
// @SuppressWarnings("unused")
// private void addExtensionPoint(Class umlClass, Stereotype hl7Template) {
// String templateId = (String) umlClass.getValue(hl7Template, ICDAProfileConstants.CDA_TEMPLATE_TEMPLATE_ID);
// String nsURI = null;
//
// // get nsURI from the ePackage stereotype
// org.eclipse.uml2.uml.Package umlPackage = umlClass.getNearestPackage();
// Stereotype ePackage = EcoreTransformUtil.getEcoreStereotype(umlPackage, UMLUtil.STEREOTYPE__E_PACKAGE);
// if (umlPackage.isStereotypeApplied(ePackage)) {
// nsURI = (String) umlPackage.getValue(ePackage, "nsURI");
// }
// else {
// UMLUtil.safeApplyStereotype(umlPackage, ePackage);
// }
// if (nsURI == null) {
// nsURI = "http://www.openhealthtools.org/" + umlPackage.eResource().getURI().lastSegment();
// umlPackage.setValue(ePackage, "nsURI", nsURI);
// }
//
// IFile pluginXML = findPluginXML(umlClass);
//
// if (pluginXML != null && templateId != null) {
// //insert extension point into plugin.xml
// PluginXMLUtil pluginUtil = new PluginXMLUtil(pluginXML);
// pluginUtil.addTemplateExtension(umlClass.getName(), templateId, nsURI);
// }
// }
// private IFile findPluginXML(Element element) {
// IFile pluginXML = null;
//
// // get project file path
// String modelFilePath = element.eResource().getURI().toFileString();
// IWorkspace workspace = ResourcesPlugin.getWorkspace();
// IPath modelLocation = Path.fromOSString(modelFilePath);
// IFile[] files = workspace.getRoot().findFilesForLocation(modelLocation);
// if (files.length > 0) {
// IProject project = files[0].getProject();
// IResource file = project.findMember("plugin.xml");
// if (file instanceof IFile) {
// pluginXML = (IFile)file;
// }
// else {
// // create new plugin.xml
// pluginXML = project.getFile("plugin.xml");
// }
//
// if (!pluginXML.exists()) {
// ByteArrayInputStream is = new ByteArrayInputStream(new byte[0]);
// try {
// pluginXML.create(is, true, null);
// } catch (CoreException e) {
// e.printStackTrace();
// }
// }
// }
//
// return pluginXML;
// }
}