...
 
Commits (5)
target
extras.log
graph.log
.*.swp
......@@ -59,7 +59,7 @@
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
<version>1.6.2</version>
<version>1.7.2</version>
<type>maven-plugin</type>
</dependency>
......@@ -85,6 +85,18 @@
<build>
<plugins>
<!-- ## File to exclude (dev-only) ######################################### -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<excludes>
<!--<exclude>**/uk/ac/ed/cyphsem/cli/Executor.java</exclude>-->
<!--<exclude>**/uk/ac/ed/cyphsem/cli/RandomComparator.java</exclude>-->
<!--<exclude>**/uk/ac/ed/cyphsem/outbridge/InterpreterComparator.java</exclude>-->
</excludes>
</configuration>
</plugin>
<!-- ## Execution ######################################################### -->
<!-- <plugin>
<groupId>org.apache.maven.plugins</groupId>
......@@ -164,7 +176,7 @@
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.0.1</version>
<configuration>
<stylesheetfile>${basedir}/src/main/javadoc/stylesheet.css</stylesheetfile>
<!--<stylesheetfile>${basedir}/src/main/javadoc/stylesheet.css</stylesheetfile>-->
<quiet>true</quiet>
<show>private</show>
<encoding>UTF-8</encoding>
......
......@@ -30,10 +30,11 @@ import uk.ac.ed.cyphsem.table.*;
import uk.ac.ed.cyphsem.utils.*;
import java.io.IOException;
import java.io.File;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.charset.StandardCharsets;
......@@ -131,28 +132,28 @@ public class Utils {
// }
// }
public static String readFile(String path)
throws IOException {
return readFile(new File(path));
}
public static String readFile(File f)
throws IOException {
return readFile(f, StandardCharsets.UTF_8);
}
public static String readFile(String path, Charset encoding)
throws IOException
{
return readFile(new File(path), encoding);
}
public static String readFile(File f, Charset encoding)
throws IOException
{
byte[] encoded = Files.readAllBytes(f.toPath());
return new String(encoded, encoding);
}
// public static String readFile(String path)
// throws IOException {
// return readFile(new File(path));
// }
//
// public static String readFile(File f)
// throws IOException {
// return readFile(f, StandardCharsets.UTF_8);
// }
//
// public static String readFile(String path, Charset encoding)
// throws IOException
// {
// return readFile(new File(path), encoding);
// }
//
// public static String readFile(File f, Charset encoding)
// throws IOException
// {
// byte[] encoded = Files.readAllBytes(f.toPath());
// return new String(encoded, encoding);
// }
public static <E,F> List<F> map (List<E> input, Function<? super E,F> f) {
return input.stream().map(e -> f.apply(e)).collect(Collectors.toList());
......@@ -272,4 +273,23 @@ public class Utils {
return false;
return true;
}
/** Functions creating a temporary file with given extension and containing given content
* @param content Content of the file
* @param ext Extension of the created file
* @return A temporary file containing the given content.
***/
public static Path tmpFileOfString(String content, String ext) {
Path file = null ;
try {
file = Files.createTempFile("CyphSem_",ext);
Files.write(file, content.getBytes());
}
catch (IOException e) {
throw new RuntimeException("Problem writing to temporary file "+file+".",e);
}
return file;
}
}
......@@ -30,7 +30,7 @@ import uk.ac.ed.cyphsem.language.query.QueryData;
import uk.ac.ed.cyphsem.table.Table;
import uk.ac.ed.cyphsem.outbridge.NeoComInterpreter;
import uk.ac.ed.cyphsem.outbridge.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
......
/* CyphSem
Copyright (c) 2018,2019 Victor Marsault
This file is part of CyphSem.
CyphSem is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
CyphSem is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CyphSem. If not, see <https://www.gnu.org/licenses/>. */
package uk.ac.ed.cyphsem.cli;
import uk.ac.ed.cyphsem.exception.*;
import uk.ac.ed.cyphsem.language.expression.*;
import uk.ac.ed.cyphsem.datamodel.graph.*;
import uk.ac.ed.cyphsem.outbridge.*;
import uk.ac.ed.cyphsem.outbridge.InterpreterComparator.*;
import uk.ac.ed.cyphsem.language.query.*;
import uk.ac.ed.cyphsem.table.*;
import uk.ac.ed.cyphsem.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.ExecutionException;
import java.io.PrintWriter;
public class RandomComparator {
public static void main(String[] args) throws Exception {
Random r = new Random();
Graph g = r.randomGraph();
PrintWriter gw = new PrintWriter("graph.log", "UTF-8");
gw.println(g.toCypher());
gw.flush();
InterpreterComparator comparator
= new InterpreterComparator(g, 200,
() -> new CyphSemInterpreter(),
() -> new Neo4jInterpreter()
);
PrintWriter writer = new PrintWriter("extras.log", "UTF-8");
// writer.println("The second line");
// writer.close();
// System.out.println("\u250F\u2501\u2501\u2501 NEOCOM class (for fail, for timeout) ");
// System.out.println("\u2503\u250F\u2501\u2501\u2501 CYPHSEM result class (for fail, for timeout)");
// // System.out.println("\u2503\u2503\u250F\u2501\u2501\u2501 If Neither fails, are result equal ?");
// System.out.println("\u2503\u2503\u2503 \n");
comparator.printHeader(System.out);
String querySep = "========================================================================= Query ";
String indent = " ";
for (int o = 0; o < comparator.size(); o++)
indent += " ";
for (int i = 0 ; i< 2000 ; i++) {
String x = String.valueOf(i);
x = querySep.substring(x.length()+3)+x+" ==";
System.out.println(x);
Query q = r.randomQueryBis();
String queryString = q.toString();
writer.println("======================================================================");
writer.println(q);
writer.println("----------------------------------------------------------------------");
writer.flush();
Comparison c = comparator.compare(g,q);
int o = 0;
for ( Table t : c.tables ) {
writer.print("Class n°"+(o++)+": { ");
int max = 42;
String sep = "";
for(Record record: t.recordSet()) {
if (--max == 0) {
writer.print(" ... ");
break;
}
writer.print(sep+record+"="+t.multiplicityOf(record));
sep=" ";
}
writer.println(" }");
}
writer.flush();
String str = "";
for (int j = 0; j<comparator.size(); j++) {
if(c.hasTimedOut(j))
str += "\u231B";
else if (c.hasFailedWithException(j)) {
writer.println("Interpreter n°"+j+" failed with Exception: "+c.getException(j));
writer.flush();
str += "\u2718";
}
else
str+= String.valueOf(c.behavioralClasses.get(j));
}
queryString = queryString.replace("\n","\n"+indent);
System.out.println(str+" "+queryString);
writer.println("----------------------------------------------------------------------");
writer.println("Summary: "+str);
// (neo_result.equals(cyphsem_result)?"=":"\u2260"
//
//
// "\uD83D""\uDD50"
// // boolean except = false;
// // Table neo_result = null;
// // Table cyphsem_result = null;
// // try {
// // neo_result = neocom.run(stt);
// str += "\u00B7";
// } catch (Exception e) {
// except = true;
// str += "\u2718";
// }
// try {
// cyphsem_result = uk.ac.ed.cyphsem.run(stt);
// str += "\u00B7";
// } catch (Exception e) {
// except = true;
// str += "\u2718";
// }
//
// if (!except)
// str += (neo_result.equals(cyphsem_result)?"=":"\u2260");
// else
// str += "\u00B7";
// System.out.println(str+" "+stt);
}
}
}
......@@ -73,7 +73,7 @@ public class Sample {
+--------[loves]---------+
| |
| |
+---(cat tabby savvy) <--+
+---(cat tabby savvy) &lt;--+
(name:"zelia" )
/\
|
......@@ -82,20 +82,20 @@ public class Sample {
[since:2018]
|
| [knows ]
+ -------> (human )------------[since:2011]----------------+
+ -------&gt; (human )------------[since:2011]----------------+
| (name:"Nadime")-----+ |
| | | | |
[knows ] | | | |
[since:2008] [kept ] | [kept ] v
| [in:2015] | [in:2017]---> (cat) <---[has]---(name:"Leonid")
| [in:2015] | [in:2017]---&gt; (cat) &lt;---[has]---(name:"Leonid")
| | | |
+-----+ | +---[kept ]------------+ |
| | [in:2017] | |
| | | |
| +-----------------+ | |
| | v |
(human ) +--> (cat blue savvy ) |
+--> (name:"Victor")---[has ]-----> (name:"Athanase" ) |
(human ) +--&gt; (cat blue savvy ) |
+--&gt; (name:"Victor")---[has ]-----&gt; (name:"Athanase" ) |
| [since:2014] (breed:"RussianBlue") |
| |
+------------------------------[knows ] ---------------------------+
......
......@@ -55,7 +55,7 @@ public class Graph {
protected Node.IdSupplier nodeIdSupplier = new Node.IdSupplier();
/** Maximal id among relations */
/** A supplier for relation Id. */
protected Relation.IdSupplier relationIdSupplier = new Relation.IdSupplier();
......
package uk.ac.ed.cyphsem.datamodel.graph;
import uk.ac.ed.cyphsem.datamodel.graph.PropertyKey;
import uk.ac.ed.cyphsem.datamodel.value.*;
/** Interface compiling misc functions about {@link Graph}'s ***/
public interface Graphs {
/** {@link PropertyKey} used to annotate
* @see annonateWithCyphSemId
***/
public static final PropertyKey cyphsemidKey = new PropertyKey("cyphsem_id");
public static
void annotateWithCyphSemId(Graph graph)
{
for (Node node : graph.nodes())
node.overwriteProperty(cyphsemidKey, new Value(node.content()));
for (Relation relation : graph.relations())
relation.overwriteProperty(cyphsemidKey, new Value(relation.content()));
}
}
......@@ -47,10 +47,15 @@ public class Node extends Id implements Comparable<Node> {
protected int next = 0;
@Override
public Integer get() { return next++; }
/** Method to notify the supplier that a Node with given id was created
/** Method to notify the supplier that given Node was created
* without using this supplier.
***/
public void update(Node n) { next = (n.content() >= next) ? n.content()+1 : next; }
public void update(Node n) { update(n.content()); }
/** Notifies this supplier that a Node with given id was created without using
* this supplier
***/
public void update(int i) { next = (i >= next) ? i+1 : next; }
}
......
......@@ -46,10 +46,17 @@ public class Relation extends Id implements Comparable<Relation> {
protected int next = 0;
@Override
public Integer get() { return next++; }
/** Method to notify the supplier that a Relation with given id was created
/** Method to notify the supplier that given Relation was created
* without using this supplier.
***/
public void update(Relation r) { next = (r.content() >= next) ? r.content()+1 : next; }
public void update(Relation r) { update(r.content()); }
/** Method to notify the supplier that a Relation with given id was created
* without using this supplier
***/
public void update(int i) { next = (i >= next) ? i+1 : next; }
}
/** The type of the relation */
......
/* CyphSem
Copyright (c) 2018,2019 Victor Marsault
This file is part of CyphSem.
CyphSem is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
CyphSem is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CyphSem. If not, see <https://www.gnu.org/licenses/>. */
package uk.ac.ed.cyphsem.exception;
import uk.ac.ed.cyphsem.outbridge.Interpreter;
/** Exception launched when a result is asked from an {@link Interpreter} and the result is not entirely computed.
*/
public class ComputationOngoingException extends Exception {
public ComputationOngoingException() {}
public ComputationOngoingException (String e) { super(e); }
}
......@@ -318,7 +318,7 @@ public interface Expressions {
* @param e {@link Expression} to evaluate.
* @param g {@link Graph} used for evaluation.
* @param r {@link Record} used for evaluation.
* @return The {@link <List<Value>>} <tt>e</tt> evaluates to, or Optional.empty() if e evaluates to a {@link Kind#NULL NULL} {@link Value}.
* @return The {@link List<Value>} <tt>e</tt> evaluates to, or Optional.empty() if e evaluates to a {@link Kind#NULL NULL} {@link Value}.
* @throws DynamicCastException if the evaluated value is not of {@link Kind Kind} {@link Kind#MAP MAP}
* @throws UndefinedNameException
* @throws UnspecifiedBehaviourException
......
......@@ -62,7 +62,7 @@ public class AssignmentResult {
An {@link Expression} is added in the set whenever its evaluation raises
a {@link UndefinedNameException}, that is a variable occurring in the Expression
is not set yet.
Typically, this occurs with patterns such as <tt>({name:b.name})-->(b)</tt>.
Typically, this occurs with patterns such as <tt>({name:b.name})--&gt;(b)</tt>.
*/
public Set<Expression> postConditions;
......
......@@ -59,9 +59,9 @@ very similar to one that appears in the input query.
representation string to be identical to the input string.
* A compiled pattern will always print the content (properties, labels, etc.)
associated with a name together with the first occurrence of the name.
* For instance, if one use <tt>(a)-[:has]->(b:chat)-[:likes]->(a:human)</tt>
* For instance, if one use <tt>(a)-[:has]-&gt;(b:chat)-[:likes]-&gt;(a:human)</tt>
to build a compiled pattern, then its string representation will be
<tt>(a:human)-[:has]->(b:chat)-[:likes]->(a)</tt>.
<tt>(a:human)-[:has]-&gt;(b:chat)-[:likes]-&gt;(a)</tt>.
**/
public class CompiledPattern {
......@@ -91,7 +91,7 @@ public class CompiledPattern {
/** Indicate whether a variable appears in the compiled pattern. */
public boolean hasVariable(Name name) { return kindOf(name) != Kind.ABSENT; }
/** Indicate the status of a variable : first component is the {@link #Kind}
/** Indicate the status of a variable : first component is the {@link Kind}
* of the variable and second component indicates whether the variable is genuine or autogenerated.
* <br>If first component is {@link Kind#ABSENT ABSENT}, the second component is meaningless.
* */
......@@ -361,7 +361,7 @@ public class CompiledPattern {
/** Get the content of the path associated with given {@link Name}.
* @throws IllegalArgumentException if {@code name} is not of {@link Kind Kind} {@link Kind.PATH PATH}.
* @throws IllegalArgumentException if {@code name} is not of {@link Kind Kind} {@link Kind#PATH PATH}.
**/
public List<Name> pathOf(Name name) {
if (!hasVariable(name))
......
......@@ -173,8 +173,8 @@ public abstract class PathPattern {
/** Returns the string representation of this pattern only, ignoring
* the remainder of the path (if applicable).
* For instance, a relation pattern would return <tt>-[]-></tt> instead of
* <tt>-[]->()-[]-></tt> .
* For instance, a relation pattern would return <tt>-[]-&gt;</tt> instead of
* <tt>-[]-&gt;()-[]-&gt;</tt> .
***/
public String toThisString() {
return toString();
......
......@@ -46,7 +46,9 @@ import java.util.HashSet;
/** Implements Cypher clauses of the form <tt>MATCH p1,..,pn</tt>,
* where p1, ..., pn are path patterns.
***/
public class MatchClause implements StandardReadingClause, PatternHolder {
public class MatchClause
implements StandardReadingClause, PatternHolder
{
/** Path patterns of this {@link MatchClause}. */
protected List<PathPattern> patterns;
......
......@@ -19,12 +19,14 @@
package uk.ac.ed.cyphsem.language.query;
import uk.ac.ed.cyphsem.language.expression.*;
import uk.ac.ed.cyphsem.datamodel.value.Value.Kind;
import uk.ac.ed.cyphsem.Interruptor;
import uk.ac.ed.cyphsem.datamodel.graph.Graph;
import uk.ac.ed.cyphsem.datamodel.value.Value;
import uk.ac.ed.cyphsem.datamodel.value.Value.Kind;
import uk.ac.ed.cyphsem.table.Table;
import uk.ac.ed.cyphsem.table.Record;
import uk.ac.ed.cyphsem.table.RecordComparator;
......
......@@ -19,15 +19,20 @@
package uk.ac.ed.cyphsem.outbridge;
import java.io.File;
import java.util.concurrent.Future;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import uk.ac.ed.cyphsem.Interruptor;
import uk.ac.ed.cyphsem.exception.InterpretingException;
import uk.ac.ed.cyphsem.exception.UndefinedNameException;
import uk.ac.ed.cyphsem.exception.UnspecifiedBehaviourException;
import uk.ac.ed.cyphsem.datamodel.graph.Graph;
import uk.ac.ed.cyphsem.exception.*;
import uk.ac.ed.cyphsem.datamodel.graph.Graph;
import uk.ac.ed.cyphsem.language.query.QueryData;
import uk.ac.ed.cyphsem.language.parser.Parser;
import uk.ac.ed.cyphsem.exception.AnTLRException;
......@@ -35,59 +40,74 @@ import uk.ac.ed.cyphsem.language.query.Query;
import uk.ac.ed.cyphsem.table.Table;
/** Class implementing the Cypher Interpreter native to CyphSem.
* @see Interpreters#CYPHSEM
***/
public class CyphSemInterpreter implements Interpreter {
public class CyphSemInterpreter extends Interpreter.AbstractHelper implements Interpreter {
Graph graph;
protected long lastRunTime;
// Boolean interrupted = false;
/** Stored input graph */
Graph graph = null;
/** Stored input query */
Query query = null;
/** Interruptor of the query execution currently run (if any). Never {@code null}. */
Interruptor interruptor = new Interruptor();
/** The resut of currently run query-execution, when it will be available. */
Future<QueryData> futureResult = null;
public CyphSemInterpreter() { }
public CyphSemInterpreter(Graph graph) { this.graph = graph; }
public CyphSemInterpreter(Interpreter other) { this(other.getGraph()); }
@Override
public void load(File database) { }
@Override
public void load(String str) { }
public CyphSemInterpreter(Graph graph) { inputGraph(graph); }
@Override
public void loadFrom(Interpreter i) { this.graph = i.getGraph(); }
@Override
public Graph getGraph() { return graph; }
public void setGraph(Graph graph) { this.graph = graph; }
public void inputGraph(Graph g) { graph = g; }
@Override
public void inputQuery(Query q) { query= q; }
@Override
public Graph outputGraph()
throws InterruptedException, ExecutionException, ComputationOngoingException
{
if (futureResult.isDone())
return futureResult.get().graph();
else
throw new ComputationOngoingException();
}
@Override
public Table outputTable()
throws InterruptedException, ExecutionException, ComputationOngoingException
{
if (futureResult.isDone())
return futureResult.get().table();
else
throw new ComputationOngoingException();
}
@Override
public Table run(String statement) throws InterpretingException, InterruptedException {
try {
lastRunTime = -System.nanoTime();
Query query = Parser.queryOf(statement);
Table result = query.execute(graph, interruptor).table();
lastRunTime += System.nanoTime();
return result;
} catch (UndefinedNameException e) {
throw new InterpretingException(e);
} catch (UnspecifiedBehaviourException e) {
throw new InterpretingException(e);
} catch (AnTLRException e) {
throw new InterpretingException(e.getCause());
}
public void run() {
interruptor = new Interruptor();
Callable<QueryData> runnable = new Callable<QueryData> () {
public QueryData call() throws InterruptedException {
return query.execute(graph, interruptor);
}
};
ExecutorService exe = Executors.newSingleThreadExecutor();
futureResult = exe.submit(runnable);
}
@Override
public long getLastRunTime() {
return lastRunTime;
}
public void interrupt() { interruptor.interrupt(); }
/**{@inheritDoc}
* Implemtentation in {@link CyphSemInterpreter} does nothing.
***/
@Override
public void close() { }
@Override
public void interrupt() { interruptor.interrupt(); }
/**{@inheritDoc} ***/
@Override public
String displayName() { return "CyphSem"; }
}
......@@ -18,11 +18,12 @@
package uk.ac.ed.cyphsem.outbridge;
import uk.ac.ed.cyphsem.exception.ConversionException;
import uk.ac.ed.cyphsem.exception.InterpretingException;
import uk.ac.ed.cyphsem.exception.*;
import uk.ac.ed.cyphsem.datamodel.graph.Graph;
import uk.ac.ed.cyphsem.language.query.*;
import uk.ac.ed.cyphsem.table.Table;
import java.util.Arrays;
......@@ -30,7 +31,11 @@ import java.util.ArrayList;
import java.util.List;
import java.util.LinkedList;
import java.lang.InterruptedException;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.io.PrintStream;
......@@ -38,7 +43,7 @@ public class InterpreterComparator {
public static class Comparison {
// public List<Integer> failedWithExceptions;
public List<InterpretingException> exceptions;
public List<ExecutionException> exceptions;
public List<List<Integer>> succeeded = new LinkedList<List<Integer>>();
public List<Table> tables = new LinkedList<Table>();
......@@ -47,13 +52,13 @@ public class InterpreterComparator {
// -3 -> unset
// -2 -> timeout
// -1 -> exception
// >0 -> proper result
// >0 -> finished properly with class of Table
public Comparison(int n) {
behavioralClasses = new ArrayList<Integer>(n);
for (int i = 0; i<n; i++)
behavioralClasses.add(-3);
exceptions = new ArrayList<InterpretingException>(n);
exceptions = new ArrayList<ExecutionException>(n);
for (int i = 0; i<n; i++)
exceptions.add(null);
}
......@@ -66,7 +71,7 @@ public class InterpreterComparator {
tables.add(table);
}
void addExceptionFails(Integer index, InterpretingException e) {
void addExceptionFails(Integer index, ExecutionException e) {
exceptions.set(index, e);
behavioralClasses.set(index, -1); }
void addTimeoutFails(Integer index) { behavioralClasses.add(index, -2); }
......@@ -92,7 +97,7 @@ public class InterpreterComparator {
public boolean hasFailedWithException(Integer i) {
return (behavioralClasses.get(i).equals(-1));
}
public InterpretingException getException(Integer i) {
public ExecutionException getException(Integer i) {
return exceptions.get(i);
}
public boolean hasFailed(Integer i) {
......@@ -105,16 +110,22 @@ public class InterpreterComparator {
}
}
private List<InterpreterFactory> factories;
private List<Interpreter.Factory> factories;
private boolean graphLoaded = false;
private Graph graph;
private long timeout;
public InterpreterComparator(Graph g, long timeout, InterpreterFactory... factories) {
public
InterpreterComparator
(Graph g, long timeout, Interpreter.Factory... factories)
{
this(g, timeout, Arrays.asList(factories));
}
public InterpreterComparator(Graph graph, long timeout, List<InterpreterFactory> factories) {
public
InterpreterComparator
(Graph graph, long timeout, List<Interpreter.Factory> factories)
{
this.factories = factories;
this.graph = graph;
this.timeout = timeout;
......@@ -122,32 +133,53 @@ public class InterpreterComparator {
// First element is timeout, second element is Exception, then each list group
// the factories with the same behavior;
public Comparison compare (String statement) {
public
Comparison compare (Graph graph, Query query)
throws InterruptedException
{
Comparison result = new Comparison(factories.size());
List<Interpreter> interpreters = makeInterpreters();
for (Interpreter interpreter : interpreters) {
interpreter.inputGraph(graph);
interpreter.inputQuery(query);
}
for (Interpreter interpreter : interpreters) {
interpreter.run();
}
TimeUnit.MILLISECONDS.sleep(timeout);
//InterruptedException raised by `sleep` is propagated.
for (Interpreter interpreter : interpreters) {
interpreter.interrupt();
}
for (int i=0; i<interpreters.size(); i++) {
try { result.addSuccess(i, interpreters.get(i).run(statement, timeout) ); }
catch (InterpretingException e) { result.addExceptionFails(i,e); }
catch (TimeoutException e) { result.addTimeoutFails(i); }
interpreters.get(i).close();
Interpreter interpreter = interpreters.get(i);
try {
Table resultingTable = interpreter.outputTable();
result.addSuccess(i, resultingTable);
}
catch (ExecutionException e) {
result.addExceptionFails(i,e);
}
catch (InterruptedException e) {
result.addTimeoutFails(i);
}
catch (ComputationOngoingException e) {
// This should not happen
throw new UnreachableStatementError();
}
interpreter.close();
}
return result;
}
private List<Interpreter> makeInterpreters() {
List<Interpreter> result = new ArrayList<Interpreter> (factories.size());
boolean b = !graphLoaded;
for (InterpreterFactory factory : factories) {
Interpreter i = factory.make(graph, graphLoaded);
if (b) {
b = false;
graph = i.getGraph();
}
result.add(i);
// System.out.println(i.getGraph().toJson());
List<Interpreter> result
= new ArrayList<Interpreter> (factories.size());
for (Interpreter.Factory factory : factories) {
result.add(factory.make());
}
graphLoaded = true;
return result;
}
......@@ -157,8 +189,9 @@ public class InterpreterComparator {
public void printHeader (PrintStream e) {
String start = "";
for (InterpreterFactory factory : factories) {
e.println(start+"\u250F\u2501\u2501\u2501"+factory+".");
for (Interpreter.Factory factory : factories) {
e.println(start + "\u250F\u2501\u2501\u2501 "
+ factory.make().displayName() +".");
start += "\u2503";
}
e.println(start);
......
......@@ -18,56 +18,58 @@
package uk.ac.ed.cyphsem.outbridge;
import uk.ac.ed.cyphsem.exception.InterpretingException;
import uk.ac.ed.cyphsem.exception.*;
import java.io.File;
import java.util.concurrent.ExecutionException;
import java.lang.InterruptedException;
import uk.ac.ed.cyphsem.datamodel.graph.Graph;
import uk.ac.ed.cyphsem.language.query.Query;
import uk.ac.ed.cyphsem.table.Table;
import java.util.concurrent.TimeoutException;
/** This enum registers instance of different {@link Intepreter}'s for easier use.
* Note that they won't inconditionally work; for instance, {@link #NEO4J} will only work if Neo4j service is correcly started and set up.
***/
public enum Interpreters implements Interpreter {
CYPHSEM(new CyphSemInterpreter()),
NEOCOM(new NeoComInterpreter());
CYPHSEM(new CyphSemInterpreter())
// ,NEO4J(new NeoComInterpreter())
;
Interpreter boxedInterpreter;
private Interpreters(Interpreter i) { boxedInterpreter = i; }
@Override
public void load(File database) throws InterpretingException
{ boxedInterpreter.load(database); }
@Override
public void load(String str) throws InterpretingException
{ boxedInterpreter.load(str); }
public void inputGraph(Graph g) { boxedInterpreter.inputGraph(g); }
@Override
public Graph getGraph() { return boxedInterpreter.getGraph(); }
public void inputQuery(Query q) { boxedInterpreter.inputQuery(q); }
@Override
public Table run(String statement) throws InterpretingException, InterruptedException
{ return boxedInterpreter.run(statement); }
public Graph outputGraph()
throws InterruptedException, ExecutionException, ComputationOngoingException
{
return boxedInterpreter.outputGraph();
}
@Override
public Table run(String statement, long timeout)
throws InterpretingException, TimeoutException
{ return boxedInterpreter.run(statement, timeout); }
public Table outputTable()
throws InterruptedException, ExecutionException, ComputationOngoingException
{ return boxedInterpreter.outputTable(); }
@Override
public void close() { boxedInterpreter.close(); }
public void interrupt() { boxedInterpreter.interrupt(); }
@Override
public long getLastRunTime() { return boxedInterpreter.getLastRunTime(); }
public void run() { boxedInterpreter.run(); }
@Override
public void interrupt() { boxedInterpreter.interrupt(); }
public void close() { boxedInterpreter.close(); }
@Override
public void loadFrom(Interpreter i) throws InterpretingException
{ boxedInterpreter.loadFrom(i); }
public String displayName() { return boxedInterpreter.displayName(); }
}
This diff is collapsed.
......@@ -139,8 +139,9 @@ public class Random {
Graph graph = new Graph();
int node_n = 12 + nextInt(14);
List<Node> nodes = new ArrayList<Node>(node_n);
for (int i = 0; i<node_n; i++)
for (int i = 0; i<node_n; i++) {
nodes.add(graph.addNode(randomLabels(),randomProperties()));
}
for (int i = 0; i<node_n; i++)
while(nextDouble() < p_out) {
graph.addRelation( randomType(),
......
/* CyphSem
Copyright (c) 2018,2019 Victor Marsault
This file is part of CyphSem.
CyphSem is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
CyphSem is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CyphSem. If not, see <https://www.gnu.org/licenses/>. */
package uk.ac.ed.cyphsem.outbridge;
import uk.ac.ed.cyphsem.Utils;
import uk.ac.ed.cyphsem.utils.StringOf;
import uk.ac.ed.cyphsem.exception.*;
import uk.ac.ed.cyphsem.language.query.Query;
import uk.ac.ed.cyphsem.language.parser.Parser;
import uk.ac.ed.cyphsem.table.*;
import uk.ac.ed.cyphsem.datamodel.graph.*;
import uk.ac.ed.cyphsem.datamodel.value.*;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Files;
import java.util.concurrent.ExecutionException;
import java.lang.InterruptedException ;
/** This abstract class is an helper to implement an {@link Interpreter} linking outside CyphSem. Functions to implement manipulate strings instead of internal data types such as {@link #Graph}'s or {@link #Query}'s.
* Note that no helper method is given for outputTable as there is no
***/
public abstract class StringInterpreter implements Interpreter {
/** {@inheritDoc}
* Implementation in {@link StringInterpreter} calls {@link #inputGraph(java.util.String} with {@code g.toCypher()} as parameter.
***/
@Override
public void inputGraph(Graph g) {
inputGraph(g.toCypher());
}
abstract protected void inputGraph(String g);
abstract protected void inputQuery(String q);
abstract protected String outputGraphAsString() throws InterruptedException, ExecutionException, ComputationOngoingException;
@Override public abstract Table outputTable() throws InterruptedException, ExecutionException, ComputationOngoingException;
/** {@inheritDoc}
* Implementation in {@link StringInterpreter} calls {@link #inputQuery(java.util.String)} with {@code q.toString()}.
***/
@Override
public void inputQuery(Query q) {
inputQuery(q.toString());
}
/** {@inheritDoc}
* Implementation in {@link StringInterpreter} calls {@link Parser#graphOf} with value returned by {@link #outputGraphAsString()}.
***/
@Override
public Graph outputGraph()
throws InterruptedException, ExecutionException, ComputationOngoingException
{
return Parser.graphOf(outputGraphAsString());
}
}
......@@ -46,7 +46,7 @@ import java.util.function.Supplier;
/** Represents a ``row from the driving table``.
* <br>
* Formally, a record is a function from {@link Name}s to {@link Value}s.
* It is implemented here as a {@link Map}&lt{@link Name},{@link Value}&gt; stored in field {@link #map}.
* It is implemented here as a {@link Map}&lt;{@link Name},{@link Value}&gt; stored in field {@link #map}.
* <br>
* Note that methods {@link #get} and {@link #bind}, as implemented here, are less permissive than their counterpart in {@link Map} (that is, {@link Map#get get} and {@link Map#put put}).
***/
......
......@@ -96,7 +96,7 @@ public class Table extends AbstractCollection<Record> {
/** Adds multiple copies of given {@link Record}.
* @param r Element to remove.
* @param i Number of copies to add. If negative, copies of{@code o) are effectively remove.
* @param i Number of copies to add. If negative, copies of {@code o} are effectively remove.
* @return the number of copies effectively added. (If {@code i} is negative, returned value may also be negative.)
* @throws IllegalArgumentException if {@code r} is not uniform with this {@link Table}.
* @see remove(uk.ac.ed.cyphsem.table.Record,int)
......@@ -166,7 +166,7 @@ public class Table extends AbstractCollection<Record> {
}
/** Adds multiple copies of each given {@link Record}.
* If a {@link Record} occurs <var>j<.var> times in the {@link Iterable}, then {@code inputMultiplicity} times <var>j</var> copies of it will be added.
* If a {@link Record} occurs <var>j</var> times in the {@link Iterable}, then {@code inputMultiplicity} times <var>j</var> copies of it will be added.
* <br><br>
* Effectively removes copies if parameter {@code i} is negative.
* @param records Elements to add.
......@@ -343,7 +343,7 @@ public class Table extends AbstractCollection<Record> {
/** Remove multiple copies of given {@link Record}.
* @param r Element to remove.
* @param i Number of copies to remove. If negative, copies of{@code o) are effectively added.
* @param i Number of copies to remove. If negative, copies of {@code o} are effectively added.
* @return the number of copies effectively removed. (If {@code i} is negative, returned value may also be negative)
* @throws IllegalArgumentException if {@code r} is not uniform with this {@link Table}.
* @see add(uk.ac.ed.cyphsem.table.Record,int)
......
......@@ -23,6 +23,10 @@ import java.util.function.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Files;
/** This is collection of static function that helps format to string.
*
**/
......@@ -122,4 +126,15 @@ public interface StringOf {
return map(map, "{", "}", ",", "","",":");
}
/** Functions reading full content of a given file.
* @param file File to read.
* @return A string with the whole content of given file.
* @throws IOException
***/
public static String file(Path file) throws IOException {
List<String> lines = Files.readAllLines(file);
return iterable(lines,"\n");
}
}
......@@ -26,7 +26,7 @@ import java.util.Objects;
public class Wrapper<E extends Comparable<E>> {
/** The content of the wrapper. */
protected final E content;
protected E content;
/** Returns the content of the wrapper (without copy). */
......
/* CyphSem
Copyright (c) 2018,2019 Victor Marsault
This file is part of CyphSem.
CyphSem is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
CyphSem is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CyphSem. If not, see <https://www.gnu.org/licenses/>. */
package uk.ac.ed.cyphsem.outbridge;
import java.io.File;
import uk.ac.ed.cyphsem.Interruptor;
import uk.ac.ed.cyphsem.exception.InterpretingException;
import uk.ac.ed.cyphsem.exception.UndefinedNameException;
import uk.ac.ed.cyphsem.exception.UnspecifiedBehaviourException;
import uk.ac.ed.cyphsem.datamodel.graph.Graph;
import uk.ac.ed.cyphsem.language.parser.Parser;
import uk.ac.ed.cyphsem.exception.AnTLRException;
import uk.ac.ed.cyphsem.language.query.Query;
import uk.ac.ed.cyphsem.table.Table;
public class CyphSemInterpreter extends Interpreter.AbstractHelper implements Interpreter {
Graph graph;
protected long lastRunTime;
// Boolean interrupted = false;
Interruptor interruptor = new Interruptor();
public CyphSemInterpreter() { }
public CyphSemInterpreter(Graph graph) { this.graph = graph; }
public CyphSemInterpreter(Interpreter other) { this(other.getGraph()); }
@Override
public void load(File database) { }
@Override
public void load(String str) { }
@Override
public void loadFrom(Interpreter i) { this.graph = i.getGraph(); }
@Override
public Graph getGraph() { return graph; }
public void setGraph(Graph graph) { this.graph = graph; }
@Override
public Table run(String statement) throws InterpretingException, InterruptedException {
try {
lastRunTime = -System.nanoTime();
Query query = Parser.queryOf(statement);
Table result = query.execute(graph, interruptor).table();
lastRunTime += System.nanoTime();
return result;
} catch (UndefinedNameException e) {
throw new InterpretingException(e);
} catch (UnspecifiedBehaviourException e) {
throw new InterpretingException(e);
} catch (AnTLRException e) {
throw new InterpretingException(e.getCause());
}
}
@Override
public long getLastRunTime() {
return lastRunTime;
}
@Override
public void close() { }
@Override
public void interrupt() { interruptor.interrupt(); }
}
/* CyphSem
Copyright (c) 2018,2019 Victor Marsault
This file is part of CyphSem.
CyphSem is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
CyphSem is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CyphSem. If not, see <https://www.gnu.org/licenses/>. */
package uk.ac.ed.cyphsem.outbridge;
import java.io.File;
import java.io.IOException;
import uk.ac.ed.cyphsem.exception.ConversionException;
import uk.ac.ed.cyphsem.exception.InterpretingException;
import uk.ac.ed.cyphsem.datamodel.graph.Graph;
import uk.ac.ed.cyphsem.table.Table;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.ExecutionException;
import uk.ac.ed.cyphsem.Utils;
import uk.ac.ed.cyphsem.exception.UnreachableStatementError;
public interface Interpreter extends AutoCloseable {
public void load(File database) throws InterpretingException ;
public void load(String str) throws InterpretingException ;
public Graph getGraph();
public Table run(String statement) throws InterpretingException, InterruptedException ;
public abstract Table run(String statement, long timeout)
throws InterpretingException, TimeoutException ;
public long getLastRunTime();
@Override
public void close();
public void interrupt();
public void loadFrom(Interpreter i) throws InterpretingException ;
public abstract class AbstractHelper implements Interpreter {
@Override
public void load(File database) throws InterpretingException {
try { load(uk.ac.ed.cyphsem.Utils.readFile(database)); }
catch (IOException e) { throw new ConversionException(e); }
}
@Override
public abstract void load(String str) throws InterpretingException ;
@Override
public abstract void loadFrom(Interpreter i) throws InterpretingException ;
@Override
public abstract Graph getGraph();
@Override
public abstract Table run(String statement) throws InterpretingException, InterruptedException ;
@Override
public Table run(String statement, long timeout)
throws InterpretingException, TimeoutException
{
uk.ac.ed.cyphsem.table.Table result = null;
Callable<uk.ac.ed.cyphsem.table.Table> callable = new Callable<uk.ac.ed.cyphsem.table.Table> () {
public uk.ac.ed.cyphsem.table.Table call() throws InterpretingException, InterruptedException {
return run(statement);
}
};
ExecutorService exe = Executors.newSingleThreadExecutor();
Future<uk.ac.ed.cyphsem.table.Table> futureResult = exe.submit(callable);
try {
result = futureResult.get(timeout, TimeUnit.MILLISECONDS);
exe.shutdownNow();
} catch (TimeoutException e) {
exe.shutdownNow();
interrupt();
throw e;
} catch (InterruptedException e) {
exe.shutdownNow();
throw new UnreachableStatementError();
} catch (ExecutionException e) {
// System.out.println(e);
exe.shutdownNow();
Throwable thr = e.getCause();
if (thr instanceof InterpretingException)
throw ((InterpretingException) thr);
else
throw new InterpretingException(e);
}
return result;
}
@Override
public void close() { }
@Override
public void interrupt() { }
}
}