This is an automated email from the git hooks/post-receive script. New commit to annotated tag v2.0.0-beta-1 in repository jaxx. See https://gitlab.nuiton.org/nuiton/jaxx.git commit ebd88138a62a203b1b5796432e87eba5a461b054 Author: Tony Chemit <chemit@codelutin.com> Date: Wed Oct 28 07:54:21 2009 +0000 remove binding from jaxx.compiler package --- .../src/main/java/jaxx/compiler/DataBinding.java | 119 ----- .../src/main/java/jaxx/compiler/DataSource.java | 485 --------------------- 2 files changed, 604 deletions(-) diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/DataBinding.java b/jaxx-compiler/src/main/java/jaxx/compiler/DataBinding.java deleted file mode 100644 index e55ca04..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/DataBinding.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * *##% - * 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; - -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 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 - */ - public DataBinding(String source, String dest, String assignment) { - this.id = dest; - 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</code> if the expression has dependencies, <code>false</code> 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) + ")"); - - 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 - } - if (compiler.hasProcessDataBinding()) { - compiler.appendProcessDataBinding(" else "); - } else { - compiler.appendProcessDataBinding(" "); - } - compiler.appendProcessDataBinding("if (" + compiler.getJavaCode(id) + ".equals($dest)) {" + eol); - String objectCode = dataSource.getObjectCode(); - //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) { - compiler.appendProcessDataBinding(" if (" + objectCode + " != null) {" + eol); - compiler.appendProcessDataBinding(" "); - } - compiler.appendProcessDataBinding(" " + assignment.trim()); - if (needTest) { - compiler.appendProcessDataBinding(eol + " }"); - } - compiler.appendProcessDataBinding(eol + " }"); - return true; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/DataSource.java b/jaxx-compiler/src/main/java/jaxx/compiler/DataSource.java deleted file mode 100644 index 9003f2d..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/DataSource.java +++ /dev/null @@ -1,485 +0,0 @@ -/* - * *##% - * 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; - -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; - -/** - * 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 { - - /** - * 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; - - /** - * 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; - } - - 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 - * @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 autoId = compiler.getAutoId(ClassDescriptorLoader.getClassDescriptor(getClass())); - JavaParser p = new JavaParser(new StringReader(source + ";")); - while (!p.Line()) { - SimpleNode node = p.popNode(); - scanNode(node, autoId); - } - - 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.getSimpleName(), autoId, false, 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 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 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) { - 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 ClassDescriptor 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(); - } - - 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); - 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); - 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, ClassDescriptor objectClass, String memberName, boolean method, String listenerId) { - 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 - } - } - - /** - * 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) { - 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 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 && !compiler.getRootObject().getId().equals(objectCode); -// boolean needTest = objectCode != null; - 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(" }"); - } - } - } - - 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("}"); - } - } -} -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.