/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.lang.reflect.features;
import gw.lang.PublishedName;
import gw.lang.reflect.IFeatureInfo;
import gw.lang.reflect.IMethodInfo;
import gw.lang.reflect.IParameterInfo;
import gw.lang.reflect.IType;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class MethodChainReference<R, T> extends FeatureReference<R, T> implements IMethodReference<R, T>, IFeatureChain
{
private FeatureReference _root;
private IType _rootType;
private IMethodInfo _mi;
private Object[] _boundValues;
public MethodChainReference( IType rootType, FeatureReference root, String funcName, IType[] params, Object[] boundValues )
{
_root = root;
_rootType = rootType;
_mi = MethodReference.getMethodInfo(rootType, funcName, params );
_boundValues = boundValues;
}
public Object evaluate( Object... args )
{
return evaluate( Arrays.asList( args ).iterator() );
}
@Override
protected Object evaluate( Iterator args ) {
Object ctx = _root.evaluate(args);
IMethodInfo mi = getMethodInfo();
if( _boundValues != null )
{
args = Arrays.asList(_boundValues).iterator();
}
Object[] argArray = new Object[mi.getParameters().length];
for (int i = 0; i < argArray.length; i++) {
argArray[i] = args.next();
}
return mi.getCallHandler().handleCall(ctx, argArray);
}
@Override
public List<IType> getFullArgTypes() {
List argTypes = _root.getFullArgTypes();
if( _boundValues == null )
{
for (IParameterInfo pi : _mi.getParameters()) {
argTypes.add(pi.getFeatureType());
}
}
return argTypes;
}
@Override
public IMethodInfo getMethodInfo() {
return _mi;
}
@PublishedName("invoke")
@Override
public T getinvoke()
{
return toBlock();
}
@Override
public T toBlock() {
return (T) BlockWrapper.toBlock(this);
}
@Override
public Object[] getBoundArgValues()
{
return _boundValues;
}
@Override
public IType getRootType() {
return _rootType;
}
@Override
public IFeatureInfo getFeatureInfo() {
return getMethodInfo();
}
public IFeatureReference getRootFeatureReference() {
return _root;
}
public Object[] getBoundValues() {
return _boundValues;
}
@Override
public boolean equals( Object o )
{
if( this == o )
{
return true;
}
if( o == null || getClass() != o.getClass() )
{
return false;
}
MethodChainReference that = (MethodChainReference)o;
// Probably incorrect - comparing Object[] arrays with Arrays.equals
if( !Arrays.equals( _boundValues, that._boundValues ) )
{
return false;
}
if( _mi != null ? !_mi.equals( that._mi ) : that._mi != null )
{
return false;
}
if( _root != null ? !_root.equals( that._root ) : that._root != null )
{
return false;
}
if( _rootType != null ? !_rootType.equals( that._rootType ) : that._rootType != null )
{
return false;
}
return true;
}
@Override
public int hashCode()
{
int result = _root != null ? _root.hashCode() : 0;
result = 31 * result + (_rootType != null ? _rootType.hashCode() : 0);
result = 31 * result + (_mi != null ? _mi.hashCode() : 0);
result = 31 * result + (_boundValues != null ? Arrays.hashCode( _boundValues ) : 0);
return result;
}
}