/*
* Copyright 2015 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.bean.BeanCopier;
import org.cruxframework.crux.core.client.dataprovider.DataChangedEvent;
import org.cruxframework.crux.core.client.dataprovider.DataChangedHandler;
import org.cruxframework.crux.core.client.dataprovider.DataFilterEvent;
import org.cruxframework.crux.core.client.dataprovider.DataFilterHandler;
import org.cruxframework.crux.core.client.dataprovider.DataLoadStoppedEvent;
import org.cruxframework.crux.core.client.dataprovider.DataLoadStoppedHandler;
import org.cruxframework.crux.core.client.dataprovider.DataLoadedEvent;
import org.cruxframework.crux.core.client.dataprovider.DataLoadedHandler;
import org.cruxframework.crux.core.client.dataprovider.DataSelectionEvent;
import org.cruxframework.crux.core.client.dataprovider.DataSelectionHandler;
import org.cruxframework.crux.core.client.dataprovider.DataSortedEvent;
import org.cruxframework.crux.core.client.dataprovider.DataSortedHandler;
import org.cruxframework.crux.core.client.dataprovider.EagerDataLoader;
import org.cruxframework.crux.core.client.dataprovider.EagerLoadEvent;
import org.cruxframework.crux.core.client.dataprovider.EagerPagedDataProvider;
import org.cruxframework.crux.core.client.dataprovider.FetchDataEvent;
import org.cruxframework.crux.core.client.dataprovider.LazyDataLoader;
import org.cruxframework.crux.core.client.dataprovider.LazyDataProvider;
import org.cruxframework.crux.core.client.dataprovider.MeasureDataEvent;
import org.cruxframework.crux.core.client.dataprovider.ResetEvent;
import org.cruxframework.crux.core.client.dataprovider.ResetHandler;
import org.cruxframework.crux.core.client.dataprovider.StreamingDataLoader;
import org.cruxframework.crux.core.client.dataprovider.StreamingDataProvider;
import org.cruxframework.crux.core.client.dataprovider.TransactionEndEvent;
import org.cruxframework.crux.core.client.dataprovider.TransactionEndHandler;
import org.cruxframework.crux.core.client.dataprovider.TransactionStartEvent;
import org.cruxframework.crux.core.client.dataprovider.TransactionStartHandler;
import org.cruxframework.crux.core.client.screen.DeviceAdaptive.Device;
import org.cruxframework.crux.core.client.utils.StringUtils;
import org.cruxframework.crux.core.rebind.AbstractProxyCreator.SourcePrinter;
import org.cruxframework.crux.core.rebind.CruxGeneratorException;
import org.cruxframework.crux.core.rebind.screen.DataProvider;
import org.json.JSONObject;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.ext.typeinfo.JClassType;
/**
* @author Thiago da Rosa de Bustamante
*
*/
class DataProviderHelper
{
private ViewFactoryCreator viewFactory;
public DataProviderHelper(ViewFactoryCreator viewFactory)
{
this.viewFactory = viewFactory;
}
public String createDataProvider(SourcePrinter out, DataProvider dataProvider)
{
if (viewFactory.targetsDevice(dataProvider.getMetadata()))
{
switch (dataProvider.getType())
{
case dataProvider: return createEagerPagedDataProvider(out, dataProvider);
case lazyDataProvider: return createLazyDataProvider(out, dataProvider);
case streamingDataProvider: return createStreamingDataProvider(out, dataProvider);
}
}
return null;
}
public JClassType getDataObjectFromProvider(String dataProviderId)
{
DataProvider dataProvider = viewFactory.getView().getDataProvider(dataProviderId);
if(dataProvider == null)
{
throw new CruxGeneratorException("DataProvider ["+dataProviderId+"] on view ["+viewFactory.getView().getId()+"] must inform the dataObject to bind.");
}
return getDataObject(dataProviderId, dataProvider.getMetadata());
}
protected String createEagerPagedDataProvider(SourcePrinter out, DataProvider dataProvider)
{
JSONObject metadata = dataProvider.getMetadata();
String onLoadData = metadata.optString("onLoadData");
JClassType dataObjectType = getDataObject(dataProvider.getId(), metadata);
String dataObjectClassName = dataObjectType.getParameterizedQualifiedSourceName();
String dataProviderVariable = ViewFactoryCreator.createVariableName("dataProvider");
String dataLoaderClassName = EagerDataLoader.class.getCanonicalName();
String dataEventClassName = EagerLoadEvent.class.getCanonicalName();
String dataProviderClassName = EagerPagedDataProvider.class.getCanonicalName();
out.print(dataProviderClassName+"<"+dataObjectClassName+"> " + dataProviderVariable+" = new "+dataProviderClassName+"<"+dataObjectClassName+">(");
createDataHandlerObject(out, dataObjectType);
out.println(");");
out.println(dataProviderVariable+".setDataLoader(new "+dataLoaderClassName+"<"+dataObjectClassName+">(){");
out.println("public void onLoadData("+dataEventClassName+"<"+dataObjectClassName+"> event){");
EvtProcessor.printEvtCall(out, onLoadData, "onLoadData", dataEventClassName, "event", viewFactory.getContext(),
viewFactory.getView(), viewFactory.getControllerAccessHandler(), getDevice(), true);
out.println("}");
out.println("});");
processCommonProperties(out, metadata, dataProviderVariable);
String onDataFiltered = metadata.optString("onDataFiltered");
if (!StringUtils.isEmpty(onDataFiltered))
{
printEventHandler(out, dataProviderVariable, onDataFiltered, DataFilterHandler.class,
DataFilterEvent.class.getCanonicalName(), "onFiltered");
}
return dataProviderVariable;
}
protected String createLazyDataProvider(SourcePrinter out, DataProvider dataProvider)
{
JSONObject metadata = dataProvider.getMetadata();
String onMeasureData = metadata.optString("onMeasureData");
String onFetchData = metadata.optString("onFetchData");
JClassType dataObjectType = getDataObject(dataProvider.getId(), metadata);
String dataObjectClassName = dataObjectType.getParameterizedQualifiedSourceName();
String dataProviderVariable = ViewFactoryCreator.createVariableName("dataProvider");
String dataProviderClassName = LazyDataProvider.class.getCanonicalName();
String dataLoaderClassName = LazyDataLoader.class.getCanonicalName();
String dataEventClassName = FetchDataEvent.class.getCanonicalName();
String dataMeasureEventClassName = MeasureDataEvent.class.getCanonicalName();
out.println(dataProviderClassName+"<"+dataObjectClassName+"> " + dataProviderVariable+" = new "+dataProviderClassName+"<"+dataObjectClassName+">(");
createDataHandlerObject(out, dataObjectType);
out.println(");");
out.println(dataProviderVariable+".setDataLoader(new "+dataLoaderClassName+"<"+dataObjectClassName+">(){");
out.println("public void onMeasureData("+dataMeasureEventClassName+"<"+dataObjectClassName+"> event){");
EvtProcessor.printEvtCall(out, onMeasureData, "onMeasureData", dataMeasureEventClassName, "event", viewFactory.getContext(),
viewFactory.getView(), viewFactory.getControllerAccessHandler(), getDevice(), true);
out.println("}");
out.println("public void onFetchData("+dataEventClassName+"<"+dataObjectClassName+"> event){");
EvtProcessor.printEvtCall(out, onFetchData, "onFetchData", dataEventClassName, "event", viewFactory.getContext(),
viewFactory.getView(), viewFactory.getControllerAccessHandler(), getDevice(), true);
out.println("}");
out.println("});");
processCommonProperties(out, metadata, dataProviderVariable);
return dataProviderVariable;
}
protected String createStreamingDataProvider(SourcePrinter out, DataProvider dataProvider)
{
JSONObject metadata = dataProvider.getMetadata();
String onFetchData = metadata.optString("onFetchData");
JClassType dataObjectType = getDataObject(dataProvider.getId(), metadata);
String dataObjectClassName = dataObjectType.getParameterizedQualifiedSourceName();
String dataProviderVariable = ViewFactoryCreator.createVariableName("dataProvider");
String dataProviderClassName = StreamingDataProvider.class.getCanonicalName();
String dataLoaderClassName = StreamingDataLoader.class.getCanonicalName();
String dataEventClassName = FetchDataEvent.class.getCanonicalName();
out.println(dataProviderClassName+"<"+dataObjectClassName+"> " + dataProviderVariable+" = new "+dataProviderClassName+"<"+dataObjectClassName+">(");
createDataHandlerObject(out, dataObjectType);
out.println(");");
out.println(dataProviderVariable+".setDataLoader(new "+dataLoaderClassName+"<"+dataObjectClassName+">(){");
out.println("public void onFetchData("+dataEventClassName+"<"+dataObjectClassName+"> event){");
EvtProcessor.printEvtCall(out, onFetchData, "onFetchData", dataEventClassName, "event", viewFactory.getContext(),
viewFactory.getView(), viewFactory.getControllerAccessHandler(), getDevice(), true);
out.println("}");
out.println("});");
processCommonProperties(out, metadata, dataProviderVariable);
return dataProviderVariable;
}
private void createDataHandlerObject(SourcePrinter out, JClassType dataObjectType)
{
JClassType javascriptObjectType = viewFactory.getContext().getGeneratorContext().
getTypeOracle().findType(JavaScriptObject.class.getCanonicalName());
String dataObject = dataObjectType.getParameterizedQualifiedSourceName();
String copierSimpleClassName = dataObjectType.getSimpleSourceName() + "_Data_Copier";
String packageName = dataObjectType.getPackage().getName();
SourcePrinter subTypeWriter = viewFactory.getSubTypeWriter(packageName,
copierSimpleClassName, null, new String[]{BeanCopier.class.getCanonicalName()+"<"+dataObject+", "+dataObject+">"}, null, true);
// TODO tentar ler do cache primeiro (tryReuse....)
if (subTypeWriter != null)
{
subTypeWriter.commit();
}
String copierClassName = packageName + "." + copierSimpleClassName;
out.println("new " + org.cruxframework.crux.core.client.dataprovider.DataProvider.EditionDataHandler.class.getCanonicalName() + "<" + dataObject + ">(){");
out.println(copierClassName + " copier = GWT.create(" + copierClassName + ".class);");
out.println("public " + dataObject + " clone(" + dataObject + " value){");
if (dataObjectType.isAssignableTo(javascriptObjectType))
{
out.println(dataObject + " result = " + dataObject + ".createObject().cast();");
}
else
{
out.println(dataObject + " result = new " + dataObject + "();");
}
out.println("copier.copyTo(value, result);");
out.println("return result;");
out.println("}");
out.println("}");
}
private JClassType getDataObject(String dataProviderId, JSONObject elem)
{
String dataObject = elem.optString("dataObject");
if (StringUtils.isEmpty(dataObject))
{
throw new CruxGeneratorException("DataProvider ["+dataProviderId+"] on view ["+viewFactory.getView().getId()+"] must inform the dataObject to bind.");
}
String dataObjectClass = viewFactory.getContext().getDataObjects().getDataObject(dataObject);
if (StringUtils.isEmpty(dataObjectClass))
{
throw new CruxGeneratorException("DataProvider ["+dataProviderId+"] on view ["+viewFactory.getView().getId()+"] informed an invalid "
+ "dataObject ["+dataObject+"]. Can not found the informed value");
}
JClassType dtoType = viewFactory.getContext().getGeneratorContext().getTypeOracle().findType(dataObjectClass);
return dtoType;
}
private Device getDevice()
{
return (viewFactory.getDevice() == null?null:Device.valueOf(viewFactory.getDevice()));
}
private void processCommonProperties(SourcePrinter out, JSONObject metadata, String dataProviderVariable)
{
int pageSize = metadata.optInt("pageSize", -1);
if (pageSize > 0)
{
out.println(dataProviderVariable+".setPageSize(" + pageSize + ");");
}
boolean autoLoadData = metadata.optBoolean("autoLoadData", false);
if (autoLoadData)
{
out.println(dataProviderVariable+".load();");
}
String selectionMode = metadata.optString("selectionMode");
if (!StringUtils.isEmpty(selectionMode))
{
String selectionModeClassName = org.cruxframework.crux.core.client.dataprovider.DataProvider.SelectionMode.class.getCanonicalName();
out.println(dataProviderVariable + ".setSelectionMode(" + selectionModeClassName + "." + selectionMode + ");");
}
String onDataChanged = metadata.optString("onDataChanged");
if (!StringUtils.isEmpty(onDataChanged))
{
printEventHandler(out, dataProviderVariable, onDataChanged, DataChangedHandler.class,
DataChangedEvent.class.getCanonicalName(), "onDataChanged");
}
String onDataLoaded = metadata.optString("onDataLoaded");
if (!StringUtils.isEmpty(onDataLoaded))
{
printEventHandler(out, dataProviderVariable, onDataLoaded, DataLoadedHandler.class,
DataLoadedEvent.class.getCanonicalName(), "onLoaded");
}
String onDataSelected = metadata.optString("onDataSelected");
if (!StringUtils.isEmpty(onDataSelected))
{
printEventHandler(out, dataProviderVariable, onDataSelected, DataSelectionHandler.class,
DataSelectionEvent.class.getCanonicalName(), "onDataSelection");
}
String onDataSorted = metadata.optString("onDataSorted");
if (!StringUtils.isEmpty(onDataSorted))
{
printEventHandler(out, dataProviderVariable, onDataSorted, DataSortedHandler.class,
DataSortedEvent.class.getCanonicalName(), "onSorted");
}
String onLoadStopped = metadata.optString("onLoadStopped");
if (!StringUtils.isEmpty(onLoadStopped))
{
printEventHandler(out, dataProviderVariable, onLoadStopped, DataLoadStoppedHandler.class,
DataLoadStoppedEvent.class.getCanonicalName(), "onLoadStopped");
}
String onReset = metadata.optString("onReset");
if (!StringUtils.isEmpty(onReset))
{
printEventHandler(out, dataProviderVariable, onReset, ResetHandler.class,
ResetEvent.class.getCanonicalName(), "onReset");
}
String onTransactionEnd = metadata.optString("onTransactionEnd");
if (!StringUtils.isEmpty(onTransactionEnd))
{
printEventHandler(out, dataProviderVariable, onTransactionEnd, TransactionEndHandler.class,
TransactionEndEvent.class.getCanonicalName(), "onTransactionEnd");
}
String onTransactionStart = metadata.optString("onTransactionStart");
if (!StringUtils.isEmpty(onTransactionStart))
{
printEventHandler(out, dataProviderVariable, onTransactionStart, TransactionStartHandler.class,
TransactionStartEvent.class.getCanonicalName(), "onTransactionStart");
}
}
private void printEventHandler(SourcePrinter out, String dataProviderVariable, String onDataChanged,
Class<?> eventHandlerClass, String eventClassName, String eventName)
{
out.println(dataProviderVariable+".add"+eventHandlerClass.getSimpleName()+"(new "+eventHandlerClass.getCanonicalName()+"(){");
out.println("public void "+eventName+"("+eventClassName+" event){");
EvtProcessor.printEvtCall(out, onDataChanged, eventName, eventClassName, "event",
viewFactory.getContext(), viewFactory.getView(),
viewFactory.getControllerAccessHandler(), getDevice(), true);
out.println("}");
out.println("});");
}
}