Permalink
Browse files

altered Subgraph.Rule.from to read multiple rules from single string

  • Loading branch information...
technige committed Apr 9, 2012
1 parent d5f634a commit c55398b0f41a275243b5b3d3d51706267adb292d
@@ -105,20 +105,56 @@ public static Rule fromValues(String descriptor, Object... data) throws SyntaxEr
return new Rule(new Descriptor(descriptor), dataMap);
}
- public static Rule from(String text) throws SyntaxError {
+ /**
+ * Read one or more rules from a string, returning all rules read in
+ * a list. Each descriptor may or may not be followed by a data map.
+ *
+ * @param text the string from which to read the rules
+ * @return collection of rules read
+ * @throws SyntaxError if JSON is unparsable
+ */
+ public static List<Rule> from(String text) throws SyntaxError {
if (Geoff.DEBUG) {
System.out.println("Parsing rule: " + text);
}
- String[] bits = text.split("\\s+", 2);
- try {
+ ArrayList<Rule> rules = new ArrayList<Rule>();
+ text = text.trim();
+ while (text.length() > 0) {
+ String[] bits = text.split("\\s+", 2);
+ Descriptor descriptor = new Descriptor(bits[0]);
+ Map<String, Object> data;
if (bits.length == 1) {
- return new Rule(new Descriptor(bits[0]), null);
+ data = null;
+ text = "";
+ } else if (bits[1].charAt(0) == '{') {
+ data = null;
+ // look for each '}' in turn, trying to parse
+ // JSON up to that point; bit brute force but
+ // easier than building a JSON parser...
+ int pos = 0;
+ do {
+ pos = bits[1].indexOf('}', pos + 1);
+ if (pos >= 0) {
+ try {
+ data = JSON.toObject(bits[1].substring(0, pos + 1));
+ } catch(JSONException e) {
+ data = null;
+ }
+ }
+ } while (pos >= 0 && data == null);
+ if (data == null) {
+ throw new SyntaxError("Unparsable JSON in rule: " + text);
+ }
+ // now continue parsing the string
+ text = bits[1].substring(pos + 1).trim();
} else {
- return new Rule(new Descriptor(bits[0]), JSON.toObject(bits[1]));
+ data = null;
+ text = bits[1];
}
- } catch (JSONException e) {
- throw new SyntaxError("Unparsable JSON in rule: " + text, e);
+ Rule rule = new Rule(descriptor, data);
+ rules.add(rule);
}
+ return rules;
}
private final Descriptor descriptor;
@@ -224,13 +260,13 @@ public void add(String... rules) throws SyntaxError {
} else if (ruleString.startsWith("[\"")) {
try {
for(String string : JSON.toListOfStrings(ruleString)) {
- this.rules.add(Rule.from(string));
+ this.rules.addAll(Rule.from(string));
}
} catch (JSONException e) {
throw new SyntaxError("Cannot parse JSON list", e);
}
} else {
- this.rules.add(Rule.from(ruleString));
+ this.rules.addAll(Rule.from(ruleString));
}
}
}
@@ -21,6 +21,10 @@
public class SyntaxError extends Exception {
+ public SyntaxError(String s) {
+ super(s);
+ }
+
public SyntaxError(String s, Throwable throwable) {
super(s, throwable);
}
@@ -26,17 +26,17 @@
import org.neo4j.geoff.store.RelationshipToken;
import org.neo4j.geoff.store.Token;
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import java.util.List;
+
+import static org.junit.Assert.*;
public class RuleTest {
@Test
public void canBuildNodeRule() throws Exception {
String source = "(A) {\"name\": \"Alice\"}";
- Subgraph.Rule rule = Subgraph.Rule.from(source);
+ List<Subgraph.Rule> rules = Subgraph.Rule.from(source);
+ Subgraph.Rule rule = rules.get(0);
assertNotNull(rule);
assertEquals("N", rule.getDescriptor().getPattern());
assertTrue(rule.getDescriptor().getToken(0) instanceof NodeToken);
@@ -51,7 +51,8 @@ public void canBuildNodeRule() throws Exception {
@Test
public void canBuildRelationshipRule() throws Exception {
String source = "[:KNOWS] {\"since\": 1977}";
- Subgraph.Rule rule = Subgraph.Rule.from(source);
+ List<Subgraph.Rule> rules = Subgraph.Rule.from(source);
+ Subgraph.Rule rule = rules.get(0);
assertNotNull(rule);
assertEquals("R", rule.getDescriptor().getPattern());
assertTrue(rule.getDescriptor().getToken(0) instanceof RelationshipToken);
@@ -67,7 +68,8 @@ public void canBuildRelationshipRule() throws Exception {
@Test
public void canBuildPathRule() throws Exception {
String source = "(A)-[:KNOWS]->(B) {\"since\": 1977}";
- Subgraph.Rule rule = Subgraph.Rule.from(source);
+ List<Subgraph.Rule> rules = Subgraph.Rule.from(source);
+ Subgraph.Rule rule = rules.get(0);
assertNotNull(rule);
assertEquals("N-R->N", rule.getDescriptor().getPattern());
assertTrue(rule.getDescriptor().getToken(0) instanceof NodeToken);
@@ -93,7 +95,8 @@ public void canBuildPathRule() throws Exception {
@Test
public void canBuildNodeIndexEntryRule() throws Exception {
String source = "(A)<=|People| {\"name\": \"Alice\"}";
- Subgraph.Rule rule = Subgraph.Rule.from(source);
+ List<Subgraph.Rule> rules = Subgraph.Rule.from(source);
+ Subgraph.Rule rule = rules.get(0);
assertNotNull(rule);
assertEquals("N^I", rule.getDescriptor().getPattern());
assertTrue(rule.getDescriptor().getToken(0) instanceof NodeToken);
@@ -114,7 +117,8 @@ public void canBuildNodeIndexEntryRule() throws Exception {
@Test
public void canBuildRelationshipIndexEntryRule() throws Exception {
String source = "[R]<=|People| {\"name\": \"Alice\"}";
- Subgraph.Rule rule = Subgraph.Rule.from(source);
+ List<Subgraph.Rule> rules = Subgraph.Rule.from(source);
+ Subgraph.Rule rule = rules.get(0);
assertNotNull(rule);
assertEquals("R^I", rule.getDescriptor().getPattern());
assertTrue(rule.getDescriptor().getToken(0) instanceof RelationshipToken);
@@ -132,4 +136,29 @@ public void canBuildRelationshipIndexEntryRule() throws Exception {
assertEquals("Alice", rule.getData().get("name"));
}
+ @Test
+ public void canParseMultipleRules() throws Exception {
+ String source = "(A) {\"name\": \"Alice\"} (B) {\"name\": \"Bob\"} (A)-[:KNOWS]->(B) {\"odd_value\": \"{#!:\\\"}\"} (C) (D) (C)-[:LIKES]->(D)";
+ List<Subgraph.Rule> rules = Subgraph.Rule.from(source);
+ assertEquals(6, rules.size());
+ Subgraph.Rule aliceRule = rules.get(0);
+ Subgraph.Rule bobRule = rules.get(1);
+ Subgraph.Rule aliceKnowsBobRule = rules.get(2);
+ Subgraph.Rule ruleC = rules.get(3);
+ Subgraph.Rule ruleD = rules.get(4);
+ Subgraph.Rule ruleCD = rules.get(5);
+ assertEquals("(A)", aliceRule.getDescriptor().toString());
+ assertEquals("Alice", aliceRule.getData().get("name"));
+ assertEquals("(B)", bobRule.getDescriptor().toString());
+ assertEquals("Bob", bobRule.getData().get("name"));
+ assertEquals("(A)-[:KNOWS]->(B)", aliceKnowsBobRule.getDescriptor().toString());
+ assertEquals("{#!:\"}", aliceKnowsBobRule.getData().get("odd_value"));
+ assertEquals("(C)", ruleC.getDescriptor().toString());
+ assertNull(ruleC.getData());
+ assertEquals("(D)", ruleD.getDescriptor().toString());
+ assertNull(ruleD.getData());
+ assertEquals("(C)-[:LIKES]->(D)", ruleCD.getDescriptor().toString());
+ assertNull(ruleCD.getData());
+ }
+
}

0 comments on commit c55398b

Please sign in to comment.