Skip to content

Commit c7db98b

Browse files
DATAMONGO-479 - Add support for calling functions.
Use more explicit wording and add methods for checking existence of functions via name as well as listing names of available scripts. Updated javaDoc and reference documentation.
1 parent 4921118 commit c7db98b

File tree

11 files changed

+241
-110
lines changed

11 files changed

+241
-110
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultScriptOperations.java

Lines changed: 67 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,26 @@
1919
import static org.springframework.data.mongodb.core.query.Criteria.*;
2020
import static org.springframework.data.mongodb.core.query.Query.*;
2121

22-
import java.io.Serializable;
2322
import java.util.ArrayList;
23+
import java.util.Collections;
24+
import java.util.HashSet;
2425
import java.util.List;
26+
import java.util.Set;
2527

28+
import org.bson.types.ObjectId;
2629
import org.springframework.dao.DataAccessException;
2730
import org.springframework.data.mongodb.core.script.CallableMongoScript;
28-
import org.springframework.data.mongodb.core.script.MongoScript;
31+
import org.springframework.data.mongodb.core.script.ServerSideJavaScript;
2932
import org.springframework.util.Assert;
33+
import org.springframework.util.CollectionUtils;
3034
import org.springframework.util.ObjectUtils;
3135
import org.springframework.util.StringUtils;
3236

3337
import com.mongodb.DB;
3438
import com.mongodb.MongoException;
3539

