package org.springframework.roo.addon.gwt; import static org.springframework.roo.model.JavaType.LONG_OBJECT; import static org.springframework.roo.model.JavaType.OBJECT; import static org.springframework.roo.model.JdkJavaType.BIG_DECIMAL; import static org.springframework.roo.model.JdkJavaType.BIG_INTEGER; import static org.springframework.roo.model.JdkJavaType.DATE; import static org.springframework.roo.model.JpaJavaType.EMBEDDABLE; import static org.springframework.roo.model.SpringJavaType.DATE_TIME_FORMAT; import static org.springframework.roo.model.SpringJavaType.NUMBER_FORMAT; import java.util.List; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; import org.springframework.roo.classpath.PhysicalTypeCategory; import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails; import org.springframework.roo.classpath.details.MemberFindingUtils; import org.springframework.roo.classpath.details.annotations.AnnotationAttributeValue; import org.springframework.roo.classpath.details.annotations.AnnotationMetadata; import org.springframework.roo.model.JavaPackage; import org.springframework.roo.model.JavaSymbolName; import org.springframework.roo.model.JavaType; public class GwtProxyProperty { public static String getProxyRendererType( final JavaPackage topLevelPackage, final JavaType javaType) { return GwtType.EDIT_RENDERER.getPath().packageName(topLevelPackage) + "." + javaType.getSimpleTypeName() + "Renderer"; } private List<AnnotationMetadata> annotations; private String getter; private String name; private final ClassOrInterfaceTypeDetails ptmd; private final JavaPackage topLevelPackage; private final JavaType type; public GwtProxyProperty(final JavaPackage topLevelPackage, final ClassOrInterfaceTypeDetails ptmd, final JavaType type) { Validate.notNull(type, "Type required"); this.topLevelPackage = topLevelPackage; this.ptmd = ptmd; this.type = type; } public GwtProxyProperty(final JavaPackage topLevelPackage, final ClassOrInterfaceTypeDetails ptmd, final JavaType type, final String name, final List<AnnotationMetadata> annotations, final String getter) { this(topLevelPackage, ptmd, type); this.name = name; this.annotations = annotations; this.getter = getter; } public String forEditView() { String initializer = ""; if (isBoolean()) { initializer = " = " + getCheckboxSubtype(); } if (isEnum() && !isCollection()) { initializer = String.format(" = new ValueListBox<%s>(%s)", type.getFullyQualifiedTypeName(), getRenderer()); } if (isProxy()) { initializer = String .format(" = new ValueListBox<%1$s>(%2$s.instance(), new com.google.web.bindery.requestfactory.gwt.ui.client.EntityProxyKeyProvider<%1$s>())", type.getFullyQualifiedTypeName(), getProxyRendererType()); } return String.format("@UiField %s %s %s", getEditor(), getName(), initializer); } public String forMobileListView(final String rendererName) { return new StringBuilder("if (value.").append(getGetter()) .append("() != null) {\n\t\t\t\tsb.appendEscaped(") .append(rendererName).append(".render(value.") .append(getGetter()).append("()));\n\t\t\t}").toString(); } public String getBinder() { if (type.equals(JavaType.DOUBLE_OBJECT)) { return "g:DoubleBox"; } if (type.equals(LONG_OBJECT)) { return "g:LongBox"; } if (type.equals(JavaType.INT_OBJECT)) { return "g:IntegerBox"; } if (type.equals(JavaType.FLOAT_OBJECT)) { return "r:FloatBox"; } if (type.equals(JavaType.BYTE_OBJECT)) { return "r:ByteBox"; } if (type.equals(JavaType.SHORT_OBJECT)) { return "r:ShortBox"; } if (type.equals(JavaType.CHAR_OBJECT)) { return "r:CharBox"; } if (type.equals(BIG_DECIMAL)) { return "r:BigDecimalBox"; } return isCollection() ? "a:" + getSetEditor() : isDate() ? "d:DateBox" : isBoolean() ? "g:CheckBox" : isString() ? "g:TextBox" : "g:ValueListBox"; } public String getCheckboxSubtype() { // TODO: Ugly hack, fix in M4 return "new CheckBox() { public void setValue(Boolean value) { super.setValue(value == null ? Boolean.FALSE : value); } }"; } public String getCollectionRenderer() { JavaType arg = OBJECT; if (type.getParameters().size() > 0) { arg = type.getParameters().get(0); } return GwtPath.SCAFFOLD_PLACE.packageName(topLevelPackage) + ".CollectionRenderer.of(" + new GwtProxyProperty(topLevelPackage, ptmd, arg) .getRenderer() + ")"; } private String getDateTimeFormat() { String format = "DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_SHORT)"; if (annotations == null || annotations.isEmpty()) { return format; } String style = ""; final AnnotationMetadata annotation = MemberFindingUtils .getAnnotationOfType(annotations, DATE_TIME_FORMAT); if (annotation != null) { final AnnotationAttributeValue<?> attr = annotation .getAttribute(new JavaSymbolName("style")); if (attr != null) { style = (String) attr.getValue(); } } if (StringUtils.isNotBlank(style)) { if (style.equals("S")) { format = "DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_TIME_SHORT)"; } else if (style.equals("M")) { format = "DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_TIME_MEDIUM)"; } else if (style.equals("F")) { format = "DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_TIME_FULL)"; } else if (style.equals("S-")) { format = "DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_SHORT)"; } else if (style.equals("M-")) { format = "DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_MEDIUM)"; } else if (style.equals("F-")) { format = "DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_FULL)"; } } return format; } private String getEditor() { if (type.equals(JavaType.DOUBLE_OBJECT)) { return "DoubleBox"; } if (type.equals(LONG_OBJECT)) { return "LongBox"; } if (type.equals(JavaType.INT_OBJECT)) { return "IntegerBox"; } if (type.equals(JavaType.FLOAT_OBJECT)) { return "FloatBox"; } if (type.equals(JavaType.BYTE_OBJECT)) { return "ByteBox"; } if (type.equals(JavaType.SHORT_OBJECT)) { return "ShortBox"; } if (type.equals(JavaType.CHAR_OBJECT)) { return "CharBox"; } if (type.equals(BIG_DECIMAL)) { return "BigDecimalBox"; } if (isBoolean()) { return "(provided = true) CheckBox"; } return isCollection() ? getSetEditor() : isDate() ? "DateBox" : isString() ? "TextBox" : "(provided = true) ValueListBox<" + type.getFullyQualifiedTypeName() + ">"; } public String getFormatter() { if (isCollectionOfProxy()) { return getCollectionRenderer() + ".render"; } else if (isDate()) { return getDateTimeFormat() + ".format"; } else if (type.equals(JavaType.INT_OBJECT) || type.equals(JavaType.FLOAT_OBJECT) || type.equals(JavaType.DOUBLE_OBJECT) || type.equals(BIG_INTEGER) || type.equals(BIG_DECIMAL)) { String formatter = "String.valueOf"; if (annotations == null || annotations.isEmpty()) { return formatter; } final AnnotationMetadata annotation = MemberFindingUtils .getAnnotationOfType(annotations, NUMBER_FORMAT); if (annotation != null) { final AnnotationAttributeValue<?> attr = annotation .getAttribute(new JavaSymbolName("style")); if (attr != null) { final String style = attr.getValue().toString(); if ("org.springframework.format.annotation.NumberFormat.Style.CURRENCY" .equals(style)) { formatter = "NumberFormat.getCurrencyFormat().format"; } else if ("org.springframework.format.annotation.NumberFormat.Style.PERCENT" .equals(style)) { formatter = "NumberFormat.getPercentFormat().format"; } else { formatter = "NumberFormat.getDecimalFormat().format"; } } else { formatter = "NumberFormat.getDecimalFormat().format"; } } return formatter; } else if (isProxy()) { return getProxyRendererType() + ".instance().render"; } else { return "String.valueOf"; } } public String getGetter() { return getter; } public String getName() { return name; } public JavaType getPropertyType() { return type; } String getProxyRendererType() { return getProxyRendererType(topLevelPackage, isCollectionOfProxy() ? type.getParameters().get(0) : type); } public String getReadableName() { return new JavaSymbolName(name).getReadableSymbolName(); } public String getRenderer() { return isCollection() ? getCollectionRenderer() : isDate() ? "new DateTimeFormatRenderer(" + getDateTimeFormat() + ")" : isPrimitive() || isEnum() || isEmbeddable() || type.equals(OBJECT) ? "new AbstractRenderer<" + getType() + ">() {\n public String render(" + getType() + " obj) {\n return obj == null ? \"\" : String.valueOf(obj);\n }\n }" : getProxyRendererType() + ".instance()"; } private String getSetEditor() { String typeName = OBJECT.getFullyQualifiedTypeName(); if (type.getParameters().size() > 0) { typeName = type.getParameters().get(0).getSimpleTypeName(); } if (typeName.endsWith(GwtType.PROXY.getSuffix())) { typeName = typeName.substring(0, typeName.length() - GwtType.PROXY.getSuffix().length()); } return typeName + (type.getSimpleTypeName().equals("Set") ? GwtType.SET_EDITOR .getSuffix() : GwtType.LIST_EDITOR.getSuffix()); } public JavaType getSetEditorType() { return new JavaType(GwtType.SET_EDITOR.getPath().packageName( topLevelPackage) + "." + getSetEditor()); } public String getSetValuePickerMethod() { return "\tpublic void " + getSetValuePickerMethodName() + "(Collection<" + (isCollection() ? type.getParameters().get(0) .getSimpleTypeName() : type.getSimpleTypeName()) + "> values) {\n" + "\t\t" + getName() + ".setAcceptableValues(values);\n" + "\t}\n"; } String getSetValuePickerMethodName() { return "set" + StringUtils.capitalize(getName()) + "PickerValues"; } public String getType() { return type.getFullyQualifiedTypeName(); } public JavaType getValueType() { if (isCollection()) { return type.getParameters().get(0); } return type; } public boolean isBoolean() { return type.equals(JavaType.BOOLEAN_OBJECT); } public boolean isCollection() { return type.isCommonCollectionType(); } public boolean isCollectionOfProxy() { return type.getParameters().size() != 0 && isCollection() && new GwtProxyProperty(topLevelPackage, ptmd, type .getParameters().get(0)).isProxy(); } public boolean isDate() { return type.equals(DATE); } public boolean isEmbeddable() { if (ptmd != null) { final List<AnnotationMetadata> annotations = ptmd.getAnnotations(); for (final AnnotationMetadata annotation : annotations) { if (annotation.getAnnotationType().equals(EMBEDDABLE)) { return true; } } } return false; } boolean isEnum() { return ptmd != null && ptmd.getPhysicalTypeCategory() == PhysicalTypeCategory.ENUMERATION; } public boolean isPrimitive() { return type.isPrimitive() || isDate() || isString() || isBoolean() || type.equals(JavaType.DOUBLE_OBJECT) || type.equals(LONG_OBJECT) || type.equals(JavaType.INT_OBJECT) || type.equals(JavaType.FLOAT_OBJECT) || type.equals(JavaType.BYTE_OBJECT) || type.equals(JavaType.SHORT_OBJECT) || type.equals(JavaType.CHAR_OBJECT) || type.equals(BIG_DECIMAL); } public boolean isProxy() { return ptmd != null && !isDate() && !isString() && !isPrimitive() && !isEnum() && !isCollection() && !isEmbeddable() && !type.equals(OBJECT); } public boolean isString() { return type.equals(JavaType.STRING); } }