package com.openMap1.mapper.writer; import com.openMap1.mapper.core.*; import com.openMap1.mapper.mapping.*; import java.util.*; /** * The context of a node in the output XML tree, while * generating wproc code. * * @author robert * */ public class codingContext extends outputContext { /* anticipated grouping criteria in force; each grouping criterion is represented by a (classSet, property name) pair where the property will be used to group objects beneath this node or a higher node. If property name = null, an association to an object in the classSet will be used. */ private Vector<propSet> groupingCriteria; /* vector of the path specifications (definite or indefinite XPaths) for all outer procedures on the way down to the current one. */ private Vector<Xpth> pathSpecs; // multiplicity of this element as defined by the XML tree structure private multiplicity mult; /* Last element of the vector = number identifier of the case currently being handled, according to the numbering of the table on page 35 of the development log for May 2002 */ private Vector<String> caseNumbers; /* true if the element has not failed its case check. */ private boolean elementOK; // if true, write code generation trace messages private boolean codeTracing; /* If this is true, a choice between several when-condition values has been made on this node, so the current procedure is one of several procedures for different when-values, to be called in succession. Therefore semantic maxOccurs = 1 (in one procedure) leads to actual maxOccurs = N (from the procedures called in series). whenChoiceMade is not propagated down to contexts for lower nodes by copyCC(). */ // private boolean whenChoiceMade; not used public Vector<propSet> groupingCriteria() {return groupingCriteria;} public Vector<String> caseNumbers() {return caseNumbers;} public String getCase() {return caseNumbers.elementAt(caseNumbers.size());} public multiplicity mult() {return mult;} public boolean elementOK() {return elementOK;} public boolean codeTracing() {return codeTracing;} public void addGroupingCriterion(propSet ps) {groupingCriteria.addElement(ps);} public void setMultiplicity(multiplicity m) {mult = m;} protected void setCaseNumbers(Vector<String> cn) {caseNumbers = cn;} protected void setTracing(boolean b) {codeTracing = b;} public void addPathSpec(Xpth ps) {pathSpecs.addElement(ps);} /* coding case number is usually added by checkCase, which also checks minOccurs and maxOccurs against the array below. */ public void setCase(String caseNumber){caseNumbers.addElement(caseNumber);} public codingContext(MDLBase md, Xpth rp, boolean trace) { super(md, rp); groupingCriteria = new Vector<propSet>(); pathSpecs = new Vector<Xpth>(); elementOK = true; caseNumbers = new Vector<String>(); codeTracing = trace; } /* deep copy as starting point for changes to a new version. However, this clone has 'revisit' false - not copied across from this context. Assume ab initio that a child element will not require a revisit procedure. Do not copy over whenChoiceMade. */ public codingContext copyCC() throws MDLWriteException { int i; codingContext cc = new codingContext(MD,rootPath().copy(),codeTracing); for (i = 0; i < uniqueCSets().size(); i++) {cc.addUniqueCSet(uniqueCSets().elementAt(i));} for (Enumeration<whenValue> en = whenValues().elements(); en.hasMoreElements();) {cc.setWhenValue(en.nextElement());} for (i = 0; i < groupingCriteria.size(); i++) {cc.addGroupingCriterion(groupingCriteria.elementAt(i));} for (i = 0; i < pathSpecs.size(); i++) {cc.addPathSpec(pathSpecs.elementAt(i));} cc.setCaseNumbers(caseNumbers); cc.setMultiplicity(mult); cc.setTracing(codeTracing); return cc; } // make a deep copy and append to the vector of whenValues public codingContext fixWhenValues(Vector<whenValue> whens) throws MDLWriteException { codingContext cc = copyCC(); for (int i = 0; i < whens.size(); i++) try { whenValue wv = (whenValue)whens.elementAt(i); cc.setWhenValue(wv); } catch (Exception e) {codeError("fatal",rootPath(),"Vector in fixWhenValues is not a vector of when-values","");} return cc; } public Xpth latestPathSpec() { Xpth ps = null; if (pathSpecs.size() > 0) {ps = pathSpecs.elementAt(pathSpecs.size()-1);} return ps; } /* */ public Xpth latestOuterDefinitePathSpec() throws XpthException { Xpth ps = null; if (pathSpecs.size() > 0) {ps = pathSpecs.elementAt(pathSpecs.size()-1).outerDefinitePart();} return ps; } public boolean isStillDefinite() throws XpthException { boolean res = true; if (pathSpecs.size() > 0) {res = pathSpecs.elementAt(pathSpecs.size()-1).definite();} return res; } public boolean alreadyHasPathSpec(Xpth ps) { boolean res = false; for (int i = 0; i < pathSpecs.size(); i++) { Xpth pt = pathSpecs.elementAt(i); if (pt.equalPath(ps)) res = true; } return res; } // message for errors detected in code generation void codeError(String type, Xpth p, String s1, String s2) throws MDLWriteException { String preface = "Fatal error"; if (type.equals("warning")) {preface = "Warning";} else if (type.equals("warningCheck")){preface = "Warning";} else if (type.equals("check")){preface = "Error";} else if (type.equals("bad")){preface = "Error";} message(""); message(preface + " at node '" + p.stringForm() + "': "); message(s1); if (!(s2.equals(""))) message(s2); if (type.equals("fatal")) throw new MDLWriteException("Fatal error terminated code generation."); } //------------------------------------------------------------------------------------------------ // //------------------------------------------------------------------------------------------------ void message(String s) {System.out.println(s);} }