/*
* Copyright 2014 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.screen.binding.NativeWrapper;
import org.cruxframework.crux.core.client.utils.EscapeUtils;
import org.cruxframework.crux.core.client.utils.StringUtils;
import org.cruxframework.crux.core.utils.JClassUtils;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.dom.client.Element;
import com.ibm.icu.text.MessageFormat;
/**
* @author Thiago da Rosa de Bustamante
*
*/
public class PropertyBindInfo extends BindInfo
{
protected static String WIDGET_VAR_REF = "widget";
protected boolean boundToAttribute;
protected String getUiObjectExpression;
protected boolean nativeElement = false;
protected boolean nativeWrapperOrElement = false;
protected JClassType uiObjectType;
protected String widgetClassName;
protected String widgetPropertyPath;
public PropertyBindInfo(String widgetPropertyPath, boolean boundToAttribute, String bindPath, JClassType widgetType, JClassType dataObjectType,
JClassType converterType, String dataObject, String converterParams,
JClassType uiObjectType, String getUiObjectExpression) throws NoSuchFieldException
{
super(bindPath, dataObjectType, converterType, dataObject, converterParams);
this.widgetPropertyPath = widgetPropertyPath;
this.boundToAttribute = boundToAttribute;
this.uiObjectType = uiObjectType==null?widgetType:uiObjectType;
this.nativeElement = this.uiObjectType.getQualifiedSourceName().equals(Element.class.getCanonicalName());
this.nativeWrapperOrElement = nativeElement || this.uiObjectType.getQualifiedSourceName().equals(NativeWrapper.class.getCanonicalName());
this.getUiObjectExpression = getUiObjectExpression;
if (widgetType != null)
{
this.widgetClassName = widgetType.getQualifiedSourceName();
}
}
public String getDataObjectReadExpression(String contextVariable, String resultVariable, String collectionDataObjectRef, String collectionItemVar)
{
boolean isCollectionObjectReference = collectionDataObjectRef != null && collectionItemVar.equals(dataObject);
String dataObjectVariable = isCollectionObjectReference?collectionDataObjectRef:ViewFactoryCreator.createVariableName(dataObject);
String result = "";
if (!isCollectionObjectReference)
{
result = getDataObjectClassName()+" "+dataObjectVariable+" = "+contextVariable+".getDataObject("+EscapeUtils.quote(dataObject)+");\n";
}
result += "if (" + dataObjectVariable + " != null){\n"
+ resultVariable + " = " + getExpression(getDataObjectReadExpression(), dataObjectVariable) + ";"
+ "\n} else {\n"
+ resultVariable + " = null;\n"
+ "}";
return result;
}
public String getDataObjectWriteExpression(String dataObjectVar, String newValue)
{
return getExpression(getDataObjectWriteExpression(newValue), dataObjectVar);
}
public String getReadExpression(String dataObjectVariable) throws NoSuchFieldException
{
String readExpression = buildReadExpression(widgetPropertyPath);
return getExpression(readExpression, dataObjectVariable);
}
public String getUiObjectClassName()
{
return uiObjectType.getParameterizedQualifiedSourceName();
}
public String getUiObjectExpression()
{
return getUiObjectExpression;
}
/**
* Retrieve the reference to the variable that represents the target ui element from this binding
* @param widgetVar
* @return
*/
public String getUIObjectVar(String widgetVar)
{
if (!hasUiObjectExpression())
{
return widgetVar;
}
String uiObjectVar = MessageFormat.format(getUiObjectExpression, widgetVar);
return uiObjectVar;
}
public String getWidgetClassName()
{
return widgetClassName;
}
public String getWriteExpression(String dataObjectVariable) throws NoSuchFieldException
{
String writeExpression = buildWriteExpression(widgetPropertyPath, null);
return getExpression(writeExpression, dataObjectVariable);
}
public String getWriteExpression(String contextVariable, String widgetVar,
String collectionObjectReference, String collectionItemVar,
String uiObjectVariable) throws NoSuchFieldException
{
String writeExpression = buildWriteExpression(widgetPropertyPath, uiObjectVariable);
boolean isCollectionObjectReference = collectionObjectReference != null && collectionItemVar.equals(dataObject);
String dataObjectVariable = isCollectionObjectReference?collectionObjectReference:ViewFactoryCreator.createVariableName(dataObject);
boolean isReferenced = !isCollectionObjectReference;
String result;
if (isReferenced)
{
result = getDataObjectClassName()+" "+dataObjectVariable+" = "+contextVariable+".getDataObject("+EscapeUtils.quote(dataObject)+");\n"
+ "if (" + dataObjectVariable + " != null){\n"
+ getExpression(writeExpression.replace(WIDGET_VAR_REF, widgetVar), dataObjectVariable)
+ "\n}";
}
else
{
result = getExpression(writeExpression.replace(WIDGET_VAR_REF, widgetVar), dataObjectVariable);
}
return result;
}
/**
* If this databinding reference an ui element that is not the widget bound to this binding,
* then an expression is used to retrieve the target ui element
* @return
*/
public boolean hasUiObjectExpression()
{
return !StringUtils.isEmpty(getUiObjectExpression);
}
public boolean isBoundToAttribute()
{
return boundToAttribute;
}
public boolean isNativeElement()
{
return nativeElement;
}
/**
* Expression to read FROM widget and write TO dataObject
* @param widgetPropertyPath
* @return
* @throws NoSuchFieldException
*/
protected String buildReadExpression(String widgetPropertyPath) throws NoSuchFieldException
{
StringBuilder getExpression = new StringBuilder();
String uiObjectVar = getUIObjectVar(WIDGET_VAR_REF);
boolean createAuxiliaryVariable = hasUiObjectExpression();
String uiObjectVariable = createAuxiliaryVariable?ViewFactoryCreator.createVariableName("uiObjectVariable"):uiObjectVar;
if (nativeWrapperOrElement)
{
String propertyGetter = DataBindingNativeTypeResolver.resolveTypeForProperty(widgetPropertyPath).getGetter();
getExpression.append(uiObjectVariable+"."+propertyGetter+"(" + EscapeUtils.quote(widgetPropertyPath) + ")");
}
else
{
JClassUtils.buildGetValueExpression(getExpression, uiObjectType, widgetPropertyPath, uiObjectVariable, false, true, true);
}
StringBuilder result = new StringBuilder();
if (createAuxiliaryVariable)
{
result.append(getUiObjectClassName() + " " + uiObjectVariable + " = " + uiObjectVar + ";\n");
}
result.append("if ("+uiObjectVariable + " != null){\n");
result.append(buildDataObjectWriteExpression(getExpression.toString()));
result.append("\n}");
return result.toString();
}
/**
* Expression to read FROM dataObject and write TO widget
*
* @param widgetPropertyPath
* @param uiObjectVariable
* @return
* @throws NoSuchFieldException
*/
protected String buildWriteExpression(String widgetPropertyPath, String uiObjectVariable) throws NoSuchFieldException
{
StringBuilder writeExpression = new StringBuilder();
String uiObjectVar = getUIObjectVar(WIDGET_VAR_REF);
boolean hasUiObjectVariable = !StringUtils.isEmpty(uiObjectVariable);
boolean createAuxiliaryVariable = hasUiObjectExpression() && !hasUiObjectVariable;
uiObjectVariable = createAuxiliaryVariable?ViewFactoryCreator.createVariableName("uiObjectVariable"):
(hasUiObjectVariable?uiObjectVariable:uiObjectVar);
if (createAuxiliaryVariable)
{
writeExpression.append(getUiObjectClassName() + " " + uiObjectVariable + " = " + uiObjectVar + ";\n");
}
writeExpression.append("if ("+uiObjectVariable + " != null)\n");
if (nativeWrapperOrElement)
{
String propertySetter = DataBindingNativeTypeResolver.resolveTypeForProperty(widgetPropertyPath).getSetter();
writeExpression.append(uiObjectVariable+"."+propertySetter+"(" +
EscapeUtils.quote(widgetPropertyPath) + "," + getDataObjectReadExpression() + ");");
}
else
{
JClassUtils.buildSetValueExpression(writeExpression, uiObjectType, widgetPropertyPath,
uiObjectVariable, getDataObjectReadExpression());
}
return writeExpression.toString();
}
}