3640
/**
37-
* Default implementation of {@link ScriptOperations} capable of saving and executing simple {@link MongoScript}.
41+
* Default implementation of {@link ScriptOperations} capable of saving and executing {@link ServerSideJavaScript}.
3842
*
3943
* @author Christoph Strobl
4044
* @since 1.7
@@ -53,6 +57,7 @@ public class DefaultScriptOperations implements ScriptOperations {
5357
public DefaultScriptOperations(MongoOperations mongoOperations) {
5458

5559
Assert.notNull(mongoOperations, "MongoOperations must not be null!");
60+
5661
this.mongoOperations = mongoOperations;
5762
}
5863

@@ -61,17 +66,12 @@ public DefaultScriptOperations(MongoOperations mongoOperations) {
6166
* @see org.springframework.data.mongodb.core.ScriptOperations#save(org.springframework.data.mongodb.core.script.MongoScript)
6267
*/
6368
@Override
64-
public CallableMongoScript save(MongoScript script) {
69+
public CallableMongoScript register(ServerSideJavaScript script) {
6570

6671
Assert.notNull(script, "Script must not be null!");
67-
CallableMongoScript callableScript = null;
68-
69-
if (script instanceof CallableMongoScript) {
70-
callableScript = (CallableMongoScript) script;
71-
} else {
72-
callableScript = new CallableMongoScript(generateScriptName(), script);
73-
}
7472

73+
CallableMongoScript callableScript = (script instanceof CallableMongoScript) ? (CallableMongoScript) script
74+
: new CallableMongoScript(generateScriptName(), script);
7575
mongoOperations.save(callableScript, SCRIPT_COLLECTION_NAME);
7676
return callableScript;
7777
}
@@ -81,41 +81,83 @@ public CallableMongoScript save(MongoScript script) {
8181
* @see org.springframework.data.mongodb.core.ScriptOperations#execute(org.springframework.data.mongodb.core.script.MongoScript, java.lang.Object[])
8282
*/
8383
@Override
84-
public Object execute(final MongoScript script, final Object... args) {
84+
public Object execute(final ServerSideJavaScript script, final Object... args) {
8585

8686
Assert.notNull(script, "Script must not be null!");
87+
88+
if (script instanceof CallableMongoScript) {
89+
return call(((CallableMongoScript) script).getName(), args);
90+
}
91+
8792
return mongoOperations.execute(new DbCallback<Object>() {
8893

8994
@Override
9095
public Object doInDB(DB db) throws MongoException, DataAccessException {
9196

92-
if (script instanceof CallableMongoScript) {
97+
Assert.notNull(script.getCode(), "Script.code must not be null!");
98+
99+
return db.eval(script.getCode(), convertScriptArgs(args));
100+
}
101+
});
102+
}
93103

94-
String evalString = ((CallableMongoScript) script).getName() + "(" + convertAndJoinScriptArgs(args) + ")";
95-
return db.eval(evalString);
96-
}
104+
/*
105+
* (non-Javadoc)
106+
* @see org.springframework.data.mongodb.core.ScriptOperations#call(java.lang.String, java.lang.Object[])
107+
*/
108+
@Override
109+
public Object call(final String scriptName, final Object... args) {
97110

98-
Assert.notNull(script.getCode(), "Script.code must not be null!");
99-
return db.eval(script.getCode().toString(), convertScriptArgs(args));
111+
Assert.hasText(scriptName, "ScriptName must not be null or empty!");
112+
113+
return mongoOperations.execute(new DbCallback<Object>() {
114+
115+
@Override
116+
public Object doInDB(DB db) throws MongoException, DataAccessException {
117+
118+
String evalString = scriptName + "(" + convertAndJoinScriptArgs(args) + ")";
119+
return db.eval(evalString);
100120
}
101121
});
102122
}
103123

104124
/*
105125
* (non-Javadoc)
106-
* @see org.springframework.data.mongodb.core.ScriptOperations#load(java.io.Serializable)
126+
* @see org.springframework.data.mongodb.core.ScriptOperations#exists(java.lang.String)
127+
*/
128+
@Override
129+
public Boolean exists(String scriptName) {
130+
131+
Assert.hasText(scriptName, "ScriptName must not be null or empty!");
132+
133+
return mongoOperations.exists(query(where("name").is(scriptName)), CallableMongoScript.class,
134+
SCRIPT_COLLECTION_NAME);
135+
}
136+
137+
/*
138+
* (non-Javadoc)
139+
* @see org.springframework.data.mongodb.core.ScriptOperations#scriptNames()
107140
*/
108141
@Override
109-
public CallableMongoScript load(Serializable name) {
142+
public Set<String> scriptNames() {
110143

111-
Assert.notNull(name, "Name must not be null!");
112-
return mongoOperations.findOne(query(where("name").is(name)), CallableMongoScript.class, SCRIPT_COLLECTION_NAME);
144+
List<CallableMongoScript> scripts = (mongoOperations.findAll(CallableMongoScript.class, SCRIPT_COLLECTION_NAME));
145+
146+
if (CollectionUtils.isEmpty(scripts)) {
147+
return Collections.emptySet();
148+
}
149+
150+
Set<String> scriptNames = new HashSet<String>();
151+
for (CallableMongoScript script : scripts) {
152+
scriptNames.add(script.getName());
153+
}
154+
return scriptNames;
113155
}
114156

115157
/**
116-
* Generate a valid name for the script. MongoDB requires a script id of type String. Calling scripts having ObjectId
117-
* as id fails. Therefore we create a random UUID without {@code -} (as this won't work) an prefix the result with
118-
* {@link #SCRIPT_NAME_PREFIX}.
158+
* Generate a valid name for the {@literal JavaScript}. MongoDB requires an id of type String for scripts. Calling
159+
* scripts having {@link ObjectId} as id fails. Therefore we create a random UUID without {@code -} (as this won't
160+
* work) an prefix the result with {@link #SCRIPT_NAME_PREFIX}.
119161
*
120162
* @return
121163
*/

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScriptOperations.java

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,43 +15,62 @@
1515
*/
1616
package org.springframework.data.mongodb.core;
1717

18-
import java.io.Serializable;
18+
import java.util.Set;
1919

2020
import org.springframework.data.mongodb.core.script.CallableMongoScript;
21-
import org.springframework.data.mongodb.core.script.MongoScript;
21+
import org.springframework.data.mongodb.core.script.ServerSideJavaScript;
22+
23+
import com.mongodb.DB;
2224

2325
/**
24-
* Script operations on {@link com.mongodb.DB} level.
26+
* Script operations on {@link com.mongodb.DB} level. Allows interaction with server side {@literal JavaScript}
27+
* functions.
2528
*
2629
* @author Christoph Strobl
2730
* @since 1.7
2831
*/
2932
public interface ScriptOperations {
3033

3134
/**
32-
* Saves given {@literal script} to currently used {@link com.mongodb.DB}.
35+
* Store given {@literal script} to {@link com.mongodb.DB} so it can be called via its name.
3336
*
3437
* @param script must not be {@literal null}.
35-
* @return
38+
* @return {@link CallableMongoScript} with name under which the {@literal JavaScript} function can be called.
3639
*/
37-
CallableMongoScript save(MongoScript script);
40+
CallableMongoScript register(ServerSideJavaScript script);
3841

3942
/**
40-
* Executes the {@literal script} by either calling it via its {@literal _id} or directly sending it.
43+
* Executes the {@literal script} by either calling it via its {@literal name} or directly sending it.
4144
*
4245
* @param script must not be {@literal null}.
4346
* @param args arguments to pass on for script execution.
4447
* @return the script evaluation result.
4548
* @throws org.springframework.dao.DataAccessException
4649
*/
47-
Object execute(MongoScript script, Object... args);
50+
Object execute(ServerSideJavaScript script, Object... args);
51+
52+
/**
53+
* Call the {@literal JavaScript} by its name.
54+
*
55+
* @param scriptName must not be {@literal null} or empty.
56+
* @param args
57+
* @return
58+
*/
59+
Object call(String scriptName, Object... args);
60+
61+
/**
62+
* Checks {@link DB} for existence of {@link ServerSideJavaScript} with given name.
63+
*
64+
* @param scriptName must not be {@literal null} or empty.
65+
* @return false if no {@link ServerSideJavaScript} with given name exists.
66+
*/
67+
Boolean exists(String scriptName);
4868

4969
/**
50-
* Retrieves the {@link CallableMongoScript} by its {@literal id}.
70+
* Returns names of {@literal JavaScript} functions that can be called.
5171
*
52-
* @param name
53-
* @return {@literal null} if not found.
72+
* @return empty {@link Set} if no scripts found.
5473
*/
55-
CallableMongoScript load(Serializable name);
74+
Set<String> scriptNames();
5675

5776
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverters.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.net.MalformedURLException;
2121
import java.net.URL;
2222

23+
import org.bson.types.Code;
2324
import org.bson.types.ObjectId;
2425
import org.springframework.core.convert.ConversionFailedException;
2526
import org.springframework.core.convert.TypeDescriptor;
@@ -201,11 +202,7 @@ public CallableMongoScript convert(DBObject source) {
201202
String id = source.get("_id").toString();
202203
Object rawValue = source.get("value");
203204

204-
if (rawValue != null) {
205-
return new CallableMongoScript(id, rawValue.toString());
206-
}
207-
208-
return new CallableMongoScript(id);
205+
return new CallableMongoScript(id, rawValue.toString());
209206
}
210207
}
211208

@@ -229,7 +226,7 @@ public DBObject convert(CallableMongoScript source) {
229226

230227
builder.append("_id", source.getName());
231228
if (source.getCode() != null) {
232-
builder.append("value", source.getCode());
229+
builder.append("value", new Code(source.getCode()));
233230
}
234231

235232
return builder.get();

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/script/CallableMongoScript.java

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,37 +15,27 @@
1515
*/
1616
package org.springframework.data.mongodb.core.script;
1717

18-
import org.bson.types.Code;
1918
import org.springframework.data.annotation.Id;
2019
import org.springframework.util.Assert;
2120

2221
/**
23-
* A {@link MongoScript} implementation that allows calling the function by its {@literal id} once it has been saved to
24-
* the {@link com.mongodb.DB} instance.
22+
* A {@link ServerSideJavaScript} implementation that allows calling the function by its {@literal name} once it has
23+
* been saved to the {@link com.mongodb.DB} instance.
2524
*
2625
* @author Christoph Strobl
2726
* @since 1.7
2827
*/
29-
public class CallableMongoScript implements MongoScript {
28+
public class CallableMongoScript implements ServerSideJavaScript {
3029

3130
private final @Id String name;
32-
private final MongoScript script;
33-
34-
/**
35-
* Creates new {@link CallableMongoScript} that uses the given {@literal id} to call the function on the server.
36-
*
37-
* @param name must not be {@literal null} or {@literal empty}.
38-
*/
39-
public CallableMongoScript(String name) {
40-
this(name, (MongoScript) null);
41-
}
31+
private final ServerSideJavaScript script;
4232

4333
/**
4434
* Creates new {@link CallableMongoScript} that can be saved to the {@link com.mongodb.DB} instance.
4535
*
4636
* @param name must not be {@literal null} or {@literal empty}.
47-
* @param rawScript the {@link String} representation of the javascript function. Must not be {@literal null} or
48-
* {@literal empty}.
37+
* @param rawScript the {@link String} representation of the {@literal JavaScript} function. Must not be
38+
* {@literal null} or {@literal empty}.
4939
*/
5040
public CallableMongoScript(String name, String rawScript) {
5141
this(name, new ExecutableMongoScript(rawScript));
@@ -57,7 +47,7 @@ public CallableMongoScript(String name, String rawScript) {
5747
* @param name must not be {@literal null} or {@literal empty}.
5848
* @param script can be {@literal null}.
5949
*/
60-
public CallableMongoScript(String name, MongoScript script) {
50+
public CallableMongoScript(String name, ServerSideJavaScript script) {
6151

6252
Assert.hasText(name, "Name must not be null or empty!");
6353
this.name = name;
@@ -69,7 +59,7 @@ public CallableMongoScript(String name, MongoScript script) {
6959
* @see org.springframework.data.mongodb.core.script.MongoScript#getCode()
7060
*/
7161
@Override
72-
public Code getCode() {
62+
public String getCode() {
7363

7464
if (script == null) {
7565
return null;
@@ -79,7 +69,7 @@ public Code getCode() {
7969
}
8070

8171
/**
82-
* Get the id of the callable script.
72+
* Get the name of the {@link CallableMongoScript} script.
8373
*
8474
* @return
8575
*/

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/script/ExecutableMongoScript.java

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,37 +15,36 @@
1515
*/
1616
package org.springframework.data.mongodb.core.script;
1717

18-
import org.bson.types.Code;
1918
import org.springframework.util.Assert;
2019

2120
/**
22-
* {@link MongoScript} implementation that can be saved or directly executed.
21+
* {@link ServerSideJavaScript} implementation that can be saved or directly executed.
2322
*
2423
* @author Christoph Strobl
2524
* @since 1.7
2625
*/
27-
public class ExecutableMongoScript implements MongoScript {
26+
public class ExecutableMongoScript implements ServerSideJavaScript {
2827

29-
private final String rawScript;
28+
private final String code;
3029

3130
/**
3231
* Creates new {@link ExecutableMongoScript}.
3332
*
34-
* @param rawScript must not be {@literal null} or {@literal empty}.
33+
* @param code must not be {@literal null} or {@literal empty}.
3534
*/
36-
public ExecutableMongoScript(String rawScript) {
35+
public ExecutableMongoScript(String code) {
3736

38-
Assert.hasText(rawScript, "RawScript must not be null or empty!");
39-
this.rawScript = rawScript;
37+
Assert.hasText(code, "Code must not be null or empty!");
38+
this.code = code;
4039
}
4140

4241
/*
4342
* (non-Javadoc)
4443
* @see org.springframework.data.mongodb.core.script.MongoScript#getCode()
4544
*/
4645
@Override
47-
public Code getCode() {
48-
return new Code(this.rawScript);
46+
public String getCode() {
47+
return this.code;
4948
}
5049

5150
}

0 commit comments

Comments
 (0)