[New] Added a QueryParser to parse String queries to Strolch queries

This commit is contained in:
Robert von Burg 2016-04-05 08:30:07 +02:00
parent 0246adb4ab
commit 5f71427d33
5 changed files with 242 additions and 1 deletions

View File

@ -109,7 +109,7 @@
<version>${eitchnet.privilege.version}</version>
</dependency>
<!-- main -->
<!-- Other -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
@ -120,6 +120,11 @@
<artifactId>commons-cli</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>com.github.petitparser</groupId>
<artifactId>java-petitparser</artifactId>
<version>2.0.0</version>
</dependency>
<!-- JSON -->
<dependency>

View File

@ -97,6 +97,11 @@
<artifactId>jersey-media-moxy</artifactId>
</dependency>
<dependency>
<groupId>com.github.petitparser</groupId>
<artifactId>java-petitparser</artifactId>
</dependency>
<!-- test dependencies -->
<dependency>
<groupId>li.strolch</groupId>

View File

@ -0,0 +1,112 @@
package li.strolch.model.query.parser;
import static org.petitparser.parser.primitive.CharacterParser.whitespace;
import static org.petitparser.parser.primitive.CharacterParser.word;
import static org.petitparser.parser.primitive.StringParser.ofIgnoringCase;
import org.petitparser.context.Result;
import org.petitparser.parser.Parser;
import org.petitparser.tools.CompositeParser;
import ch.eitchnet.utils.StringMatchMode;
import li.strolch.model.Order;
import li.strolch.model.Resource;
import li.strolch.model.query.IdSelection;
import li.strolch.model.query.NameSelection;
import li.strolch.model.query.OrSelection;
import li.strolch.model.query.OrderQuery;
import li.strolch.model.query.ResourceQuery;
import li.strolch.model.query.StrolchElementQuery;
import li.strolch.model.query.StrolchTypeNavigation;
import li.strolch.model.visitor.NoStrategyOrderVisitor;
import li.strolch.model.visitor.NoStrategyResourceVisitor;
public class QueryParser extends CompositeParser {
private StrolchElementQuery<?> query;
private OrSelection or;
private IdSelection idSelection;
/**
* Use static helper methods instead of constructors
*
* @param resourceQuery
*/
private QueryParser(StrolchElementQuery<?> query) {
// don't allow public construction
this.query = query;
}
private OrSelection or() {
if (this.or == null)
this.or = query.or();
return or;
}
@Override
protected void initialize() {
// [id:<value>] [name:<value>] [type:<value>] [param:<bagId>:<paramId>] [value]
Parser id = ofIgnoringCase("id:").seq(word().star().flatten()).pick(1);
Parser name = ofIgnoringCase("name:").seq(word().star().flatten()).pick(1);
Parser type = ofIgnoringCase("type:").seq(word().star().flatten()).pick(1);
def("id", id);
def("name", name);
def("type", type);
Parser query = whitespace().optional().seq(ref("type").or(ref("id")).or(ref("name")).or(whitespace())).star();
def("query", query);
def("start", ref("query"));
action("id", (String s) -> {
if (this.idSelection == null) {
this.idSelection = new IdSelection(s.trim(), StringMatchMode.ci());
or().with(this.idSelection);
} else {
this.idSelection.with(s.trim());
}
return null;
});
action("name", (String s) -> {
or().with(new NameSelection(s.trim(), StringMatchMode.ci()));
return null;
});
action("type", (String s) -> {
this.query.setNavigation(new StrolchTypeNavigation(s.trim()));
return null;
});
action("start", o -> this.query);
}
public static ResourceQuery<Resource> parseToResourceQuery(String queryString, boolean withAny) {
QueryParser parser = new QueryParser(new ResourceQuery<>());
Result result = parser.parse(queryString);
ResourceQuery<Resource> query = result.get();
query.setResourceVisitor(new NoStrategyResourceVisitor());
if (!query.hasSelection() && withAny) {
query.withAny();
}
return query;
}
public static OrderQuery<Order> parseToOrderQuery(String queryString, boolean withAny) {
QueryParser parser = new QueryParser(new OrderQuery<>());
Result result = parser.parse(queryString);
OrderQuery<Order> query = result.get();
query.setOrderVisitor(new NoStrategyOrderVisitor());
if (!query.hasSelection() && withAny) {
query.withAny();
}
return query;
}
}

View File

