Author: tchemit Date: 2011-02-16 22:21:44 +0100 (Wed, 16 Feb 2011) New Revision: 2220 Url: http://nuiton.org/repositories/revision/jaxx/2220 Log: Evolution #1344: Improve DefaultFinalizer code Modified: trunk/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/DefaultFinalizer.java Modified: trunk/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/DefaultFinalizer.java =================================================================== --- trunk/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/DefaultFinalizer.java 2011-02-16 21:18:47 UTC (rev 2219) +++ trunk/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/DefaultFinalizer.java 2011-02-16 21:21:44 UTC (rev 2220) @@ -42,7 +42,6 @@ import jaxx.compiler.java.JavaMethod; import jaxx.compiler.reflect.ClassDescriptor; import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.reflect.FieldDescriptor; import jaxx.compiler.reflect.MethodDescriptor; import jaxx.compiler.types.TypeManager; import jaxx.runtime.Base64Coder; @@ -51,6 +50,7 @@ import jaxx.runtime.JAXXObject; import jaxx.runtime.JAXXObjectDescriptor; import jaxx.runtime.JAXXUtil; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -529,126 +529,83 @@ String packageName, String className) throws ClassNotFoundException { - String jaxxContextImplementorClass = - compiler.getConfiguration().getJaxxContextClass().getName(); - boolean superclassIsJAXXObject = javaFile.isSuperclassIsJAXXObject(); + // add logger support if required + addLoggerSupport(compiler, javaFile, className); - // add logger support - if (compiler.getConfiguration().isAddLogger()) { + // add JAXXObject support if required + addJAXXObjectSupport(compiler, root, javaFile); - javaFile.addImport(LogFactory.class); + addSimpleField(javaFile, SERIAL_VERSION_UID_FIELD); + addSimpleField(javaFile, ALL_COMPONENTS_CREATED_FIELD); - javaFile.addSimpleField(newField( - PRIVATE | STATIC | FINAL, - Log.class.getName(), - "log", - false, - "LogFactory.getLog(" + className + ".class)") - ); - } + addJAXXObjectDescriptorField(compiler, javaFile); + addMethod(javaFile, GET_JAXX_OBJECT_DESCRIPTOR_METHOD); - if (!superclassIsJAXXObject) { + addPreviousValuesField(compiler, javaFile, root); - // add JAXXObject support - addField(javaFile, OBJECT_MAP_FIELD); - addSimpleField(javaFile, BINDING_SOURCES_FIELD); - addSimpleField(javaFile, ACTIVE_BINDINGS_FIELD); - addSimpleField(javaFile, BINDINGS_FIELD); - javaFile.addMethod(GET_OBJECT_BY_ID_METHOD); - javaFile.addMethod(REGISTER_DATA_BINDING_METHOD); - javaFile.addMethod(GET_DATA_BINDING_METHOD); + addConstructors(compiler, javaFile, className); - javaFile.addMethod(createApplyDataBindingMethod()); - javaFile.addMethod(createProcessDataBindingMethod()); - javaFile.addMethod(createRemoveDataBindingMethod()); + DataBinding[] bindings = compiler.getBindingHelper().getDataBindings(); - // JAXXContext + addInitializerMethod(compiler, javaFile, bindings.length); - String type = - javaFile.getImportManager().getType(jaxxContextImplementorClass); + javaFile.addBodyCode(compiler.getBodyCode().toString()); - javaFile.addField(newField( - PROTECTED | FINAL, - JAXXContext.class.getName(), - FIELD_NAME_DELEGATE_CONTEXT, - true, - "new " + type + "()") - ); + addDataBindings(compiler, javaFile, bindings); - javaFile.addImport(Container.class); + addCompleteSetupMethod(compiler, javaFile); - 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); + addEventHandlers(compiler, javaFile); + } - // PropertyChangeSupport - addPropertyChangeSupport(root, javaFile); + protected void addDataBindings(JAXXCompiler compiler, + JavaFile javaFile, + DataBinding[] bindings) { - // DataBinding - javaFile.addMethod(PROCESS_DATA_BINDING_METHOD); - } else { + if (bindings.length < 1) { + // no data bindings + return; + } - //FIXME tchemit 2011-01-30 : We should not add it (if user want to use it in script it must add the correct import - // Will be removed in version 3.0 with strict imports features - javaFile.addImport(JAXXContext.class); + // create the $registerDefaultBindings method + + for (JAXXBindingWriter<?> writer : bindingWriters) { + writer.reset(); } + addRegisteredDefaultBindingsMethod(compiler, javaFile); - addSimpleField(javaFile, SERIAL_VERSION_UID_FIELD); - addSimpleField(javaFile, ALL_COMPONENTS_CREATED_FIELD); - boolean overrideContextInitialized = false; - FieldDescriptor[] scriptFields = compiler.getScriptFields(); - for (FieldDescriptor f : scriptFields) { - if (FIELD_NAME_CONTEXT_INITIALIZED.equals(f.getName())) { - overrideContextInitialized = true; - break; + // add import on each type of JAXXBinding used + + for (JAXXBindingWriter<?> writer : bindingWriters) { + if (writer.isUsed()) { + compiler.getJavaFile().addImport(writer.getType()); } } - if (!overrideContextInitialized) { - //addSimpleField(javaFile, CONTEXT_INITIALIZED); - } - JavaField descriptorField = - createJAXXObjectDescriptorField(compiler, javaFile); - javaFile.addSimpleField(descriptorField); - if (compiler.getStylesheet() != null) { - boolean needField = true; - if (superclassIsJAXXObject) { - // check alreay exists on parent - ClassDescriptor superclass = root.getObjectClass(); - if (log.isDebugEnabled()) { - log.debug("superclass : " + superclass); - } - JAXXCompiler parentCompiler = - compiler.getEngine().getJAXXCompiler( - superclass.getName() - ); + // for each binding declare the constant Id - if (parentCompiler != null) { - needField = parentCompiler.getStylesheet() == null; - } else { - try { - superclass.getDeclaredFieldDescriptor( - PREVIOUS_VALUES_FIELD.getName()); - needField = false; - } catch (NoSuchFieldException ex) { - // field not found - } - } - if (needField && log.isDebugEnabled()) { - log.debug("no " + PREVIOUS_VALUES_FIELD.getName() + - " field in super class"); - } - } - if (needField) { - addSimpleField(javaFile, PREVIOUS_VALUES_FIELD); - } + for (DataBinding binding : bindings) { + + String constantId = binding.getConstantId(); + + // add the data binding constant Id + + compiler.addSimpleField(newField( + (constantId.startsWith("BINDING_$") ? PRIVATE : PUBLIC) | FINAL | STATIC, + TYPE_STRING, + constantId, + false, + TypeManager.getJavaCode(binding.getRealId())) + ); } + } + protected void addConstructors(JAXXCompiler compiler, + JavaFile javaFile, + String className) { + + boolean superclassIsJAXXObject = javaFile.isSuperclassIsJAXXObject(); + //TC 20090228 - only generate constructors if not done in scripts boolean constructorDetected = false; MethodDescriptor[] methods = compiler.getScriptMethods(); @@ -679,56 +636,83 @@ ); javaFile.addMethod(constructor); } + } - DataBinding[] bindings = compiler.getBindingHelper().getDataBindings(); + protected void addJAXXObjectSupport(JAXXCompiler compiler, + CompiledObject root, + JavaFile javaFile) { - int nbBindings = bindings.length; - boolean hasDataBindings = nbBindings > 0; + String jaxxContextImplementorClass = + compiler.getConfiguration().getJaxxContextClass().getName(); - javaFile.addMethod(createInitializer(compiler, nbBindings, overrideContextInitialized)); + boolean superclassIsJAXXObject = javaFile.isSuperclassIsJAXXObject(); - addMethod(javaFile, GET_JAXX_OBJECT_DESCRIPTOR_METHOD); + if (superclassIsJAXXObject) { - javaFile.addBodyCode(compiler.getBodyCode().toString()); + //FIXME tchemit 2011-01-30 : We should not add it (if user want to use it in script it must add the correct import + // Will be removed in version 3.0 with strict imports features + javaFile.addImport(JAXXContext.class); - if (hasDataBindings) { + } else { - // create the $registerDefaultBindings method + // add JAXXObject support + addField(javaFile, OBJECT_MAP_FIELD); + addSimpleField(javaFile, BINDING_SOURCES_FIELD); + addSimpleField(javaFile, ACTIVE_BINDINGS_FIELD); + addSimpleField(javaFile, BINDINGS_FIELD); + javaFile.addMethod(GET_OBJECT_BY_ID_METHOD); + javaFile.addMethod(REGISTER_DATA_BINDING_METHOD); + javaFile.addMethod(GET_DATA_BINDING_METHOD); - for (JAXXBindingWriter<?> writer : bindingWriters) { - writer.reset(); - } - javaFile.addMethod(createRegisterDefaultBindingsMethod(compiler)); + javaFile.addMethod(createApplyDataBindingMethod()); + javaFile.addMethod(createProcessDataBindingMethod()); + javaFile.addMethod(createRemoveDataBindingMethod()); - // add import on each type of JAXXBinding used + // JAXXContext - for (JAXXBindingWriter<?> writer : bindingWriters) { - if (writer.isUsed()) { - compiler.getJavaFile().addImport(writer.getType()); - } - } + String type = + javaFile.getImportManager().getType(jaxxContextImplementorClass); - // for each binding declare the constant Id + javaFile.addField(newField( + PROTECTED | FINAL, + JAXXContext.class.getName(), + FIELD_NAME_DELEGATE_CONTEXT, + true, + "new " + type + "()") + ); - for (DataBinding binding : bindings) { + javaFile.addImport(Container.class); - String constantId = binding.getConstantId(); + 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); - // add the data binding constant Id + // PropertyChangeSupport + addPropertyChangeSupport(root, javaFile); - compiler.addSimpleField(newField( - (constantId.startsWith("BINDING_$") ? PRIVATE : PUBLIC) | FINAL | STATIC, - TYPE_STRING, - constantId, - false, - TypeManager.getJavaCode(binding.getRealId())) - ); - } + // DataBinding + javaFile.addMethod(PROCESS_DATA_BINDING_METHOD); } + } - javaFile.addMethod(createCompleteSetupMethod(compiler, javaFile)); + protected void addLoggerSupport(JAXXCompiler compiler, JavaFile javaFile, String className) { + if (compiler.getConfiguration().isAddLogger()) { - addEventHandlers(compiler, javaFile); + javaFile.addImport(LogFactory.class); + + javaFile.addSimpleField(newField( + PRIVATE | STATIC | FINAL, + Log.class.getName(), + "log", + false, + "LogFactory.getLog(" + className + ".class)") + ); + } } protected final JAXXBindingWriter<?>[] bindingWriters = new @@ -736,41 +720,12 @@ new DefaultJAXXBindingWriter() }; - protected JavaMethod createRegisterDefaultBindingsMethod(JAXXCompiler compiler) { - DataBinding[] bindings = compiler.getBindingHelper().getDataBindings(); - StringBuilder initCode = new StringBuilder(); - - String eol = JAXXCompiler.getLineSeparator(); - JavaFileGenerator generator = new JavaFileGenerator(eol, true); - //TODO use optimized writer for simple cases - - initCode.append("// register "); - initCode.append(bindings.length); - initCode.append(" data bindings"); - initCode.append(eol); - - for (DataBinding binding : bindings) { - - for (JAXXBindingWriter<?> writer : bindingWriters) { - if (writer.accept(binding)) { - writer.write(binding, generator, initCode); - break; - } - } - } - return newMethod(PRIVATE, - TYPE_VOID, - METHOD_NAME_$REGISTER_DEFAULT_BINDINGS, - initCode.toString(), - false - ); - } - /*---------------------------------------------------------------------------------*/ /*-- Create fields ----------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/ - protected JavaField createJAXXObjectDescriptorField(JAXXCompiler compiler, - JavaFile javaFile) { + protected JavaField addJAXXObjectDescriptorField(JAXXCompiler compiler, + JavaFile javaFile) { + JavaField field; try { JAXXObjectDescriptor descriptor = compiler.getJAXXObjectDescriptor(); String data = Base64Coder.serialize(descriptor, true); @@ -788,12 +743,13 @@ 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 newField(PRIVATE | STATIC | FINAL, - TYPE_STRING, - FIELD_NAME_$JAXX_OBJECT_DESCRIPTOR, - false, - TypeManager.getJavaCode(data) + field = newField(PRIVATE | STATIC | FINAL, + TYPE_STRING, + FIELD_NAME_$JAXX_OBJECT_DESCRIPTOR, + false, + TypeManager.getJavaCode(data) ); + } else { StringBuffer initializer = new StringBuffer(); for (int i = 0; i < data.length(); i += sizeLimit) { @@ -812,18 +768,60 @@ initializer.append(name); initializer.append(")"); } - return newField(PRIVATE | STATIC | FINAL, - TYPE_STRING, - FIELD_NAME_$JAXX_OBJECT_DESCRIPTOR, - false, - initializer.toString() + field = newField(PRIVATE | STATIC | FINAL, + TYPE_STRING, + FIELD_NAME_$JAXX_OBJECT_DESCRIPTOR, + false, + initializer.toString() ); } } catch (IOException e) { throw new RuntimeException("Internal error: can't-happen error", e); } + javaFile.addSimpleField(field); + return field; } + protected void addPreviousValuesField(JAXXCompiler compiler, + JavaFile javaFile, CompiledObject root) { + + boolean superclassIsJAXXObject = javaFile.isSuperclassIsJAXXObject(); + + if (compiler.getStylesheet() != null) { + boolean needField = true; + if (superclassIsJAXXObject) { + // check alreay exists on parent + ClassDescriptor superclass = root.getObjectClass(); + if (log.isDebugEnabled()) { + log.debug("superclass : " + superclass); + } + JAXXCompiler parentCompiler = + compiler.getEngine().getJAXXCompiler( + superclass.getName() + ); + + if (parentCompiler != null) { + needField = parentCompiler.getStylesheet() == null; + } else { + try { + superclass.getDeclaredFieldDescriptor( + PREVIOUS_VALUES_FIELD.getName()); + needField = false; + } catch (NoSuchFieldException ex) { + // field not found + } + } + if (needField && log.isDebugEnabled()) { + log.debug("no " + PREVIOUS_VALUES_FIELD.getName() + + " field in super class"); + } + } + if (needField) { + addSimpleField(javaFile, PREVIOUS_VALUES_FIELD); + } + } + } + /*---------------------------------------------------------------------------------*/ /*-- Create methods ---------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/ @@ -856,9 +854,6 @@ // 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.addImport(PropertyChangeListener.class); -// javaFile.addImport(PropertyChangeSupport.class); addField(javaFile, PROPERTY_CHANGE_SUPPORT_FIELD); javaFile.addMethod(GET_PROPERTY_CHANGE_SUPPORT_METHOD); @@ -870,6 +865,39 @@ } } + protected JavaMethod addRegisteredDefaultBindingsMethod(JAXXCompiler compiler, + JavaFile javaFile) { + DataBinding[] bindings = compiler.getBindingHelper().getDataBindings(); + StringBuilder initCode = new StringBuilder(); + + String eol = JAXXCompiler.getLineSeparator(); + JavaFileGenerator generator = new JavaFileGenerator(eol, true); + //TODO use optimized writer for simple cases + + initCode.append("// register "); + initCode.append(bindings.length); + initCode.append(" data bindings"); + initCode.append(eol); + + for (DataBinding binding : bindings) { + + for (JAXXBindingWriter<?> writer : bindingWriters) { + if (writer.accept(binding)) { + writer.write(binding, generator, initCode); + break; + } + } + } + JavaMethod method = newMethod(PRIVATE, + TYPE_VOID, + METHOD_NAME_$REGISTER_DEFAULT_BINDINGS, + initCode.toString(), + false + ); + javaFile.addMethod(method); + return method; + } + protected void addEventHandlers(JAXXCompiler compiler, JavaFile javaFile) { @@ -946,25 +974,50 @@ protected JavaMethod createConstructorWithInitialContext(JAXXCompiler compiler, String className, boolean superclassIsJAXXObject) throws CompilerException { - StringBuffer code = new StringBuffer(); + StringBuilder code = new StringBuilder(); String constructorParams = compiler.getRootObject().getConstructorParams(); String eol = JAXXCompiler.getLineSeparator(); + String realConstructorParams = ""; + if (superclassIsJAXXObject) { + realConstructorParams = PARAMETER_NAME_PARENT_CONTEXT; + } if (constructorParams != null) { + if (superclassIsJAXXObject) { - //TODO-TC20091127 This MUST be a convention in JAXX : all specialized constructor must a second - //TODO constructor with extra first parameter as parentContext - constructorParams = PARAMETER_NAME_PARENT_CONTEXT + ", " + constructorParams; + realConstructorParams += " ,"; } + realConstructorParams += constructorParams; + } + + realConstructorParams = realConstructorParams.trim(); + + if (StringUtils.isNotEmpty(realConstructorParams)) { + + // add a super invocation code.append(" super("); - code.append(constructorParams); + code.append(realConstructorParams); code.append(");"); code.append(eol); - } else { - if (superclassIsJAXXObject) { - code.append(" super(" + PARAMETER_NAME_PARENT_CONTEXT + ");"); - code.append(eol); - } } + + +// if (constructorParams != null) { +// if (superclassIsJAXXObject) { +// //TODO-TC20091127 This MUST be a convention in JAXX : all specialized constructor must a second +// //TODO constructor with extra first parameter as parentContext +// constructorParams = PARAMETER_NAME_PARENT_CONTEXT + ", " + constructorParams; +// } +// code.append(" super("); +// code.append(constructorParams); +// code.append(");"); +// code.append(eol); +// } else { +// if (superclassIsJAXXObject) { +// code.append(" super(" + PARAMETER_NAME_PARENT_CONTEXT); +// code.append(");"); +// code.append(eol); +// } +// } if (!superclassIsJAXXObject) { String prefix = compiler.getImportManager().getType(JAXXUtil.class); code.append(prefix); @@ -986,9 +1039,13 @@ ); } - public JavaMethod createInitializer(JAXXCompiler compiler, - int nbBindings, - boolean overrideContextInitialized) throws CompilerException { + public JavaMethod addInitializerMethod(JAXXCompiler compiler, + JavaFile javaFile, + int nbBindings) throws CompilerException { + + boolean overrideContextInitialized = + compiler.containsScriptField(FIELD_NAME_CONTEXT_INITIALIZED); + String eol = JAXXCompiler.getLineSeparator(); StringBuffer code = new StringBuffer(); CompiledObject root = compiler.getRootObject(); @@ -1046,16 +1103,18 @@ } code.append(METHOD_NAME_$COMPLETE_SETUP + "();"); code.append(eol); - return JavaElementFactory.newMethod(PRIVATE, - TYPE_VOID, - METHOD_NAME_$INITIALIZE, - code.toString(), - false + JavaMethod method = JavaElementFactory.newMethod(PRIVATE, + TYPE_VOID, + METHOD_NAME_$INITIALIZE, + code.toString(), + false ); + javaFile.addMethod(method); + return method; } - protected JavaMethod createCompleteSetupMethod(JAXXCompiler compiler, - JavaFile javaFile) { + protected JavaMethod addCompleteSetupMethod(JAXXCompiler compiler, + JavaFile javaFile) { StringBuffer code = new StringBuffer(); code.append(FIELD_NAME_ALL_COMPONENTS_CREATED + " = true;"); String eol = JAXXCompiler.getLineSeparator(); @@ -1083,12 +1142,14 @@ if (method != null) { code.append(METHOD_NAME_$AFTER_COMPLETE_SETUP + "();").append(eol); } - return JavaElementFactory.newMethod(PRIVATE, - TYPE_VOID, - METHOD_NAME_$COMPLETE_SETUP, - code.toString(), - false + JavaMethod javaMethod = JavaElementFactory.newMethod(PRIVATE, + TYPE_VOID, + METHOD_NAME_$COMPLETE_SETUP, + code.toString(), + false ); + javaFile.addMethod(javaMethod); + return javaMethod; } protected String createInitBindingsCode(JAXXCompiler compiler) {