<commit_before>/*******************************************************************************
 * Copyright (c) 2009 <NAME>.
 * 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:
 *     <NAME> (XMLmodeling.com) - initial API and implementation
 *     
 * $Id$
 *******************************************************************************/
package org.openhealthtools.mdht.uml.cda.transform;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Enumeration;
import org.eclipse.uml2.uml.LiteralUnlimitedNatural;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Stereotype;
import org.openhealthtools.mdht.uml.cda.transform.internal.Logger;
import org.openhealthtools.mdht.uml.hdf.util.IHDFProfileConstants;

public class TransformVocabConstraint extends TransformAbstract {

	public TransformVocabConstraint(EcoreTransformerOptions options) {
		super(options);
	}
	
	public Object caseProperty(Property property) {
		if (isRemoved(property)) {
			return null;
		}
		
		// only process properties that are owned by a Class
		if (property.getClass_() == null) {
			return null;
		}
		
		Stereotype enumConstraint = EcoreTransformUtil.getAppliedHDFStereotype(
				property, IHDFProfileConstants.ENUMERATION_CONSTRAINT);
		Stereotype valueSet = EcoreTransformUtil.getAppliedHDFStereotype(
				property, IHDFProfileConstants.VALUE_SET_CONSTRAINT);
		Stereotype codeSystem = EcoreTransformUtil.getAppliedHDFStereotype(
				property, IHDFProfileConstants.CODE_SYSTEM_CONSTRAINT);
		
		if (enumConstraint != null) {
			Enumeration enumeration = (Enumeration) property.getValue(enumConstraint, IHDFProfileConstants.ENUMERATION_VALUE);
			//TODO check for stereotype on Enumeration
			
			if (enumeration != null) {
				addAnnotation(property, null, enumeration.getName(), null, null, null);
				addConstraint(property, null, enumeration.getName(), null, null, null);
			}

			//TODO May need to retain property if there are other constraints, e.g. multiplicity
			//   maybe check if there is a property redefinition relationship?
			removeModelElement(property);
		}
		else if (valueSet != null) {
			String valueSetOID = (String) property.getValue(valueSet, IHDFProfileConstants.VALUE_SET_OID);
			String valueSetName = (String) property.getValue(valueSet, IHDFProfileConstants.VALUE_SET_NAME);
			String valueSetVersion = (String) property.getValue(valueSet, IHDFProfileConstants.VALUE_SET_VERSION_DATE);
			String rootCode = (String) property.getValue(valueSet, IHDFProfileConstants.VALUE_SET_ROOT_CODE);

			addAnnotation(property, valueSetOID, valueSetName, rootCode, null, valueSetVersion);
			addConstraint(property, valueSetOID, valueSetName, rootCode, null, valueSetVersion);

			removeModelElement(property);
		}
		else if (codeSystem != null) {
			String codeSystemOID = (String) property.getValue(codeSystem, IHDFProfileConstants.CODE_SYSTEM_OID);
			String codeSystemName = (String) property.getValue(codeSystem, IHDFProfileConstants.CODE_SYSTEM_NAME);
			String codeSystemVersion = (String) property.getValue(codeSystem, IHDFProfileConstants.CODE_SYSTEM_VERSION);
			String code = (String) property.getValue(codeSystem, IHDFProfileConstants.CODE);
			String codePrintName = (String) property.getValue(codeSystem, IHDFProfileConstants.CODE_PRINT_NAME);
			
			addAnnotation(property, codeSystemOID, codeSystemName, code, codePrintName, codeSystemVersion);
			addConstraint(property, codeSystemOID, codeSystemName, code, codePrintName, codeSystemVersion);

			removeModelElement(property);
		}
		
		return property;
	}

	private void addAnnotation(Property property, String codeSystem, String codeSystemName,
			String code, String displayName, String codeSystemVersion) {
		
		if (SEVERITY_INFO.equals(getValidationSeverity(property))) {
			// omit annotation for MAY constraints
			return;
		}

		AnnotationsUtil annotationsUtil = new AnnotationsUtil(property.getClass_());
		if (codeSystem != null) {
			annotationsUtil.setAnnotation(property.getName()+".codeSystem", codeSystem);
		}
		if (codeSystemName != null) {
			annotationsUtil.setAnnotation(property.getName()+".codeSystemName", codeSystemName);
		}
		if (codeSystemVersion != null) {
			annotationsUtil.setAnnotation(property.getName()+".codeSystemVersion", codeSystemVersion);
		}
		if (code != null) {
			annotationsUtil.setAnnotation(property.getName()+".code", code);
		}
		if (displayName != null) {
			annotationsUtil.setAnnotation(property.getName()+".displayName", displayName);
		}
		
		annotationsUtil.saveAnnotations();
	}

