r1574 - in trunk/guix-compiler/src/main/java/org/nuiton/guix: . databinding generator model tags
Author: kmorin Date: 2009-08-25 12:49:26 +0200 (Tue, 25 Aug 2009) New Revision: 1574 Added: trunk/guix-compiler/src/main/java/org/nuiton/guix/BindingUtils.java Removed: trunk/guix-compiler/src/main/java/org/nuiton/guix/GuixLauncher1.java trunk/guix-compiler/src/main/java/org/nuiton/guix/databinding/BindingUtils.java trunk/guix-compiler/src/main/java/org/nuiton/guix/databinding/DataBinding.java trunk/guix-compiler/src/main/java/org/nuiton/guix/databinding/DataSource.java Modified: trunk/guix-compiler/src/main/java/org/nuiton/guix/GuixCompiler.java trunk/guix-compiler/src/main/java/org/nuiton/guix/GuixLauncher.java trunk/guix-compiler/src/main/java/org/nuiton/guix/generator/Generator.java trunk/guix-compiler/src/main/java/org/nuiton/guix/generator/GuixGenerator.java trunk/guix-compiler/src/main/java/org/nuiton/guix/generator/JavaFile.java trunk/guix-compiler/src/main/java/org/nuiton/guix/generator/JavaFileGenerator.java trunk/guix-compiler/src/main/java/org/nuiton/guix/generator/JavaMethod.java trunk/guix-compiler/src/main/java/org/nuiton/guix/model/GuixModelObject.java trunk/guix-compiler/src/main/java/org/nuiton/guix/tags/DefaultTagHandler.java trunk/guix-compiler/src/main/java/org/nuiton/guix/tags/ScriptHandler.java trunk/guix-compiler/src/main/java/org/nuiton/guix/tags/StyleHandler.java trunk/guix-compiler/src/main/java/org/nuiton/guix/tags/TagHandler.java trunk/guix-compiler/src/main/java/org/nuiton/guix/tags/TagManager.java Log: Add inherited methods and fields in the Javafile Imporved the binding Removed packages with only 1 class or unused classes Copied: trunk/guix-compiler/src/main/java/org/nuiton/guix/BindingUtils.java (from rev 1572, trunk/guix-compiler/src/main/java/org/nuiton/guix/databinding/BindingUtils.java) =================================================================== --- trunk/guix-compiler/src/main/java/org/nuiton/guix/BindingUtils.java (rev 0) +++ trunk/guix-compiler/src/main/java/org/nuiton/guix/BindingUtils.java 2009-08-25 10:49:26 UTC (rev 1574) @@ -0,0 +1,443 @@ +/** + * *##% guix-compiler + * Copyright (C) 2009 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%* + */ +package org.nuiton.guix; + +import java.beans.Introspector; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.guix.CompilerException; +import org.nuiton.guix.parser.JavaParserConstants; +import org.nuiton.guix.parser.JavaParserTreeConstants; +import org.nuiton.guix.parser.SimpleNode; + +/** + * + * @author kevin + */ +public class BindingUtils { + /** left brace matcher */ + protected static Matcher leftBraceMatcher = Pattern.compile("^(\\{)|[^\\\\](\\{)").matcher(""); + /** right brace matcher */ + protected static Matcher rightBraceMatcher = Pattern.compile("^(\\})|[^\\\\](\\})").matcher(""); + /** log */ + private static Log log = LogFactory.getLog(BindingUtils.class); + + /** + * Examine an attribute value for data binding expressions. Returns a 'cooked' expression which + * can be used to determine the resulting value. It is expected that this expression will be used + * as the source expression in a call to {@link #registerDataBinding}. + * If the attribute value does not invoke data binding, this method returns <code>null</code> + * + * @param stringValue the string value of the property from the XML + * @param type the type of the property, from the <code>JAXXPropertyDescriptor</code> + * @return a processed version of the expression + * @throws jaxx.CompilerException ? + */ + public static String processDataBindings(String stringValue) { + int pos = getNextLeftBrace(stringValue, 0); + if (pos != -1) { + StringBuffer expression = new StringBuffer(); + int lastPos = 0; + while (pos != -1 && pos < stringValue.length()) { + if (pos > lastPos) { + if (expression.length() > 0) { + expression.append(" + "); + } + expression.append('"'); + expression.append(escapeJavaString(stringValue.substring(lastPos, pos))); + expression.append('"'); + } + + if (expression.length() > 0) { + expression.append(" + "); + } + int pos2 = getNextRightBrace(stringValue, pos + 1); + if (pos2 == -1) { + if(log.isErrorEnabled()) + log.error("unmatched '{' in expression: " + stringValue); + return ""; + } + expression.append(stringValue.substring(pos + 1, pos2)); + pos2++; + if (pos2 < stringValue.length()) { + pos = getNextLeftBrace(stringValue, pos2); + lastPos = pos2; + } else { + pos = stringValue.length(); + lastPos = pos; + } + } + if (lastPos < stringValue.length()) { + if (expression.length() > 0) { + expression.append(" + "); + } + expression.append('"'); + expression.append(escapeJavaString(stringValue.substring(lastPos))); + expression.append('"'); + } +// +// StringBuffer el = new StringBuffer(); +// Pattern p = Pattern .compile("\\.(get|is)([A-Z])([a-zA-Z0-9]*)\\(\\)"); +// Matcher m = p.matcher(expression.toString()); +// int mEnd = 0; +// if(m.find()) { +// do { +// el.append(expression.toString().substring(mEnd, m.start())) +// .append("."); +// mEnd = m.end(); +// el.append(m.group(2).toLowerCase()) +// .append(m.group(3)); +// } while (m.find()); +// } +// else { +// el.append(expression.toString()); +// } +// return el.toString().length() > 0 ? el.toString().substring(0, el.toString().length()) : el.toString(); + return expression.toString(); + } + return null; + } + + protected static int getNextLeftBrace(String string, int pos) { + leftBraceMatcher.reset(string); + return leftBraceMatcher.find(pos) ? Math.max(leftBraceMatcher.start(1), leftBraceMatcher.start(2)) : -1; + } + + protected static int getNextRightBrace(String string, int pos) { + leftBraceMatcher.reset(string); + rightBraceMatcher.reset(string); + int openCount = 1; + int rightPos; + while (openCount > 0) { + pos++; + int leftPos = leftBraceMatcher.find(pos) ? Math.max(leftBraceMatcher.start(1), leftBraceMatcher.start(2)) : -1; + rightPos = rightBraceMatcher.find(pos) ? Math.max(rightBraceMatcher.start(1), rightBraceMatcher.start(2)) : -1; + assert leftPos == -1 || leftPos >= pos; + assert rightPos == -1 || rightPos >= pos; + if (leftPos != -1 && leftPos < rightPos) { + pos = leftPos; + openCount++; + } else if (rightPos != -1) { + pos = rightPos; + openCount--; + } else { + openCount = 0; + } + } + return pos; + } + + /** + * Escapes a string using standard Java escape sequences, generally in preparation to including it in a string literal + * in a compiled Java file. + * + * @param raw the raw string to be escape + * @return a string in which all 'dangerous' characters have been replaced by equivalent Java escape sequences + */ + protected static String escapeJavaString(String raw) { + StringBuffer out = new StringBuffer(raw); + for (int i = 0; i < out.length(); i++) { + char c = out.charAt(i); + if (c == '\\' || c == '"') { + out.insert(i, '\\'); + i++; + } else if (c == '\n') { + out.replace(i, i + 1, "\\n"); + i++; + } else if (c == '\r') { + out.replace(i, i + 1, "\\r"); + i++; + } else if (c < 32 || c > 127) { + String value = Integer.toString((int) c, 16); + while (value.length() < 4) { + value = "0" + value; + } + out.replace(i, i + 1, "\\u" + value); + i += 5; + } + } + return out.toString(); + } + + /** + * Examines a node to identify any dependencies it contains. + * + * @param node node to scan + * @throws jaxx.CompilerException ? + */ + public static List<String[]> scanNode(SimpleNode node) throws CompilerException { + List<String[]> bindings = new ArrayList<String[]>(); + switch (node.getId()) { + case JavaParserTreeConstants.JJTMETHODDECLARATION: + break; + case JavaParserTreeConstants.JJTFIELDDECLARATION: + break; + + default: + int count = node.jjtGetNumChildren(); + for(int i = 0; i < count; i++) { + List<String[]> sss = scanNode(node.getChild(i)); + if(sss != null) { + bindings.addAll(sss); + } + } + String[] sArray = determineNodeType(node); + if(sArray != null) { + bindings.add(sArray); + } + } + return bindings; + } + + /** + * Scans through a compound symbol (foo.bar.baz) to identify and track all trackable pieces of it. + * + * @param symbol symbol to scan + * @param contextClass current class context + * @param isMethod flag to search a method + * @param listenerId id of the listener + * @return the type of the symbol (or null if it could not be determined). + */ +// private Class scanCompoundSymbol(String symbol, boolean isMethod) { +// String[] tokens = symbol.split("\\s*\\.\\s*"); +// StringBuffer currentSymbol = new StringBuffer(); +// StringBuffer tokensSeenSoFar = new StringBuffer(); +// boolean accepted; // if this ends up false, it means we weren't able to figure out +// // which object the method is being invoked on +// boolean recognizeClassNames = true; +// for (int j = 0; j < tokens.length - (isMethod ? 1 : 0); j++) { +// accepted = false; +// +// if (tokensSeenSoFar.length() > 0) { +// tokensSeenSoFar.append('.'); +// } +// tokensSeenSoFar.append(tokens[j]); +// if (currentSymbol.length() > 0) { +// currentSymbol.append('.'); +// } +// currentSymbol.append(tokens[j]); +// +// if (currentSymbol.indexOf(".") == -1) { +// String memberName = currentSymbol.toString(); +// CompiledObject object = compiler.getCompiledObject(memberName); +// if (object != null) { +// contextClass = object.getObjectClass(); +// currentSymbol.setLength(0); +// accepted = true; +// recognizeClassNames = false; +// } else { +// try { +// FieldDescriptor field = contextClass.getFieldDescriptor(memberName); +// contextClass = field.getType(); +// currentSymbol.setLength(0); +// accepted = true; +// recognizeClassNames = false; +// } +// catch (NoSuchFieldException e) { +// if (j == 0 || j == 1 && tokens[0].equals(compiler.getRootObject().getId())) { // still in root context +// FieldDescriptor[] newFields = compiler.getScriptFields(); +// for (FieldDescriptor newField : newFields) { +// if (newField.getName().equals(memberName)) { +// addListener(tokensSeenSoFar.toString(), +// null, +// "addPropertyChangeListener(\"" + memberName + "\", " + listenerId + ");" + JAXXCompiler.getLineSeparator(), +// "removePropertyChangeListener(\"" + memberName + "\", " + listenerId + ");" + JAXXCompiler.getLineSeparator()); +// contextClass = newField.getType(); +// assert contextClass != null : "script field '" + memberName + "' is defined, but has type null"; +// currentSymbol.setLength(0); +// accepted = true; +// recognizeClassNames = false; +// break; +// } +// } +// } +// } +// } +// } +// if (currentSymbol.length() > 0 && recognizeClassNames) { +// contextClass = TagManager.resolveClass(currentSymbol.toString(), compiler); +// if (contextClass != null) { +// currentSymbol.setLength(0); +// //accepted = true; +// //recognizeClassNames = false; +// // TODO: for now we don't handle statics +// return null; +// } +// } +// if (!accepted) { +// return null; +// } +// } +// +// return contextClass; +// } + + /** + * Adds type information to nodes where possible, and as a side effect adds event listeners to nodes which + * can be tracked. + * + * @param expression the node to scan + * @param listenerId id of the listener + * @return the class descriptor of the return type or null + */ + private static String[] determineExpressionType(SimpleNode expression) { + assert expression.getId() == JavaParserTreeConstants.JJTPRIMARYEXPRESSION; + SimpleNode prefix = expression.getChild(0); + if (prefix.jjtGetNumChildren() == 1) { +// log.info("1 : " + prefix.getChild(0).getText()); + //return prefix.getChild(0).getText(); + int type = prefix.getChild(0).getId(); + if (type == JavaParserTreeConstants.JJTLITERAL || type == JavaParserTreeConstants.JJTEXPRESSION) { + return null; + } else if (type == JavaParserTreeConstants.JJTNAME && expression.jjtGetNumChildren() == 1) // name with no arguments after it + { + return prefix.getChild(0).getText().trim().split("\\."); + } + } + + if (expression.jjtGetNumChildren() == 1) { +// log.info("2 " + prefix.getText()); + return null; + } + else { + List<String> result = new ArrayList<String>(); + int index = 0; + for(int i = 0 ; i < expression.jjtGetNumChildren() ; i++) { + //log.info(expression.getChild(i).getText().trim()); + String token = expression.getChild(i).getText().trim(); + + if(token.startsWith("(")) { + result.set(index - 1, result.get(index - 1) + token); + } + else { + int nbToken = 0; + while(token.startsWith(".")) { + token = token.substring(1); + } + String[] splitedToken = token.split("\\."); + for(int j = splitedToken.length - 1 ; j >= 0 ; j-- ) { + if(Character.isUpperCase(splitedToken[j].charAt(0))) { + StringBuffer stringBuffer = new StringBuffer(); + for(int k = 0 ; k < j ; k++) { + stringBuffer.append(splitedToken[k]).append("."); + } + result.add(index, stringBuffer.append(splitedToken[j]).toString()); + nbToken ++; + break; + } + else { + result.add(index, splitedToken[j]); + nbToken++; + } + } + index += nbToken; + } + } + return result.toArray(new String[result.size()]); + } + +// Class contextClass = prefix.getJavaType(); +// if (contextClass == null) { +// contextClass = compiler.getRootObject().getObjectClass(); +// } +// String lastNode = prefix.getText().trim(); +// +// for (int i = 1; i < expression.jjtGetNumChildren(); i++) { +// SimpleNode suffix = expression.getChild(i); +// if (suffix.jjtGetNumChildren() == 1 && suffix.getChild(0).getId() == JavaParserTreeConstants.JJTARGUMENTS) { +// if (suffix.getChild(0).jjtGetNumChildren() == 0) { // at the moment only no-argument methods are trackable +// contextClass = scanCompoundSymbol(lastNode, contextClass, true, listenerId); +// if (contextClass == null) { +// return null; +// } +// int dotPos = lastNode.lastIndexOf("."); +// String objectCode = dotPos == -1 ? "" : lastNode.substring(0, dotPos); +// log.info("oc : " + objectCode); +// for (int j = i - 2; j >= 0; j--) { +// log.info(expression.getChild(j).getText()); +// } +// for (int j = i - 2; j >= 0; j--) { +// objectCode = expression.getChild(j).getText() + objectCode; +// } +// return objectCode; +// if (objectCode.length() == 0) { +// objectCode = compiler.getRootObject().getJavaCode(); +// } +// String methodName = lastNode.substring(dotPos + 1).trim(); +// try { +// MethodDescriptor method = contextClass.getMethodDescriptor(methodName); +// trackMemberIfPossible(objectCode, contextClass, method.getName(), true, listenerId); +// return method.getReturnType(); +// } +// catch (NoSuchMethodException e) { +// // happens for methods defined in the current JAXX file via scripts +// String propertyName = null; +// if (methodName.startsWith("is")) { +// propertyName = Introspector.decapitalize(methodName.substring("is".length())); +// } else if (methodName.startsWith("get")) { +// propertyName = Introspector.decapitalize(methodName.substring("get".length())); +// } +// if (propertyName != null) { +// MethodDescriptor[] newMethods = compiler.getScriptMethods(); +// for (MethodDescriptor newMethod : newMethods) { +// if (newMethod.getName().equals(methodName)) { +// addListener(compiler.getRootObject().getId(), +// null, +// "addPropertyChangeListener(\"" + propertyName + "\", " + listenerId + ");" + JAXXCompiler.getLineSeparator(), +// "removePropertyChangeListener(\"" + propertyName + "\", " + listenerId + ");" + JAXXCompiler.getLineSeparator()); +// contextClass = newMethod.getReturnType(); +// break; +// } +// } +// } +// } +// } +// } +// lastNode = suffix.getText().trim(); +// if (lastNode.startsWith(".")) { +// lastNode = lastNode.substring(1); +// } +// } +// +// return null; + } + + /** + * Adds type information to nodes where possible, and as a side effect adds event listeners to nodes which + * can be tracked. + * + * @param node node to scan + */ + private static String[] determineNodeType(SimpleNode node) { + String[] result = null; + switch (node.getId()) { + case JavaParserTreeConstants.JJTPRIMARYEXPRESSION: + result = determineExpressionType(node); + return result; + default: + return null; + } + } +} Property changes on: trunk/guix-compiler/src/main/java/org/nuiton/guix/BindingUtils.java ___________________________________________________________________ Added: svn:mergeinfo + Modified: trunk/guix-compiler/src/main/java/org/nuiton/guix/GuixCompiler.java =================================================================== --- trunk/guix-compiler/src/main/java/org/nuiton/guix/GuixCompiler.java 2009-08-25 10:35:58 UTC (rev 1573) +++ trunk/guix-compiler/src/main/java/org/nuiton/guix/GuixCompiler.java 2009-08-25 10:49:26 UTC (rev 1574) @@ -24,7 +24,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.nuiton.guix.GuixLauncher; import org.nuiton.guix.model.AttributeDescriptor; import org.nuiton.guix.model.ClassDescriptor; import org.nuiton.guix.model.GuixModelObject; @@ -53,13 +52,17 @@ */ public class GuixCompiler { + private static final String STYLE_TAG = "style"; + private static final String SCRIPT_TAG = "script"; + private static final String CONSTRUCTOR_PARAMS_ATTRIBUTE = "constructor"; + private static final String ID_ATTRIBUTE = "id"; + private static final String STYLE_CLASS_ATTRIBUTE = "styleClass"; + private static final String SOURCE_ATTRIBUTE = "source"; + private static final String JAVA_BEAN_ATTRIBUTE = "javaBean"; + /** log */ - private static final Log log = LogFactory.getLog(GuixCompiler.class); - - /** - * Integer used to give an id to the objects which don't have one specified - * by the user - */ + private Log log = LogFactory.getLog(GuixCompiler.class); + /** Integer used to give an id to the objects which don't have one specified by the user */ private int index = 1; private StyleHandler styleHandler = new StyleHandler(); private ScriptHandler scriptHandler = new ScriptHandler(); @@ -160,13 +163,13 @@ String tagPackageName = resolvePackageName(tagNameSpace, xpp.getName()); - String id = ((xpp.getAttributeValue("", "id") != null) - ? xpp.getAttributeValue("", "id") + String id = ((xpp.getAttributeValue("", ID_ATTRIBUTE) != null) + ? xpp.getAttributeValue("", ID_ATTRIBUTE) : "_" + tagName + index++); // creation of the root GuixModelObject - rootMO = new GuixModelObject(id, xpp.getAttributeValue("", "constructor"), - doc.toString(), xpp.getAttributeValue("", "styleClass")); + rootMO = new GuixModelObject(id, xpp.getAttributeValue("", CONSTRUCTOR_PARAMS_ATTRIBUTE), + doc.toString(), xpp.getAttributeValue("", STYLE_CLASS_ATTRIBUTE)); // the class name is the name of the file minus the extension String className = src.getName().substring(0, src.getName().lastIndexOf('.')); @@ -286,11 +289,11 @@ if(xpp.getPrefix() == null || xpp.getPrefix().equalsIgnoreCase(generationLanguage)) { // if the tag is a style tag - if ((xpp.getName() != null) && xpp.getName().equals("style")) { + if ((xpp.getName() != null) && xpp.getName().equals(STYLE_TAG)) { File styleFile = null; // the name of the file to load - String source = xpp.getAttributeValue("", "source"); + String source = xpp.getAttributeValue("", SOURCE_ATTRIBUTE); // if the source attribute is specified if (source != null) { @@ -312,11 +315,11 @@ // the parent is still the same prev = previousMO; } // if the tag is a script tag - else if ((xpp.getName() != null) && xpp.getName().equals("script")) { + else if ((xpp.getName() != null) && xpp.getName().equals(SCRIPT_TAG)) { File scriptFile = null; // the name of the file to load - String source = xpp.getAttributeValue("", "source"); + String source = xpp.getAttributeValue("", SOURCE_ATTRIBUTE); // if the source attribute is specified if (source != null) { @@ -346,14 +349,16 @@ } - String id = ((xpp.getAttributeValue("", "id") != null) - ? xpp.getAttributeValue("", "id") + String id = ((xpp.getAttributeValue("", ID_ATTRIBUTE) != null) + ? xpp.getAttributeValue("", ID_ATTRIBUTE) : "_" + tagName + index++); // create the GuixModelObject representing the tag - GuixModelObject mo = new GuixModelObject(id, xpp.getAttributeValue("", "constructor"), - javaDoc, xpp.getAttributeValue("", "styleClass")); + GuixModelObject mo = new GuixModelObject(id, xpp.getAttributeValue("", CONSTRUCTOR_PARAMS_ATTRIBUTE), + javaDoc, xpp.getAttributeValue("", STYLE_CLASS_ATTRIBUTE)); + mo.setJavaBean(xpp.getAttributeValue("", JAVA_BEAN_ATTRIBUTE) == null || Boolean.valueOf(xpp.getAttributeValue("", JAVA_BEAN_ATTRIBUTE))); + // register the ClassDescriptor ClassDescriptor cd = launcher.registerClassDescriptor(new ClassDescriptor(tagName, tagPackageName)); mo.setClassDescriptor(cd); @@ -444,8 +449,6 @@ // if not eof if (xpp.getEventType() == XmlPullParser.START_TAG) { - - log.info(prev.getClassDescriptor()); // compile the rest of the document result.append(compile(xpp, prev, doc.toString())); } @@ -511,8 +514,8 @@ List<AttributeDescriptor> result = new ArrayList<AttributeDescriptor>(); for (int i = 0; i < xpp.getAttributeCount(); i++) { - if (!xpp.getAttributeName(i).equals("id") && !xpp.getAttributeName(i).equals("constructor") - && !xpp.getAttributeName(i).equals("styleClass")) { + if (!xpp.getAttributeName(i).equals(ID_ATTRIBUTE) && !xpp.getAttributeName(i).equals(CONSTRUCTOR_PARAMS_ATTRIBUTE) + && !xpp.getAttributeName(i).equals(STYLE_CLASS_ATTRIBUTE) && ! xpp.getAttributeName(i).equals(JAVA_BEAN_ATTRIBUTE)) { result.add(new AttributeDescriptor(xpp.getAttributeName(i), xpp.getAttributeValue(i))); } } Modified: trunk/guix-compiler/src/main/java/org/nuiton/guix/GuixLauncher.java =================================================================== --- trunk/guix-compiler/src/main/java/org/nuiton/guix/GuixLauncher.java 2009-08-25 10:35:58 UTC (rev 1573) +++ trunk/guix-compiler/src/main/java/org/nuiton/guix/GuixLauncher.java 2009-08-25 10:49:26 UTC (rev 1574) @@ -30,10 +30,12 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.nuiton.guix.BindingUtils; import org.nuiton.guix.generator.GuixGenerator; import org.nuiton.guix.generator.JavaArgument; import org.nuiton.guix.generator.JavaField; import org.nuiton.guix.generator.JavaFile; +import org.nuiton.guix.generator.JavaFileGenerator; import org.nuiton.guix.generator.JavaMethod; import org.nuiton.guix.model.ClassDescriptor; import org.nuiton.guix.model.GuixModelObject; @@ -82,9 +84,8 @@ private String generationLanguage; /** Name of the class that will launch the application */ private String launcherName; - + /** Maps the ClassDescriptors to generate to the corresponding root GuixModelObject */ private Map<ClassDescriptor, GuixModelObject> rootClassDescriptors = new HashMap<ClassDescriptor, GuixModelObject>(); - /** Dependencies between the different files to generate */ private Map<GuixModelObject, ArrayList<ClassDescriptor>> dependencies = new HashMap<GuixModelObject, ArrayList<ClassDescriptor>>(); @@ -200,15 +201,12 @@ //if the compilation successed if (success) { - int i = 0; //check if all the objects have an existing clas or a class being generated - while (success && i < classDescriptors.size()) { - success = (classDescriptors.get(i).getPackageName() != null || TagManager.getGuixClassHandler(classDescriptors.get(i).getName()) != null); - i++; - } - if (!success) { - if (log.isErrorEnabled()) { - log.error("The class '" + classDescriptors.get(--i).getName() + "' has no package."); + for(ClassDescriptor classDescriptor : classDescriptors) { + if(classDescriptor.getPackageName() == null && TagManager.getGuixClassHandler(classDescriptor.getName()) == null) { + if(log.isWarnEnabled()) { + log.warn("The class '" + classDescriptor.getName() + "' has no package. Default package will be applied."); + } } } if (generatorClass != null) { @@ -290,79 +288,95 @@ dbCreation.append(dbCreation.length() != 0 ? "else if(\"" : "if(\"").append(field).append(".").append(attr).append("\".equals(_binding)) {\n"); dbDeletion.append(dbDeletion.length() != 0 ? "else if(\"" : "if(\"").append(field).append(".").append(attr).append("\".equals(_binding)) {\n"); dbProcess.append(dbProcess.length() != 0 ? "else if(\"" : "if(\"").append(field).append(".").append(attr).append("\".equals(_binding)) {\n"); - List<String[]> bindings = new ArrayList<String[]>(); - //the parser which decompose the binding into the different elements to bind - JavaParser p = new JavaParser(new StringReader(gen.getBindingsToGenerate().get(field).get(attr))); - //start parsing the binding value - while (!p.Line()) { - SimpleNode node = p.popNode(); - if (node != null) { - //get the different elements to bind - for (String s : browseNode(node)) { - //decompose the element s into attributes - List<String> l = new ArrayList<String>(); - //number of open brackets - int parOuvertes = 0; - StringBuffer read = new StringBuffer(); - for (char c : s.toCharArray()) { - if (c == '(') { - parOuvertes++; - read.append(c); - } - else if (c == ')') { - parOuvertes--; - read.append(c); - } - else if (c == '.') { - if (parOuvertes == 0) { - l.add(read.toString()); - read = new StringBuffer(); - } - else { - read.append(c); - } - } - else { - read.append(c); - } + List<Class> listeners = new ArrayList<Class>(); + +// if(gen.getBindingsToGenerate().get(field).get(attr).startsWith("new ")) { +// listeners = null; +// } +// else { + List<String[]> bindings = new ArrayList<String[]>(); + //the parser which decompose the binding into the different elements to bind + JavaParser p = new JavaParser(new StringReader(gen.getBindingsToGenerate().get(field).get(attr))); + //start parsing the binding value + while (!p.Line()) { + SimpleNode node = p.popNode(); + if (node != null) { + List<String[]> l = BindingUtils.scanNode(node); + if(l != null) { + bindings.addAll(l); } - l.add(read.toString()); - bindings.add(l.toArray(new String[l.size()])); + +// if(l != null) { +// for(String s : l) { +// bindings.add(s.split("\\.").length > 0 ? s.split("\\.") : new String[]{s}); +// } +// } + //get the different elements to bind +// for (String s : browseNode(node)) { +// //decompose the element s into attributes +// List<String> l = new ArrayList<String>(); +// //number of open brackets +// int parOuvertes = 0; +// StringBuffer read = new StringBuffer(); +// for (char c : s.toCharArray()) { +// if (c == '(') { +// parOuvertes++; +// read.append(c); +// } +// else if (c == ')') { +// parOuvertes--; +// read.append(c); +// } +// else if (c == '.') { +// if (parOuvertes == 0) { +// l.add(read.toString()); +// read = new StringBuffer(); +// } +// else { +// read.append(c); +// } +// } +// else { +// read.append(c); +// } +// } +// l.add(read.toString()); +// bindings.add(l.toArray(new String[l.size()])); +// } } } - } - //generates the code - List<Class> listeners = new ArrayList<Class>(); - for (String[] binding : bindings) { - StringBuffer methodToInvoke = new StringBuffer(); - //the binding value before the generator changes it - StringBuffer oldBinding = new StringBuffer(); - //generates the method name for calling the databinding process method - for (String s : binding) { - methodToInvoke.append(s.replaceAll("\\W", "")); - oldBinding.append(s).append("."); - } - oldBinding.setLength(oldBinding.length() - 1); - //generates the code and modify the simple attribute name in the binding by the getter - listeners.addAll(gen.generateBindings(dbCreation, dbDeletion, null, jf, null, binding, 0, null, methodToInvoke.toString(), generatedFiles)); - //JavaArgument[] args = new JavaArgument[]{new JavaArgument(parameterType.getName(), "event")}; - //new value of the binding with the getters - StringBuffer newBinding = new StringBuffer(); - for (String s : binding) { - newBinding.append(s).append("."); - } - newBinding.setLength(newBinding.length() - 1); - //replaces the old binding by the newer one - gen.getBindingsToGenerate().get(field).put(attr, gen.getBindingsToGenerate().get(field).get(attr).replace(oldBinding.toString(), newBinding.toString())); + //generates the code + for (String[] binding : bindings) { + StringBuffer methodToInvoke = new StringBuffer(); + //the binding value before the generator changes it + StringBuffer oldBinding = new StringBuffer(); + //generates the method name for calling the databinding process method + for (String s : binding) { + methodToInvoke.append(s.replaceAll("\\W", "")); + oldBinding.append(s).append("."); + } + oldBinding.setLength(oldBinding.length() - 1); + //generates the code and modify the simple attribute name in the binding by the getter + listeners.addAll(gen.generateBindings(dbCreation, dbDeletion, null, jf, null, binding, 0, null, methodToInvoke.toString(), generatedFiles)); + //JavaArgument[] args = new JavaArgument[]{new JavaArgument(parameterType.getName(), "event")}; + //new value of the binding with the getters + StringBuffer newBinding = new StringBuffer(); + for (String s : binding) { + newBinding.append(s).append("."); + } + newBinding.setLength(newBinding.length() - 1); + //replaces the old binding by the newer one + gen.getBindingsToGenerate().get(field).put(attr, gen.getBindingsToGenerate().get(field).get(attr).replace(oldBinding.toString(), newBinding.toString())); - //method called by the listener - if (jf.getMethod("onChangeFrom" + methodToInvoke, /*args*/ null) == null) { - jf.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "onChangeFrom" + methodToInvoke.toString(), /*args*/ null, null, /*"_DataSource" + dataSourceNumber + ".propertyChange(null);"*/ "processDataBinding(\"" + field + "." + attr + "\");", "Method called when the objects bound by '" + attr + "' of '" + field + "' change")); + //method called by the listener + if (jf.getMethod("onChangeFrom" + methodToInvoke, /*args*/ null) == null) { + jf.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "onChangeFrom" + methodToInvoke.toString(), /*args*/ null, null, /*"_DataSource" + dataSourceNumber + ".propertyChange(null);"*/ "processDataBinding(\"" + field + "." + attr + "\");", "Method called when the objects bound by '" + attr + "' of '" + field + "' change")); + } + else { + jf.getMethod("onChangeFrom" + methodToInvoke.toString(), /*args*/ null).appendBodyCode(/*"_DataSource" + dataSourceNumber + ".propertyChange(null);"*/"processDataBinding(\"" + field + "." + attr + "\");", "\n"); + } } - else { - jf.getMethod("onChangeFrom" + methodToInvoke.toString(), /*args*/ null).appendBodyCode(/*"_DataSource" + dataSourceNumber + ".propertyChange(null);"*/"processDataBinding(\"" + field + "." + attr + "\");", "\n"); - } - } +// } dbCreation.append("}\n"); dbDeletion.append("}\n"); dbProcess.append(field).append(".set").append(Character.toUpperCase(attr.charAt(0))).append(attr.substring(1)).append("(").append(gen.getBindingsToGenerate().get(field).get(attr)).append(");\n}\n"); @@ -402,8 +416,8 @@ } jf.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "applyDataBinding", new JavaArgument[]{new JavaArgument("String", "_binding")}, null, (jf.isSuperclassIsGuixObject() ? "super.applyDataBinding(_binding);\n" : "") + dbCreation.toString(), "Adds the listeners to the elements which are bound by another attribute")); - jf.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "removeDataBinding", new JavaArgument[]{new JavaArgument("String", "_binding")}, null, - (jf.isSuperclassIsGuixObject() ? "super.removeDataBinding(_binding);\n" : "") + dbDeletion.toString(), "Removes the listeners to the elements which are bound by another attribute")); +// jf.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "removeDataBinding", new JavaArgument[]{new JavaArgument("String", "_binding")}, null, +// (jf.isSuperclassIsGuixObject() ? "super.removeDataBinding(_binding);\n" : "") + dbDeletion.toString(), "Removes the listeners to the elements which are bound by another attribute")); jf.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "processDataBinding", new JavaArgument[]{new JavaArgument("String", "_binding")}, null, (jf.isSuperclassIsGuixObject() ? "super.processDataBinding(_binding);\n" : "") + dbProcess.toString(), "Executes the binding instruction")); //saves the files Deleted: trunk/guix-compiler/src/main/java/org/nuiton/guix/GuixLauncher1.java =================================================================== --- trunk/guix-compiler/src/main/java/org/nuiton/guix/GuixLauncher1.java 2009-08-25 10:35:58 UTC (rev 1573) +++ trunk/guix-compiler/src/main/java/org/nuiton/guix/GuixLauncher1.java 2009-08-25 10:49:26 UTC (rev 1574) @@ -1,372 +0,0 @@ -/** - * *##% guix-compiler - * Copyright (C) 2009 CodeLutin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%* - */ -package org.nuiton.guix; - -import java.beans.BeanInfo; -import java.beans.PropertyChangeListener; -import org.nuiton.guix.GuixCompiler; -import java.io.File; -import java.io.PrintWriter; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.EventListener; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.guix.generator.Generator; -import org.nuiton.guix.generator.GuixGenerator; -import org.nuiton.guix.generator.JavaArgument; -import org.nuiton.guix.generator.JavaField; -import org.nuiton.guix.generator.JavaFile; -import org.nuiton.guix.generator.JavaMethod; -import org.nuiton.guix.model.ClassDescriptor; -import org.nuiton.guix.model.GuixModelObject; -import org.nuiton.guix.tags.TagHandler; -import org.nuiton.guix.tags.TagManager; -import org.xmlpull.v1.XmlPullParserFactory; -import org.xmlpull.v1.XmlSerializer; - -/** - * Launch Guix files compilation - * - * @author morin - */ -public class GuixLauncher1 { - - /** log */ - protected static final Log log = LogFactory.getLog(GuixLauncher1.class); - /** original list of files to compile */ - protected final File[] files; - /** original list of classes to compile */ - protected final String[] classNames; - /** Files to be treated while compilation. */ - protected List<File> guixFiles = new ArrayList<File>(); - /** Class names corresponding to the files in the guixFiles list. */ - protected List<String> guixFileClassNames = new ArrayList<String>(); - /** Maps the root GuixModelObjects being compiled to the compiler instance - * handling the compilation. */ - protected Map<GuixModelObject, Long> rootModelObjects = - new HashMap<GuixModelObject, Long>(); - /** CLassDescriptor met during the compilation */ - protected List<ClassDescriptor> classDescriptors = - new ArrayList<ClassDescriptor>(); - private List<File> compiledFiles = new ArrayList<File>(); - private Map<GuixGenerator,JavaFile> generatedFiles = new HashMap<GuixGenerator,JavaFile>(); - protected int compilerCount; - private File targetDirectory; - private String rootPackage; - private String mainClass; - private Class generatorClass; - private String launcherName; - - /** - * Constructor - * - * @param files the files to compile - */ - public GuixLauncher1(File[] files, File targetDirectory, String rootPackage, - File baseDir, String mainClass, Class generatorClass, String launcherName) { - // Set up a simple configuration that logs on the console. - this.files = files; - this.targetDirectory = targetDirectory; - this.rootPackage = rootPackage != null ? rootPackage : ""; - if (files != null) { - classNames = new String[files.length]; - for (int i = 0; i < files.length; i++) { - String path = files[i].getAbsolutePath(); - if (baseDir != null) { - classNames[i] = rootPackage + "." + path.substring(baseDir.getAbsolutePath().length() + 1, - path.lastIndexOf('.')).replace(File.separatorChar, '.'); - } - else { - classNames[i] = path.substring(0, path.lastIndexOf('.')); - } - } - } - else { - classNames = null; - } - this.mainClass = mainClass != null ? mainClass : ""; - this.launcherName = launcherName != null ? launcherName : "Main"; - this.generatorClass = generatorClass; - } - - /** - * Compiled a set of files. - * - * @return <code>true</code> if compilation succeeds, - * <code>false</code> otherwise - */ - public synchronized boolean compile() { - compilerCount = 0; - File destDir = targetDirectory; - if (files != null) { - if (log.isInfoEnabled()) { - log.info("Start compiling"); - } - guixFiles.addAll(Arrays.asList(files)); - guixFileClassNames.addAll(Arrays.asList(classNames)); - boolean success = true; - - try { - assert guixFiles.size() == guixFileClassNames.size(); - - for (int i = 0; i < guixFiles.size(); i++) { - File file = guixFiles.get(i); - String className = guixFileClassNames.get(i); - - //if we have not compiled the file yet - if (!compiledFiles.contains(file)) { - if (log.isInfoEnabled()) { - log.info("Compiling class " + className); - } - compiledFiles.add(file); - - String classPackage; - if (targetDirectory != null) { - int dotPos = className.lastIndexOf("."); - if (dotPos != -1) { - destDir = new File(targetDirectory, className.substring(0, dotPos).replace('.', File.separatorChar)); - classPackage = className.substring(0, dotPos); - } - else { - destDir = new File(targetDirectory, className); - classPackage = className; - } - if (!destDir.exists() && !destDir.mkdirs()) { - if (log.isWarnEnabled()) { - log.warn("couldn't create directory " + destDir); - } - continue; - } - } - else { - destDir = file.getParentFile(); - classPackage = destDir.getAbsolutePath().replace(File.separatorChar, '.'); - } - //compile the file - // GuixCompiler compiler = new GuixCompiler(file, this, classPackage); - GuixCompiler compiler = null; - - GuixModelObject rootModelObject = compiler.compile(); - rootModelObjects.put(rootModelObject, compiler.getLastModification()); - - if (compiler.isFailed()) { - success = false; - } - } - else { - if (log.isWarnEnabled()) { - log.warn(file.getName() + " has already been compiled."); - } - } - } - - if (success) { - int i = 0; - while (success && i < classDescriptors.size()) { - success = (classDescriptors.get(i).getPackageName() != null || TagManager.getGuixClassHandler(classDescriptors.get(i).getName()) != null); - i++; - } - if (!success) { - if (log.isErrorEnabled()) { - log.error("The class '" + classDescriptors.get(--i).getName() + "' has no package."); - } - } - } - - if (generatorClass != null) { - //creates the XML serializer for the spring conf - XmlPullParserFactory factory = - XmlPullParserFactory.newInstance( - System.getProperty(XmlPullParserFactory.PROPERTY_NAME), - null); - XmlSerializer serializer = factory.newSerializer(); - - File config = new File(targetDirectory,"config.xml"); - - serializer.setOutput(new PrintWriter(config)); - serializer.startDocument("UTF-8", null); - serializer.setProperty("http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n"); - serializer.setProperty("http://xmlpull.org/v1/doc/properties.html#serializer-indentation", "\t"); - serializer.text("\n"); - serializer.docdecl(" beans SYSTEM \"http://www.springframework.org/dtd/spring-beans.dtd\""); - serializer.text("\n"); - serializer.startTag("", "beans"); - - for (GuixModelObject mo : rootModelObjects.keySet()) { - try { - GuixGenerator gen = (GuixGenerator) generatorClass.newInstance(); - gen.setDestDir(destDir); - gen.setGmo(mo); - gen.setLastModification(rootModelObjects.get(mo)); - gen.setMainClass((mo.getClassDescriptor().getPackageName() + "." + mo.getClassDescriptor().getName()).equals(mainClass)); - gen.setSerializer(serializer); - //gen.setClasses(Arrays.asList(classNames)); - gen.setLauncherName(launcherName); - generatedFiles.put(gen,gen.generate()); - } - catch (InstantiationException eee) { - if(log.isErrorEnabled()) - log.error(eee); - } - catch (IllegalAccessException eee) { - if(log.isErrorEnabled()) - log.error(eee); - } - } - for(GuixGenerator gen : generatedFiles.keySet()) { - int dataSourceNumber = 0; - StringBuffer dbCreation = new StringBuffer(); - StringBuffer dbDeletion = new StringBuffer(); - StringBuffer dbProcess = new StringBuffer(); - JavaFile jf = generatedFiles.get(gen); - for(String field : gen.getBindingsToGenerate().keySet()) { - for(String attr : gen.getBindingsToGenerate().get(field).keySet()) { - dbCreation.append(dbCreation.length() != 0 ? "else if(\"" : "if(\"").append(field) - .append(".").append(attr) - .append("\".equals(_binding)) {\n"); - dbDeletion.append(dbDeletion.length() != 0 ? "else if(\"" : "if(\"").append(field) - .append(".").append(attr) - .append("\".equals(_binding)) {\n"); - dbProcess.append(dbProcess.length() != 0 ? "else if(\"" : "if(\"").append(field) - .append(".").append(attr) - .append("\".equals(_binding)) {\n") - .append(field).append(".set") - .append(Character.toUpperCase(attr.charAt(0))) - .append(attr.substring(1)) - .append("("); - String[] binding = gen.getBindingsToGenerate().get(field).get(attr).split("\\s*\\.\\s*"); - String methodToInvoke = gen.getBindingsToGenerate().get(field).get(attr).replaceAll("\\W", ""); - List<Class> listeners = gen.generateBindings(dbCreation, dbDeletion, null, jf, null,null, 0, null, methodToInvoke, generatedFiles); - dbCreation.append("}\n"); - dbDeletion.append("}\n"); - dbProcess.append(");\n}\n"); - if(listeners != null) { - jf.addField(new JavaField(Modifier.PRIVATE, "java.beans.PropertyChangeListener", "_DataSource" + dataSourceNumber, "new org.nuiton.guix.runtime.DataBindingListener(this,\"" + field + "." + attr + "\")", null, null)); - jf.getMethod("initDataBinding", null).appendBodyCode("applyDataBinding(\"" + field + "." + attr + "\");", "\n"); - for(Class listener : listeners) { - final List<Method> listenerMethods = Arrays.asList(listener.getMethods()); - Class parameterType = listenerMethods.get(0).getParameterTypes()[0]; - JavaArgument[] args = new JavaArgument[]{new JavaArgument(parameterType.getName(), "event")}; - if (jf.getMethod("onChangeFrom" + methodToInvoke, args) == null) { - jf.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "onChangeFrom" + methodToInvoke, args, null, "_DataSource" + dataSourceNumber + ".propertyChange(null);", null)); - } - else { - jf.getMethod("onChangeFrom" + methodToInvoke, args).appendBodyCode("_DataSource" + dataSourceNumber + ".propertyChange(null);", "\n"); - } - } - } - dataSourceNumber++; - } - } - if(generatedFiles.get(jf.getSuperClass()) != null) { - dbCreation.append("else {\nsuper.applyDataBinding(_binding);\n" + - "return;\n}"); - dbDeletion.append("\nelse {\nsuper.removeDataBinding(_binding);\n}\n"); - } - dbCreation.append("\nprocessDataBinding(_binding);"); - jf.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "applyDataBinding", new JavaArgument[]{new JavaArgument("String", "_binding")}, null, dbCreation.toString(), null)); - jf.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "removeDataBinding", new JavaArgument[]{new JavaArgument("String", "_binding")}, null, dbDeletion.toString(), null)); - jf.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "processDataBinding", new JavaArgument[]{new JavaArgument("String", "_binding")}, null, dbProcess.toString(), null)); - gen.saveFiles(); - } - serializer.endTag("", "beans"); - serializer.endDocument(); - } - else { - if(log.isWarnEnabled()) { - log.warn("No generation language given"); - } - } - } - catch (Throwable e) { - e.printStackTrace(); - return false; - } - return success; - } - else { - if (log.isWarnEnabled()) { - log.warn("No file to compile"); - } - return true; - } - } - - - /** - * Registers a ClassDescriptor - * - * @param classDescriptor the ClassDescripor to register - * @return false if another ClassDescriptor with the same classname - * and package has a different script or superclass - */ - public ClassDescriptor registerClassDescriptor(ClassDescriptor classDescriptor) { - if (classDescriptor == null || classDescriptor.getName() == null) { - return null; - } - int i = 0; - while (i < classDescriptors.size() && (!classDescriptors.get(i).getName().equals(classDescriptor.getName()) || (classDescriptors.get(i).getPackageName() != null && classDescriptor.getPackageName() != null && !classDescriptors.get(i).getPackageName().equals(classDescriptor.getPackageName())))) { - i++; - } - //if the ClassDescriptor does not exist - if (i >= classDescriptors.size()) { - classDescriptors.add(classDescriptor); - if (log.isDebugEnabled()) { - log.debug("new ClassDescriptor " + classDescriptor + " inserted"); - } - return classDescriptor; - } - classDescriptors.get(i).setPackageName(classDescriptor.getPackageName()); - if (classDescriptor.getScript() != null) { - if (classDescriptors.get(i).getScript() == null) { - classDescriptors.get(i).setScript(classDescriptor.getScript()); - if (log.isDebugEnabled()) { - log.debug("add script to ClassDescriptor " + classDescriptor); - } - } - else if (!classDescriptors.get(i).getScript().equals(classDescriptor.getScript())) { - if (log.isDebugEnabled()) { - log.error("ClassDescriptor " + classDescriptor + " script already defined and different !"); - } - return null; - } - } - if (classDescriptor.getSuperClass() != null) { - if (classDescriptors.get(i).getSuperClass() == null) { - classDescriptors.get(i).setSuperClass(classDescriptor.getSuperClass()); - if (log.isDebugEnabled()) { - log.debug("add superclass to ClassDescriptor " + classDescriptor); - } - } - else if (!classDescriptors.get(i).getSuperClass().equals(classDescriptor.getSuperClass())) { - if (log.isErrorEnabled()) { - log.error("ClassDescriptor " + classDescriptor + " superclass already defined and different !"); - } - return null; - } - } - return classDescriptors.get(i); - } -} Deleted: trunk/guix-compiler/src/main/java/org/nuiton/guix/databinding/BindingUtils.java =================================================================== --- trunk/guix-compiler/src/main/java/org/nuiton/guix/databinding/BindingUtils.java 2009-08-25 10:35:58 UTC (rev 1573) +++ trunk/guix-compiler/src/main/java/org/nuiton/guix/databinding/BindingUtils.java 2009-08-25 10:49:26 UTC (rev 1574) @@ -1,174 +0,0 @@ -/** - * *##% guix-compiler - * Copyright (C) 2009 CodeLutin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%* - */ -package org.nuiton.guix.databinding; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * - * @author kevin - */ -public class BindingUtils { - /** left brace matcher */ - protected static Matcher leftBraceMatcher = Pattern.compile("^(\\{)|[^\\\\](\\{)").matcher(""); - /** right brace matcher */ - protected static Matcher rightBraceMatcher = Pattern.compile("^(\\})|[^\\\\](\\})").matcher(""); - /** log */ - private static Log log = LogFactory.getLog(BindingUtils.class); - - /** - * Examine an attribute value for data binding expressions. Returns a 'cooked' expression which - * can be used to determine the resulting value. It is expected that this expression will be used - * as the source expression in a call to {@link #registerDataBinding}. - * If the attribute value does not invoke data binding, this method returns <code>null</code> - * - * @param stringValue the string value of the property from the XML - * @param type the type of the property, from the <code>JAXXPropertyDescriptor</code> - * @return a processed version of the expression - * @throws jaxx.CompilerException ? - */ - public static String processDataBindings(String stringValue) { - int pos = getNextLeftBrace(stringValue, 0); - if (pos != -1) { - StringBuffer expression = new StringBuffer(); - int lastPos = 0; - while (pos != -1 && pos < stringValue.length()) { - if (pos > lastPos) { - if (expression.length() > 0) { - expression.append(" + "); - } - expression.append('"'); - expression.append(escapeJavaString(stringValue.substring(lastPos, pos))); - expression.append('"'); - } - - if (expression.length() > 0) { - expression.append(" + "); - } - int pos2 = getNextRightBrace(stringValue, pos + 1); - if (pos2 == -1) { - if(log.isErrorEnabled()) - log.error("unmatched '{' in expression: " + stringValue); - return ""; - } - expression.append(stringValue.substring(pos + 1, pos2)); - pos2++; - if (pos2 < stringValue.length()) { - pos = getNextLeftBrace(stringValue, pos2); - lastPos = pos2; - } else { - pos = stringValue.length(); - lastPos = pos; - } - } - if (lastPos < stringValue.length()) { - if (expression.length() > 0) { - expression.append(" + "); - } - expression.append('"'); - expression.append(escapeJavaString(stringValue.substring(lastPos))); - expression.append('"'); - } -// -// StringBuffer el = new StringBuffer(); -// Pattern p = Pattern .compile("\\.(get|is)([A-Z])([a-zA-Z0-9]*)\\(\\)"); -// Matcher m = p.matcher(expression.toString()); -// int mEnd = 0; -// if(m.find()) { -// do { -// el.append(expression.toString().substring(mEnd, m.start())) -// .append("."); -// mEnd = m.end(); -// el.append(m.group(2).toLowerCase()) -// .append(m.group(3)); -// } while (m.find()); -// } -// else { -// el.append(expression.toString()); -// } -// return el.toString().length() > 0 ? el.toString().substring(0, el.toString().length()) : el.toString(); - return expression.toString(); - } - return null; - } - - protected static int getNextLeftBrace(String string, int pos) { - leftBraceMatcher.reset(string); - return leftBraceMatcher.find(pos) ? Math.max(leftBraceMatcher.start(1), leftBraceMatcher.start(2)) : -1; - } - - protected static int getNextRightBrace(String string, int pos) { - leftBraceMatcher.reset(string); - rightBraceMatcher.reset(string); - int openCount = 1; - int rightPos; - while (openCount > 0) { - pos++; - int leftPos = leftBraceMatcher.find(pos) ? Math.max(leftBraceMatcher.start(1), leftBraceMatcher.start(2)) : -1; - rightPos = rightBraceMatcher.find(pos) ? Math.max(rightBraceMatcher.start(1), rightBraceMatcher.start(2)) : -1; - assert leftPos == -1 || leftPos >= pos; - assert rightPos == -1 || rightPos >= pos; - if (leftPos != -1 && leftPos < rightPos) { - pos = leftPos; - openCount++; - } else if (rightPos != -1) { - pos = rightPos; - openCount--; - } else { - openCount = 0; - } - } - return pos; - } - - /** - * Escapes a string using standard Java escape sequences, generally in preparation to including it in a string literal - * in a compiled Java file. - * - * @param raw the raw string to be escape - * @return a string in which all 'dangerous' characters have been replaced by equivalent Java escape sequences - */ - protected static String escapeJavaString(String raw) { - StringBuffer out = new StringBuffer(raw); - for (int i = 0; i < out.length(); i++) { - char c = out.charAt(i); - if (c == '\\' || c == '"') { - out.insert(i, '\\'); - i++; - } else if (c == '\n') { - out.replace(i, i + 1, "\\n"); - i++; - } else if (c == '\r') { - out.replace(i, i + 1, "\\r"); - i++; - } else if (c < 32 || c > 127) { - String value = Integer.toString((int) c, 16); - while (value.length() < 4) { - value = "0" + value; - } - out.replace(i, i + 1, "\\u" + value); - i += 5; - } - } - return out.toString(); - } -} Deleted: trunk/guix-compiler/src/main/java/org/nuiton/guix/databinding/DataBinding.java =================================================================== --- trunk/guix-compiler/src/main/java/org/nuiton/guix/databinding/DataBinding.java 2009-08-25 10:35:58 UTC (rev 1573) +++ trunk/guix-compiler/src/main/java/org/nuiton/guix/databinding/DataBinding.java 2009-08-25 10:49:26 UTC (rev 1574) @@ -1,92 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package org.nuiton.guix.databinding; - -import org.nuiton.guix.CompilerException; -import org.nuiton.guix.GuixCompiler; - -/** - * Represents a data binding in a JAXX file. <code>DataBinding</code> uses {@link DataSource} to - * track changes to a source expression and update the destination. - */ -public class DataBinding { - private String id; - - /** The DatSource which tracks source expression changes. */ - private DataSource dataSource; - - /** The data binding destination in the form <code><id>.<propertyName></code>. */ - private String dest; - - /** - * A Java snippet which will cause the destination property to be updated with the current value of - * the binding. - */ - private String assignment; - - /** The current <code>GuixCompiler</code>. */ - private GuixCompiler compiler; - - - /** - * Creates a new data binding. - * - * @param source the Java source code for the data binding expression - * @param dest the data binding destination in the form <code><id>.<propertyName></code> - * @param assignment Java snippet which will cause the destination property to be updated with the current value of the binding - * @param compiler the current <code>JAXXCompiler</code> - */ - public DataBinding(String source, String dest, String assignment, GuixCompiler compiler) { - this.id = dest; - this.dataSource = new DataSource(id, source); - this.dest = dest; - this.assignment = assignment; - this.compiler = compiler; - } - - - public String getId() { - return id; - } - - - /** - * Compiles the data binding expression. This method calls methods in <code>JAXXCompiler</code> - * to add the Java code that performs the data binding setup. - * - * @param quickNoDependencies true to optimize bindings with no dependencies by simply running them at startup time - * @return <code>true</code> if the expression has dependencies, <code>false</code> otherwise - * @throws CompilerException if a compilation error occurs - */ -// public boolean compile(boolean quickNoDependencies) throws CompilerException { -// // DataSource.compile handles all of the listener additions -// boolean result = dataSource.compile("new jaxx.runtime.DataBindingListener(" + compiler.getRootObject().getJavaCode() + ", " + TypeManager.getJavaCode(id) + ")"); -// -// if (!result && quickNoDependencies) { -// if (!dest.endsWith(".layout")) // layout is specially handled early in the chain -// { -// compiler.appendInitDataBindings(assignment + JAXXCompiler.getLineSeparator()); -// } -// return false; // no dependencies, just a static expression -// } -// if (compiler.haveProcessDataBinding()) { -// compiler.appendProcessDataBinding(" else "); -// } else { -// compiler.appendProcessDataBinding(" "); -// } -// compiler.appendProcessDataBinding("if (" + TypeManager.getJavaCode(id) + ".equals($dest)) {" + JAXXCompiler.getLineSeparator()); -// String objectCode = dataSource.getObjectCode(); -// if (objectCode != null) { -// compiler.appendProcessDataBinding(" if (" + objectCode + " != null) {" + JAXXCompiler.getLineSeparator()); -// compiler.appendProcessDataBinding(" "); -// } -// compiler.appendProcessDataBinding(" " + assignment.trim()); -// if (objectCode != null) { -// compiler.appendProcessDataBinding(JAXXCompiler.getLineSeparator() + " }"); -// } -// compiler.appendProcessDataBinding(JAXXCompiler.getLineSeparator() + " }"); -// return true; -// } -} \ No newline at end of file Deleted: trunk/guix-compiler/src/main/java/org/nuiton/guix/databinding/DataSource.java =================================================================== --- trunk/guix-compiler/src/main/java/org/nuiton/guix/databinding/DataSource.java 2009-08-25 10:35:58 UTC (rev 1573) +++ trunk/guix-compiler/src/main/java/org/nuiton/guix/databinding/DataSource.java 2009-08-25 10:49:26 UTC (rev 1574) @@ -1,460 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package org.nuiton.guix.databinding; - -import java.beans.Introspector; -import java.beans.PropertyChangeListener; -import java.io.StringReader; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.guix.CompilerException; -import org.nuiton.guix.UnsupportedAttributeException; -import org.nuiton.guix.generator.JavaField; -import org.nuiton.guix.parser.JavaParser; -import org.nuiton.guix.parser.JavaParserConstants; -import org.nuiton.guix.parser.JavaParserTreeConstants; -import org.nuiton.guix.parser.SimpleNode; -import org.nuiton.guix.tags.DefaultTagHandler; -import org.nuiton.guix.tags.TagHandler; -import org.nuiton.guix.tags.TagManager; - -/** - * Represents a Java expression which fires a <code>PropertyChangeEvent</code> when it can be - * determined that its value may have changed. Events are fired on a "best effort" basis, and events - * may either be fired too often (the value has not actually changed) or not often enough (the value - * changed but no event was fired). - */ -public class DataSource { - private class NULL { - } // type attached to "null" constants in parsed expressions - - private Log log = LogFactory.getLog(DataSource.class); - - private String id; - - /** The Java source code for the expression. */ - private String source; - - /** The current <code>JAXXCompiler</code>. */ - //private JAXXCompiler compiler; - - /** List of symbols which this data source expression depends on. */ - private List<String> dependencySymbols = new ArrayList<String>(); - - private StringBuffer addListenerCode = new StringBuffer(); - private StringBuffer removeListenerCode = new StringBuffer(); - private boolean compiled; - - /** the delegate of property to be required */ - private String objectCode; - - /** - * Creates a new data source. After creating a <code>DataSource</code>, use {@link #compile} - * to cause it to function at runtime. - * - * @param id the DataSource's id - * @param source the Java source code for the data source expression - * @param compiler the current <code>JAXXCompiler</code> - */ - public DataSource(String id, String source) { - this.id = id; - this.source = source; - } - - - public String getId() { - return id; - } - - public String getSource() { - return source; - } - - public String getObjectCode() { - return objectCode; - } - - /** - * Compiles the data source expression and listener. This method calls methods in <code>JAXXCompiler</code> - * to add the Java code that performs the data source setup. Adding listeners to <code>DataSource</code> is - * slightly more complicated than with ordinary classes, because <code>DataSource</code> only exists at compile - * time. You must pass in a Java expression which evaluates to a <code>PropertyChangeListener</code>; this - * expression will be compiled and evaluated at runtime to yield the <code>DataSource's</code> listener. - * - * @param propertyChangeListenerCode Java code snippet which evaluates to a <code>PropertyChangeListener</code> - * @return <code>true</code> if the expression has dependencies, <code>false</code> otherwise - * @throws CompilerException if a compilation error occurs - */ -// public boolean compile(String propertyChangeListenerCode) throws CompilerException { -// if (compiled) { -// throw new IllegalStateException(this + " has already been compiled"); -// } -// String id = ""; -// JavaParser p = new JavaParser(new StringReader(source + ";")); -// while (!p.Line()) { -// SimpleNode node = p.popNode(); -// scanNode(node, id); -// } -// -// if (dependencySymbols.size() > 0) { -// //TC 20081108 prefer add a real JavaField instead of raw code -// //compiler.appendBodyCode("private PropertyChangeListener " + id + " = " + propertyChangeListenerCode + ";\n"); -// compiler.addSimpleField(new JavaField(Modifier.PRIVATE, PropertyChangeListener.class.getName(), id, propertyChangeListenerCode)); -// } -// -// compileListeners(); -// compiled = true; -// -// return dependencySymbols.size() > 0; -// } -// -// /** @return a list of symbols on which this data source depends. */ -// public Collection<String> getDependencies() { -// return Collections.unmodifiableList(dependencySymbols); -// } -// -// /** -// * Examines a node to identify any dependencies it contains. -// * -// * @param node node to scan -// * @param listenerId id of listener -// * @throws jaxx.CompilerException ? -// */ -// private void scanNode(SimpleNode node, String listenerId) throws CompilerException { -// switch (node.getId()) { -// case JavaParserTreeConstants.JJTMETHODDECLARATION: -// break; -// case JavaParserTreeConstants.JJTFIELDDECLARATION: -// break; -// -// default: -// int count = node.jjtGetNumChildren(); -// for (int i = 0; i < count; i++) { -// scanNode(node.getChild(i), listenerId); -// } -// determineNodeType(node, listenerId); -// } -// } -// -// private Class determineLiteralType(SimpleNode node) { -// assert node.getId() == JavaParserTreeConstants.JJTLITERAL; -// if (node.jjtGetNumChildren() == 1) { -// int id = node.getChild(0).getId(); -// if (id == JavaParserTreeConstants.JJTBOOLEANLITERAL) { -// return boolean.class; -// } -// if (id == JavaParserTreeConstants.JJTNULLLITERAL) { -// return null; -// } -// throw new RuntimeException("Expected BooleanLiteral or NullLiteral, found " + JavaParserTreeConstants.jjtNodeName[id]); -// } -// int id = node.firstToken.kind; -// switch (id) { -// case JavaParserConstants.INTEGER_LITERAL: -// if (node.firstToken.image.toLowerCase().endsWith("l")) { -// return long.class; -// } -// return int.class; -// case JavaParserConstants.CHARACTER_LITERAL: -// return char.class; -// case JavaParserConstants.FLOATING_POINT_LITERAL: -// if (node.firstToken.image.toLowerCase().endsWith("f")) { -// return float.class; -// } -// return double.class; -// case JavaParserConstants.STRING_LITERAL: -// return String.class; -// default: -// throw new RuntimeException("Expected literal token, found " + JavaParserConstants.tokenImage[id]); -// } -// } -// -// /** -// * Scans through a compound symbol (foo.bar.baz) to identify and track all trackable pieces of it. -// * -// * @param symbol symbol to scan -// * @param contextClass current class context -// * @param isMethod flag to search a method -// * @param listenerId id of the listener -// * @return the type of the symbol (or null if it could not be determined). -// */ -// private Class scanCompoundSymbol(String symbol, Class contextClass, boolean isMethod, String listenerId) { -// String[] tokens = symbol.split("\\s*\\.\\s*"); -// StringBuffer currentSymbol = new StringBuffer(); -// StringBuffer tokensSeenSoFar = new StringBuffer(); -// boolean accepted; // if this ends up false, it means we weren't able to figure out -// // which object the method is being invoked on -// boolean recognizeClassNames = true; -// for (int j = 0; j < tokens.length - (isMethod ? 1 : 0); j++) { -// accepted = false; -// -// if (tokensSeenSoFar.length() > 0) { -// tokensSeenSoFar.append('.'); -// } -// tokensSeenSoFar.append(tokens[j]); -// if (currentSymbol.length() > 0) { -// currentSymbol.append('.'); -// } -// currentSymbol.append(tokens[j]); -// -// if (currentSymbol.indexOf(".") == -1) { -// String memberName = currentSymbol.toString(); -// CompiledObject object = compiler.getCompiledObject(memberName); -// if (object != null) { -// contextClass = object.getObjectClass(); -// currentSymbol.setLength(0); -// accepted = true; -// recognizeClassNames = false; -// } else { -// try { -// FieldDescriptor field = contextClass.getFieldDescriptor(memberName); -// trackMemberIfPossible(tokensSeenSoFar.toString(), contextClass, field.getName(), false, listenerId); -// contextClass = field.getType(); -// currentSymbol.setLength(0); -// accepted = true; -// recognizeClassNames = false; -// } -// catch (NoSuchFieldException e) { -// if (j == 0 || j == 1 && tokens[0].equals(compiler.getRootObject().getId())) { // still in root context -// FieldDescriptor[] newFields = compiler.getScriptFields(); -// for (FieldDescriptor newField : newFields) { -// if (newField.getName().equals(memberName)) { -// addListener(tokensSeenSoFar.toString(), -// null, -// "addPropertyChangeListener(\"" + memberName + "\", " + listenerId + ");" + JAXXCompiler.getLineSeparator(), -// "removePropertyChangeListener(\"" + memberName + "\", " + listenerId + ");" + JAXXCompiler.getLineSeparator()); -// contextClass = newField.getType(); -// assert contextClass != null : "script field '" + memberName + "' is defined, but has type null"; -// currentSymbol.setLength(0); -// accepted = true; -// recognizeClassNames = false; -// break; -// } -// } -// } -// } -// } -// } -// if (currentSymbol.length() > 0 && recognizeClassNames) { -// contextClass = TagManager.resolveClass(currentSymbol.toString(), compiler); -// if (contextClass != null) { -// currentSymbol.setLength(0); -// //accepted = true; -// //recognizeClassNames = false; -// // TODO: for now we don't handle statics -// return null; -// } -// } -// if (!accepted) { -// return null; -// } -// } -// -// return contextClass; -// } -// -// /** -// * Adds type information to nodes where possible, and as a side effect adds event listeners to nodes which -// * can be tracked. -// * -// * @param expression the node to scan -// * @param listenerId id of the listener -// * @return the class descriptor of the return type or null -// */ -// private Class determineExpressionType(SimpleNode expression, String listenerId) { -// assert expression.getId() == JavaParserTreeConstants.JJTPRIMARYEXPRESSION; -// SimpleNode prefix = expression.getChild(0); -// if (prefix.jjtGetNumChildren() == 1) { -// int type = prefix.getChild(0).getId(); -// if (type == JavaParserTreeConstants.JJTLITERAL || type == JavaParserTreeConstants.JJTEXPRESSION) { -// prefix.setJavaType(prefix.getChild(0).getJavaType()); -// } else if (type == JavaParserTreeConstants.JJTNAME && expression.jjtGetNumChildren() == 1) // name with no arguments after it -// { -// prefix.setJavaType(scanCompoundSymbol(prefix.getText().trim(), compiler.getRootObject().getObjectClass(), false, listenerId)); -// } -// } -// -// if (expression.jjtGetNumChildren() == 1) { -// return prefix.getJavaType(); -// } -// -// Class contextClass = prefix.getJavaType(); -// if (contextClass == null) { -// contextClass = compiler.getRootObject().getObjectClass(); -// } -// String lastNode = prefix.getText().trim(); -// -// for (int i = 1; i < expression.jjtGetNumChildren(); i++) { -// SimpleNode suffix = expression.getChild(i); -// if (suffix.jjtGetNumChildren() == 1 && suffix.getChild(0).getId() == JavaParserTreeConstants.JJTARGUMENTS) { -// if (suffix.getChild(0).jjtGetNumChildren() == 0) { // at the moment only no-argument methods are trackable -// contextClass = scanCompoundSymbol(lastNode, contextClass, true, listenerId); -// if (contextClass == null) { -// return null; -// } -// int dotPos = lastNode.lastIndexOf("."); -// String objectCode = dotPos == -1 ? "" : lastNode.substring(0, dotPos); -// for (int j = i - 2; j >= 0; j--) { -// objectCode = expression.getChild(j).getText() + objectCode; -// } -// if (objectCode.length() == 0) { -// objectCode = compiler.getRootObject().getJavaCode(); -// } -// String methodName = lastNode.substring(dotPos + 1).trim(); -// try { -// MethodDescriptor method = contextClass.getMethodDescriptor(methodName); -// trackMemberIfPossible(objectCode, contextClass, method.getName(), true, listenerId); -// return method.getReturnType(); -// } -// catch (NoSuchMethodException e) { -// // happens for methods defined in the current JAXX file via scripts -// String propertyName = null; -// if (methodName.startsWith("is")) { -// propertyName = Introspector.decapitalize(methodName.substring("is".length())); -// } else if (methodName.startsWith("get")) { -// propertyName = Introspector.decapitalize(methodName.substring("get".length())); -// } -// if (propertyName != null) { -// MethodDescriptor[] newMethods = compiler.getScriptMethods(); -// for (MethodDescriptor newMethod : newMethods) { -// if (newMethod.getName().equals(methodName)) { -// addListener(compiler.getRootObject().getId(), -// null, -// "addPropertyChangeListener(\"" + propertyName + "\", " + listenerId + ");" + JAXXCompiler.getLineSeparator(), -// "removePropertyChangeListener(\"" + propertyName + "\", " + listenerId + ");" + JAXXCompiler.getLineSeparator()); -// contextClass = newMethod.getReturnType(); -// break; -// } -// } -// } -// } -// } -// } -// lastNode = suffix.getText().trim(); -// if (lastNode.startsWith(".")) { -// lastNode = lastNode.substring(1); -// } -// } -// -// return null; -// } -// -//// private void trackMemberIfPossible(String objectCode, Class objectClass, String memberName, boolean method, String listenerId) { -//// if (objectClass.isInterface()) // might be technically possible to track in some cases, but for now -//// { -//// return; // we can't create a DefaultObjectHandler for interfaces -//// } -//// -//// TagHandler handler = (TagHandler)TagManager.getGuixClassHandler(objectClass.getName()).newInstance(); -//// try { -//// if (handler.isMemberBound(memberName)) { -//// addListener(objectCode + "." + memberName + (method ? "()" : ""), -//// objectCode, -//// handler.getAddMemberListenerCode(objectCode, id, memberName, listenerId, compiler), -//// handler.getRemoveMemberListenerCode(objectCode, id, memberName, listenerId, compiler)); -//// } -//// } -//// catch (UnsupportedAttributeException e) { -//// // ignore -- this is thrown for methods like toString(), for which there is no tracking and -//// // no setting support -//// } -//// } -// -// /** -// * Adds type information to nodes where possible, and as a side effect adds event listeners to nodes which -// * can be tracked. -// * -// * @param node node to scan -// * @param listenerId the listener id -// */ -// private void determineNodeType(SimpleNode node, String listenerId) { -// Class type = null; -// if (node.jjtGetNumChildren() == 1) { -// type = node.getChild(0).getJavaType(); -// } -// switch (node.getId()) { -// case JavaParserTreeConstants.JJTCLASSORINTERFACETYPE: -// type = Class.class; -// break; -// case JavaParserTreeConstants.JJTPRIMARYEXPRESSION: -// type = determineExpressionType(node, listenerId); -// break; -// case JavaParserTreeConstants.JJTLITERAL: -// type = determineLiteralType(node); -// break; -// case JavaParserTreeConstants.JJTCASTEXPRESSION: -// try { -// type = Class.forName(node.getChild(0).getText()); -// } -// catch (ClassNotFoundException eee) { -// if(log.isErrorEnabled()) { -// log.error(eee); -// } -// } -// break; -// } -// node.setJavaType(type); -// } -// -// private void addListener(String dependencySymbol, String objectCode, String addCode, String removeCode) { -// this.objectCode = objectCode; -// if (!dependencySymbols.contains(dependencySymbol)) { -// dependencySymbols.add(dependencySymbol); -// if (objectCode != null) { -// addListenerCode.append("if (").append(objectCode).append(" != null) {").append(JAXXCompiler.getLineSeparator()); -// addListenerCode.append(" "); -// } -// addListenerCode.append(" ").append(addCode); -// if (objectCode != null) { -// addListenerCode.append(" ").append("}"); -// } -// -// if (objectCode != null) { -// removeListenerCode.append("if (").append(objectCode).append(" != null) {").append(JAXXCompiler.getLineSeparator()); -// removeListenerCode.append(" "); -// } -// removeListenerCode.append(" ").append(removeCode); -// if (objectCode != null) { -// removeListenerCode.append(" }"); -// } -// } -// } -// -// private void compileListeners() { -// String javaCodeId = TypeManager.getJavaCode(id); -// if (addListenerCode.length() > 0) { -// if (compiler.haveApplyDataBinding()) { -// compiler.appendApplyDataBinding(" else "); -// } -// compiler.appendApplyDataBinding("if (" + javaCodeId + ".equals($binding)) {" + JAXXCompiler.getLineSeparator()); -// compiler.appendApplyDataBinding(" " + addListenerCode + JAXXCompiler.getLineSeparator()); -// compiler.appendApplyDataBinding("}"); -// //if (compiler.applyDataBinding.length() > 0) -// // compiler.applyDataBinding.append("else "); -// //compiler.applyDataBinding.append("if ($binding.equals(").append(TypeManager.getJavaCode(id)).append(")) {").append(JAXXCompiler.getLineSeparator()); -// //compiler.applyDataBinding.append(" ").append(addListenerCode).append(JAXXCompiler.getLineSeparator()); -// //compiler.applyDataBinding.append("}").append(JAXXCompiler.getLineSeparator()); -// } -// -// if (removeListenerCode.length() > 0) { -// if (compiler.haveRemoveDataBinding()) { -// compiler.appendRemoveDataBinding(" else "); -// } -// compiler.appendRemoveDataBinding("if (" + javaCodeId + ".equals($binding)) {" + JAXXCompiler.getLineSeparator()); -// compiler.appendRemoveDataBinding(" " + removeListenerCode + JAXXCompiler.getLineSeparator()); -// compiler.appendRemoveDataBinding("}"); -// //if (compiler.removeDataBinding.length() > 0) -// // compiler.removeDataBinding.append("else "); -// //compiler.removeDataBinding.append("if ($binding.equals(").append(TypeManager.getJavaCode(id)).append(")) {").append(JAXXCompiler.getLineSeparator()); -// //compiler.removeDataBinding.append(" ").append(removeListenerCode).append(JAXXCompiler.getLineSeparator()); -// //compiler.removeDataBinding.append("}").append(JAXXCompiler.getLineSeparator()); -// } -// } -} Modified: trunk/guix-compiler/src/main/java/org/nuiton/guix/generator/Generator.java =================================================================== --- trunk/guix-compiler/src/main/java/org/nuiton/guix/generator/Generator.java 2009-08-25 10:35:58 UTC (rev 1573) +++ trunk/guix-compiler/src/main/java/org/nuiton/guix/generator/Generator.java 2009-08-25 10:49:26 UTC (rev 1574) @@ -69,4 +69,9 @@ public String getLauncherName(); public void setLauncherName(String launcherName); + + public List<JavaFile> getPropertyChangeListenerDependencies(); + + public void setPropertyChangeListenerDependencies(List<JavaFile> propertyChangeListenerDependencies); + } Modified: trunk/guix-compiler/src/main/java/org/nuiton/guix/generator/GuixGenerator.java =================================================================== --- trunk/guix-compiler/src/main/java/org/nuiton/guix/generator/GuixGenerator.java 2009-08-25 10:35:58 UTC (rev 1573) +++ trunk/guix-compiler/src/main/java/org/nuiton/guix/generator/GuixGenerator.java 2009-08-25 10:49:26 UTC (rev 1574) @@ -20,6 +20,7 @@ package org.nuiton.guix.generator; import java.io.File; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -54,6 +55,8 @@ protected String launcherName = null; /** Maps the field name with a map of the attribute and its value */ protected Map<String,Map<String, String>> bindings2Generate = new HashMap<String,Map<String, String>>(); + /** List of the user file names containing the addPropertyChangeListener method */ + protected List<JavaFile> propertyChangeListenerDependencies = new ArrayList<JavaFile>(); /** * Generates a JavaFile @@ -143,6 +146,14 @@ this.bindings2Generate = bindings2Generate; } + public List<JavaFile> getPropertyChangeListenerDependencies() { + return propertyChangeListenerDependencies; + } + + public void setPropertyChangeListenerDependencies(List<JavaFile> propertyChangeListenerDependencies) { + this.propertyChangeListenerDependencies = propertyChangeListenerDependencies; + } + /** * Saves the generated files */ Modified: trunk/guix-compiler/src/main/java/org/nuiton/guix/generator/JavaFile.java =================================================================== --- trunk/guix-compiler/src/main/java/org/nuiton/guix/generator/JavaFile.java 2009-08-25 10:35:58 UTC (rev 1573) +++ trunk/guix-compiler/src/main/java/org/nuiton/guix/generator/JavaFile.java 2009-08-25 10:49:26 UTC (rev 1574) @@ -166,7 +166,8 @@ if(method.getArguments() == null && args == null) { return method; } - else if (method.getArguments().length == args.length) { + else if (method.getArguments() != null && args != null + && method.getArguments().length == args.length) { boolean samesame = true; for(int i = 0 ; i < args.length ; i++) { if(!args[i].getName().equals(method.getArguments()[i].getName()) @@ -199,7 +200,8 @@ if(method.getArguments() == null && args == null) { return method; } - else if (method.getArguments().length == args.length) { + else if (method.getArguments() != null && args != null + && method.getArguments().length == args.length) { boolean samesame = true; for(int i = 0 ; i < args.length ; i++) { if(!args[i].getName().equals(method.getArguments()[i].getName()) @@ -217,6 +219,13 @@ return null; } + public JavaMethod[] getAllMethods() { + List<JavaMethod> allMethods = new ArrayList<JavaMethod>(); + allMethods.addAll(methods); + allMethods.addAll(inheritedMethods); + return allMethods.toArray(new JavaMethod[allMethods.size()]); + } + public void addField(JavaField field) { addField(field, false); } @@ -233,7 +242,7 @@ if (javaBean) { // add full javabean support if (Boolean.class.getName().equals(field.getType())) { - content = String.format(BOOLEAN_GETTER_PATTERN, id); + content = (classType == INTERFACE) ? null : String.format(BOOLEAN_GETTER_PATTERN, id); addMethod(new JavaMethod(Modifier.PUBLIC, field.getType(), "is" + capitalizedName, null, null, content, null)); } content = (classType == INTERFACE) ? null : String.format(SETTER_PATTERN, field.getType(), id); @@ -277,6 +286,12 @@ return null; } + public JavaField[] getAllFields() { + List<JavaField> allFields = new ArrayList<JavaField>(); + allFields.addAll(fields); + allFields.addAll(inheritedFields); + return allFields.toArray(new JavaField[allFields.size()]); + } public static String addIndentation(String source, String lineSeparator) { return indent(source, false, lineSeparator); Modified: trunk/guix-compiler/src/main/java/org/nuiton/guix/generator/JavaFileGenerator.java =================================================================== --- trunk/guix-compiler/src/main/java/org/nuiton/guix/generator/JavaFileGenerator.java 2009-08-25 10:35:58 UTC (rev 1573) +++ trunk/guix-compiler/src/main/java/org/nuiton/guix/generator/JavaFileGenerator.java 2009-08-25 10:49:26 UTC (rev 1574) @@ -43,7 +43,7 @@ */ public enum Method { COMPONENTS_CREATION, COMPONENTS_SETTINGS, COMPONENTS_TREE, DATABINDING_INIT, - BEFORE_CREATION, BEFORE_INITIALIZATION, BEFORE_BINDING, IN_THE_END + BEFORE_CREATION, BEFORE_TREE, BEFORE_SETTINGS, BEFORE_BINDING, IN_THE_END } /** log */ protected Log log = LogFactory.getLog(JavaFileGenerator.class); @@ -79,7 +79,7 @@ * * @param gmo GuixModelObject which represents the class to generate */ - protected abstract void addImports(GuixModelObject gmo); + protected abstract void addImports(); /** * Fills and saves the generated file @@ -120,12 +120,15 @@ else if (m == Method.DATABINDING_INIT) { return "initDataBinding"; } - else if (m == Method.BEFORE_INITIALIZATION) { - return "beforeInitialization"; + else if (m == Method.BEFORE_TREE) { + return "beforeTree"; } else if (m == Method.COMPONENTS_CREATION) { return "componentsCreation"; } + else if (m == Method.BEFORE_SETTINGS) { + return "beforeSetting"; + } else if (m == Method.COMPONENTS_SETTINGS) { return "componentsSetting"; } Modified: trunk/guix-compiler/src/main/java/org/nuiton/guix/generator/JavaMethod.java =================================================================== --- trunk/guix-compiler/src/main/java/org/nuiton/guix/generator/JavaMethod.java 2009-08-25 10:35:58 UTC (rev 1573) +++ trunk/guix-compiler/src/main/java/org/nuiton/guix/generator/JavaMethod.java 2009-08-25 10:49:26 UTC (rev 1574) @@ -27,8 +27,6 @@ import java.util.EnumSet; import java.util.Iterator; import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * Represents a method in a Java source file being generated for output. <code>JavaMethods</code> are created @@ -181,7 +179,11 @@ return bodyCode.toString(); } + public void setBodyCode(String bodyCode) { + this.bodyCode = new StringBuffer(bodyCode); + } + /** * Appends additional code to the method's body. * Modified: trunk/guix-compiler/src/main/java/org/nuiton/guix/model/GuixModelObject.java =================================================================== --- trunk/guix-compiler/src/main/java/org/nuiton/guix/model/GuixModelObject.java 2009-08-25 10:35:58 UTC (rev 1573) +++ trunk/guix-compiler/src/main/java/org/nuiton/guix/model/GuixModelObject.java 2009-08-25 10:49:26 UTC (rev 1574) @@ -59,6 +59,9 @@ /** The contructor parameters fro this object */ private String constructor; + /** The contructor parameters fro this object */ + private boolean javaBean = true; + /** The javaDoc of the object */ private String javadoc; @@ -121,6 +124,14 @@ public void setConstructor(String constructor) { this.constructor = constructor; } + + public boolean isJavaBean() { + return javaBean; + } + + public void setJavaBean(boolean javaBean) { + this.javaBean = javaBean; + } public GuixModelObject getParent() { return parent; Modified: trunk/guix-compiler/src/main/java/org/nuiton/guix/tags/DefaultTagHandler.java =================================================================== --- trunk/guix-compiler/src/main/java/org/nuiton/guix/tags/DefaultTagHandler.java 2009-08-25 10:35:58 UTC (rev 1573) +++ trunk/guix-compiler/src/main/java/org/nuiton/guix/tags/DefaultTagHandler.java 2009-08-25 10:49:26 UTC (rev 1574) @@ -239,6 +239,11 @@ return attrMap.get(attr); } + @Override + public String getDefaultConstructor() { + return null; + } + /** * @param name ? * @return <code>true</code> if the named member is <i>bound</i> (fires <code>PropertyChangeEvent</code> Modified: trunk/guix-compiler/src/main/java/org/nuiton/guix/tags/ScriptHandler.java =================================================================== --- trunk/guix-compiler/src/main/java/org/nuiton/guix/tags/ScriptHandler.java 2009-08-25 10:35:58 UTC (rev 1573) +++ trunk/guix-compiler/src/main/java/org/nuiton/guix/tags/ScriptHandler.java 2009-08-25 10:49:26 UTC (rev 1574) @@ -40,6 +40,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.guix.generator.JavaArgument; +import org.nuiton.guix.generator.JavaField; import org.nuiton.guix.generator.JavaMethod; import org.nuiton.guix.parser.JavaParser; import org.nuiton.guix.parser.JavaParserTreeConstants; @@ -52,8 +53,10 @@ */ public class ScriptHandler { - private Log log = LogFactory.getLog(ScriptHandler.class); + private static final Log log = LogFactory.getLog(ScriptHandler.class); + private static final String SWING_POSTPROCESS_FIRST_TOKEN_PATTERN = "%1$s old%2$s = %2$s;\n%2$s"; + private static final String SWING_POSTPROCESS_LAST_TOKEN_PATTERN = "%1$s;\nfirePropertyChange(\"%2$s\", old%2$s, %2$s)"; /** * Loads the content of a script file * @@ -90,12 +93,10 @@ if ((scriptFile != null) && scriptFile.exists()) { script.append(loadScriptFile(scriptFile)); } - + xpp.nextToken(); - if (xpp.getEventType() == XmlPullParser.CDSECT) { - script.append(xpp.getText()); - } + script.append(xpp.getText()); while ((xpp.getEventType() != XmlPullParser.END_TAG) || (!xpp.getName().equals("script"))) { xpp.nextToken(); @@ -109,20 +110,21 @@ */ public enum ScriptPart { - IMPORTS, BODYCODE, INITIALIZERS, METHODS + IMPORTS, BODYCODE, INITIALIZERS, METHODS, FIELDS } /** - * Decopose the script into the different parts + * Decompose the script into the different parts * @param script the script to decompose * @return a map containing the imports, the bodycode, the initializers and the methods of the script */ - public Map<ScriptPart, Object> decomposeScript(String script) { + public static Map<ScriptPart, Object> decomposeScript(String script) { Map<ScriptPart, Object> map = new HashMap<ScriptPart, Object>(); List<String> imports = new ArrayList<String>(); StringBuffer bodyCode = new StringBuffer(); List<JavaMethod> methods = new ArrayList<JavaMethod>(); + List<JavaField> fields = new ArrayList<JavaField>(); StringBuffer initializers = new StringBuffer(); JavaParser p = new JavaParser(new StringReader(script)); @@ -137,6 +139,7 @@ bodyCode.append(ssn.get(ScriptPart.BODYCODE)); initializers.append(ssn.get(ScriptPart.INITIALIZERS)); methods.addAll((List<JavaMethod>)ssn.get(ScriptPart.METHODS)); + fields.addAll((List<JavaField>)ssn.get(ScriptPart.FIELDS)); } } //add results @@ -144,17 +147,87 @@ map.put(ScriptPart.BODYCODE, bodyCode.toString()); map.put(ScriptPart.INITIALIZERS, initializers.toString()); map.put(ScriptPart.METHODS, methods); + map.put(ScriptPart.FIELDS, fields); return map; } + public static String postProcessMethodBody(JavaMethod method, JavaField[] fields) { + JavaParser p = new JavaParser(new StringReader(method.getBodyCode())); + StringBuffer newMethodBody = new StringBuffer(); + //start parsing + while (!p.Line()) { + SimpleNode node = p.popNode(); + if (node != null) { + postProcessContents(node, Modifier.isStatic(method.getModifiers()), fields); + newMethodBody.append(node.getText()); + } + } + return newMethodBody.toString(); + } + + public static String postProcessInitializers(String initializers, JavaField[] fields) { + JavaParser p = new JavaParser(new StringReader(initializers)); + StringBuffer newInitializers = new StringBuffer(); + //start parsing + while (!p.Line()) { + SimpleNode node = p.popNode(); + if (node != null) { + postProcessContents(node, false, fields); + newInitializers.append(node.getText()); + } + } + return newInitializers.toString(); + } + + private static void postProcessContents(SimpleNode node, boolean staticContext, JavaField[] fields) { + // identify static methods and initializers -- we can't fire events statically + if (node.getId() == JavaParserTreeConstants.JJTMETHODDECLARATION) { + if (node.getParent().getChild(0).getText().indexOf("static") != -1) { + staticContext = true; + } + } + else if (node.getId() == JavaParserTreeConstants.JJTINITIALIZER) { + if (node.getText().trim().startsWith("static")) { + staticContext = true; + } + } + + int count = node.jjtGetNumChildren(); + for (int i = 0; i < count; i++) { + postProcessContents(node.getChild(i), staticContext, fields); + } + + int id = node.getId(); + if (!staticContext) { + String lhs = null; + if (id == JavaParserTreeConstants.JJTASSIGNMENTEXPRESSION || (id == JavaParserTreeConstants.JJTPOSTFIXEXPRESSION && node.jjtGetNumChildren() == 2)) { + lhs = ((SimpleNode) node.jjtGetChild(0)).getText().trim(); + } + else + if (id == JavaParserTreeConstants.JJTPREINCREMENTEXPRESSION || id == JavaParserTreeConstants.JJTPREDECREMENTEXPRESSION) { + lhs = ((SimpleNode) node.jjtGetChild(0)).getText().trim(); + } + if (lhs != null) { + for (JavaField field : fields) { + if (field.getName().equals(lhs)) { + //lhs.substring(lhs.lastIndexOf(".") + 1); + node.firstToken.image = String.format(SWING_POSTPROCESS_FIRST_TOKEN_PATTERN, field.getType(), node.firstToken.image); + node.lastToken.image = String.format(SWING_POSTPROCESS_LAST_TOKEN_PATTERN, node.lastToken.image, lhs); + } + } + } + } + } + /** * Analyse a node of the parsed script * @param node the node to analyse * @return a map containing the imports, the bodycode, the initializers and the methods of the node */ - private Map<ScriptPart, Object> analyseScriptNode(SimpleNode node) { + private static Map<ScriptPart, Object> analyseScriptNode(SimpleNode node) { List<String> imports = new ArrayList<String>(); List<JavaMethod> methods = new ArrayList<JavaMethod>(); + List<JavaField> fields = new ArrayList<JavaField>(); StringBuffer bodyCode = new StringBuffer(); StringBuffer initializers = new StringBuffer(); @@ -254,12 +327,33 @@ // the "local" variable declarations in this expression aren't actually local -- they are flagged local // just because there isn't an enclosing class scope visible to the parser. "Real" local variable // declarations won't show up here, because they will be buried inside of methods. - String text = node.getText().trim(); - if (!text.endsWith(";")) { - text += ";"; + SimpleNode fieldDeclaration = node.getChild(0).getChild(0); + String fieldClass = null, fieldName = null, fieldInit = null; + int fieldModifier = 4; //4 is Modifier.PROTECTED + + for (int i = 0; i < fieldDeclaration.jjtGetNumChildren(); i++) { + SimpleNode child = fieldDeclaration.getChild(i); + int type = child.getId(); + if(type == JavaParserTreeConstants.JJTMODIFIERS) { + fieldModifier = getModifier(child); + } + else if(type == JavaParserTreeConstants.JJTVARIABLEDECLARATOR) { + fieldName = child.getChild(0).getText().trim(); + if(child.jjtGetNumChildren() > 1) { + fieldInit = child.getChild(1).getText().trim(); + } + } + else if(type == JavaParserTreeConstants.JJTTYPE) { + fieldClass = child.getChild(0).getText().trim(); + } } - //add the field to the bodycode - bodyCode.append(text).append("\n"); + JavaField field; + if(fieldInit != null) { + initializers.append(fieldName).append(" = ").append(fieldInit).append(";\n"); + } + field = new JavaField(fieldModifier, fieldClass, fieldName, null, TagManager.getGuixClassHandler(fieldClass)); + + fields.add(field); } //if the node initialize a field else { @@ -279,6 +373,7 @@ result.put(ScriptPart.BODYCODE, bodyCode.toString()); result.put(ScriptPart.INITIALIZERS, initializers.toString()); result.put(ScriptPart.METHODS, methods); + result.put(ScriptPart.FIELDS, fields); return result; } @@ -290,7 +385,7 @@ * @param line line to scan * @return the line type */ - private int getLineType(SimpleNode line) { + private static int getLineType(SimpleNode line) { if (line.jjtGetNumChildren() == 1) { SimpleNode node = line.getChild(0); if (node.getId() == JavaParserTreeConstants.JJTBLOCKSTATEMENT) { @@ -319,7 +414,7 @@ * @param node * @return */ - private String processConstructor(String modifiers, SimpleNode node) { + private static String processConstructor(String modifiers, SimpleNode node) { //FIXME assert node.getId() == JavaParserTreeConstants.JJTCONSTRUCTORDECLARATION : "expected node to be ConstructorDeclaration, found " + JavaParserTreeConstants.jjtNodeName[node.getId()] + " instead"; assert node.getChild(0).getId() == JavaParserTreeConstants.JJTFORMALPARAMETERS : "expected node 0 to be FormalParameters, found " + JavaParserTreeConstants.jjtNodeName[node.getChild(1).getId()] + " instead"; @@ -348,7 +443,7 @@ /** * */ - private SimpleNode findExplicitConstructorInvocation(SimpleNode parent) { + private static SimpleNode findExplicitConstructorInvocation(SimpleNode parent) { if (parent.getId() == JavaParserTreeConstants.JJTEXPLICITCONSTRUCTORINVOCATION) { return parent; } @@ -369,7 +464,7 @@ * @param node the node which contains the javaDoc * @return the javadoc */ - private String getJavaDoc(SimpleNode node) { + private static String getJavaDoc(SimpleNode node) { Pattern p = Pattern.compile(".*/\\*\\*(.*)\\*/.*", Pattern.DOTALL); Matcher m = p.matcher(node.getText()); return m.matches() ? m.group(1).replace("*", "") : null; @@ -381,27 +476,27 @@ * @param node the node which contains the modifier * @return the modifier of the node */ - private int getModifier(SimpleNode node) { - int result = 0; + private static int getModifier(SimpleNode node) { + int result = 4; //remove the javadoc from the node text Pattern p = Pattern.compile(".*(/\\*\\*(.*)\\*/).*", Pattern.DOTALL); Matcher m = p.matcher(node.getText()); String modifier = m.matches() ? node.getText().replace(m.group(1), "") : node.getText(); if (modifier.contains("public")) { - result = result == 0 ? Modifier.PUBLIC : result | Modifier.PUBLIC; + result = result == 4 ? Modifier.PUBLIC : result | Modifier.PUBLIC; } if (modifier.contains("private")) { - result = result == 0 ? Modifier.PRIVATE : result | Modifier.PRIVATE; + result = result == 4 ? Modifier.PRIVATE : result | Modifier.PRIVATE; } if (modifier.contains("protected")) { - result = result == 0 ? Modifier.PROTECTED : result | Modifier.PROTECTED; + result = result == 4 ? Modifier.PROTECTED : result | Modifier.PROTECTED; } if (modifier.contains("static")) { - result = result == 0 ? Modifier.STATIC : result | Modifier.STATIC; + result = result == 4 ? Modifier.STATIC : result | Modifier.STATIC; } if (modifier.contains("final")) { - result = result == 0 ? Modifier.FINAL : result | Modifier.FINAL; + result = result == 4 ? Modifier.FINAL : result | Modifier.FINAL; } return result; } Modified: trunk/guix-compiler/src/main/java/org/nuiton/guix/tags/StyleHandler.java =================================================================== --- trunk/guix-compiler/src/main/java/org/nuiton/guix/tags/StyleHandler.java 2009-08-25 10:35:58 UTC (rev 1573) +++ trunk/guix-compiler/src/main/java/org/nuiton/guix/tags/StyleHandler.java 2009-08-25 10:49:26 UTC (rev 1574) @@ -129,6 +129,8 @@ break; case XmlPullParser.TEXT: + style.append(xpp.getText()); + xpp.nextToken(); break; // fall through case XmlPullParser.CDSECT: @@ -136,8 +138,11 @@ xpp.nextToken(); break; + + default : + break; } - } while ((xpp.getEventType() != XmlPullParser.END_TAG) && (!xpp.getName().equals("style"))); + } while ((xpp.getEventType() != XmlPullParser.END_TAG) && (xpp.getEventType() != XmlPullParser.END_DOCUMENT) && (!"style".equals(xpp.getName()))); // analyze the content of the CSS result = processStylesheet(style.toString()); Modified: trunk/guix-compiler/src/main/java/org/nuiton/guix/tags/TagHandler.java =================================================================== --- trunk/guix-compiler/src/main/java/org/nuiton/guix/tags/TagHandler.java 2009-08-25 10:35:58 UTC (rev 1573) +++ trunk/guix-compiler/src/main/java/org/nuiton/guix/tags/TagHandler.java 2009-08-25 10:49:26 UTC (rev 1574) @@ -31,6 +31,8 @@ public String getAttrToGenerate(String attr); + public String getDefaultConstructor(); + public boolean hasEventInfosAboutMethod(String methodName); public Class getEventInfosListenerClass(String methodName); Modified: trunk/guix-compiler/src/main/java/org/nuiton/guix/tags/TagManager.java =================================================================== --- trunk/guix-compiler/src/main/java/org/nuiton/guix/tags/TagManager.java 2009-08-25 10:35:58 UTC (rev 1573) +++ trunk/guix-compiler/src/main/java/org/nuiton/guix/tags/TagManager.java 2009-08-25 10:49:26 UTC (rev 1574) @@ -59,44 +59,7 @@ private TagManager() { /* not instantiable */ } - /* - * public static void reset(boolean verbose) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException { - * registeredBeans.clear(); - * registeredTags.clear(); - * defaultNamespaces.clear(); - * CompiledObjectDecorator.reset(); - * JAXXCompilerLaunchor.loadLibraries(verbose); - * } - */ - /** - * Maps a class tag to a specific <code>TagHandler</code>. When a tag representing the bean class is - * encountered (either the class' simple name, if it is unambiguous, or its fully-qualified name), the specified - * <code>TagHandler</code> will be invoked to compile it. - * - * @param beanClass the class to associate with a <code>TagHandler</code> - * @param handler the <code>TagHandler</code> class, which must descend from <code>DefaultObjectHandler</code> - * @throws IllegalArgumentException if the handler class does not descend from <code>DefaultObjectHandler</code> - */ - - /* - * public static <T extends TagHandler> void registerBean(ClassDescriptor beanClass, Class<T> handler) { - * if (!DefaultObjectHandler.class.isAssignableFrom(handler)) { - * throw new IllegalArgumentException("handler class must be a subclass of DefaultObjectHandler"); - * } - * registeredBeans.put(beanClass, handler); - * if (log.isDebugEnabled()) { - * log.debug(beanClass + " : " + handler); - * } - * String name = beanClass.getName(); - * int dotPos = name.lastIndexOf("."); - * String namespace = name.substring(0, dotPos + 1) + "*"; - * name = name.substring(dotPos + 1); - * registerDefaultNamespace(name, namespace); - * } - */ - - /** * Sets the default namespace for a tag. When the tag is encountered with no namespace specified, * the specified namespace will be assumed. Mapping the same tag to two or more default namespaces * removes the mapping and marks the entry as being ambiguous (by putting a <code>null</code> @@ -124,13 +87,13 @@ * @param className */ public static void registerGuixClassHandler(String className, Class clazz) { - guixClassHandlers.put(className, clazz); + guixClassHandlers.put(className.toUpperCase(), clazz); } public static TagHandler getGuixClassHandler(String className) { - if(guixClassHandlers.get(className) != null) { + if(guixClassHandlers.get(className.toUpperCase()) != null) { try { - return (TagHandler)guixClassHandlers.get(className).newInstance(); + return (TagHandler)guixClassHandlers.get(className.toUpperCase()).newInstance(); } catch (InstantiationException eee) { } @@ -157,142 +120,6 @@ } /** - * Registers a <code>TagHandler</code> for a tag. When a tag with the given name and namespace - * is encountered, the <code>TagHandler's compileFirstPass</code> and <code>compileSecondPass</code> - * methods will be invoked to handle it. - * <p/> - * It is not an error to register an already-registered tag and namespace combination. The new mapping - * will replace the old mapping. - * - * @param namespace the tag's namespace - * @param tag the simple name of the tag - * @param handler the <code>TagHandler</code> which should process the tag - */ - - /* - * public static <T extends TagHandler> void registerTag(String namespace, String tag, T handler) { - * if (namespace == null) { - * namespace = "*"; - * } - * //System.out.println("registerTag "+namespace+" : "+tag+" : "+handler); - * if (log.isDebugEnabled()) { - * log.debug(tag + " : " + handler); - * } - * registeredTags.put(new QName(namespace, tag), handler); - * registerDefaultNamespace(tag, namespace); - * } - */ - - /** - * Returns the <code>TagHandler</code> that should be used to process the specified tag. - * If the tag represents the class name of an uncompiled <code>.jaxx</code> file, the - * <code>.jaxx</code> is first compiled. - * - * @param namespace the tag's namespace (may be <code>null</code>) - * @param tag the tag's simple name - * @param compiler the current <code>JAXXCompiler</code> - * @return the <code>TagHandler</code> for the tag - * @throws jaxx.CompilerException ? - */ - - /* - * public static TagHandler getTagHandler(String namespace, String tag, JAXXCompiler compiler) throws CompilerException { - * return getTagHandler(namespace, tag, false, compiler); - * } - */ - - /* - * private static String getNamespace(ClassDescriptor beanClass) { - * String packageName = beanClass.getPackageName(); - * return packageName != null ? packageName + ".*" : "*"; - * - * } - */ - - /* - * private static String getSimpleName(ClassDescriptor beanClass) { - * String packageName = beanClass.getPackageName(); - * if (packageName != null) { - * assert beanClass.getName().startsWith(packageName); - * return beanClass.getName().substring(packageName.length() + 1); - * } - * return beanClass.getName(); - * } - */ - - /** - * @param beanClass the tag class - * @return the <code>TagHandler</code> that should be used to process the specified class. - * Only <code>TagHandlers</code> previously registered with <code>registerBean</code> - * are considered. - * @throws jaxx.CompilerException ? - */ - - /* - * public static DefaultObjectHandler getTagHandler(ClassDescriptor beanClass) throws CompilerException { - * try { - * if (beanClass == null) { - * throw new NullPointerException(); - * } - * String namespace = getNamespace(beanClass); - * String tag = getSimpleName(beanClass); - * DefaultObjectHandler handler = (DefaultObjectHandler) registeredTags.get(new QName(namespace, tag)); - * if (handler == null) { - * Class<? extends TagHandler> handlerClass = registeredBeans.get(beanClass); - * if (handlerClass == null) { - * throw new CompilerException("unable to find handler for " + beanClass); - * } - * Constructor<? extends TagHandler> constructor = handlerClass.getConstructor(ClassDescriptor.class); - * handler = (DefaultObjectHandler) constructor.newInstance(beanClass); - * registerTag(namespace, tag, handler); - * } - * return handler; - * } - * catch (InstantiationException e) { - * throw new RuntimeException(e); - * } - * catch (NoSuchMethodException e) { - * throw new RuntimeException(e); - * } - * catch (IllegalAccessException e) { - * throw new RuntimeException(e); - * } - * catch (InvocationTargetException e) { - * throw new RuntimeException(e); - * } - * } - */ - - /** - * Tests if a class exists - * - * @param className name of the class we want to know if it exists - * @return true if the class exists - */ - private static boolean classExists(String className) { - if (classExistenceCache.containsKey(className)) { - return classExistenceCache.get(className); - } - - boolean found = false; - - try { - Class.forName(className); - found = true; - } catch (ClassNotFoundException e) { - - // ignore ? - } catch (NoClassDefFoundError e) { // we get this instead of ClassNotFoundException on case-insensitive file systems when - - // looking up a class with the wrong case - } - - classExistenceCache.put(className, found); - - return found; - } - - /** * Resolves a simple class name (like <code>Object</code> or <code>String</code>) to its fully-qualified name. Inner * classes should be represented as they would appear in Java source code (e.g. JPopupMenu.Separator). Fully-qualified names, * such as <code>java.lang.Object</code> are legal and will be returned unmodified (and in fact it is generally impossible to @@ -311,13 +138,17 @@ if (name.indexOf("<") != -1) { name = name.substring(0, name.indexOf("<")); // strip off generic types } - + name = name.intern(); if (name.equals("boolean") || name.equals("byte") || name.equals("short") || name.equals("int") || name.equals("long") || name.equals("float") || name.equals("double") || name.equals("char")) { return name; } + else if(name.equals("Boolean") || name.equals("Byte") || name.equals("Short") || name.equals("Integer") || name.equals("String") + || name.equals("Long") || name.equals("Float") || name.equals("Double") || name.equals("Character")) { + return "java.lang." + name; + } if (guixClassHandlers.containsKey(name)) { return name;
participants (1)
-
kmorin@users.nuiton.org