/*
* 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.wrapper;
import org.cruxframework.crux.core.client.Crux;
import org.cruxframework.crux.core.client.screen.Screen;
import org.cruxframework.crux.core.client.screen.views.BindableView;
import org.cruxframework.crux.core.client.screen.views.Target;
import org.cruxframework.crux.core.client.screen.views.View;
import org.cruxframework.crux.core.client.screen.views.ViewContainer;
import org.cruxframework.crux.core.client.screen.views.ViewFactory.CreateCallback;
import org.cruxframework.crux.core.rebind.AbstractWrapperProxyCreator;
import org.cruxframework.crux.core.rebind.CruxGeneratorException;
import org.cruxframework.crux.core.rebind.context.RebindContext;
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.JParameter;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.user.client.Window;
/**
* @author Thiago da Rosa de Bustamante
*
*/
public class ViewAccessorProxyCreator extends AbstractWrapperProxyCreator
{
private final JClassType viewType;
private JClassType createCallbackType;
private JClassType bindableViewType;
/**
* Constructor
* @param logger
* @param context
*/
public ViewAccessorProxyCreator(RebindContext context, JClassType invokerIntf)
{
super(context, invokerIntf);
try
{
viewType = invokerIntf.getOracle().getType(View.class.getCanonicalName());
bindableViewType = invokerIntf.getOracle().getType(BindableView.class.getCanonicalName());
createCallbackType = invokerIntf.getOracle().getType(CreateCallback.class.getCanonicalName());
}
catch (NotFoundException e)
{
throw new CruxGeneratorException(e.getMessage(), e);
}
}
@Override
protected String[] getImports()
{
String[] imports = new String[] {
View.class.getCanonicalName(),
GWT.class.getCanonicalName(),
Crux.class.getCanonicalName(),
Window.class.getCanonicalName()
};
return imports;
}
@Override
protected void generateProxyMethods(SourcePrinter srcWriter) throws CruxGeneratorException
{
super.generateProxyMethods(srcWriter);
generateRootViewMethod(srcWriter);
}
/**
* @param method
* @param sourceWriter
* @param interfaceClass
*/
@Override
protected void generateWrapperMethod(JMethod method, SourcePrinter sourceWriter)
{
String name = method.getName();
JParameter[] parameters = method.getParameters();
if (name.equals("getRootView") && parameters.length == 0)
{
return; //Ignore
}
JType returnType = method.getReturnType();
JClassType returnTypeClass = returnType.isClassOrInterface();
if (returnTypeClass!= null && viewType.isAssignableFrom(returnTypeClass))
{
if(parameters.length == 0)
{
String viewName;
Target target = method.getAnnotation(Target.class);
if (target != null)
{
viewName = target.value();
}
else if (name.startsWith("get"))
{
if (name.length() > 3)
{
viewName = ""+Character.toLowerCase(name.charAt(3));
if (name.length() > 4)
{
viewName += name.substring(4);
}
}
else
{
viewName = name;
}
}
else
{
viewName = name;
}
generateWrapperMethod(sourceWriter, name, viewName, returnTypeClass);
}
else
{
throw new CruxGeneratorException("The method ["+method.getName()+"] from ViewAccessor ["+method.getEnclosingType().getQualifiedSourceName()+"] must have no parameters.");
}
}
else if (returnTypeClass == null && parameters.length == 1 && parameters[0].getType().isInterface() != null && parameters[0].getType().isInterface().isAssignableTo(createCallbackType))
{
generateLoaderMethod(sourceWriter, name);
}
else
{
throw new CruxGeneratorException("The method ["+method.getName()+"] from ViewAccessor ["+method.getEnclosingType().getQualifiedSourceName()+"] must return a subclass of View.");
}
}
/**
* @param sourceWriter
* @param name
* @param viewName
* @param returnTypeClass
*/
private void generateWrapperMethod(SourcePrinter sourceWriter, String name, String viewName, JClassType returnTypeClass)
{
sourceWriter.println("public "+returnTypeClass.getParameterizedQualifiedSourceName()+" " + name+"(){");
if (returnTypeClass.isAssignableTo(bindableViewType))
{
sourceWriter.println("return ("+returnTypeClass.getParameterizedQualifiedSourceName()+")View.getView(\""+viewName+"\");");
}
else
{
sourceWriter.println("return View.getView(\""+viewName+"\");");
}
sourceWriter.println("}");
}
/**
* @param sourceWriter
* @param name
* @param viewName
*/
private void generateLoaderMethod(SourcePrinter sourceWriter, String name)
{
sourceWriter.println("public void " + name+"("+CreateCallback.class.getCanonicalName()+" callback){");
sourceWriter.println("if (callback != null) {");
sourceWriter.println("View ret = View.getView(\""+name+"\");");
sourceWriter.println("if (ret != null) {");
sourceWriter.println("callback.onViewCreated(ret);");
sourceWriter.println("} else {");
sourceWriter.println(ViewContainer.class.getCanonicalName()+".createView(\""+name+"\", callback);");
sourceWriter.println("}");
sourceWriter.println("}");
sourceWriter.println("}");
}
private void generateRootViewMethod(SourcePrinter sourceWriter)
{
sourceWriter.println("public View getRootView(){");
sourceWriter.println("return "+Screen.class.getCanonicalName()+".getRootView();");
sourceWriter.println("}");
}
}