/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along
with this program; if not, see http://www.gnu.org/licenses or write to the Free
Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*/
package com.servoy.j2db.dataprocessing;
import java.sql.Types;
import org.mozilla.javascript.Function;
import com.servoy.base.persistence.constants.IValueListConstants;
import com.servoy.j2db.IServiceProvider;
import com.servoy.j2db.persistence.IDataProvider;
import com.servoy.j2db.persistence.ScriptMethod;
import com.servoy.j2db.persistence.ValueList;
import com.servoy.j2db.scripting.GlobalScope;
import com.servoy.j2db.util.Pair;
import com.servoy.j2db.util.SafeArrayList;
import com.servoy.j2db.util.ScopesUtils;
import com.servoy.j2db.util.Utils;
/**
* @author jcompagner
*
*/
public class GlobalMethodValueList extends CustomValueList
{
private final Pair<String, String> globalFunction;
private IRecordInternal record;
private String displayString;
private Object realObject;
private boolean filling;
/**
* @param application
* @param vlName
*/
public GlobalMethodValueList(IServiceProvider application, ValueList vl)
{
super(application, vl);
setValueType(Types.OTHER);
ScriptMethod globalScriptMethod = application.getFlattenedSolution().getScriptMethod(vl.getCustomValues());
Pair<String, String> scope = ScopesUtils.getVariableScope(globalScriptMethod != null ? globalScriptMethod.getPrefixedName() : null);
if (vl.getValueListType() != IValueListConstants.GLOBAL_METHOD_VALUES || scope == null || scope.getLeft() == null)
{
throw new RuntimeException("GlobalMethodValueList couldnt be made for: " + ScopesUtils.getScopeString(scope)); //$NON-NLS-1$
}
if (vl.getAddEmptyValue() == IValueListConstants.EMPTY_VALUE_ALWAYS)
{
allowEmptySelection = true;
}
globalFunction = scope;
if (application.getScriptEngine() != null)
{
GlobalScope gs = application.getScriptEngine().getScopesScope().getGlobalScope(globalFunction.getLeft());
Function func = gs == null ? null : gs.getFunctionByName(globalFunction.getRight());
if (func == null)
{
throw new RuntimeException("global Function not found for: " + ScopesUtils.getScopeString(scope)); //$NON-NLS-1$
}
}
}
private boolean hasRealValue = false;
/**
* @see com.servoy.j2db.dataprocessing.CustomValueList#hasRealValues()
*/
@Override
public boolean hasRealValues()
{
return hasRealValue;
}
public void fill()
{
fill(record, null, null);
}
public void fill(IRecordInternal state, String filter, Object real)
{
String display = filter == null ? null : filter.toLowerCase();
if (filling)
{
return;
}
try
{
filling = true;
if (this.record != state || !Utils.equalObjects(display, this.displayString) || !Utils.equalObjects(real, this.realObject))
{
this.displayString = display;
this.realObject = real;
this.record = state;
super.fill(state);
GlobalScope globalScope = application.getScriptEngine().getScopesScope().getGlobalScope(globalFunction.getLeft());
if (globalScope != null)
{
Function function = globalScope.getFunctionByName(globalFunction.getRight());
try
{
if (real == null || "".equals(real)) //$NON-NLS-1$
{
application.invokeAndWait(new Runnable()
{
public void run()
{
realValues = new SafeArrayList<Object>();
removeAllElements();
}
});
}
else if (realValues == null)
{
realValues = new SafeArrayList<Object>();
}
Object[] args = null;
if (display != null && !"".equals(display)) //$NON-NLS-1$
{
args = new Object[] { display, null, state, valueList.getName(), Boolean.valueOf(state instanceof FindState), filter };
}
else if (real != null && !"".equals(real)) //$NON-NLS-1$
{
args = new Object[] { null, real, state, valueList.getName(), Boolean.valueOf(state instanceof FindState), null };
}
else
{
args = new Object[] { null, null, state, valueList.getName(), Boolean.valueOf(state instanceof FindState), null };
}
final Object retValue = application.getScriptEngine().executeFunction(function, globalScope, globalScope, args, false, true);
application.invokeAndWait(new Runnable()
{
public void run()
{
//add empty row
if (valueList.getAddEmptyValue() == IValueListConstants.EMPTY_VALUE_ALWAYS)
{
addElement(""); //$NON-NLS-1$
realValues.add(null);
}
if (retValue instanceof IDataSet && ((IDataSet)retValue).getRowCount() > 0)
{
startBundlingEvents();
try
{
hasRealValue = false;
IDataSet dataSet = (IDataSet)retValue;
for (int i = 0; i < dataSet.getRowCount(); i++)
{
Object[] row = dataSet.getRow(i);
if (row.length == 1)
{
realValues.add(CustomValueList.handleRowData(valueList, false, 1, row, application));
}
else
{
hasRealValue = true;
realValues.add(CustomValueList.handleRowData(valueList, false, 2, row, application));
}
addElement(CustomValueList.handleRowData(valueList, false, 1, row, application));
}
}
finally
{
stopBundlingEvents();
}
}
}
});
}
catch (Exception e)
{
application.reportError("error getting data from global method valuelist", e); //$NON-NLS-1$
}
}
}
}
finally
{
filling = false;
}
}
/**
* @see com.servoy.j2db.dataprocessing.CustomValueList#fill(com.servoy.j2db.dataprocessing.IRecordInternal)
*/
@Override
public void fill(IRecordInternal parentState)
{
super.fill(parentState);
fill(parentState, null, null);
}
/**
* @see com.servoy.j2db.dataprocessing.CustomValueList#realValueIndexOf(java.lang.Object)
*/
@Override
public int realValueIndexOf(Object obj)
{
int index = super.realValueIndexOf(obj);
if (index == -1 && obj != null)
{
fill(record, null, obj);
index = super.realValueIndexOf(obj);
}
return index;
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.dataprocessing.CustomValueList#deregister()
*/
@Override
public void deregister()
{
super.deregister();
realValues = new SafeArrayList<Object>();
removeAllElements();
}
@Override
public IDataProvider[] getDependedDataProviders()
{
return new IDataProvider[0];
}
}