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 6f521a81dce0d63a33c34c01b87c1cdc3912e4c5 Author: Tony Chemit <chemit@codelutin.com> Date: Wed Oct 7 14:23:35 2009 +0000 refactor jaxx 2.x --- .../java/jaxx/compiler/CompilerConfiguration.java | 155 ++++++ .../decorators/BoxedCompiledObjectDecorator.java | 30 + .../decorators/CompiledObjectDecorator.java | 26 + .../decorators/CompiledObjectDecoratorManager.java | 59 ++ .../decorators/DefaultCompiledObjectDecorator.java | 131 +++++ .../HelpRootCompiledObjectDecorator.java | 100 ++++ .../jaxx/compiler/generators/GeneratorManager.java | 42 ++ .../compiler/generators/JAXXObjectGenerator.java | 604 +++++++++++++++++++++ .../jaxx/compiler/generators/SwingGenerator.java | 27 + .../compiler/generators/ValidatorGenerator.java | 88 +++ 10 files changed, 1262 insertions(+) diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/CompilerConfiguration.java b/jaxx-compiler/src/main/java/jaxx/compiler/CompilerConfiguration.java new file mode 100644 index 0000000..5181c5b --- /dev/null +++ b/jaxx-compiler/src/main/java/jaxx/compiler/CompilerConfiguration.java @@ -0,0 +1,155 @@ +package jaxx.compiler; + +import java.io.File; +import jaxx.compiler.decorators.CompiledObjectDecorator; +import jaxx.runtime.context.JAXXContext; + +/** + * TODO javadoc. + * + * @author chemit + * @since 2.0.0 + */ +public interface CompilerConfiguration { + + /** + * + * @return + */ + ClassLoader getClassLoader(); + + /** + * + * @return + */ + Class<? extends JAXXCompiler> getCompilerClass(); + + /** + * + * @return + */ + Class<? extends CompiledObjectDecorator> getDefaultDecoratorClass(); + + /** + * + * @return + */ + Class<?> getDefaultErrorUI(); + + /** + * + * @return + */ + String[] getExtraImports(); + + /** + * + * @return + */ + String getHelpBrokerFQN(); + + /** + * + * @return + */ + String getHelpSetName(); + + /** + * + * @return + */ + String getHelpsetI18nPrefix(); + + /** + * + * @return + */ + String getHelpsetIndexI18nSuffix(); + + /** + * + * @return + */ + String getHelpsetTitleI18nSuffix(); + + /** + * + * @return + */ + String getHelpsetTocI18nSuffix(); + + /** + * + * @return + */ + Class<? extends JAXXContext> getJaxxContextClass(); + + /** + * Returns whether or not optimization should be performed. + * + * @return whether or not optimizations should be performed + */ + boolean getOptimize(); + + /** + * Returns the target directory, generally specified with the "-d" option on the command line. + * + * @return the target directory + * @see #setTargetDirectory + */ + File getTargetDirectory(); + + /** + * + * @return + */ + Class<?> getValidatorClass(); + + /** + * + * @return + */ + boolean isAddLogger(); + + /** + * + * @return + */ + boolean isGenerateHelp(); + + /** + * + * @return + */ + boolean isI18nable(); + + /** + * + * @return + */ + boolean isOptimize(); + + /** + * + * @return + */ + boolean isProfile(); + + /** + * + * @return + */ + boolean isResetAfterCompile(); + + /** + * + * @return + */ + boolean isUseUIManagerForIcon(); + + /** + * + * @return + */ + boolean isVerbose(); +} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/decorators/BoxedCompiledObjectDecorator.java b/jaxx-compiler/src/main/java/jaxx/compiler/decorators/BoxedCompiledObjectDecorator.java new file mode 100644 index 0000000..abd81f0 --- /dev/null +++ b/jaxx-compiler/src/main/java/jaxx/compiler/decorators/BoxedCompiledObjectDecorator.java @@ -0,0 +1,30 @@ +package jaxx.compiler.decorators; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompiledObject.ChildRef; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.JavaFile; +import jaxx.runtime.SwingUtil; + +/** + * A decorator to surround a compiled object (should be a component at least) + * with a JXLayer. + * + * @author tony + * @since 1.2 + */ +public class BoxedCompiledObjectDecorator extends DefaultCompiledObjectDecorator { + + @Override + public void finalizeCompiler(JAXXCompiler compiler, CompiledObject root, CompiledObject object, JavaFile javaFile, String packageName, String className, String fullClassName) { + CompiledObject parent = object.getParent(); + for (ChildRef child : parent.getChilds()) { + if (child.getChild() == object) { + String javaCode = child.getChildJavaCode(); + child.setChildJavaCode(SwingUtil.class.getName() + ".boxComponentWithJxLayer(" + javaCode + ")"); + break; + } + } + super.finalizeCompiler(compiler, root, object, javaFile, packageName, className, fullClassName); + } +} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/decorators/CompiledObjectDecorator.java b/jaxx-compiler/src/main/java/jaxx/compiler/decorators/CompiledObjectDecorator.java new file mode 100644 index 0000000..f698e94 --- /dev/null +++ b/jaxx-compiler/src/main/java/jaxx/compiler/decorators/CompiledObjectDecorator.java @@ -0,0 +1,26 @@ +package jaxx.compiler.decorators; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.JavaFile; + +/** + * + * Contract of compiled object decorator at generation time. + * + * Note : The implementation of this class must be stateless. + * + * @author tony + * @since 1.2 + */ +public interface CompiledObjectDecorator { + + String createCompleteSetupMethod(JAXXCompiler compiler, CompiledObject object, JavaFile javaFile, StringBuffer initDataBindings); + + boolean createInitializer(JAXXCompiler compiler, CompiledObject root, CompiledObject object, StringBuffer code, boolean lastWasMethodCall); + + void finalizeCompiler(JAXXCompiler compiler, CompiledObject root, CompiledObject object, JavaFile javaFile, String packageName, String className, String fullClassName); + + String getCreationCode(JAXXCompiler compiler, CompiledObject object) throws CompilerException; +} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/decorators/CompiledObjectDecoratorManager.java b/jaxx-compiler/src/main/java/jaxx/compiler/decorators/CompiledObjectDecoratorManager.java new file mode 100644 index 0000000..1fcfe4d --- /dev/null +++ b/jaxx-compiler/src/main/java/jaxx/compiler/decorators/CompiledObjectDecoratorManager.java @@ -0,0 +1,59 @@ +package jaxx.compiler.decorators; + +import java.util.Map; +import java.util.TreeMap; + +/** + * + * @author chemit + * @since 2.0.0 + */ +public class CompiledObjectDecoratorManager { + + protected static Map<String, CompiledObjectDecorator> cache; + + public static void registerDecorator(String key, Class<? extends CompiledObjectDecorator> klass) { + synchronized (getCache()) { + if (getCache().containsKey(key)) { + throw new IllegalArgumentException("the decorator with key [" + key + "] is already registred! use another key name"); + } + try { + getCache().put(key, klass.newInstance()); + } catch (InstantiationException ex) { + throw new IllegalArgumentException("could not create decorator " + klass + " for reason " + ex.getMessage(), ex); + } catch (IllegalAccessException ex) { + throw new IllegalArgumentException("could not create decorator " + klass + " for reason " + ex.getMessage(), ex); + } + } + } + + public static CompiledObjectDecorator getDecorator(String name) { + CompiledObjectDecorator decorator = getCache().get(name); + if (decorator == null) { + throw new IllegalArgumentException("could not find decorator with key " + name + " (known decorators : " + getCache().keySet()); + } + return decorator; + } + + public static CompiledObjectDecorator getDecorator(Class<?> type) { + for (CompiledObjectDecorator decorator : getCache().values()) { + if (type == decorator.getClass()) { + return decorator; + } + } + return null; + } + + protected static synchronized Map<String, CompiledObjectDecorator> getCache() { + if (cache == null) { + cache = new TreeMap<String, CompiledObjectDecorator>(); + } + return cache; + } + + public static void reset() { + if (cache != null) { + cache.clear(); + } + } +} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/decorators/DefaultCompiledObjectDecorator.java b/jaxx-compiler/src/main/java/jaxx/compiler/decorators/DefaultCompiledObjectDecorator.java new file mode 100644 index 0000000..57ff26f --- /dev/null +++ b/jaxx-compiler/src/main/java/jaxx/compiler/decorators/DefaultCompiledObjectDecorator.java @@ -0,0 +1,131 @@ +package jaxx.compiler.decorators; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.JavaField; +import jaxx.compiler.JavaFile; +import jaxx.compiler.JavaMethod; +import jaxx.compiler.ScriptInitializer; +import jaxx.compiler.types.TypeManager; + +import java.lang.reflect.Modifier; +import java.util.Map.Entry; + +/** + * The default compiledObjectDecorator. + * + * @author tony + * @since 1.2 + */ +public class DefaultCompiledObjectDecorator implements CompiledObjectDecorator { + + @Override + 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(); + int access = id.startsWith("$") ? Modifier.PRIVATE : Modifier.PROTECTED; + if (object == root) { + javaFile.addField(new JavaField(access, fullClassName, id, "this")); + } else { + //TC -20081017 can have generic on compiled Object + javaFile.addField(JavaField.newField(access, JAXXCompiler.getCanonicalName(object), id), object.isJavaBean()); + } + } + + if (!compiler.inlineCreation(object) && object != root) { + javaFile.addMethod(JavaMethod.newMethod(Modifier.PROTECTED, "void", object.getCreationMethodName(), getCreationCode(compiler, object))); + } + } + + @Override + public String getCreationCode(JAXXCompiler compiler, CompiledObject object) throws CompilerException { + if (object instanceof ScriptInitializer) { + return object.getInitializationCode(compiler); + } + StringBuffer result = new StringBuffer(); + if (object.isOverride() && object.getOverrideType() == object.getObjectClass()) { + //TC-20090309 on utilise le super code quand l'objet est de meme type + result.append("super.").append(object.getCreationMethodName()).append("();"); + } else { + result.append(object.getId()); + result.append(" = "); + if (object.isJavaBean() && object.getJavaBeanInitCode() != null) { + result.append(object.getJavaBeanInitCode()).append(";"); + } else { + String constructorParams = object.getConstructorParams(); + if (constructorParams != null) { + //TC - 20081017 compiledObject can have generics + result.append(" new ").append(JAXXCompiler.getCanonicalName(object)).append("(").append(constructorParams).append(");"); + //result.append("(").append(getCanonicalName(object.getObjectClass())).append(") new ").append(getCanonicalName(object.getObjectClass())).append("(").append(constructorParams).append(");"); + } else { + //TC - 20081017 compiledObject can have generics + result.append("new ").append(JAXXCompiler.getCanonicalName(object)).append("();"); + } + } + result.append(JAXXCompiler.getLineSeparator()); + result.append("$objectMap.put(").append(TypeManager.getJavaCode(object.getId())).append(", ").append(object.getId()).append(");"); + } + result.append(JAXXCompiler.getLineSeparator()); + String initCode = object.getInitializationCode(compiler); + if (initCode != null && initCode.length() > 0) { + result.append(initCode); + } + + return result.toString(); + } + + @Override + public String createCompleteSetupMethod(JAXXCompiler compiler, CompiledObject object, JavaFile javaFile, StringBuffer initDataBindings) { + StringBuffer code = new StringBuffer(); + //TC-20090327 generate client properties + if (object.hasClientProperties()) { + // generate putClientProperty invocations + for (Entry<String, String> entry : object.getClientProperties().entrySet()) { + object.appendAdditionCode(object.getJavaCode() + ".putClientProperty(\"" + entry.getKey() + "\", " + entry.getValue() + ");"); + } + + } + //TC - 20081017 only generate the method if not empty ? + if (object.getId().startsWith("$")) { + code.append(object.getAdditionCode()).append(JAXXCompiler.getLineSeparator()); + } else { + String additionCode = object.getAdditionCode(); + if (additionCode.length() > 0) { + code.append(object.getAdditionMethodName()).append("();").append(JAXXCompiler.getLineSeparator()); + additionCode = "if (!allComponentsCreated) {" + JAXXCompiler.getLineSeparator() + " return;" + JAXXCompiler.getLineSeparator() + "}" + JAXXCompiler.getLineSeparator() + additionCode; + javaFile.addMethod(JavaMethod.newMethod(Modifier.PROTECTED, "void", object.getAdditionMethodName(), additionCode)); + } + } + //code.append(getLineSeparator()); + return code.toString(); + } + + @Override + public boolean createInitializer(JAXXCompiler compiler, CompiledObject root, CompiledObject object, StringBuffer code, boolean lastWasMethodCall) { + if (object == root) { + String rootCode = root.getInitializationCode(compiler); + if (rootCode != null && rootCode.length() > 0) { + code.append(rootCode); + code.append(JAXXCompiler.getLineSeparator()); + } + } else { + if (!object.isOverride()) { + if (compiler.inlineCreation(object)) { + if (lastWasMethodCall) { + lastWasMethodCall = false; + code.append(JAXXCompiler.getLineSeparator()); + } + code.append(getCreationCode(compiler, object)); + code.append(JAXXCompiler.getLineSeparator()); + } else { + code.append(object.getCreationMethodName()).append("();"); + code.append(JAXXCompiler.getLineSeparator()); + lastWasMethodCall = true; + } + } + } + return lastWasMethodCall; + } +} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/decorators/HelpRootCompiledObjectDecorator.java b/jaxx-compiler/src/main/java/jaxx/compiler/decorators/HelpRootCompiledObjectDecorator.java new file mode 100644 index 0000000..eb11a1a --- /dev/null +++ b/jaxx-compiler/src/main/java/jaxx/compiler/decorators/HelpRootCompiledObjectDecorator.java @@ -0,0 +1,100 @@ +package jaxx.compiler.decorators; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompilerConfiguration; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.JavaArgument; +import jaxx.compiler.JavaFile; +import jaxx.compiler.JavaMethod; + +import java.lang.reflect.Modifier; +import java.util.Iterator; +import java.util.Set; + +/** + * A decorator to place on a root compiled object to process javaHelp on the file. + * + * @author tony + * @since 1.2 + */ +public class HelpRootCompiledObjectDecorator extends DefaultCompiledObjectDecorator { + + /** + * the list of discovered helpId + */ + protected static Set<String> helpIds = new java.util.HashSet<String>(); + + protected String getBrokerFQN(JAXXCompiler compiler) { + String helpBrokerFQN = compiler.getConfiguration().getHelpBrokerFQN(); + return helpBrokerFQN; + } + + protected String getHelpId(CompiledObject o) { + String helpID = null; + if (o.hasClientProperties()) { + helpID = o.getClientProperty("help"); + } + return helpID; + } + + @Override + public void finalizeCompiler(JAXXCompiler compiler, CompiledObject root, CompiledObject object, JavaFile javaFile, String packageName, String className, String fullClassName) { + super.finalizeCompiler(compiler, root, object, javaFile, packageName, className, fullClassName); + CompilerConfiguration options = compiler.getConfiguration(); + + if (options.isGenerateHelp()) { + + // add JaxxHelpUI interface + Class<?> validatorInterface = jaxx.runtime.JaxxHelpUI.class; + String helpBrokerFQN = getBrokerFQN(compiler); + javaFile.addInterface(JAXXCompiler.getCanonicalName(validatorInterface) + "<" + helpBrokerFQN + ">"); + + javaFile.addMethod(JavaMethod.newMethod(Modifier.PUBLIC, "void", "registerHelpId", + "broker.installUI(component, helpId);", + new JavaArgument(helpBrokerFQN, "broker"), + new JavaArgument("Component", "component"), + new JavaArgument("String", "helpId"))); + + javaFile.addMethod(JavaMethod.newMethod(Modifier.PUBLIC, "void", "showHelp", + "getBroker().showHelp(this, helpId);", + new JavaArgument("String", "helpId"))); + + StringBuilder buffer = new StringBuilder(); + + String lineSeparator = JAXXCompiler.getLineSeparator(); + + if (options.isGenerateHelp()) { + + // 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(lineSeparator); + // 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();"); + + buffer.append(lineSeparator).append("_broker.prepareUI(this);"); + buffer.append(lineSeparator); + + // add the calls + compiler.appendLateInitializer(extraCode.toString()); + compiler.appendLateInitializer(buffer.toString()); + } + } + } + + public static Set<String> getHelpIds() { + return helpIds; + } +} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/generators/GeneratorManager.java b/jaxx-compiler/src/main/java/jaxx/compiler/generators/GeneratorManager.java new file mode 100644 index 0000000..1a79d46 --- /dev/null +++ b/jaxx-compiler/src/main/java/jaxx/compiler/generators/GeneratorManager.java @@ -0,0 +1,42 @@ +package jaxx.compiler.generators; + +import java.util.ArrayList; +import java.util.List; +import java.util.ServiceLoader; + +/** + * + * @author chemit + * @since 2.0.0 + */ +public class GeneratorManager { + + protected static List<Generator> generators; + + public static List<Generator> getGenerators() { + if (generators == null) { + loadGenerators(); + } + return generators; + } + + public static void addGenerator(Generator g) { + getGenerators().add(g); + } + + public static void clear() { + if (generators != null) { + generators.clear(); + generators = null; + } + } + + protected static void loadGenerators() { + if (generators == null) { + generators = new ArrayList<Generator>(); + for (Generator generator : ServiceLoader.load(Generator.class)) { + generators.add(generator); + } + } + } +} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/generators/JAXXObjectGenerator.java b/jaxx-compiler/src/main/java/jaxx/compiler/generators/JAXXObjectGenerator.java new file mode 100644 index 0000000..6f7f5f6 --- /dev/null +++ b/jaxx-compiler/src/main/java/jaxx/compiler/generators/JAXXObjectGenerator.java @@ -0,0 +1,604 @@ +package jaxx.compiler.generators; + +import jaxx.compiler.*; +import jaxx.runtime.Base64Coder; +import jaxx.compiler.CompilerException; +import jaxx.compiler.decorators.CompiledObjectDecorator; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorLoader; +import jaxx.compiler.reflect.FieldDescriptor; +import jaxx.compiler.reflect.MethodDescriptor; +import jaxx.compiler.types.TypeManager; +import jaxx.runtime.JAXXObject; +import jaxx.runtime.JAXXObjectDescriptor; +import jaxx.runtime.context.JAXXContext; +import jaxx.runtime.Util; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.IOException; +import java.lang.reflect.Modifier; +import static java.lang.reflect.Modifier.FINAL; +import static java.lang.reflect.Modifier.PROTECTED; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * This class is a refactoring of the {@link jaxx.compiler.JAXXCompiler}. + * <p/> + * We delegate now the generation of a {@link jaxx.runtime.JAXXObject} to this class, the + * {@link jaxx.compiler.JAXXCompiler} now only deals with the compilation of files. + * + * @author chemit + */ +public class JAXXObjectGenerator implements Generator { + + /** log */ + protected static final Log log = LogFactory.getLog(JAXXObjectGenerator.class); + protected static final JavaField ACTIVE_BINDINGS_FIELD = JavaField.newField(PROTECTED, + "java.util.List<Object>", "$activeBindings", "new ArrayList<Object>()"); + protected static final JavaField BINDING_SOURCES_FIELD = JavaField.newField(PROTECTED, + "java.util.Map<String,Object>", "$bindingSources", "new HashMap<String,Object>()"); + protected static final JavaField OBJECT_MAP_FIELD = JavaField.newField(PROTECTED, + "Map<String,Object>", "$objectMap", "new HashMap<String,Object>()"); + protected static final JavaField ALL_COMPONENTS_CREATED_FIELD = JavaField.newField(java.lang.reflect.Modifier.PRIVATE, + "boolean", "allComponentsCreated"); + protected static final JavaField CONTEXT_INITIALIZED = JavaField.newField(java.lang.reflect.Modifier.PRIVATE, + "boolean", "contextInitialized", "true"); + protected static final JavaField PREVIOUS_VALUES_FIELD = JavaField.newField(0, + "java.util.Map", "$previousValues", "new java.util.HashMap()"); + protected static final JavaField DELEGATE_CONTEXT_FIELD = JavaField.newField(PROTECTED, + "jaxx.runtime.context.JAXXContext", "delegateContext"); + protected static final JavaField PROPERTY_CHANGE_SUPPORT_FIELD = JavaField.newField(0, + "java.beans.PropertyChangeSupport", "$propertyChangeSupport"); + protected static final JavaMethod GET_CONTEXT_VALUE_METHOD = JavaMethod.newMethod(java.lang.reflect.Modifier.PUBLIC, "<T> T", "getContextValue", + "return delegateContext.getContextValue(clazz, null);", + new JavaArgument("Class<T>", "clazz")); + protected static final JavaMethod GET_CONTEXT_VALUE_NAMED_METHOD = JavaMethod.newMethod(java.lang.reflect.Modifier.PUBLIC, "<T> T", "getContextValue", + "return delegateContext.getContextValue(clazz, name);", + new JavaArgument("Class<T>", "clazz"), new JavaArgument("String", "name")); + protected static final JavaMethod SET_CONTEXT_VALUE_NAMED_METHOD = JavaMethod.newMethod(java.lang.reflect.Modifier.PUBLIC, "<T> void", "setContextValue", + "delegateContext.setContextValue(o, name);", + new JavaArgument("T", "o"), new JavaArgument("String", "name")); + protected static final JavaMethod SET_CONTEXT_VALUE_METHOD = JavaMethod.newMethod(java.lang.reflect.Modifier.PUBLIC, "<T> void", "setContextValue", + "delegateContext.setContextValue(o, null);", + new JavaArgument("T", "o")); + protected static final JavaMethod REMOVE_CONTEXT_VALUE_NAMED_METHOD = JavaMethod.newMethod(java.lang.reflect.Modifier.PUBLIC, "<T> void", "removeContextValue", + "delegateContext.removeContextValue(clazz, name);", + new JavaArgument("Class<T>", "clazz"), new JavaArgument("String", "name")); + protected static final JavaMethod REMOVE_CONTEXT_VALUE_METHOD = JavaMethod.newMethod(java.lang.reflect.Modifier.PUBLIC, "<T> void", "removeContextValue", + "delegateContext.removeContextValue(clazz, null);", + new JavaArgument("Class<T>", "clazz")); + protected static final JavaMethod GET_PARENT_CONTAINER_MORE_METHOD = JavaMethod.newMethod(java.lang.reflect.Modifier.PUBLIC, "<O extends Container> O", "getParentContainer", + "return delegateContext.getParentContainer(source, clazz);", + new JavaArgument("Object", "source"), new JavaArgument("Class<O>", "clazz")); + protected static final JavaMethod GET_PARENT_CONTAINER_METHOD = JavaMethod.newMethod(java.lang.reflect.Modifier.PUBLIC, "<O extends Container> O", "getParentContainer", + "return delegateContext.getParentContainer(clazz);", + new JavaArgument("Class<O>", "clazz")); + protected static final JavaMethod GET_OBJECT_BY_ID_METHOD = JavaMethod.newMethod(java.lang.reflect.Modifier.PUBLIC, "java.lang.Object", "getObjectById", + "return $objectMap.get(id);", + new JavaArgument("String", "id")); + protected static final JavaMethod GET_JAXX_OBJECT_DESCRIPTOR_METHOD = JavaMethod.newMethod(java.lang.reflect.Modifier.PUBLIC | java.lang.reflect.Modifier.STATIC, "jaxx.runtime.JAXXObjectDescriptor", "$getJAXXObjectDescriptor", + "return jaxx.runtime.Util.decodeCompressedJAXXObjectDescriptor($jaxxObjectDescriptor);"); + protected static final JavaMethod PROCESS_DATA_BINDING_METHOD = JavaMethod.newMethod(java.lang.reflect.Modifier.PUBLIC, "void", "processDataBinding", + "processDataBinding(dest, false);", + new JavaArgument("String", "dest")); + protected static final JavaMethod FIRE_PROPERTY_CHANGE_METHOD = JavaMethod.newMethod(java.lang.reflect.Modifier.PUBLIC, "void", "firePropertyChange", + "super.firePropertyChange(propertyName, oldValue, newValue);", + new JavaArgument("String", "propertyName"), new JavaArgument("Object", "oldValue"), new JavaArgument("Object", "newValue")); + protected static final JavaMethod FIRE_PROPERTY_CHANGE_NAMED_METHOD = JavaMethod.newMethod(java.lang.reflect.Modifier.PUBLIC, "void", "firePropertyChange", + "$getPropertyChangeSupport().firePropertyChange(propertyName, oldValue, newValue);", + new JavaArgument("String", "propertyName"), new JavaArgument("Object", "oldValue"), new JavaArgument("Object", "newValue")); + protected static final JavaMethod GET_PROPERTY_CHANGE_SUPPORT_METHOD = JavaMethod.newMethod(0, "java.beans.PropertyChangeSupport", "$getPropertyChangeSupport", + "if ($propertyChangeSupport == null)\n" + + " $propertyChangeSupport = new PropertyChangeSupport(this);\n" + + "return $propertyChangeSupport;"); + protected static final JavaMethod ADD_PROPERTY_CHANGE_SUPPORT_METHOD = JavaMethod.newMethod(java.lang.reflect.Modifier.PUBLIC, "void", "addPropertyChangeListener", + "$getPropertyChangeSupport().addPropertyChangeListener(listener);", + new JavaArgument("java.beans.PropertyChangeListener", "listener")); + protected static final JavaMethod ADD_PROPERTY_CHANGE_SUPPORT_NAMED_METHOD = JavaMethod.newMethod(java.lang.reflect.Modifier.PUBLIC, "void", "addPropertyChangeListener", + "$getPropertyChangeSupport().addPropertyChangeListener(property, listener);", + new JavaArgument("String", "property"), new JavaArgument("java.beans.PropertyChangeListener", "listener")); + protected static final JavaMethod REMOVE_PROPERTY_CHANGE_SUPPORT_METHOD = JavaMethod.newMethod(java.lang.reflect.Modifier.PUBLIC, "void", "removePropertyChangeListener", + "$getPropertyChangeSupport().removePropertyChangeListener(listener);", + new JavaArgument("java.beans.PropertyChangeListener", "listener")); + protected static final JavaMethod REMOVE_PROPERTY_CHANGE_SUPPORT_NAMED_METHOD = JavaMethod.newMethod(java.lang.reflect.Modifier.PUBLIC, "void", "removePropertyChangeListener", + "$getPropertyChangeSupport().removePropertyChangeListener(property, listener);", + new JavaArgument("String", "property"), new JavaArgument("java.beans.PropertyChangeListener", "listener")); + + @Override + public void finalizeCompiler(CompiledObject root, JAXXCompiler compiler, JavaFile javaFile, String packageName, String className) { + + String fullClassName = packageName != null ? packageName + "." + className : className; + if (root == null) { + throw new CompilerException("root tag must be a class tag"); + } + //Map<String, CompiledObject> objects = compiler.getObjects(); + ClassDescriptor superclass = root.getObjectClass(); + boolean superclassIsJAXXObject = ClassDescriptorLoader.getClassDescriptor(JAXXObject.class).isAssignableFrom(superclass); + javaFile.setModifiers(Modifier.PUBLIC); + javaFile.setClassName(fullClassName); + javaFile.setSuperClass(JAXXCompiler.getCanonicalName(superclass)); + javaFile.setSuperclassIsJAXXObject(superclassIsJAXXObject); + + javaFile.addInterfaces(compiler.getExtraInterfaces()); + javaFile.setAbstractClass(compiler.isAbstractClass()); + javaFile.setGenericType(compiler.getGenericType()); + javaFile.setSuperGenericType(compiler.getSuperGenericType()); + + for (CompiledObject object : compiler.getObjects().values()) { + CompiledObjectDecorator decorator = object.getDecorator(); + decorator.finalizeCompiler(compiler, root, object, javaFile, packageName, className, fullClassName); + + /*if (!object.isOverride() && !(object instanceof ScriptInitializer)) { + String id = object.getId(); + int access = id.startsWith("$") ? Modifier.PRIVATE : Modifier.PROTECTED; + if (object == root) { + javaFile.addField(new JavaField(access, fullClassName, id, "this")); + } else { + //TC -20081017 can have generic on compiled Object + javaFile.addField(JavaField.newField(access, JAXXCompiler.getCanonicalName(object), id), object.isJavaBean()); + } + } + + if (!compiler.inlineCreation(object) && object != root) { + javaFile.addMethod(JavaMethod.newMethod(Modifier.PROTECTED, "void", object.getCreationMethodName(), getCreationCode(compiler, object))); + }*/ + } + + // DataBinding + for (DataBinding dataBinding : compiler.getDataBindings()) { + if (dataBinding.compile(true)) { + compiler.getInitDataBindings().append("applyDataBinding(").append(TypeManager.getJavaCode(dataBinding.getId())).append(");").append(JAXXCompiler.getLineSeparator()); + } + } + + if (superclassIsJAXXObject) { + boolean hasBind = compiler.getApplyDataBinding().length() > 0; + if (hasBind) { + compiler.appendApplyDataBinding(" else {"); + compiler.appendApplyDataBinding(JAXXCompiler.getLineSeparator()); + compiler.appendApplyDataBinding(" "); + } + compiler.appendApplyDataBinding("super.applyDataBinding($binding);"); + compiler.appendApplyDataBinding(JAXXCompiler.getLineSeparator()); + + if (hasBind) { + compiler.appendApplyDataBinding(" return;"); + compiler.appendApplyDataBinding(JAXXCompiler.getLineSeparator()); + compiler.appendApplyDataBinding("}"); + } + + + hasBind = compiler.getRemoveDataBinding().length() > 0; + if (hasBind) { + compiler.appendRemoveDataBinding(" else {"); + compiler.appendRemoveDataBinding(JAXXCompiler.getLineSeparator()); + compiler.appendRemoveDataBinding(" "); + } + compiler.appendRemoveDataBinding("super.removeDataBinding($binding);"); + compiler.appendRemoveDataBinding(JAXXCompiler.getLineSeparator()); + + if (hasBind) { + compiler.appendRemoveDataBinding("}"); + } + } else { + javaFile.addInterface(JAXXCompiler.getCanonicalName(JAXXObject.class)); + } + } + + @Override + public void prepareJavaFile(CompiledObject root, JAXXCompiler compiler, JavaFile javaFile, String packageName, String className) throws ClassNotFoundException { + + String fullClassName = javaFile.getClassName(); + + String jaxxContextImplementorClass = compiler.getConfiguration().getJaxxContextClass().getName(); + boolean superclassIsJAXXObject = javaFile.isSuperclassIsJAXXObject(); + if (!superclassIsJAXXObject) { + // add logger + if (compiler.getConfiguration().isAddLogger()) { + javaFile.addImport(Log.class); + javaFile.addImport(LogFactory.class); + javaFile.addField(JavaField.newField(Modifier.PUBLIC + Modifier.STATIC + FINAL, "Log", "log", "LogFactory.getLog(" + fullClassName + ".class)")); + } + + // JAXXObject + javaFile.addField(OBJECT_MAP_FIELD); + javaFile.addMethod(GET_OBJECT_BY_ID_METHOD); + javaFile.addField(BINDING_SOURCES_FIELD); + javaFile.addField(ACTIVE_BINDINGS_FIELD); + + // JAXXContext + javaFile.addField(JavaField.newField(PROTECTED | FINAL, JAXXContext.class.getName(), "delegateContext", "new " + jaxxContextImplementorClass + "(this);")); + javaFile.addMethod(SET_CONTEXT_VALUE_METHOD); + javaFile.addMethod(SET_CONTEXT_VALUE_NAMED_METHOD); + javaFile.addMethod(GET_CONTEXT_VALUE_METHOD); + javaFile.addMethod(GET_CONTEXT_VALUE_NAMED_METHOD); + javaFile.addMethod(REMOVE_CONTEXT_VALUE_METHOD); + javaFile.addMethod(REMOVE_CONTEXT_VALUE_NAMED_METHOD); + javaFile.addMethod(GET_PARENT_CONTAINER_METHOD); + javaFile.addMethod(GET_PARENT_CONTAINER_MORE_METHOD); + + // PropertyChangeSupport + addPropertyChangeSupport(root, javaFile); + + // DataBinding + javaFile.addMethod(PROCESS_DATA_BINDING_METHOD); + } + + javaFile.addField(ALL_COMPONENTS_CREATED_FIELD); + boolean overrideContextInitialized = false; + FieldDescriptor[] scriptFields = compiler.getScriptFields(); + for (FieldDescriptor f : scriptFields) { + if ("contextInitialized".equals(f.getName())) { + overrideContextInitialized = true; + break; + } + } + if (!overrideContextInitialized) { + javaFile.addField(CONTEXT_INITIALIZED); + } + javaFile.addField(createJAXXObjectDescriptorField(compiler, javaFile)); + + if (compiler.getStylesheet() != null) { + javaFile.addField(PREVIOUS_VALUES_FIELD); + } + /*for (CompiledObject object : compiler.getObjects().values()) { + List<CompiledObject.ChildRef> refList = object.getChilds(); + if (refList==null || refList.isEmpty()) { + continue; + } + for (ChildRef childRef : refList) { + childRef.addToAdditionCode(buffer); + } + }*/ + //TC 20090228 - only generate constructors if not done in scripts + boolean constructorDetected = false; + MethodDescriptor[] methods = compiler.getScriptMethods(); + for (MethodDescriptor m : methods) { + try { + m.getReturnType(); + if (className.equals(m.getName())) { + constructorDetected = true; + break; + } + } catch (Exception e) { + log.warn("could not find return type " + m); + } + } + if (!constructorDetected) { + javaFile.addMethod(createConstructor(compiler, className, superclassIsJAXXObject)); + javaFile.addMethod(createConstructorWithInitialContext(compiler, className, superclassIsJAXXObject)); + } + + javaFile.addMethod(createInitializer(compiler)); + javaFile.addMethod(GET_JAXX_OBJECT_DESCRIPTOR_METHOD); + + javaFile.addBodyCode(compiler.getBodyCode().toString()); + + javaFile.addMethod(createCompleteSetupMethod(compiler, javaFile, compiler.getInitDataBindings())); + + + javaFile.addMethod(JavaMethod.newMethod(Modifier.PUBLIC, "void", "applyDataBinding", + compiler.getApplyDataBinding().toString() + JAXXCompiler.getLineSeparator() + "processDataBinding($binding);", + new JavaArgument("String", "$binding"))); + + javaFile.addMethod(JavaMethod.newMethod(Modifier.PUBLIC, "void", "removeDataBinding", + compiler.getRemoveDataBinding().toString(), new JavaArgument("String", "$binding"))); + + javaFile.addMethod(createProcessDataBindingMethod(compiler, superclassIsJAXXObject)); + + addEventHandlers(compiler, javaFile); + + } + + + /*---------------------------------------------------------------------------------*/ + /*-- Create fields ----------------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + protected JavaField createJAXXObjectDescriptorField(JAXXCompiler compiler, JavaFile javaFile) { + try { + JAXXObjectDescriptor descriptor = compiler.getJAXXObjectDescriptor(); + String data = Base64Coder.serialize(descriptor, true); + /*ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(new GZIPOutputStream(buffer)); + out.writeObject(descriptor); + out.close(); + // the use of the weird deprecated constructor is deliberate -- we need to store the data as a String + // in the compiled class file, since byte array initialization is horribly inefficient compared to + // String initialization. So we store the bytes in the String, and we quite explicitly want a 1:1 + // mapping between bytes and chars, with the high byte of the char set to zero. We can then safely + // reconstitute the original byte[] at a later date. This is unquestionably an abuse of the String + // type, but if we could efficiently store a byte[] we wouldn't have to do this. + String data = new String(buffer.toByteArray(), 0);*/ + + int sizeLimit = 65000; // constant strings are limited to 64K, and I'm not brave enough to push right up to the limit + if (data.length() < sizeLimit) { + return JavaField.newField(Modifier.PRIVATE | Modifier.STATIC, "java.lang.String", "$jaxxObjectDescriptor", TypeManager.getJavaCode(data)); + } else { + StringBuffer initializer = new StringBuffer(); + for (int i = 0; i < data.length(); i += sizeLimit) { + String name = "$jaxxObjectDescriptor" + i; + javaFile.addField(new JavaField(Modifier.PRIVATE | Modifier.STATIC, "java.lang.String", name, + TypeManager.getJavaCode(data.substring(i, Math.min(i + sizeLimit, data.length()))))); + if (initializer.length() > 0) { + initializer.append(" + "); + } + initializer.append("String.valueOf(").append(name).append(")"); + } + return JavaField.newField(Modifier.PRIVATE | Modifier.STATIC, "java.lang.String", "$jaxxObjectDescriptor", initializer.toString()); + } + } catch (IOException e) { + throw new RuntimeException("Internal error: can't-happen error", e); + } + } + + /*---------------------------------------------------------------------------------*/ + /*-- Create methods ---------------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + protected void addPropertyChangeSupport(CompiledObject root, JavaFile javaFile) { + ClassDescriptor currentClass = root.getObjectClass(); + MethodDescriptor firePropertyChange = null; + while (firePropertyChange == null && currentClass != null) { + try { + firePropertyChange = currentClass.getDeclaredMethodDescriptor("firePropertyChange", ClassDescriptorLoader.getClassDescriptor(String.class), + ClassDescriptorLoader.getClassDescriptor(Object.class), + ClassDescriptorLoader.getClassDescriptor(Object.class)); + + } catch (NoSuchMethodException e) { + currentClass = currentClass.getSuperclass(); + } + } + + int modifiers = firePropertyChange != null ? firePropertyChange.getModifiers() : 0; + if (Modifier.isPublic(modifiers)) { + // we have all the support we need + } + if (Modifier.isProtected(modifiers)) { + // there is property change support but the firePropertyChange method is protected + javaFile.addMethod(FIRE_PROPERTY_CHANGE_METHOD); + } else { + // either no support at all or firePropertyChange isn't accessible + javaFile.addField(PROPERTY_CHANGE_SUPPORT_FIELD); + javaFile.addMethod(GET_PROPERTY_CHANGE_SUPPORT_METHOD); + javaFile.addMethod(ADD_PROPERTY_CHANGE_SUPPORT_METHOD); + javaFile.addMethod(ADD_PROPERTY_CHANGE_SUPPORT_NAMED_METHOD); + javaFile.addMethod(REMOVE_PROPERTY_CHANGE_SUPPORT_METHOD); + javaFile.addMethod(REMOVE_PROPERTY_CHANGE_SUPPORT_NAMED_METHOD); + javaFile.addMethod(FIRE_PROPERTY_CHANGE_NAMED_METHOD); + } + } + + protected void addEventHandlers(JAXXCompiler compiler, JavaFile javaFile) { + for (Map.Entry<String, Map<ClassDescriptor, List<EventHandler>>> e1 : compiler.getEventHandlers().entrySet()) { + // outer loop is iterating over different objects (well, technically, different Java expressions) + for (Map.Entry<ClassDescriptor, List<EventHandler>> e2 : e1.getValue().entrySet()) { + // iterate over different types of listeners for this particular object (MouseListener, ComponentListener, etc.) + for (EventHandler handler : e2.getValue()) { + // iterate over individual event handlers of a single type + String methodName = compiler.getEventHandlerMethodName(handler); + MethodDescriptor listenerMethod = handler.getListenerMethod(); + if (listenerMethod.getParameterTypes().length != 1) { + throw new CompilerException("Expected event handler " + listenerMethod.getName() + " of class " + handler.getListenerClass() + " to have exactly one argument"); + } + javaFile.addMethod(JavaMethod.newMethod(Modifier.PUBLIC, "void", methodName, handler.getJavaCode(), + new JavaArgument(JAXXCompiler.getCanonicalName(listenerMethod.getParameterTypes()[0]), "event"))); + } + } + } + } + + protected JavaMethod createConstructor(JAXXCompiler compiler, String className, boolean superclassIsJAXXObject) throws CompilerException { + StringBuffer code = new StringBuffer(); + String constructorParams = compiler.getRootObject().getConstructorParams(); + if (constructorParams != null) { + code.append(" super(").append(constructorParams).append(");").append(JAXXCompiler.getLineSeparator()); + } else { + if (superclassIsJAXXObject) { + code.append(" super();").append(JAXXCompiler.getLineSeparator()); + } + } + code.append("$initialize();"); + code.append(JAXXCompiler.getLineSeparator()); + return JavaMethod.newMethod(Modifier.PUBLIC, null, className, code.toString()); + } + + protected JavaMethod createConstructorWithInitialContext(JAXXCompiler compiler, String className, boolean superclassIsJAXXObject) throws CompilerException { + StringBuffer code = new StringBuffer(); + String constructorParams = compiler.getRootObject().getConstructorParams(); + if (constructorParams != null) { + code.append(" super(").append(constructorParams).append(");").append(JAXXCompiler.getLineSeparator()); + } else { + if (superclassIsJAXXObject) { + code.append(" super(parentContext);").append(JAXXCompiler.getLineSeparator()); + } + } + if (!superclassIsJAXXObject) { + code.append(Util.class.getName() + ".initContext(this, parentContext);"); + code.append(JAXXCompiler.getLineSeparator()); + +// code.append("if (parentContext instanceof jaxx.runtime.context.JAXXInitialContext) {"); +// code.append(JAXXCompiler.getLineSeparator()); +// code.append(" ((jaxx.runtime.context.JAXXInitialContext)parentContext).to(this);"); +// code.append(JAXXCompiler.getLineSeparator()); +// code.append("} else {"); +// code.append(JAXXCompiler.getLineSeparator()); +// code.append(" setContextValue(parentContext);"); +// code.append(JAXXCompiler.getLineSeparator()); +// code.append("}"); +// code.append(JAXXCompiler.getLineSeparator()); + } + code.append("$initialize();"); + code.append(JAXXCompiler.getLineSeparator()); + return JavaMethod.newMethod(Modifier.PUBLIC, null, className, code.toString(), new JavaArgument("jaxx.runtime.context.JAXXContext", "parentContext")); + } + + public JavaMethod createInitializer(JAXXCompiler compiler) throws CompilerException { + StringBuffer code = new StringBuffer(); + CompiledObject root = compiler.getRootObject(); + code.append("if (allComponentsCreated || !contextInitialized) {"); + code.append(JAXXCompiler.getLineSeparator()); + code.append(" return;"); + code.append(JAXXCompiler.getLineSeparator()); + code.append("}"); + code.append(JAXXCompiler.getLineSeparator()); + code.append("$objectMap.put(").append(TypeManager.getJavaCode(root.getId())).append(", this);"); + code.append(JAXXCompiler.getLineSeparator()); + + Iterator<CompiledObject> i = compiler.getObjectCreationOrder(); + boolean lastWasMethodCall = false; + while (i.hasNext()) { + CompiledObject object = i.next(); + if (object == root) { + continue; + } + CompiledObjectDecorator decorator = object.getDecorator(); + lastWasMethodCall = decorator.createInitializer(compiler, root, object, code, lastWasMethodCall); + /*if (object != root && !object.isOverride()) { + if (compiler.inlineCreation(object)) { + if (lastWasMethodCall) { + lastWasMethodCall = false; + code.append(JAXXCompiler.getLineSeparator()); + } + code.append(getCreationCode(compiler, object)); + code.append(JAXXCompiler.getLineSeparator()); + } else { + code.append(object.getCreationMethodName()).append("();"); + code.append(JAXXCompiler.getLineSeparator()); + lastWasMethodCall = true; + } + }*/ + } + root.getDecorator().createInitializer(compiler, root, root, code, lastWasMethodCall); + /*String rootCode = root.getInitializationCode(compiler); + if (rootCode != null && rootCode.length() > 0) { + code.append(rootCode); + code.append(JAXXCompiler.getLineSeparator()); + }*/ + code.append(JAXXCompiler.getLineSeparator()); + if (compiler.getInitializer().length() > 0) { + code.append(compiler.getInitializer()); + code.append(JAXXCompiler.getLineSeparator()); + } + code.append("$completeSetup();"); + code.append(JAXXCompiler.getLineSeparator()); + return JavaMethod.newMethod(Modifier.PRIVATE, "void", "$initialize", code.toString()); + } + + protected JavaMethod createCompleteSetupMethod(JAXXCompiler compiler, JavaFile javaFile, StringBuffer initDataBindings) { + StringBuffer code = new StringBuffer(); + code.append("allComponentsCreated = true;"); + code.append(JAXXCompiler.getLineSeparator()); + for (CompiledObject object : compiler.getObjects().values()) { + CompiledObjectDecorator decorator = object.getDecorator(); + code.append(decorator.createCompleteSetupMethod(compiler, object, javaFile, initDataBindings)); + + /*//TC - 20081017 only generate the method if not empty ? + if (object.getId().startsWith("$")) { + code.append(object.getAdditionCode()).append(JAXXCompiler.getLineSeparator()); + } else { + String additionCode = object.getAdditionCode(); + if (additionCode.length() > 0) { + code.append(object.getAdditionMethodName()).append("();").append(JAXXCompiler.getLineSeparator()); + additionCode = "if (!allComponentsCreated) {" + JAXXCompiler.getLineSeparator() + " return;" + JAXXCompiler.getLineSeparator() + "}" + JAXXCompiler.getLineSeparator() + additionCode; + javaFile.addMethod(JavaMethod.newMethod(Modifier.PROTECTED, "void", object.getAdditionMethodName(), additionCode)); + } + }*/ + //code.append(getLineSeparator()); + } + + code.append(initDataBindings); + + if (compiler.getLateInitializer().length() > 0) { + code.append(compiler.getLateInitializer()); + code.append(JAXXCompiler.getLineSeparator()); + } + //TC-20090313 add an extra method after complete setup + MethodDescriptor method = compiler.getScriptMethod("$afterCompleteSetup"); + if (method != null) { + code.append("$afterCompleteSetup();").append(JAXXCompiler.getLineSeparator()); + } + return JavaMethod.newMethod(Modifier.PRIVATE, "void", "$completeSetup", code.toString()); + } + + protected JavaMethod createProcessDataBindingMethod(JAXXCompiler compiler, boolean superclassIsJAXXObject) { + StringBuffer code = new StringBuffer(); + //boolean superclassIsJAXXObject = ClassDescriptorLoader.getClassDescriptor(JAXXObject.class).isAssignableFrom(compiler.getRootObject().getObjectClass()); + // the force parameter forces the update to happen even if it is already in activeBindings. This + // is used on superclass invocations b/c by the time the call gets to the superclass, it is already + // marked active and would otherwise be skipped + if (compiler.getProcessDataBinding().length() > 0) { + code.append(" if (!$force && $activeBindings.contains($dest)) { "); + code.append(JAXXCompiler.getLineSeparator()); + code.append(" return;"); + code.append(JAXXCompiler.getLineSeparator()); + code.append("}"); + code.append(JAXXCompiler.getLineSeparator()); + code.append("$activeBindings.add($dest);"); + code.append(JAXXCompiler.getLineSeparator()); + code.append("try {"); + code.append(JAXXCompiler.getLineSeparator()); + if (compiler.getProcessDataBinding().length() > 0) { + code.append(compiler.getProcessDataBinding().toString()); + //code.append(JAXXCompiler.getLineSeparator()); + } + if (superclassIsJAXXObject) { + code.append(" else {"); + code.append(JAXXCompiler.getLineSeparator()); + code.append(" super.processDataBinding($dest, true);"); + code.append(JAXXCompiler.getLineSeparator()); + code.append(" }"); + code.append(JAXXCompiler.getLineSeparator()); + } + code.append("} finally {"); + code.append(JAXXCompiler.getLineSeparator()); + code.append(" $activeBindings.remove($dest);"); + code.append(JAXXCompiler.getLineSeparator()); + code.append("}"); + code.append(JAXXCompiler.getLineSeparator()); + } else if (superclassIsJAXXObject) { + code.append("super.processDataBinding($dest, true);"); + code.append(JAXXCompiler.getLineSeparator()); + } + return JavaMethod.newMethod(Modifier.PUBLIC, "void", "processDataBinding", code.toString(), + new JavaArgument("String", "$dest"), new JavaArgument("boolean", "$force")); + } + + /*---------------------------------------------------------------------------------*/ + /*-- Create methods code ----------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + /* protected String getCreationCode(JAXXCompiler compiler, CompiledObject object) throws CompilerException { + if (object instanceof ScriptInitializer) { + return object.getInitializationCode(compiler); + } + CompiledObjectDecorator decorator = object.getDecorator(); + String result = decorator.getCreationCode(compiler, object); + return result;*/ + /*StringBuffer result = new StringBuffer(); + result.append(object.getId()); + result.append(" = "); + if (object.isJavaBean() && object.getJavaBeanInitCode() != null) { + result.append(object.getJavaBeanInitCode()).append(";"); + } else { + String constructorParams = object.getConstructorParams(); + if (constructorParams != null) { + //TC - 20081017 compiledObject can have generics + result.append(" new ").append(JAXXCompiler.getCanonicalName(object)).append("(").append(constructorParams).append(");"); + //result.append("(").append(getCanonicalName(object.getObjectClass())).append(") new ").append(getCanonicalName(object.getObjectClass())).append("(").append(constructorParams).append(");"); + } else { + //TC - 20081017 compiledObject can have generics + result.append("new ").append(JAXXCompiler.getCanonicalName(object)).append("();"); + } + } + result.append(JAXXCompiler.getLineSeparator()); + String initCode = object.getInitializationCode(compiler); + if (initCode != null && initCode.length() > 0) { + result.append(initCode); + } + result.append("$objectMap.put(").append(TypeManager.getJavaCode(object.getId())).append(", ").append(object.getId()).append(");"); + + return result.toString();*/ +// } +} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/generators/SwingGenerator.java b/jaxx-compiler/src/main/java/jaxx/compiler/generators/SwingGenerator.java new file mode 100644 index 0000000..bf2a206 --- /dev/null +++ b/jaxx-compiler/src/main/java/jaxx/compiler/generators/SwingGenerator.java @@ -0,0 +1,27 @@ +package jaxx.compiler.generators; + +import jaxx.compiler.*; +import jaxx.compiler.reflect.ClassDescriptorLoader; +import jaxx.runtime.swing.Application; + +import java.lang.reflect.Modifier; + +/** @author chemit */ +public class SwingGenerator implements Generator { + + @Override + public void finalizeCompiler(CompiledObject root, JAXXCompiler compiler, JavaFile javaFile, String packageName, String className) { + } + + @Override + public void prepareJavaFile(CompiledObject root, JAXXCompiler compiler, JavaFile javaFile, String packageName, String className) throws ClassNotFoundException { + + //TODO : move this to jaxx-compiler-swing generator + if (ClassDescriptorLoader.getClassDescriptor(Application.class.getName()).isAssignableFrom(root.getObjectClass()) && !compiler.isMainDeclared()) { + // TODO: check for existing main method first + javaFile.addMethod(JavaMethod.newMethod(Modifier.PUBLIC | Modifier.STATIC, "void", "main", + "SwingUtilities.invokeLater(new Runnable() { public void run() { new " + className + "().setVisible(true); } });", + new JavaArgument("String[]", "arg"))); + } + } +} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/generators/ValidatorGenerator.java b/jaxx-compiler/src/main/java/jaxx/compiler/generators/ValidatorGenerator.java new file mode 100644 index 0000000..0f8e3ec --- /dev/null +++ b/jaxx-compiler/src/main/java/jaxx/compiler/generators/ValidatorGenerator.java @@ -0,0 +1,88 @@ +package jaxx.compiler.generators; + +import jaxx.compiler.*; +import jaxx.compiler.CompiledObject.ChildRef; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorLoader; +import jaxx.compiler.tags.validator.BeanValidatorHandler; +import jaxx.compiler.tags.validator.BeanValidatorHandler.CompiledBeanValidator; +import jaxx.compiler.types.TypeManager; + +import java.util.List; +import jaxx.runtime.SwingUtil; + +/** @author chemit */ +public class ValidatorGenerator implements Generator { + + protected static final JavaField VALIDATOR_IDS_FIELD = JavaField.newField(java.lang.reflect.Modifier.PROTECTED, + "java.util.List<String>", "validatorIds", "new ArrayList<String>()"); + + @Override + public void finalizeCompiler(CompiledObject root, JAXXCompiler compiler, JavaFile javaFile, String packageName, String className) { + + if (!BeanValidatorHandler.hasValidator(compiler)) { + return; + } + + for (CompiledObject object : compiler.getObjects().values()) { + List<ChildRef> childs = object.getChilds(); + if (childs == null || childs.isEmpty()) { + continue; + } + for (ChildRef child : childs) { + String javaCode = child.getChildJavaCode(); + // some validators are defined on this object + boolean found = BeanValidatorHandler.isComponentUsedByValidator(compiler, child.getChild().getId()); + if (found) { + // box the child component in a JxLayer + child.setChildJavaCode(SwingUtil.class.getName() + ".boxComponentWithJxLayer(" + javaCode + ")"); + } + } + } + // register validator + for (CompiledBeanValidator validator : BeanValidatorHandler.getValidators(compiler)) { + String id = TypeManager.getJavaCode(validator.getId()); + compiler.appendLateInitializer("validatorIds.add(" + id + ");"); + compiler.appendLateInitializer(JAXXCompiler.getLineSeparator()); + compiler.appendLateInitializer("getValidator(" + id + ").installUIs();"); + compiler.appendLateInitializer(JAXXCompiler.getLineSeparator()); + compiler.appendLateInitializer("getValidator(" + id + ").reloadBean();"); + //compiler.appendLateInitializer("getValidator(" + id + ").validate();"); + compiler.appendLateInitializer(JAXXCompiler.getLineSeparator()); + } + compiler.appendLateInitializer("validatorIds = java.util.Collections.unmodifiableList(validatorIds);"); + compiler.appendLateInitializer(JAXXCompiler.getLineSeparator()); + } + + @Override + public void prepareJavaFile(CompiledObject root, JAXXCompiler compiler, JavaFile javaFile, String packageName, String className) throws ClassNotFoundException { + if (!BeanValidatorHandler.hasValidator(compiler)) { + return; + } + Class<?> validatorClass = compiler.getConfiguration().getValidatorClass(); + String validatorFQN = validatorClass.getName(); + javaFile.addImport(validatorFQN); + + //TODO use the specific JAXXValidator interface (swing, gwt,...) + Class<?> validatorInterface = jaxx.runtime.JAXXValidator.class; + + if (javaFile.isSuperclassIsJAXXObject()) { + ClassDescriptor superClass = ClassDescriptorLoader.getClassDescriptor(javaFile.getSuperClass()); + boolean parentIsValidator = ClassDescriptorLoader.getClassDescriptor(validatorInterface).isAssignableFrom(superClass); + + if (parentIsValidator) { + // nothing to generate (use the parent directly) + return; + } + } + + // add JAXXValidator interface + javaFile.addInterface(JAXXCompiler.getCanonicalName(validatorInterface)); + + // implements JAXXValidator + javaFile.addField(VALIDATOR_IDS_FIELD); + javaFile.addMethod(JavaMethod.newMethod(java.lang.reflect.Modifier.PUBLIC, validatorFQN + "<?>", "getValidator", + "return (" + validatorFQN + ") (validatorIds.contains(validatorId) ? getObjectById(validatorId) : null);", + new JavaArgument("String", "validatorId"))); + } +} -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.