Skip to content

Commit f4f054d

Browse files
committed
Added Selection
1 parent 89e845e commit f4f054d

4 files changed

Lines changed: 364 additions & 0 deletions

File tree

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
A provenance-aware spreadsheet library
3+
Copyright (C) 2021-2022 Sylvain Hallé
4+
5+
This program is free software: you can redistribute it and/or modify
6+
it under the terms of the GNU Lesser General Public License as published by
7+
the Free Software Foundation, either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public License
16+
along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package ca.uqac.lif.spreadsheet.relation;
19+
20+
import ca.uqac.lif.petitpoucet.function.AtomicFunction;
21+
import ca.uqac.lif.petitpoucet.function.InvalidArgumentTypeException;
22+
import ca.uqac.lif.petitpoucet.function.InvalidNumberOfArgumentsException;
23+
24+
/**
25+
* A function taking as input a {@link NamedRow}, and returning the value of a
26+
* given attribute in this row.
27+
* @author Sylvain Hallé
28+
*/
29+
public class AttributeValue extends AtomicFunction
30+
{
31+
/*@ non_null @*/ protected final Object m_attributeName;
32+
33+
/**
34+
* Obtains an instance of the function.
35+
* @param attribute_name The name of the attribute to fetch inside a
36+
* named row
37+
* @return The instance
38+
*/
39+
/*@ non_null @*/ public static AttributeValue get(/*@ non_null @*/ Object attribute_name)
40+
{
41+
return new AttributeValue(attribute_name);
42+
}
43+
44+
/**
45+
* Creates a new instance of the function.
46+
* @param attribute_name The name of the attribute to fetch inside a
47+
* named row
48+
*/
49+
protected AttributeValue(/*@ non_null @*/ Object attribute_name)
50+
{
51+
super(1, 1);
52+
m_attributeName = attribute_name;
53+
}
54+
55+
@Override
56+
protected Object[] getValue(Object... inputs) throws InvalidNumberOfArgumentsException
57+
{
58+
if (!(inputs[0] instanceof NamedRow))
59+
{
60+
throw new InvalidArgumentTypeException("Input argument must be a named row");
61+
}
62+
NamedRow r = (NamedRow) inputs[0];
63+
return new Object[] {r.valueOf(m_attributeName)};
64+
}
65+
66+
@Override
67+
public String toString()
68+
{
69+
if (m_attributeName == null)
70+
{
71+
return "null";
72+
}
73+
return m_attributeName.toString();
74+
}
75+
76+
@Override
77+
public AttributeValue duplicate(boolean with_state)
78+
{
79+
AttributeValue av = get(m_attributeName);
80+
super.copyInto(av, with_state);
81+
return av;
82+
}
83+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
A provenance-aware spreadsheet library
3+
Copyright (C) 2021-2022 Sylvain Hallé
4+
5+
This program is free software: you can redistribute it and/or modify
6+
it under the terms of the GNU Lesser General Public License as published by
7+
the Free Software Foundation, either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public License
16+
along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package ca.uqac.lif.spreadsheet.relation;
19+
20+
import ca.uqac.lif.spreadsheet.Spreadsheet;
21+
22+
/**
23+
* A {@link Row} that keeps track of the name of each column.
24+
* @author Sylvain Hallé
25+
*/
26+
public class NamedRow extends Row
27+
{
28+
/**
29+
* The name of each column.
30+
*/
31+
/*@ non_null @*/ protected final Object[] m_columnNames;
32+
33+
/**
34+
* Creates a new named row.
35+
* @param col_names The name of each attribute
36+
* @param values The value of each attribute
37+
*/
38+
public NamedRow(Object[] col_names, Object[] values)
39+
{
40+
super(values);
41+
m_columnNames = col_names;
42+
}
43+
44+
/**
45+
* Gets the value associated to a column name.
46+
* @param col_name The name of the column
47+
* @return The corresponding value, or <tt>null</tt> if no such column name
48+
* exists
49+
*/
50+
public Object valueOf(Object col_name)
51+
{
52+
for (int i = 0; i < m_columnNames.length; i++)
53+
{
54+
if (Spreadsheet.same(m_columnNames[i], col_name))
55+
{
56+
return m_contents[i];
57+
}
58+
}
59+
return null;
60+
}
61+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
A provenance-aware spreadsheet library
3+
Copyright (C) 2021-2022 Sylvain Hallé
4+
5+
This program is free software: you can redistribute it and/or modify
6+
it under the terms of the GNU Lesser General Public License as published by
7+
the Free Software Foundation, either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public License
16+
along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package ca.uqac.lif.spreadsheet.relation;
19+
20+
import java.util.ArrayList;
21+
import java.util.List;
22+
23+
import ca.uqac.lif.dag.LabelledNode;
24+
import ca.uqac.lif.petitpoucet.NodeFactory;
25+
import ca.uqac.lif.petitpoucet.function.Function;
26+
import ca.uqac.lif.petitpoucet.function.InvalidArgumentTypeException;
27+
import ca.uqac.lif.petitpoucet.function.InvalidNumberOfArgumentsException;
28+
import ca.uqac.lif.spreadsheet.Spreadsheet;
29+
30+
public class Selection extends RelationalOperator
31+
{
32+
/*@ non_null @*/ protected final Function m_condition;
33+
34+
/**
35+
* Creates a new instance of the selection function.
36+
* @param sort_output Set to <tt>true</tt> to sort rows of the output,
37+
* <tt>false</tt> otherwise
38+
* @param condition The condition to evaluate on each row
39+
*/
40+
public Selection(boolean sort_output, Function condition)
41+
{
42+
super(1);
43+
m_sortOutput = sort_output;
44+
m_condition = condition;
45+
}
46+
47+
/**
48+
* Creates a new instance of the selection function, assuming unsorted
49+
* rows in the output.
50+
* @param condition The condition to evaluate on each row
51+
*/
52+
public Selection(Function condition)
53+
{
54+
this(false, condition);
55+
}
56+
57+
@Override
58+
protected LabelledNode getConnectorNode(NodeFactory f)
59+
{
60+
return f.getOrNode();
61+
}
62+
63+
@Override
64+
protected Object[] getValue(Object... inputs) throws InvalidNumberOfArgumentsException
65+
{
66+
m_mapping.clear();
67+
if (!(inputs[0] instanceof Spreadsheet))
68+
{
69+
throw new InvalidArgumentTypeException("Argument is not a spreadsheet");
70+
}
71+
Spreadsheet s = (Spreadsheet) inputs[0];
72+
Object[] headers = s.getRow(0);
73+
List<Row> row_list = new ArrayList<Row>();
74+
for (int s_row = 1; s_row < s.getHeight(); s_row++)
75+
{
76+
Function condition = m_condition.duplicate();
77+
NamedRow r = new NamedRow(headers, s.getRow(s_row));
78+
Object o;
79+
if (condition.getInputArity() == 0)
80+
{
81+
// We consider the case where the function is a constant
82+
o = condition.evaluate()[0];
83+
}
84+
else
85+
{
86+
o = condition.evaluate(r)[0];
87+
}
88+
if (Boolean.TRUE.equals(o))
89+
{
90+
// Keep row
91+
row_list.add(r);
92+
List<Integer[]> tuples = new ArrayList<Integer[]>(1);
93+
tuples.add(new Integer[] {0, s_row});
94+
m_mapping.add(tuples);
95+
}
96+
}
97+
return new Object[] {createOutput(headers, row_list)};
98+
}
99+
100+
@Override
101+
public String toString()
102+
{
103+
return "\u03c3 [" + m_condition + "]";
104+
}
105+
106+
@Override
107+
public Selection duplicate(boolean with_state)
108+
{
109+
Selection sel = new Selection(m_sortOutput, m_condition.duplicate(with_state));
110+
copyInto(sel, with_state);
111+
return sel;
112+
}
113+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
A provenance-aware spreadsheet library
3+
Copyright (C) 2021-2022 Sylvain Hallé
4+
5+
This program is free software: you can redistribute it and/or modify
6+
it under the terms of the GNU Lesser General Public License as published by
7+
the Free Software Foundation, either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public License
16+
along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package ca.uqac.lif.spreadsheet.relation;
19+
20+
import static org.junit.Assert.*;
21+
22+
import org.junit.Test;
23+
24+
import static ca.uqac.lif.dag.NodeConnector.connect;
25+
26+
import ca.uqac.lif.petitpoucet.ComposedPart;
27+
import ca.uqac.lif.petitpoucet.PartNode;
28+
import ca.uqac.lif.petitpoucet.function.Circuit;
29+
import ca.uqac.lif.petitpoucet.function.Constant;
30+
import ca.uqac.lif.petitpoucet.function.NthInput;
31+
import ca.uqac.lif.petitpoucet.function.NthOutput;
32+
import ca.uqac.lif.petitpoucet.function.number.IsGreaterThan;
33+
import ca.uqac.lif.spreadsheet.Cell;
34+
import ca.uqac.lif.spreadsheet.Spreadsheet;
35+
36+
/**
37+
* Unit tests for {@link Selection}.
38+
*/
39+
public class SelectionTest
40+
{
41+
@Test
42+
public void test1()
43+
{
44+
Spreadsheet s = Spreadsheet.read(3, 4,
45+
"A", "B", "C",
46+
3, 1, "a",
47+
4, 1, "b",
48+
5, 5, "c");
49+
Selection f = new Selection(new Constant(true));
50+
Spreadsheet out = (Spreadsheet) f.evaluate(s)[0];
51+
assertEquals(s, out);
52+
}
53+
54+
@Test
55+
public void test2()
56+
{
57+
Spreadsheet s = Spreadsheet.read(3, 4,
58+
"A", "B", "C",
59+
3, 1, "a",
60+
4, 1, "b",
61+
5, 5, "c");
62+
Circuit c = new Circuit(1, 1, "> 3");
63+
{
64+
AttributeValue a = AttributeValue.get("A");
65+
IsGreaterThan gt = new IsGreaterThan();
66+
Constant three = new Constant(3);
67+
connect(a, 0, gt, 0);
68+
connect(three, 0, gt, 1);
69+
c.associateInput(0, a.getInputPin(0));
70+
c.associateOutput(0, gt.getOutputPin(0));
71+
c.addNodes(a, gt, three);
72+
}
73+
Selection f = new Selection(c);
74+
Spreadsheet out = (Spreadsheet) f.evaluate(s)[0];
75+
assertEquals(Spreadsheet.read(3, 3,
76+
"A", "B", "C",
77+
4, 1, "b",
78+
5, 5, "c"), out);
79+
}
80+
81+
@Test
82+
public void testExplanation1()
83+
{
84+
Spreadsheet s = Spreadsheet.read(3, 4,
85+
"A", "B", "C",
86+
3, 1, "a",
87+
4, 1, "b",
88+
5, 5, "c");
89+
Circuit c = new Circuit(1, 1, "> 3");
90+
{
91+
AttributeValue a = AttributeValue.get("A");
92+
IsGreaterThan gt = new IsGreaterThan();
93+
Constant three = new Constant(3);
94+
connect(a, 0, gt, 0);
95+
connect(three, 0, gt, 1);
96+
c.associateInput(0, a.getInputPin(0));
97+
c.associateOutput(0, gt.getOutputPin(0));
98+
c.addNodes(a, gt, three);
99+
}
100+
Selection f = new Selection(c);
101+
f.evaluate(s);
102+
PartNode root = f.getExplanation(ComposedPart.compose(Cell.get(1, 1), NthOutput.FIRST));
103+
assertEquals(1, root.getOutputLinks(0).size());
104+
PartNode child = (PartNode) root.getOutputLinks(0).get(0).getNode();
105+
assertEquals(ComposedPart.compose(Cell.get(1, 2), NthInput.FIRST), child.getPart());
106+
}
107+
}

0 commit comments

Comments
 (0)