From f3239cda1409550047a435c71fa294e4bdebf159 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Tue, 21 Feb 2012 18:23:24 +0200 Subject: [PATCH] #8304 Generator for Serializers --- .../gwt/client/ComponentState_Serializer.java | 28 --- .../client/ui/VButtonState_Serializer.java | 34 ---- .../widgetsetutils/SerializerGenerator.java | 161 ++++++++++++++++++ .../SerializerMapGenerator.java | 11 +- 4 files changed, 171 insertions(+), 63 deletions(-) delete mode 100644 src/com/vaadin/terminal/gwt/client/ComponentState_Serializer.java delete mode 100644 src/com/vaadin/terminal/gwt/client/ui/VButtonState_Serializer.java create mode 100644 src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java diff --git a/src/com/vaadin/terminal/gwt/client/ComponentState_Serializer.java b/src/com/vaadin/terminal/gwt/client/ComponentState_Serializer.java deleted file mode 100644 index 075b7f9daa..0000000000 --- a/src/com/vaadin/terminal/gwt/client/ComponentState_Serializer.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.vaadin.terminal.gwt.client; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.json.client.JSONArray; -import com.google.gwt.json.client.JSONObject; -import com.vaadin.terminal.gwt.client.communication.JsonDecoder; -import com.vaadin.terminal.gwt.client.communication.VaadinSerializer; - -//TODO This should be autogenerated -public class ComponentState_Serializer implements VaadinSerializer { - - public ComponentState deserialize(JSONObject jsonValue, - VPaintableMap idMapper) { - ComponentState state = GWT.create(ComponentState.class); - - // For (Field f : fields) { - // state.setState((Map) - // JsonDecoder.convertMap(jsonValue, - // idMapper)); - JSONArray jsonHeight = (JSONArray) jsonValue.get("height"); - state.setHeight((String) JsonDecoder.convertValue(jsonHeight, idMapper)); - - JSONArray jsonWidth = (JSONArray) jsonValue.get("width"); - state.setWidth((String) JsonDecoder.convertValue(jsonWidth, idMapper)); - - return state; - } -} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VButtonState_Serializer.java b/src/com/vaadin/terminal/gwt/client/ui/VButtonState_Serializer.java deleted file mode 100644 index 31cb9ab70f..0000000000 --- a/src/com/vaadin/terminal/gwt/client/ui/VButtonState_Serializer.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.vaadin.terminal.gwt.client.ui; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.json.client.JSONArray; -import com.google.gwt.json.client.JSONObject; -import com.vaadin.terminal.gwt.client.VPaintableMap; -import com.vaadin.terminal.gwt.client.communication.JsonDecoder; -import com.vaadin.terminal.gwt.client.communication.VaadinSerializer; - -//TODO This should be autogenerated -public class VButtonState_Serializer implements VaadinSerializer { - - public VButtonState deserialize(JSONObject jsonValue, VPaintableMap idMapper) { - VButtonState state = GWT.create(VButtonState.class); - - JSONArray jsonHeight = (JSONArray) jsonValue.get("height"); - state.setHeight((String) JsonDecoder.convertValue(jsonHeight, idMapper)); - - JSONArray jsonWidth = (JSONArray) jsonValue.get("width"); - state.setWidth((String) JsonDecoder.convertValue(jsonWidth, idMapper)); - - JSONArray jsonDisableOnClick = (JSONArray) jsonValue - .get("disableOnClick"); - state.setDisableOnClick((Boolean) JsonDecoder.convertValue( - jsonDisableOnClick, idMapper)); - - JSONArray jsonClickShortcutKeyCode = (JSONArray) jsonValue - .get("clickShortcutKeyCode"); - state.setClickShortcutKeyCode((Integer) JsonDecoder.convertValue( - jsonClickShortcutKeyCode, idMapper)); - - return state; - } -} diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java new file mode 100644 index 0000000000..1cd156e303 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java @@ -0,0 +1,161 @@ +package com.vaadin.terminal.gwt.widgetsetutils; + +import java.io.PrintWriter; +import java.util.Date; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.core.ext.Generator; +import com.google.gwt.core.ext.GeneratorContext; +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.TreeLogger.Type; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JClassType; +import com.google.gwt.core.ext.typeinfo.JMethod; +import com.google.gwt.core.ext.typeinfo.JPrimitiveType; +import com.google.gwt.core.ext.typeinfo.JType; +import com.google.gwt.core.ext.typeinfo.TypeOracle; +import com.google.gwt.json.client.JSONArray; +import com.google.gwt.json.client.JSONObject; +import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; +import com.google.gwt.user.rebind.SourceWriter; +import com.vaadin.terminal.gwt.client.VPaintableMap; +import com.vaadin.terminal.gwt.client.communication.JsonDecoder; +import com.vaadin.terminal.gwt.client.communication.VaadinSerializer; + +public class SerializerGenerator extends Generator { + + private String packageName; + private String beanSerializerClassName; + + @Override + public String generate(TreeLogger logger, GeneratorContext context, + String beanTypeName) throws UnableToCompleteException { + String beanSerializerTypeName = beanTypeName + "_Serializer"; + try { + TypeOracle typeOracle = context.getTypeOracle(); + + // get classType and save instance variables + JClassType classType = typeOracle.getType(beanTypeName); + packageName = classType.getPackage().getName(); + beanSerializerClassName = classType.getSimpleSourceName() + + "_Serializer"; + // Generate class source code + generateClass(logger, context, beanTypeName, beanSerializerTypeName); + } catch (Exception e) { + logger.log(TreeLogger.ERROR, "SerializerGenerator failed for " + + beanTypeName, e); + } + // return the fully qualifed name of the class generated + return packageName + "." + beanSerializerClassName; + } + + /** + * Generate source code for WidgetMapImpl + * + * @param logger + * Logger object + * @param context + * Generator context + * @param typeName + */ + private void generateClass(TreeLogger logger, GeneratorContext context, + String beanTypeName, String beanSerializerTypeName) { + // get print writer that receives the source code + PrintWriter printWriter = null; + printWriter = context.tryCreate(logger, packageName, + beanSerializerClassName); + + // print writer if null, source code has ALREADY been generated + if (printWriter == null) { + return; + } + Date date = new Date(); + TypeOracle typeOracle = context.getTypeOracle(); + logger.log(Type.DEBUG, "Processing serializable type " + beanTypeName + + "..."); + + // init composer, set class properties, create source writer + ClassSourceFileComposerFactory composer = null; + composer = new ClassSourceFileComposerFactory(packageName, + beanSerializerClassName); + composer.addImport(GWT.class.getName()); + composer.addImport(JSONArray.class.getName()); + // composer.addImport(JSONObject.class.getName()); + // composer.addImport(VPaintableMap.class.getName()); + composer.addImport(JsonDecoder.class.getName()); + // composer.addImport(VaadinSerializer.class.getName()); + + composer.addImplementedInterface(VaadinSerializer.class.getName()); + + SourceWriter sourceWriter = composer.createSourceWriter(context, + printWriter); + sourceWriter.indent(); + + sourceWriter.println("public " + beanTypeName + " deserialize(" + + JSONObject.class.getName() + " jsonValue, " + + VPaintableMap.class.getName() + " idMapper) {"); + sourceWriter.indent(); + + // VButtonState state = GWT.create(VButtonState.class); + sourceWriter.println(beanTypeName + " state = GWT.create(" + + beanTypeName + ".class);"); + JClassType beanType = typeOracle.findType(beanTypeName); + for (JMethod method : beanType.getMethods()) { + // Process all setters that have corresponding fields + if (!method.isPublic() || method.isStatic() + || !method.getName().startsWith("set") + || method.getParameterTypes().length != 1) { + // Not setter, skip to next method + continue; + + } + String setterName = method.getName(); + String capitalizedFieldName = setterName.substring(3); + String fieldName = decapitalize(capitalizedFieldName); + JType setterParameterType = method.getParameterTypes()[0]; + + logger.log(Type.DEBUG, "* Processing field " + fieldName + " in " + + beanTypeName); + + String jsonFieldName = "json" + capitalizedFieldName; + // JSONArray jsonHeight = (JSONArray) jsonValue.get("height"); + sourceWriter.println("JSONArray " + jsonFieldName + + " = (JSONArray) jsonValue.get(\"" + fieldName + "\");"); + // state.setHeight((String) + // JsonDecoder.convertValue(jsonFieldValue,idMapper)); + + String fieldType; + JPrimitiveType primitiveType = setterParameterType.isPrimitive(); + if (primitiveType != null) { + // This is a primitive type -> must used the boxed type + fieldType = primitiveType.getQualifiedBoxedSourceName(); + } else { + fieldType = setterParameterType.getQualifiedSourceName(); + } + + sourceWriter.println("state." + setterName + "((" + fieldType + + ") JsonDecoder.convertValue(" + jsonFieldName + + ", idMapper));"); + } + + // return state; + sourceWriter.println("return state;"); + sourceWriter.println("}"); + sourceWriter.outdent(); + + // End of class + sourceWriter.println("}"); + sourceWriter.outdent(); + + // commit generated class + context.commit(logger, printWriter); + logger.log(Type.INFO, + "Done. (" + (new Date().getTime() - date.getTime()) / 1000 + + "seconds)"); + + } + + private String decapitalize(String name) { + return name.substring(0, 1).toLowerCase() + name.substring(1); + } +} diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerMapGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerMapGenerator.java index 651ae24b2d..2fabf8bd71 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerMapGenerator.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerMapGenerator.java @@ -34,8 +34,17 @@ public class SerializerMapGenerator extends Generator { className = classType.getSimpleSourceName() + "Impl"; // Generate class source code generateClass(logger, context); + + JClassType serializerType = typeOracle.findType(SharedState.class + .getName()); + JClassType[] serializerSubtypes = serializerType.getSubtypes(); + SerializerGenerator sg = new SerializerGenerator(); + for (JClassType type : serializerSubtypes) { + sg.generate(logger, context, type.getQualifiedSourceName()); + } } catch (Exception e) { - logger.log(TreeLogger.ERROR, "WidgetMap creation failed", e); + logger.log(TreeLogger.ERROR, + "SerializerMapGenerator creation failed", e); } // return the fully qualifed name of the class generated return packageName + "." + className; -- 2.39.5