/*
* This file is part of Skript.
*
* Skript is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Skript 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Skript. If not, see <http://www.gnu.org/licenses/>.
*
*
* Copyright 2011-2013 Peter Güttinger
*
*/
package ch.njol.skript.lang.function;
import java.util.Arrays;
import org.eclipse.jdt.annotation.Nullable;
import ch.njol.skript.classes.ClassInfo;
import ch.njol.util.coll.CollectionUtils;
/**
* @author Peter Güttinger
*/
public abstract class Function<T> {
final String name;
final Parameter<?>[] parameters;
@Nullable
final ClassInfo<T> returnType;
final boolean single;
public Function(final String name, final Parameter<?>[] parameters, final @Nullable ClassInfo<T> returnType, final boolean single) {
this.name = name;
this.parameters = parameters;
this.returnType = returnType;
this.single = single;
}
public String getName() {
return name;
}
@SuppressWarnings("null")
public Parameter<?> getParameter(final int index) {
return parameters[index];
}
public Parameter<?>[] getParameters() {
return parameters;
}
@Nullable
public ClassInfo<T> getReturnType() {
return returnType;
}
public boolean isSingle() {
return single;
}
// TODO allow setting parameters by name
public int getMinParameters() {
for (int i = parameters.length - 1; i >= 0; i--) {
if (parameters[i].def == null)
return i + 1;
}
return 0;
}
public int getMaxParameters() {
return parameters.length;
}
// FIXME what happens with a delay in a function?
/**
* @param params An array with at least {@link #getMinParameters()} elements and at most {@link #getMaxParameters()} elements.
* @return The result of the function
*/
@SuppressWarnings("null")
@Nullable
public final T[] execute(final Object[][] params) {
final FunctionEvent e = new FunctionEvent();
if (params.length > parameters.length) {
assert false : params.length;
return null;
}
final Object[][] ps = params.length < parameters.length ? Arrays.copyOf(params, parameters.length) : params;
assert ps != null;
for (int i = 0; i < parameters.length; i++) {
final Parameter<?> p = parameters[i];
final Object[] val = i < params.length ? params[i] : p.def != null ? p.def.getArray(e) : null;
if (val == null || val.length == 0)
return null;
ps[i] = val;
}
final T[] r = execute(e, ps);
assert returnType == null ? r == null : r == null || (r.length <= 1 || !single) && !CollectionUtils.contains(r, null) && returnType.getC().isAssignableFrom(r.getClass().getComponentType()) : this + "; " + Arrays.toString(r);
return r == null || r.length > 0 ? r : null;
}
/**
* @param e
* @param params An array containing as many arrays as this function has parameters. The contained arrays are neither null nor empty, and are of type Object[] (i.e. not of the
* actual parameters' types).
* @return Whatever this function is supposed to return. May be null or empty, but must not contain null elements.
*/
@Nullable
public abstract T[] execute(FunctionEvent e, final Object[][] params);
@Override
public String toString() {
return "function " + name;
}
}