001: package jaxx.tools.jaxxcapture.handlers;
002:
003: import java.awt.*;
004: import java.lang.reflect.*;
005: import java.util.*;
006: import org.w3c.dom.*;
007:
008: import jaxx.compiler.*;
009: import jaxx.tools.jaxxcapture.*;
010:
011: public class ObjectHandler {
012: private static int count;
013:
014: protected CapturedObject createCapturedObject(String className,
015: JAXXCapture capture) {
016: return new CapturedObject(this , className, capture);
017: }
018:
019: // returns true if the tag has any "void" children
020: protected boolean processChildren(Element tag,
021: Stack/*<ContextNode>*/context, JAXXCapture capture) {
022: boolean result = false;
023: NodeList children = tag.getChildNodes();
024: for (int i = 0; i < children.getLength(); i++) {
025: Node child = children.item(i);
026: if (child.getNodeType() == Node.ELEMENT_NODE) {
027: Element innerTag = (Element) child;
028: if (innerTag.getTagName().equals("void"))
029: result = true;
030: evaluate(innerTag, context, capture);
031: }
032: }
033: return result;
034: }
035:
036: protected void evaluateProperty(Element tag,
037: Stack/*<ContextNode>*/context, JAXXCapture capture) {
038: // determine containing object
039: CapturedObject contextObject = null;
040: for (int i = context.size() - 1; i >= 0; i--) {
041: if (context.get(i) instanceof CapturedObject) {
042: contextObject = (CapturedObject) context.get(i);
043: break;
044: }
045: }
046: assert contextObject != null;
047:
048: String property = tag.getAttribute("property");
049: if (!property.equals("actionCommand")) { // filter out actionCommand due to screwiness in XMLEncoder's handling of it
050: Object current = context.peek();
051: PropertyNode newContext = new PropertyNode(property);
052: context.push(newContext);
053: boolean voidChildren = processChildren(tag, context,
054: capture);
055:
056: ContextNode[] arguments = newContext.getArguments();
057: if (arguments.length == 1) {
058: if (current instanceof CapturedObject
059: && arguments[0] instanceof ValueNode) // simple property assignment
060: ((CapturedObject) current).setProperty(property,
061: dataBindingEncode(String
062: .valueOf(((ValueNode) arguments[0])
063: .getValue())));
064: else if (current instanceof CapturedObject
065: && arguments[0] instanceof CapturedObject
066: && ((CapturedObject) arguments[0])
067: .isInlineable()) // simple data binding
068: ((CapturedObject) current).setProperty(property,
069: "{" + capture.getJavaCode(arguments[0])
070: + "}");
071: else {
072: contextObject.setInlineable(false);
073: contextObject.appendScriptCode(capture
074: .getJavaCode(context));
075: }
076: } else if (!voidChildren) {
077: contextObject.setInlineable(false);
078: contextObject.appendScriptCode(capture
079: .getJavaCode(context));
080: }
081:
082: assert context.peek() == newContext;
083: context.pop();
084: }
085: }
086:
087: protected void evaluateAdd(CapturedObject contextObject,
088: CapturedObject child, ContextNode constraints) {
089: contextObject.addChild(child, constraints);
090: }
091:
092: protected void evaluateMethod(Element tag,
093: Stack/*<ContextNode>*/context, JAXXCapture capture) {
094: // determine containing object
095: CapturedObject contextObject = null;
096: for (int i = context.size() - 1; i >= 0; i--) {
097: if (context.get(i) instanceof CapturedObject) {
098: contextObject = (CapturedObject) context.get(i);
099: break;
100: }
101: }
102: assert contextObject != null;
103:
104: try {
105: String methodName = tag.getAttribute("method");
106: MethodNode newContext = new MethodNode(methodName);
107: context.push(newContext);
108: boolean voidChildren = processChildren(tag, context,
109: capture);
110: boolean add = false;
111:
112: ContextNode[] arguments = newContext.getArguments();
113: if (methodName.equals("add") && arguments.length >= 1
114: && arguments[0] instanceof CapturedObject) {
115: Class contextClass = Class
116: .forName(contextObject.getClassName(), true,
117: capture.getClassLoader());
118: if (Container.class.isAssignableFrom(contextClass)) {
119: add = true;
120: evaluateAdd(contextObject,
121: (CapturedObject) arguments[0], null);
122: }
123: }
124:
125: if (!voidChildren && !add)
126: contextObject.appendScriptCode(capture
127: .getJavaCode(context));
128:
129: assert context.peek() == newContext;
130: context.pop();
131: } catch (ClassNotFoundException e) {
132: throw new RuntimeException(e);
133: }
134: }
135:
136: protected void evaluate(Element tag,
137: Stack/*<ContextNode>*/context, JAXXCapture capture) {
138: String tagName = tag.getTagName();
139: if (tagName.equals("object")) {
140: String fieldName = tag.getAttribute("field");
141: ContextNode currentNode = (ContextNode) context.peek();
142: if (fieldName.length() > 0) {
143: try {
144: String className = tag.getAttribute("class");
145: Field field = Class.forName(className, true,
146: capture.getClassLoader()).getField(
147: fieldName);
148: Object value = field.get(null);
149: currentNode.addArgument(new LiteralNode(className
150: + "." + fieldName, value));
151: } catch (Exception e) {
152: throw new RuntimeException(e);
153: }
154: } else
155: currentNode.addArgument(capture.processObject(tag,
156: context));
157: } else if (tagName.equals("void")) {
158: String property = tag.getAttribute("property");
159: if (property.length() > 0)
160: evaluateProperty(tag, context, capture);
161: else
162: evaluateMethod(tag, context, capture);
163: } else if (tagName.equals("string"))
164: ((ContextNode) context.peek()).addArgument(new ValueNode(
165: JAXXCapture.getText(tag)));
166: else if (tagName.equals("boolean"))
167: ((ContextNode) context.peek()).addArgument(new ValueNode(
168: Boolean.valueOf(JAXXCapture.getText(tag))));
169: else if (tagName.equals("char"))
170: ((ContextNode) context.peek()).addArgument(new ValueNode(
171: new Character(JAXXCapture.getText(tag).charAt(0))));
172: else if (tagName.equals("short"))
173: ((ContextNode) context.peek()).addArgument(new ValueNode(
174: Short.valueOf(JAXXCapture.getText(tag))));
175: else if (tagName.equals("int"))
176: ((ContextNode) context.peek()).addArgument(new ValueNode(
177: Integer.valueOf(JAXXCapture.getText(tag))));
178: else if (tagName.equals("long"))
179: ((ContextNode) context.peek()).addArgument(new ValueNode(
180: Long.valueOf(JAXXCapture.getText(tag))));
181: else if (tagName.equals("float"))
182: ((ContextNode) context.peek()).addArgument(new ValueNode(
183: Float.valueOf(JAXXCapture.getText(tag))));
184: else if (tagName.equals("double"))
185: ((ContextNode) context.peek()).addArgument(new ValueNode(
186: Double.valueOf(JAXXCapture.getText(tag))));
187: else if (tagName.equals("null"))
188: ((ContextNode) context.peek()).addArgument(new ValueNode(
189: null));
190: else
191: System.err.println("unsupported tag: " + tag.getTagName());
192: }
193:
194: private static String dataBindingEncode(String value) {
195: return value.replaceAll("\\{", "\\\\{").replaceAll("\\}",
196: "\\\\}");
197: }
198:
199: public CapturedObject processObject(Element objectTag,
200: Stack/*<ContextNode>*/context, JAXXCapture capture) {
201: String className = objectTag.getAttribute("class");
202: if (className.length() > 0) {
203: CapturedObject capturedObject = createCapturedObject(
204: className, capture);
205: context.push(capturedObject);
206: NodeList children = objectTag.getChildNodes();
207: String id = objectTag.getAttribute("id");
208: if (id.length() == 0
209: || capture.getCapturedObjects().containsKey(id))
210: id = "Auto" + ++count;
211: assert !capture.getCapturedObjects().containsKey(id);
212: capture.getCapturedObjects().put(id, capturedObject);
213: capturedObject.setProperty("id", id);
214: // process object's name before anything else
215: for (int i = 0; i < children.getLength(); i++) {
216: Node child = children.item(i);
217: if (child.getNodeType() == Node.ELEMENT_NODE) {
218: Element element = (Element) child;
219: if (element.getTagName().equals("void")
220: && element.getAttribute("property").equals(
221: "name")) {
222: evaluate(element, context, capture);
223: String name = capturedObject
224: .getProperty("name");
225: if (name != null
226: && !capture.getCapturedObjects()
227: .containsKey(name)) {
228: capture.getCapturedObjects().put(name,
229: capturedObject);
230: capturedObject.setProperty("id", name);
231: capturedObject.getProperties().remove(
232: "name");
233: }
234: }
235: }
236: }
237: // process remaining children
238: for (int i = 0; i < children.getLength(); i++) {
239: Node child = children.item(i);
240: if (child.getNodeType() == Node.ELEMENT_NODE) {
241: Element element = (Element) child;
242: if (!element.getTagName().equals("void")
243: || !element.getAttribute("property")
244: .equals("name"))
245: evaluate(element, context, capture);
246: }
247: }
248: assert context.peek() == capturedObject;
249: context.pop();
250:
251: return capturedObject;
252: } else {
253: CapturedObject result = (CapturedObject) capture
254: .getCapturedObjects().get(
255: objectTag.getAttribute("idref"));
256: if (result == null)
257: throw new RuntimeException(
258: "Internal error: could not find tag with id "
259: + objectTag.getAttribute("idref"));
260: result.setInlineable(false); // we have at least two references to it, and so can't inline it
261: return result;
262: }
263: }
264:
265: private static String xmlEncode(String src) {
266: return src.replaceAll("'", "&").replaceAll("<", "<");
267: }
268:
269: public String getXML(CapturedObject object, JAXXCapture capture) {
270: StringBuffer result = new StringBuffer();
271: result.append('<');
272: String className = object.getClassName();
273: if (className.startsWith("javax.swing."))
274: className = className.substring("javax.swing.".length());
275: result.append(className);
276: Map/*<String, String>*/properties = object.getProperties();
277: Iterator/*<Map.Entry<String, String>>*/i = properties
278: .entrySet().iterator();
279: while (i.hasNext()) {
280: Map.Entry/*<String, String>*/e = (Map.Entry) i.next();
281: result.append(' ');
282: result.append(e.getKey());
283: result.append("='");
284: result.append(xmlEncode((String) e.getValue()));
285: result.append('\'');
286: }
287: ContextNode[] arguments = object.getArguments();
288: if (arguments != null && arguments.length > 0) {
289: result.append(" constructorParams='");
290: for (int j = 0; j < arguments.length; j++) {
291: if (j != 0)
292: result.append(", ");
293: result.append(capture.getJavaCode(arguments[j]));
294: }
295: result.append('\'');
296: }
297: boolean tagClosed = false;
298:
299: String children = getChildXML(object, capture);
300: if (children != null && children.length() > 0) {
301: if (!tagClosed) {
302: tagClosed = true;
303: result.append('>');
304: result.append(JAXXCompiler.getLineSeparator());
305: }
306: result.append(children);
307: }
308:
309: String script = object.getScriptCode();
310: if (script != null && script.length() > 0) {
311: if (!tagClosed) {
312: tagClosed = true;
313: result.append('>');
314: result.append(JAXXCompiler.getLineSeparator());
315: }
316: result.append(" <script>");
317: result.append(JAXXCompiler.getLineSeparator());
318: result.append(JavaFile.indent(script, 4, false));
319: result.append(JAXXCompiler.getLineSeparator());
320: result.append(" </script>");
321: result.append(JAXXCompiler.getLineSeparator());
322: }
323: if (tagClosed) {
324: result.append("</");
325: result.append(className);
326: result.append('>');
327: } else
328: result.append("/>");
329: return result.toString();
330: }
331:
332: protected String getChildXML(CapturedObject object,
333: JAXXCapture capture) {
334: StringBuffer result = new StringBuffer();
335: CapturedObject[] children = object.getChildren();
336: for (int i = 0; i < children.length; i++) {
337: if (!children[i].isInlineable()) {
338: result.append(JavaFile.indent(children[i]
339: .getXML(capture), 2, false));
340: result.append(JAXXCompiler.getLineSeparator());
341: }
342: }
343: return result.toString();
344: }
345: }
|