1// BEGIN LICENSE BLOCK
2// Version: CMPL 1.1
3//
4// The contents of this file are subject to the Cisco-style Mozilla Public
5// License Version 1.1 (the "License"); you may not use this file except
6// in compliance with the License.  You may obtain a copy of the License
7// at www.eclipse-clp.org/license.
8//
9// Software distributed under the License is distributed on an "AS IS"
10// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
11// the License for the specific language governing rights and limitations
12// under the License.
13//
14// The Original Code is  CPViz Constraint Visualization System
15// The Initial Developer of the Original Code is  Helmut Simonis
16// Portions created by the Initial Developer are
17// Copyright (C) 2009-2010 Helmut Simonis
18//
19// Contributor(s): 	Helmut Simonis, 4C, Univerity College Cork, Cork
20//
21//
22// END LICENSE BLOCK
23// ----------------------------------------------------------------------
24package ie.ucc.cccc.viz;
25
26import java.io.*;
27
28import javax.xml.parsers.*;
29import org.xml.sax.*;
30import org.xml.sax.helpers.*;
31import java.util.*;
32
33/**
34 * The is the entry point for the Viz application. The program parses
35 * three XML files and produces output files accordingly.
36 * @author hsimonis
37 *
38 */
39public class Viz {
40	static private Tools tools;
41	static private PrintWriter idx;
42	static private Tree tree;
43	static private int countInvariant;
44	/**
45	 * This is the entry point for the command line interface. It works with three file names
46	 * @param args String array with three entries config tree and viz files, all in XML format
47	 */
48	public static void main(String[] args)
49
50	throws SAXException,IOException,ParserConfigurationException {
51
52		if (args.length != 3) {
53			System.out.println("Usage: viz configfile treefile vizfile");
54			for(int i=0;i<args.length;i++) {
55				System.out.println(args[i]);
56			}
57			return;
58		}
59		String configFilename = args[0];
60		String treeFilename = args[1];
61		String vizFilename = args[2];
62		runViz(configFilename,treeFilename,vizFilename);
63	}
64
65	/**
66	 * Method to run the viz program inside another program
67	 * @param configFilename String filename for the configuration
68	 * @param treeFilename String filename for the tree log
69	 * @param vizFilename String filename for the viz log
70	 * @throws SAXException
71	 * @throws IOException
72	 * @throws ParserConfigurationException
73	 */
74	static public void runViz(String configFilename,String treeFilename,String vizFilename)
75	throws SAXException,IOException,ParserConfigurationException {
76		countInvariant = 0;
77		System.out.println("Running: viz " + configFilename +
78				" "+ treeFilename+ " "+ vizFilename);
79
80		SAXParserFactory configFactory = SAXParserFactory.newInstance();
81		SAXParser configParser = configFactory.newSAXParser();
82		ConfigHandler configHandler = new ConfigHandler();
83		configParser.parse(new File(configFilename),configHandler);
84		System.out.println(configFilename +" contains " + configHandler.numNodes +
85				" nodes ");
86//		System.out.println("Tools" + configHandler.getTools());
87		tools = configHandler.getTools();
88
89		SAXParserFactory treeFactory = SAXParserFactory.newInstance();
90		SAXParser treeParser = treeFactory.newSAXParser();
91		TreeHandler treeHandler = new TreeHandler();
92		try{
93			treeParser.parse(new File(treeFilename),treeHandler);
94		} catch (IllegalArgumentException e) {
95			System.out.println("Caught "+e);
96		}
97		System.out.println(treeFilename +" contains " + treeHandler.numNodes +
98				" nodes ");
99
100		// the tree exists for marking purposes
101		tree = treeHandler.tree;
102
103		// create an idx file; this needs more work to respect TOOL
104		try {
105			File f = new File(tools.getDirectory(),tools.getIdx()+".idx");
106			idx = new PrintWriter(new FileWriter(f));
107		} catch (IOException e) {
108			System.out.println("Can not create idx file");
109		}
110		if (tools.hasVizTools()){
111			SAXParserFactory vizFactory = SAXParserFactory.newInstance();
112			SAXParser vizParser = vizFactory.newSAXParser();
113			VizHandler vizHandler = new VizHandler();
114			vizParser.parse(new File(vizFilename),vizHandler);
115			System.out.println(vizFilename +" contains " + vizHandler.numNodes +
116			" nodes ");
117		}
118		// close the idx file; needs cleanup
119		idx.close();
120
121		// run all Tree Tools on the tree data structure
122		for(Tool tool : tools.getTreeTools()){
123			tool.handleTree(tree);
124		}
125		if (countInvariant > 0) {
126			System.out.println("There were "+countInvariant+" Invariant violations.");
127		}
128	}
129
130
131	static String getAttribute(String attributeName,Attributes attributes) {
132		return getAttribute(attributeName,attributes,null);
133	}
134	static String getAttribute(String attributeName,
135			Attributes attributes,String defaultValue) {
136		String e = attributes.getValue(attributeName);
137		if (e==null) {
138			return defaultValue;
139		} else {
140			return e;
141		}
142	}
143
144	static int getInteger(String attributeName,Attributes attributes) {
145		return getInteger(attributeName,attributes,0);
146	}
147	static int getInteger(String attributeName,Attributes attributes,
148			int defaultValue) {
149		String e = attributes.getValue(attributeName);
150		if (e==null) {
151			return defaultValue;
152		} else {
153			return Integer.parseInt(e);
154		}
155	}
156
157	static void markTreeNode(InvariantType type,int treeNode){
158		countInvariant++;
159		Node node = tree.getMap().get(treeNode);
160		if (node != null){
161//			System.out.println("Node "+node.getId()+" "+node.getType());
162			node.setInvariantType(type);
163		}
164	}
165	private static class ConfigHandler extends DefaultHandler {
166		private Tools tools = new Tools();
167		private int numNodes=0;
168
169		private Tools getTools() {
170			return tools;
171		}
172		private String getShow(Attributes attributes) {
173			return getAttribute("show",attributes,"tree");
174		}
175		private String getType(Attributes attributes) {
176			return getAttribute("type",attributes,"layout");
177		}
178		private String getDisplay(Attributes attributes) {
179			return getAttribute("display",attributes,"compact");
180		}
181		private String getRepeat(Attributes attributes) {
182			return getAttribute("repeat",attributes,"final");
183		}
184		private int getWidth(Attributes attributes) {
185			return getInteger("width",attributes,500);
186		}
187		private int getHeight(Attributes attributes) {
188			return getInteger("height",attributes,500);
189		}
190		private String getDirectory(Attributes attributes) {
191			return getAttribute("directory",attributes,"TREE");
192		}
193		private String getIdx(Attributes attributes) {
194			return getAttribute("idx",attributes,"aaa");
195		}
196		private String getFileRoot(Attributes attributes) {
197			return getAttribute("fileroot",attributes,"tree");
198		}
199
200		private String getVersion(Attributes attributes) {
201			return getAttribute("version",attributes);
202		}
203
204		public void startDocument() {
205			System.out.println("Started Config Document");
206		}
207
208		public void endDocument() {
209			System.out.println("End Document");
210		}
211		public void processingInstruction(String target,String data){
212			System.out.println("Process target"+target+" data "+data);
213		}
214		public void startElement(String uri,
215				String localname, String qname,
216				Attributes attributes) {
217			if (qname.equals("configuration")) {
218				String version=getVersion(attributes);
219				tools.setDirectory(getDirectory(attributes));
220				tools.setIdx(getIdx(attributes));
221				if (!version.equals("1.0")) {
222					System.out.println("Wrong version "+version);
223				};
224			} else if (qname.equals("tool")){
225				numNodes++;
226				tools.addTool(new Tool(tools,
227						getShow(attributes),
228						getType(attributes),
229						getDisplay(attributes),
230						getRepeat(attributes),
231						getWidth(attributes),
232						getHeight(attributes),
233						getFileRoot(attributes)
234						));
235			} else {
236				System.out.println("Wrong Element Structure "+qname);
237				numNodes++;
238			}
239		}
240	}
241
242	private static class TreeHandler extends DefaultHandler {
243		private Tree tree;
244		private int numNodes=0;
245
246		private int getId(Attributes attributes) {
247			return getInteger("id",attributes);
248		}
249		private int getParent(Attributes attributes) {
250			return getInteger("parent",attributes);
251		}
252		private String getName(Attributes attributes) {
253			return getAttribute("name",attributes);
254		}
255		private String getChoice(Attributes attributes) {
256			return getAttribute("choice",attributes);
257		}
258		private int getSize(Attributes attributes) {
259			return getInteger("size",attributes);
260		}
261		private int getValue(Attributes attributes) {
262			return getInteger("value",attributes);
263		}
264		private String getVersion(Attributes attributes) {
265			return getAttribute("version",attributes);
266		}
267
268		public void startDocument() {
269			tree = new Tree();
270			System.out.println("Started Tree Document");
271		}
272
273		public void endDocument() {
274			tree.buildParentLists();
275			System.out.println("End Tree Document");
276		}
277		public void processingInstruction(String target,String data){
278			System.out.println("Process target"+target+" data "+data);
279		}
280		public void startElement(String uri,
281				String localname, String qname,
282				Attributes attributes){
283//			System.out.println(uri+ " " + localname+" "+ qname);
284			if (numNodes % 10000 == 0 && numNodes > 0) {
285				System.out.println(numNodes);
286			}
287			if (numNodes > 2000000){
288				numNodes++;
289				tree.buildParentLists();
290				System.out.println("End Tree Document");
291				throw new IllegalArgumentException("too long");
292			} else {
293			if (qname.equals("tree")) {
294				String version=getVersion(attributes);
295				if (!version.equals("1.0")) {
296					System.out.println("Wrong version "+version);
297				};
298			} else if (qname.equals("root")){
299				int id=getId(attributes);
300//				System.out.println("root"+id);
301				tree.addNode(NodeType.ROOT,id);
302				numNodes++;
303			} else if (qname.equals("succ")){
304				int id=getId(attributes);
305				tree.markSucc(id);
306			} else {
307				int id=getId(attributes);
308				int parent=getParent(attributes);
309				String name=getName(attributes);
310				int size=getSize(attributes);
311				NodeType nodeType;
312				if (qname.equals("try")){
313					int value=getValue(attributes);
314					nodeType = NodeType.TRY;
315					tree.addNode(nodeType,
316							id,parent,name,size,value);
317				} else if (qname.equals("fail")){
318					int value=getValue(attributes);
319					nodeType = NodeType.FAIL;
320					tree.addNode(nodeType,
321							id,parent,name,size,value);
322				} else if (qname.equals("tryc")){
323					String choice = getChoice(attributes);
324					nodeType = NodeType.TRYC;
325					tree.addNode(nodeType,
326							id,parent,name,size,choice);
327				} else if (qname.equals("failc")){
328					String choice = getChoice(attributes);
329					nodeType = NodeType.FAILC;
330					tree.addNode(nodeType,
331							id,parent,name,size,choice);
332				} else {
333					System.out.println("Wrong node type >"+qname+"<");
334					nodeType = NodeType.FAIL;
335				}
336				numNodes++;
337			}
338			}
339		}
340	}
341
342	private static class VizHandler extends DefaultHandler {
343		private int numNodes=0;
344		private State state = null;
345		private VisualState visualState = null;
346		private Map<Integer,Visualizer> visualizerMap= new HashMap<Integer,Visualizer>();
347		private Box box = new Box(0,0,1,1);
348		private VizParentStack stack;
349		private StateStack stateStack = new StateStack();;
350
351		public void startDocument() {
352			stack = new VizParentStack();
353			System.out.println("Started Viz Document");
354		}
355		public void endDocument() {
356			System.out.println("End Viz Document");
357		}
358		public void processingInstruction(String target,String data){
359			System.out.println("Process target"+target+" data "+data);
360		}
361		public void startElement(String uri,
362				String localName, String qName,
363				Attributes attributes) {
364//			System.out.println(qName);
365				numNodes++;
366				if (qName.equals("visualization")) {
367					// dummy bottom element of stack
368					stateStack.push(new State(0,-1,null));
369				} else if (qName.equals("state")) {
370					int treeNode = getTreeNode(attributes);
371					int parentTreeNode = tree.findParent(treeNode);
372//					System.out.println("Parent "+treeNode+" "+ parentTreeNode);
373					while (stateStack.peek().getTreeNode() != parentTreeNode){
374						stateStack.pop();
375					}
376					state = new State(getId(attributes),
377							treeNode,stateStack.peek());
378//					if (tree.isNotFailState(treeNode)) {
379						stateStack.push(state);
380//					}
381//					stateStack.dumpStack();
382
383				} else if (qName.equals("visualizer_state")) {
384					visualState = new VisualState(getVisualizer(attributes),state);
385					stack.push(visualState);
386					state.addVisualizerState(visualState);
387				} else if (qName.equals("visualizer")) {
388					int id=getId(attributes);
389					//get attributes
390					Visualizer visualizer = new Visualizer(id,getType(attributes),
391							getDisplay(attributes),
392							getX(attributes),
393							getY(attributes),
394							getWidth(attributes),
395							getHeight(attributes),
396							getGroup(attributes),
397							getMin(attributes),
398							getMax(attributes),
399							getIndexStart(attributes));
400					box.expandBox(visualizer.getBox());
401					visualizerMap.put(id,visualizer);
402				} else if (qName.equals("dvar")) {
403					//get attributes
404					stack.peek().add(new VizDVar(getIndex(attributes),
405							getDomain(attributes)));
406				} else if (qName.equals("integer")) {
407					//get attributes
408					stack.peek().add(new VizInteger(getIndex(attributes),
409							getValue(attributes)));
410				} else if (qName.equals("focus")) {
411					//get attributes
412					assert stack.peek() == visualState;
413					visualState.focus(new VizFocus(getIndex(attributes),
414							getGroup(attributes),
415							getType(attributes)));
416				} else if (qName.equals("failed")) {
417					//get attributes
418					assert stack.peek() == visualState;
419					visualState.failed(new VizFailed(getIndex(attributes),
420							getGroup(attributes),
421							getValue(attributes)));
422				} else if (qName.equals("tuple")) {
423					VizParent e = new VizTuple(getIndex(attributes));
424					//get attributes
425					stack.peek().add(e);
426					stack.push(e);
427				} else if (qName.equals("collection")) {
428					//get attributes
429					VizParent e = new VizCollection(getIndex(attributes));
430					stack.peek().add(e);
431					stack.push(e);
432				} else if (qName.equals("argument")) {
433					//get attributes
434					VizParent e = new VizArgument(getIndex(attributes));
435					stack.peek().add(e);
436					stack.push(e);
437				} else {
438					System.out.println("start:" + state.getId() + " " +
439						" uri" + uri + " local " + localName + " qname " + qName);
440
441				}
442		}
443
444		public void endElement(String uri, String localName, String qName) {
445			if (qName.equals("state")) {
446				String treeRoot="tree";
447				for(Tool tool : tools.getTreeTools()) {
448					treeRoot = tool.getFileroot();
449				}
450				for(Tool tool : tools.getVizTools()) {
451					tool.handleState(state,box);
452					// this needs more work to respect information in Tool
453//					if (state.getTreeNode() >= 0){
454					idx.println(treeRoot+Math.max(0, state.getTreeNode())+".svg"+" "+
455							tool.getFileroot()+state.getId()+".svg");
456//					}
457
458				}
459				state = null;
460			} else if (qName.equals("tuple")) {
461				stack.pop();
462			} else if (qName.equals("collection")) {
463				stack.pop();
464			} else if (qName.equals("argument")) {
465				stack.pop();
466			} else if (qName.equals("visualizer_state")) {
467				stack.pop();
468				visualState = null;
469			} else if (qName.equals("visualizer")) {
470			} else {
471
472			}
473		}
474
475		private Visualizer getVisualizer(Attributes attributes) {
476			return visualizerMap.get(getId(attributes));
477		}
478		private int getId(Attributes attributes) {
479			return getInteger("id",attributes);
480		}
481		private int getTreeNode(Attributes attributes) {
482			return getInteger("tree_node",attributes);
483		}
484		private String getIndex(Attributes attributes) {
485			return getAttribute("index",attributes);
486		}
487		private int getValue(Attributes attributes) {
488			return getInteger("value",attributes);
489		}
490		private int getX(Attributes attributes) {
491			return getInteger("x",attributes);
492		}
493		private int getY(Attributes attributes) {
494			return getInteger("y",attributes);
495		}
496		private int getWidth(Attributes attributes) {
497			return getInteger("width",attributes);
498		}
499		private int getHeight(Attributes attributes) {
500			return getInteger("height",attributes);
501		}
502		private int getMin(Attributes attributes) {
503			return getInteger("min",attributes);
504		}
505		private int getMax(Attributes attributes) {
506			return getInteger("max",attributes);
507		}
508		private String getDomain(Attributes attributes) {
509			return getAttribute("domain",attributes);
510		}
511		private String getGroup(Attributes attributes) {
512			// if no group given, use dummy group 0, matches nothing
513			return getAttribute("group",attributes,"0");
514		}
515		private String getType(Attributes attributes) {
516			return getAttribute("type",attributes);
517		}
518		private String getDisplay(Attributes attributes) {
519			return getAttribute("display",attributes);
520		}
521		private int getIndexStart(Attributes attributes) {
522			// redefine lower index limit, default is 1
523			return getInteger("indexstart",attributes,1);
524		}
525
526	}
527
528
529}
530
531