package com.openMap1.mapper.health.cda;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import org.w3c.dom.Element;
import com.openMap1.mapper.core.MapperException;
import com.openMap1.mapper.util.GenUtil;
import com.openMap1.mapper.util.XMLUtil;
public class TrifoliaConstraint {
/**
* @return the path from the template node or outer constraint node, to the node this constraint applies to
*/
public String context() {return context;}
private String context;
/**
* @return the deep context, including a path through outer constraints from the template
*/
public String deepContext() {return deepContext;}
private String deepContext;
private String cardinality;
private String[] allowedCardinalities = {"0..0","1..1","0..1","0..*","1..*",""};
public boolean hasCardinalities() {return hasCardinalities;}
private boolean hasCardinalities = false;
/**
* @return min cardinality, 0 or 1
*/
public int minCardinality() {return minCardinality;}
private int minCardinality;
/**
* @return max cardnality, 1 or -1 (= *)
*/
public int maxCardinality() {return maxCardinality;}
private int maxCardinality;
private String conformance;
private String[] allowedConformance = {"SHALL","SHOULD","MAY",""};
public boolean hasConformance() {return hasConformance;}
private boolean hasConformance = false;
static int SHALL = 0;
static int SHOULD = 1;
static int MAY = 2;
/**
* @return int constant for SHALL, SHOULD, or MAY
*/
public int conformance()
{
if (conformance.equals("SHALL")) return SHALL;
if (conformance.equals("SHOULD")) return SHOULD;
if (conformance.equals("MAY")) return MAY;
return -1;
}
/**
* @return constraint number as in the IG
*/
public int number() {return number;}
private int number;
/**
* @return true if this constraint defines a single value for the node
*/
public boolean hasSingleValue() {return hasSingleValue;}
private boolean hasSingleValue = false;
/**
* @return the code for a single value defined by this constraint
*/
public String singleValueCode() {return singleValueCode;}
private String singleValueCode = null;
/**
* @return the display name for a single value defined by this constraint
*/
public String singleValueDisplayName() {return singleValueDisplayName;}
private String singleValueDisplayName = null;
/**
* @return the oid of a template required by this constraint
*/
public String containedTemplateOid() {return containedTemplateOid;}
private String containedTemplateOid;
/**
* @return List of immediately nested constraints
*/
public List<TrifoliaConstraint> nestedConstraints() {return nestedConstraints;}
private Vector<TrifoliaConstraint> nestedConstraints = new Vector<TrifoliaConstraint>();
/**
* @return depth of nesting of this constraint - from 0 upwards
*/
public int depth() {return depth;}
private int depth;
public TrifoliaConstraint(Element constraintEl, int depth, String outerContext) throws MapperException
{
try
{
this.depth = depth;
context = constraintEl.getAttribute("context");
deepContext = context;
if (!(outerContext.equals(""))) deepContext = outerContext + "/" + context;
containedTemplateOid = constraintEl.getAttribute("containedTemplateOid");
cardinality = constraintEl.getAttribute("cardinality");
if (!(cardinality.equals(""))) hasCardinalities = true;
if (!GenUtil.inArray(cardinality, allowedCardinalities))
throw new MapperException("Disallowed cardinality: " + cardinality);
minCardinality = 0;
maxCardinality = -1;
if (cardinality.startsWith("1")) minCardinality = 1;
if (cardinality.endsWith("1")) maxCardinality = 1;
if (cardinality.endsWith("0")) maxCardinality = 0;
number = new Integer(constraintEl.getAttribute("number")).intValue();
conformance = constraintEl.getAttribute("conformance");
if (!(conformance.equals(""))) hasConformance = true;
if (!GenUtil.inArray(conformance, allowedConformance))
throw new MapperException("Disallowed conformance: " + conformance);
// single value constraints
Element valueEl = XMLUtil.firstNamedChild(constraintEl, "SingleValueCode");
if (valueEl != null)
{
hasSingleValue = true;
singleValueCode = valueEl.getAttribute("code");
singleValueDisplayName = valueEl.getAttribute("displayName");
}
// nested constraints
Vector<Element> nestedEls = XMLUtil.namedChildElements(constraintEl, "Constraint");
for (int i = 0; i < nestedEls.size();i++)
nestedConstraints.add(new TrifoliaConstraint(nestedEls.get(i),depth + 1,deepContext));
}
catch (Exception ex) {throw new MapperException("Cannot make Trifolia Constraint: " + ex.getMessage());}
}
/**
* if a constraint requires some nested template, then that constraint has a nested constraint
* giving the required template oid as its 'containedTemplateOid' attribute
* @return the required template oid; or null if none is specified
*/
public String requiredTemplateOid()
{
String oid = null;
// there may be several nested constraints, only one of which is a contained template oid
if (nestedConstraints.size() > 1) for (int c = 0; c < nestedConstraints.size(); c++)
{
String possibleOid = nestedConstraints.get(c).containedTemplateOid();
if (!(possibleOid.equals(""))) oid = possibleOid;
}
return oid;
}
/**
* add to a table of fixed value constraints, for this template and its nested templates
* @param fvConstraints
*/
public void addFixedValueConstraints(Hashtable<String,String> fvConstraints)
{
if (hasSingleValue)
{
String path = deepContext;
// the attribute 'code' can stand for some other attribute, if the context is that attribute
if (!(singleValueCode.equals("")))
{
if (!context.startsWith("@")) path = path + "/@code";
fvConstraints.put(path, singleValueCode);
}
// 'displayName' is ignored if the context is an attribute
if ((!(singleValueDisplayName.equals(""))) && (!context.startsWith("@")))
fvConstraints.put(path + "/@displayName", singleValueDisplayName);
}
for (Iterator<TrifoliaConstraint> it = nestedConstraints.iterator();it.hasNext();)
it.next().addFixedValueConstraints(fvConstraints);
}
// private String[] csvHeader = {"Template_Name","Template_id","XPath","Constraint_id","Card.","Value","Comment","Response"};
/**
* add rows to the csv file for this constraint and all its nested constraints
* @param csvOfConstraints
*/
public void addToCSVFile(String templateName, String templateId, Vector<String[]> csvOfConstraints)
{
String[] row = new String[8];
row[0] = templateName;
row[1] = templateId;
row[2] = deepContext();
row[3] = new Integer(number).toString();
row[4] = "";
if (cardinality != null) row[4] = cardinality;
row[5] = "";
if (singleValueCode() != null) row[5] = singleValueCode();
row[6] = "";
row[7] = "";
csvOfConstraints.add(row);
for (Iterator<TrifoliaConstraint> it = nestedConstraints().iterator();it.hasNext();)
it.next().addToCSVFile(templateName, templateId, csvOfConstraints);
}
private void message(String s) {System.out.println(s);}
}