package com.openMap1.mapper.health.cda;
import java.util.Iterator;
import java.util.Vector;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import com.openMap1.mapper.util.GenUtil;
import com.openMap1.mapper.util.ModelUtil;
/**
* This class defines one step in the path defining the context of a CDA
* template - i.e one step in the chain of associations from the top
* class 'ClinicalDocument' of CDA. It includes the templates on the step.
*
* @author robert
*
*/
public class ContextStep {
/**
* @return name of the association leading to this class;
* or null for the first step to ClinicalDocument
*/
public String associationName() {return associationName;}
private String associationName;
/**
* @return name of the class, not qualified with a package name
*/
public String className() {return className;}
private String className;
public String stepName()
{
if (associationName != null) return associationName;
return className;
}
/**
* @return Vector of template ids that are required for this step
*/
public Vector<String> templateIds() {return templateIds;}
private Vector<String> templateIds;
/**
* @return each fixed value is an array {attribute name, required value}
* for the instance of the class (could have used a Hashtable, stupid)
*/
public Vector<String[]> fixedValues() {return fixedValues;}
private Vector<String[]> fixedValues;
//------------------------------------------------------------------------------------------------
// constructor
//------------------------------------------------------------------------------------------------
public ContextStep(String associationName, String className)
{
this.associationName =associationName;
this.className = className;
templateIds = new Vector<String>();
fixedValues = new Vector<String[]>();
}
//------------------------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------------------------
/**
* @param templateId note that this template id is required on this step of the path
*/
public void addTemplateId(String templateId)
{
templateIds.add(templateId);
}
/**
* @param attName an attribute name
* @return its fixed value if it has one; otherwise null
*/
public String getFixedValue(String attName)
{
String value = null;
for (Iterator<String[]> it = fixedValues.iterator(); it.hasNext();)
{
String[] fixedValue = it.next();
if (fixedValue[0].equals(attName)) value = fixedValue[1];
}
return value;
}
/**
*
* @param attName
* @param value
* If no fixed value has yet been set for the attribute, set it and return true.
* If a value has already been set, ignore the new value and return false.
*/
public boolean setFixedValue(String attName, String value)
{
boolean found = false;
for (Iterator<String[]> it = fixedValues.iterator(); it.hasNext();)
if (it.next()[0].equals(attName)) found = true;
if (!found)
{
String[] newValue = new String[2];
newValue[0] = attName;
newValue[1] = value;
fixedValues.add(newValue);
}
return !found;
}
/**
* @param attName an attribute name
* @param attValue a fixed value of the attribute
* @return true if the fixed value conflicts with the existing fixed value
*/
public boolean fixedValueConflict(String attName, String attValue)
{
boolean conflict = false;
for (Iterator<String[]> it = fixedValues.iterator(); it.hasNext();)
{
String[] fixedValue = it.next();
if ((fixedValue[0].equals(attName)) && (!fixedValue[1].equals(attValue)))
conflict = true;
}
return conflict;
}
/**
* @return a clone of this ContextStep
*/
public ContextStep clone()
{
ContextStep clone = new ContextStep(associationName, className);
for (int i = 0; i < fixedValues.size(); i++)
clone.setFixedValue(fixedValues.get(i)[0], fixedValues.get(i)[1]);
for (int i = 0; i < templateIds.size(); i++)
clone.addTemplateId(templateIds.get(i));
return clone;
}
/**
* @return String form of the step, for writing out
*/
public String stringForm()
{
String stringForm = associationName;
if (stringForm == null) stringForm = className;
for (int i = 0; i < fixedValues.size(); i++)
{
String[] fv = fixedValues.get(i);
stringForm = stringForm + "[" + fv[0] + "='" + fv[1] + "']";
}
if (templateIds.size() > 0)
{
stringForm = stringForm + "{";
for (int i = 0; i < templateIds.size(); i++)
{
stringForm = stringForm + templateIds.get(i);
if (i < templateIds.size() -1) stringForm = stringForm + ",";
}
stringForm = stringForm + "}";
}
return stringForm;
}
public String shortStringForm()
{
String res = associationName;
if (templateIds.size() > 0) res = res + "[" + templateIds.size() + "]";
return res;
}
/**
* some step from another context is compatible with this step if:
* (a) The step name (association name or class name) matches
* (b) All the template ids required by this template's context are supplied by the context
* (c) All the fixed values required by this template's context are supplied by the context
* The other context step may have more template ids and fixed values.
* @param other the other context step
* @return true if it is compatible with this one
*/
public boolean compatibleStep(ContextStep other)
{
if (other.stepName().equals(stepName()))
{
boolean compatible = true;
for (int i = 0; i < templateIds.size();i++)
if (!GenUtil.inVector(templateIds.get(i), other.templateIds())) compatible = false;
for (int i = 0; i < fixedValues.size(); i++)
{
String[] fv = fixedValues.get(i);
if (!other.hasFixedValue(fv)) compatible = false;
}
return compatible;
}
return false;
}
/**
*
* @param other
* @return true if the other step is equal to this in association name, template ids and fixedvalues
*/
public boolean equalStep(ContextStep other)
{
return ((compatibleStep(other)) && (other.compatibleStep(this)));
}
/**
*
* @param fixVal a fixed value pair {attribute name, value}
* @return true if this step has the same value for the same attribute
*/
public boolean hasFixedValue(String[] fixVal)
{
boolean hasValue = false;
for (int i = 0; i < fixedValues.size(); i++)
{
String[] fv = fixedValues.get(i);
if ((fv[0].equals(fixVal[0])) && (fv[1].equals(fixVal[1]))) hasValue = true;
}
return hasValue;
}
/**
* @param step a ContextStep leading to an EClass
* @param eClass the EClass at the end of the step
* set all the fixed attribute values of the EClass on the ContextStep
*/
public void setFixedValues(EClass eClass)
{
for (Iterator<EAttribute> ia = eClass.getEAllAttributes().iterator();ia.hasNext();)
{
EAttribute att = ia.next();
String attName = att.getName();
String fixedValue = ModelUtil.getEAnnotationDetail(att,"fixed value");
if (fixedValue != null) setFixedValue(attName, fixedValue);
}
}
/**
* @param templateId
* @return true if this step contains the context
*/
public boolean containsTemplate(String templateId)
{
return GenUtil.inVector(templateId, templateIds);
}
}