/******************************************************************************* * Copyright (c) 2014 Open Door Logistics (www.opendoorlogistics.com) * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser Public License v3 * which accompanies this distribution, and is available at http://www.gnu.org/licenses/lgpl.txt ******************************************************************************/ package com.opendoorlogistics.core.formulae.definitions; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import com.opendoorlogistics.core.formulae.FunctionFactory; import com.opendoorlogistics.core.formulae.definitions.FunctionDefinition.FunctionArgument; import com.opendoorlogistics.core.utils.strings.Strings; public final class FunctionDefinition implements Iterable<FunctionArgument> { private final String name; private final List<FunctionArgument> args = new ArrayList<>(); private final FunctionType type; private FunctionFactory factory; private String description; private int operatorPrecendence=Integer.MAX_VALUE; private String group; public enum FunctionType { OPERATOR,FUNCTION, CONSTANT } public enum ArgumentType { GENERAL, STRING_CONSTANT, TABLE_REFERENCE_CONSTANT } public FunctionDefinition(String name) { this(FunctionType.FUNCTION, name); } public FunctionDefinition(FunctionType type, String name) { this.name = name; this.type = type; } public static class FunctionArgument { private final String name; private final ArgumentType argType; private final String description; private final boolean varargs; public FunctionArgument(String name, String description) { this(name, ArgumentType.GENERAL, description, false); } public FunctionArgument(String name, ArgumentType argType, String description, boolean varArgs) { this.name = name; this.argType = argType; this.description = description; this.varargs = varArgs; } public String getName() { return name; } public boolean isConstantString() { return argType == ArgumentType.STRING_CONSTANT || argType == ArgumentType.TABLE_REFERENCE_CONSTANT; } public ArgumentType getArgumentType() { return argType; } public String getDescription() { return description; } public boolean isVarArgs() { return varargs; } } public int addArg(String name, String description) { return addArg(name, ArgumentType.GENERAL, description); } public int addArg(String name, ArgumentType argType) { return addArg(name, argType, null); } public int addArg(String name) { return addArg(name, ArgumentType.GENERAL, null); } public String getName() { return name; } public FunctionDefinition deepCopy() { FunctionDefinition ret = new FunctionDefinition(name); for (FunctionArgument arg : this) { ret.addArg(arg.getName(), arg.getArgumentType(), arg.getDescription(), arg.isVarArgs()); } return ret; } public int addArg(String name, ArgumentType argType, String description) { return addArg(name, argType, description, false); } public int addVarArgs(String name, ArgumentType argType, String description) { return addArg(name, argType, description, true); } public boolean hasVarArgs() { for (FunctionArgument arg : args) { if (arg.isVarArgs()) { return true; } } return false; } private int addArg(String name, ArgumentType argType, String description, boolean isVarArgs) { return addArg(new FunctionArgument(name, argType, description, isVarArgs)); } public int addArg(FunctionArgument arg){ checkNameOk(arg.getName()); if (hasVarArgs()) { throw new RuntimeException("Varargs must be at the end of the function and we can only have one of them."); } args.add(arg); return args.size()-1; } private void checkNameOk(String name) { if (Strings.std(name).length() == 0) { throw new RuntimeException(); } if (indexOf(name) != -1) { throw new RuntimeException(); } } public int nbArgs() { return args.size(); } public FunctionArgument getArg(int i) { return args.get(i); } public int indexOf(String s) { for (int i = 0; i < args.size(); i++) { if (Strings.equalsStd(s, getArg(i).getName())) { return i; } } return -1; } @Override public Iterator<FunctionArgument> iterator() { return args.iterator(); } @Override public String toString() { return getSignature(false); } public String getSignature(boolean html) { StringBuilder builder = new StringBuilder(); if(html){ builder.append("<html><b>"); } builder.append(getName()); if(html){ builder.append("</b>"); } switch (type) { case FUNCTION: builder.append("("); for (int i = 0; i < nbArgs(); i++) { if (i > 0) { builder.append(", "); } FunctionArgument arg = getArg(i); builder.append(arg.getName()); if (arg.isVarArgs()) { builder.append("..."); } } builder.append(")"); break; case CONSTANT: break; case OPERATOR: break; } if(html){ builder.append("</html>"); } return builder.toString(); } public FunctionFactory getFactory() { return factory; } public void setFactory(FunctionFactory factory) { this.factory = factory; } public FunctionType getType() { return type; } public int getOperatorPrecendence() { return operatorPrecendence; } public void setOperatorPrecendence(int operatorPrecendence) { this.operatorPrecendence = operatorPrecendence; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getGroup() { return group; } public void setGroup(String group) { this.group = group; } }