/* * Copyright 2013 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.widget; import org.cruxframework.crux.core.client.converter.TypeConverter; import org.cruxframework.crux.core.client.dto.DataObject; import org.cruxframework.crux.core.client.screen.LazyPanelWrappingType; import org.cruxframework.crux.core.client.screen.views.BindableView; import org.cruxframework.crux.core.client.screen.views.ViewFactoryUtils; import org.cruxframework.crux.core.client.utils.EscapeUtils; import org.cruxframework.crux.core.client.utils.StringUtils; import org.cruxframework.crux.core.config.ConfigurationFactory; import org.cruxframework.crux.core.rebind.AbstractProxyCreator.SourcePrinter; import org.cruxframework.crux.core.rebind.CruxGeneratorException; import org.cruxframework.crux.core.rebind.context.RebindContext; import org.cruxframework.crux.core.rebind.screen.widget.ViewFactoryCreator.LazyCompatibleWidgetConsumer; import org.cruxframework.crux.core.utils.JClassUtils; import org.json.JSONObject; import com.google.gwt.core.ext.typeinfo.JClassType; import com.google.gwt.core.ext.typeinfo.JType; import com.google.gwt.user.client.ui.HasText; import com.google.gwt.user.client.ui.HasValue; /** * * @author Thiago da Rosa de Bustamante * */ public class ViewWidgetConsumer extends DataWidgetConsumer implements LazyCompatibleWidgetConsumer { private final ViewFactoryCreator viewFactoryCreator; public ViewWidgetConsumer(ViewFactoryCreator viewFactoryCreator) { this.viewFactoryCreator = viewFactoryCreator; } public void consume(SourcePrinter out, String widgetId, String widgetVariableName, String widgetType, JSONObject metaElem) { String bindPath = metaElem!=null?metaElem.optString("bindPath"):null; String bindConverter = metaElem!=null?metaElem.optString("bindConverter"):null; if (viewFactoryCreator.isBindableView() && !StringUtils.isEmpty(bindPath)) { Class<?> widgetClass = viewFactoryCreator.getWidgetCreator(widgetType).getWidgetClass(); String dataObjectClassName = viewFactoryCreator.getContext().getDataObjects().getDataObject(viewFactoryCreator.view.getDataObject()); JClassType dataObjectType = viewFactoryCreator.getContext().getGeneratorContext().getTypeOracle().findType(dataObjectClassName); JClassType widgetClassType = viewFactoryCreator.getContext().getGeneratorContext().getTypeOracle().findType(widgetClass.getCanonicalName()); try { out.println(ViewFactoryCreator.getViewVariable()+".addWidget("+EscapeUtils.quote(widgetId)+", "+ widgetVariableName + ", new "+BindableView.class.getCanonicalName()+".PropertyBinder<"+dataObjectClassName+">(){"); JClassType converterType = ViewBindHandler.getConverterType(viewFactoryCreator.getContext(), bindConverter); String converterVariable = null; if (converterType != null) { JType propertyType = JClassUtils.getTypeForProperty(bindPath, dataObjectType); if (propertyType == null) { throw new CruxGeneratorException("No Data Object type declared for binding path [" + bindPath + "] " + "for type " + widgetClassType.getName() + ". Have you used the annotation " + DataObject.class.getCanonicalName() + "?"); } String propertyClassName = JClassUtils.getGenericDeclForType(propertyType); validateConverter(converterType, viewFactoryCreator.getContext(), widgetClassType, viewFactoryCreator.getContext().getGeneratorContext().getTypeOracle().findType(propertyClassName)); converterVariable = "__converter"; out.println(converterType.getParameterizedQualifiedSourceName()+" "+converterVariable+" = new "+converterType.getParameterizedQualifiedSourceName()+"();"); } out.println("public void copyTo("+dataObjectClassName+" dataObject, Widget w){"); generateCopyToCode(out, viewFactoryCreator.getContext(), "dataObject", "w", dataObjectType, widgetClassType, bindPath, converterVariable, converterType, false); out.println("}"); out.println("public void copyFrom(Widget w, "+dataObjectClassName+" dataObject){"); generateCopyFromCode(out, viewFactoryCreator.getContext(), "dataObject", "w", dataObjectType, widgetClassType, bindPath, converterVariable, converterType, false); out.println("}"); out.println("});"); } catch (NoSuchFieldException e) { throw new CruxGeneratorException("Invalid binding path ["+bindPath+"] on target dataobject ["+dataObjectClassName+"]. Property not found."); } } else { out.println(ViewFactoryCreator.getViewVariable()+".addWidget("+EscapeUtils.quote(widgetId)+", "+ widgetVariableName +");"); } if (Boolean.parseBoolean(ConfigurationFactory.getConfigurations().renderWidgetsWithIDs())) { out.println("ViewFactoryUtils.updateWidgetElementId("+EscapeUtils.quote(widgetId)+", "+ widgetVariableName +", "+ViewFactoryCreator.getViewVariable()+");"); } } @Override public void handleLazyWholeWidgetCreation(SourcePrinter out, String widgetId) { out.println(ViewFactoryCreator.getViewVariable()+".checkRuntimeLazyDependency("+EscapeUtils.quote(widgetId)+", "+ EscapeUtils.quote(ViewFactoryUtils.getLazyPanelId(widgetId, LazyPanelWrappingType.wrapWholeWidget)) +");"); } @Override public void handleLazyWrapChildrenCreation(SourcePrinter out, String widgetId) { out.println(ViewFactoryCreator.getViewVariable()+".checkRuntimeLazyDependency("+EscapeUtils.quote(widgetId)+", "+ EscapeUtils.quote(ViewFactoryUtils.getLazyPanelId(widgetId, LazyPanelWrappingType.wrapChildren)) +");"); } public static void validateConverter(JClassType converterType, RebindContext context, JClassType widgetClass, JClassType propertyType) { JClassType hasValueType = context.getGeneratorContext().getTypeOracle().findType(HasValue.class.getCanonicalName()); JClassType hasTextType = context.getGeneratorContext().getTypeOracle().findType(HasText.class.getCanonicalName()); JClassType typeConverterType = context.getGeneratorContext().getTypeOracle().findType(TypeConverter.class.getCanonicalName()); JClassType stringType = context.getGeneratorContext().getTypeOracle().findType(String.class.getCanonicalName()); JClassType[] types = JClassUtils.getActualParameterTypes(converterType, typeConverterType); JClassType widgetType = null; if (widgetClass.isAssignableTo(hasValueType)) { JClassType[] widgetValueType = JClassUtils.getActualParameterTypes(widgetClass, hasValueType); widgetType = widgetValueType[0]; } else if (widgetClass.isAssignableTo(hasTextType)) { widgetType = stringType; } else { throw new CruxGeneratorException("converter ["+converterType.getQualifiedSourceName()+ "] can not be used to convert values to widget of type ["+widgetClass.getQualifiedSourceName()+"]. Incompatible types."); } if (!propertyType.isAssignableTo(types[0])) { throw new CruxGeneratorException("converter ["+converterType.getQualifiedSourceName()+ "] can not be used to convert values to widget of type ["+widgetClass.getQualifiedSourceName()+"]. Incompatible types."); } if (!widgetType.isAssignableTo(types[1])) { throw new CruxGeneratorException("converter ["+converterType.getQualifiedSourceName()+ "] can not be used to convert values to property of type ["+propertyType.getQualifiedSourceName()+"]. Incompatible types."); } } }