-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #118 from iliclaey/join-function
Built-in join function
- Loading branch information
Showing
19 changed files
with
403 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
127 changes: 127 additions & 0 deletions
127
panc/src/main/java/org/quattor/pan/dml/functions/Join.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
package org.quattor.pan.dml.functions; | ||
|
||
import org.quattor.pan.dml.Operation; | ||
import org.quattor.pan.dml.data.*; | ||
import org.quattor.pan.exceptions.EvaluationException; | ||
import org.quattor.pan.exceptions.SyntaxException; | ||
import org.quattor.pan.template.Context; | ||
import org.quattor.pan.template.SourceRange; | ||
|
||
import java.util.ArrayList; | ||
|
||
import static org.quattor.pan.utils.MessageUtils.MSG_SECOND_ARG_LIST_OR_VARIABLE_REF; | ||
import static org.quattor.pan.utils.MessageUtils.MSG_VALUE_CANNOT_BE_NULL; | ||
import static org.quattor.pan.utils.MessageUtils.MSG_FIRST_STRING_ARG_REQ; | ||
import static org.quattor.pan.utils.MessageUtils.MSG_TWO_OR_MORE_ARG_REQ; | ||
|
||
/** | ||
* Created by iliclaey. | ||
* | ||
* This only allows strings to be passed as arguments. | ||
* If you want to be able to pass other types, remove the check whether the arguments are strings. | ||
* In execute, make sure the values are somehow converted to strings, since a list of strings is | ||
* used to perform the join. | ||
*/ | ||
final public class Join extends BuiltInFunction { | ||
|
||
protected Join(SourceRange sourceRange, Operation... operations) { | ||
super("join", sourceRange, operations); | ||
} | ||
|
||
public static Operation getInstance(SourceRange sourceRange, Operation... operations) throws SyntaxException { | ||
|
||
if (operations.length < 2) { | ||
throw SyntaxException.create(sourceRange, MSG_TWO_OR_MORE_ARG_REQ, "join"); | ||
} | ||
|
||
// The first and second argument can't be null. | ||
if (operations[0] instanceof Null || operations[1] instanceof Null) { | ||
throw SyntaxException.create(sourceRange, MSG_VALUE_CANNOT_BE_NULL, "join"); | ||
} | ||
|
||
// If there are only two arguments, the second argument needs to be a list. | ||
if (operations.length == 2) { | ||
if (operations[1] instanceof Element) { | ||
if (!(operations[1] instanceof ListResource)) { | ||
throw SyntaxException.create(sourceRange, MSG_SECOND_ARG_LIST_OR_VARIABLE_REF, "join"); | ||
} | ||
} | ||
} | ||
|
||
return new Join(sourceRange, operations); | ||
} | ||
|
||
@Override | ||
public Element execute(Context context) throws EvaluationException { | ||
|
||
assert (ops.length != 1); | ||
|
||
// Extract the first argument. This must be a string value. | ||
String delimeter = null; | ||
try { | ||
delimeter = ((StringProperty) ops[0].execute(context)).getValue(); | ||
} catch (ClassCastException cce) { | ||
throw new EvaluationException("first argument in join() must be a string", getSourceRange(), context); | ||
} | ||
|
||
// Create a list containing all elements we need to join. | ||
ArrayList<String> result = new ArrayList<String>(); | ||
|
||
// If the second argument is a ListResource, add the strings to the result-list. | ||
if (ops.length == 2) { | ||
|
||
// Double check whether the second argument is actually a list. | ||
Element list = ops[1].execute(context); | ||
|
||
if (list instanceof ListResource) { | ||
|
||
// Loop over the list items and convert them to strings. | ||
Resource.Iterator it = ((ListResource) list).iterator(); | ||
while (it.hasNext()) { | ||
Element e = it.next().getValue(); | ||
|
||
if (e instanceof Resource) { | ||
throw new EvaluationException( | ||
"join() doesn't accept nested elements in the passed list", | ||
getSourceRange(), context); | ||
} | ||
|
||
if (!(e instanceof StringProperty)) { | ||
throw new EvaluationException( | ||
"join() only accepts strings as elements in the list", | ||
getSourceRange(), context); | ||
} | ||
|
||
result.add(((StringProperty) e).getValue()); | ||
} | ||
|
||
} else { | ||
throw new EvaluationException( | ||
"join() only accepts strings or a list of strings as input arguments", | ||
getSourceRange(), context); | ||
} | ||
|
||
// If all arguments are passed individually, add them to a list. | ||
} else { | ||
int length = ops.length; | ||
|
||
for (int i = 1; i < length; i++) { | ||
Element e = ops[i].execute(context); | ||
|
||
if (e instanceof ListResource) { | ||
throw new EvaluationException( | ||
"join() only accepts a single list as an argument or all the arguments individually", | ||
getSourceRange(), context); | ||
} else if (!(e instanceof StringProperty)) { | ||
throw new EvaluationException( | ||
"join() only accepts strings or a list of strings as input arguments", | ||
getSourceRange(), context); | ||
} | ||
|
||
result.add(((StringProperty) e).getValue()); | ||
} | ||
} | ||
|
||
return StringProperty.getInstance(String.join(delimeter, result)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
112 changes: 112 additions & 0 deletions
112
panc/src/test/java/org/quattor/pan/dml/functions/JoinTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
package org.quattor.pan.dml.functions; | ||
|
||
import org.junit.Test; | ||
import org.quattor.pan.dml.data.*; | ||
import org.quattor.pan.exceptions.EvaluationException; | ||
import org.quattor.pan.exceptions.SyntaxException; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
import static org.junit.Assert.assertTrue; | ||
|
||
/** | ||
* Created by iliclaey. | ||
*/ | ||
public class JoinTest extends BuiltInFunctionTestUtils { | ||
|
||
@Test | ||
public void checkGetInstance() { | ||
checkClassRequirements(Join.class); | ||
} | ||
|
||
@Test(expected = SyntaxException.class) | ||
public void testTooFewArguments() throws SyntaxException { | ||
Join.getInstance(null); | ||
} | ||
|
||
@Test(expected = SyntaxException.class) | ||
public void testNullValueFirstArg() throws SyntaxException { | ||
Join.getInstance(null, Null.getInstance(), new ListResource()); | ||
} | ||
|
||
@Test(expected = SyntaxException.class) | ||
public void testNullValueSecondArg() throws SyntaxException { | ||
Join.getInstance(null, StringProperty.getInstance(","), Null.getInstance()); | ||
} | ||
|
||
@Test(expected = EvaluationException.class) | ||
public void testInvalidFirstArg() throws SyntaxException { | ||
runDml(Join.getInstance(null, LongProperty.getInstance(0L), new ListResource())); | ||
} | ||
|
||
@Test(expected = SyntaxException.class) | ||
public void testInvalidSecondArg() throws SyntaxException { | ||
runDml(Join.getInstance(null, StringProperty.getInstance(","), new HashResource())); | ||
} | ||
|
||
@Test(expected = EvaluationException.class) | ||
public void testInvalidArgs1() throws SyntaxException { | ||
runDml(Join.getInstance(null, StringProperty.getInstance(","), | ||
StringProperty.getInstance("First"), LongProperty.getInstance(0L))); | ||
} | ||
|
||
@Test(expected = EvaluationException.class) | ||
public void testInvalidArgs2() throws SyntaxException { | ||
runDml(Join.getInstance(null, StringProperty.getInstance(","), | ||
StringProperty.getInstance("a"), new ListResource())); | ||
} | ||
|
||
@Test(expected = EvaluationException.class) | ||
public void testInvalidTypeSecondArg() throws SyntaxException { | ||
Element[] args = { | ||
LongProperty.getInstance(1), | ||
LongProperty.getInstance(2), | ||
LongProperty.getInstance(3) | ||
}; | ||
|
||
runDml(Join.getInstance(null, StringProperty.getInstance(","), new ListResource(args))); | ||
} | ||
|
||
@Test(expected = EvaluationException.class) | ||
public void testNestedElements() throws SyntaxException { | ||
Element[] args = { new ListResource() }; | ||
|
||
runDml(Join.getInstance(null, StringProperty.getInstance("OK"), new ListResource(args))); | ||
} | ||
|
||
@Test | ||
public void testJoinWithList() throws SyntaxException { | ||
String expected = new String("a-b-c"); | ||
|
||
// Execute operation | ||
Element[] args = { | ||
StringProperty.getInstance("a"), | ||
StringProperty.getInstance("b"), | ||
StringProperty.getInstance("c") | ||
}; | ||
|
||
Element e = runDml(Join.getInstance(null, StringProperty.getInstance("-"), new ListResource(args))); | ||
|
||
// Check result | ||
assertTrue(e instanceof StringProperty); | ||
String result = ((StringProperty) e).getValue(); | ||
assertEquals(result, expected); | ||
} | ||
|
||
@Test | ||
public void testJoinWithoutList() throws SyntaxException { | ||
String expected = new String("a-b-c"); | ||
|
||
// Execute operation | ||
Element e = runDml(Join.getInstance(null, | ||
StringProperty.getInstance("-"), | ||
StringProperty.getInstance("a"), | ||
StringProperty.getInstance("b"), | ||
StringProperty.getInstance("c") | ||
)); | ||
|
||
// Check result | ||
assertTrue(e instanceof StringProperty); | ||
String result = ((StringProperty) e).getValue(); | ||
assertEquals(result, expected); | ||
} | ||
} |
Oops, something went wrong.