	private void addConstraint(Property property, String codeSystem, String codeSystemName,
			String code, String displayName, String codeSystemVersion) {

		StringBuffer body = getValueExpression(property);
		if (body == null) {
			return;
		}

		if (SEVERITY_INFO.equals(getValidationSeverity(property))) {
			// constraint only applies if value is undefined
			body.append("not value.code.oclIsUndefined() and not value.codeSystem.oclIsUndefined()");
		}
		else {
			boolean needsAnd = false;
			if (code != null && code.length() > 0) {
				body.append("value.code = '");
				body.append(code);
				body.append("'");
				needsAnd = true;
			}
			if (codeSystem != null && codeSystem.length() > 0) {
				if (needsAnd) {
					body.append(" and ");
				}
				body.append("value.codeSystem = '");
				body.append(codeSystem);
				body.append("'");
				needsAnd = true;
			}
//			if (codeSystemName != null && codeSystemName.length() > 0) {
//				if (needsAnd) {
//					body.append(" and ");
//				}
//				body.append("value.codeSystemName = '");
//				body.append(codeSystemName);
//				body.append("'");
//				needsAnd = true;
//			}
//			if (codeSystemVersion != null && codeSystemVersion.length() > 0) {
//				if (needsAnd) {
//					body.append(" and ");
//				}
//				body.append("value.codeSystemVersion = '");
//				body.append(codeSystemVersion);
//				body.append("'");
//			}
		}

		if (body.length() > 0) {
			body.append(")");
			addOCLConstraint(property, body);
		}<commit_msg>Use codeSystemName in constraint if codeSystem is not specified. Omit constraint if missing all vocab constraint attributes.<commit_after>/*******************************************************************************
 * Copyright (c) 2009 <NAME>.
 * 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:
 *     <NAME> (XMLmodeling.com) - initial API and implementation
 *     
 * $Id$
 *******************************************************************************/
package org.openhealthtools.mdht.uml.cda.transform;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Enumeration;
import org.eclipse.uml2.uml.LiteralUnlimitedNatural;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Stereotype;
import org.openhealthtools.mdht.uml.cda.transform.internal.Logger;
import org.openhealthtools.mdht.uml.hdf.util.IHDFProfileConstants;

public class TransformVocabConstraint extends TransformAbstract {

	public TransformVocabConstraint(EcoreTransformerOptions options) {
		super(options);
	}
	
	public Object caseProperty(Property property) {
		if (isRemoved(property)) {
			return null;
		}
		
		// only process properties that are owned by a Class
		if (property.getClass_() == null) {
			return null;
		}
		
		Stereotype enumConstraint = EcoreTransformUtil.getAppliedHDFStereotype(
				property, IHDFProfileConstants.ENUMERATION_CONSTRAINT);
		Stereotype valueSet = EcoreTransformUtil.getAppliedHDFStereotype(
				property, IHDFProfileConstants.VALUE_SET_CONSTRAINT);
		Stereotype codeSystem = EcoreTransformUtil.getAppliedHDFStereotype(
				property, IHDFProfileConstants.CODE_SYSTEM_CONSTRAINT);
		
		if (enumConstraint != null) {
			Enumeration enumeration = (Enumeration) property.getValue(enumConstraint, IHDFProfileConstants.ENUMERATION_VALUE);
			//TODO check for stereotype on Enumeration
			
			if (enumeration != null) {
				addAnnotation(property, null, enumeration.getName(), null, null, null);
				addConstraint(property, null, enumeration.getName(), null, null, null);
			}

			//TODO May need to retain property if there are other constraints, e.g. multiplicity
			//   maybe check if there is a property redefinition relationship?
			removeModelElement(property);
		}
		else if (valueSet != null) {
			String valueSetOID = (String) property.getValue(valueSet, IHDFProfileConstants.VALUE_SET_OID);
			String valueSetName = (String) property.getValue(valueSet, IHDFProfileConstants.VALUE_SET_NAME);
			String valueSetVersion = (String) property.getValue(valueSet, IHDFProfileConstants.VALUE_SET_VERSION_DATE);
			String rootCode = (String) property.getValue(valueSet, IHDFProfileConstants.VALUE_SET_ROOT_CODE);

			addAnnotation(property, valueSetOID, valueSetName, rootCode, null, valueSetVersion);
			addConstraint(property, valueSetOID, valueSetName, rootCode, null, valueSetVersion);

			removeModelElement(property);
		}
		else if (codeSystem != null) {
			String codeSystemOID = (String) property.getValue(codeSystem, IHDFProfileConstants.CODE_SYSTEM_OID);
			String codeSystemName = (String) property.getValue(codeSystem, IHDFProfileConstants.CODE_SYSTEM_NAME);
			String codeSystemVersion = (String) property.getValue(codeSystem, IHDFProfileConstants.CODE_SYSTEM_VERSION);
			String code = (String) property.getValue(codeSystem, IHDFProfileConstants.CODE);
			String codePrintName = (String) property.getValue(codeSystem, IHDFProfileConstants.CODE_PRINT_NAME);
			
			addAnnotation(property, codeSystemOID, codeSystemName, code, codePrintName, codeSystemVersion);
			addConstraint(property, codeSystemOID, codeSystemName, code, codePrintName, codeSystemVersion);

			removeModelElement(property);
		}
		
		return property;
	}

	private void addAnnotation(Property property, String codeSystem, String codeSystemName,
			String code, String displayName, String codeSystemVersion) {
		
		if (SEVERITY_INFO.equals(getValidationSeverity(property))) {
			// omit annotation for MAY constraints
			return;
		}

		AnnotationsUtil annotationsUtil = new AnnotationsUtil(property.getClass_());
		if (codeSystem != null) {
			annotationsUtil.setAnnotation(property.getName()+".codeSystem", codeSystem);
		}
		if (codeSystemName != null) {
			annotationsUtil.setAnnotation(property.getName()+".codeSystemName", codeSystemName);
		}
		if (codeSystemVersion != null) {
			annotationsUtil.setAnnotation(property.getName()+".codeSystemVersion", codeSystemVersion);
		}
		if (code != null) {
			annotationsUtil.setAnnotation(property.getName()+".code", code);
		}
		if (displayName != null) {
			annotationsUtil.setAnnotation(property.getName()+".displayName", displayName);
		}
		
		annotationsUtil.saveAnnotations();
	}

	private void addConstraint(Property property, String codeSystem, String codeSystemName,
			String code, String displayName, String codeSystemVersion) {
		
		if (codeSystem == null && codeSystemName == null && code == null) {
			return;
		}

		StringBuffer body = getValueExpression(property);
		if (body == null) {
			return;
		}

		if (SEVERITY_INFO.equals(getValidationSeverity(property))) {
			// constraint only applies if code system is undefined
			body.append("not value.codeSystem.oclIsUndefined() or not value.codeSystemName.oclIsUndefined()");
		}
		else {
			boolean needsAnd = false;
			if (code != null && code.length() > 0) {
				body.append("value.code = '");
				body.append(code);
				body.append("'");
				needsAnd = true;
			}
			if (codeSystem != null && codeSystem.length() > 0) {
				if (needsAnd) {
					body.append(" and ");
				}
				body.append("value.codeSystem = '");
				body.append(codeSystem);
				body.append("'");
				needsAnd = true;
			}
			
			/*
			 * Only add this constraint if codeSystem is not specified.
			 */
			if ((codeSystem == null || codeSystem.length() == 0)
					&& codeSystemName != null && codeSystemName.length() > 0) {
				if (needsAnd) {
					body.append(" and ");
				}
				body.append("value.codeSystemName = '");
				body.append(codeSystemName);
				body.append("'");
				needsAnd = true;
			}
			
//			if (codeSystemVersion != null && codeSystemVersion.length() > 0) {
//				if (needsAnd) {
//					body.append(" and ");
//				}
//				body.append("value.codeSystemVersion = '");
//				body.append(codeSystemVersion);
//				body.append("'");
//			}
		}

		if (body.length() > 0) {
			body.append(")");
			addOCLConstraint(property, body);
		}
{'fraction_non_alphanumeric': 0.13735965931087882, 'fraction_numerical': 0.00286488579171506, 'mean_word_length': 4.6525164113785555, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1096136', 'n_tokens_mistral': 4352, 'n_tokens_neox': 3737, 'n_words': 816}