/*
* Copyright 2011 cruxframework.org.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.cruxframework.crux.core.rebind.screen.binder;
import org.cruxframework.crux.core.client.Crux;
import org.cruxframework.crux.core.client.formatter.HasFormatter;
import org.cruxframework.crux.core.client.screen.views.Target;
import org.cruxframework.crux.core.client.screen.views.ViewBinder;
import org.cruxframework.crux.core.rebind.AbstractViewBindableProxyCreator;
import org.cruxframework.crux.core.rebind.CruxGeneratorException;
import org.cruxframework.crux.core.rebind.context.RebindContext;
import org.cruxframework.crux.core.utils.JClassUtils;
import com.google.gwt.core.client.GWT;
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.NotFoundException;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.IsWidget;
/**
* @author Thiago da Rosa de Bustamante
*
*/
public class ViewBinderProxyCreator extends AbstractViewBindableProxyCreator
{
private final JClassType viewBinderType;
private final JClassType stringType;
/**
* Constructor
* @param logger
* @param context
*/
public ViewBinderProxyCreator(RebindContext context, JClassType invokerIntf)
{
super(context, invokerIntf);
try
{
viewBinderType = invokerIntf.getOracle().getType(ViewBinder.class.getCanonicalName());
stringType = invokerIntf.getOracle().getType(String.class.getCanonicalName());
}
catch (NotFoundException e)
{
throw new CruxGeneratorException(e.getMessage(), e);
}
}
@Override
protected void generateProxyMethods(SourcePrinter srcWriter) throws CruxGeneratorException
{
super.generateProxyMethods(srcWriter);
generateViewGetterMethod(srcWriter);
}
@Override
protected void generateProxyFields(SourcePrinter srcWriter) throws CruxGeneratorException
{
super.generateProxyFields(srcWriter);
JMethod[] methods = baseIntf.getOverridableMethods();
for (JMethod method : methods)
{
String methodName = method.getName();
if (method.getName().startsWith("get"))
{
JClassType returnTypeClass = method.getReturnType().isClassOrInterface();
if (returnTypeClass != null && returnTypeClass.isAssignableTo(viewBinderType))
{
String sourceName = returnTypeClass.getParameterizedQualifiedSourceName();
srcWriter.println("private "+sourceName+" _"+methodName+" = GWT.create("+sourceName+".class);");
}
}
}
}
@Override
protected String[] getImports()
{
String[] imports = new String[] {
IsWidget.class.getCanonicalName(),
GWT.class.getCanonicalName(),
Crux.class.getCanonicalName(),
HasValue.class.getCanonicalName(),
HasText.class.getCanonicalName(),
HasFormatter.class.getCanonicalName()
};
return imports;
}
/**
* @param method
* @param sourceWriter
* @param interfaceClass
*/
@Override
protected void generateWrapperMethod(JMethod method, SourcePrinter sourceWriter)
{
checkMethodSignature(method);
String name = method.getName();
String widgetName;
Target target = method.getAnnotation(Target.class);
if (target != null)
{
widgetName = target.value();
}
else
{
if (name.length() > 3)
{
widgetName = ""+Character.toLowerCase(name.charAt(3));
if (name.length() > 4)
{
widgetName += name.substring(4);
}
}
else
{
widgetName = "";
}
}
if (name.startsWith("get"))
{
if (widgetName.length() > 0)
{
JType returnType = method.getReturnType();
generateWrapperMethodForGetter(sourceWriter, returnType, name, widgetName);
}
}
else if (name.startsWith("set"))
{
if (widgetName.length() > 0)
{
JType parameterType = method.getParameterTypes()[0];
generateWrapperMethodForSetter(sourceWriter, parameterType, name, widgetName);
}
}
}
/**
* @param sourceWriter
* @param parameterType
* @param methodName
* @param widgetName
*/
private void generateWrapperMethodForSetter(SourcePrinter sourceWriter, JType parameterType, String methodName, String widgetName)
{
String parameterClassName = JClassUtils.getGenericDeclForType(parameterType);
sourceWriter.println("public void " + methodName+"("+parameterType.getParameterizedQualifiedSourceName()+" value){");
if (JClassUtils.isSimpleType(parameterType))
{
sourceWriter.println("IsWidget w = _getFromView(\""+widgetName+"\");");
sourceWriter.println("if (w != null) {");
sourceWriter.println("if (w instanceof HasValue) {");
sourceWriter.println("((HasValue<"+parameterClassName+">)w).setValue(value);");
sourceWriter.println("}");
sourceWriter.println("else if (w instanceof HasFormatter) {");
if (parameterType.isPrimitive() != null)
{
sourceWriter.println("((HasFormatter)w).setUnformattedValue(("+parameterClassName+")value);");
}
else
{
sourceWriter.println("((HasFormatter)w).setUnformattedValue(value);");
}
sourceWriter.println("}");
if (parameterType.equals(stringType))
{
sourceWriter.println("else if (w instanceof HasText) {");
sourceWriter.println("((HasText)w).setText(value);");
sourceWriter.println("}");
}
sourceWriter.println("}");
}
else
{
sourceWriter.println("this._"+methodName+" = value;");
}
sourceWriter.println("}");
}
/**
*
* @param sourceWriter
* @param returnType
* @param methodName
* @param widgetName
*/
private void generateWrapperMethodForGetter(SourcePrinter sourceWriter, JType returnType, String methodName, String widgetName)
{
String returnClassName = JClassUtils.getGenericDeclForType(returnType);
sourceWriter.println("public "+returnType.getParameterizedQualifiedSourceName()+" " + methodName+"(){");
if (JClassUtils.isSimpleType(returnType))
{
sourceWriter.println("IsWidget w = _getFromView(\""+widgetName+"\");");
sourceWriter.println("if (w != null) {");
sourceWriter.println("if (w instanceof HasValue) {");
sourceWriter.println("return ((HasValue<"+returnClassName+">)w).getValue();");
sourceWriter.println("}");
sourceWriter.println("else if (w instanceof HasFormatter) {");
sourceWriter.println("return ("+returnClassName+")((HasFormatter)w).getUnformattedValue();");
sourceWriter.println("}");
if (returnType.equals(stringType))
{
sourceWriter.println("else if (w instanceof HasText) {");
sourceWriter.println("return ((HasText)w).getText();");
sourceWriter.println("}");
}
sourceWriter.println("}");
sourceWriter.println("return null;");
}
else
{
sourceWriter.println("return _"+methodName+";");
}
sourceWriter.println("}");
}
private void checkMethodSignature(JMethod method)
{
JType returnType = method.getReturnType();
String name = method.getName();
if (name.startsWith("get"))
{
if (method.getParameters().length != 0)
{
throw new CruxGeneratorException("The method ["+name+"] from ViewBinder ["+baseIntf.getQualifiedSourceName()+"] has an invalid signature.");
}
if (!JClassUtils.isSimpleType(returnType))
{
JClassType returnTypeClass = returnType.isClassOrInterface();
if (returnTypeClass == null || !returnTypeClass.isAssignableTo(viewBinderType))
{
throw new CruxGeneratorException("The method ["+name+"] from ViewBinder ["+baseIntf.getQualifiedSourceName()+"] has an invalid signature.");
}
}
}
else if (name.startsWith("set"))
{
if (method.getParameters().length != 1)
{
throw new CruxGeneratorException("The method ["+name+"] from ViewBinder ["+baseIntf.getQualifiedSourceName()+"] has an invalid signature.");
}
if (returnType.getErasedType() != JPrimitiveType.VOID)
{
throw new CruxGeneratorException("The method ["+name+"] from ViewBinder ["+baseIntf.getQualifiedSourceName()+"] has an invalid signature.");
}
JType parameterType = method.getParameterTypes()[0];
if (!JClassUtils.isSimpleType(parameterType))
{
JClassType parameterTypeClass = parameterType.isClassOrInterface();
if (parameterTypeClass == null || !parameterTypeClass.isAssignableTo(viewBinderType))
{
throw new CruxGeneratorException("The method ["+name+"] from ViewBinder ["+baseIntf.getQualifiedSourceName()+"] has an invalid signature.");
}
}
}
else
{
throw new CruxGeneratorException("The method ["+name+"] from ViewBinder ["+baseIntf.getQualifiedSourceName()+"] has an invalid signature.");
}
}
}