/*
* Copyright 2014 (C) Tom Parker <thpr@users.sourceforge.net>
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library 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 Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package plugin.function;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import junit.framework.TestCase;
import pcgen.base.formatmanager.FormatUtilities;
import pcgen.base.formatmanager.SimpleFormatManagerLibrary;
import pcgen.base.formula.base.EvaluationManager;
import pcgen.base.formula.base.FormulaSemantics;
import pcgen.base.formula.base.VariableID;
import pcgen.base.formula.base.VariableLibrary;
import pcgen.base.formula.base.WriteableVariableStore;
import pcgen.base.formula.operator.number.NumberMinus;
import pcgen.base.formula.parse.SimpleNode;
import pcgen.base.formula.visitor.EvaluateVisitor;
import pcgen.base.formula.visitor.ReconstructionVisitor;
import pcgen.base.formula.visitor.SemanticsVisitor;
import pcgen.base.util.DoubleKeyMap;
import pcgen.base.util.FormatManager;
import pcgen.base.util.Indirect;
import pcgen.base.util.ObjectDatabase;
import pcgen.cdom.base.Loadable;
import pcgen.cdom.format.table.ColumnFormatFactory;
import pcgen.cdom.format.table.DataTable;
import pcgen.cdom.format.table.TableColumn;
import pcgen.cdom.format.table.TableFormatFactory;
import plugin.function.testsupport.AbstractFormulaTestCase;
import plugin.function.testsupport.TestUtilities;
public class LookupFunctionTest extends AbstractFormulaTestCase
{
private SimpleFormatManagerLibrary formatLibrary;
@Override
protected void setUp() throws Exception
{
super.setUp();
formatLibrary = new SimpleFormatManagerLibrary();
FormatUtilities.loadDefaultFormats(formatLibrary);
getFunctionLibrary().addFunction(new LookupFunction());
getOperatorLibrary().addAction(new NumberMinus());
}
public DataTable doTableSetup()
{
DataTable dt = new DataTable();
dt.setName("A");
TableColumn c1 = new TableColumn();
c1.setName("Name");
c1.setFormatManager(stringManager);
TableColumn c2 = new TableColumn();
c2.setName("Value");
c2.setFormatManager(numberManager);
dt.addColumn(c1);
dt.addColumn(c2);
List<Object> row = new ArrayList<>();
row.add("This");
row.add(1);
dt.addRow(row);
row.clear();
row.add("That");
row.add(2);
dt.addRow(row);
row.clear();
row.add("The \"Other\"");
row.add(3);
dt.addRow(row);
row.clear();
return dt;
}
@Test
public void testInvalidWrongArg()
{
String formula = "lookup(2)";
SimpleNode node = TestUtilities.doParse(formula);
isNotValid(formula, node, numberManager, null);
formula = "lookup(2, 3, 4, 5)";
node = TestUtilities.doParse(formula);
isNotValid(formula, node, numberManager, null);
}
@Test
public void testInvalidWrongFormat1()
{
Finder finder = new Finder();
finder.map.put(TableColumn.class, "Value",
buildColumn("Value", numberManager));
finder.map.put(TableColumn.class, "Result",
buildColumn("Result", stringManager));
VariableLibrary vl = getVariableLibrary();
WriteableVariableStore vs = getVariableStore();
ColumnFormatFactory cfac = new ColumnFormatFactory(finder);
FormatManager<?> columnMgr = cfac.build("STRING", formatLibrary);
vl.assertLegalVariableID("ResultColumn", getGlobalScope(), columnMgr);
VariableID columnID =
vl.getVariableID(getGlobalScopeInst(), "ResultColumn");
vs.put(columnID, columnMgr.convert("Value"));
String formula = "lookup(3,\"That\",ResultColumn)";
SimpleNode node = TestUtilities.doParse(formula);
isNotValid(formula, node, numberManager, null);
}
@Test
public void testInvalidWrongFormat2()
{
Finder finder = new Finder();
DataTable dt = doTableSetup();
finder.map.put(DataTable.class, "A", dt);
finder.map.put(TableColumn.class, "Value",
buildColumn("Value", numberManager));
finder.map.put(TableColumn.class, "Result",
buildColumn("Result", stringManager));
VariableLibrary vl = getVariableLibrary();
WriteableVariableStore vs = getVariableStore();
TableFormatFactory fac = new TableFormatFactory(finder);
FormatManager<?> tableMgr = fac.build("STRING,NUMBER", formatLibrary);
vl.assertLegalVariableID("TableA", getGlobalScope(), tableMgr);
VariableID tableID = vl.getVariableID(getGlobalScopeInst(), "TableA");
vs.put(tableID, tableMgr.convert("A"));
ColumnFormatFactory cfac = new ColumnFormatFactory(finder);
FormatManager<?> columnMgr = cfac.build("STRING", formatLibrary);
vl.assertLegalVariableID("ResultColumn", getGlobalScope(), columnMgr);
VariableID columnID =
vl.getVariableID(getGlobalScopeInst(), "ResultColumn");
vs.put(columnID, columnMgr.convert("Value"));
String formula = "lookup(TableA,3,ResultColumn)";
SimpleNode node = TestUtilities.doParse(formula);
isNotValid(formula, node, numberManager, null);
}
@Test
public void testInvalidWrongFormat3()
{
Finder finder = new Finder();
DataTable dt = doTableSetup();
finder.map.put(DataTable.class, "A", dt);
VariableLibrary vl = getVariableLibrary();
WriteableVariableStore vs = getVariableStore();
TableFormatFactory fac = new TableFormatFactory(finder);
FormatManager<?> tableMgr = fac.build("STRING,NUMBER", formatLibrary);
vl.assertLegalVariableID("TableA", getGlobalScope(), tableMgr);
VariableID tableID = vl.getVariableID(getGlobalScopeInst(), "TableA");
vs.put(tableID, tableMgr.convert("A"));
String formula = "lookup(TableA,\"That\",3)";
SimpleNode node = TestUtilities.doParse(formula);
isNotValid(formula, node, numberManager, null);
}
@Test
public void testInvalidBadSemantics1()
{
Finder finder = new Finder();
finder.map.put(TableColumn.class, "Value",
buildColumn("Value", numberManager));
finder.map.put(TableColumn.class, "Result",
buildColumn("Result", stringManager));
VariableLibrary vl = getVariableLibrary();
WriteableVariableStore vs = getVariableStore();
ColumnFormatFactory cfac = new ColumnFormatFactory(finder);
FormatManager<?> columnMgr = cfac.build("STRING", formatLibrary);
vl.assertLegalVariableID("ResultColumn", getGlobalScope(), columnMgr);
VariableID columnID =
vl.getVariableID(getGlobalScopeInst(), "ResultColumn");
vs.put(columnID, columnMgr.convert("Value"));
String formula = "lookup(badf(),\"That\",ResultColumn)";
SimpleNode node = TestUtilities.doParse(formula);
isNotValid(formula, node, numberManager, null);
}
@Test
public void testInvalidBadSemantics2()
{
Finder finder = new Finder();
DataTable dt = doTableSetup();
finder.map.put(DataTable.class, "A", dt);
finder.map.put(TableColumn.class, "Value",
buildColumn("Value", numberManager));
finder.map.put(TableColumn.class, "Result",
buildColumn("Result", stringManager));
VariableLibrary vl = getVariableLibrary();
WriteableVariableStore vs = getVariableStore();
TableFormatFactory fac = new TableFormatFactory(finder);
FormatManager<?> tableMgr = fac.build("STRING,NUMBER", formatLibrary);
vl.assertLegalVariableID("TableA", getGlobalScope(), tableMgr);
VariableID tableID = vl.getVariableID(getGlobalScopeInst(), "TableA");
vs.put(tableID, tableMgr.convert("A"));
ColumnFormatFactory cfac = new ColumnFormatFactory(finder);
FormatManager<?> columnMgr = cfac.build("STRING", formatLibrary);
vl.assertLegalVariableID("ResultColumn", getGlobalScope(), columnMgr);
VariableID columnID =
vl.getVariableID(getGlobalScopeInst(), "ResultColumn");
vs.put(columnID, columnMgr.convert("Value"));
String formula = "lookup(TableA,badf(),ResultColumn)";
SimpleNode node = TestUtilities.doParse(formula);
isNotValid(formula, node, numberManager, null);
}
@Test
public void testInvalidBadSemantics3()
{
Finder finder = new Finder();
DataTable dt = doTableSetup();
finder.map.put(DataTable.class, "A", dt);
finder.map.put(TableColumn.class, "Value",
buildColumn("Value", numberManager));
finder.map.put(TableColumn.class, "Result",
buildColumn("Value", stringManager));
VariableLibrary vl = getVariableLibrary();
WriteableVariableStore vs = getVariableStore();
TableFormatFactory fac = new TableFormatFactory(finder);
FormatManager<?> tableMgr = fac.build("STRING,NUMBER", formatLibrary);
vl.assertLegalVariableID("TableA", getGlobalScope(), tableMgr);
VariableID tableID = vl.getVariableID(getGlobalScopeInst(), "TableA");
vs.put(tableID, tableMgr.convert("A"));
String formula = "lookup(TableA,\"That\",badf())";
SimpleNode node = TestUtilities.doParse(formula);
isNotValid(formula, node, numberManager, null);
}
@Test
public void testBadResultColumnFormat()
{
Finder finder = new Finder();
DataTable dt = doTableSetup();
finder.map.put(DataTable.class, "A", dt);
finder.map.put(TableColumn.class, "Name",
buildColumn("Name", stringManager));
finder.map.put(TableColumn.class, "Value",
buildColumn("Value", numberManager));
finder.map.put(TableColumn.class, "Result",
buildColumn("Result", stringManager));
VariableLibrary vl = getVariableLibrary();
WriteableVariableStore vs = getVariableStore();
TableFormatFactory fac = new TableFormatFactory(finder);
FormatManager<?> tableMgr = fac.build("STRING,NUMBER", formatLibrary);
vl.assertLegalVariableID("TableA", getGlobalScope(), tableMgr);
ColumnFormatFactory cfac = new ColumnFormatFactory(finder);
FormatManager<?> columnMgr = cfac.build("STRING", formatLibrary);
vl.assertLegalVariableID("ResultColumn", getGlobalScope(), columnMgr);
VariableID tableID = vl.getVariableID(getGlobalScopeInst(), "TableA");
vs.put(tableID, tableMgr.convert("A"));
VariableID columnID =
vl.getVariableID(getGlobalScopeInst(), "ResultColumn");
vs.put(columnID, columnMgr.convert("Result"));
String formula = "lookup(TableA,\"That\",ResultColumn)";
SimpleNode node = TestUtilities.doParse(formula);
SemanticsVisitor semanticsVisitor = new SemanticsVisitor();
FormulaSemantics semantics = getManagerFactory()
.generateFormulaSemantics(getFormulaManager(), getGlobalScope(), null);
semanticsVisitor.visit(node, semantics);
if (semantics.isValid())
{
TestCase.fail("Expected Invalid Formula: " + formula);
}
}
@Test
public void testBasic()
{
Finder finder = new Finder();
DataTable dt = doTableSetup();
finder.map.put(DataTable.class, "A", dt);
finder.map.put(TableColumn.class, "Name",
buildColumn("Name", stringManager));
finder.map.put(TableColumn.class, "Value",
buildColumn("Value", numberManager));
VariableLibrary vl = getVariableLibrary();
WriteableVariableStore vs = getVariableStore();
TableFormatFactory fac = new TableFormatFactory(finder);
FormatManager<?> tableMgr = fac.build("STRING,NUMBER", formatLibrary);
vl.assertLegalVariableID("TableA", getGlobalScope(), tableMgr);
ColumnFormatFactory cfac = new ColumnFormatFactory(finder);
FormatManager<?> columnMgr = cfac.build("NUMBER", formatLibrary);
vl.assertLegalVariableID("ResultColumn", getGlobalScope(), columnMgr);
VariableID tableID = vl.getVariableID(getGlobalScopeInst(), "TableA");
vs.put(tableID, tableMgr.convert("A"));
VariableID columnID =
vl.getVariableID(getGlobalScopeInst(), "ResultColumn");
vs.put(columnID, columnMgr.convert("Value"));
String formula = "lookup(TableA,\"That\",ResultColumn)";
SimpleNode node = TestUtilities.doParse(formula);
isValid(formula, node, numberManager, null);
isStatic(formula, node, false);
evaluatesTo(formula, node, 2);
Object rv =
new ReconstructionVisitor().visit(node, new StringBuilder());
assertTrue(rv.toString().equals(formula));
}
@Test
public void testNoColumn()
{
Finder finder = new Finder();
DataTable dt = doTableSetup();
finder.map.put(DataTable.class, "A", dt);
finder.map.put(TableColumn.class, "Name",
buildColumn("Name", stringManager));
finder.map.put(TableColumn.class, "Value",
buildColumn("Value", numberManager));
finder.map.put(TableColumn.class, "Result",
buildColumn("Result", stringManager));
VariableLibrary vl = getVariableLibrary();
WriteableVariableStore vs = getVariableStore();
TableFormatFactory fac = new TableFormatFactory(finder);
FormatManager<?> tableMgr = fac.build("STRING,NUMBER", formatLibrary);
vl.assertLegalVariableID("TableA", getGlobalScope(), tableMgr);
ColumnFormatFactory cfac = new ColumnFormatFactory(finder);
FormatManager<?> columnMgr = cfac.build("NUMBER", formatLibrary);
vl.assertLegalVariableID("ResultColumn", getGlobalScope(), columnMgr);
VariableID tableID = vl.getVariableID(getGlobalScopeInst(), "TableA");
vs.put(tableID, tableMgr.convert("A"));
VariableID columnID =
vl.getVariableID(getGlobalScopeInst(), "ResultColumn");
vs.put(columnID, columnMgr.convert("Result"));
String formula = "lookup(TableA,\"That\",ResultColumn)";
SimpleNode node = TestUtilities.doParse(formula);
isValid(formula, node, numberManager, null);
isStatic(formula, node, false);
EvaluationManager manager = generateManager();
Object result = new EvaluateVisitor().visit(node, manager);
if (result instanceof Number)
{
TestCase.fail(
"Expected Invalid result, should have been a string due to invalid column: "
+ result);
}
}
@Test
public void testNoLookup()
{
Finder finder = new Finder();
DataTable dt = doTableSetup();
finder.map.put(DataTable.class, "A", dt);
finder.map.put(TableColumn.class, "Name",
buildColumn("Name", stringManager));
finder.map.put(TableColumn.class, "Value",
buildColumn("Value", numberManager));
finder.map.put(TableColumn.class, "Result",
buildColumn("Result", stringManager));
VariableLibrary vl = getVariableLibrary();
WriteableVariableStore vs = getVariableStore();
TableFormatFactory fac = new TableFormatFactory(finder);
FormatManager<?> tableMgr = fac.build("STRING,NUMBER", formatLibrary);
vl.assertLegalVariableID("TableA", getGlobalScope(), tableMgr);
ColumnFormatFactory cfac = new ColumnFormatFactory(finder);
FormatManager<?> columnMgr = cfac.build("NUMBER", formatLibrary);
vl.assertLegalVariableID("ResultColumn", getGlobalScope(), columnMgr);
VariableID tableID = vl.getVariableID(getGlobalScopeInst(), "TableA");
vs.put(tableID, tableMgr.convert("A"));
VariableID columnID =
vl.getVariableID(getGlobalScopeInst(), "ResultColumn");
vs.put(columnID, columnMgr.convert("Value"));
String formula = "lookup(TableA,\"Oh No\",ResultColumn)";
SimpleNode node = TestUtilities.doParse(formula);
isValid(formula, node, numberManager, null);
isStatic(formula, node, false);
EvaluationManager manager = generateManager();
Object result = new EvaluateVisitor().visit(node, manager);
if (!result.equals(0))
{
TestCase.fail(
"Expected Invalid result, should have been zero due to invalid column: "
+ result);
}
}
private Object buildColumn(String string, FormatManager<?> manager)
{
TableColumn tc = new TableColumn();
tc.setName(string);
tc.setFormatManager(manager);
return tc;
}
private class Finder implements ObjectDatabase
{
DoubleKeyMap<Class<?>, String, Object> map = new DoubleKeyMap<>();
@Override
public <T extends Loadable> T get(Class<T> cl, String name)
{
return (T) map.get(cl, name);
}
@Override
public <T extends Loadable> Indirect<T> getIndirect(Class<T> cl, String name)
{
throw new UnsupportedOperationException();
}
}
}