1212import org .neo4j .logging .Log ;
1313import org .neo4j .procedure .Context ;
1414import org .neo4j .procedure .Name ;
15+ import org .neo4j .procedure .Mode ;
1516import org .neo4j .procedure .PerformsWrites ;
1617import org .neo4j .procedure .Procedure ;
18+ import org .neo4j .procedure .UserFunction ;
1719
1820import javax .script .Invocable ;
1921import javax .script .ScriptEngine ;
2224
2325import static org .neo4j .helpers .collection .MapUtil .stringMap ;
2426
25- /**
26- * This is an example showing how you could expose Neo4j's full text indexes as
27- * two procedures - one for updating indexes, and one for querying by label and
28- * the lucene query language.
29- */
3027public class Scripts {
3128
29+ private static String PREFIX = "script.function." ;
3230 public static final Object [] NO_OBJECTS = new Object [0 ];
33- // This field declares that we need a GraphDatabaseService
34- // as context when any procedure in this class is invoked
31+
3532 @ Context
36- public GraphDatabaseService db ;
33+ public GraphDatabaseAPI db ;
3734
38- // This gives us a log instance that outputs messages to the
39- // standard log, normally found under `data/log/console.log`
4035 @ Context
4136 public Log log ;
4237
@@ -47,7 +42,7 @@ public class Scripts {
4742
4843 private GraphProperties graphProperties () {
4944 if (graphProperties == NO_GRAPH_PROPERTIES )
50- graphProperties = (( GraphDatabaseAPI ) db ) .getDependencyResolver ().resolveDependency (NodeManager .class ).newGraphProperties ();
45+ graphProperties = db .getDependencyResolver ().resolveDependency (NodeManager .class ).newGraphProperties ();
5146 return graphProperties ;
5247 }
5348 private ScriptEngine getEngine () {
@@ -70,57 +65,52 @@ private void addFunctions(ScriptEngine js, String...script) {
7065 }
7166 }
7267
73- @ Procedure
74- public Stream <Result > run (@ Name ("name" ) String name , @ Name ("params" ) List params ) {
75- try {
76- ScriptEngine js = getEngine ();
77- String code = (String ) graphProperties ().getProperty (name , null );
78- if (code == null )
79- throw new RuntimeException ("Function " + name + " not defined, use CALL function('name','code') " );
80-
81- js .put ("db" , db );
82- js .put ("log" , log );
83- js .eval (String .format ("function %s(){ return (%s).apply(this, arguments) }" , name , code ));
84- Object value = ((Invocable ) js ).invokeFunction (name , params == null ? NO_OBJECTS : params .toArray ());
85- if (value instanceof Object []) {
86- return Stream .of ((Object []) value ).map (Result ::new );
87- }
88- if (value instanceof Iterable ) {
89- return StreamSupport .stream (((Iterable <?>)value ).spliterator (),false ).map (Result ::new );
90- }
91- return Stream .of (new Result (value ));
92- } catch (ScriptException | NoSuchMethodException e ) {
93- throw new RuntimeException (e );
94- }
68+ @ UserFunction ("scripts.run" )
69+ public Object runFunction (@ Name ("name" ) String name , @ Name (value ="params" ,defaultValue ="[]" ) List <Object > params ) throws ScriptException , NoSuchMethodException {
70+ ScriptEngine js = getEngine ();
71+ String code = (String ) graphProperties ().getProperty (PREFIX + name , null );
72+ if (code == null )
73+ throw new RuntimeException ("Function " + name + " not defined, use CALL function('name','code') " );
74+
75+ js .put ("db" , db );
76+ js .put ("log" , log );
77+ js .eval (String .format ("function %s(){ return (%s).apply(this, arguments) }" , name , code ));
78+ return ((Invocable ) js ).invokeFunction (name , params == null ? NO_OBJECTS : params .toArray ());
9579 }
9680
9781 @ Procedure
98- @ PerformsWrites
99- public Stream <Result > function (@ Name ("name" ) String name , @ Name ("code" ) String code ) {
100- try {
101- ScriptEngine js = getEngine ();
102- js .eval ("function(){" + code + "}" );
103- GraphProperties props = graphProperties ();
104- boolean replaced = props .hasProperty (name );
105- props .setProperty (name , code );
106- return Stream .of (new Result (String .format ("%s Function %s" , replaced ? "Updated" : "Added" , name )));
107- } catch (ScriptException e ) {
108- throw new RuntimeException (e );
109- }
82+ public Stream <Result > run (@ Name ("name" ) String name , @ Name (value ="params" ,defaultValue ="[]" ) List <Object > params ) throws ScriptException , NoSuchMethodException {
83+ Object value = runFunction (name , params );
84+ if (value instanceof Object []) {
85+ return Stream .of ((Object []) value ).map (Result ::new );
86+ }
87+ if (value instanceof Iterable ) {
88+ return StreamSupport .stream (((Iterable <?>)value ).spliterator (),false ).map (Result ::new );
89+ }
90+ return Stream .of (new Result (value ));
11091 }
11192
112- @ Procedure
113- @ PerformsWrites
93+ @ Procedure (mode =Mode .WRITE )
94+ public Stream <Result > function (@ Name ("name" ) String name , @ Name ("code" ) String code ) throws ScriptException {
95+ ScriptEngine js = getEngine ();
96+ js .eval ("function(){" + code + "}" );
97+ GraphProperties props = graphProperties ();
98+ boolean replaced = props .hasProperty (PREFIX + name );
99+ props .setProperty (PREFIX + name , code );
100+ return Stream .of (new Result (String .format ("%s Function %s" , replaced ? "Updated" : "Added" , name )));
101+ }
102+
103+ @ Procedure (mode =Mode .WRITE )
114104 public Stream <Result > delete (@ Name ("name" ) String name ) {
115105 GraphProperties props = graphProperties ();
116- props .removeProperty (name );
106+ props .removeProperty (PREFIX + name );
117107 return Stream .of (new Result (String .format ("Function '%s' removed" , name )));
118108 }
119109
120110
121111 @ Procedure
122112 public Stream <Result > list () {
123- return StreamSupport .stream (graphProperties .getPropertyKeys ().spliterator (), false ).map (Result ::new );
113+ return StreamSupport .stream (graphProperties .getPropertyKeys ().spliterator (), false ).filter ( s -> s . startsWith ( PREFIX )). map (Result ::new );
124114 }
125115
126116 public static class Result {
0 commit comments