summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/Reference.java29
-rw-r--r--searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/ReferenceTestCase.java39
2 files changed, 63 insertions, 5 deletions
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/Reference.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/Reference.java
index 73e278f7d8a..eaecdf78162 100644
--- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/Reference.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/Reference.java
@@ -33,6 +33,10 @@ public class Reference extends Name implements Comparable<Reference> {
private final static Pattern identifierPattern = Pattern.compile("[A-Za-z0-9_@.\"$-]+");
+ private static boolean isValidIdentifier(String name) {
+ return identifierPattern.matcher(name).matches();
+ }
+
public Reference(String name, Arguments arguments, String output) {
this(name, arguments, output, false);
}
@@ -142,7 +146,7 @@ public class Reference extends Name implements Comparable<Reference> {
/** Creates a reference from a simple identifier. */
public static Reference fromIdentifier(String identifier) {
- if ( ! identifierPattern.matcher(identifier).matches())
+ if ( ! isValidIdentifier(identifier))
throw new IllegalArgumentException("Identifiers can only contain [A-Za-z0-9_@.\"$-]+, but was '" + identifier + "'");
return new Reference(identifier, Arguments.EMPTY, null, true);
}
@@ -156,21 +160,36 @@ public class Reference extends Name implements Comparable<Reference> {
/**
* Returns the given simple feature as a reference, or empty if it is not a valid simple
- * feature string on the form name(argument).
+ * feature string on the form name(argument) or name(argument).outputname
*/
public static Optional<Reference> simple(String feature) {
int startParenthesis = feature.indexOf('(');
- if (startParenthesis < 0)
+ if (startParenthesis < 1)
return Optional.empty();
int endParenthesis = feature.lastIndexOf(')');
String featureName = feature.substring(0, startParenthesis);
- if (startParenthesis < 1 || endParenthesis < startParenthesis) return Optional.empty();
+ if (endParenthesis < startParenthesis)
+ return Optional.empty();
String argument = feature.substring(startParenthesis + 1, endParenthesis);
if (argument.startsWith("'") || argument.startsWith("\""))
argument = argument.substring(1);
if (argument.endsWith("'") || argument.endsWith("\""))
argument = argument.substring(0, argument.length() - 1);
- return Optional.of(simple(featureName, argument));
+ if ( ! isValidIdentifier(argument))
+ return Optional.empty();
+ Reference result = simple(featureName, argument);
+ if (endParenthesis + 1 == feature.length())
+ return Optional.of(result);
+ // text after end parenthesis; must be ".outputname"
+ int lastDot = feature.lastIndexOf('.');
+ if (endParenthesis + 1 == lastDot && lastDot + 1 < feature.length()) {
+ String outputName = feature.substring(lastDot + 1);
+ if (isValidIdentifier(outputName)) {
+ result = result.withOutput(outputName);
+ return Optional.of(result);
+ }
+ }
+ return Optional.empty();
}
}
diff --git a/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/ReferenceTestCase.java b/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/ReferenceTestCase.java
index fbc7a96f1f2..1060e721363 100644
--- a/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/ReferenceTestCase.java
+++ b/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/ReferenceTestCase.java
@@ -31,4 +31,43 @@ public class ReferenceTestCase {
assertEquals("foo", new Reference("foo", new Arguments(), null).toString());
}
+ @Test
+ public void testFromString() {
+ Reference ref = Reference.fromIdentifier("foo_bar_1");
+ assertFalse(ref.isSimple());
+ assertTrue(ref.isIdentifier());
+ assertEquals(0, ref.arguments().size());
+ assertEquals(null, ref.output());
+ assertEquals("foo_bar_1", ref.toString());
+
+ ref = Reference.simple("foo_1", "bar_2");
+ assertTrue(ref.isSimple());
+ assertFalse(ref.isIdentifier());
+ assertEquals(1, ref.arguments().size());
+ assertTrue(ref.simpleArgument().isPresent());
+ assertEquals(null, ref.output());
+ assertEquals("foo_1(bar_2)", ref.toString());
+
+ assertFalse(Reference.simple("foo").isPresent());
+ assertFalse(Reference.simple("foo()").isPresent());
+ assertTrue(Reference.simple("x(y)").isPresent());
+
+ ref = Reference.simple("foo_1(bar_2)").orElseThrow();
+ assertTrue(ref.isSimple());
+ assertFalse(ref.isIdentifier());
+ assertEquals(1, ref.arguments().size());
+ assertTrue(ref.simpleArgument().isPresent());
+ assertEquals("bar_2", ref.simpleArgument().get());
+ assertEquals(null, ref.output());
+ assertEquals("foo_1(bar_2)", ref.toString());
+
+ ref = Reference.simple("foo_1(bar_2).baz_3").orElseThrow();
+ assertTrue(ref.isSimple());
+ assertFalse(ref.isIdentifier());
+ assertEquals(1, ref.arguments().size());
+ assertTrue(ref.simpleArgument().isPresent());
+ assertEquals("baz_3", ref.output());
+ assertEquals("foo_1(bar_2).baz_3", ref.toString());
+ }
+
}