Author: tchemit Date: 2010-05-18 20:08:14 +0200 (Tue, 18 May 2010) New Revision: 1922 Url: http://nuiton.org/repositories/revision/jaxx/1922 Log: - Evolution #625: Improve data binding with inheritance - Improve JAXXEngine and JAXXTask (simplify a lot...) Modified: trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXCompiler.java trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXEngine.java trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataBinding.java trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataSource.java trunk/jaxx-compiler/src/main/java/jaxx/compiler/decorators/DefaultCompiledObjectDecorator.java trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/CompileFirstPassTask.java trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/CompileSecondPassTask.java trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/FinalizeTask.java trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/GenerateTask.java trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/InitTask.java trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/JAXXEngineTask.java trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/ProfileTask.java trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/StyleSheetTask.java Modified: trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXCompiler.java =================================================================== --- trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXCompiler.java 2010-05-18 18:04:03 UTC (rev 1921) +++ trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXCompiler.java 2010-05-18 18:08:14 UTC (rev 1922) @@ -110,7 +110,7 @@ * inner classes (including enumerations), because currently they don't * always resolve (but will generally run without error anyway). */ - public static boolean STRICT_CHECKS = false; + public static boolean STRICT_CHECKS; public static final String JAXX_NAMESPACE = @@ -1307,34 +1307,30 @@ return; } - // register the jaxx file into the engine - URL jaxxURL = getClassLoader().getResource( - className.replace('.', '/') + ".jaxx"); - URL classURL = getClassLoader().getResource( - className.replace('.', '/') + ".class"); - if (jaxxURL == null || classURL == null) { + // register the jaxx file into the engine - // unknown class - //FIXME-TC20100502 : should throw something or at least warn + URL jaxxURL = ClassDescriptorHelper.getURL(getClassLoader(), className, "jaxx"); + + if (jaxxURL == null) { + + // not a jaxx file, can quit now return; } - try { - File jaxxFile = URLtoFile(jaxxURL); - File classFile = URLtoFile(classURL); - if (classFile.lastModified() > jaxxFile.lastModified()) { - return; // class file is newer, no need to recompile - } - } catch (Exception e) { - // do nothing + if (!engine.isCompileFirstPassTask()) { + throw new IllegalStateException( + "Internal error: adding dependency class " + + className + " during second compilation pass"); } + //FIXME tchemit 20100518 Must unify this with ClassDescriptorHelper to use the less costless resource if (jaxxURL.toString().startsWith("file:")) { File jaxxFile = URLtoFile(jaxxURL); try { jaxxFile = jaxxFile.getCanonicalFile(); } catch (IOException ex) { - // ignore ? + // ignore ? (at least log it...) + log.error(ex); } String jaxxFileName = className.substring(className.lastIndexOf(".") + 1) + @@ -1343,12 +1339,7 @@ assert jaxxFile.getName().equalsIgnoreCase(jaxxFileName) : "expecting file name to match " + className + ", but found " + jaxxFile.getName(); - if (jaxxFile.getName().equals(jaxxFileName)) { // check case match - if (!engine.isFirstCompilePassTask()) { - throw new AssertionError( - "Internal error: adding dependency class " + - className + " during second compilation pass"); - } + if (jaxxFile.getName().equals(jaxxFileName)) { engine.addFileToCompile(jaxxFile, className); } } Modified: trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXEngine.java =================================================================== --- trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXEngine.java 2010-05-18 18:04:03 UTC (rev 1921) +++ trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXEngine.java 2010-05-18 18:08:14 UTC (rev 1922) @@ -60,10 +60,10 @@ /** configuration of the launchor and underlines compilers */ protected final CompilerConfiguration configuration; - /** original list of files to run */ + /** original list of files to compile (says the detected modfied files) */ protected final JAXXCompilerFile[] incomingFiles; - /** Files to be treated while compilation. */ + /** Files to compile */ protected final List<JAXXCompilerFile> compilingFiles; /** Warnings detected while running. */ @@ -103,7 +103,9 @@ addFileToCompile(compilerFile); } - incomingFiles = getCompilingFiles(); + // fix once for all incoming files to compile + incomingFiles = compilingFiles.toArray( + new JAXXCompilerFile[compilingFiles.size()]); } public JAXXEngineTask[] getTasks() { @@ -151,13 +153,34 @@ return incomingFiles; } - public JAXXCompilerFile[] getCompilingFiles() { - return compilingFiles.toArray( - new JAXXCompilerFile[compilingFiles.size()]); +// public JAXXCompilerFile[] getCompilingFiles() { +// return compilingFiles.toArray( +// new JAXXCompilerFile[compilingFiles.size()]); +// } + + public JAXXCompilerFile[] getFilesToCompile() { + List<JAXXCompilerFile> files = new ArrayList<JAXXCompilerFile>(); + for (JAXXCompilerFile file : compilingFiles) { + if (file.getCompiler() == null) { + files.add(file); + } + } + return files.toArray(new JAXXCompilerFile[files.size()]); } + public JAXXCompilerFile[] getCompiledFiles() { + List<JAXXCompilerFile> files = new ArrayList<JAXXCompilerFile>(); + for (JAXXCompilerFile file : compilingFiles) { + if (file.getCompiler() != null) { + files.add(file); + } + } + // always send a copy to be safe. + return files.toArray(new JAXXCompilerFile[files.size()]); + } + public boolean containsJaxxFileClassName(String className) { - for (JAXXCompilerFile file : getCompilingFiles()) { + for (JAXXCompilerFile file : compilingFiles) { if (className.equals(file.getClassName())) { return true; } @@ -165,7 +188,7 @@ return false; } - public boolean isFirstCompilePassTask() { + public boolean isCompileFirstPassTask() { return currentTask != null && CompileFirstPassTask.TASK_NAME.equals(currentTask.getName()); } @@ -362,8 +385,8 @@ */ public void addFileToCompile(File jaxxFile, String jaxxClassName) { - if (isVerbose()) { - log.info("file = " + jaxxFile + ", fqn = " + jaxxClassName); + if (log.isDebugEnabled()) { + log.debug("file = " + jaxxFile + ", fqn = " + jaxxClassName); } JAXXCompilerFile file = new JAXXCompilerFile(jaxxFile, jaxxClassName); Modified: trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataBinding.java =================================================================== --- trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataBinding.java 2010-05-18 18:04:03 UTC (rev 1921) +++ trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataBinding.java 2010-05-18 18:08:14 UTC (rev 1922) @@ -25,6 +25,7 @@ package jaxx.compiler.binding; +import jaxx.compiler.CompiledObject; import jaxx.compiler.CompilerException; import jaxx.compiler.JAXXCompiler; import jaxx.compiler.java.JavaFileGenerator; @@ -37,6 +38,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Set; /** * Represents a data binding in a JAXX file. <code>DataBinding</code> uses @@ -45,56 +47,43 @@ */ public class DataBinding { - /** - * Logger - */ + /** Logger */ protected static final Log log = LogFactory.getLog(DataBinding.class); - /** - * Id of the data binding - */ + + /** Id of the data binding */ private String id; - /** - * Real Id of the data binding (can be suffix by a number for css binding to avoid collisions) - */ + + /** Real Id of the data binding (can be suffix by a number for css binding to avoid collisions) */ private String realId; - /** - * Constant id build from the {@link #realId} and used instead of {@link #realId} in generated code - */ + + /** Constant id build from the {@link #realId} and used instead of {@link #realId} in generated code */ protected String constantId; - /** - * source of the data binding - */ + + /** 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; - /** - * A internal flag to - */ + + /** A internal flag to */ private boolean quickNoDependencies; - /** - * Compiled data source - */ + /** Compiled data source */ protected DataSource dataSource; - /** - * code to add to processDataBinding (null if no binding) - */ + /** code to add to processDataBinding (null if no binding) */ protected String processDataBinding; - /** - * code to register the databinding (null if no binding) - */ + + /** code to register the databinding (null if no binding) */ protected String initDataBinding; - /** - * Extra method to add to the binding - */ + + /** Extra method to add to the binding */ protected final List<JavaMethod> methods = new ArrayList<JavaMethod>(); - /** - * internal state passed to {@code true} when {@link #compile(jaxx.compiler.JAXXCompiler)} method is invoked - */ + + /** internal state passed to {@code true} when {@link #compile(JAXXCompiler)} method is invoked */ private boolean compiled; /** @@ -180,7 +169,7 @@ * * @param compiler compiler which includes the data binding * @return {@code true} if the expression has dependencies, {@code false} otherwise - * @throws jaxx.compiler.CompilerException if a compilation error occurs + * @throws CompilerException if a compilation error occurs */ public boolean compile(JAXXCompiler compiler) throws CompilerException { @@ -212,7 +201,7 @@ // was compiled compiled = true; - if (DataBindingHelper.SHOW_LOG || log.isDebugEnabled()) { + if (dataSource.showLog()) { if (binding) { log.info("detect a databinding : " + this); } else { @@ -260,10 +249,27 @@ if (needTest) { buffer.append("if (").append(objectCode).append(") {").append(eol); } - buffer.append(JavaFileGenerator.indent(getAssignment(), needTest ? 4 : 0, false, eol)); + String assiggment = getAssignment(compiler, dataSource.getOverrideIds()); + buffer.append(JavaFileGenerator.indent(assiggment, needTest ? 4 : 0, false, eol)); if (needTest) { buffer.append(eol).append("}"); } return buffer.toString(); } + + protected String getAssignment(JAXXCompiler compiler, Set<String> overrides) { + String s = getAssignment(); + + if (overrides != null && !overrides.isEmpty()) { + String tmp = s; + for (String override : overrides) { + CompiledObject o = compiler.getCompiledObject(override); + tmp = tmp.replaceFirst(override + ".", o.getJavaCode() + "."); + } + log.info("Assignment with overrides (" + s + ") = " + tmp); + s = tmp; + } + + return s; + } } \ No newline at end of file Modified: trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataSource.java =================================================================== --- trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataSource.java 2010-05-18 18:04:03 UTC (rev 1921) +++ trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataSource.java 2010-05-18 18:08:14 UTC (rev 1922) @@ -52,7 +52,14 @@ import java.beans.Introspector; import java.io.StringReader; import java.lang.reflect.Modifier; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * Represents a Java expression which fires a <code>PropertyChangeEvent</code> when it can be @@ -62,40 +69,29 @@ */ public class DataSource { - /** - * Logger - */ + /** Logger */ protected static final Log log = LogFactory.getLog(DataSource.class); - /** - * type attached to "null" constants in parsed expressions - */ + /** type attached to "null" constants in parsed expressions */ private class NULL { } - /** - * id of data source - */ + /** id of data source */ private final String id; - /** - * Constant id - */ + + /** Constant id */ protected final String constantId; - /** - * The Java source code for the expression. - */ + + /** The Java source code for the expression. */ private final String source; - /** - * The current <code>JAXXCompiler</code>. - */ + + /** The current <code>JAXXCompiler</code>. */ private final JAXXCompiler compiler; - /** - * List of detected tracker (if none found, it is not a data binding) - */ + + /** List of detected tracker (if none found, it is not a data binding) */ private final List<DataListener> trackers; - /** - * the delegate of property to be required - */ + + /** the delegate of property to be required */ private String objectCode; protected final List<JavaMethod> methods; @@ -116,7 +112,7 @@ this.source = source; this.compiler = compiler; this.methods = methods; - this.trackers = new ArrayList<DataListener>(); + trackers = new ArrayList<DataListener>(); } public String getObjectCode() { @@ -142,6 +138,11 @@ return b.toString(); } + public boolean showLog() { +// return DataBindingHelper.SHOW_LOG || log.isDebugEnabled(); + return DataBindingHelper.SHOW_LOG; + } + /** * 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 @@ -150,13 +151,12 @@ * expression will be compiled and evaluated at runtime to yield the <code>DataSource's</code> listener. * * @return <code>true</code> if the expression has dependencies, <code>false</code> otherwise - * @throws jaxx.compiler.CompilerException - * if a compilation error occurs + * @throws CompilerException if a compilation error occurs * @throws IllegalStateException if data source was already compiled */ protected boolean compile() throws CompilerException, IllegalStateException { - if (DataBindingHelper.SHOW_LOG || log.isDebugEnabled()) { + if (showLog()) { log.info("======= Start compile of " + source); } JavaParser p = new JavaParser(new StringReader(source)); @@ -185,7 +185,7 @@ // scan accepted expressions to detect dependencies and track listeners for (SimpleNode node : expressions.keySet()) { - if (DataBindingHelper.SHOW_LOG || log.isDebugEnabled()) { + if (showLog()) { log.info("Will parse expression " + node.getText()); } scanNode(node); @@ -204,7 +204,7 @@ // no requirements - this.objectCode = ""; + objectCode = ""; } else { // build the fully test from requirements @@ -212,11 +212,16 @@ StringBuilder buffer = new StringBuilder(); Iterator<String> itr = result.iterator(); - buffer.append(itr.next()).append(" != null"); + + overrideIds = new HashSet<String>(); + + String realSource = getJavaCode(itr.next()); + buffer.append(realSource).append(" != null"); while (itr.hasNext()) { - buffer.append(" && ").append(itr.next()).append(" != null"); + realSource = getJavaCode(itr.next()); + buffer.append(" && ").append(realSource).append(" != null"); } - this.objectCode = buffer.toString().trim(); + objectCode = buffer.toString().trim(); } } castsExpressions.clear(); @@ -224,16 +229,34 @@ return isBinding; } + private Set<String> overrideIds; + + private String getJavaCode(String s) { + CompiledObject o = compiler.getCompiledObject(s); + if (o != null && o.isOverride()) { + + if (showLog()) { + log.info("Use an override identifier : " + o.getJavaCode()); + } + + overrideIds.add(s); + } + return s; + } + + public Set<String> getOverrideIds() { + return overrideIds; + } + /** * Examines a node to identify any dependencies it contains. * * @param node node to scan - * @throws jaxx.compiler.CompilerException - * ? + * @throws CompilerException ? */ private void scanNode(SimpleNode node) throws CompilerException { if (node.getId() == JavaParserTreeConstants.JJTMETHODDECLARATION || - node.getId() == JavaParserTreeConstants.JJTFIELDDECLARATION) { + node.getId() == JavaParserTreeConstants.JJTFIELDDECLARATION) { return; } if (log.isTraceEnabled()) { @@ -254,7 +277,7 @@ break; case JavaParserTreeConstants.JJTPRIMARYEXPRESSION: type = determineExpressionType(node); - if (log.isDebugEnabled()) { + if (showLog()) { log.debug("result of determineExpressionType for " + node.getText() + " = " + type); } break; @@ -276,11 +299,12 @@ * @return the class descriptor of the return type or null */ private ClassDescriptor determineExpressionType(SimpleNode expression) { - if (log.isTraceEnabled()) { - log.trace("for expression " + expression.getText()); - } assert expression.getId() == JavaParserTreeConstants.JJTPRIMARYEXPRESSION; SimpleNode prefix = expression.getChild(0); + if (log.isDebugEnabled()) { + log.debug("for expression " + expression.getText() + " - prefix " + prefix + " - nb childrens of prefix: " + prefix.jjtGetNumChildren() + ", nb childrens of expression : " + expression.jjtGetNumChildren()); + } + if (prefix.jjtGetNumChildren() == 1) { int type = prefix.getChild(0).getId(); if (type == JavaParserTreeConstants.JJTLITERAL || type == JavaParserTreeConstants.JJTEXPRESSION) { @@ -340,6 +364,12 @@ } return method.getReturnType(); } catch (NoSuchMethodException e) { + if (showLog()) { + log.info("Could not find method " + methodName + ", code : " + code + " on : " + contextClass); + for (MethodDescriptor descriptor : contextClass.getMethodDescriptors()) { + log.info(" - " + Modifier.toString(descriptor.getModifiers()) + " " + descriptor.getName() + "(...) : " + descriptor.getReturnType()); + } + } // happens for methods defined in the current JAXX file via scripts String propertyName = null; if (methodName.startsWith("is")) { @@ -360,15 +390,16 @@ // check this is a javaBean CompiledObject compiledObject = compiler.getObjects().get(propertyName); if (compiledObject != null && compiledObject.isJavaBean()) { - if (DataBindingHelper.SHOW_LOG || log.isDebugEnabled()) { - log.info("Detect a dependency from a script method '" + newMethod.getName() + "' which reflect a javaBean property " + propertyName); - log.info("Try to add a listener [symbol:" + bindingId + ",objectCode:" + "null" + "]"); + String objectCode = null; + if (showLog()) { + log.info("Detect a dependency from compiled object [" + objectCode + "]a script method '" + newMethod.getName() + "' which reflect a javaBean property " + propertyName); + log.info("Try to add a listener [symbol:" + bindingId + ",objectCode:" + objectCode + "]"); log.debug(">> lastnode = " + lastNode + "(), suffix = " + suffix.getText() + ", expression = " + expression.getText()); } addListener(bindingId, - null, - "addPropertyChangeListener(\"" + propertyName + "\", this);" + JAXXCompiler.getLineSeparator(), - "removePropertyChangeListener(\"" + propertyName + "\", this);" + JAXXCompiler.getLineSeparator()); + objectCode, + "addPropertyChangeListener(\"" + propertyName + "\", this);" + JAXXCompiler.getLineSeparator(), + "removePropertyChangeListener(\"" + propertyName + "\", this);" + JAXXCompiler.getLineSeparator()); } contextClass = newMethod.getReturnType(); } @@ -486,16 +517,16 @@ FieldDescriptor newField = compiler.getScriptField(memberName); if (newField != null) { contextClass = newField.getType(); - if (DataBindingHelper.SHOW_LOG || log.isDebugEnabled()) { + if (showLog()) { log.info("Detect a dependency from a script field '" + newField + "'"); log.info("Try to add a listenenr [symbol:" + tokensSeenSoFar.toString() + ",objectCode:" + null + "]"); } String eol = JAXXCompiler.getLineSeparator(); addListener(tokensSeenSoFar.toString(), - null, - "addPropertyChangeListener(\"" + memberName + "\", this);" + eol, + null, + "addPropertyChangeListener(\"" + memberName + "\", this);" + eol, // "addPropertyChangeListener(\"" + memberName + "\", " + listenerId + ");" + eol, - "removePropertyChangeListener(\"" + memberName + "\", this);" + eol); +"removePropertyChangeListener(\"" + memberName + "\", this);" + eol); // "removePropertyChangeListener(\"" + memberName + "\", " + listenerId + ");" + eol); assert contextClass != null : "script field '" + memberName + "' is defined, but has type null"; @@ -540,14 +571,14 @@ try { if (handler.isMemberBound(memberName)) { String bindingId = objectCode + "." + memberName + (method ? "()" : ""); - if (DataBindingHelper.SHOW_LOG || log.isDebugEnabled()) { + if (showLog()) { log.info("Detect a dependency from a event handler for memberName '" + memberName + "' for class " + objectClass); log.info("Try to add a listenenr [symbol:" + bindingId + ", objectCode:" + objectCode + "]"); } addListener(bindingId, - objectCode, - getAddMemberListenerCode(handler, objectCode, memberName, "this", compiler), - getRemoveMemberListenerCode(handler, objectCode, memberName, "this", compiler)); + objectCode, + getAddMemberListenerCode(handler, objectCode, memberName, "this", compiler), + getRemoveMemberListenerCode(handler, objectCode, memberName, "this", compiler)); } } catch (UnsupportedAttributeException e) { // ignore -- this is thrown for methods like toString(), for which there is no tracking and @@ -620,8 +651,8 @@ ClassDescriptor eventClass = DefaultObjectHandler.getEventClass(eventInfo.getListenerClass()); if (!methodExists) { methods.add(new JavaMethod(Modifier.PUBLIC, "void", methodName, - new JavaArgument[]{new JavaArgument(JAXXCompiler.getCanonicalName(eventClass), "event")}, null, - "propertyChange(null);", false)); + new JavaArgument[]{new JavaArgument(JAXXCompiler.getCanonicalName(eventClass), "event")}, null, + "propertyChange(null);", false)); } String code = objectCode + (eventInfo.getModelName() != null ? ".get" + StringUtils.capitalize(eventInfo.getModelName()) + "()" : ""); result.append("$bindingSources.put(\"").append(code).append("\", ").append(code).append(");").append(JAXXCompiler.getLineSeparator()); @@ -630,16 +661,16 @@ result.append(JAXXCompiler.getLineSeparator()); if (eventInfo.getModelName() != null) { result.append(getAddMemberListenerCode(handler, objectCode, "get" + StringUtils.capitalize(eventInfo.getModelName()), - JAXXUtil.class.getSimpleName() + ".getDataBindingUpdateListener(" + (compiler.getOutputClassName() + ".this") + ", " + constantId + ")", - compiler)); + JAXXUtil.class.getSimpleName() + ".getDataBindingUpdateListener(" + compiler.getOutputClassName() + ".this" + ", " + constantId + ")", + compiler)); } return result.toString(); } String propertyName = null; if (memberName.startsWith("get")) { - propertyName = Introspector.decapitalize(memberName.substring("get".length())); + propertyName = Introspector.decapitalize(memberName.substring(3)); } else if (memberName.startsWith("is")) { - propertyName = Introspector.decapitalize(memberName.substring("is".length())); + propertyName = Introspector.decapitalize(memberName.substring(2)); } else { try { handler.getBeanClass().getFieldDescriptor(memberName); @@ -690,8 +721,8 @@ if (!methodExists) { ClassDescriptor eventClass = DefaultObjectHandler.getEventClass(eventInfo.getListenerClass()); methods.add(new JavaMethod(Modifier.PUBLIC, "void", methodName, - new JavaArgument[]{new JavaArgument(JAXXCompiler.getCanonicalName(eventClass), "event")}, null, - "propertyChange(null);", false)); + new JavaArgument[]{new JavaArgument(JAXXCompiler.getCanonicalName(eventClass), "event")}, null, + "propertyChange(null);", false)); } try { String modelMemberName = eventInfo.getModelName() != null ? "get" + StringUtils.capitalize(eventInfo.getModelName()) : null; @@ -706,8 +737,8 @@ result.append("}").append(eol); if (eventInfo.getModelName() != null) { result.append(getRemoveMemberListenerCode(handler, objectCode, "get" + StringUtils.capitalize(eventInfo.getModelName()), - JAXXUtil.class.getSimpleName() + ".getDataBindingUpdateListener(" + compiler.getOutputClassName() + ".this, " + constantId + ")", - compiler)); + JAXXUtil.class.getSimpleName() + ".getDataBindingUpdateListener(" + compiler.getOutputClassName() + ".this, " + constantId + ")", + compiler)); } return result.toString(); } catch (NoSuchMethodException e) { Modified: trunk/jaxx-compiler/src/main/java/jaxx/compiler/decorators/DefaultCompiledObjectDecorator.java =================================================================== --- trunk/jaxx-compiler/src/main/java/jaxx/compiler/decorators/DefaultCompiledObjectDecorator.java 2010-05-18 18:04:03 UTC (rev 1921) +++ trunk/jaxx-compiler/src/main/java/jaxx/compiler/decorators/DefaultCompiledObjectDecorator.java 2010-05-18 18:08:14 UTC (rev 1922) @@ -29,44 +29,115 @@ import jaxx.compiler.CompiledObjectDecorator; import jaxx.compiler.CompilerException; import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.java.JavaField; import jaxx.compiler.java.JavaFile; import jaxx.compiler.java.JavaFileGenerator; +import jaxx.compiler.java.JavaMethod; import jaxx.compiler.script.ScriptInitializer; import jaxx.compiler.types.TypeManager; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import java.lang.reflect.Modifier; import java.util.Map.Entry; /** * The default decorator to use on all compiled objects. - * + * * @author tchemit <chemit@codelutin.com> + * @plexus.component role-hint="default" role="jaxx.compiler.CompiledObjectDecorator" * @since 1.2 - * @plexus.component role-hint="default" role="jaxx.compiler.CompiledObjectDecorator" */ public class DefaultCompiledObjectDecorator implements CompiledObjectDecorator { + + /** Logger */ + protected static final Log log = + LogFactory.getLog(DefaultCompiledObjectDecorator.class); + @Override public String getName() { return "default"; } @Override - public void finalizeCompiler(JAXXCompiler compiler, CompiledObject root, CompiledObject object, JavaFile javaFile, String packageName, String className, String fullClassName) { + public void finalizeCompiler(JAXXCompiler compiler, + CompiledObject root, + CompiledObject object, + JavaFile javaFile, + String packageName, + String className, + String fullClassName) { - if (!object.isOverride() && !(object instanceof ScriptInitializer)) { - String id = object.getId(); + if (object instanceof ScriptInitializer) { + + // nothing to finalize + return; + } + + String fqn = JAXXCompiler.getCanonicalName(object); + + String id = object.getId(); + + if (log.isDebugEnabled()) { + log.debug("finalize " + id); + } + + if (object.isOverride()) { + + // add a specialized getter, only if type has changed + + if (object.getObjectClass().equals(object.getOverrideType())) { + + // type is the same do nothing + + return; + } + + // add a specialized getter + + String methodName = "get" + StringUtils.capitalize(id); + + String body = "return (" + fqn + ") " + id + ";"; + + if (log.isDebugEnabled()) { + log.debug("Add specialized getter " + methodName + " : " + body); + } + JavaMethod getter = JavaFileGenerator.newMethod(Modifier.PUBLIC, fqn, methodName, body, true); + javaFile.addMethod(getter); + } else { + int access = id.startsWith("$") ? Modifier.PRIVATE : Modifier.PROTECTED; - if (object == root) { - javaFile.addSimpleField(JavaFileGenerator.newField(access, className, id, false, "this")); + if (root.equals(object)) { + JavaField field = JavaFileGenerator.newField(access, className, id, false, "this"); + javaFile.addSimpleField(field); } else { - javaFile.addField(JavaFileGenerator.newField(access, JAXXCompiler.getCanonicalName(object), id, object.isOverride()), object.isJavaBean()); + + JavaField field = JavaFileGenerator.newField(access, fqn, id, object.isOverride()); + javaFile.addField(field, object.isJavaBean()); } } - if (!compiler.inlineCreation(object) && object != root) { + if (!compiler.inlineCreation(object) && !root.equals(object)) { javaFile.addMethod(JavaFileGenerator.newMethod(Modifier.PROTECTED, "void", object.getCreationMethodName(), getCreationCode(compiler, object), object.isOverride())); } + +// if (!object.isOverride() && !(object instanceof ScriptInitializer)) { +// String id = object.getId(); +// int access = id.startsWith("$") ? Modifier.PRIVATE : Modifier.PROTECTED; +// if (object == root) { +// JavaField field = JavaFileGenerator.newField(access, className, id, false, "this"); +// javaFile.addSimpleField(field); +// } else { +// JavaField field = JavaFileGenerator.newField(access, JAXXCompiler.getCanonicalName(object), id, object.isOverride()); +// javaFile.addField(field, object.isJavaBean()); +// } +// } +// +// if (!compiler.inlineCreation(object) && object != root) { +// javaFile.addMethod(JavaFileGenerator.newMethod(Modifier.PROTECTED, "void", object.getCreationMethodName(), getCreationCode(compiler, object), object.isOverride())); +// } } @Override @@ -145,7 +216,18 @@ @Override public boolean createInitializer(JAXXCompiler compiler, CompiledObject root, CompiledObject object, StringBuffer code, boolean lastWasMethodCall) { String eol = JAXXCompiler.getLineSeparator(); - if (object == root) { + + if (object instanceof ScriptInitializer) { + + // initializer has special direct treatment : can not be in a method + // just push code to compiler + code.append(getCreationCode(compiler, object)); + + // nothing to initialize of a script + return lastWasMethodCall; + } + + if (root.equals(object)) { String rootCode = root.getInitializationCode(compiler); if (rootCode != null && rootCode.length() > 0) { code.append("// inline creation of ").append(object.getId()).append(eol); Modified: trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/CompileFirstPassTask.java =================================================================== --- trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/CompileFirstPassTask.java 2010-05-18 18:04:03 UTC (rev 1921) +++ trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/CompileFirstPassTask.java 2010-05-18 18:08:14 UTC (rev 1922) @@ -44,30 +44,25 @@ /** Logger */ private static final Log log = LogFactory.getLog(CompileFirstPassTask.class); - private static final long serialVersionUID = -1L; - + /** Task name */ public static final String TASK_NAME = "CompileFirstPass"; public CompileFirstPassTask() { super(TASK_NAME); } - protected boolean compiled; - @Override public boolean perform(JAXXEngine engine) throws Exception { boolean success = true; - compiled = true; - while (compiled) { - // at each round, says nothing has to be compiled - // the method treateFile will if required change the state - compiled = false; + JAXXCompilerFile[] undone = engine.getFilesToCompile(); - JAXXCompilerFile[] files = engine.getCompilingFiles(); + while (undone.length > 0) { - for (JAXXCompilerFile jaxxFile : files) { + // start a new round of compilation + for (JAXXCompilerFile jaxxFile : undone) { + boolean successForFile = treateFile(engine, jaxxFile); if (!successForFile) { @@ -76,6 +71,9 @@ success = false; } } + + // prepare next round + undone = engine.getFilesToCompile(); } return success; } @@ -86,32 +84,21 @@ boolean isVerbose = engine.isVerbose(); if (isVerbose) { - log.info(getName() + " for " + jaxxFile.getClassName()); + log.info("start " + jaxxFile.getClassName()); } - JAXXCompiler compiler = jaxxFile.getCompiler(); - - if (compiler != null) { - - // file already registred - return true; - } - boolean success = true; - // mark to have another round to treate new files - compiled = true; - CompilerConfiguration configuration = engine.getConfiguration(); - compiler = engine.newCompiler(jaxxFile); + JAXXCompiler compiler = engine.newCompiler(jaxxFile); addStartProfileTime(engine, compiler); compiler.compileFirstPass(); if (configuration.isAutoImportCss() && !compiler.isIdentCssFound()) { - // check if can add ident css file + // check if we can add ident css file File cssFile = jaxxFile.getCssFile(); Modified: trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/CompileSecondPassTask.java =================================================================== --- trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/CompileSecondPassTask.java 2010-05-18 18:04:03 UTC (rev 1921) +++ trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/CompileSecondPassTask.java 2010-05-18 18:08:14 UTC (rev 1922) @@ -24,15 +24,12 @@ */ package jaxx.compiler.tasks; -import jaxx.compiler.CompilerException; import jaxx.compiler.JAXXCompiler; import jaxx.compiler.JAXXCompilerFile; import jaxx.compiler.JAXXEngine; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import java.util.Arrays; - /** * Task to execute the Second round of compile. * @@ -45,8 +42,7 @@ private static final Log log = LogFactory.getLog(CompileSecondPassTask.class); - private static final long serialVersionUID = -1L; - + /** Task name */ public static final String TASK_NAME = "CompileSecondPass"; public CompileSecondPassTask() { @@ -58,16 +54,20 @@ boolean success = true; boolean isVerbose = engine.isVerbose(); - JAXXCompilerFile[] files = engine.getCompilingFiles(); + // check all files are attached to a compiler + checkAllFilesCompiled(engine); + JAXXCompilerFile[] files = engine.getCompiledFiles(); + for (JAXXCompilerFile jaxxFile : files) { String className = jaxxFile.getClassName(); if (isVerbose) { - log.info(getName() + " for " + className); + log.info("start " + className); } - JAXXCompiler compiler = getSafeCompiler(jaxxFile); + JAXXCompiler compiler = jaxxFile.getCompiler(); + addStartProfileTime(engine, compiler); if (log.isDebugEnabled()) { log.debug("runInitializers for " + className); @@ -89,15 +89,7 @@ } } - // check that compilation set was not altered during pass 2 - JAXXCompilerFile[] jaxxFilesClone = engine.getCompilingFiles(); - if (jaxxFilesClone.length > files.length) { - throw new CompilerException( - "Internal error: compilation set altered during pass" + - " 2 (was " + Arrays.toString(jaxxFilesClone) + - ", modified to " + Arrays.toString(files) + ")" - ); - } return success; } + } \ No newline at end of file Modified: trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/FinalizeTask.java =================================================================== --- trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/FinalizeTask.java 2010-05-18 18:04:03 UTC (rev 1921) +++ trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/FinalizeTask.java 2010-05-18 18:08:14 UTC (rev 1922) @@ -43,8 +43,7 @@ /** Logger */ private static final Log log = LogFactory.getLog(FinalizeTask.class); - private static final long serialVersionUID = -1L; - + /** Task name */ public static final String TASK_NAME = "Finalize"; public FinalizeTask() { @@ -56,12 +55,17 @@ boolean success = true; boolean isVerbose = engine.getConfiguration().isVerbose(); - for (JAXXCompilerFile jaxxFile : engine.getCompilingFiles()) { + // check all files are attached to a compiler + checkAllFilesCompiled(engine); + JAXXCompilerFile[] files = engine.getCompiledFiles(); + + for (JAXXCompilerFile jaxxFile : files) { + if (isVerbose) { - log.info(getName() + " for " + jaxxFile.getClassName()); + log.info("start " + jaxxFile.getClassName()); } - JAXXCompiler compiler = getSafeCompiler(jaxxFile); + JAXXCompiler compiler = jaxxFile.getCompiler(); addStartProfileTime(engine, compiler); compiler.finalizeCompiler(); addEndProfileTime(engine, compiler); Modified: trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/GenerateTask.java =================================================================== --- trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/GenerateTask.java 2010-05-18 18:04:03 UTC (rev 1921) +++ trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/GenerateTask.java 2010-05-18 18:08:14 UTC (rev 1922) @@ -42,8 +42,7 @@ /** Logger */ private static final Log log = LogFactory.getLog(GenerateTask.class); - private static final long serialVersionUID = -1L; - + /** Task name */ public static final String TASK_NAME = "Generate"; public GenerateTask() { @@ -52,6 +51,10 @@ @Override public boolean perform(JAXXEngine engine) throws Exception { + + // check all files are attached to a compiler + checkAllFilesCompiled(engine); + boolean success = true; boolean verbose = engine.isVerbose(); @@ -59,13 +62,15 @@ JavaFileGenerator generator = new JavaFileGenerator(JAXXCompiler.getLineSeparator(), verbose); - for (JAXXCompilerFile jaxxFile : engine.getCompilingFiles()) { + JAXXCompilerFile[] files = engine.getCompiledFiles(); + + for (JAXXCompilerFile jaxxFile : files) { if (verbose) { - log.info(getName() + " for " + jaxxFile.getClassName()); + log.info("start " + jaxxFile.getClassName()); } - JAXXCompiler compiler = getSafeCompiler(jaxxFile); + JAXXCompiler compiler = jaxxFile.getCompiler(); addStartProfileTime(engine, compiler); compiler.generate(generator); addEndProfileTime(engine, compiler); Modified: trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/InitTask.java =================================================================== --- trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/InitTask.java 2010-05-18 18:04:03 UTC (rev 1921) +++ trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/InitTask.java 2010-05-18 18:08:14 UTC (rev 1922) @@ -38,13 +38,12 @@ */ public class InitTask extends JAXXEngineTask { - private static final long serialVersionUID = -1L; - - public static final String TASK_NAME = "Init"; - /** Logger */ private static final Log log = LogFactory.getLog(InitTask.class); + /** Task name */ + public static final String TASK_NAME = "Init"; + public InitTask() { super(TASK_NAME); } @@ -76,7 +75,7 @@ } if (configuration.isVerbose()) { - log.info("will init " + JAXXFactory.class.getName()); + log.info("Will init " + JAXXFactory.class.getName()); } JAXXFactory.initFactory(); Modified: trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/JAXXEngineTask.java =================================================================== --- trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/JAXXEngineTask.java 2010-05-18 18:04:03 UTC (rev 1921) +++ trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/JAXXEngineTask.java 2010-05-18 18:08:14 UTC (rev 1922) @@ -24,13 +24,10 @@ */ package jaxx.compiler.tasks; -import jaxx.compiler.CompilerException; import jaxx.compiler.JAXXCompiler; import jaxx.compiler.JAXXCompilerFile; import jaxx.compiler.JAXXEngine; -import java.io.Serializable; - /** * Base class to implement a task to be launched by a {@link JAXXEngine}. * <p/> @@ -39,49 +36,51 @@ * @author tchemit <chemit@codelutin.com> * @since 2.0.2 */ -public abstract class JAXXEngineTask implements Serializable { +public abstract class JAXXEngineTask { + /** Task name */ private final String name; public JAXXEngineTask(String name) { this.name = name; } + /** + * Performs the task on the given {@code engine}. + * + * @param engine the engine to use + * @return {@code false} if task failed (with no exception), {@code true} otherwise. + * @throws Exception if any error + */ public abstract boolean perform(JAXXEngine engine) throws Exception; - public String getName() { return name; } + /** + * Checks the engine does not have any more files to discover. + * + * @param engine the engine to test + * @throws IllegalStateException if there is still some files to discover. + */ + protected void checkAllFilesCompiled(JAXXEngine engine) throws IllegalStateException { + JAXXCompilerFile[] undone = engine.getFilesToCompile(); + + if (undone.length > 0) { + + throw new IllegalStateException("Can not start '" + getName() + "', there is still files to process in '" + CompileFirstPassTask.TASK_NAME); + } + } + protected void addStartProfileTime(JAXXEngine engine, JAXXCompiler compiler) { engine.addProfileTime(compiler, name + "_start"); } + protected void addEndProfileTime(JAXXEngine engine, JAXXCompiler compiler) { engine.addProfileTime(compiler, name + "_end"); } - - protected JAXXCompiler getSafeCompiler(JAXXCompilerFile engine) { - JAXXCompiler compiler = engine.getCompiler(); - if (compiler == null) { - throw new CompilerException( - "Internal error: could not find compiler for " + - engine.getClassName() + " during task [" + getName() + "]" - ); - } - - return compiler; - } -// -// protected JAXXCompiler getSafeCompiler(JAXXEngine engine, -// String className) { -// JAXXCompiler compiler = engine.getCompiler( -// className, -// "Internal error: could not find compiler for " + className + -// " during task [" + getName() + "]"); -// return compiler; -// } } Modified: trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/ProfileTask.java =================================================================== --- trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/ProfileTask.java 2010-05-18 18:04:03 UTC (rev 1921) +++ trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/ProfileTask.java 2010-05-18 18:08:14 UTC (rev 1922) @@ -39,8 +39,7 @@ /** Logger */ private static final Log log = LogFactory.getLog(ProfileTask.class); - private static final long serialVersionUID = -1L; - + /** Task name */ public static final String TASK_NAME = "Profile"; public ProfileTask() { Modified: trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/StyleSheetTask.java =================================================================== --- trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/StyleSheetTask.java 2010-05-18 18:04:03 UTC (rev 1921) +++ trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/StyleSheetTask.java 2010-05-18 18:08:14 UTC (rev 1922) @@ -41,8 +41,7 @@ /** Logger */ private static final Log log = LogFactory.getLog(StyleSheetTask.class); - private static final long serialVersionUID = -1L; - + /** Task name */ public static final String TASK_NAME = "StyleSheet"; public StyleSheetTask() { @@ -51,18 +50,26 @@ @Override public boolean perform(JAXXEngine engine) throws Exception { + + // check all files are attached to a compiler + checkAllFilesCompiled(engine); + boolean success = true; boolean isVerbose = engine.getConfiguration().isVerbose(); - JAXXCompilerFile[] files = engine.getCompilingFiles(); + + JAXXCompilerFile[] files = engine.getCompiledFiles(); + for (JAXXCompilerFile jaxxFile : files) { String className = jaxxFile.getClassName(); if (isVerbose) { - log.info(getName() + " for " + className); + log.info("start " + className); } - JAXXCompiler compiler = getSafeCompiler(jaxxFile); + + JAXXCompiler compiler = jaxxFile.getCompiler(); addStartProfileTime(engine, compiler); compiler.applyStylesheets(); addEndProfileTime(engine, compiler); + if (compiler.isFailed()) { success = false; }
participants (1)
-
tchemit@users.nuiton.org