Author: tchemit Date: 2009-10-28 08:18:13 +0100 (Wed, 28 Oct 2009) New Revision: 1605 Added: branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/binding/ branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataBinding.java branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataSource.java Modified: branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/CompiledObject.java branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/JAXXCompiler.java branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/JAXXEngine.java branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/css/StylesheetHelper.java branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/decorators/DefaultCompiledObjectDecorator.java branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/decorators/HelpRootCompiledObjectDecorator.java branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/DefaultFinalizer.java branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/tags/DefaultObjectHandler.java Log: - Evolution #105: permettre l'initialisation des objets sans JavaBean - Evolution #100: am?\195?\169lioration du design du compilateur - Evolution #99: Am?\195?\169liorer le code g?\195?\169n?\195?\169r?\195?\169 Modified: branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/CompiledObject.java =================================================================== --- branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/CompiledObject.java 2009-10-27 10:46:23 UTC (rev 1604) +++ branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/CompiledObject.java 2009-10-28 07:18:13 UTC (rev 1605) @@ -117,6 +117,10 @@ * client properties */ private Map<String, String> clientProperties; + /** + * initializer of the object + */ + private String initializer; public class ChildRef { @@ -426,6 +430,14 @@ this.constructorParams = constructorParams; } + public String getInitializer() { + return initializer; + } + + public void setInitializer(String initializer) { + this.initializer = initializer; + } + /** * Returns the code that performs basic initialization of this object, * after it has already been constructed. Modified: branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/JAXXCompiler.java =================================================================== --- branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/JAXXCompiler.java 2009-10-27 10:46:23 UTC (rev 1604) +++ branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/JAXXCompiler.java 2009-10-28 07:18:13 UTC (rev 1605) @@ -20,6 +20,7 @@ */ package jaxx.compiler; +import jaxx.compiler.binding.DataBinding; import jaxx.compiler.css.StylesheetHelper; import jaxx.compiler.script.ScriptManager; import jaxx.compiler.java.JavaMethod; @@ -632,18 +633,20 @@ expression.append(escapeJavaString(stringValue.substring(lastPos, pos))); expression.append('"'); } - - if (expression.length() > 0) { + boolean multi = expression.length() > 0; + if (multi) { expression.append(" + "); + expression.append('('); } - expression.append('('); int pos2 = getNextRightBrace(stringValue, pos + 1); if (pos2 == -1) { reportError("unmatched '{' in expression: " + stringValue); return ""; } expression.append(stringValue.substring(pos + 1, pos2)); - expression.append(')'); + if (multi) { + expression.append(')'); + } pos2++; if (pos2 < stringValue.length()) { pos = getNextLeftBrace(stringValue, pos2); @@ -661,7 +664,12 @@ expression.append(escapeJavaString(stringValue.substring(lastPos))); expression.append('"'); } - return type == ClassDescriptorLoader.getClassDescriptor(String.class) ? "String.valueOf(" + expression + ")" : expression.toString(); + //TC-20091027 : developper must write extact databinding + // the fact of adding the String boxed for String type binding is not + // a good thing, since it add one more call to process in binding + // and add nothing special more ? +// return type == ClassDescriptorLoader.getClassDescriptor(String.class) ? "String.valueOf(" + expression + ")" : expression.toString(); + return expression.toString(); } return null; } @@ -1307,10 +1315,22 @@ } public String getAutoId(ClassDescriptor objectClass) { + String name = objectClass.getName(); + name = name.substring(name.lastIndexOf(".") + 1); + return getAutoId(name); +// if (configuration.getOptimize()) { +// return "$" + Integer.toString(autogenID++, 36); +// } else { +// String name = objectClass.getName(); +// name = name.substring(name.lastIndexOf(".") + 1); +// return "$" + name + autogenID++; +// } + } + + public String getAutoId(String name) { if (configuration.getOptimize()) { return "$" + Integer.toString(autogenID++, 36); } else { - String name = objectClass.getName(); name = name.substring(name.lastIndexOf(".") + 1); return "$" + name + autogenID++; } @@ -1368,26 +1388,26 @@ return javaFile; } - public void finalizeCompilers(Iterable<JAXXCompilerFinalizer> generatorIterator) throws Exception { + public void finalizeCompiler(Iterable<JAXXCompilerFinalizer> finalizers) throws Exception { int dotPos = getOutputClassName().lastIndexOf("."); String packageName = dotPos != -1 ? getOutputClassName().substring(0, dotPos) : null; String simpleClassName = getOutputClassName().substring(dotPos + 1); CompiledObject compiledObject = getRootObject(); - for (JAXXCompilerFinalizer generator : generatorIterator) { - generator.finalizeCompiler(compiledObject, this, javaFile, packageName, simpleClassName); + for (JAXXCompilerFinalizer finalizer : finalizers) { + finalizer.finalizeCompiler(compiledObject, this, javaFile, packageName, simpleClassName); } for (CompiledObject object : getObjects().values()) { object.finalizeCompiler(this); } - for (JAXXCompilerFinalizer generator : generatorIterator) { - generator.prepareJavaFile(compiledObject, this, javaFile, packageName, simpleClassName); + for (JAXXCompilerFinalizer finalizer : finalizers) { + finalizer.prepareJavaFile(compiledObject, this, javaFile, packageName, simpleClassName); } } - public void generate(JavaFileGenerator generator, Iterable<JAXXCompilerFinalizer> generatorIterator) throws IOException { + public void generate(JavaFileGenerator generator) throws IOException { File dest; if (getConfiguration().getTargetDirectory() != null) { dest = new File(getConfiguration().getTargetDirectory(), getOutputClassName().replace('.', File.separatorChar) + ".java"); Modified: branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/JAXXEngine.java =================================================================== --- branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/JAXXEngine.java 2009-10-27 10:46:23 UTC (rev 1604) +++ branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/JAXXEngine.java 2009-10-28 07:18:13 UTC (rev 1605) @@ -365,7 +365,7 @@ for (String className : engine.jaxxFileClassNames) { JAXXCompiler compiler = engine.getCompiler(className, "Internal error: could not find compiler for " + className + " during code generation"); addStartProfileTime(engine, compiler); - compiler.finalizeCompilers(engine.finalizers); + compiler.finalizeCompiler(engine.finalizers); addEndProfileTime(engine, compiler); if (compiler.isFailed()) { success = false; @@ -387,7 +387,7 @@ for (String className : engine.jaxxFileClassNames) { JAXXCompiler compiler = engine.getCompiler(className, "Internal error: could not find compiler for " + className + " during code generation"); addStartProfileTime(engine, compiler); - compiler.generate(generator, engine.finalizers); + compiler.generate(generator); addEndProfileTime(engine, compiler); if (compiler.isFailed()) { success = false; Copied: branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataBinding.java (from rev 1602, branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/DataBinding.java) =================================================================== --- branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataBinding.java (rev 0) +++ branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataBinding.java 2009-10-28 07:18:13 UTC (rev 1605) @@ -0,0 +1,137 @@ +/* + * *##% + * JAXX Compiler + * Copyright (C) 2008 - 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 jaxx.compiler.binding; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * 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 { + + /** + * Logger + */ + protected static final Log log = LogFactory.getLog(DataBinding.class); + /** + * Id of the data binding + */ + private String id; + /** + * source of the data binding + */ + private String source; + /** + * A Java snippet which will cause the destination property to be updated with the current value of + * the binding. + */ + private String assignment; + + /** + * Creates a new data binding. + * + * @param source the Java source code for the data binding expression + * @param id 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 + */ + public DataBinding(String source, String id, String assignment) { + this.id = id; + this.source = source; + this.assignment = assignment; + if (log.isDebugEnabled()) { + log.debug("id=" + id + " assignement=" + assignment + " source=" + source); + } + } + + 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 compiler compiler which includes the data binding + * @param quickNoDependencies true to optimize bindings with no dependencies by simply running them at startup time + * @return {@code true} if the expression has dependencies, {@code false} otherwise + * @throws CompilerException if a compilation error occurs + */ + public boolean compile(JAXXCompiler compiler, boolean quickNoDependencies) throws CompilerException { + + DataSource dataSource = new DataSource(id, source, compiler); + + // handles all of the listener additions + //TC-20091026 use 'this' instead of root object javaCode +// boolean result = dataSource.compile("new jaxx.runtime.DataBindingListener(" + compiler.getRootObject().getJavaCode() + ", " + compiler.getJavaCode(id) + ")"); + boolean result = dataSource.compile("new jaxx.runtime.DataBindingListener(this, " + compiler.getJavaCode(id) + ")"); + if (log.isDebugEnabled()) { + log.debug(id + " isBinding ? " + result); + } + String eol = JAXXCompiler.getLineSeparator(); + if (!result && quickNoDependencies) { + // layout is specially handled early in the chain + if (!id.endsWith(".layout")) { + compiler.appendInitDataBindings(assignment + eol); + } + return false; // no dependencies, just a static expression + } + + StringBuilder buffer = new StringBuilder(); + if (compiler.hasProcessDataBinding()) { + buffer.append(" else "); +// compiler.appendProcessDataBinding(" else "); + } else { + buffer.append(" "); +// compiler.appendProcessDataBinding(" "); + } + buffer.append("if (" + compiler.getJavaCode(id) + ".equals($dest)) {" + eol); +// compiler.appendProcessDataBinding("if (" + compiler.getJavaCode(id) + ".equals($dest)) {" + eol); + String objectCode = dataSource.getObjectCode(); + if (log.isDebugEnabled()) { + log.debug(id + " objectCode= " + objectCode); + } + //TC-20091026 no need to test objectCode not null if on root object +// boolean needTest = objectCode != null; + boolean needTest = objectCode != null && !compiler.getRootObject().getId().equals(objectCode); + if (needTest) { + buffer.append(" if (" + objectCode + " != null) {" + eol); + buffer.append(" "); +// compiler.appendProcessDataBinding(" if (" + objectCode + " != null) {" + eol); +// compiler.appendProcessDataBinding(" "); + } + buffer.append(" " + assignment.trim()); +// compiler.appendProcessDataBinding(" " + assignment.trim()); + if (needTest) { + buffer.append(eol + " }"); +// compiler.appendProcessDataBinding(eol + " }"); + } + buffer.append(eol + " }"); +// compiler.appendProcessDataBinding(eol + " }"); + compiler.appendProcessDataBinding(buffer.toString()); + return true; + } +} Property changes on: branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataBinding.java ___________________________________________________________________ Added: svn:mergeinfo + Copied: branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataSource.java (from rev 1602, branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/DataSource.java) =================================================================== --- branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataSource.java (rev 0) +++ branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataSource.java 2009-10-28 07:18:13 UTC (rev 1605) @@ -0,0 +1,596 @@ +/* + * *##% + * JAXX Compiler + * Copyright (C) 2008 - 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 jaxx.compiler.binding; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.UnsupportedAttributeException; +import jaxx.compiler.java.JavaField; +import jaxx.compiler.java.parser.JavaParser; +import jaxx.compiler.java.parser.JavaParserConstants; +import jaxx.compiler.java.parser.JavaParserTreeConstants; +import jaxx.compiler.java.parser.SimpleNode; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorLoader; +import jaxx.compiler.reflect.FieldDescriptor; +import jaxx.compiler.reflect.MethodDescriptor; +import jaxx.compiler.tags.DefaultObjectHandler; +import jaxx.compiler.tags.TagManager; +import jaxx.compiler.types.TypeManager; + +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; + +/** + * 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 { + + /** + * Logger + */ + protected static final Log log = LogFactory.getLog(DataSource.class); + + /** + * type attached to "null" constants in parsed expressions + */ + private class NULL { + } + /** + * id of data source + */ + 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; + /** + * the data source id + */ + private String listenerId; + + /** + * 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, JAXXCompiler compiler) { + this.id = id; + this.source = source; + this.compiler = compiler; + if (log.isDebugEnabled()) { + log.debug("id=" + id + " source=" + source); + } + } + + public String getId() { + return id; + } + + public String getSource() { + return source; + } + + public String getObjectCode() { + return objectCode; + } + + public String getListenerId() { + return listenerId; + } + + /** + * 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 + * @throws IllegalStateException if data source was already compiled + */ + public boolean compile(String propertyChangeListenerCode) throws CompilerException, IllegalStateException { + if (compiled) { + throw new IllegalStateException(this + " has already been compiled"); + } +// String listenerId = compiler.getAutoId(ClassDescriptorLoader.getClassDescriptor(getClass())); + listenerId = compiler.getAutoId(getClass().getSimpleName()); + if (log.isDebugEnabled()) { + log.debug("listenerId=" + listenerId); + } + JavaParser p = new JavaParser(new StringReader(source)); +// JavaParser p = new JavaParser(new StringReader(source + ";")); + while (!p.Line()) { + SimpleNode node = p.popNode(); + if (log.isDebugEnabled()) { + log.debug("will scan node " + node.getText()); + } +// scanNode(node, listenerId); + scanNode(node); + } + if (log.isDebugEnabled()) { + log.debug("dependencySymbols=" + dependencySymbols); + } + if (dependencySymbols.size() > 0) { + // a real binding was detected + + // add a dataBinding field + //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.getSimpleName(), listenerId, false, propertyChangeListenerCode)); + + // add listener codes in compiler + +// compileListeners(); + String javaCodeId = TypeManager.getJavaCode(id); + String eol = JAXXCompiler.getLineSeparator(); + +// if (addListenerCode.length() > 0) { + if (compiler.hasApplyDataBinding()) { + compiler.appendApplyDataBinding(" else "); + } + compiler.appendApplyDataBinding("if (" + javaCodeId + ".equals($binding)) {"); + compiler.appendApplyDataBinding(" " + addListenerCode + eol); + compiler.appendApplyDataBinding("}"); +// } + +// if (removeListenerCode.length() > 0) { + if (compiler.hasRemoveDataBinding()) { + compiler.appendRemoveDataBinding(" else "); + } + compiler.appendRemoveDataBinding("if (" + javaCodeId + ".equals($binding)) {"); + compiler.appendRemoveDataBinding(" " + removeListenerCode + eol); + compiler.appendRemoveDataBinding("}"); +// } + } + //TC-20091027 if no dependency symbols then no listeners +// 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 CompilerException ? + */ + private void scanNode(SimpleNode node) throws CompilerException { +// private void scanNode(SimpleNode node, String listenerId) throws CompilerException { + if (node.getId() == JavaParserTreeConstants.JJTMETHODDECLARATION || + node.getId() == JavaParserTreeConstants.JJTFIELDDECLARATION) { + return; + } + if (log.isTraceEnabled()) { + log.trace(node.getText()); + } + int count = node.jjtGetNumChildren(); + for (int i = 0; i < count; i++) { + scanNode(node.getChild(i)); + } + // determine node type + ClassDescriptor type = null; + if (node.jjtGetNumChildren() == 1) { + type = node.getChild(0).getJavaType(); + } + switch (node.getId()) { + case JavaParserTreeConstants.JJTCLASSORINTERFACETYPE: + type = ClassDescriptorLoader.getClassDescriptor(Class.class); + break; + case JavaParserTreeConstants.JJTPRIMARYEXPRESSION: +// type = determineExpressionType(node, listenerId); + type = determineExpressionType(node); + break; + case JavaParserTreeConstants.JJTLITERAL: + type = determineLiteralType(node); + break; + case JavaParserTreeConstants.JJTCASTEXPRESSION: + type = TagManager.resolveClass(node.getChild(0).getText(), compiler); + break; + } + node.setJavaType(type); + +// 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); +// } + } + + /** + * 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 ClassDescriptor determineExpressionType(SimpleNode expression, String listenerId) { + private ClassDescriptor determineExpressionType(SimpleNode expression) { + 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)); + prefix.setJavaType(scanCompoundSymbol(prefix.getText().trim(), compiler.getRootObject().getObjectClass(), false)); + } + } + + if (expression.jjtGetNumChildren() == 1) { + return prefix.getJavaType(); + } + + ClassDescriptor 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); + contextClass = scanCompoundSymbol(lastNode, contextClass, true); + if (contextClass == null) { + return null; + } + int dotPos = lastNode.lastIndexOf("."); + String code = dotPos == -1 ? "" : lastNode.substring(0, dotPos); + for (int j = i - 2; j >= 0; j--) { + code = expression.getChild(j).getText() + code; + } + if (code.length() == 0) { + code = compiler.getRootObject().getJavaCode(); + } + String methodName = lastNode.substring(dotPos + 1).trim(); + try { + MethodDescriptor method = contextClass.getMethodDescriptor(methodName); +// trackMemberIfPossible(code, contextClass, method.getName(), true, listenerId); + trackMemberIfPossible(code, contextClass, method.getName(), true); + 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) { + //TC-20091026 use the getScriptMethod from compiler + MethodDescriptor newMethod = compiler.getScriptMethod(methodName); + if (newMethod != null) { + addListener(compiler.getRootObject().getId(), + null, + "addPropertyChangeListener(\"" + propertyName + "\", " + listenerId + ");" + JAXXCompiler.getLineSeparator(), + "removePropertyChangeListener(\"" + propertyName + "\", " + listenerId + ");" + JAXXCompiler.getLineSeparator()); + contextClass = newMethod.getReturnType(); + } +// 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 ClassDescriptor determineLiteralType(SimpleNode node) { + assert node.getId() == JavaParserTreeConstants.JJTLITERAL; + if (node.jjtGetNumChildren() == 1) { + int childId = node.getChild(0).getId(); + if (childId == JavaParserTreeConstants.JJTBOOLEANLITERAL) { + return ClassDescriptorLoader.getClassDescriptor(boolean.class); + } + if (childId == JavaParserTreeConstants.JJTNULLLITERAL) { + return ClassDescriptorLoader.getClassDescriptor(NULL.class); + } + throw new RuntimeException("Expected BooleanLiteral or NullLiteral, found " + JavaParserTreeConstants.jjtNodeName[childId]); + } + int nodeId = node.firstToken.kind; + switch (nodeId) { + case JavaParserConstants.INTEGER_LITERAL: + if (node.firstToken.image.toLowerCase().endsWith("l")) { + return ClassDescriptorLoader.getClassDescriptor(long.class); + } + return ClassDescriptorLoader.getClassDescriptor(int.class); + case JavaParserConstants.CHARACTER_LITERAL: + return ClassDescriptorLoader.getClassDescriptor(char.class); + case JavaParserConstants.FLOATING_POINT_LITERAL: + if (node.firstToken.image.toLowerCase().endsWith("f")) { + return ClassDescriptorLoader.getClassDescriptor(float.class); + } + return ClassDescriptorLoader.getClassDescriptor(double.class); + case JavaParserConstants.STRING_LITERAL: + return ClassDescriptorLoader.getClassDescriptor(String.class); + default: + throw new RuntimeException("Expected literal token, found " + JavaParserConstants.tokenImage[nodeId]); + } + } + + /** + * 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 ClassDescriptor scanCompoundSymbol(String symbol, ClassDescriptor contextClass, boolean isMethod, String listenerId) { + private ClassDescriptor scanCompoundSymbol(String symbol, ClassDescriptor contextClass, 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); +// trackMemberIfPossible(tokensSeenSoFar.toString(), contextClass, field.getName(), false, listenerId); + trackMemberIfPossible(tokensSeenSoFar.toString(), contextClass, field.getName(), false); + 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; + } + +// private void trackMemberIfPossible(String objectCode, ClassDescriptor objectClass, String memberName, boolean method, String listenerId) { + private void trackMemberIfPossible(String objectCode, ClassDescriptor objectClass, String memberName, boolean method) { +// if (objectClass.isInterface()) { +// // might be technically possible to track in some cases, but for now +// // we can't create a DefaultObjectHandler for interfaces +// return; +// } + + DefaultObjectHandler handler = TagManager.getTagHandler(objectClass); + 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 + } + } + + private void addListener(String dependencySymbol, String objectCode, String addCode, String removeCode) { + this.objectCode = objectCode; + //TC-20091026 no need to test objectCode not null if on root object +// boolean needTest = objectCode != null; + boolean needTest = objectCode != null && !compiler.getRootObject().getId().equals(objectCode); + if (!dependencySymbols.contains(dependencySymbol)) { + dependencySymbols.add(dependencySymbol); + String eol = JAXXCompiler.getLineSeparator(); + addListenerCode.append(eol); + if (needTest) { + addListenerCode.append(" if (").append(objectCode).append(" != null) {").append(eol); + addListenerCode.append(" "); + } + addListenerCode.append(" ").append(addCode.trim()); + if (needTest) { + addListenerCode.append(eol).append(" }"); + } + + removeListenerCode.append(eol); + if (needTest) { + removeListenerCode.append(" if (").append(objectCode).append(" != null) {").append(eol); + removeListenerCode.append(" "); + } + removeListenerCode.append(" ").append(removeCode.trim()); + if (needTest) { + removeListenerCode.append(eol).append(" }"); + } + } + } +// /** +// * 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) { +// private void determineNodeType(SimpleNode node) { +// ClassDescriptor type = null; +// if (node.jjtGetNumChildren() == 1) { +// type = node.getChild(0).getJavaType(); +// } +// switch (node.getId()) { +// case JavaParserTreeConstants.JJTCLASSORINTERFACETYPE: +// type = ClassDescriptorLoader.getClassDescriptor(Class.class); +// break; +// case JavaParserTreeConstants.JJTPRIMARYEXPRESSION: +// type = determineExpressionType(node, listenerId); +// break; +// case JavaParserTreeConstants.JJTLITERAL: +// type = determineLiteralType(node); +// break; +// case JavaParserTreeConstants.JJTCASTEXPRESSION: +// type = TagManager.resolveClass(node.getChild(0).getText(), compiler); +// break; +// } +// node.setJavaType(type); +// } +// private void compileListeners() { +// String javaCodeId = TypeManager.getJavaCode(id); +// String eol = JAXXCompiler.getLineSeparator(); +// if (addListenerCode.length() > 0) { +// if (compiler.hasApplyDataBinding()) { +// compiler.appendApplyDataBinding(" else "); +// } +//// compiler.appendApplyDataBinding("if (" + javaCodeId + ".equals($binding)) {" + eol); +// compiler.appendApplyDataBinding("if (" + javaCodeId + ".equals($binding)) {"); +// compiler.appendApplyDataBinding(" " + addListenerCode + eol); +// compiler.appendApplyDataBinding("}"); +// } +// +// if (removeListenerCode.length() > 0) { +// if (compiler.hasRemoveDataBinding()) { +// compiler.appendRemoveDataBinding(" else "); +// } +//// compiler.appendRemoveDataBinding("if (" + javaCodeId + ".equals($binding)) {" + eol); +// compiler.appendRemoveDataBinding("if (" + javaCodeId + ".equals($binding)) {"); +// compiler.appendRemoveDataBinding(" " + removeListenerCode + eol); +// compiler.appendRemoveDataBinding("}"); +// } +// } +} Property changes on: branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataSource.java ___________________________________________________________________ Added: svn:mergeinfo + Modified: branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/css/StylesheetHelper.java =================================================================== --- branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/css/StylesheetHelper.java 2009-10-27 10:46:23 UTC (rev 1604) +++ branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/css/StylesheetHelper.java 2009-10-28 07:18:13 UTC (rev 1605) @@ -20,6 +20,8 @@ */ package jaxx.compiler.css; +import jaxx.compiler.binding.DataSource; +import jaxx.compiler.binding.DataBinding; import jaxx.compiler.*; import jaxx.runtime.css.Selector; import jaxx.runtime.css.Rule; Modified: branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/decorators/DefaultCompiledObjectDecorator.java =================================================================== --- branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/decorators/DefaultCompiledObjectDecorator.java 2009-10-27 10:46:23 UTC (rev 1604) +++ branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/decorators/DefaultCompiledObjectDecorator.java 2009-10-28 07:18:13 UTC (rev 1605) @@ -81,6 +81,8 @@ String init = object.getId() + " = "; if (object.isJavaBean() && object.getJavaBeanInitCode() != null) { init += object.getJavaBeanInitCode(); + } else if (object.getInitializer() != null) { + init += object.getInitializer(); } else { //TC - 20081017 compiledObject can have generics String canonicalName = JAXXCompiler.getCanonicalName(object); Modified: branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/decorators/HelpRootCompiledObjectDecorator.java =================================================================== --- branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/decorators/HelpRootCompiledObjectDecorator.java 2009-10-27 10:46:23 UTC (rev 1604) +++ branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/decorators/HelpRootCompiledObjectDecorator.java 2009-10-28 07:18:13 UTC (rev 1605) @@ -88,23 +88,23 @@ String eol = JAXXCompiler.getLineSeparator(); - if (options.isGenerateHelp()) { +// if (options.isGenerateHelp()) { - // add code to init javax help system - Iterator<CompiledObject> itr = compiler.getObjectCreationOrder(); + // add code to init javax help system + Iterator<CompiledObject> itr = compiler.getObjectCreationOrder(); - for (; itr.hasNext();) { - CompiledObject o = itr.next(); - String helpID = getHelpId(o); - if (helpID != null) { - buffer.append(eol); - // detects a helpId to register - buffer.append("registerHelpId(_broker, " + o.getJavaCode() + ", " + helpID + ");"); - //keep the helpID for helpSet generation - helpIds.add(helpID); - } + for (; itr.hasNext();) { + CompiledObject o = itr.next(); + String helpID = getHelpId(o); + if (helpID != null) { + buffer.append(eol); + // detects a helpId to register + buffer.append("registerHelpId(_broker, " + o.getJavaCode() + ", " + helpID + ");"); + //keep the helpID for helpSet generation + helpIds.add(helpID); } } +// } if (buffer.length() > 0) { StringBuilder extraCode = new StringBuilder(helpBrokerFQN).append(" _broker = getBroker();"); Modified: branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/DefaultFinalizer.java =================================================================== --- branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/DefaultFinalizer.java 2009-10-27 10:46:23 UTC (rev 1604) +++ branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/DefaultFinalizer.java 2009-10-28 07:18:13 UTC (rev 1605) @@ -24,7 +24,7 @@ import jaxx.compiler.CompilerException; import jaxx.compiler.CompiledObject; import jaxx.compiler.CompiledObjectDecorator; -import jaxx.compiler.DataBinding; +import jaxx.compiler.binding.DataBinding; import jaxx.compiler.EventHandler; import jaxx.compiler.JAXXCompiler; import jaxx.compiler.java.JavaMethod; @@ -39,7 +39,6 @@ import jaxx.runtime.JAXXObject; import jaxx.runtime.JAXXObjectDescriptor; import jaxx.runtime.JAXXContext; -import jaxx.runtime.Util; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -48,6 +47,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import jaxx.runtime.Util; import static jaxx.compiler.java.JavaFileGenerator.*; /** @@ -242,45 +242,10 @@ CompiledObjectDecorator decorator = object.getDecorator(); decorator.finalizeCompiler(compiler, root, object, javaFile, packageName, className, fullClassName); } - String eol = JAXXCompiler.getLineSeparator(); - // DataBinding - for (DataBinding dataBinding : compiler.getDataBindings()) { - if (dataBinding.compile(compiler, true)) { - String expression = "applyDataBinding(" + compiler.getJavaCode(dataBinding.getId()) + ");" + eol; - compiler.appendInitDataBindings(expression); - } - } + finalizeBindings(compiler, superclassIsJAXXObject); - if (superclassIsJAXXObject) { - boolean hasBind = compiler.hasApplyDataBinding(); - if (hasBind) { - compiler.appendApplyDataBinding(" else {"); - compiler.appendApplyDataBinding(eol); - compiler.appendApplyDataBinding(" "); - } - compiler.appendApplyDataBinding("super.applyDataBinding($binding);"); - compiler.appendApplyDataBinding(eol); - - if (hasBind) { - compiler.appendApplyDataBinding(" return;"); - compiler.appendApplyDataBinding(eol); - compiler.appendApplyDataBinding("}"); - } - - hasBind = compiler.hasRemoveDataBinding(); - if (hasBind) { - compiler.appendRemoveDataBinding(" else {"); - compiler.appendRemoveDataBinding(eol); - compiler.appendRemoveDataBinding(" "); - } - compiler.appendRemoveDataBinding("super.removeDataBinding($binding);"); - compiler.appendRemoveDataBinding(eol); - - if (hasBind) { - compiler.appendRemoveDataBinding("}"); - } - } else { + if (!superclassIsJAXXObject) { javaFile.addInterface(JAXXCompiler.getCanonicalName(JAXXObject.class)); } } @@ -405,7 +370,47 @@ } + protected void finalizeBindings(JAXXCompiler compiler, boolean superclassIsJAXXObject) { + String eol = JAXXCompiler.getLineSeparator(); + for (DataBinding dataBinding : compiler.getDataBindings()) { + if (dataBinding.compile(compiler, true)) { + String expression = "applyDataBinding(" + compiler.getJavaCode(dataBinding.getId()) + ");" + eol; + compiler.appendInitDataBindings(expression); + } + } + + if (superclassIsJAXXObject) { + boolean hasBind = compiler.hasApplyDataBinding(); + if (hasBind) { + compiler.appendApplyDataBinding(" else {"); + compiler.appendApplyDataBinding(eol); + compiler.appendApplyDataBinding(" "); + } + compiler.appendApplyDataBinding("super.applyDataBinding($binding);"); + compiler.appendApplyDataBinding(eol); + + if (hasBind) { + compiler.appendApplyDataBinding(" return;"); + compiler.appendApplyDataBinding(eol); + compiler.appendApplyDataBinding("}"); + } + + hasBind = compiler.hasRemoveDataBinding(); + if (hasBind) { + compiler.appendRemoveDataBinding(" else {"); + compiler.appendRemoveDataBinding(eol); + compiler.appendRemoveDataBinding(" "); + } + compiler.appendRemoveDataBinding("super.removeDataBinding($binding);"); + compiler.appendRemoveDataBinding(eol); + + if (hasBind) { + compiler.appendRemoveDataBinding("}"); + } + } + } + /*---------------------------------------------------------------------------------*/ /*-- Create fields ----------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/ @@ -614,8 +619,9 @@ if (superclassIsJAXXObject) { code.append(" else {").append(eol); code.append(" super.processDataBinding($dest, true);").append(eol); - code.append(" }").append(eol); + code.append(" }"); } + code.append(eol); code.append("} finally {").append(eol); code.append(" $activeBindings.remove($dest);").append(eol); code.append("}").append(eol); Modified: branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/tags/DefaultObjectHandler.java =================================================================== --- branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/tags/DefaultObjectHandler.java 2009-10-27 10:46:23 UTC (rev 1604) +++ branches/jaxx-2.X/jaxx-compiler/src/main/java/jaxx/compiler/tags/DefaultObjectHandler.java 2009-10-28 07:18:13 UTC (rev 1605) @@ -85,6 +85,7 @@ public static final String GENERICTYPE_ATTRIBUTE = "genericType"; public static final String ID_ATTRIBUTE = "id"; public static final String IMPLEMENTS_ATTRIBUTE = "implements"; + public static final String INITIALIZER_ATTRIBUTE = "initializer"; public static final String JAVA_BEAN_ATTRIBUTE = "javaBean"; public static final String LAYOUT_ATTRIBUTE = "layout"; public static final String MNEMONIC_ATTRIBUTE = "mnemonic"; @@ -324,7 +325,8 @@ } ProxyEventInfo eventInfo = eventInfos != null ? eventInfos.get(memberName) : null; - if (eventInfo != null) { // a "proxied" event is one that doesn't fire PropertyChangeEvent, so we need to convert its native event type into PropertyChangeEvents + if (eventInfo != null) { + // a "proxied" event is one that doesn't fire PropertyChangeEvent, so we need to convert its native event type into PropertyChangeEvents StringBuffer result = new StringBuffer(); String methodName = "$pr" + compiler.getUniqueId(propertyChangeListenerCode); boolean methodExists = compiler.hasMethod(methodName); @@ -665,7 +667,8 @@ continue; } if (name.equals(CONSTRAINTS_ATTRIBUTE) || isEventHandlerName(name)) { - compiler.preprocessScript(value); // adds dependencies as a side effect + // adds dependencies as a side effect + compiler.preprocessScript(value); } else if (name.equals(CONSTRUCTOR_PARAMS_ATTRIBUTE)) { for (String param : value.split("\\s*,\\s*")) { compiler.preprocessScript(param); @@ -713,6 +716,14 @@ } continue; } + if (name.equals(INITIALIZER_ATTRIBUTE)) { + if (!value.isEmpty()) { + object.setInitializer(value); + } else { + object.setInitializer("null"); + } + continue; + } if (name.equals(IMPLEMENTS_ATTRIBUTE)) { if (object != compiler.getRootObject()) { // can ony be apply to root object @@ -863,23 +874,25 @@ if (inline) { compiler.addInlineStyle(object, propertyName, true); } - ClassDescriptor propertyType = getPropertyType(object, propertyName, compiler); - if (propertyType != null && - propertyType != ClassDescriptorLoader.getClassDescriptor(Boolean.class) && - propertyType != ClassDescriptorLoader.getClassDescriptor(Byte.class) && - propertyType != ClassDescriptorLoader.getClassDescriptor(Short.class) && - propertyType != ClassDescriptorLoader.getClassDescriptor(Integer.class) && - propertyType != ClassDescriptorLoader.getClassDescriptor(Float.class) && - propertyType != ClassDescriptorLoader.getClassDescriptor(Double.class) && - propertyType != ClassDescriptorLoader.getClassDescriptor(Character.class)) { - //binding = "((" + propertyType.getName() + ") " + binding + ")"; - } + //TC-20091027 : make sure this code is never used ? +// ClassDescriptor propertyType = getPropertyType(object, propertyName, compiler); +// if (propertyType != null && +// propertyType != ClassDescriptorLoader.getClassDescriptor(Boolean.class) && +// propertyType != ClassDescriptorLoader.getClassDescriptor(Byte.class) && +// propertyType != ClassDescriptorLoader.getClassDescriptor(Short.class) && +// propertyType != ClassDescriptorLoader.getClassDescriptor(Integer.class) && +// propertyType != ClassDescriptorLoader.getClassDescriptor(Float.class) && +// propertyType != ClassDescriptorLoader.getClassDescriptor(Double.class) && +// propertyType != ClassDescriptorLoader.getClassDescriptor(Character.class)) { +// //binding = "((" + propertyType.getName() + ") " + binding + ")"; +// } + String setPropertyCode = getSetPropertyCode(object.getJavaCode(), propertyName, binding, compiler); if (propertyName.equals(LAYOUT_ATTRIBUTE)) { // handle containerDelegate (e.g. contentPane on JFrame) // have to set layout early, before children are added - object.appendInitializationCode(getSetPropertyCode(object.getJavaCode(), propertyName, binding, compiler)); + object.appendInitializationCode(setPropertyCode); } // object.registerDataBinding(binding, propertyName, getSetPropertyCode(object.getJavaCode(), propertyName, binding, compiler), compiler); - compiler.registerDataBinding(binding, object.getId() + "." + propertyName, getSetPropertyCode(object.getJavaCode(), propertyName, binding, compiler)); + compiler.registerDataBinding(binding, object.getId() + "." + propertyName, setPropertyCode); } else { // no bindings, convert from string if (inline) { compiler.addInlineStyle(object, propertyName, false);