Skip to content

Commit 39d9312

Browse files
committed
DATAMONGO-479 - Polishing.
Removed ServersideJavaScript abstraction as we still had to resort on instanceof checks and it created more ambiguities than it helped (e.g. in a script with name and code, which of the two get's executed?). We now have an ExecutableMongoScript which is code only and a NamedMongoScript, which basically is the former assigned to a name. Execution can be triggered on the former or a name. ScriptOperations.exists(…) now returns a primitive boolean to avoid null checks. JavaDoc. Original pull request: #254.
1 parent a0e42f5 commit 39d9312

File tree

11 files changed

+194
-218
lines changed

11 files changed

+194
-218
lines changed
Lines changed: 45 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014 the original author or authors.
2+
* Copyright 2014-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,8 +27,8 @@
2727

2828
import org.bson.types.ObjectId;
2929
import org.springframework.dao.DataAccessException;
30-
import org.springframework.data.mongodb.core.script.CallableMongoScript;
31-
import org.springframework.data.mongodb.core.script.ServerSideJavaScript;
30+
import org.springframework.data.mongodb.core.script.ExecutableMongoScript;
31+
import org.springframework.data.mongodb.core.script.NamedMongoScript;
3232
import org.springframework.util.Assert;
3333
import org.springframework.util.CollectionUtils;
3434
import org.springframework.util.ObjectUtils;
@@ -41,12 +41,14 @@
4141
* Default implementation of {@link ScriptOperations} capable of saving and executing {@link ServerSideJavaScript}.
4242
*
4343
* @author Christoph Strobl
44+
* @author Oliver Gierke
4445
* @since 1.7
4546
*/
46-
public class DefaultScriptOperations implements ScriptOperations {
47+
class DefaultScriptOperations implements ScriptOperations {
4748

4849
private static final String SCRIPT_COLLECTION_NAME = "system.js";
4950
private static final String SCRIPT_NAME_PREFIX = "func_";
51+
5052
private final MongoOperations mongoOperations;
5153

5254
/**
@@ -63,39 +65,39 @@ public DefaultScriptOperations(MongoOperations mongoOperations) {
6365

6466
/*
6567
* (non-Javadoc)
66-
* @see org.springframework.data.mongodb.core.ScriptOperations#save(org.springframework.data.mongodb.core.script.MongoScript)
68+
* @see org.springframework.data.mongodb.core.ScriptOperations#register(org.springframework.data.mongodb.core.script.ExecutableMongoScript)
69+
*/
70+
@Override
71+
public NamedMongoScript register(ExecutableMongoScript script) {
72+
return register(new NamedMongoScript(generateScriptName(), script));
73+
}
74+
75+
/*
76+
* (non-Javadoc)
77+
* @see org.springframework.data.mongodb.core.ScriptOperations#register(org.springframework.data.mongodb.core.script.NamedMongoScript)
6778
*/
6879
@Override
69-
public CallableMongoScript register(ServerSideJavaScript script) {
80+
public NamedMongoScript register(NamedMongoScript script) {
7081

7182
Assert.notNull(script, "Script must not be null!");
7283

73-
CallableMongoScript callableScript = (script instanceof CallableMongoScript) ? (CallableMongoScript) script
74-
: new CallableMongoScript(generateScriptName(), script);
75-
mongoOperations.save(callableScript, SCRIPT_COLLECTION_NAME);
76-
return callableScript;
84+
mongoOperations.save(script, SCRIPT_COLLECTION_NAME);
85+
return script;
7786
}
7887

7988
/*
8089
* (non-Javadoc)
81-
* @see org.springframework.data.mongodb.core.ScriptOperations#execute(org.springframework.data.mongodb.core.script.MongoScript, java.lang.Object[])
90+
* @see org.springframework.data.mongodb.core.ScriptOperations#execute(org.springframework.data.mongodb.core.script.ExecutableMongoScript, java.lang.Object[])
8291
*/
8392
@Override
84-
public Object execute(final ServerSideJavaScript script, final Object... args) {
93+
public Object execute(final ExecutableMongoScript script, final Object... args) {
8594

8695
Assert.notNull(script, "Script must not be null!");
8796

88-
if (script instanceof CallableMongoScript) {
89-
return call(((CallableMongoScript) script).getName(), args);
90-
}
91-
9297
return mongoOperations.execute(new DbCallback<Object>() {
9398

9499
@Override
95100
public Object doInDB(DB db) throws MongoException, DataAccessException {
96-
97-
Assert.notNull(script.getCode(), "Script.code must not be null!");
98-
99101
return db.eval(script.getCode(), convertScriptArgs(args));
100102
}
101103
});
@@ -114,9 +116,7 @@ public Object call(final String scriptName, final Object... args) {
114116

115117
@Override
116118
public Object doInDB(DB db) throws MongoException, DataAccessException {
117-
118-
String evalString = scriptName + "(" + convertAndJoinScriptArgs(args) + ")";
119-
return db.eval(evalString);
119+
return db.eval(String.format("%s(%s)", scriptName, convertAndJoinScriptArgs(args)));
120120
}
121121
});
122122
}
@@ -126,43 +126,33 @@ public Object doInDB(DB db) throws MongoException, DataAccessException {
126126
* @see org.springframework.data.mongodb.core.ScriptOperations#exists(java.lang.String)
127127
*/
128128
@Override
129-
public Boolean exists(String scriptName) {
129+
public boolean exists(String scriptName) {
130130

131131
Assert.hasText(scriptName, "ScriptName must not be null or empty!");
132132

133-
return mongoOperations.exists(query(where("name").is(scriptName)), CallableMongoScript.class,
134-
SCRIPT_COLLECTION_NAME);
133+
return mongoOperations.exists(query(where("name").is(scriptName)), NamedMongoScript.class, SCRIPT_COLLECTION_NAME);
135134
}
136135

137136
/*
138137
* (non-Javadoc)
139-
* @see org.springframework.data.mongodb.core.ScriptOperations#scriptNames()
138+
* @see org.springframework.data.mongodb.core.ScriptOperations#getScriptNames()
140139
*/
141140
@Override
142-
public Set<String> scriptNames() {
141+
public Set<String> getScriptNames() {
143142

144-
List<CallableMongoScript> scripts = (mongoOperations.findAll(CallableMongoScript.class, SCRIPT_COLLECTION_NAME));
143+
List<NamedMongoScript> scripts = mongoOperations.findAll(NamedMongoScript.class, SCRIPT_COLLECTION_NAME);
145144

146145
if (CollectionUtils.isEmpty(scripts)) {
147146
return Collections.emptySet();
148147
}
149148

150149
Set<String> scriptNames = new HashSet<String>();
151-
for (CallableMongoScript script : scripts) {
150+
151+
for (NamedMongoScript script : scripts) {
152152
scriptNames.add(script.getName());
153153
}
154-
return scriptNames;
155-
}
156154

157-
/**
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}.
161-
*
162-
* @return
163-
*/
164-
private String generateScriptName() {
165-
return SCRIPT_NAME_PREFIX + randomUUID().toString().replaceAll("-", "");
155+
return scriptNames;
166156
}
167157

168158
private Object[] convertScriptArgs(Object... args) {
@@ -172,23 +162,27 @@ private Object[] convertScriptArgs(Object... args) {
172162
}
173163

174164
List<Object> convertedValues = new ArrayList<Object>(args.length);
165+
175166
for (Object arg : args) {
176-
if (arg instanceof String) {
177-
convertedValues.add("'" + arg + "'");
178-
} else {
179-
convertedValues.add(this.mongoOperations.getConverter().convertToMongoType(arg));
180-
}
167+
convertedValues.add(arg instanceof String ? String.format("'%s'", arg) : this.mongoOperations.getConverter()
168+
.convertToMongoType(arg));
181169
}
170+
182171
return convertedValues.toArray();
183172
}
184173

185174
private String convertAndJoinScriptArgs(Object... args) {
186-
187-
if (ObjectUtils.isEmpty(args)) {
188-
return "";
189-
}
190-
191-
return StringUtils.arrayToCommaDelimitedString(convertScriptArgs(args));
175+
return ObjectUtils.isEmpty(args) ? "" : StringUtils.arrayToCommaDelimitedString(convertScriptArgs(args));
192176
}
193177

178+
/**
179+
* Generate a valid name for the {@literal JavaScript}. MongoDB requires an id of type String for scripts. Calling
180+
* scripts having {@link ObjectId} as id fails. Therefore we create a random UUID without {@code -} (as this won't
181+
* work) an prefix the result with {@link #SCRIPT_NAME_PREFIX}.
182+
*
183+
* @return
184+
*/
185+
private static String generateScriptName() {
186+
return SCRIPT_NAME_PREFIX + randomUUID().toString().replaceAll("-", "");
187+
}
194188
}

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

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014 the original author or authors.
2+
* Copyright 2014-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,27 +17,36 @@
1717

1818
import java.util.Set;
1919

20-
import org.springframework.data.mongodb.core.script.CallableMongoScript;
21-
import org.springframework.data.mongodb.core.script.ServerSideJavaScript;
20+
import org.springframework.data.mongodb.core.script.ExecutableMongoScript;
21+
import org.springframework.data.mongodb.core.script.NamedMongoScript;
2222

2323
import com.mongodb.DB;
2424

2525
/**
26-
* Script operations on {@link com.mongodb.DB} level. Allows interaction with server side {@literal JavaScript}
27-
* functions.
26+
* Script operations on {@link com.mongodb.DB} level. Allows interaction with server side JavaScript functions.
2827
*
2928
* @author Christoph Strobl
29+
* @author Oliver Gierke
3030
* @since 1.7
3131
*/
3232
public interface ScriptOperations {
3333

3434
/**
35-
* Store given {@literal script} to {@link com.mongodb.DB} so it can be called via its name.
35+
* Store given {@link ExecutableMongoScript} generating a syntheitcal name so that it can be called by it
36+
* subsequently.
3637
*
3738
* @param script must not be {@literal null}.
38-
* @return {@link CallableMongoScript} with name under which the {@literal JavaScript} function can be called.
39+
* @return {@link NamedMongoScript} with name under which the {@code JavaScript} function can be called.
3940
*/
40-
CallableMongoScript register(ServerSideJavaScript script);
41+
NamedMongoScript register(ExecutableMongoScript script);
42+
43+
/**
44+
* Registers the given {@link NamedMongoScript} in the database.
45+
*
46+
* @param script the {@link NamedMongoScript} to be registered.
47+
* @return
48+
*/
49+
NamedMongoScript register(NamedMongoScript script);
4150

4251
/**
4352
* Executes the {@literal script} by either calling it via its {@literal name} or directly sending it.
@@ -47,7 +56,7 @@ public interface ScriptOperations {
4756
* @return the script evaluation result.
4857
* @throws org.springframework.dao.DataAccessException
4958
*/
50-
Object execute(ServerSideJavaScript script, Object... args);
59+
Object execute(ExecutableMongoScript script, Object... args);
5160

5261
/**
5362
* Call the {@literal JavaScript} by its name.
@@ -64,13 +73,12 @@ public interface ScriptOperations {
6473
* @param scriptName must not be {@literal null} or empty.
6574
* @return false if no {@link ServerSideJavaScript} with given name exists.
6675
*/
67-
Boolean exists(String scriptName);
76+
boolean exists(String scriptName);
6877

6978
/**
7079
* Returns names of {@literal JavaScript} functions that can be called.
7180
*
7281
* @return empty {@link Set} if no scripts found.
7382
*/
74-
Set<String> scriptNames();
75-
83+
Set<String> getScriptNames();
7684
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@
4444
import org.springframework.data.mapping.model.SimpleTypeHolder;
4545
import org.springframework.data.mongodb.core.convert.MongoConverters.BigDecimalToStringConverter;
4646
import org.springframework.data.mongodb.core.convert.MongoConverters.BigIntegerToStringConverter;
47-
import org.springframework.data.mongodb.core.convert.MongoConverters.CallableMongoScriptToDBObjectConverter;
48-
import org.springframework.data.mongodb.core.convert.MongoConverters.DBObjectToCallableMongoScriptCoverter;
47+
import org.springframework.data.mongodb.core.convert.MongoConverters.NamedMongoScriptToDBObjectConverter;
48+
import org.springframework.data.mongodb.core.convert.MongoConverters.DBObjectToNamedMongoScriptCoverter;
4949
import org.springframework.data.mongodb.core.convert.MongoConverters.DBObjectToStringConverter;
5050
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigDecimalConverter;
5151
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigIntegerConverter;
@@ -120,8 +120,8 @@ public CustomConversions(List<?> converters) {
120120
toRegister.add(StringToURLConverter.INSTANCE);
121121
toRegister.add(DBObjectToStringConverter.INSTANCE);
122122
toRegister.add(TermToStringConverter.INSTANCE);
123-
toRegister.add(CallableMongoScriptToDBObjectConverter.INSTANCE);
124-
toRegister.add(DBObjectToCallableMongoScriptCoverter.INSTANCE);
123+
toRegister.add(NamedMongoScriptToDBObjectConverter.INSTANCE);
124+
toRegister.add(DBObjectToNamedMongoScriptCoverter.INSTANCE);
125125

126126
toRegister.addAll(JodaTimeConverters.getConvertersToRegister());
127127
toRegister.addAll(GeoConverters.getConvertersToRegister());

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

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011-2014 the original author or authors.
2+
* Copyright 2011-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@
2828
import org.springframework.data.convert.ReadingConverter;
2929
import org.springframework.data.convert.WritingConverter;
3030
import org.springframework.data.mongodb.core.query.Term;
31-
import org.springframework.data.mongodb.core.script.CallableMongoScript;
31+
import org.springframework.data.mongodb.core.script.NamedMongoScript;
3232
import org.springframework.util.StringUtils;
3333

3434
import com.mongodb.BasicDBObject;
@@ -187,13 +187,12 @@ public String convert(Term source) {
187187
* @author Christoph Strobl
188188
* @since 1.7
189189
*/
190-
@ReadingConverter
191-
public static enum DBObjectToCallableMongoScriptCoverter implements Converter<DBObject, CallableMongoScript> {
190+
public static enum DBObjectToNamedMongoScriptCoverter implements Converter<DBObject, NamedMongoScript> {
192191

193192
INSTANCE;
194193

195194
@Override
196-
public CallableMongoScript convert(DBObject source) {
195+
public NamedMongoScript convert(DBObject source) {
197196

198197
if (source == null) {
199198
return null;
@@ -202,21 +201,20 @@ public CallableMongoScript convert(DBObject source) {
202201
String id = source.get("_id").toString();
203202
Object rawValue = source.get("value");
204203

205-
return new CallableMongoScript(id, ((Code) rawValue).getCode());
204+
return new NamedMongoScript(id, ((Code) rawValue).getCode());
206205
}
207206
}
208207

209208
/**
210209
* @author Christoph Strobl
211210
* @since 1.7
212211
*/
213-
@WritingConverter
214-
public static enum CallableMongoScriptToDBObjectConverter implements Converter<CallableMongoScript, DBObject> {
212+
public static enum NamedMongoScriptToDBObjectConverter implements Converter<NamedMongoScript, DBObject> {
215213

216214
INSTANCE;
217215

218216
@Override
219-
public DBObject convert(CallableMongoScript source) {
217+
public DBObject convert(NamedMongoScript source) {
220218

221219
if (source == null) {
222220
return new BasicDBObject();
@@ -225,9 +223,7 @@ public DBObject convert(CallableMongoScript source) {
225223
BasicDBObjectBuilder builder = new BasicDBObjectBuilder();
226224

227225
builder.append("_id", source.getName());
228-
if (source.getCode() != null) {
229-
builder.append("value", new Code(source.getCode()));
230-
}
226+
builder.append("value", new Code(source.getCode()));
231227

232228
return builder.get();
233229
}

0 commit comments

Comments
 (0)