@ -0,0 +1,112 @@
package li.strolch.model.query.parser;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.List;
import org.junit.Test;
import li.strolch.model.Resource;
import li.strolch.model.query.IdSelection;
import li.strolch.model.query.NameSelection;
import li.strolch.model.query.OrSelection;
import li.strolch.model.query.ResourceQuery;
import li.strolch.model.query.Selection;
import li.strolch.model.query.StrolchTypeNavigation;
public class QueryParserTest {
@Test
public void shouldParseEmpty() {
ResourceQuery<Resource> query = QueryParser.parseToResourceQuery("", false);
assertFalse(query.hasNavigation());
assertFalse(query.hasSelection());
}
@Test
public void shouldParseId() {
ResourceQuery<Resource> query = QueryParser.parseToResourceQuery("id:asd", false);
OrSelection or = (OrSelection) query.getSelection();
List<Selection> selections = or.getSelections();
assertEquals(1, selections.size());
assertEquals(IdSelection.class, selections.get(0).getClass());
IdSelection idSelection = (IdSelection) selections.get(0);
List<String> ids = idSelection.getIds();
assertEquals(1, ids.size());
assertEquals("asd", ids.get(0));
assertFalse(query.hasNavigation());
}
@Test
public void shouldParseIds() {
ResourceQuery<Resource> query = QueryParser.parseToResourceQuery("id:asd id:bbb", false);
OrSelection or = (OrSelection) query.getSelection();
List<Selection> selections = or.getSelections();
assertEquals(1, selections.size());
assertEquals(IdSelection.class, selections.get(0).getClass());
IdSelection idSelection = (IdSelection) selections.get(0);
List<String> ids = idSelection.getIds();
assertEquals(2, ids.size());
assertEquals("asd", ids.get(0));
assertEquals("bbb", ids.get(1));
assertFalse(query.hasNavigation());
}
@Test
public void shouldParseName() {
ResourceQuery<Resource> query = QueryParser.parseToResourceQuery("name:asd", false);
OrSelection or = (OrSelection) query.getSelection();
List<Selection> selections = or.getSelections();
assertEquals(1, selections.size());
assertEquals(NameSelection.class, selections.get(0).getClass());
assertEquals("asd", ((NameSelection) selections.get(0)).getName());
assertFalse(query.hasNavigation());
}
@Test
public void shouldParseNames() {
ResourceQuery<Resource> query = QueryParser.parseToResourceQuery("name:asd name:bbb", false);
OrSelection or = (OrSelection) query.getSelection();
List<Selection> selections = or.getSelections();
assertEquals(2, selections.size());
assertEquals(NameSelection.class, selections.get(0).getClass());
assertEquals("asd", ((NameSelection) selections.get(0)).getName());
assertEquals(NameSelection.class, selections.get(1).getClass());
assertEquals("bbb", ((NameSelection) selections.get(1)).getName());
assertFalse(query.hasNavigation());
}
@Test
public void shouldParseType() {
ResourceQuery<Resource> query = QueryParser.parseToResourceQuery("type:asd", false);
assertFalse(query.hasSelection());
assertTrue(query.hasNavigation());
StrolchTypeNavigation navigation = (StrolchTypeNavigation) query.getNavigation();
assertEquals("asd", navigation.getType());
}
@Test
public void shouldParseIdNameType() {
ResourceQuery<Resource> query = QueryParser.parseToResourceQuery("id:foo name:bar type:asd", false);
OrSelection or = (OrSelection) query.getSelection();
List<Selection> selections = or.getSelections();
assertEquals(2, selections.size());
assertEquals(IdSelection.class, selections.get(0).getClass());
assertEquals(NameSelection.class, selections.get(1).getClass());
assertTrue(query.hasNavigation());
}
@Test
public void shouldParseWithWhitespace() {
ResourceQuery<Resource> query = QueryParser.parseToResourceQuery(" id:foo name:bar type:asd \t ", false);
OrSelection or = (OrSelection) query.getSelection();
List<Selection> selections = or.getSelections();
assertEquals(2, selections.size());
assertEquals(IdSelection.class, selections.get(0).getClass());
assertEquals(NameSelection.class, selections.get(1).getClass());
assertTrue(query.hasNavigation());
}
}

View File

@ -21,6 +21,13 @@
<buildTimestamp>${maven.build.timestamp}</buildTimestamp>
</properties>
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<distributionManagement>
<repository>
<id>archive.eitchnet.ch</id>