Change indentation from spaces to tabs.

This commit is contained in:
Oliver Gierke
2011-05-13 18:04:19 +02:00
parent 94e4d2b095
commit 025691a97a
166 changed files with 7570 additions and 7663 deletions

View File

@@ -19,39 +19,39 @@ import org.springframework.dao.DataAccessResourceFailureException;
public class CannotGetMongoDbConnectionException extends DataAccessResourceFailureException {
private String username;
private char[] password;
private String database;
private static final long serialVersionUID = 1172099106475265589L;
private String username;
public CannotGetMongoDbConnectionException(String msg, Throwable cause) {
super(msg, cause);
}
public CannotGetMongoDbConnectionException(String msg) {
super(msg);
}
private char[] password;
public CannotGetMongoDbConnectionException(String msg, String database, String username, char[] password2) {
super(msg);
this.username = username;
this.password = password2;
this.database = database;
}
private String database;
public String getUsername() {
return username;
}
private static final long serialVersionUID = 1172099106475265589L;
public char[] getPassword() {
return password;
}
public CannotGetMongoDbConnectionException(String msg, Throwable cause) {
super(msg, cause);
}
public CannotGetMongoDbConnectionException(String msg) {
super(msg);
}
public CannotGetMongoDbConnectionException(String msg, String database, String username, char[] password2) {
super(msg);
this.username = username;
this.password = password2;
this.database = database;
}
public String getUsername() {
return username;
}
public char[] getPassword() {
return password;
}
public String getDatabase() {
return database;
}
public String getDatabase() {
return database;
}
}

View File

@@ -21,6 +21,6 @@ import org.springframework.dao.DataAccessException;
public interface CollectionCallback<T> {
T doInCollection(DBCollection collection) throws MongoException, DataAccessException;
T doInCollection(DBCollection collection) throws MongoException, DataAccessException;
}

View File

@@ -17,55 +17,57 @@ package org.springframework.data.document.mongodb;
/**
* Provides a simple wrapper to encapsulate the variety of settings you can use when creating a collection.
*
*
* @author Thomas Risberg
*/
public class CollectionOptions {
private Integer maxDocuments;
private Integer maxDocuments;
private Integer size;
private Integer size;
private Boolean capped;
private Boolean capped;
/**
* Constructs a new <code>CollectionOptions</code> instance.
*
* @param size the collection size in bytes, this data space is preallocated
* @param maxDocuments the maximum number of documents in the collection.
* @param capped true to created a "capped" collection (fixed size with auto-FIFO behavior
* based on insertion order), false otherwise.
*/
public CollectionOptions(Integer size, Integer maxDocuments, Boolean capped) {
super();
this.maxDocuments = maxDocuments;
this.size = size;
this.capped = capped;
}
/**
* Constructs a new <code>CollectionOptions</code> instance.
*
* @param size
* the collection size in bytes, this data space is preallocated
* @param maxDocuments
* the maximum number of documents in the collection.
* @param capped
* true to created a "capped" collection (fixed size with auto-FIFO behavior based on insertion order), false
* otherwise.
*/
public CollectionOptions(Integer size, Integer maxDocuments, Boolean capped) {
super();
this.maxDocuments = maxDocuments;
this.size = size;
this.capped = capped;
}
public Integer getMaxDocuments() {
return maxDocuments;
}
public Integer getMaxDocuments() {
return maxDocuments;
}
public void setMaxDocuments(Integer maxDocuments) {
this.maxDocuments = maxDocuments;
}
public void setMaxDocuments(Integer maxDocuments) {
this.maxDocuments = maxDocuments;
}
public Integer getSize() {
return size;
}
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
public void setSize(Integer size) {
this.size = size;
}
public Boolean getCapped() {
return capped;
}
public void setCapped(Boolean capped) {
this.capped = capped;
}
public Boolean getCapped() {
return capped;
}
public void setCapped(Boolean capped) {
this.capped = capped;
}
}

View File

@@ -17,18 +17,17 @@ package org.springframework.data.document.mongodb;
import com.mongodb.DBCursor;
/**
* Simple callback interface to allow customization of a {@link DBCursor}.
*
*
* @author Oliver Gierke
*/
public interface CursorPreparer {
/**
* Prepare the given cursor (apply limits, skips and so on). Returns th eprepared cursor.
*
* @param cursor
*/
DBCursor prepare(DBCursor cursor);
/**
* Prepare the given cursor (apply limits, skips and so on). Returns th eprepared cursor.
*
* @param cursor
*/
DBCursor prepare(DBCursor cursor);
}

View File

@@ -21,5 +21,5 @@ import org.springframework.dao.DataAccessException;
public interface DbCallback<T> {
T doInDB(DB db) throws MongoException, DataAccessException;
T doInDB(DB db) throws MongoException, DataAccessException;
}

View File

@@ -8,63 +8,59 @@ import org.springframework.transaction.support.ResourceHolderSupport;
import org.springframework.util.Assert;
class DbHolder extends ResourceHolderSupport {
private static final Object DEFAULT_KEY = new Object();
private static final Object DEFAULT_KEY = new Object();
private final Map<Object, DB> dbMap = new ConcurrentHashMap<Object, DB>();
private final Map<Object, DB> dbMap = new ConcurrentHashMap<Object, DB>();
public DbHolder(DB db) {
addDB(db);
}
public DbHolder(DB db) {
addDB(db);
}
public DbHolder(Object key, DB db) {
addDB(key, db);
}
public DbHolder(Object key, DB db) {
addDB(key, db);
}
public DB getDB() {
return getDB(DEFAULT_KEY);
}
public DB getDB(Object key) {
return this.dbMap.get(key);
}
public DB getDB() {
return getDB(DEFAULT_KEY);
}
public DB getAnyDB() {
if (!this.dbMap.isEmpty()) {
return this.dbMap.values().iterator().next();
}
return null;
}
public DB getDB(Object key) {
return this.dbMap.get(key);
}
public void addDB(DB session) {
addDB(DEFAULT_KEY, session);
}
public void addDB(Object key, DB session) {
Assert.notNull(key, "Key must not be null");
Assert.notNull(session, "DB must not be null");
this.dbMap.put(key, session);
}
public DB getAnyDB() {
if (!this.dbMap.isEmpty()) {
return this.dbMap.values().iterator().next();
}
return null;
}
public DB removeDB(Object key) {
return this.dbMap.remove(key);
}
public void addDB(DB session) {
addDB(DEFAULT_KEY, session);
}
public boolean containsDB(DB session) {
return this.dbMap.containsValue(session);
}
public void addDB(Object key, DB session) {
Assert.notNull(key, "Key must not be null");
Assert.notNull(session, "DB must not be null");
this.dbMap.put(key, session);
}
public boolean isEmpty() {
return this.dbMap.isEmpty();
}
public DB removeDB(Object key) {
return this.dbMap.remove(key);
}
public boolean containsDB(DB session) {
return this.dbMap.containsValue(session);
}
public boolean isEmpty() {
return this.dbMap.isEmpty();
}
public boolean doesNotHoldNonDefaultDB() {
synchronized (this.dbMap) {
return this.dbMap.isEmpty() ||
(this.dbMap.size() == 1 && this.dbMap.containsKey(DEFAULT_KEY));
}
}
public boolean doesNotHoldNonDefaultDB() {
synchronized (this.dbMap) {
return this.dbMap.isEmpty() || (this.dbMap.size() == 1 && this.dbMap.containsKey(DEFAULT_KEY));
}
}
}

View File

@@ -24,71 +24,72 @@ import org.springframework.jmx.export.annotation.ManagedResource;
/**
* Mongo server administration exposed via JMX annotations
*
*
* @author Mark Pollack
*/
@ManagedResource(description = "Mongo Admin Operations")
public class MongoAdmin implements MongoAdminOperations {
/**
* Logger available to subclasses
*/
protected final Log logger = LogFactory.getLog(getClass());
/**
* Logger available to subclasses
*/
protected final Log logger = LogFactory.getLog(getClass());
private Mongo mongo;
private String username;
private String password;
private Mongo mongo;
private String username;
private String password;
public MongoAdmin(Mongo mongo) {
this.mongo = mongo;
}
public MongoAdmin(Mongo mongo) {
this.mongo = mongo;
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoAdminOperations#dropDatabase(java.lang.String)
*/
@ManagedOperation
public void dropDatabase(String databaseName) {
getDB(databaseName).dropDatabase();
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoAdminOperations#dropDatabase(java.lang.String)
*/
@ManagedOperation
public void dropDatabase(String databaseName) {
getDB(databaseName).dropDatabase();
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoAdminOperations#createDatabase(java.lang.String)
*/
@ManagedOperation
public void createDatabase(String databaseName) {
getDB(databaseName);
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoAdminOperations#createDatabase(java.lang.String)
*/
@ManagedOperation
public void createDatabase(String databaseName) {
getDB(databaseName);
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoAdminOperations#getDatabaseStats(java.lang.String)
*/
@ManagedOperation
public String getDatabaseStats(String databaseName) {
return getDB(databaseName).getStats().toString();
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoAdminOperations#getDatabaseStats(java.lang.String)
*/
@ManagedOperation
public String getDatabaseStats(String databaseName) {
return getDB(databaseName).getStats().toString();
}
/**
* Sets the username to use to connect to the Mongo database
*
* @param username The username to use
*/
public void setUsername(String username) {
this.username = username;
}
/**
* Sets the username to use to connect to the Mongo database
*
* @param username
* The username to use
*/
public void setUsername(String username) {
this.username = username;
}
/**
* Sets the password to use to authenticate with the Mongo database.
*
* @param password The password to use
*/
public void setPassword(String password) {
/**
* Sets the password to use to authenticate with the Mongo database.
*
* @param password
* The password to use
*/
public void setPassword(String password) {
this.password = password;
}
this.password = password;
}
DB getDB(String databaseName) {
return MongoDbUtils.getDB(mongo, databaseName, username, password == null ? null : password.toCharArray());
}
DB getDB(String databaseName) {
return MongoDbUtils.getDB(mongo, databaseName, username, password == null ? null : password.toCharArray());
}
}

View File

@@ -4,13 +4,13 @@ import org.springframework.jmx.export.annotation.ManagedOperation;
public interface MongoAdminOperations {
@ManagedOperation
public abstract void dropDatabase(String databaseName);
@ManagedOperation
public abstract void dropDatabase(String databaseName);
@ManagedOperation
public abstract void createDatabase(String databaseName);
@ManagedOperation
public abstract void createDatabase(String databaseName);
@ManagedOperation
public abstract String getDatabaseStats(String databaseName);
@ManagedOperation
public abstract String getDatabaseStats(String databaseName);
}

View File

@@ -27,8 +27,9 @@ import org.springframework.util.Assert;
/**
* Helper class featuring helper methods for internal MongoDb classes.
* <p/>
* <p>Mainly intended for internal use within the framework.
*
* <p>
* Mainly intended for internal use within the framework.
*
* @author Thomas Risberg
* @author Graeme Rocher
* @author Oliver Gierke
@@ -36,133 +37,138 @@ import org.springframework.util.Assert;
*/
public abstract class MongoDbUtils {
private static final Log LOGGER = LogFactory.getLog(MongoDbUtils.class);
private static final Log LOGGER = LogFactory.getLog(MongoDbUtils.class);
/**
* Private constructor to prevent instantiation.
*/
private MongoDbUtils() {
/**
* Private constructor to prevent instantiation.
*/
private MongoDbUtils() {
}
}
/**
* Obtains a {@link DB} connection for the given {@link Mongo} instance and database name
*
* @param mongo The {@link Mongo} instance
* @param databaseName The database name
* @return The {@link DB} connection
*/
public static DB getDB(Mongo mongo, String databaseName) {
return doGetDB(mongo, databaseName, null, null, true);
}
/**
* Obtains a {@link DB} connection for the given {@link Mongo} instance and database name
*
* @param mongo
* The {@link Mongo} instance
* @param databaseName
* The database name
* @return The {@link DB} connection
*/
public static DB getDB(Mongo mongo, String databaseName) {
return doGetDB(mongo, databaseName, null, null, true);
}
/**
* Obtains a {@link DB} connection for the given {@link Mongo} instance and database name
*
* @param mongo The {@link Mongo} instance
* @param databaseName The database name
* @param username The username to authenticate with
* @param password The password to authenticate with
* @return The {@link DB} connection
*/
public static DB getDB(Mongo mongo, String databaseName, String username, char[] password) {
return doGetDB(mongo, databaseName, username, password, true);
}
/**
* Obtains a {@link DB} connection for the given {@link Mongo} instance and database name
*
* @param mongo
* The {@link Mongo} instance
* @param databaseName
* The database name
* @param username
* The username to authenticate with
* @param password
* The password to authenticate with
* @return The {@link DB} connection
*/
public static DB getDB(Mongo mongo, String databaseName, String username, char[] password) {
return doGetDB(mongo, databaseName, username, password, true);
}
public static DB doGetDB(Mongo mongo, String databaseName, String username, char[] password, boolean allowCreate) {
Assert.notNull(mongo, "No Mongo instance specified");
public static DB doGetDB(Mongo mongo, String databaseName, String username, char[] password, boolean allowCreate) {
Assert.notNull(mongo, "No Mongo instance specified");
DbHolder dbHolder = (DbHolder) TransactionSynchronizationManager.getResource(mongo);
if (dbHolder != null && !dbHolder.isEmpty()) {
// pre-bound Mongo DB
DB db = null;
if (TransactionSynchronizationManager.isSynchronizationActive() &&
dbHolder.doesNotHoldNonDefaultDB()) {
// Spring transaction management is active ->
db = dbHolder.getDB();
if (db != null && !dbHolder.isSynchronizedWithTransaction()) {
LOGGER.debug("Registering Spring transaction synchronization for existing Mongo DB");
TransactionSynchronizationManager.registerSynchronization(new MongoSynchronization(dbHolder, mongo));
dbHolder.setSynchronizedWithTransaction(true);
}
}
if (db != null) {
return db;
}
}
DbHolder dbHolder = (DbHolder) TransactionSynchronizationManager.getResource(mongo);
if (dbHolder != null && !dbHolder.isEmpty()) {
// pre-bound Mongo DB
DB db = null;
if (TransactionSynchronizationManager.isSynchronizationActive() && dbHolder.doesNotHoldNonDefaultDB()) {
// Spring transaction management is active ->
db = dbHolder.getDB();
if (db != null && !dbHolder.isSynchronizedWithTransaction()) {
LOGGER.debug("Registering Spring transaction synchronization for existing Mongo DB");
TransactionSynchronizationManager.registerSynchronization(new MongoSynchronization(dbHolder, mongo));
dbHolder.setSynchronizedWithTransaction(true);
}
}
if (db != null) {
return db;
}
}
LOGGER.trace("Getting Mongo Database name=["+databaseName+"]");
DB db = mongo.getDB(databaseName);
boolean credentialsGiven = username != null && password != null;
if (credentialsGiven && !db.isAuthenticated()) {
//Note, can only authenticate once against the same com.mongodb.DB object.
if (!db.authenticate(username, password)) {
throw new CannotGetMongoDbConnectionException("Failed to authenticate to database [" + databaseName +
"], username = [" + username + "], password = [" + new String(password) + "]", databaseName, username, password );
}
}
LOGGER.trace("Getting Mongo Database name=[" + databaseName + "]");
DB db = mongo.getDB(databaseName);
// Use same Session for further Mongo actions within the transaction.
// Thread object will get removed by synchronization at transaction completion.
if (TransactionSynchronizationManager.isSynchronizationActive()) {
// We're within a Spring-managed transaction, possibly from JtaTransactionManager.
LOGGER.debug("Registering Spring transaction synchronization for new Hibernate Session");
DbHolder holderToUse = dbHolder;
if (holderToUse == null) {
holderToUse = new DbHolder(db);
} else {
holderToUse.addDB(db);
}
TransactionSynchronizationManager.registerSynchronization(new MongoSynchronization(holderToUse, mongo));
holderToUse.setSynchronizedWithTransaction(true);
if (holderToUse != dbHolder) {
TransactionSynchronizationManager.bindResource(mongo, holderToUse);
}
}
boolean credentialsGiven = username != null && password != null;
if (credentialsGiven && !db.isAuthenticated()) {
// Note, can only authenticate once against the same com.mongodb.DB object.
if (!db.authenticate(username, password)) {
throw new CannotGetMongoDbConnectionException("Failed to authenticate to database [" + databaseName
+ "], username = [" + username + "], password = [" + new String(password) + "]", databaseName, username,
password);
}
}
// Check whether we are allowed to return the DB.
if (!allowCreate && !isDBTransactional(db, mongo)) {
throw new IllegalStateException("No Mongo DB bound to thread, " +
"and configuration does not allow creation of non-transactional one here");
}
// Use same Session for further Mongo actions within the transaction.
// Thread object will get removed by synchronization at transaction completion.
if (TransactionSynchronizationManager.isSynchronizationActive()) {
// We're within a Spring-managed transaction, possibly from JtaTransactionManager.
LOGGER.debug("Registering Spring transaction synchronization for new Hibernate Session");
DbHolder holderToUse = dbHolder;
if (holderToUse == null) {
holderToUse = new DbHolder(db);
} else {
holderToUse.addDB(db);
}
TransactionSynchronizationManager.registerSynchronization(new MongoSynchronization(holderToUse, mongo));
holderToUse.setSynchronizedWithTransaction(true);
if (holderToUse != dbHolder) {
TransactionSynchronizationManager.bindResource(mongo, holderToUse);
}
}
return db;
}
// Check whether we are allowed to return the DB.
if (!allowCreate && !isDBTransactional(db, mongo)) {
throw new IllegalStateException("No Mongo DB bound to thread, "
+ "and configuration does not allow creation of non-transactional one here");
}
return db;
}
/**
* Return whether the given DB instance is transactional, that is,
* bound to the current thread by Spring's transaction facilities.
*
* @param db the DB to check
* @param mongo the Mongo instance that the DB was created with
* (may be <code>null</code>)
* @return whether the DB is transactional
*/
public static boolean isDBTransactional(DB db, Mongo mongo) {
if (mongo == null) {
return false;
}
DbHolder dbHolder =
(DbHolder) TransactionSynchronizationManager.getResource(mongo);
return (dbHolder != null && dbHolder.containsDB(db));
}
/**
* Return whether the given DB instance is transactional, that is, bound to the current thread by Spring's transaction
* facilities.
*
* @param db
* the DB to check
* @param mongo
* the Mongo instance that the DB was created with (may be <code>null</code>)
* @return whether the DB is transactional
*/
public static boolean isDBTransactional(DB db, Mongo mongo) {
if (mongo == null) {
return false;
}
DbHolder dbHolder = (DbHolder) TransactionSynchronizationManager.getResource(mongo);
return (dbHolder != null && dbHolder.containsDB(db));
}
/**
* Perform actual closing of the Mongo DB object,
* catching and logging any cleanup exceptions thrown.
*
* @param db the DB to close (may be <code>null</code>)
*/
public static void closeDB(DB db) {
if (db != null) {
LOGGER.debug("Closing Mongo DB object");
try {
db.requestDone();
} catch (Throwable ex) {
LOGGER.debug("Unexpected exception on closing Mongo DB object", ex);
}
}
}
/**
* Perform actual closing of the Mongo DB object, catching and logging any cleanup exceptions thrown.
*
* @param db
* the DB to close (may be <code>null</code>)
*/
public static void closeDB(DB db) {
if (db != null) {
LOGGER.debug("Closing Mongo DB object");
try {
db.requestDone();
} catch (Throwable ex) {
LOGGER.debug("Unexpected exception on closing Mongo DB object", ex);
}
}
}
}

View File

@@ -34,51 +34,52 @@ import org.springframework.data.document.UncategorizedDocumentStoreException;
* Simple {@link PersistenceExceptionTranslator} for Mongo. Convert the given runtime exception to an appropriate
* exception from the {@code org.springframework.dao} hierarchy. Return {@literal null} if no translation is
* appropriate: any other exception may have resulted from user code, and should not be translated.
*
* @param ex runtime exception that occurred
*
* @param ex
* runtime exception that occurred
* @author Oliver Gierke
* @return the corresponding DataAccessException instance, or {@literal null} if the exception should not be translated
*/
public class MongoExceptionTranslator implements PersistenceExceptionTranslator {
/*
* (non-Javadoc)
*
* @see org.springframework.dao.support.PersistenceExceptionTranslator#
* translateExceptionIfPossible(java.lang.RuntimeException)
*/
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
/*
* (non-Javadoc)
*
* @see org.springframework.dao.support.PersistenceExceptionTranslator#
* translateExceptionIfPossible(java.lang.RuntimeException)
*/
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
// Check for well-known MongoException subclasses.
// Check for well-known MongoException subclasses.
// All other MongoExceptions
if (ex instanceof DuplicateKey) {
return new DuplicateKeyException(ex.getMessage(), ex);
}
if (ex instanceof Network) {
return new DataAccessResourceFailureException(ex.getMessage(), ex);
}
if (ex instanceof CursorNotFound) {
return new DataAccessResourceFailureException(ex.getMessage(), ex);
}
if (ex instanceof MongoException) {
int code = ((MongoException)ex).getCode();
if (code == 11000 || code == 11001) {
throw new DuplicateKeyException(ex.getMessage(), ex);
} else if (code == 12000 || code == 13440) {
throw new DataAccessResourceFailureException(ex.getMessage(), ex);
} else if (code == 10003 || code == 12001 || code == 12010 || code == 12011 || code == 12012 ) {
throw new InvalidDataAccessApiUsageException(ex.getMessage(), ex);
}
return new UncategorizedDocumentStoreException(ex.getMessage(), ex);
}
if (ex instanceof MongoInternalException) {
return new InvalidDataAccessResourceUsageException(ex.getMessage(), ex);
}
// All other MongoExceptions
if (ex instanceof DuplicateKey) {
return new DuplicateKeyException(ex.getMessage(), ex);
}
if (ex instanceof Network) {
return new DataAccessResourceFailureException(ex.getMessage(), ex);
}
if (ex instanceof CursorNotFound) {
return new DataAccessResourceFailureException(ex.getMessage(), ex);
}
if (ex instanceof MongoException) {
int code = ((MongoException) ex).getCode();
if (code == 11000 || code == 11001) {
throw new DuplicateKeyException(ex.getMessage(), ex);
} else if (code == 12000 || code == 13440) {
throw new DataAccessResourceFailureException(ex.getMessage(), ex);
} else if (code == 10003 || code == 12001 || code == 12010 || code == 12011 || code == 12012) {
throw new InvalidDataAccessApiUsageException(ex.getMessage(), ex);
}
return new UncategorizedDocumentStoreException(ex.getMessage(), ex);
}
if (ex instanceof MongoInternalException) {
return new InvalidDataAccessResourceUsageException(ex.getMessage(), ex);
}
// If we get here, we have an exception that resulted from user code,
// rather than the persistence provider, so we return null to indicate
// that translation should not occur.
return null;
}
// If we get here, we have an exception that resulted from user code,
// rather than the persistence provider, so we return null to indicate
// that translation should not occur.
return null;
}
}

View File

@@ -31,101 +31,100 @@ import org.springframework.util.Assert;
/**
* Convenient factory for configuring MongoDB.
*
*
* @author Thomas Risberg
* @author Graeme Rocher
* @since 1.0
*/
public class MongoFactoryBean implements FactoryBean<Mongo>, InitializingBean, PersistenceExceptionTranslator {
/**
* Logger, available to subclasses.
*/
protected final Log logger = LogFactory.getLog(getClass());
/**
* Logger, available to subclasses.
*/
protected final Log logger = LogFactory.getLog(getClass());
private Mongo mongo;
private MongoOptions mongoOptions;
private String host;
private Integer port;
private List<ServerAddress> replicaSetSeeds;
private List<ServerAddress> replicaPair;
private Mongo mongo;
private MongoOptions mongoOptions;
private String host;
private Integer port;
private List<ServerAddress> replicaSetSeeds;
private List<ServerAddress> replicaPair;
private PersistenceExceptionTranslator exceptionTranslator = new MongoExceptionTranslator();
private PersistenceExceptionTranslator exceptionTranslator = new MongoExceptionTranslator();
public void setMongoOptions(MongoOptions mongoOptions) {
this.mongoOptions = mongoOptions;
}
public void setMongoOptions(MongoOptions mongoOptions) {
this.mongoOptions = mongoOptions;
}
public void setReplicaSetSeeds(List<ServerAddress> replicaSetSeeds) {
this.replicaSetSeeds = replicaSetSeeds;
}
public void setReplicaSetSeeds(List<ServerAddress> replicaSetSeeds) {
this.replicaSetSeeds = replicaSetSeeds;
}
public void setReplicaPair(List<ServerAddress> replicaPair) {
this.replicaPair = replicaPair;
}
public void setReplicaPair(List<ServerAddress> replicaPair) {
this.replicaPair = replicaPair;
}
public void setHost(String host) {
this.host = host;
}
public void setHost(String host) {
this.host = host;
}
public void setPort(int port) {
this.port = port;
}
public void setPort(int port) {
this.port = port;
}
public PersistenceExceptionTranslator getExceptionTranslator() {
return exceptionTranslator;
}
public PersistenceExceptionTranslator getExceptionTranslator() {
return exceptionTranslator;
}
public void setExceptionTranslator(PersistenceExceptionTranslator exceptionTranslator) {
this.exceptionTranslator = exceptionTranslator;
}
public void setExceptionTranslator(
PersistenceExceptionTranslator exceptionTranslator) {
this.exceptionTranslator = exceptionTranslator;
}
public Mongo getObject() throws Exception {
Assert.notNull(mongo, "Mongo must not be null");
return mongo;
}
public Mongo getObject() throws Exception {
Assert.notNull(mongo, "Mongo must not be null");
return mongo;
}
public Class<? extends Mongo> getObjectType() {
return Mongo.class;
}
public Class<? extends Mongo> getObjectType() {
return Mongo.class;
}
public boolean isSingleton() {
return false;
}
public boolean isSingleton() {
return false;
}
public void afterPropertiesSet() throws Exception {
// apply defaults - convenient when used to configure for tests
// in an application context
if (mongo == null) {
public void afterPropertiesSet() throws Exception {
// apply defaults - convenient when used to configure for tests
// in an application context
if (mongo == null) {
if (host == null) {
logger.warn("Property host not specified. Using default configuration");
mongo = new Mongo();
} else {
ServerAddress defaultOptions = new ServerAddress();
if (mongoOptions == null)
mongoOptions = new MongoOptions();
if (replicaPair != null) {
if (replicaPair.size() < 2) {
throw new CannotGetMongoDbConnectionException("A replica pair must have two server entries");
}
mongo = new Mongo(replicaPair.get(0), replicaPair.get(1), mongoOptions);
} else if (replicaSetSeeds != null) {
mongo = new Mongo(replicaSetSeeds, mongoOptions);
} else {
String mongoHost = host != null ? host : defaultOptions.getHost();
if (port != null) {
mongo = new Mongo(new ServerAddress(mongoHost, port), mongoOptions);
} else {
mongo = new Mongo(mongoHost, mongoOptions);
}
}
}
}
}
if (host == null) {
logger.warn("Property host not specified. Using default configuration");
mongo = new Mongo();
} else {
ServerAddress defaultOptions = new ServerAddress();
if (mongoOptions == null) mongoOptions = new MongoOptions();
if (replicaPair != null) {
if (replicaPair.size() < 2) {
throw new CannotGetMongoDbConnectionException("A replica pair must have two server entries");
}
mongo = new Mongo(replicaPair.get(0), replicaPair.get(1), mongoOptions);
} else if (replicaSetSeeds != null) {
mongo = new Mongo(replicaSetSeeds, mongoOptions);
} else {
String mongoHost = host != null ? host : defaultOptions.getHost();
if (port != null) {
mongo = new Mongo(new ServerAddress(mongoHost, port), mongoOptions);
} else {
mongo = new Mongo(mongoHost, mongoOptions);
}
}
}
}
}
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
return exceptionTranslator.translateExceptionIfPossible(ex);
}
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
return exceptionTranslator.translateExceptionIfPossible(ex);
}
}

View File

@@ -28,495 +28,537 @@ import org.springframework.data.document.mongodb.query.Query;
import org.springframework.data.document.mongodb.query.Update;
/**
* Interface that specifies a basic set of MongoDB operations. Implemented by {@link MongoTemplate}.
* Not often used but a useful option for extensibility and testability (as it can be easily mocked, stubbed, or be
* the target of a JDK proxy).
*
* Interface that specifies a basic set of MongoDB operations. Implemented by {@link MongoTemplate}. Not often used but
* a useful option for extensibility and testability (as it can be easily mocked, stubbed, or be the target of a JDK
* proxy).
*
* @author Thomas Risberg
* @author Mark Pollack
* @author Oliver Gierke
*/
public interface MongoOperations {
/**
* The collection name used for the specified class by this template.
*
* @return
*/
String getCollectionName(Class<?> clazz);
/**
* The collection name used for the specified class by this template.
*
* @return
*/
String getCollectionName(Class<?> clazz);
/**
* Execute the a MongoDB command expressed as a JSON string. This will call the method
* JSON.parse that is part of the MongoDB driver to convert the JSON string to a DBObject.
* Any errors that result from executing this command will be converted into Spring's DAO
* exception hierarchy.
*
* @param jsonCommand a MongoDB command expressed as a JSON string.
*/
CommandResult executeCommand(String jsonCommand);
/**
* Execute the a MongoDB command expressed as a JSON string. This will call the method JSON.parse that is part of the
* MongoDB driver to convert the JSON string to a DBObject. Any errors that result from executing this command will be
* converted into Spring's DAO exception hierarchy.
*
* @param jsonCommand
* a MongoDB command expressed as a JSON string.
*/
CommandResult executeCommand(String jsonCommand);
/**
* Execute a MongoDB command. Any errors that result from executing this command will be converted
* into Spring's DAO exception hierarchy.
*
* @param command a MongoDB command
*/
CommandResult executeCommand(DBObject command);
/**
* Execute a MongoDB command. Any errors that result from executing this command will be converted into Spring's DAO
* exception hierarchy.
*
* @param command
* a MongoDB command
*/
CommandResult executeCommand(DBObject command);
/**
* Executes a {@link DbCallback} translating any exceptions as necessary.
* <p/>
* Allows for returning a result object, that is a domain object or a collection of domain objects.
*
* @param <T> return type
* @param action callback object that specifies the MongoDB actions to perform on the passed in DB instance.
* @return a result object returned by the action or <tt>null</tt>
*/
<T> T execute(DbCallback<T> action);
/**
* Executes a {@link DbCallback} translating any exceptions as necessary.
* <p/>
* Allows for returning a result object, that is a domain object or a collection of domain objects.
*
* @param <T>
* return type
* @param action
* callback object that specifies the MongoDB actions to perform on the passed in DB instance.
* @return a result object returned by the action or <tt>null</tt>
*/
<T> T execute(DbCallback<T> action);
/**
* Executes the given {@link CollectionCallback} on the entity collection of the specified class.
* <p/>
* Allows for returning a result object, that is a domain object or a collection of domain objects.
*
* @param entityClass class that determines the collection to use
* @param <T> return type
* @param action callback object that specifies the MongoDB action
* @return a result object returned by the action or <tt>null</tt>
*/
<T> T execute(Class<?> entityClass, CollectionCallback<T> action);
/**
* Executes the given {@link CollectionCallback} on the entity collection of the specified class.
* <p/>
* Allows for returning a result object, that is a domain object or a collection of domain objects.
*
* @param entityClass
* class that determines the collection to use
* @param <T>
* return type
* @param action
* callback object that specifies the MongoDB action
* @return a result object returned by the action or <tt>null</tt>
*/
<T> T execute(Class<?> entityClass, CollectionCallback<T> action);
/**
* Executes the given {@link CollectionCallback} on the collection of the given name.
* <p/>
* Allows for returning a result object, that is a domain object or a collection of domain objects.
*
* @param <T> return type
* @param collectionName the name of the collection that specifies which DBCollection instance will be passed into
* @param action callback object that specifies the MongoDB action
* the callback action.
* @return a result object returned by the action or <tt>null</tt>
*/
<T> T execute(String collectionName, CollectionCallback<T> action);
/**
* Executes the given {@link CollectionCallback} on the collection of the given name.
* <p/>
* Allows for returning a result object, that is a domain object or a collection of domain objects.
*
* @param <T>
* return type
* @param collectionName
* the name of the collection that specifies which DBCollection instance will be passed into
* @param action
* callback object that specifies the MongoDB action the callback action.
* @return a result object returned by the action or <tt>null</tt>
*/
<T> T execute(String collectionName, CollectionCallback<T> action);
/**
* Executes the given {@link DbCallback} within the same connection to the database so as to ensure
* consistency in a write heavy environment where you may read the data that you wrote. See the
* comments on {@see <a href=http://www.mongodb.org/display/DOCS/Java+Driver+Concurrency>Java Driver Concurrency</a>}
* <p/>
* Allows for returning a result object, that is a domain object or a collection of domain objects.
*
* @param <T> return type
* @param action callback that specified the MongoDB actions to perform on the DB instance
* @return a result object returned by the action or <tt>null</tt>
*/
<T> T executeInSession(DbCallback<T> action);
/**
* Executes the given {@link DbCallback} within the same connection to the database so as to ensure consistency in a
* write heavy environment where you may read the data that you wrote. See the comments on {@see <a
* href=http://www.mongodb.org/display/DOCS/Java+Driver+Concurrency>Java Driver Concurrency</a>}
* <p/>
* Allows for returning a result object, that is a domain object or a collection of domain objects.
*
* @param <T>
* return type
* @param action
* callback that specified the MongoDB actions to perform on the DB instance
* @return a result object returned by the action or <tt>null</tt>
*/
<T> T executeInSession(DbCallback<T> action);
/**
* Create an uncapped collection with the provided name.
*
* @param collectionName name of the collection
* @return the created collection
*/
DBCollection createCollection(String collectionName);
/**
* Create an uncapped collection with the provided name.
*
* @param collectionName
* name of the collection
* @return the created collection
*/
DBCollection createCollection(String collectionName);
/**
* Create a collect with the provided name and options.
*
* @param collectionName name of the collection
* @param collectionOptions options to use when creating the collection.
* @return the created collection
*/
DBCollection createCollection(String collectionName, CollectionOptions collectionOptions);
/**
* Create a collect with the provided name and options.
*
* @param collectionName
* name of the collection
* @param collectionOptions
* options to use when creating the collection.
* @return the created collection
*/
DBCollection createCollection(String collectionName, CollectionOptions collectionOptions);
/**
* A set of collection names.
*
* @return list of collection names
*/
Set<String> getCollectionNames();
/**
* A set of collection names.
*
* @return list of collection names
*/
Set<String> getCollectionNames();
/**
* Get a collection by name, creating it if it doesn't exist.
* <p/>
* Translate any exceptions as necessary.
*
* @param collectionName name of the collection
* @return an existing collection or a newly created one.
*/
DBCollection getCollection(String collectionName);
/**
* Get a collection by name, creating it if it doesn't exist.
* <p/>
* Translate any exceptions as necessary.
*
* @param collectionName
* name of the collection
* @return an existing collection or a newly created one.
*/
DBCollection getCollection(String collectionName);
/**
* Check to see if a collection with a given name exists.
* <p/>
* Translate any exceptions as necessary.
*
* @param collectionName name of the collection
* @return true if a collection with the given name is found, false otherwise.
*/
boolean collectionExists(String collectionName);
/**
* Check to see if a collection with a given name exists.
* <p/>
* Translate any exceptions as necessary.
*
* @param collectionName
* name of the collection
* @return true if a collection with the given name is found, false otherwise.
*/
boolean collectionExists(String collectionName);
/**
* Drop the collection with the given name.
* <p/>
* Translate any exceptions as necessary.
*
* @param collectionName name of the collection to drop/delete.
*/
void dropCollection(String collectionName);
/**
* Drop the collection with the given name.
* <p/>
* Translate any exceptions as necessary.
*
* @param collectionName
* name of the collection to drop/delete.
*/
void dropCollection(String collectionName);
/**
* Query for a list of objects of type T from the default collection.
* <p/>
* The object is converted from the MongoDB native representation using an instance of
* {@see MongoConverter}. Unless configured otherwise, an
* instance of SimpleMongoConverter will be used.
* <p/>
* If your collection does not contain a homogeneous collection of types, this operation will not be an efficient
* way to map objects since the test for class type is done in the client and not on the server.
*
* @param targetClass the parameterized type of the returned list
* @return the converted collection
*/
<T> List<T> getCollection(Class<T> targetClass);
/**
* Query for a list of objects of type T from the default collection.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* If your collection does not contain a homogeneous collection of types, this operation will not be an efficient way
* to map objects since the test for class type is done in the client and not on the server.
*
* @param targetClass
* the parameterized type of the returned list
* @return the converted collection
*/
<T> List<T> getCollection(Class<T> targetClass);
/**
* Query for a list of objects of type T from the specified collection.
* <p/>
* The object is converted from the MongoDB native representation using an instance of
* {@see MongoConverter}. Unless configured otherwise, an
* instance of SimpleMongoConverter will be used.
* <p/>
* If your collection does not contain a homogeneous collection of types, this operation will not be an efficient
* way to map objects since the test for class type is done in the client and not on the server.
*
* @param collectionName name of the collection to retrieve the objects from
* @param targetClass the parameterized type of the returned list.
* @return the converted collection
*/
<T> List<T> getCollection(String collectionName, Class<T> targetClass);
/**
* Query for a list of objects of type T from the specified collection.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* If your collection does not contain a homogeneous collection of types, this operation will not be an efficient way
* to map objects since the test for class type is done in the client and not on the server.
*
* @param collectionName
* name of the collection to retrieve the objects from
* @param targetClass
* the parameterized type of the returned list.
* @return the converted collection
*/
<T> List<T> getCollection(String collectionName, Class<T> targetClass);
/**
* Ensure that an index for the provided {@link IndexDefinition} exists for the default collection.
* If not it will be created.
*
* @param entityClass class that determines the collection to use
* @param indexDefinition
*/
void ensureIndex(Class<?> entityClass, IndexDefinition indexDefinition);
/**
* Ensure that an index for the provided {@link IndexDefinition} exists for the default collection. If not it will be
* created.
*
* @param entityClass
* class that determines the collection to use
* @param indexDefinition
*/
void ensureIndex(Class<?> entityClass, IndexDefinition indexDefinition);
/**
* Ensure that an index for the provided {@link IndexDefinition} exists. If not it will be
* created.
*
* @param collectionName
* @param index
*/
void ensureIndex(String collectionName, IndexDefinition indexDefinition);
/**
* Ensure that an index for the provided {@link IndexDefinition} exists. If not it will be created.
*
* @param collectionName
* @param index
*/
void ensureIndex(String collectionName, IndexDefinition indexDefinition);
/**
* Map the results of an ad-hoc query on the default MongoDB collection to a single instance of an object
* of the specified type.
* <p/>
* The object is converted from the MongoDB native representation using an instance of
* {@see MongoConverter}. Unless configured otherwise, an
* instance of SimpleMongoConverter will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param query the query class that specifies the criteria used to find a record and also an optional fields specification
* @param targetClass the parameterized type of the returned list.
* @return the converted object
*/
<T> T findOne(Query query, Class<T> targetClass);
/**
* Map the results of an ad-hoc query on the default MongoDB collection to a single instance of an object of the
* specified type.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param query
* the query class that specifies the criteria used to find a record and also an optional fields
* specification
* @param targetClass
* the parameterized type of the returned list.
* @return the converted object
*/
<T> T findOne(Query query, Class<T> targetClass);
/**
* Map the results of an ad-hoc query on the specified collection to a single instance of an object
* of the specified type.
* <p/>
* The object is converted from the MongoDB native representation using an instance of
* {@see MongoConverter}. Unless configured otherwise, an
* instance of SimpleMongoConverter will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param collectionName name of the collection to retrieve the objects from
* @param query the query class that specifies the criteria used to find a record and also an optional fields specification
* @param targetClass the parameterized type of the returned list.
* @return the converted object
*/
<T> T findOne(String collectionName, Query query,
Class<T> targetClass);
/**
* Map the results of an ad-hoc query on the specified collection to a single instance of an object of the specified
* type.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param collectionName
* name of the collection to retrieve the objects from
* @param query
* the query class that specifies the criteria used to find a record and also an optional fields
* specification
* @param targetClass
* the parameterized type of the returned list.
* @return the converted object
*/
<T> T findOne(String collectionName, Query query, Class<T> targetClass);
/**
* Map the results of an ad-hoc query on the default MongoDB collection to a List of the specified type.
* <p/>
* The object is converted from the MongoDB native representation using an instance of
* {@see MongoConverter}. Unless configured otherwise, an
* instance of SimpleMongoConverter will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param query the query class that specifies the criteria used to find a record and also an optional fields specification
* @param targetClass the parameterized type of the returned list.
* @return the List of converted objects
*/
<T> List<T> find(Query query, Class<T> targetClass);
/**
* Map the results of an ad-hoc query on the default MongoDB collection to a List of the specified type.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param query
* the query class that specifies the criteria used to find a record and also an optional fields
* specification
* @param targetClass
* the parameterized type of the returned list.
* @return the List of converted objects
*/
<T> List<T> find(Query query, Class<T> targetClass);
/**
* Map the results of an ad-hoc query on the specified collection to a List of the specified type.
* <p/>
* The object is converted from the MongoDB native representation using an instance of
* {@see MongoConverter}. Unless configured otherwise, an
* instance of SimpleMongoConverter will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param collectionName name of the collection to retrieve the objects from
* @param query the query class that specifies the criteria used to find a record and also an optional fields specification
* @param targetClass the parameterized type of the returned list.
* @return the List of converted objects
*/
<T> List<T> find(String collectionName, Query query,
Class<T> targetClass);
/**
* Map the results of an ad-hoc query on the specified collection to a List of the specified type.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param collectionName
* name of the collection to retrieve the objects from
* @param query
* the query class that specifies the criteria used to find a record and also an optional fields
* specification
* @param targetClass
* the parameterized type of the returned list.
* @return the List of converted objects
*/
<T> List<T> find(String collectionName, Query query, Class<T> targetClass);
/**
* Map the results of an ad-hoc query on the specified collection to a List of the specified type.
* <p/>
* The object is converted from the MongoDB native representation using an instance of
* {@see MongoConverter}. Unless configured otherwise, an
* instance of SimpleMongoConverter will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param collectionName name of the collection to retrieve the objects from
* @param query the query class that specifies the criteria used to find a record and also an optional fields specification
* @param targetClass the parameterized type of the returned list.
* @param preparer allows for customization of the DBCursor used when iterating over the result set,
* (apply limits, skips and so on).
* @return the List of converted objects.
*/
<T> List<T> find(String collectionName, Query query, Class<T> targetClass, CursorPreparer preparer);
/**
* Map the results of an ad-hoc query on the specified collection to a List of the specified type.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param collectionName
* name of the collection to retrieve the objects from
* @param query
* the query class that specifies the criteria used to find a record and also an optional fields
* specification
* @param targetClass
* the parameterized type of the returned list.
* @param preparer
* allows for customization of the DBCursor used when iterating over the result set, (apply limits, skips and
* so on).
* @return the List of converted objects.
*/
<T> List<T> find(String collectionName, Query query, Class<T> targetClass, CursorPreparer preparer);
/**
* Map the results of an ad-hoc query on the default MongoDB collection to a single instance of an object
* of the specified type. The first document that matches the query is returned and also removed from the
* collection in the database.
* <p/>
* The object is converted from the MongoDB native representation using an instance of
* {@see MongoConverter}. Unless configured otherwise, an
* instance of SimpleMongoConverter will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param query the query class that specifies the criteria used to find a record and also an optional fields specification
* @param targetClass the parameterized type of the returned list.
* @return the converted object
*/
<T> T findAndRemove(Query query, Class<T> targetClass);
/**
* Map the results of an ad-hoc query on the default MongoDB collection to a single instance of an object of the
* specified type. The first document that matches the query is returned and also removed from the collection in the
* database.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param query
* the query class that specifies the criteria used to find a record and also an optional fields
* specification
* @param targetClass
* the parameterized type of the returned list.
* @return the converted object
*/
<T> T findAndRemove(Query query, Class<T> targetClass);
/**
* Map the results of an ad-hoc query on the specified collection to a single instance of an object
* of the specified type. The first document that matches the query is returned and also removed from the
* collection in the database.
* <p/>
* The object is converted from the MongoDB native representation using an instance of
* {@see MongoConverter}. Unless configured otherwise, an
* instance of SimpleMongoConverter will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param collectionName name of the collection to retrieve the objects from
* @param query the query class that specifies the criteria used to find a record and also an optional fields specification
* @param targetClass the parameterized type of the returned list.
* @return the converted object
*/
<T> T findAndRemove(String collectionName, Query query,
Class<T> targetClass);
/**
* Map the results of an ad-hoc query on the specified collection to a single instance of an object of the specified
* type. The first document that matches the query is returned and also removed from the collection in the database.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param collectionName
* name of the collection to retrieve the objects from
* @param query
* the query class that specifies the criteria used to find a record and also an optional fields
* specification
* @param targetClass
* the parameterized type of the returned list.
* @return the converted object
*/
<T> T findAndRemove(String collectionName, Query query, Class<T> targetClass);
/**
* Insert the object into the default collection.
* <p/>
* The object is converted to the MongoDB native representation using an instance of
* {@see MongoConverter}. Unless configured otherwise, an
* instance of SimpleMongoConverter will be used.
* <p/>
* If you object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property
* is a String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from
* ObjectId to your property type will be handled by Spring's BeanWrapper class that leverages Spring 3.0's
* new Type Conversion API.
* See <a href="http://static.springsource.org/spring/docs/3.0.x/reference/validation.html#core-convert">Spring 3 Type Conversion"</a>
* for more details.
* <p/>
* <p/>
* Insert is used to initially store the object into the database.
* To update an existing object use the save method.
*
* @param objectToSave the object to store in the collection.
*/
void insert(Object objectToSave);
/**
* Insert the object into the default collection.
* <p/>
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* If you object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
* property type will be handled by Spring's BeanWrapper class that leverages Spring 3.0's new Type Conversion API.
* See <a href="http://static.springsource.org/spring/docs/3.0.x/reference/validation.html#core-convert">Spring 3 Type
* Conversion"</a> for more details.
* <p/>
* <p/>
* Insert is used to initially store the object into the database. To update an existing object use the save method.
*
* @param objectToSave
* the object to store in the collection.
*/
void insert(Object objectToSave);
/**
* Insert the object into the specified collection.
* <p/>
* The object is converted to the MongoDB native representation using an instance of
* {@see MongoConverter}. Unless configured otherwise, an
* instance of SimpleMongoConverter will be used.
* <p/>
* Insert is used to initially store the object into the
* database. To update an existing object use the save method.
*
* @param collectionName name of the collection to store the object in
* @param objectToSave the object to store in the collection
*/
void insert(String collectionName, Object objectToSave);
/**
* Insert the object into the specified collection.
* <p/>
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* Insert is used to initially store the object into the database. To update an existing object use the save method.
*
* @param collectionName
* name of the collection to store the object in
* @param objectToSave
* the object to store in the collection
*/
void insert(String collectionName, Object objectToSave);
/**
* Insert a list of objects into the default collection in a single batch write to the database.
*
* @param listToSave the list of objects to save.
*/
void insertList(List<? extends Object> listToSave);
/**
* Insert a list of objects into the default collection in a single batch write to the database.
*
* @param listToSave
* the list of objects to save.
*/
void insertList(List<? extends Object> listToSave);
/**
* Insert a list of objects into the specified collection in a single batch write to the database.
*
* @param collectionName name of the collection to store the object in
* @param listToSave the list of objects to save.
*/
void insertList(String collectionName, List<? extends Object> listToSave);
/**
* Insert a list of objects into the specified collection in a single batch write to the database.
*
* @param collectionName
* name of the collection to store the object in
* @param listToSave
* the list of objects to save.
*/
void insertList(String collectionName, List<? extends Object> listToSave);
/**
* Save the object to the default collection. This will perform an insert if the object is not already
* present, that is an 'upsert'.
* <p/>
* The object is converted to the MongoDB native representation using an instance of
* {@see MongoConverter}. Unless configured otherwise, an
* instance of SimpleMongoConverter will be used.
* <p/>
* If you object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property
* is a String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from
* ObjectId to your property type will be handled by Spring's BeanWrapper class that leverages Spring 3.0's
* new Type Conversion API.
* See <a href="http://static.springsource.org/spring/docs/3.0.x/reference/validation.html#core-convert">Spring 3 Type Conversion"</a>
* for more details.
*
* @param objectToSave the object to store in the collection
*/
void save(Object objectToSave);
/**
* Save the object to the default collection. This will perform an insert if the object is not already present, that
* is an 'upsert'.
* <p/>
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* If you object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
* property type will be handled by Spring's BeanWrapper class that leverages Spring 3.0's new Type Conversion API.
* See <a href="http://static.springsource.org/spring/docs/3.0.x/reference/validation.html#core-convert">Spring 3 Type
* Conversion"</a> for more details.
*
* @param objectToSave
* the object to store in the collection
*/
void save(Object objectToSave);
/**
* Save the object to the specified collection. This will perform an insert if the object is not already
* present, that is an 'upsert'.
* <p/>
* The object is converted to the MongoDB native representation using an instance of
* {@see MongoConverter}. Unless configured otherwise, an
* instance of SimpleMongoConverter will be used.
* <p/>
* If you object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property
* is a String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from
* ObjectId to your property type will be handled by Spring's BeanWrapper class that leverages Spring 3.0's
* new Type Cobnversion API.
* See <a href="http://static.springsource.org/spring/docs/3.0.x/reference/validation.html#core-convert">Spring 3 Type Conversion"</a>
* for more details.
*
* @param collectionName name of the collection to store the object in
* @param objectToSave the object to store in the collection
*/
void save(String collectionName, Object objectToSave);
/**
* Save the object to the specified collection. This will perform an insert if the object is not already present, that
* is an 'upsert'.
* <p/>
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* If you object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
* property type will be handled by Spring's BeanWrapper class that leverages Spring 3.0's new Type Cobnversion API.
* See <a href="http://static.springsource.org/spring/docs/3.0.x/reference/validation.html#core-convert">Spring 3 Type
* Conversion"</a> for more details.
*
* @param collectionName
* name of the collection to store the object in
* @param objectToSave
* the object to store in the collection
*/
void save(String collectionName, Object objectToSave);
/**
* Updates the first object that is found in the default collection that matches the query document
* with the provided updated document.
*
* @param entityClass class that determines the collection to use
* @param queryDoc the query document that specifies the criteria used to select a record to be updated
* @param updateDoc the update document that contains the updated object or $ operators to manipulate the
* existing object.
*/
WriteResult updateFirst(Class<?> entityClass, Query query, Update update);
/**
* Updates the first object that is found in the default collection that matches the query document with the provided
* updated document.
*
* @param entityClass
* class that determines the collection to use
* @param queryDoc
* the query document that specifies the criteria used to select a record to be updated
* @param updateDoc
* the update document that contains the updated object or $ operators to manipulate the existing object.
*/
WriteResult updateFirst(Class<?> entityClass, Query query, Update update);
/**
* Updates the first object that is found in the specified collection that matches the query document criteria
* with the provided updated document.
*
* @param collectionName name of the collection to update the object in
* @param queryDoc the query document that specifies the criteria used to select a record to be updated
* @param updateDoc the update document that contains the updated object or $ operators to manipulate the
* existing object.
*/
WriteResult updateFirst(String collectionName, Query query,
Update update);
/**
* Updates the first object that is found in the specified collection that matches the query document criteria with
* the provided updated document.
*
* @param collectionName
* name of the collection to update the object in
* @param queryDoc
* the query document that specifies the criteria used to select a record to be updated
* @param updateDoc
* the update document that contains the updated object or $ operators to manipulate the existing object.
*/
WriteResult updateFirst(String collectionName, Query query, Update update);
/**
* Updates all objects that are found in the default collection that matches the query document criteria
* with the provided updated document.
*
* @param entityClass class that determines the collection to use
* @param queryDoc the query document that specifies the criteria used to select a record to be updated
* @param updateDoc the update document that contains the updated object or $ operators to manipulate the
* existing object.
*/
WriteResult updateMulti(Class<?> entityClass, Query query, Update update);
/**
* Updates all objects that are found in the default collection that matches the query document criteria with the
* provided updated document.
*
* @param entityClass
* class that determines the collection to use
* @param queryDoc
* the query document that specifies the criteria used to select a record to be updated
* @param updateDoc
* the update document that contains the updated object or $ operators to manipulate the existing object.
*/
WriteResult updateMulti(Class<?> entityClass, Query query, Update update);
/**
* Updates all objects that are found in the specified collection that matches the query document criteria
* with the provided updated document.
*
* @param collectionName name of the collection to update the object in
* @param queryDoc the query document that specifies the criteria used to select a record to be updated
* @param updateDoc the update document that contains the updated object or $ operators to manipulate the
* existing object.
*/
WriteResult updateMulti(String collectionName, Query query,
Update update);
/**
* Updates all objects that are found in the specified collection that matches the query document criteria with the
* provided updated document.
*
* @param collectionName
* name of the collection to update the object in
* @param queryDoc
* the query document that specifies the criteria used to select a record to be updated
* @param updateDoc
* the update document that contains the updated object or $ operators to manipulate the existing object.
*/
WriteResult updateMulti(String collectionName, Query query, Update update);
/**
* Remove the given object from the collection by Id
* @param object
*/
void remove(Object object);
/**
* Remove all documents from the default collection that match the provided query document criteria.
*
* @param queryDoc the query document that specifies the criteria used to remove a record
*/
void remove(Query query);
/**
* Remove all documents from the default collection that match the provided query document criteria. The
* Class parameter is used to help convert the Id of the object if it is present in the query.
* @param <T>
* @param query
* @param targetClass
*/
<T> void remove(Query query, Class<T> targetClass);
/**
* Remove all documents from the specified collection that match the provided query document criteria.
*
* @param collectionName name of the collection where the objects will removed
* @param queryDoc the query document that specifies the criteria used to remove a record
*/
void remove(String collectionName, Query query);
/**
* Remove all documents from the specified collection that match the provided query document criteria.
* The Class parameter is used to help convert the Id of the object if it is present in the query.
* @param collectionName
* @param query
* @param targetClass
*/
<T> void remove(String collectionName, Query query, Class<T> targetClass);
/**
* Remove the given object from the collection by Id
*
* @param object
*/
void remove(Object object);
/**
* Remove all documents from the default collection that match the provided query document criteria.
*
* @param queryDoc
* the query document that specifies the criteria used to remove a record
*/
void remove(Query query);
/**
* Remove all documents from the default collection that match the provided query document criteria. The Class
* parameter is used to help convert the Id of the object if it is present in the query.
*
* @param <T>
* @param query
* @param targetClass
*/
<T> void remove(Query query, Class<T> targetClass);
/**
* Remove all documents from the specified collection that match the provided query document criteria.
*
* @param collectionName
* name of the collection where the objects will removed
* @param queryDoc
* the query document that specifies the criteria used to remove a record
*/
void remove(String collectionName, Query query);
/**
* Remove all documents from the specified collection that match the provided query document criteria. The Class
* parameter is used to help convert the Id of the object if it is present in the query.
*
* @param collectionName
* @param query
* @param targetClass
*/
<T> void remove(String collectionName, Query query, Class<T> targetClass);
}

View File

@@ -21,114 +21,108 @@ import org.springframework.beans.factory.InitializingBean;
/**
* A factory bean for consruction a MongoOptions instance
*
*
* @author Graeme Rocher
*/
public class MongoOptionsFactoryBean implements FactoryBean<MongoOptions>, InitializingBean {
private static final MongoOptions MONGO_OPTIONS = new MongoOptions();
/**
* number of connections allowed per host
* will block if run out
*/
private int connectionsPerHost = MONGO_OPTIONS.connectionsPerHost;
private static final MongoOptions MONGO_OPTIONS = new MongoOptions();
/**
* number of connections allowed per host will block if run out
*/
private int connectionsPerHost = MONGO_OPTIONS.connectionsPerHost;
/**
* multiplier for connectionsPerHost for # of threads that can block
* if connectionsPerHost is 10, and threadsAllowedToBlockForConnectionMultiplier is 5,
* then 50 threads can block
* more than that and an exception will be throw
*/
private int threadsAllowedToBlockForConnectionMultiplier = MONGO_OPTIONS.threadsAllowedToBlockForConnectionMultiplier;
/**
* multiplier for connectionsPerHost for # of threads that can block if connectionsPerHost is 10, and
* threadsAllowedToBlockForConnectionMultiplier is 5, then 50 threads can block more than that and an exception will
* be throw
*/
private int threadsAllowedToBlockForConnectionMultiplier = MONGO_OPTIONS.threadsAllowedToBlockForConnectionMultiplier;
/**
* max wait time of a blocking thread for a connection
*/
private int maxWaitTime = MONGO_OPTIONS.maxWaitTime;
/**
* max wait time of a blocking thread for a connection
*/
private int maxWaitTime = MONGO_OPTIONS.maxWaitTime;
/**
* connect timeout in milliseconds. 0 is default and infinite
*/
private int connectTimeout = MONGO_OPTIONS.connectTimeout;
/**
* connect timeout in milliseconds. 0 is default and infinite
*/
private int connectTimeout = MONGO_OPTIONS.connectTimeout;
/**
* socket timeout. 0 is default and infinite
*/
private int socketTimeout = MONGO_OPTIONS.socketTimeout;
/**
* socket timeout. 0 is default and infinite
*/
private int socketTimeout = MONGO_OPTIONS.socketTimeout;
/**
* this controls whether or not on a connect, the system retries automatically
*/
private boolean autoConnectRetry = MONGO_OPTIONS.autoConnectRetry;
/**
* this controls whether or not on a connect, the system retries automatically
*/
private boolean autoConnectRetry = MONGO_OPTIONS.autoConnectRetry;
/**
* number of connections allowed per host will block if run out
*/
public void setConnectionsPerHost(int connectionsPerHost) {
this.connectionsPerHost = connectionsPerHost;
}
/**
* number of connections allowed per host
* will block if run out
*/
public void setConnectionsPerHost(int connectionsPerHost) {
this.connectionsPerHost = connectionsPerHost;
}
/**
* multiplier for connectionsPerHost for # of threads that can block if connectionsPerHost is 10, and
* threadsAllowedToBlockForConnectionMultiplier is 5, then 50 threads can block more than that and an exception will
* be throw
*/
public void setThreadsAllowedToBlockForConnectionMultiplier(int threadsAllowedToBlockForConnectionMultiplier) {
this.threadsAllowedToBlockForConnectionMultiplier = threadsAllowedToBlockForConnectionMultiplier;
}
/**
* multiplier for connectionsPerHost for # of threads that can block
* if connectionsPerHost is 10, and threadsAllowedToBlockForConnectionMultiplier is 5,
* then 50 threads can block
* more than that and an exception will be throw
*/
public void setThreadsAllowedToBlockForConnectionMultiplier(
int threadsAllowedToBlockForConnectionMultiplier) {
this.threadsAllowedToBlockForConnectionMultiplier = threadsAllowedToBlockForConnectionMultiplier;
}
/**
* max wait time of a blocking thread for a connection
*/
public void setMaxWaitTime(int maxWaitTime) {
this.maxWaitTime = maxWaitTime;
}
/**
* max wait time of a blocking thread for a connection
*/
public void setMaxWaitTime(int maxWaitTime) {
this.maxWaitTime = maxWaitTime;
}
/**
* connect timeout in milliseconds. 0 is default and infinite
*/
public void setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
}
/**
* connect timeout in milliseconds. 0 is default and infinite
*/
public void setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
}
/**
* socket timeout. 0 is default and infinite
*/
public void setSocketTimeout(int socketTimeout) {
this.socketTimeout = socketTimeout;
}
/**
* socket timeout. 0 is default and infinite
*/
public void setSocketTimeout(int socketTimeout) {
this.socketTimeout = socketTimeout;
}
/**
* this controls whether or not on a connect, the system retries automatically
*/
public void setAutoConnectRetry(boolean autoConnectRetry) {
this.autoConnectRetry = autoConnectRetry;
}
/**
* this controls whether or not on a connect, the system retries automatically
*/
public void setAutoConnectRetry(boolean autoConnectRetry) {
this.autoConnectRetry = autoConnectRetry;
}
public void afterPropertiesSet() {
MONGO_OPTIONS.connectionsPerHost = connectionsPerHost;
MONGO_OPTIONS.threadsAllowedToBlockForConnectionMultiplier = threadsAllowedToBlockForConnectionMultiplier;
MONGO_OPTIONS.maxWaitTime = maxWaitTime;
MONGO_OPTIONS.connectTimeout = connectTimeout;
MONGO_OPTIONS.socketTimeout = socketTimeout;
MONGO_OPTIONS.autoConnectRetry = autoConnectRetry;
public void afterPropertiesSet() {
MONGO_OPTIONS.connectionsPerHost = connectionsPerHost;
MONGO_OPTIONS.threadsAllowedToBlockForConnectionMultiplier = threadsAllowedToBlockForConnectionMultiplier;
MONGO_OPTIONS.maxWaitTime = maxWaitTime;
MONGO_OPTIONS.connectTimeout = connectTimeout;
MONGO_OPTIONS.socketTimeout = socketTimeout;
MONGO_OPTIONS.autoConnectRetry = autoConnectRetry;
}
}
public MongoOptions getObject() {
return MONGO_OPTIONS;
}
public MongoOptions getObject() {
return MONGO_OPTIONS;
}
public Class<?> getObjectType() {
return MongoOptions.class;
}
public Class<?> getObjectType() {
return MongoOptions.class;
}
public boolean isSingleton() {
return true;
}
public boolean isSingleton() {
return true;
}
}

View File

@@ -29,217 +29,216 @@ import org.springframework.util.ReflectionUtils;
/**
* An iterable of {@link MongoPropertyDescriptor}s that allows dedicated access to the {@link MongoPropertyDescriptor}
* that captures the id-property.
*
*
* @author Oliver Gierke
*/
public class MongoPropertyDescriptors implements Iterable<MongoPropertyDescriptors.MongoPropertyDescriptor> {
private final Collection<MongoPropertyDescriptors.MongoPropertyDescriptor> descriptors;
private final MongoPropertyDescriptors.MongoPropertyDescriptor idDescriptor;
private final Collection<MongoPropertyDescriptors.MongoPropertyDescriptor> descriptors;
private final MongoPropertyDescriptors.MongoPropertyDescriptor idDescriptor;
/**
* Creates the {@link MongoPropertyDescriptors} for the given type.
*
* @param type
*/
public MongoPropertyDescriptors(Class<?> type) {
/**
* Creates the {@link MongoPropertyDescriptors} for the given type.
*
* @param type
*/
public MongoPropertyDescriptors(Class<?> type) {
Assert.notNull(type);
Set<MongoPropertyDescriptors.MongoPropertyDescriptor> descriptors = new HashSet<MongoPropertyDescriptors.MongoPropertyDescriptor>();
MongoPropertyDescriptors.MongoPropertyDescriptor idDesciptor = null;
Assert.notNull(type);
Set<MongoPropertyDescriptors.MongoPropertyDescriptor> descriptors = new HashSet<MongoPropertyDescriptors.MongoPropertyDescriptor>();
MongoPropertyDescriptors.MongoPropertyDescriptor idDesciptor = null;
for (PropertyDescriptor candidates : BeanUtils.getPropertyDescriptors(type)) {
MongoPropertyDescriptor descriptor = new MongoPropertyDescriptors.MongoPropertyDescriptor(candidates, type);
descriptors.add(descriptor);
if (descriptor.isIdProperty()) {
idDesciptor = descriptor;
}
}
for (PropertyDescriptor candidates : BeanUtils.getPropertyDescriptors(type)) {
MongoPropertyDescriptor descriptor = new MongoPropertyDescriptors.MongoPropertyDescriptor(candidates, type);
descriptors.add(descriptor);
if (descriptor.isIdProperty()) {
idDesciptor = descriptor;
}
}
this.descriptors = Collections.unmodifiableSet(descriptors);
this.idDescriptor = idDesciptor;
}
this.descriptors = Collections.unmodifiableSet(descriptors);
this.idDescriptor = idDesciptor;
}
/**
* Returns the {@link MongoPropertyDescriptor} for the id property.
*
* @return the idDescriptor
*/
public MongoPropertyDescriptors.MongoPropertyDescriptor getIdDescriptor() {
return idDescriptor;
}
/**
* Returns the {@link MongoPropertyDescriptor} for the id property.
*
* @return the idDescriptor
*/
public MongoPropertyDescriptors.MongoPropertyDescriptor getIdDescriptor() {
return idDescriptor;
}
/*
* (non-Javadoc)
*
* @see java.lang.Iterable#iterator()
*/
public Iterator<MongoPropertyDescriptors.MongoPropertyDescriptor> iterator() {
return descriptors.iterator();
}
/*
* (non-Javadoc)
*
* @see java.lang.Iterable#iterator()
*/
public Iterator<MongoPropertyDescriptors.MongoPropertyDescriptor> iterator() {
return descriptors.iterator();
}
/**
* Simple value object to have a more suitable abstraction for MongoDB specific property handling.
*
* @author Oliver Gierke
*/
public static class MongoPropertyDescriptor {
/**
* Simple value object to have a more suitable abstraction for MongoDB specific property handling.
*
* @author Oliver Gierke
*/
public static class MongoPropertyDescriptor {
public static Collection<Class<?>> SUPPORTED_ID_CLASSES;
public static Collection<Class<?>> SUPPORTED_ID_CLASSES;
static {
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(ObjectId.class);
classes.add(String.class);
classes.add(BigInteger.class);
SUPPORTED_ID_CLASSES = Collections.unmodifiableCollection(classes);
}
static {
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(ObjectId.class);
classes.add(String.class);
classes.add(BigInteger.class);
SUPPORTED_ID_CLASSES = Collections.unmodifiableCollection(classes);
}
private static final String ID_PROPERTY = "id";
static final String ID_KEY = "_id";
private static final String ID_PROPERTY = "id";
static final String ID_KEY = "_id";
private final PropertyDescriptor delegate;
private final Class<?> owningType;
private final PropertyDescriptor delegate;
private final Class<?> owningType;
/**
* Creates a new {@link MongoPropertyDescriptor} for the given {@link PropertyDescriptor}.
*
* @param descriptor
* @param owningType
*/
public MongoPropertyDescriptor(PropertyDescriptor descriptor, Class<?> owningType) {
Assert.notNull(descriptor);
this.delegate = descriptor;
this.owningType = owningType;
}
/**
* Creates a new {@link MongoPropertyDescriptor} for the given {@link PropertyDescriptor}.
*
* @param descriptor
* @param owningType
*/
public MongoPropertyDescriptor(PropertyDescriptor descriptor, Class<?> owningType) {
Assert.notNull(descriptor);
this.delegate = descriptor;
this.owningType = owningType;
}
/**
* Returns whether the property is the id-property. Will be identified by name for now ({@value #ID_PROPERTY}).
*
* @return
*/
public boolean isIdProperty() {
return ID_PROPERTY.equals(delegate.getName()) || ID_KEY.equals(delegate.getName());
}
/**
* Returns whether the property is the id-property. Will be identified by name for now ({@value #ID_PROPERTY}).
*
* @return
*/
public boolean isIdProperty() {
return ID_PROPERTY.equals(delegate.getName()) || ID_KEY.equals(delegate.getName());
}
/**
* Returns whether the property is of one of the supported id types. Currently we support {@link String},
* {@link ObjectId} and {@link BigInteger}.
*
* @return
*/
public boolean isOfIdType() {
return SUPPORTED_ID_CLASSES.contains(delegate.getPropertyType());
}
/**
* Returns whether the property is of one of the supported id types. Currently we support {@link String},
* {@link ObjectId} and {@link BigInteger}.
*
* @return
*/
public boolean isOfIdType() {
return SUPPORTED_ID_CLASSES.contains(delegate.getPropertyType());
}
/**
* Returns the key that shall be used for mapping. Will return {@value #ID_KEY} for the id property and the
* plain name for all other ones.
*
* @return
*/
public String getKeyToMap() {
return isIdProperty() ? ID_KEY : delegate.getName();
}
/**
* Returns the key that shall be used for mapping. Will return {@value #ID_KEY} for the id property and the plain
* name for all other ones.
*
* @return
*/
public String getKeyToMap() {
return isIdProperty() ? ID_KEY : delegate.getName();
}
/**
* Returns the name of the property.
*
* @return
*/
public String getName() {
return delegate.getName();
}
/**
* Returns the name of the property.
*
* @return
*/
public String getName() {
return delegate.getName();
}
/**
* Returns whether the underlying property is actually mappable. By default this will exclude the
* {@literal class} property and only include properties with a getter.
*
* @return
*/
public boolean isMappable() {
boolean isNotClassAttribute = !delegate.getName().equals("class");
boolean hasGetter = delegate.getReadMethod() != null;
boolean hasField = ReflectionUtils.findField(owningType, delegate.getName()) != null;
return isNotClassAttribute && hasGetter && hasField;
}
/**
* Returns whether the underlying property is actually mappable. By default this will exclude the {@literal class}
* property and only include properties with a getter.
*
* @return
*/
public boolean isMappable() {
/**
* Returns the plain property type.
*
* @return
*/
public Class<?> getPropertyType() {
return delegate.getPropertyType();
}
boolean isNotClassAttribute = !delegate.getName().equals("class");
boolean hasGetter = delegate.getReadMethod() != null;
boolean hasField = ReflectionUtils.findField(owningType, delegate.getName()) != null;
/**
* Returns the type type to be set. Will return the setter method's type and fall back to the getter method's
* return type in case no setter is available. Useful for further (generics) inspection.
*
* @return
*/
public Type getTypeToSet() {
return isNotClassAttribute && hasGetter && hasField;
}
Method method = delegate.getWriteMethod();
return method == null ? delegate.getReadMethod().getGenericReturnType()
: method.getGenericParameterTypes()[0];
}
/**
* Returns the plain property type.
*
* @return
*/
public Class<?> getPropertyType() {
return delegate.getPropertyType();
}
/**
* Returns whther we describe a {@link Map}.
*
* @return
*/
public boolean isMap() {
return Map.class.isAssignableFrom(getPropertyType());
}
/**
* Returns the type type to be set. Will return the setter method's type and fall back to the getter method's return
* type in case no setter is available. Useful for further (generics) inspection.
*
* @return
*/
public Type getTypeToSet() {
/**
* Returns whether the descriptor is for a collection.
*
* @return
*/
public boolean isCollection() {
return Collection.class.isAssignableFrom(getPropertyType());
}
Method method = delegate.getWriteMethod();
return method == null ? delegate.getReadMethod().getGenericReturnType() : method.getGenericParameterTypes()[0];
}
/**
* Returns whether the descriptor is for an {@link Enum}.
*
* @return
*/
public boolean isEnum() {
return Enum.class.isAssignableFrom(getPropertyType());
}
/**
* Returns whther we describe a {@link Map}.
*
* @return
*/
public boolean isMap() {
return Map.class.isAssignableFrom(getPropertyType());
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj == null || !getClass().equals(obj.getClass())) {
return false;
}
MongoPropertyDescriptor that = (MongoPropertyDescriptor) obj;
return that.delegate.equals(this.delegate);
}
/**
* Returns whether the descriptor is for a collection.
*
* @return
*/
public boolean isCollection() {
return Collection.class.isAssignableFrom(getPropertyType());
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return delegate.hashCode();
}
}
/**
* Returns whether the descriptor is for an {@link Enum}.
*
* @return
*/
public boolean isEnum() {
return Enum.class.isAssignableFrom(getPropertyType());
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj == null || !getClass().equals(obj.getClass())) {
return false;
}
MongoPropertyDescriptor that = (MongoPropertyDescriptor) obj;
return that.delegate.equals(this.delegate);
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return delegate.hashCode();
}
}
}

View File

@@ -19,22 +19,25 @@ import com.mongodb.DBObject;
/**
* A MongoWriter is responsible for converting a native MongoDB DBObject to an object of type T.
*
* @param <T> the type of the object to convert from a DBObject
*
* @param <T>
* the type of the object to convert from a DBObject
* @author Mark Pollack
* @author Thomas Risberg
* @author Oliver Gierke
*/
public interface MongoReader<T> {
/**
* Ready from the native MongoDB DBObject representation to an instance of the class T. The given type has to be the
* starting point for marshalling the {@link DBObject} into it. So in case there's no real valid data inside
* {@link DBObject} for the given type, just return an empty instance of the given type.
*
* @param clazz the type of the return value
* @param dbo theDBObject
* @return the converted object
*/
<S extends T> S read(Class<S> clazz, DBObject dbo);
/**
* Ready from the native MongoDB DBObject representation to an instance of the class T. The given type has to be the
* starting point for marshalling the {@link DBObject} into it. So in case there's no real valid data inside
* {@link DBObject} for the given type, just return an empty instance of the given type.
*
* @param clazz
* the type of the return value
* @param dbo
* theDBObject
* @return the converted object
*/
<S extends T> S read(Class<S> clazz, DBObject dbo);
}

View File

@@ -5,8 +5,7 @@ import org.springframework.transaction.support.ResourceHolderSynchronization;
class MongoSynchronization extends ResourceHolderSynchronization<ResourceHolder, Object> {
public MongoSynchronization(ResourceHolder resourceHolder,
Object resourceKey) {
super(resourceHolder, resourceKey);
}
public MongoSynchronization(ResourceHolder resourceHolder, Object resourceKey) {
super(resourceHolder, resourceKey);
}
}

View File

@@ -73,7 +73,7 @@ import org.springframework.util.Assert;
/**
* Primary implementation of {@link MongoOperations}.
*
*
* @author Thomas Risberg
* @author Graeme Rocher
* @author Mark Pollack
@@ -110,7 +110,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
/**
* Constructor used for a basic template configuration
*
*
* @param mongo
* @param databaseName
*/
@@ -119,8 +119,9 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
}
/**
* Constructor used for a template configuration with a custom {@link org.springframework.data.document.mongodb.convert.MongoConverter}
*
* Constructor used for a template configuration with a custom
* {@link org.springframework.data.document.mongodb.convert.MongoConverter}
*
* @param mongo
* @param databaseName
* @param mongoConverter
@@ -130,16 +131,17 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
}
/**
* Constructor used for a template configuration with a custom {@link MongoConverter}
* and with a specific {@link com.mongodb.WriteConcern} to be used for all database write operations
*
* Constructor used for a template configuration with a custom {@link MongoConverter} and with a specific
* {@link com.mongodb.WriteConcern} to be used for all database write operations
*
* @param mongo
* @param databaseName
* @param mongoConverter
* @param writeConcern
* @param writeResultChecking
*/
MongoTemplate(Mongo mongo, String databaseName, MongoConverter mongoConverter, WriteConcern writeConcern, WriteResultChecking writeResultChecking) {
MongoTemplate(Mongo mongo, String databaseName, MongoConverter mongoConverter, WriteConcern writeConcern,
WriteResultChecking writeResultChecking) {
Assert.notNull(mongo);
Assert.notNull(databaseName);
@@ -174,8 +176,9 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
/**
* Sets the username to use to connect to the Mongo database
*
* @param username The username to use
*
* @param username
* The username to use
*/
public void setUsername(String username) {
this.username = username;
@@ -183,8 +186,9 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
/**
* Sets the password to use to authenticate with the Mongo database.
*
* @param password The password to use
*
* @param password
* The password to use
*/
public void setPassword(String password) {
@@ -193,7 +197,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
/**
* Sets the database name to be used.
*
*
* @param databaseName
*/
public void setDatabaseName(String databaseName) {
@@ -203,7 +207,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
/**
* Returns the default {@link org.springframework.data.document.mongodb.convert.MongoConverter}.
*
*
* @return
*/
public MongoConverter getConverter() {
@@ -238,10 +242,9 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
String error = result.getErrorMessage();
if (error != null) {
// TODO: allow configuration of logging level / throw
// throw new InvalidDataAccessApiUsageException("Command execution of " +
// command.toString() + " failed: " + error);
LOGGER.warn("Command execution of " +
command.toString() + " failed: " + error);
// throw new InvalidDataAccessApiUsageException("Command execution of " +
// command.toString() + " failed: " + error);
LOGGER.warn("Command execution of " + command.toString() + " failed: " + error);
}
return result;
}
@@ -285,18 +288,23 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
/**
* Central callback executing method to do queries against the datastore that requires reading a single object from a
* collection of objects. It will take the following steps <ol> <li>Execute the given {@link ConnectionCallback} for a
* {@link DBObject}.</li> <li>Apply the given
* {@link DbObjectCallback} to each of the {@link DBObject}s to obtain the result.</li> <ol>
*
* collection of objects. It will take the following steps
* <ol>
* <li>Execute the given {@link ConnectionCallback} for a {@link DBObject}.</li>
* <li>Apply the given {@link DbObjectCallback} to each of the {@link DBObject}s to obtain the result.</li>
* <ol>
*
* @param <T>
* @param collectionCallback the callback to retrieve the {@link DBObject} with
* @param objectCallback the {@link DbObjectCallback} to transform {@link DBObject}s into the actual domain type
* @param collectionName the collection to be queried
* @param collectionCallback
* the callback to retrieve the {@link DBObject} with
* @param objectCallback
* the {@link DbObjectCallback} to transform {@link DBObject}s into the actual domain type
* @param collectionName
* the collection to be queried
* @return
*/
private <T> T execute(CollectionCallback<DBObject> collectionCallback,
DbObjectCallback<T> objectCallback, String collectionName) {
private <T> T execute(CollectionCallback<DBObject> collectionCallback, DbObjectCallback<T> objectCallback,
String collectionName) {
try {
T result = objectCallback.doWith(collectionCallback.doInCollection(getCollection(collectionName)));
@@ -308,20 +316,28 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
/**
* Central callback executing method to do queries against the datastore that requires reading a collection of
* objects. It will take the following steps <ol> <li>Execute the given {@link ConnectionCallback} for a
* {@link DBCursor}.</li> <li>Prepare that {@link DBCursor} with the given {@link CursorPreparer} (will be skipped
* if {@link CursorPreparer} is {@literal null}</li> <li>Iterate over the {@link DBCursor} and applies the given
* {@link DbObjectCallback} to each of the {@link DBObject}s collecting the actual result {@link List}.</li> <ol>
*
* objects. It will take the following steps
* <ol>
* <li>Execute the given {@link ConnectionCallback} for a {@link DBCursor}.</li>
* <li>Prepare that {@link DBCursor} with the given {@link CursorPreparer} (will be skipped if {@link CursorPreparer}
* is {@literal null}</li>
* <li>Iterate over the {@link DBCursor} and applies the given {@link DbObjectCallback} to each of the
* {@link DBObject}s collecting the actual result {@link List}.</li>
* <ol>
*
* @param <T>
* @param collectionCallback the callback to retrieve the {@link DBCursor} with
* @param preparer the {@link CursorPreparer} to potentially modify the {@link DBCursor} before ireating over it
* @param objectCallback the {@link DbObjectCallback} to transform {@link DBObject}s into the actual domain type
* @param collectionName the collection to be queried
* @param collectionCallback
* the callback to retrieve the {@link DBCursor} with
* @param preparer
* the {@link CursorPreparer} to potentially modify the {@link DBCursor} before ireating over it
* @param objectCallback
* the {@link DbObjectCallback} to transform {@link DBObject}s into the actual domain type
* @param collectionName
* the collection to be queried
* @return
*/
private <T> List<T> executeEach(CollectionCallback<DBCursor> collectionCallback, CursorPreparer preparer,
DbObjectCallback<T> objectCallback, String collectionName) {
DbObjectCallback<T> objectCallback, String collectionName) {
try {
DBCursor cursor = collectionCallback.doInCollection(getCollection(collectionName));
@@ -384,7 +400,6 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
});
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoOperations#collectionExists(java.lang.String)
*/
@@ -435,8 +450,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
return findOne(determineCollectionName(targetClass), query, targetClass);
}
public <T> T findOne(String collectionName, Query query,
Class<T> targetClass) {
public <T> T findOne(String collectionName, Query query, Class<T> targetClass) {
return doFindOne(collectionName, query.getQueryObject(), query.getFieldsObject(), targetClass);
}
@@ -473,8 +487,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
return doFind(collectionName, query.getQueryObject(), query.getFieldsObject(), targetClass, cursorPreparer);
}
public <T> List<T> find(String collectionName, Query query,
Class<T> targetClass, CursorPreparer preparer) {
public <T> List<T> find(String collectionName, Query query, Class<T> targetClass, CursorPreparer preparer) {
return doFind(collectionName, query.getQueryObject(), query.getFieldsObject(), targetClass, preparer);
}
@@ -485,9 +498,9 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
return findAndRemove(determineCollectionName(targetClass), query, targetClass);
}
public <T> T findAndRemove(String collectionName, Query query,
Class<T> targetClass) {
return doFindAndRemove(collectionName, query.getQueryObject(), query.getFieldsObject(), query.getSortObject(), targetClass);
public <T> T findAndRemove(String collectionName, Query query, Class<T> targetClass) {
return doFindAndRemove(collectionName, query.getQueryObject(), query.getFieldsObject(), query.getSortObject(),
targetClass);
}
/* (non-Javadoc)
@@ -538,8 +551,8 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(o.getClass());
if (entity == null) {
throw new InvalidDataAccessApiUsageException("No Persitent Entity information found for the class " +
o.getClass().getName());
throw new InvalidDataAccessApiUsageException("No Persitent Entity information found for the class "
+ o.getClass().getName());
}
String collection = entity.getCollection();
@@ -608,15 +621,14 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbDoc));
}
protected Object insertDBObject(String collectionName, final DBObject dbDoc) {
// DATADOC-95: This will prevent null objects from being saved.
//if (dbDoc.keySet().isEmpty()) {
//return null;
//}
// if (dbDoc.keySet().isEmpty()) {
// return null;
// }
//TODO: Need to move this to more central place
// TODO: Need to move this to more central place
if (dbDoc.containsField("_id")) {
if (dbDoc.get("_id") instanceof String) {
ObjectId oid = convertIdValue(this.mongoConverter, dbDoc.get("_id"));
@@ -646,7 +658,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
return Collections.emptyList();
}
//TODO: Need to move this to more central place
// TODO: Need to move this to more central place
for (DBObject dbDoc : dbDocList) {
if (dbDoc.containsField("_id")) {
if (dbDoc.get("_id") instanceof String) {
@@ -690,7 +702,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
return null;
}
//TODO: Need to move this to more central place
// TODO: Need to move this to more central place
if (dbDoc.containsField("_id")) {
if (dbDoc.get("_id") instanceof String) {
ObjectId oid = convertIdValue(this.mongoConverter, dbDoc.get("_id"));
@@ -742,12 +754,8 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
return doUpdate(collectionName, query, update, null, false, true);
}
protected WriteResult doUpdate(final String collectionName,
final Query query,
final Update update,
final Class<?> entityClass,
final boolean upsert,
final boolean multi) {
protected WriteResult doUpdate(final String collectionName, final Query query, final Update update,
final Class<?> entityClass, final boolean upsert, final boolean multi) {
return execute(collectionName, new CollectionCallback<WriteResult>() {
public WriteResult doInCollection(DBCollection collection) throws MongoException, DataAccessException {
@@ -773,7 +781,8 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("calling update using query: " + queryObj + " and update: " + updateObj + " in collection: " + collectionName);
LOGGER.debug("calling update using query: " + queryObj + " and update: " + updateObj + " in collection: "
+ collectionName);
}
WriteResult wr;
@@ -841,7 +850,6 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
remove(collectionName, query, null);
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoOperations#getCollection(java.lang.Class)
*/
@@ -875,7 +883,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
/**
* Create the specified collection using the provided options
*
*
* @param collectionName
* @param collectionOptions
* @return the collection that was created
@@ -894,11 +902,15 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
* Map the results of an ad-hoc query on the default MongoDB collection to an object using the template's converter
* <p/>
* The query document is specified as a standard DBObject and so is the fields specification.
*
* @param collectionName name of the collection to retrieve the objects from
* @param query the query document that specifies the criteria used to find a record
* @param fields the document that specifies the fields to be returned
* @param targetClass the parameterized type of the returned list.
*
* @param collectionName
* name of the collection to retrieve the objects from
* @param query
* the query document that specifies the criteria used to find a record
* @param fields
* the document that specifies the fields to be returned
* @param targetClass
* the parameterized type of the returned list.
* @return the List of converted objects.
*/
protected <T> T doFindOne(String collectionName, DBObject query, DBObject fields, Class<T> targetClass) {
@@ -906,63 +918,70 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(targetClass);
DBObject mappedQuery = mapper.getMappedObject(query, entity);
return execute(new FindOneCallback(mappedQuery, fields),
new ReadDbObjectCallback<T>(readerToUse, targetClass),
return execute(new FindOneCallback(mappedQuery, fields), new ReadDbObjectCallback<T>(readerToUse, targetClass),
collectionName);
}
/**
* Map the results of an ad-hoc query on the default MongoDB collection to a List of the specified type.
* <p/>
* The object is converted from the MongoDB native representation using an instance of
* {@see MongoConverter}. Unless configured otherwise, an
* instance of SimpleMongoConverter will be used.
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* The query document is specified as a standard DBObject and so is the fields specification.
* <p/>
* Can be overridden by subclasses.
*
* @param collectionName name of the collection to retrieve the objects from
* @param query the query document that specifies the criteria used to find a record
* @param fields the document that specifies the fields to be returned
* @param targetClass the parameterized type of the returned list.
* @param preparer allows for customization of the DBCursor used when iterating over the result set,
* (apply limits, skips and so on).
*
* @param collectionName
* name of the collection to retrieve the objects from
* @param query
* the query document that specifies the criteria used to find a record
* @param fields
* the document that specifies the fields to be returned
* @param targetClass
* the parameterized type of the returned list.
* @param preparer
* allows for customization of the DBCursor used when iterating over the result set, (apply limits, skips and
* so on).
* @return the List of converted objects.
*/
protected <T> List<T> doFind(String collectionName, DBObject query, DBObject fields, Class<T> targetClass, CursorPreparer preparer) {
protected <T> List<T> doFind(String collectionName, DBObject query, DBObject fields, Class<T> targetClass,
CursorPreparer preparer) {
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(targetClass);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("find using query: " + query + " fields: " + fields + " for class: " + targetClass + " in collection: " + collectionName);
LOGGER.debug("find using query: " + query + " fields: " + fields + " for class: " + targetClass
+ " in collection: " + collectionName);
}
return executeEach(new FindCallback(mapper.getMappedObject(query, entity), fields),
preparer,
new ReadDbObjectCallback<T>(mongoConverter, targetClass),
collectionName);
return executeEach(new FindCallback(mapper.getMappedObject(query, entity), fields), preparer,
new ReadDbObjectCallback<T>(mongoConverter, targetClass), collectionName);
}
/**
* Map the results of an ad-hoc query on the default MongoDB collection to a List using the template's converter.
* <p/>
* The query document is specified as a standard DBObject and so is the fields specification.
*
* @param collectionName name of the collection to retrieve the objects from
* @param query the query document that specifies the criteria used to find a record
* @param fields the document that specifies the fields to be returned
* @param targetClass the parameterized type of the returned list.
* @param reader the MongoReader to convert from DBObject to an object.
*
* @param collectionName
* name of the collection to retrieve the objects from
* @param query
* the query document that specifies the criteria used to find a record
* @param fields
* the document that specifies the fields to be returned
* @param targetClass
* the parameterized type of the returned list.
* @param reader
* the MongoReader to convert from DBObject to an object.
* @return the List of converted objects.
*/
protected <T> List<T> doFind(String collectionName, DBObject query, DBObject fields, Class<T> targetClass) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("find using query: " + query + " fields: " + fields + " for class: " + targetClass + " in collection: " + collectionName);
LOGGER.debug("find using query: " + query + " fields: " + fields + " for class: " + targetClass
+ " in collection: " + collectionName);
}
MongoReader<? super T> readerToUse = this.mongoConverter;
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(targetClass);
return executeEach(new FindCallback(mapper.getMappedObject(query, entity), fields),
null,
new ReadDbObjectCallback<T>(readerToUse, targetClass),
collectionName);
return executeEach(new FindCallback(mapper.getMappedObject(query, entity), fields), null,
new ReadDbObjectCallback<T>(readerToUse, targetClass), collectionName);
}
protected DBObject convertToDbObject(CollectionOptions collectionOptions) {
@@ -986,22 +1005,27 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
* The first document that matches the query is returned and also removed from the collection in the database.
* <p/>
* The query document is specified as a standard DBObject and so is the fields specification.
*
* @param collectionName name of the collection to retrieve the objects from
* @param query the query document that specifies the criteria used to find a record
* @param targetClass the parameterized type of the returned list.
* @param reader the MongoReader to convert from DBObject to an object.
*
* @param collectionName
* name of the collection to retrieve the objects from
* @param query
* the query document that specifies the criteria used to find a record
* @param targetClass
* the parameterized type of the returned list.
* @param reader
* the MongoReader to convert from DBObject to an object.
* @return the List of converted objects.
*/
protected <T> T doFindAndRemove(String collectionName, DBObject query, DBObject fields, DBObject sort, Class<T> targetClass) {
protected <T> T doFindAndRemove(String collectionName, DBObject query, DBObject fields, DBObject sort,
Class<T> targetClass) {
MongoReader<? super T> readerToUse = this.mongoConverter;
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("findAndRemove using query: " + query + " fields: " + fields + " sort: " + sort + " for class: " + targetClass + " in collection: " + collectionName);
LOGGER.debug("findAndRemove using query: " + query + " fields: " + fields + " sort: " + sort + " for class: "
+ targetClass + " in collection: " + collectionName);
}
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(targetClass);
return execute(new FindAndRemoveCallback(mapper.getMappedObject(query, entity), fields, sort),
new ReadDbObjectCallback<T>(readerToUse, targetClass),
collectionName);
new ReadDbObjectCallback<T>(readerToUse, targetClass), collectionName);
}
protected Object getIdValue(Object object) {
@@ -1024,7 +1048,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
/**
* Populates the id property of the saved object, if it's not set already.
*
*
* @param savedObject
* @param id
*/
@@ -1051,10 +1075,10 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
}
/**
* Substitutes the id key if it is found in he query. Any 'id' keys will be replaced with '_id' and the value converted
* to an ObjectId if possible. This conversion should match the way that the id fields are converted during read
* operations.
*
* Substitutes the id key if it is found in he query. Any 'id' keys will be replaced with '_id' and the value
* converted to an ObjectId if possible. This conversion should match the way that the id fields are converted during
* read operations.
*
* @param query
* @param targetClass
* @param reader
@@ -1087,7 +1111,8 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
// no property descriptor for this key - try the other
try {
String theOtherIdKey = "id".equals(idKey) ? "_id" : "id";
MongoPropertyDescriptor mpd2 = new MongoPropertyDescriptor(new PropertyDescriptor(theOtherIdKey, targetClass), targetClass);
MongoPropertyDescriptor mpd2 = new MongoPropertyDescriptor(new PropertyDescriptor(theOtherIdKey, targetClass),
targetClass);
descriptor = mpd2;
} catch (IntrospectionException e2) {
// no property descriptor for this key either - bail
@@ -1109,8 +1134,8 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
}
}
if (ids.size() > 0 && ids.size() != count) {
throw new InvalidDataAccessApiUsageException("Inconsistent set of id values provided " +
Arrays.asList((Object[]) dbo.get("$in")));
throw new InvalidDataAccessApiUsageException("Inconsistent set of id values provided "
+ Arrays.asList((Object[]) dbo.get("$in")));
}
if (ids.size() > 0) {
dbo.removeField("$in");
@@ -1162,12 +1187,14 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
private String determineCollectionName(Class<?> clazz) {
if (clazz == null) {
throw new InvalidDataAccessApiUsageException("No class parameter provided, entity collection can't be determined for " + clazz);
throw new InvalidDataAccessApiUsageException(
"No class parameter provided, entity collection can't be determined for " + clazz);
}
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(clazz);
if (entity == null) {
throw new InvalidDataAccessApiUsageException("No Persitent Entity information found for the class " + clazz.getName());
throw new InvalidDataAccessApiUsageException("No Persitent Entity information found for the class "
+ clazz.getName());
}
return entity.getCollection();
}
@@ -1175,8 +1202,8 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
/**
* Checks and handles any errors.
* <p/>
* TODO: current implementation logs errors - will be configurable to log warning, errors or
* throw exception in later versions
* TODO: current implementation logs errors - will be configurable to log warning, errors or throw exception in later
* versions
*/
private void handleAnyWriteResultErrors(WriteResult wr, DBObject query, String operation) {
if (WriteResultChecking.NONE == this.writeResultChecking) {
@@ -1185,16 +1212,16 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
String error = wr.getError();
int n = wr.getN();
if (error != null) {
String message = "Execution of '" + operation +
(query == null ? "" : "' using '" + query.toString() + "' query") + " failed: " + error;
String message = "Execution of '" + operation + (query == null ? "" : "' using '" + query.toString() + "' query")
+ " failed: " + error;
if (WriteResultChecking.EXCEPTION == this.writeResultChecking) {
throw new DataIntegrityViolationException(message);
} else {
LOGGER.error(message);
}
} else if (n == 0) {
String message = "Execution of '" + operation +
(query == null ? "" : "' using '" + query.toString() + "' query") + " did not succeed: 0 documents updated";
String message = "Execution of '" + operation + (query == null ? "" : "' using '" + query.toString() + "' query")
+ " did not succeed: 0 documents updated";
if (WriteResultChecking.EXCEPTION == this.writeResultChecking) {
throw new DataIntegrityViolationException(message);
} else {
@@ -1207,7 +1234,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
/**
* Tries to convert the given {@link RuntimeException} into a {@link DataAccessException} but returns the original
* exception if the conversation failed. Thus allows safe rethrowing of the return value.
*
*
* @param ex
* @return
*/
@@ -1221,11 +1248,10 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
converter.setDefaultDatabase(databaseName);
}
/**
* Simple {@link CollectionCallback} that takes a query {@link DBObject} plus an optional fields specification
* {@link DBObject} and executes that against the {@link DBCollection}.
*
*
* @author Oliver Gierke
* @author Thomas Risberg
*/
@@ -1248,7 +1274,8 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
return collection.findOne(query);
} else {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("findOne using query: " + query + " fields: " + fields + " in db.collection: " + collection.getFullName());
LOGGER.debug("findOne using query: " + query + " fields: " + fields + " in db.collection: "
+ collection.getFullName());
}
return collection.findOne(query, fields);
}
@@ -1258,7 +1285,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
/**
* Simple {@link CollectionCallback} that takes a query {@link DBObject} plus an optional fields specification
* {@link DBObject} and executes that against the {@link DBCollection}.
*
*
* @author Oliver Gierke
* @author Thomas Risberg
*/
@@ -1289,7 +1316,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
/**
* Simple {@link CollectionCallback} that takes a query {@link DBObject} plus an optional fields specification
* {@link DBObject} and executes that against the {@link DBCollection}.
*
*
* @author Thomas Risberg
*/
private static class FindAndRemoveCallback implements CollectionCallback<DBObject> {
@@ -1313,7 +1340,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
/**
* Simple internal callback to allow operations on a {@link DBObject}.
*
*
* @author Oliver Gierke
*/
@@ -1325,7 +1352,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
/**
* Simple {@link DbObjectCallback} that will transform {@link DBObject} into the given target type using the given
* {@link MongoReader}.
*
*
* @author Oliver Gierke
*/
private class ReadDbObjectCallback<T> implements DbObjectCallback<T> {

View File

@@ -19,19 +19,22 @@ import com.mongodb.DBObject;
/**
* A MongoWriter is responsible for converting an object of type T to the native MongoDB representation DBObject.
*
* @param <T> the type of the object to convert to a DBObject
*
* @param <T>
* the type of the object to convert to a DBObject
* @author Mark Pollack
* @author Thomas Risberg
*/
public interface MongoWriter<T> {
/**
* Write the given object of type T to the native MongoDB object representation DBObject.
*
* @param t The object to convert to a DBObject
* @param dbo The DBObject to use for writing.
*/
void write(T t, DBObject dbo);
/**
* Write the given object of type T to the native MongoDB object representation DBObject.
*
* @param t
* The object to convert to a DBObject
* @param dbo
* The DBObject to use for writing.
*/
void write(T t, DBObject dbo);
}

View File

@@ -1,5 +1,5 @@
package org.springframework.data.document.mongodb;
public enum WriteResultChecking {
NONE, LOG, EXCEPTION
NONE, LOG, EXCEPTION
}

View File

@@ -38,61 +38,63 @@ import com.mongodb.Mongo;
@Configuration
public abstract class AbstractMongoConfiguration {
@Bean
public abstract Mongo mongo() throws Exception;
@Bean
public abstract Mongo mongo() throws Exception;
@Bean
public abstract MongoTemplate mongoTemplate() throws Exception;
public String getMappingBasePackage() {
return "";
}
@Bean
public MongoMappingContext mongoMappingContext() throws ClassNotFoundException, LinkageError {
MongoMappingContext mappingContext = new MongoMappingContext();
String basePackage = getMappingBasePackage();
if (StringUtils.hasText(basePackage)) {
ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(false);
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Document.class));
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
for (BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) {
initialEntitySet.add(ClassUtils.forName(candidate.getBeanClassName(), mappingContext.getClass().getClassLoader()));
}
mappingContext.setInitialEntitySet(initialEntitySet);
}
return mappingContext;
}
@Bean
public MappingMongoConverter mappingMongoConverter() throws Exception {
MappingMongoConverter converter = new MappingMongoConverter(mongoMappingContext());
converter.setMongo(mongo());
afterMappingMongoConverterCreation(converter);
return converter;
}
/**
* Hook that allows post-processing after the MappingMongoConverter has been
* successfully created.
* @param converter
*/
protected void afterMappingMongoConverterCreation(MappingMongoConverter converter) {
}
@Bean
public abstract MongoTemplate mongoTemplate() throws Exception;
@Bean
public MappingContextAwareBeanPostProcessor mappingContextAwareBeanPostProcessor() {
MappingContextAwareBeanPostProcessor bpp = new MappingContextAwareBeanPostProcessor();
bpp.setMappingContextBeanName("mongoMappingContext");
return bpp;
}
@Bean MongoPersistentEntityIndexCreator mongoPersistentEntityIndexCreator() throws Exception {
MongoPersistentEntityIndexCreator indexCreator = new MongoPersistentEntityIndexCreator(mongoMappingContext(), mongoTemplate() );
return indexCreator;
}
public String getMappingBasePackage() {
return "";
}
@Bean
public MongoMappingContext mongoMappingContext() throws ClassNotFoundException, LinkageError {
MongoMappingContext mappingContext = new MongoMappingContext();
String basePackage = getMappingBasePackage();
if (StringUtils.hasText(basePackage)) {
ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(
false);
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Document.class));
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
for (BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) {
initialEntitySet.add(ClassUtils.forName(candidate.getBeanClassName(), mappingContext.getClass()
.getClassLoader()));
}
mappingContext.setInitialEntitySet(initialEntitySet);
}
return mappingContext;
}
@Bean
public MappingMongoConverter mappingMongoConverter() throws Exception {
MappingMongoConverter converter = new MappingMongoConverter(mongoMappingContext());
converter.setMongo(mongo());
afterMappingMongoConverterCreation(converter);
return converter;
}
/**
* Hook that allows post-processing after the MappingMongoConverter has been successfully created.
*
* @param converter
*/
protected void afterMappingMongoConverterCreation(MappingMongoConverter converter) {
}
@Bean
public MappingContextAwareBeanPostProcessor mappingContextAwareBeanPostProcessor() {
MappingContextAwareBeanPostProcessor bpp = new MappingContextAwareBeanPostProcessor();
bpp.setMappingContextBeanName("mongoMappingContext");
return bpp;
}
@Bean
MongoPersistentEntityIndexCreator mongoPersistentEntityIndexCreator() throws Exception {
MongoPersistentEntityIndexCreator indexCreator = new MongoPersistentEntityIndexCreator(mongoMappingContext(),
mongoTemplate());
return indexCreator;
}
}

View File

@@ -63,7 +63,8 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
private static final String BASE_PACKAGE = "base-package";
@Override
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) throws BeanDefinitionStoreException {
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
throws BeanDefinitionStoreException {
String id = super.resolveId(element, definition, parserContext);
return StringUtils.hasText(id) ? id : "mappingConverter";
}
@@ -74,7 +75,8 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
String ctxRef = element.getAttribute("mapping-context-ref");
if (!StringUtils.hasText(ctxRef)) {
BeanDefinitionBuilder mappingContextBuilder = BeanDefinitionBuilder.genericBeanDefinition(MongoMappingContext.class);
BeanDefinitionBuilder mappingContextBuilder = BeanDefinitionBuilder
.genericBeanDefinition(MongoMappingContext.class);
Set<String> classesToAdd = getInititalEntityClasses(element, mappingContextBuilder);
if (classesToAdd != null) {
@@ -88,7 +90,8 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
try {
registry.getBeanDefinition(POST_PROCESSOR);
} catch (NoSuchBeanDefinitionException ignored) {
BeanDefinitionBuilder postProcBuilder = BeanDefinitionBuilder.genericBeanDefinition(MappingContextAwareBeanPostProcessor.class);
BeanDefinitionBuilder postProcBuilder = BeanDefinitionBuilder
.genericBeanDefinition(MappingContextAwareBeanPostProcessor.class);
postProcBuilder.addPropertyValue("mappingContextBeanName", ctxRef);
registry.registerBeanDefinition(POST_PROCESSOR, postProcBuilder.getBeanDefinition());
}
@@ -104,9 +107,11 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
registry.getBeanDefinition(INDEX_HELPER);
} catch (NoSuchBeanDefinitionException ignored) {
String templateRef = element.getAttribute("mongo-template-ref");
BeanDefinitionBuilder indexHelperBuilder = BeanDefinitionBuilder.genericBeanDefinition(MongoPersistentEntityIndexCreator.class);
BeanDefinitionBuilder indexHelperBuilder = BeanDefinitionBuilder
.genericBeanDefinition(MongoPersistentEntityIndexCreator.class);
indexHelperBuilder.addConstructorArgValue(new RuntimeBeanReference(ctxRef));
indexHelperBuilder.addConstructorArgValue(new RuntimeBeanReference(StringUtils.hasText(templateRef) ? templateRef : TEMPLATE));
indexHelperBuilder.addConstructorArgValue(new RuntimeBeanReference(StringUtils.hasText(templateRef) ? templateRef
: TEMPLATE));
registry.registerBeanDefinition(INDEX_HELPER, indexHelperBuilder.getBeanDefinition());
}
@@ -126,7 +131,6 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
return converterBuilder.getBeanDefinition();
}
public Set<String> getInititalEntityClasses(Element element, BeanDefinitionBuilder builder) {
String basePackage = element.getAttribute(BASE_PACKAGE);
@@ -135,7 +139,8 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
return null;
}
ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(false);
ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(
false);
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Document.class));
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
@@ -148,8 +153,8 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
}
public BeanMetadataElement parseConverter(Element element, ParserContext parserContext) {
String converterRef= element.getAttribute("ref");
String converterRef = element.getAttribute("ref");
if (StringUtils.hasText(converterRef)) {
return new RuntimeBeanReference(converterRef);
}

View File

@@ -28,42 +28,42 @@ import org.w3c.dom.Element;
public class MongoJmxParser implements BeanDefinitionParser {
public BeanDefinition parse(Element element, ParserContext parserContext) {
String name = element.getAttribute("mongo-ref");
if (!StringUtils.hasText(name)) {
name = "mongo";
}
registerJmxComponents(name, element, parserContext);
return null;
}
public BeanDefinition parse(Element element, ParserContext parserContext) {
String name = element.getAttribute("mongo-ref");
if (!StringUtils.hasText(name)) {
name = "mongo";
}
registerJmxComponents(name, element, parserContext);
return null;
}
protected void registerJmxComponents(String mongoRefName, Element element, ParserContext parserContext) {
Object eleSource = parserContext.extractSource(element);
protected void registerJmxComponents(String mongoRefName, Element element, ParserContext parserContext) {
Object eleSource = parserContext.extractSource(element);
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
createBeanDefEntry(AssertMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(BackgroundFlushingMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(BtreeIndexCounters.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(ConnectionMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(GlobalLockMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(MemoryMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(OperationCounters.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(ServerInfo.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(MongoAdmin.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(AssertMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(BackgroundFlushingMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(BtreeIndexCounters.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(ConnectionMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(GlobalLockMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(MemoryMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(OperationCounters.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(ServerInfo.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(MongoAdmin.class, compositeDef, mongoRefName, eleSource, parserContext);
parserContext.registerComponent(compositeDef);
parserContext.registerComponent(compositeDef);
}
}
protected void createBeanDefEntry(Class<?> clazz, CompositeComponentDefinition compositeDef, String mongoRefName, Object eleSource, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
builder.getRawBeanDefinition().setSource(eleSource);
builder.addConstructorArgReference(mongoRefName);
BeanDefinition assertDef = builder.getBeanDefinition();
String assertName = parserContext.getReaderContext().registerWithGeneratedName(assertDef);
compositeDef.addNestedComponent(new BeanComponentDefinition(assertDef, assertName));
}
protected void createBeanDefEntry(Class<?> clazz, CompositeComponentDefinition compositeDef, String mongoRefName,
Object eleSource, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
builder.getRawBeanDefinition().setSource(eleSource);
builder.addConstructorArgReference(mongoRefName);
BeanDefinition assertDef = builder.getBeanDefinition();
String assertName = parserContext.getReaderContext().registerWithGeneratedName(assertDef);
compositeDef.addNestedComponent(new BeanComponentDefinition(assertDef, assertName));
}
}

View File

@@ -28,67 +28,68 @@ import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
/**
* Parser for &lt;mongo;gt; definitions. If no name
*
* Parser for &lt;mongo;gt; definitions. If no name
*
* @author Mark Pollack
*/
public class MongoParser extends AbstractSingleBeanDefinitionParser {
protected Class<?> getBeanClass(Element element) {
return MongoFactoryBean.class;
}
protected Class<?> getBeanClass(Element element) {
return MongoFactoryBean.class;
}
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
super.doParse(element, builder);
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
super.doParse(element, builder);
setPropertyValue(element, builder, "port", "port");
setPropertyValue(element, builder, "host", "host");
setPropertyValue(element, builder, "port", "port");
setPropertyValue(element, builder, "host", "host");
parseOptions(parserContext, element, builder);
parseOptions(parserContext, element, builder);
}
}
/**
* Parses the options sub-element. Populates the given attribute factory with the proper attributes.
*
* @param element
* @param attrBuilder
* @return true if parsing actually occured, false otherwise
*/
private boolean parseOptions(ParserContext parserContext, Element element,
BeanDefinitionBuilder mongoBuilder) {
Element optionsElement = DomUtils.getChildElementByTagName(element, "options");
if (optionsElement == null)
return false;
/**
* Parses the options sub-element. Populates the given attribute factory with the proper attributes.
*
* @param element
* @param attrBuilder
* @return true if parsing actually occured, false otherwise
*/
private boolean parseOptions(ParserContext parserContext, Element element, BeanDefinitionBuilder mongoBuilder) {
Element optionsElement = DomUtils.getChildElementByTagName(element, "options");
if (optionsElement == null)
return false;
BeanDefinitionBuilder optionsDefBuilder = BeanDefinitionBuilder.genericBeanDefinition(MongoOptionsFactoryBean.class);
BeanDefinitionBuilder optionsDefBuilder = BeanDefinitionBuilder
.genericBeanDefinition(MongoOptionsFactoryBean.class);
setPropertyValue(optionsElement, optionsDefBuilder, "connectionsPerHost", "connectionsPerHost");
setPropertyValue(optionsElement, optionsDefBuilder, "threadsAllowedToBlockForConnectionMultiplier", "threadsAllowedToBlockForConnectionMultiplier");
setPropertyValue(optionsElement, optionsDefBuilder, "maxWaitTime", "maxWaitTime");
setPropertyValue(optionsElement, optionsDefBuilder, "connectTimeout", "connectTimeout");
setPropertyValue(optionsElement, optionsDefBuilder, "socketTimeout", "socketTimeout");
setPropertyValue(optionsElement, optionsDefBuilder, "autoConnectRetry", "autoConnectRetry");
setPropertyValue(optionsElement, optionsDefBuilder, "connectionsPerHost", "connectionsPerHost");
setPropertyValue(optionsElement, optionsDefBuilder, "threadsAllowedToBlockForConnectionMultiplier",
"threadsAllowedToBlockForConnectionMultiplier");
setPropertyValue(optionsElement, optionsDefBuilder, "maxWaitTime", "maxWaitTime");
setPropertyValue(optionsElement, optionsDefBuilder, "connectTimeout", "connectTimeout");
setPropertyValue(optionsElement, optionsDefBuilder, "socketTimeout", "socketTimeout");
setPropertyValue(optionsElement, optionsDefBuilder, "autoConnectRetry", "autoConnectRetry");
mongoBuilder.addPropertyValue("mongoOptions", optionsDefBuilder.getBeanDefinition());
return true;
}
mongoBuilder.addPropertyValue("mongoOptions", optionsDefBuilder.getBeanDefinition());
return true;
}
@Override
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
throws BeanDefinitionStoreException {
String name = super.resolveId(element, definition, parserContext);
if (!StringUtils.hasText(name)) {
name = "mongo";
}
return name;
}
@Override
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
throws BeanDefinitionStoreException {
String name = super.resolveId(element, definition, parserContext);
if (!StringUtils.hasText(name)) {
name = "mongo";
}
return name;
}
private void setPropertyValue(Element element, BeanDefinitionBuilder builder, String attrName, String propertyName) {
String attr = element.getAttribute(attrName);
if (StringUtils.hasText(attr)) {
builder.addPropertyValue(propertyName, attr);
}
}
private void setPropertyValue(Element element, BeanDefinitionBuilder builder, String attrName, String propertyName) {
String attr = element.getAttribute(attrName);
if (StringUtils.hasText(attr)) {
builder.addPropertyValue(propertyName, attr);
}
}
}

View File

@@ -23,73 +23,68 @@ import org.springframework.data.mapping.model.MappingContext;
import org.springframework.data.repository.config.AbstractRepositoryConfigDefinitionParser;
import org.w3c.dom.Element;
/**
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser} to create
* Mongo DB repositories from classpath scanning or manual definition.
*
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser} to create Mongo DB repositories from classpath
* scanning or manual definition.
*
* @author Oliver Gierke
*/
public class MongoRepositoryConfigParser
extends
AbstractRepositoryConfigDefinitionParser<SimpleMongoRepositoryConfiguration, MongoRepositoryConfiguration> {
private static final String MAPPING_CONTEXT_DEFAULT = MappingMongoConverterParser.MAPPING_CONTEXT;
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.config.
* AbstractRepositoryConfigDefinitionParser
* #getGlobalRepositoryConfigInformation(org.w3c.dom.Element)
*/
@Override
protected SimpleMongoRepositoryConfiguration getGlobalRepositoryConfigInformation(
Element element) {
public class MongoRepositoryConfigParser extends
AbstractRepositoryConfigDefinitionParser<SimpleMongoRepositoryConfiguration, MongoRepositoryConfiguration> {
return new SimpleMongoRepositoryConfiguration(element);
}
private static final String MAPPING_CONTEXT_DEFAULT = MappingMongoConverterParser.MAPPING_CONTEXT;
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.config.
* AbstractRepositoryConfigDefinitionParser
* #getGlobalRepositoryConfigInformation(org.w3c.dom.Element)
*/
@Override
protected SimpleMongoRepositoryConfiguration getGlobalRepositoryConfigInformation(Element element) {
/*
* (non-Javadoc)
* @see org.springframework.data.repository.config.AbstractRepositoryConfigDefinitionParser#postProcessBeanDefinition(org.springframework.data.repository.config.SingleRepositoryConfigInformation, org.springframework.beans.factory.support.BeanDefinitionBuilder, org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)
*/
@Override
protected void postProcessBeanDefinition(
MongoRepositoryConfiguration context,
BeanDefinitionBuilder builder, BeanDefinitionRegistry registry, Object beanSource) {
return new SimpleMongoRepositoryConfiguration(element);
}
builder.addPropertyReference("template", context.getMongoTemplateRef());
String mappingContextRef = getMappingContextReference(context, registry);
if (mappingContextRef != null) {
builder.addPropertyReference("mappingContext", mappingContextRef);
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.config.AbstractRepositoryConfigDefinitionParser#postProcessBeanDefinition(org.springframework.data.repository.config.SingleRepositoryConfigInformation, org.springframework.beans.factory.support.BeanDefinitionBuilder, org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)
*/
@Override
protected void postProcessBeanDefinition(MongoRepositoryConfiguration context, BeanDefinitionBuilder builder,
BeanDefinitionRegistry registry, Object beanSource) {
/**
* Returns the bean name of a {@link MappingContext} to be wired. Will inspect the namespace attribute first and if no
* config is found in that place it will try to lookup the default one. Will return {@literal null} if neither one is
* available.
*
* @param config
* @param registry
* @return
*/
private String getMappingContextReference(MongoRepositoryConfiguration config, BeanDefinitionRegistry registry) {
String contextRef = config.getMappingContextRef();
if (contextRef != null) {
return contextRef;
}
try {
registry.getBeanDefinition(MAPPING_CONTEXT_DEFAULT);
return MAPPING_CONTEXT_DEFAULT;
} catch(NoSuchBeanDefinitionException e) {
return null;
}
}
builder.addPropertyReference("template", context.getMongoTemplateRef());
String mappingContextRef = getMappingContextReference(context, registry);
if (mappingContextRef != null) {
builder.addPropertyReference("mappingContext", mappingContextRef);
}
}
/**
* Returns the bean name of a {@link MappingContext} to be wired. Will inspect the namespace attribute first and if no
* config is found in that place it will try to lookup the default one. Will return {@literal null} if neither one is
* available.
*
* @param config
* @param registry
* @return
*/
private String getMappingContextReference(MongoRepositoryConfiguration config, BeanDefinitionRegistry registry) {
String contextRef = config.getMappingContextRef();
if (contextRef != null) {
return contextRef;
}
try {
registry.getBeanDefinition(MAPPING_CONTEXT_DEFAULT);
return MAPPING_CONTEXT_DEFAULT;
} catch (NoSuchBeanDefinitionException e) {
return null;
}
}
}

View File

@@ -17,25 +17,23 @@ package org.springframework.data.document.mongodb.config;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
/**
* {@link org.springframework.beans.factory.xml.NamespaceHandler} for Mongo DB
* based repositories.
*
* {@link org.springframework.beans.factory.xml.NamespaceHandler} for Mongo DB based repositories.
*
* @author Oliver Gierke
*/
public class MongoRepositoryNamespaceHandler extends NamespaceHandlerSupport {
/*
* (non-Javadoc)
*
* @see org.springframework.beans.factory.xml.NamespaceHandler#init()
*/
public void init() {
/*
* (non-Javadoc)
*
* @see org.springframework.beans.factory.xml.NamespaceHandler#init()
*/
public void init() {
registerBeanDefinitionParser("repositories", new MongoRepositoryConfigParser());
registerBeanDefinitionParser("mapping-converter", new MappingMongoConverterParser());
registerBeanDefinitionParser("mongo", new MongoParser());
registerBeanDefinitionParser("jmx", new MongoJmxParser());
}
registerBeanDefinitionParser("repositories", new MongoRepositoryConfigParser());
registerBeanDefinitionParser("mapping-converter", new MappingMongoConverterParser());
registerBeanDefinitionParser("mongo", new MongoParser());
registerBeanDefinitionParser("jmx", new MongoJmxParser());
}
}

View File

@@ -23,180 +23,160 @@ import org.springframework.data.repository.config.SingleRepositoryConfigInformat
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* {@link RepositoryConfig} implementation to create
* {@link MongoRepositoryConfiguration} instances for both automatic and manual
* configuration.
*
* {@link RepositoryConfig} implementation to create {@link MongoRepositoryConfiguration} instances for both automatic
* and manual configuration.
*
* @author Oliver Gierke
*/
public class SimpleMongoRepositoryConfiguration extends RepositoryConfig<SimpleMongoRepositoryConfiguration.MongoRepositoryConfiguration, SimpleMongoRepositoryConfiguration> {
public class SimpleMongoRepositoryConfiguration
extends
RepositoryConfig<SimpleMongoRepositoryConfiguration.MongoRepositoryConfiguration, SimpleMongoRepositoryConfiguration> {
private static final String MONGO_TEMPLATE_REF = "mongo-template-ref";
private static final String DEFAULT_MONGO_TEMPLATE_REF = "mongoTemplate";
private static final String MAPPING_CONTEXT_REF = "mongo-mapping-context-ref";
private static final String MONGO_TEMPLATE_REF = "mongo-template-ref";
private static final String DEFAULT_MONGO_TEMPLATE_REF = "mongoTemplate";
private static final String MAPPING_CONTEXT_REF = "mongo-mapping-context-ref";
/**
* Creates a new {@link SimpleMongoRepositoryConfiguration} for the given
* {@link Element}.
*
* @param repositoriesElement
*/
protected SimpleMongoRepositoryConfiguration(Element repositoriesElement) {
/**
* Creates a new {@link SimpleMongoRepositoryConfiguration} for the given {@link Element}.
*
* @param repositoriesElement
*/
protected SimpleMongoRepositoryConfiguration(Element repositoriesElement) {
super(repositoriesElement, MongoRepositoryFactoryBean.class.getName());
}
super(repositoriesElement, MongoRepositoryFactoryBean.class.getName());
}
/**
* Returns the bean name of the {@link org.springframework.data.document.mongodb.MongoTemplate} to be referenced.
*
* @return
*/
public String getMongoTemplateRef() {
/**
* Returns the bean name of the {@link org.springframework.data.document.mongodb.MongoTemplate} to be referenced.
*
* @return
*/
public String getMongoTemplateRef() {
String templateRef = getSource().getAttribute(MONGO_TEMPLATE_REF);
return StringUtils.hasText(templateRef) ? templateRef : DEFAULT_MONGO_TEMPLATE_REF;
}
String templateRef = getSource().getAttribute(MONGO_TEMPLATE_REF);
return StringUtils.hasText(templateRef) ? templateRef
: DEFAULT_MONGO_TEMPLATE_REF;
}
public String getMappingContextRef() {
String attribute = getSource().getAttribute(MAPPING_CONTEXT_REF);
return StringUtils.hasText(attribute) ? attribute : null;
}
public String getMappingContextRef() {
String attribute = getSource().getAttribute(MAPPING_CONTEXT_REF);
return StringUtils.hasText(attribute) ? attribute : null;
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.config.GlobalRepositoryConfigInformation
* #getAutoconfigRepositoryInformation(java.lang.String)
*/
public MongoRepositoryConfiguration getAutoconfigRepositoryInformation(
String interfaceName) {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.config.GlobalRepositoryConfigInformation
* #getAutoconfigRepositoryInformation(java.lang.String)
*/
public MongoRepositoryConfiguration getAutoconfigRepositoryInformation(String interfaceName) {
return new AutomaticMongoRepositoryConfiguration(interfaceName, this);
}
return new AutomaticMongoRepositoryConfiguration(interfaceName, this);
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.config.RepositoryConfig#
* createSingleRepositoryConfigInformationFor(org.w3c.dom.Element)
*/
@Override
protected MongoRepositoryConfiguration createSingleRepositoryConfigInformationFor(Element element) {
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.config.RepositoryConfig#
* createSingleRepositoryConfigInformationFor(org.w3c.dom.Element)
*/
@Override
protected MongoRepositoryConfiguration createSingleRepositoryConfigInformationFor(
Element element) {
return new ManualMongoRepositoryConfiguration(element, this);
}
return new ManualMongoRepositoryConfiguration(element, this);
}
/**
* Simple interface for configuration values specific to Mongo repositories.
*
* @author Oliver Gierke
*/
public interface MongoRepositoryConfiguration extends
SingleRepositoryConfigInformation<SimpleMongoRepositoryConfiguration> {
/**
* Simple interface for configuration values specific to Mongo repositories.
*
* @author Oliver Gierke
*/
public interface MongoRepositoryConfiguration
extends
SingleRepositoryConfigInformation<SimpleMongoRepositoryConfiguration> {
String getMongoTemplateRef();
String getMongoTemplateRef();
String getMappingContextRef();
}
String getMappingContextRef();
}
/**
* Implements manual lookup of the additional attributes.
*
* @author Oliver Gierke
*/
private static class ManualMongoRepositoryConfiguration
extends
ManualRepositoryConfigInformation<SimpleMongoRepositoryConfiguration>
implements MongoRepositoryConfiguration {
/**
* Implements manual lookup of the additional attributes.
*
* @author Oliver Gierke
*/
private static class ManualMongoRepositoryConfiguration extends
ManualRepositoryConfigInformation<SimpleMongoRepositoryConfiguration> implements MongoRepositoryConfiguration {
/**
* Creates a new {@link ManualMongoRepositoryConfiguration} for the
* given {@link Element} and parent.
*
* @param element
* @param parent
*/
public ManualMongoRepositoryConfiguration(Element element,
SimpleMongoRepositoryConfiguration parent) {
/**
* Creates a new {@link ManualMongoRepositoryConfiguration} for the given {@link Element} and parent.
*
* @param element
* @param parent
*/
public ManualMongoRepositoryConfiguration(Element element, SimpleMongoRepositoryConfiguration parent) {
super(element, parent);
}
super(element, parent);
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.document.mongodb.repository.config.
* SimpleMongoRepositoryConfiguration
* .MongoRepositoryConfiguration#getMongoTemplateRef()
*/
public String getMongoTemplateRef() {
/*
* (non-Javadoc)
*
* @see org.springframework.data.document.mongodb.repository.config.
* SimpleMongoRepositoryConfiguration
* .MongoRepositoryConfiguration#getMongoTemplateRef()
*/
public String getMongoTemplateRef() {
return getAttribute(MONGO_TEMPLATE_REF);
}
return getAttribute(MONGO_TEMPLATE_REF);
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.config.SimpleMongoRepositoryConfiguration.MongoRepositoryConfiguration#getMappingContextRef()
*/
public String getMappingContextRef() {
return getAttribute(MAPPING_CONTEXT_REF);
}
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.config.SimpleMongoRepositoryConfiguration.MongoRepositoryConfiguration#getMappingContextRef()
*/
public String getMappingContextRef() {
return getAttribute(MAPPING_CONTEXT_REF);
}
}
/**
* Implements the lookup of the additional attributes during automatic
* configuration.
*
* @author Oliver Gierke
*/
private static class AutomaticMongoRepositoryConfiguration
extends
AutomaticRepositoryConfigInformation<SimpleMongoRepositoryConfiguration>
implements MongoRepositoryConfiguration {
/**
* Implements the lookup of the additional attributes during automatic configuration.
*
* @author Oliver Gierke
*/
private static class AutomaticMongoRepositoryConfiguration extends
AutomaticRepositoryConfigInformation<SimpleMongoRepositoryConfiguration> implements MongoRepositoryConfiguration {
/**
* Creates a new {@link AutomaticMongoRepositoryConfiguration} for the
* given interface and parent.
*
* @param interfaceName
* @param parent
*/
public AutomaticMongoRepositoryConfiguration(String interfaceName,
SimpleMongoRepositoryConfiguration parent) {
/**
* Creates a new {@link AutomaticMongoRepositoryConfiguration} for the given interface and parent.
*
* @param interfaceName
* @param parent
*/
public AutomaticMongoRepositoryConfiguration(String interfaceName, SimpleMongoRepositoryConfiguration parent) {
super(interfaceName, parent);
}
super(interfaceName, parent);
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.document.mongodb.repository.config.
* SimpleMongoRepositoryConfiguration
* .MongoRepositoryConfiguration#getMongoTemplateRef()
*/
public String getMongoTemplateRef() {
/*
* (non-Javadoc)
*
* @see org.springframework.data.document.mongodb.repository.config.
* SimpleMongoRepositoryConfiguration
* .MongoRepositoryConfiguration#getMongoTemplateRef()
*/
public String getMongoTemplateRef() {
return getParent().getMongoTemplateRef();
}
return getParent().getMongoTemplateRef();
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.config.SimpleMongoRepositoryConfiguration.MongoRepositoryConfiguration#getMappingContextRef()
*/
public String getMappingContextRef() {
return getParent().getMappingContextRef();
}
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.config.SimpleMongoRepositoryConfiguration.MongoRepositoryConfiguration#getMappingContextRef()
*/
public String getMappingContextRef() {
return getParent().getMappingContextRef();
}
}
}

View File

@@ -2,3 +2,4 @@
* Spring XML namespace configuration for MongoDB specific repositories.
*/
package org.springframework.data.document.mongodb.config;

View File

@@ -72,19 +72,22 @@ import org.springframework.expression.spel.support.StandardEvaluationContext;
/**
* {@link MongoConverter} that uses a {@link MappingContext} to do sophisticated mapping of domain objects to
* {@link DBObject}.
*
*
* @author Jon Brisbin <jbrisbin@vmware.com>
* @author Oliver Gierke
*/
public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware, InitializingBean {
public static final String CUSTOM_TYPE_KEY = "_class";
@SuppressWarnings({"unchecked"})
private static final List<Class<?>> MONGO_TYPES = Arrays.asList(Number.class, Date.class, String.class, DBObject.class);
private static final List<Class<?>> VALID_ID_TYPES = Arrays.asList(new Class<?>[]{ObjectId.class, String.class, BigInteger.class, byte[].class});
@SuppressWarnings({ "unchecked" })
private static final List<Class<?>> MONGO_TYPES = Arrays.asList(Number.class, Date.class, String.class,
DBObject.class);
private static final List<Class<?>> VALID_ID_TYPES = Arrays.asList(new Class<?>[] { ObjectId.class, String.class,
BigInteger.class, byte[].class });
protected static final Log log = LogFactory.getLog(MappingMongoConverter.class);
protected final GenericConversionService conversionService = ConversionServiceFactory.createDefaultConversionService();
protected final GenericConversionService conversionService = ConversionServiceFactory
.createDefaultConversionService();
protected final Set<ConvertiblePair> customTypeMapping = new HashSet<ConvertiblePair>();
protected final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
protected SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
@@ -95,10 +98,11 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
/**
* Creates a new {@link MappingMongoConverter} with the given {@link MappingContext}.
*
*
* @param mappingContext
*/
public MappingMongoConverter(MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
public MappingMongoConverter(
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
this.mappingContext = mappingContext;
this.conversionService.removeConvertible(Object.class, String.class);
}
@@ -106,7 +110,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
/**
* Add custom {@link Converter} or {@link ConverterFactory} instances to be used that will take presidence over
* metadata driven conversion between of objects to/from DBObject
*
*
* @param converters
*/
public void setConverters(List<Converter<?, ?>> converters) {
@@ -120,7 +124,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
/**
* Inspects the given {@link Converter} for the types it can convert and registers the pair for custom type conversion
* in case the target type is a Mongo basic type.
*
*
* @param converter
*/
private void registerConverter(Converter<?, ?> converter) {
@@ -177,50 +181,51 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
public <S extends Object> S read(Class<S> clazz, final DBObject dbo) {
return read(ClassTypeInformation.from(clazz), dbo);
}
@SuppressWarnings("unchecked")
protected <S extends Object> S read(TypeInformation<S> type, DBObject dbo) {
if (null == dbo) {
return null;
}
TypeInformation<? extends S> typeToUse = getMoreConcreteTargetType(dbo, type);
Class<? extends S> rawType = typeToUse.getType();
Class<?> customTarget = getCustomTarget(rawType, DBObject.class);
protected <S extends Object> S read(TypeInformation<S> type, DBObject dbo) {
if (customTarget != null) {
return conversionService.convert(dbo, rawType);
}
if (null == dbo) {
return null;
}
if (typeToUse.isCollectionLike() && dbo instanceof BasicDBList) {
List<Object> l = new ArrayList<Object>();
BasicDBList dbList = (BasicDBList) dbo;
for (Object o : dbList) {
if (o instanceof DBObject) {
Object newObj = read(typeToUse.getComponentType(), (DBObject) o);
Class<?> rawComponentType = typeToUse.getComponentType().getType();
if (newObj.getClass().isAssignableFrom(rawComponentType)) {
l.add(newObj);
} else {
l.add(conversionService.convert(newObj, rawComponentType));
}
} else {
l.add(o);
}
}
return conversionService.convert(l, rawType);
}
TypeInformation<? extends S> typeToUse = getMoreConcreteTargetType(dbo, type);
Class<? extends S> rawType = typeToUse.getType();
Class<?> customTarget = getCustomTarget(rawType, DBObject.class);
// Retrieve persistent entity info
MongoPersistentEntity<S> persistentEntity = (MongoPersistentEntity<S>) mappingContext.getPersistentEntity(typeToUse);
if (persistentEntity == null) {
throw new MappingException("No mapping metadata found for " + rawType.getName());
}
if (customTarget != null) {
return conversionService.convert(dbo, rawType);
}
return read(persistentEntity, dbo);
if (typeToUse.isCollectionLike() && dbo instanceof BasicDBList) {
List<Object> l = new ArrayList<Object>();
BasicDBList dbList = (BasicDBList) dbo;
for (Object o : dbList) {
if (o instanceof DBObject) {
Object newObj = read(typeToUse.getComponentType(), (DBObject) o);
Class<?> rawComponentType = typeToUse.getComponentType().getType();
if (newObj.getClass().isAssignableFrom(rawComponentType)) {
l.add(newObj);
} else {
l.add(conversionService.convert(newObj, rawComponentType));
}
} else {
l.add(o);
}
}
return conversionService.convert(l, rawType);
}
// Retrieve persistent entity info
MongoPersistentEntity<S> persistentEntity = (MongoPersistentEntity<S>) mappingContext
.getPersistentEntity(typeToUse);
if (persistentEntity == null) {
throw new MappingException("No mapping metadata found for " + rawType.getName());
}
return read(persistentEntity, dbo);
}
private <S extends Object> S read(final MongoPersistentEntity<S> entity, final DBObject dbo) {
@@ -230,7 +235,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
spelCtx.setBeanResolver(new BeanFactoryResolver(applicationContext));
}
if (!(dbo instanceof BasicDBList)) {
String[] keySet = dbo.keySet().toArray(new String[]{});
String[] keySet = dbo.keySet().toArray(new String[] {});
for (String key : keySet) {
spelCtx.setVariable(key, dbo.get(key));
}
@@ -240,7 +245,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
final MongoPersistentProperty idProperty = entity.getIdProperty();
final S instance = constructInstance(entity, new PreferredConstructor.ParameterValueProvider() {
@SuppressWarnings("unchecked")
public <T> T getParameterValue(PreferredConstructor.Parameter<T> parameter) {
public <T> T getParameterValue(PreferredConstructor.Parameter<T> parameter) {
String name = parameter.getName();
TypeInformation<T> type = parameter.getType();
Class<T> rawType = parameter.getRawType();
@@ -269,17 +274,17 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
// Set properties not already set in the constructor
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
public void doWithPersistentProperty(MongoPersistentProperty prop) {
boolean isConstructorProperty = ctorParamNames.contains(prop.getName());
boolean hasValueForProperty = dbo.containsField(prop.getKey());
boolean isConstructorProperty = ctorParamNames.contains(prop.getName());
boolean hasValueForProperty = dbo.containsField(prop.getKey());
if (!hasValueForProperty || isConstructorProperty) {
return;
}
Object obj = getValueInternal(prop, dbo, spelCtx, prop.getSpelExpression());
try {
setProperty(instance, prop, obj, useFieldAccessOnly);
setProperty(instance, prop, obj, useFieldAccessOnly);
} catch (IllegalAccessException e) {
throw new MappingException(e.getMessage(), e);
} catch (InvocationTargetException e) {
@@ -306,56 +311,56 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return instance;
}
/**
* Root entry method into write conversion. Adds a type discriminator to the {@link DBObject}. Shouldn't be called for
* nested conversions.
*
* @see org.springframework.data.document.mongodb.MongoWriter#write(java.lang.Object, com.mongodb.DBObject)
*/
public void write(final Object obj, final DBObject dbo) {
/**
* Root entry method into write conversion. Adds a type discriminator to the {@link DBObject}. Shouldn't be called for
* nested conversions.
*
* @see org.springframework.data.document.mongodb.MongoWriter#write(java.lang.Object, com.mongodb.DBObject)
*/
public void write(final Object obj, final DBObject dbo) {
if (null == obj) {
return;
}
boolean handledByCustomConverter = getCustomTarget(obj.getClass(), DBObject.class) != null;
if (!handledByCustomConverter) {
dbo.put(CUSTOM_TYPE_KEY, obj.getClass().getName());
dbo.put(CUSTOM_TYPE_KEY, obj.getClass().getName());
}
writeInternal(obj, dbo);
}
/**
* Internal write conversion method which should be used for nested invocations.
*
* @param obj
* @param dbo
*/
/**
* Internal write conversion method which should be used for nested invocations.
*
* @param obj
* @param dbo
*/
@SuppressWarnings("unchecked")
protected void writeInternal(final Object obj, final DBObject dbo) {
if (null == obj) {
return;
}
protected void writeInternal(final Object obj, final DBObject dbo) {
Class<?> customTarget = getCustomTarget(obj.getClass(), DBObject.class);
if (null == obj) {
return;
}
if (customTarget != null) {
DBObject result = conversionService.convert(obj, DBObject.class);
dbo.putAll(result);
return;
}
if (Map.class.isAssignableFrom(obj.getClass())) {
writeMapInternal((Map<Object, Object>) obj, dbo);
return;
}
Class<?> customTarget = getCustomTarget(obj.getClass(), DBObject.class);
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(obj.getClass());
writeInternal(obj, dbo, entity);
}
if (customTarget != null) {
DBObject result = conversionService.convert(obj, DBObject.class);
dbo.putAll(result);
return;
}
if (Map.class.isAssignableFrom(obj.getClass())) {
writeMapInternal((Map<Object, Object>) obj, dbo);
return;
}
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(obj.getClass());
writeInternal(obj, dbo, entity);
}
protected void writeInternal(final Object obj, final DBObject dbo, MongoPersistentEntity<?> entity) {
@@ -383,7 +388,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
dbo.put("_id", idObj);
} else {
if (!VALID_ID_TYPES.contains(idProperty.getType())) {
throw new MappingException("Invalid data type " + idProperty.getType().getName() + " for Id property. Should be one of " + VALID_ID_TYPES);
throw new MappingException("Invalid data type " + idProperty.getType().getName()
+ " for Id property. Should be one of " + VALID_ID_TYPES);
}
}
}
@@ -413,7 +419,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
entity.doWithAssociations(new AssociationHandler<MongoPersistentProperty>() {
public void doWithAssociation(Association<MongoPersistentProperty> association) {
MongoPersistentProperty inverseProp = association.getInverse();
MongoPersistentProperty inverseProp = association.getInverse();
Class<?> type = inverseProp.getType();
Object propertyObj;
try {
@@ -456,10 +462,10 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
setConversionService(conversionService);
}
@SuppressWarnings({"unchecked"})
@SuppressWarnings({ "unchecked" })
protected void writePropertyInternal(MongoPersistentProperty prop, Object obj, DBObject dbo) {
org.springframework.data.document.mongodb.mapping.DBRef dbref = prop.getField()
.getAnnotation(org.springframework.data.document.mongodb.mapping.DBRef.class);
org.springframework.data.document.mongodb.mapping.DBRef dbref = prop.getField().getAnnotation(
org.springframework.data.document.mongodb.mapping.DBRef.class);
String name = prop.getName();
Class<?> type = prop.getType();
@@ -542,16 +548,15 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
Object key = entry.getKey();
Object val = entry.getValue();
if (isSimpleType(key.getClass())) {
// Don't use conversion service here as removal of ObjectToString converter results in some primitive types not
// being convertable
// Don't use conversion service here as removal of ObjectToString converter results in some primitive types not
// being convertable
String simpleKey = key.toString();
if (isSimpleType(val.getClass())) {
dbo.put(simpleKey, val);
} else {
DBObject newDbo = new BasicDBObject();
Class<?> componentType = val.getClass();
if (componentType.isArray()
|| componentType.isAssignableFrom(Collection.class)
if (componentType.isArray() || componentType.isAssignableFrom(Collection.class)
|| componentType.isAssignableFrom(List.class)) {
Class<?> ctype = val.getClass().getComponentType();
dbo.put("_class", (null != ctype ? ctype.getName() : componentType.getName()));
@@ -600,15 +605,16 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return new DBRef(db, collection, id);
}
@SuppressWarnings({"unchecked"})
protected Object getValueInternal(MongoPersistentProperty prop, DBObject dbo, StandardEvaluationContext ctx, String spelExpr) {
@SuppressWarnings({ "unchecked" })
protected Object getValueInternal(MongoPersistentProperty prop, DBObject dbo, StandardEvaluationContext ctx,
String spelExpr) {
Object o;
if (null != spelExpr) {
Expression x = spelExpressionParser.parseExpression(spelExpr);
o = x.getValue(ctx);
} else {
Object dbObj = dbo.get(prop.getKey());
if (dbObj == null) {
@@ -636,10 +642,10 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
if (entry.getKey().equals(CUSTOM_TYPE_KEY)) {
continue;
}
Class<?> keyType = prop.getComponentType();
Object key = conversionService.convert(entry.getKey(), keyType);
if (null != entry.getValue() && entry.getValue() instanceof DBObject) {
m.put(key, read((null != toType ? toType : prop.getMapValueType()), (DBObject) entry.getValue()));
} else {
@@ -688,7 +694,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
/**
* Returns the type to be used to convert the DBObject given to.
*
*
* @param dbObject
* @return
*/
@@ -706,21 +712,21 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
}
/**
* Inspects the a custom class definition stored inside the given {@link DBObject} and returns that in case it's a
* subtype of the given basic one.
*
* @param dbObject
* @param basicType
* @return
*/
/**
* Inspects the a custom class definition stored inside the given {@link DBObject} and returns that in case it's a
* subtype of the given basic one.
*
* @param dbObject
* @param basicType
* @return
*/
@SuppressWarnings("unchecked")
private <S> TypeInformation<? extends S> getMoreConcreteTargetType(DBObject dbObject, TypeInformation<S> basicType) {
Class<?> documentsTargetType = findTypeToBeUsed(dbObject);
Class<S> rawType = basicType.getType();
boolean isMoreConcreteCustomType = documentsTargetType != null && rawType.isAssignableFrom(documentsTargetType);
return isMoreConcreteCustomType ? (TypeInformation<? extends S>) ClassTypeInformation.from(documentsTargetType)
: basicType;
private <S> TypeInformation<? extends S> getMoreConcreteTargetType(DBObject dbObject, TypeInformation<S> basicType) {
Class<?> documentsTargetType = findTypeToBeUsed(dbObject);
Class<S> rawType = basicType.getType();
boolean isMoreConcreteCustomType = documentsTargetType != null && rawType.isAssignableFrom(documentsTargetType);
return isMoreConcreteCustomType ? (TypeInformation<? extends S>) ClassTypeInformation.from(documentsTargetType)
: basicType;
}
protected <T> List<?> unwrapList(BasicDBList dbList, TypeInformation<T> targetType) {

View File

@@ -28,67 +28,67 @@ import org.springframework.util.Assert;
/**
* Custom Mongo specific {@link BeanWrapper} to allow access to bean properties via {@link MongoPropertyDescriptor}s.
*
*
* @author Oliver Gierke
*/
class MongoBeanWrapper {
private final ConfigurablePropertyAccessor accessor;
private final MongoPropertyDescriptors descriptors;
private final boolean fieldAccess;
private final ConfigurablePropertyAccessor accessor;
private final MongoPropertyDescriptors descriptors;
private final boolean fieldAccess;
/**
* Creates a new {@link MongoBeanWrapper} for the given target object and {@link ConversionService}.
*
* @param target
* @param conversionService
* @param fieldAccess
*/
public MongoBeanWrapper(Object target, ConversionService conversionService, boolean fieldAccess) {
/**
* Creates a new {@link MongoBeanWrapper} for the given target object and {@link ConversionService}.
*
* @param target
* @param conversionService
* @param fieldAccess
*/
public MongoBeanWrapper(Object target, ConversionService conversionService, boolean fieldAccess) {
Assert.notNull(target);
Assert.notNull(conversionService);
Assert.notNull(target);
Assert.notNull(conversionService);
this.fieldAccess = fieldAccess;
this.accessor = fieldAccess ? forDirectFieldAccess(target) : forBeanPropertyAccess(target);
this.accessor.setConversionService(conversionService);
this.descriptors = new MongoPropertyDescriptors(target.getClass());
}
this.fieldAccess = fieldAccess;
this.accessor = fieldAccess ? forDirectFieldAccess(target) : forBeanPropertyAccess(target);
this.accessor.setConversionService(conversionService);
this.descriptors = new MongoPropertyDescriptors(target.getClass());
}
/**
* Returns all {@link MongoPropertyDescriptors.MongoPropertyDescriptor}s for the underlying target object.
*
* @return
*/
public MongoPropertyDescriptors getDescriptors() {
return this.descriptors;
}
/**
* Returns all {@link MongoPropertyDescriptors.MongoPropertyDescriptor}s for the underlying target object.
*
* @return
*/
public MongoPropertyDescriptors getDescriptors() {
return this.descriptors;
}
/**
* Returns the value of the underlying object for the given property.
*
* @param descriptor
* @return
*/
public Object getValue(MongoPropertyDescriptors.MongoPropertyDescriptor descriptor) {
Assert.notNull(descriptor);
return accessor.getPropertyValue(descriptor.getName());
}
/**
* Returns the value of the underlying object for the given property.
*
* @param descriptor
* @return
*/
public Object getValue(MongoPropertyDescriptors.MongoPropertyDescriptor descriptor) {
Assert.notNull(descriptor);
return accessor.getPropertyValue(descriptor.getName());
}
/**
* Sets the property of the underlying object to the given value.
*
* @param descriptor
* @param value
*/
public void setValue(MongoPropertyDescriptors.MongoPropertyDescriptor descriptor, Object value) {
Assert.notNull(descriptor);
try {
accessor.setPropertyValue(descriptor.getName(), value);
} catch (NotWritablePropertyException e) {
if (!fieldAccess) {
throw e;
}
}
}
/**
* Sets the property of the underlying object to the given value.
*
* @param descriptor
* @param value
*/
public void setValue(MongoPropertyDescriptors.MongoPropertyDescriptor descriptor, Object value) {
Assert.notNull(descriptor);
try {
accessor.setPropertyValue(descriptor.getName(), value);
} catch (NotWritablePropertyException e) {
if (!fieldAccess) {
throw e;
}
}
}
}

View File

@@ -23,29 +23,30 @@ import org.springframework.data.document.mongodb.mapping.MongoPersistentEntity;
import org.springframework.data.document.mongodb.mapping.MongoPersistentProperty;
import org.springframework.data.mapping.model.MappingContext;
public interface MongoConverter extends MongoWriter<Object>, MongoReader<Object> {
/**
* Converts the given {@link ObjectId} to the given target type.
*
* @param <T> the actual type to create
* @param id the source {@link ObjectId}
* @param targetType the target type to convert the {@link ObjectId} to
* @return
*/
public <T> T convertObjectId(ObjectId id, Class<T> targetType);
/**
* Converts the given {@link ObjectId} to the given target type.
*
* @param <T>
* the actual type to create
* @param id
* the source {@link ObjectId}
* @param targetType
* the target type to convert the {@link ObjectId} to
* @return
*/
public <T> T convertObjectId(ObjectId id, Class<T> targetType);
/**
* Returns the {@link ObjectId} instance for the given id.
*
* @param id
* @return
*/
public ObjectId convertObjectId(Object id);
/**
* Returns the {@link ObjectId} instance for the given id.
*
* @param id
* @return
*/
public ObjectId convertObjectId(Object id);
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> getMappingContext();
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> getMappingContext();
Object maybeConvertObject(Object obj);

View File

@@ -22,67 +22,67 @@ import org.springframework.core.convert.converter.Converter;
/**
* Wrapper class to contain useful {@link ObjectId}-to-something-and-back converters.
*
*
* @author Oliver Gierke
*/
abstract class ObjectIdConverters {
/**
* Private constructor to prevent instantiation.
*/
private ObjectIdConverters() {
}
/**
* Simple singleton to convert {@link ObjectId}s to their {@link String} representation.
*
* @author Oliver Gierke
*/
public static enum ObjectIdToStringConverter implements Converter<ObjectId, String> {
INSTANCE;
/**
* Private constructor to prevent instantiation.
*/
private ObjectIdConverters() {
public String convert(ObjectId id) {
return id.toString();
}
}
/**
* Simple singleton to convert {@link String}s to their {@link ObjectId} representation.
*
* @author Oliver Gierke
*/
public static enum StringToObjectIdConverter implements Converter<String, ObjectId> {
INSTANCE;
}
public ObjectId convert(String source) {
return new ObjectId(source);
}
}
/**
* Simple singleton to convert {@link ObjectId}s to their {@link java.math.BigInteger} representation.
*
* @author Oliver Gierke
*/
public static enum ObjectIdToBigIntegerConverter implements Converter<ObjectId, BigInteger> {
INSTANCE;
/**
* Simple singleton to convert {@link ObjectId}s to their {@link String} representation.
*
* @author Oliver Gierke
*/
public static enum ObjectIdToStringConverter implements Converter<ObjectId, String> {
INSTANCE;
public BigInteger convert(ObjectId source) {
return new BigInteger(source.toString(), 16);
}
}
/**
* Simple singleton to convert {@link BigInteger}s to their {@link ObjectId} representation.
*
* @author Oliver Gierke
*/
public static enum BigIntegerToObjectIdConverter implements Converter<BigInteger, ObjectId> {
INSTANCE;
public String convert(ObjectId id) {
return id.toString();
}
}
public ObjectId convert(BigInteger source) {
return new ObjectId(source.toString(16));
}
}
/**
* Simple singleton to convert {@link String}s to their {@link ObjectId} representation.
*
* @author Oliver Gierke
*/
public static enum StringToObjectIdConverter implements Converter<String, ObjectId> {
INSTANCE;
public ObjectId convert(String source) {
return new ObjectId(source);
}
}
/**
* Simple singleton to convert {@link ObjectId}s to their {@link java.math.BigInteger} representation.
*
* @author Oliver Gierke
*/
public static enum ObjectIdToBigIntegerConverter implements Converter<ObjectId, BigInteger> {
INSTANCE;
public BigInteger convert(ObjectId source) {
return new BigInteger(source.toString(), 16);
}
}
/**
* Simple singleton to convert {@link BigInteger}s to their {@link ObjectId} representation.
*
* @author Oliver Gierke
*/
public static enum BigIntegerToObjectIdConverter implements Converter<BigInteger, ObjectId> {
INSTANCE;
public ObjectId convert(BigInteger source) {
return new ObjectId(source.toString(16));
}
}
}

View File

@@ -64,7 +64,7 @@ import org.springframework.util.comparator.CompoundComparator;
/**
* Basic {@link MongoConverter} implementation to convert between domain classes and {@link DBObject}s.
*
*
* @author Mark Pollack
* @author Thomas Risberg
* @author Oliver Gierke
@@ -73,7 +73,8 @@ public class SimpleMongoConverter extends AbstractMongoConverter implements Init
private static final Log LOG = LogFactory.getLog(SimpleMongoConverter.class);
@SuppressWarnings("unchecked")
private static final List<Class<?>> MONGO_TYPES = Arrays.asList(Number.class, Date.class, String.class, DBObject.class);
private static final List<Class<?>> MONGO_TYPES = Arrays.asList(Number.class, Date.class, String.class,
DBObject.class);
private static final Set<String> SIMPLE_TYPES;
static {
@@ -165,9 +166,9 @@ public class SimpleMongoConverter extends AbstractMongoConverter implements Init
}
/**
* Add custom {@link Converter} or {@link ConverterFactory} instances to be used that will take presidence over
* using object traversal to convert and object to/from DBObject
*
* Add custom {@link Converter} or {@link ConverterFactory} instances to be used that will take presidence over using
* object traversal to convert and object to/from DBObject
*
* @param converters
*/
public void setConverters(Set<?> converters) {
@@ -232,7 +233,7 @@ public class SimpleMongoConverter extends AbstractMongoConverter implements Init
/**
* Writes the given value to the given {@link DBObject}. Will skip {@literal null} values.
*
*
* @param dbo
* @param keyToUse
* @param value
@@ -248,7 +249,7 @@ public class SimpleMongoConverter extends AbstractMongoConverter implements Init
/**
* Writes the given {@link CompoundComparator} value to the given {@link DBObject}.
*
*
* @param dbo
* @param keyToUse
* @param value
@@ -284,7 +285,7 @@ public class SimpleMongoConverter extends AbstractMongoConverter implements Init
/**
* Returns whether the {@link ConversionService} has a custom {@link Converter} registered that can convert the given
* object into one of the types supported by MongoDB.
*
*
* @param obj
* @return
*/
@@ -300,7 +301,7 @@ public class SimpleMongoConverter extends AbstractMongoConverter implements Init
/**
* Writes the given {@link Map} to the given {@link DBObject}.
*
*
* @param dbo
* @param mapKey
* @param map
@@ -335,7 +336,7 @@ public class SimpleMongoConverter extends AbstractMongoConverter implements Init
/**
* Writes the given array to the given {@link DBObject}.
*
*
* @param dbo
* @param keyToUse
* @param array
@@ -381,24 +382,20 @@ public class SimpleMongoConverter extends AbstractMongoConverter implements Init
Object value = source.get(keyToUse);
if (!isSimpleType(value.getClass())) {
if (value instanceof Object[]) {
bw.setValue(descriptor, readCollection(descriptor, Arrays.asList((Object[]) value))
.toArray());
bw.setValue(descriptor, readCollection(descriptor, Arrays.asList((Object[]) value)).toArray());
} else if (value instanceof BasicDBList) {
bw.setValue(descriptor, readCollection(descriptor, (BasicDBList) value));
} else if (value instanceof DBObject) {
bw.setValue(descriptor, readCompoundValue(descriptor, (DBObject) value));
} else {
LOG.warn("Unable to map compound DBObject field " + keyToUse + " to property "
+ descriptor.getName()
+ ". The field value should have been a 'DBObject.class' but was "
+ value.getClass().getName());
LOG.warn("Unable to map compound DBObject field " + keyToUse + " to property " + descriptor.getName()
+ ". The field value should have been a 'DBObject.class' but was " + value.getClass().getName());
}
} else {
bw.setValue(descriptor, value);
}
} else {
LOG.warn("Unable to map DBObject field " + keyToUse + " to property " + descriptor.getName()
+ ". Skipping.");
LOG.warn("Unable to map DBObject field " + keyToUse + " to property " + descriptor.getName() + ". Skipping.");
}
}
}
@@ -409,7 +406,7 @@ public class SimpleMongoConverter extends AbstractMongoConverter implements Init
/**
* Reads the given collection values (that are {@link DBObject}s potentially) into a {@link Collection} of domain
* objects.
*
*
* @param descriptor
* @param values
* @return
@@ -442,7 +439,7 @@ public class SimpleMongoConverter extends AbstractMongoConverter implements Init
/**
* Reads a compound value from the given {@link DBObject} for the given property.
*
*
* @param pd
* @param dbo
* @return
@@ -461,7 +458,7 @@ public class SimpleMongoConverter extends AbstractMongoConverter implements Init
/**
* Create a {@link Map} instance. Will return a {@link HashMap} by default. Subclasses might want to override this
* method to use a custom {@link Map} implementation.
*
*
* @return
*/
protected Map<String, Object> createMap() {
@@ -470,7 +467,7 @@ public class SimpleMongoConverter extends AbstractMongoConverter implements Init
/**
* Reads every key/value pair from the {@link DBObject} into a {@link Map} instance.
*
*
* @param pd
* @param dbo
* @param targetType
@@ -503,9 +500,11 @@ public class SimpleMongoConverter extends AbstractMongoConverter implements Init
/**
* Callback to allow customizing creation of a {@link MongoBeanWrapper}.
*
* @param target the target object to wrap
* @param fieldAccess whether to use field access or property access
*
* @param target
* the target object to wrap
* @param fieldAccess
* whether to use field access or property access
* @return
*/
protected MongoBeanWrapper createWrapper(Object target, boolean fieldAccess) {

View File

@@ -25,57 +25,57 @@ import org.springframework.util.Assert;
*/
public class Box {
private final Point first;
private final Point second;
private final Point first;
private final Point second;
public Box(Point lowerLeft, Point upperRight) {
Assert.notNull(lowerLeft);
Assert.notNull(upperRight);
this.first = lowerLeft;
this.second = upperRight;
}
public Box(Point lowerLeft, Point upperRight) {
Assert.notNull(lowerLeft);
Assert.notNull(upperRight);
this.first = lowerLeft;
this.second = upperRight;
}
public Box(double[] lowerLeft, double[] upperRight) {
Assert.isTrue(lowerLeft.length == 2, "Point array has to have 2 elements!");
Assert.isTrue(upperRight.length == 2, "Point array has to have 2 elements!");
this.first = new Point(lowerLeft[0], lowerLeft[1]);
this.second = new Point(upperRight[0], upperRight[1]);
}
public Box(double[] lowerLeft, double[] upperRight) {
Assert.isTrue(lowerLeft.length == 2, "Point array has to have 2 elements!");
Assert.isTrue(upperRight.length == 2, "Point array has to have 2 elements!");
this.first = new Point(lowerLeft[0], lowerLeft[1]);
this.second = new Point(upperRight[0], upperRight[1]);
}
public Point getLowerLeft() {
return first;
}
public Point getLowerLeft() {
return first;
}
public Point getUpperRight() {
return second;
}
public Point getUpperRight() {
return second;
}
@Override
public String toString() {
return String.format("Box [%s, %s]", first, second);
}
@Override
public String toString() {
return String.format("Box [%s, %s]", first, second);
}
@Override
public int hashCode() {
@Override
public int hashCode() {
int result = 31;
result += 17 * first.hashCode();
result += 17 * second.hashCode();
return result;
}
int result = 31;
result += 17 * first.hashCode();
result += 17 * second.hashCode();
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Box that = (Box) obj;
return this.first.equals(that.first) && this.second.equals(that.second);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Box that = (Box) obj;
return this.first.equals(that.first) && this.second.equals(that.second);
}
}

View File

@@ -19,35 +19,36 @@ import org.springframework.util.Assert;
/**
* Represents a geospatial circle value
*
* @author Mark Pollack
* @author Oliver Gierke
*/
public class Circle {
private Point center;
private double radius;
public Circle(Point center, double radius) {
Assert.notNull(center);
Assert.isTrue(radius >= 0, "Radius must not be negative!");
this.center = center;
this.radius = radius;
}
public Circle(double centerX, double centerY, double radius) {
this(new Point(centerX, centerY), radius);
}
private Point center;
private double radius;
public Point getCenter() {
return center;
}
public Circle(Point center, double radius) {
Assert.notNull(center);
Assert.isTrue(radius >= 0, "Radius must not be negative!");
this.center = center;
this.radius = radius;
}
public double getRadius() {
return radius;
}
public Circle(double centerX, double centerY, double radius) {
this(new Point(centerX, centerY), radius);
}
@Override
public String toString() {
return String.format("Circle [center=%s, radius=%d]", center, radius);
}
public Point getCenter() {
return center;
}
public double getRadius() {
return radius;
}
@Override
public String toString() {
return String.format("Circle [center=%s, radius=%d]", center, radius);
}
}

View File

@@ -26,70 +26,68 @@ import org.springframework.util.Assert;
*/
public class Point {
private final double x;
private final double y;
@PersistenceConstructor
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public Point(Point point) {
Assert.notNull(point);
this.x = point.x;
this.y = point.y;
}
private final double x;
private final double y;
public double getX() {
return x;
}
@PersistenceConstructor
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public double getY() {
return y;
}
public double[] asArray() {
return new double[] {x, y};
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(x);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(y);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
public Point(Point point) {
Assert.notNull(point);
this.x = point.x;
this.y = point.y;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Point other = (Point) obj;
if (Double.doubleToLongBits(x) != Double
.doubleToLongBits(other.x)) {
return false;
}
if (Double.doubleToLongBits(y) != Double
.doubleToLongBits(other.y)) {
return false;
}
return true;
}
public double getX() {
return x;
}
@Override
public String toString() {
return String.format("Point [latitude=%d, longitude=%d]", x, y);
}
public double getY() {
return y;
}
public double[] asArray() {
return new double[] { x, y };
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(x);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(y);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Point other = (Point) obj;
if (Double.doubleToLongBits(x) != Double.doubleToLongBits(other.x)) {
return false;
}
if (Double.doubleToLongBits(y) != Double.doubleToLongBits(other.y)) {
return false;
}
return true;
}
@Override
public String toString() {
return String.format("Point [latitude=%d, longitude=%d]", x, y);
}
}

View File

@@ -23,9 +23,10 @@ import java.lang.annotation.Target;
/**
* Mark a class to use compound indexes.
*
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
@Target({ElementType.TYPE})
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface CompoundIndex {

View File

@@ -24,10 +24,10 @@ import java.lang.annotation.Target;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
@Target({ElementType.TYPE})
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface CompoundIndexes {
CompoundIndex[] value();
CompoundIndex[] value();
}

View File

@@ -23,7 +23,7 @@ import java.lang.annotation.Target;
/**
* Mark a field to be indexed using MongoDB's geospatial indexing feature.
*
*
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
@Target(ElementType.FIELD)
@@ -32,35 +32,35 @@ public @interface GeoSpatialIndexed {
/**
* Name of the property in the document that contains the [x, y] or radial coordinates to index.
*
*
* @return
*/
String name() default "";
/**
* Name of the collection in which to create the index.
*
*
* @return
*/
String collection() default "";
/**
* Minimum value for indexed values.
*
*
* @return
*/
int min() default -180;
/**
* Maximum value for indexed values.
*
*
* @return
*/
int max() default 180;
/**
* Bits of precision for boundary calculations.
*
*
* @return
*/
int bits() default 26;

View File

@@ -23,8 +23,8 @@ import com.mongodb.DBObject;
*/
public interface IndexDefinition {
DBObject getIndexKeys();
DBObject getIndexKeys();
DBObject getIndexOptions();
DBObject getIndexOptions();
}

View File

@@ -20,6 +20,5 @@ package org.springframework.data.document.mongodb.index;
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public enum IndexDirection {
ASCENDING,
DESCENDING;
ASCENDING, DESCENDING;
}

View File

@@ -21,31 +21,31 @@ package org.springframework.data.document.mongodb.index;
*/
public abstract class IndexPredicate {
private String name;
private IndexDirection direction = IndexDirection.ASCENDING;
private boolean unique = false;
private String name;
private IndexDirection direction = IndexDirection.ASCENDING;
private boolean unique = false;
public String getName() {
return name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public IndexDirection getDirection() {
return direction;
}
public IndexDirection getDirection() {
return direction;
}
public void setDirection(IndexDirection direction) {
this.direction = direction;
}
public void setDirection(IndexDirection direction) {
this.direction = direction;
}
public boolean isUnique() {
return unique;
}
public boolean isUnique() {
return unique;
}
public void setUnique(boolean unique) {
this.unique = unique;
}
public void setUnique(boolean unique) {
this.unique = unique;
}
}

View File

@@ -22,22 +22,23 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Mark a field to be indexed using MongoDB's indexing feature.
* Mark a field to be indexed using MongoDB's indexing feature.
*
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Indexed {
boolean unique() default false;
boolean unique() default false;
IndexDirection direction() default IndexDirection.ASCENDING;
IndexDirection direction() default IndexDirection.ASCENDING;
boolean sparse() default false;
boolean sparse() default false;
boolean dropDups() default false;
boolean dropDups() default false;
String name() default "";
String name() default "";
String collection() default "";
String collection() default "";
}

View File

@@ -22,58 +22,58 @@ import org.springframework.data.mapping.model.PersistentEntity;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.StringUtils;
/**
* Mongo specific {@link PersistentEntity} implementation that adds Mongo specific meta-data such as the collection name
* and the like.
*
*
* @author Jon Brisbin <jbrisbin@vmware.com>
* @author Oliver Gierke
*/
public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, MongoPersistentProperty> implements MongoPersistentEntity<T> {
public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, MongoPersistentProperty> implements
MongoPersistentEntity<T> {
private final String collection;
private final boolean isRootEntity;
private final String collection;
private final boolean isRootEntity;
/**
* Creates a new {@link BasicMongoPersistentEntity} with the given {@link TypeInformation}. Will
* default the collection name to the entities simple type name.
*
* @param typeInformation
*/
public BasicMongoPersistentEntity(TypeInformation<T> typeInformation) {
super(typeInformation);
Class<?> rawType = typeInformation.getType();
String fallback = rawType.getSimpleName().toLowerCase();
if (rawType.isAnnotationPresent(Document.class)) {
Document d = rawType.getAnnotation(Document.class);
this.collection = StringUtils.hasText(d.collection()) ? d.collection() : fallback;
this.isRootEntity = true;
} else {
this.collection = fallback;
this.isRootEntity = false;
}
}
/**
* Creates a new {@link BasicMongoPersistentEntity} with the given {@link TypeInformation}. Will default the
* collection name to the entities simple type name.
*
* @param typeInformation
*/
public BasicMongoPersistentEntity(TypeInformation<T> typeInformation) {
/**
* Returns the collection the entity should be stored in.
*
* @return
*/
public String getCollection() {
return collection;
}
super(typeInformation);
/* (non-Javadoc)
* @see org.springframework.data.mapping.BasicPersistentEntity#verify()
*/
@Override
public void verify() {
if (isRootEntity && idProperty == null) {
throw new MappingException(String.format("Root entity %s has to have an id property!", getType().getName()));
}
}
Class<?> rawType = typeInformation.getType();
String fallback = rawType.getSimpleName().toLowerCase();
if (rawType.isAnnotationPresent(Document.class)) {
Document d = rawType.getAnnotation(Document.class);
this.collection = StringUtils.hasText(d.collection()) ? d.collection() : fallback;
this.isRootEntity = true;
} else {
this.collection = fallback;
this.isRootEntity = false;
}
}
/**
* Returns the collection the entity should be stored in.
*
* @return
*/
public String getCollection() {
return collection;
}
/* (non-Javadoc)
* @see org.springframework.data.mapping.BasicPersistentEntity#verify()
*/
@Override
public void verify() {
if (isRootEntity && idProperty == null) {
throw new MappingException(String.format("Root entity %s has to have an id property!", getType().getName()));
}
}
}

View File

@@ -28,76 +28,73 @@ import org.springframework.data.mapping.model.Association;
import com.mongodb.DBObject;
/**
* Mongo specific
* {@link org.springframework.data.mapping.model.PersistentProperty}
* implementation.
*
* Mongo specific {@link org.springframework.data.mapping.model.PersistentProperty} implementation.
*
* @author Oliver Gierke
*/
public class BasicMongoPersistentProperty extends AnnotationBasedPersistentProperty<MongoPersistentProperty> implements MongoPersistentProperty {
public class BasicMongoPersistentProperty extends AnnotationBasedPersistentProperty<MongoPersistentProperty> implements
MongoPersistentProperty {
private static final Set<Class<?>> SUPPORTED_ID_TYPES = new HashSet<Class<?>>();
private static final Set<String> SUPPORTED_ID_PROPERTY_NAMES = new HashSet<String>();
private static final Set<Class<?>> SUPPORTED_ID_TYPES = new HashSet<Class<?>>();
private static final Set<String> SUPPORTED_ID_PROPERTY_NAMES = new HashSet<String>();
static {
SUPPORTED_ID_TYPES.add(ObjectId.class);
SUPPORTED_ID_TYPES.add(String.class);
SUPPORTED_ID_TYPES.add(BigInteger.class);
static {
SUPPORTED_ID_TYPES.add(ObjectId.class);
SUPPORTED_ID_TYPES.add(String.class);
SUPPORTED_ID_TYPES.add(BigInteger.class);
SUPPORTED_ID_PROPERTY_NAMES.add("id");
SUPPORTED_ID_PROPERTY_NAMES.add("_id");
}
SUPPORTED_ID_PROPERTY_NAMES.add("id");
SUPPORTED_ID_PROPERTY_NAMES.add("_id");
}
/**
* Creates a new {@link BasicMongoPersistentProperty}.
*
* @param field
* @param propertyDescriptor
* @param owningTypeInformation
*/
public BasicMongoPersistentProperty(Field field,
PropertyDescriptor propertyDescriptor, MongoPersistentEntity<?> owner) {
super(field, propertyDescriptor, owner);
}
/* (non-Javadoc)
* @see org.springframework.data.mapping.FooBasicPersistentProperty#isAssociation()
*/
@Override
public boolean isAssociation() {
return field.isAnnotationPresent(DBRef.class) || super.isAssociation();
}
/**
* Creates a new {@link BasicMongoPersistentProperty}.
*
* @param field
* @param propertyDescriptor
* @param owningTypeInformation
*/
public BasicMongoPersistentProperty(Field field, PropertyDescriptor propertyDescriptor, MongoPersistentEntity<?> owner) {
super(field, propertyDescriptor, owner);
}
/**
* Also considers fields as id that are of supported id type and name.
*
* @see #SUPPORTED_ID_PROPERTY_NAMES
* @see #SUPPORTED_ID_TYPES
*/
@Override
public boolean isIdProperty() {
if (super.isIdProperty()) {
return true;
}
/* (non-Javadoc)
* @see org.springframework.data.mapping.FooBasicPersistentProperty#isAssociation()
*/
@Override
public boolean isAssociation() {
return field.isAnnotationPresent(DBRef.class) || super.isAssociation();
}
return SUPPORTED_ID_TYPES.contains(field.getType())
&& SUPPORTED_ID_PROPERTY_NAMES.contains(field.getName());
}
/**
* Returns the key to be used to store the value of the property inside a Mongo {@link DBObject}.
*
* @return
*/
public String getKey() {
return isIdProperty() ? "_id" : getName();
}
/* (non-Javadoc)
* @see org.springframework.data.mapping.AbstractPersistentProperty#createAssociation()
*/
@Override
protected Association<MongoPersistentProperty> createAssociation() {
return new Association<MongoPersistentProperty>(this, null);
}
/**
* Also considers fields as id that are of supported id type and name.
*
* @see #SUPPORTED_ID_PROPERTY_NAMES
* @see #SUPPORTED_ID_TYPES
*/
@Override
public boolean isIdProperty() {
if (super.isIdProperty()) {
return true;
}
return SUPPORTED_ID_TYPES.contains(field.getType()) && SUPPORTED_ID_PROPERTY_NAMES.contains(field.getName());
}
/**
* Returns the key to be used to store the value of the property inside a Mongo {@link DBObject}.
*
* @return
*/
public String getKey() {
return isIdProperty() ? "_id" : getName();
}
/* (non-Javadoc)
* @see org.springframework.data.mapping.AbstractPersistentProperty#createAssociation()
*/
@Override
protected Association<MongoPersistentProperty> createAssociation() {
return new Association<MongoPersistentProperty>(this, null);
}
}

View File

@@ -24,20 +24,19 @@ import java.lang.annotation.Target;
import org.springframework.data.annotation.Reference;
/**
* An annotation that indicates the annotated field is to be stored using a com.mongodb.DBRef
* An annotation that indicates the annotated field is to be stored using a com.mongodb.DBRef
*
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({
ElementType.FIELD
})
@Target({ ElementType.FIELD })
@Reference
public @interface DBRef {
String collection() default "";
String collection() default "";
String id() default "";
String id() default "";
String db() default "";
String db() default "";
}

View File

@@ -25,15 +25,14 @@ import org.springframework.data.annotation.Persistent;
/**
* Identifies a domain object to be persisted to MongoDB.
*
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
@Persistent
@Retention(RetentionPolicy.RUNTIME)
@Target({
ElementType.TYPE
})
@Target({ ElementType.TYPE })
public @interface Document {
String collection() default "";
String collection() default "";
}

View File

@@ -31,30 +31,31 @@ import org.springframework.data.util.TypeInformation;
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class MongoMappingContext extends AbstractMappingContext<BasicMongoPersistentEntity<?>, MongoPersistentProperty> {
public MongoMappingContext() {
augmentSimpleTypes();
}
public MongoMappingContext() {
augmentSimpleTypes();
}
protected void augmentSimpleTypes() {
// Augment simpleTypes with MongoDB-specific classes
Set<Class<?>> simpleTypes = MappingBeanHelper.getSimpleTypes();
simpleTypes.add(com.mongodb.DBRef.class);
simpleTypes.add(ObjectId.class);
simpleTypes.add(CodeWScope.class);
simpleTypes.add(Character.class);
simpleTypes.add(BigInteger.class);
}
protected void augmentSimpleTypes() {
// Augment simpleTypes with MongoDB-specific classes
Set<Class<?>> simpleTypes = MappingBeanHelper.getSimpleTypes();
simpleTypes.add(com.mongodb.DBRef.class);
simpleTypes.add(ObjectId.class);
simpleTypes.add(CodeWScope.class);
simpleTypes.add(Character.class);
simpleTypes.add(BigInteger.class);
}
@Override
public MongoPersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor, BasicMongoPersistentEntity<?> owner) {
return new BasicMongoPersistentProperty(field, descriptor, owner);
}
/* (non-Javadoc)
* @see org.springframework.data.mapping.BasicMappingContext#createPersistentEntity(org.springframework.data.util.TypeInformation, org.springframework.data.mapping.model.MappingContext)
*/
@Override
protected <T> BasicMongoPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
return new BasicMongoPersistentEntity<T>(typeInformation);
}
@Override
public MongoPersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor,
BasicMongoPersistentEntity<?> owner) {
return new BasicMongoPersistentProperty(field, descriptor, owner);
}
/* (non-Javadoc)
* @see org.springframework.data.mapping.BasicMappingContext#createPersistentEntity(org.springframework.data.util.TypeInformation, org.springframework.data.mapping.model.MappingContext)
*/
@Override
protected <T> BasicMongoPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
return new BasicMongoPersistentEntity<T>(typeInformation);
}
}

View File

@@ -3,10 +3,10 @@ package org.springframework.data.document.mongodb.mapping;
import org.springframework.data.mapping.model.PersistentEntity;
/**
*
*
* @author Oliver Gierke
*/
public interface MongoPersistentEntity<T> extends PersistentEntity<T, MongoPersistentProperty> {
String getCollection();
String getCollection();
}

View File

@@ -45,9 +45,9 @@ import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Component that inspects {@link BasicMongoPersistentEntity} instances contained in the given {@link MongoMappingContext}
* for indexing metadata and ensures the indexes to be available.
*
* Component that inspects {@link BasicMongoPersistentEntity} instances contained in the given
* {@link MongoMappingContext} for indexing metadata and ensures the indexes to be available.
*
* @author Jon Brisbin <jbrisbin@vmware.com>
* @author Oliver Gierke
*/
@@ -64,7 +64,7 @@ public class MongoPersistentEntityIndexCreator implements ApplicationListener<Ma
Assert.notNull(mongoTemplate);
Assert.notNull(mappingContext);
this.mongoTemplate = mongoTemplate;
for (MongoPersistentEntity<?> entity : mappingContext.getPersistentEntities()) {
checkForIndexes(entity);
}
@@ -92,7 +92,8 @@ public class MongoPersistentEntityIndexCreator implements ApplicationListener<Ma
if ("".equals(indexColl)) {
indexColl = entity.getCollection();
}
ensureIndex(indexColl, index.name(), index.def(), index.direction(), index.unique(), index.dropDups(), index.sparse());
ensureIndex(indexColl, index.name(), index.def(), index.direction(), index.unique(), index.dropDups(),
index.sparse());
if (log.isDebugEnabled()) {
log.debug("Created compound index " + index);
}
@@ -121,38 +122,32 @@ public class MongoPersistentEntityIndexCreator implements ApplicationListener<Ma
if (log.isDebugEnabled()) {
log.debug("Created property index " + index);
}
} else if (field.isAnnotationPresent(GeoSpatialIndexed.class)) {
} else if (field.isAnnotationPresent(GeoSpatialIndexed.class)) {
GeoSpatialIndexed index = field.getAnnotation(GeoSpatialIndexed.class);
GeoSpatialIndexed index = field.getAnnotation(GeoSpatialIndexed.class);
GeospatialIndex indexObject = new GeospatialIndex(StringUtils.hasText(index.name()) ? index.name() : field
.getName());
indexObject.withMin(index.min()).withMax(index.max());
GeospatialIndex indexObject = new GeospatialIndex(StringUtils.hasText(index.name()) ? index.name() : field
.getName());
indexObject.withMin(index.min()).withMax(index.max());
String collection = StringUtils.hasText(index.collection()) ? index.collection() : entity.getCollection();
mongoTemplate.ensureIndex(collection, indexObject);
String collection = StringUtils.hasText(index.collection()) ? index.collection() : entity.getCollection();
mongoTemplate.ensureIndex(collection, indexObject);
if (log.isDebugEnabled()) {
log.debug(String.format("Created %s for entity %s in collection %s! ", indexObject, entity.getType(),
collection));
}
}
if (log.isDebugEnabled()) {
log.debug(String.format("Created %s for entity %s in collection %s! ", indexObject, entity.getType(),
collection));
}
}
}
});
classesSeen.add(type);
}
}
protected void ensureIndex(String collection,
final String name,
final String def,
final IndexDirection direction,
final boolean unique,
final boolean dropDups,
final boolean sparse) {
protected void ensureIndex(String collection, final String name, final String def, final IndexDirection direction,
final boolean unique, final boolean dropDups, final boolean sparse) {
mongoTemplate.execute(collection, new CollectionCallback<Object>() {
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
DBObject defObj;
@@ -163,7 +158,7 @@ public class MongoPersistentEntityIndexCreator implements ApplicationListener<Ma
defObj.put(name, (direction == IndexDirection.ASCENDING ? 1 : -1));
}
DBObject opts = new BasicDBObject();
//opts.put("name", name + "_idx");
// opts.put("name", name + "_idx");
opts.put("dropDups", dropDups);
opts.put("sparse", sparse);
opts.put("unique", unique);

View File

@@ -18,12 +18,10 @@ package org.springframework.data.document.mongodb.mapping;
import org.springframework.data.mapping.model.PersistentProperty;
/**
* Mongo specific
* {@link org.springframework.data.mapping.model.PersistentProperty}
* implementation.
*
* Mongo specific {@link org.springframework.data.mapping.model.PersistentProperty} implementation.
*
* @author Oliver Gierke
*/
public interface MongoPersistentProperty extends PersistentProperty<MongoPersistentProperty> {
String getKey();
String getKey();
}

View File

@@ -27,79 +27,83 @@ import org.springframework.data.mapping.model.Association;
import org.springframework.data.util.TypeInformation;
/**
*
*
* @author Oliver Gierke
*/
public class SimpleMongoMappingContext extends AbstractMappingContext<SimpleMongoMappingContext.SimpleMongoPersistentEntity<?>, MongoPersistentProperty> {
public class SimpleMongoMappingContext extends
AbstractMappingContext<SimpleMongoMappingContext.SimpleMongoPersistentEntity<?>, MongoPersistentProperty> {
/* (non-Javadoc)
* @see org.springframework.data.mapping.BasicMappingContext#createPersistentEntity(org.springframework.data.util.TypeInformation)
*/
@Override
protected <T> SimpleMongoPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
return new SimpleMongoPersistentEntity<T>(typeInformation);
}
/* (non-Javadoc)
* @see org.springframework.data.mapping.BasicMappingContext#createPersistentEntity(org.springframework.data.util.TypeInformation)
*/
@Override
protected <T> SimpleMongoPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
return new SimpleMongoPersistentEntity<T>(typeInformation);
}
/* (non-Javadoc)
* @see org.springframework.data.mapping.BasicMappingContext#createPersistentProperty(java.lang.reflect.Field, java.beans.PropertyDescriptor, org.springframework.data.util.TypeInformation, org.springframework.data.mapping.BasicPersistentEntity)
*/
@Override
protected SimplePersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor, SimpleMongoPersistentEntity<?> owner) {
return new SimplePersistentProperty(field, descriptor, owner);
}
static class SimplePersistentProperty extends AbstractPersistentProperty<MongoPersistentProperty> implements MongoPersistentProperty {
private static final List<String> ID_FIELD_NAMES = Arrays.asList("id", "_id");
/* (non-Javadoc)
* @see org.springframework.data.mapping.BasicMappingContext#createPersistentProperty(java.lang.reflect.Field, java.beans.PropertyDescriptor, org.springframework.data.util.TypeInformation, org.springframework.data.mapping.BasicPersistentEntity)
*/
@Override
protected SimplePersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor,
SimpleMongoPersistentEntity<?> owner) {
return new SimplePersistentProperty(field, descriptor, owner);
}
/**
* Creates a new {@link SimplePersistentProperty}.
*
* @param field
* @param propertyDescriptor
* @param information
*/
public SimplePersistentProperty(Field field, PropertyDescriptor propertyDescriptor, MongoPersistentEntity<?> owner) {
super(field, propertyDescriptor, owner);
}
/* (non-Javadoc)
* @see org.springframework.data.mapping.BasicPersistentProperty#isIdProperty()
*/
public boolean isIdProperty() {
return ID_FIELD_NAMES.contains(field.getName());
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.mapping.MongoPersistentProperty#getKey()
*/
public String getKey() {
return isIdProperty() ? "_id" : getName();
}
/* (non-Javadoc)
* @see org.springframework.data.mapping.AbstractPersistentProperty#createAssociation()
*/
@Override
protected Association<MongoPersistentProperty> createAssociation() {
return new Association<MongoPersistentProperty>(this, null);
}
}
static class SimpleMongoPersistentEntity<T> extends BasicPersistentEntity<T, MongoPersistentProperty> implements MongoPersistentEntity<T> {
static class SimplePersistentProperty extends AbstractPersistentProperty<MongoPersistentProperty> implements
MongoPersistentProperty {
/**
* @param information
*/
public SimpleMongoPersistentEntity(TypeInformation<T> information) {
super(information);
}
private static final List<String> ID_FIELD_NAMES = Arrays.asList("id", "_id");
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.mapping.MongoPersistentEntity#getCollection()
*/
public String getCollection() {
return getType().getSimpleName();
}
}
/**
* Creates a new {@link SimplePersistentProperty}.
*
* @param field
* @param propertyDescriptor
* @param information
*/
public SimplePersistentProperty(Field field, PropertyDescriptor propertyDescriptor, MongoPersistentEntity<?> owner) {
super(field, propertyDescriptor, owner);
}
/* (non-Javadoc)
* @see org.springframework.data.mapping.BasicPersistentProperty#isIdProperty()
*/
public boolean isIdProperty() {
return ID_FIELD_NAMES.contains(field.getName());
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.mapping.MongoPersistentProperty#getKey()
*/
public String getKey() {
return isIdProperty() ? "_id" : getName();
}
/* (non-Javadoc)
* @see org.springframework.data.mapping.AbstractPersistentProperty#createAssociation()
*/
@Override
protected Association<MongoPersistentProperty> createAssociation() {
return new Association<MongoPersistentProperty>(this, null);
}
}
static class SimpleMongoPersistentEntity<T> extends BasicPersistentEntity<T, MongoPersistentProperty> implements
MongoPersistentEntity<T> {
/**
* @param information
*/
public SimpleMongoPersistentEntity(TypeInformation<T> information) {
super(information);
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.mapping.MongoPersistentEntity#getCollection()
*/
public String getCollection() {
return getType().getSimpleName();
}
}
}

View File

@@ -27,59 +27,59 @@ import org.springframework.context.ApplicationListener;
*/
public abstract class AbstractMappingEventListener<T extends ApplicationEvent, E> implements ApplicationListener<T> {
protected final Log log = LogFactory.getLog(getClass());
protected final Log log = LogFactory.getLog(getClass());
@SuppressWarnings({"unchecked"})
public void onApplicationEvent(T appEvent) {
if (appEvent instanceof MongoMappingEvent) {
try {
MongoMappingEvent<E> event = (MongoMappingEvent<E>) appEvent;
if (event instanceof BeforeConvertEvent) {
onBeforeConvert(event.getSource());
} else if (event instanceof BeforeSaveEvent) {
onBeforeSave(event.getSource(), event.getDBObject());
} else if (event instanceof AfterSaveEvent) {
onAfterSave(event.getSource(), event.getDBObject());
} else if (event instanceof AfterLoadEvent) {
onAfterLoad((DBObject) event.getSource());
} else if (event instanceof AfterConvertEvent) {
onAfterConvert(event.getDBObject(), event.getSource());
}
} catch (ClassCastException e) {
// Not a mapping event for this entity, apparently.
// Just ignore it for now.
}
}
}
@SuppressWarnings({ "unchecked" })
public void onApplicationEvent(T appEvent) {
if (appEvent instanceof MongoMappingEvent) {
try {
MongoMappingEvent<E> event = (MongoMappingEvent<E>) appEvent;
if (event instanceof BeforeConvertEvent) {
onBeforeConvert(event.getSource());
} else if (event instanceof BeforeSaveEvent) {
onBeforeSave(event.getSource(), event.getDBObject());
} else if (event instanceof AfterSaveEvent) {
onAfterSave(event.getSource(), event.getDBObject());
} else if (event instanceof AfterLoadEvent) {
onAfterLoad((DBObject) event.getSource());
} else if (event instanceof AfterConvertEvent) {
onAfterConvert(event.getDBObject(), event.getSource());
}
} catch (ClassCastException e) {
// Not a mapping event for this entity, apparently.
// Just ignore it for now.
}
}
}
public void onBeforeConvert(E source) {
if (log.isDebugEnabled()) {
log.debug("onBeforeConvert(" + source + ")");
}
}
public void onBeforeConvert(E source) {
if (log.isDebugEnabled()) {
log.debug("onBeforeConvert(" + source + ")");
}
}
public void onBeforeSave(E source, DBObject dbo) {
if (log.isDebugEnabled()) {
log.debug("onBeforeSave(" + source + ", " + dbo + ")");
}
}
public void onBeforeSave(E source, DBObject dbo) {
if (log.isDebugEnabled()) {
log.debug("onBeforeSave(" + source + ", " + dbo + ")");
}
}
public void onAfterSave(E source, DBObject dbo) {
if (log.isDebugEnabled()) {
log.debug("onAfterSave(" + source + ", " + dbo + ")");
}
}
public void onAfterSave(E source, DBObject dbo) {
if (log.isDebugEnabled()) {
log.debug("onAfterSave(" + source + ", " + dbo + ")");
}
}
public void onAfterLoad(DBObject dbo) {
if (log.isDebugEnabled()) {
log.debug("onAfterLoad(" + dbo + ")");
}
}
public void onAfterLoad(DBObject dbo) {
if (log.isDebugEnabled()) {
log.debug("onAfterLoad(" + dbo + ")");
}
}
public void onAfterConvert(DBObject dbo, E source) {
if (log.isDebugEnabled()) {
log.debug("onAfterConvert(" + dbo + "," + source + ")");
}
}
public void onAfterConvert(DBObject dbo, E source) {
if (log.isDebugEnabled()) {
log.debug("onAfterConvert(" + dbo + "," + source + ")");
}
}
}

View File

@@ -23,10 +23,10 @@ import com.mongodb.DBObject;
*/
public class AfterConvertEvent<E> extends MongoMappingEvent<E> {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
public AfterConvertEvent(DBObject dbo, E source) {
super(source, dbo);
}
public AfterConvertEvent(DBObject dbo, E source) {
super(source, dbo);
}
}

View File

@@ -21,9 +21,9 @@ package org.springframework.data.document.mongodb.mapping.event;
*/
public class AfterLoadEvent<DBObject> extends MongoMappingEvent<DBObject> {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
public AfterLoadEvent(DBObject dbo) {
super(dbo, null);
}
public AfterLoadEvent(DBObject dbo) {
super(dbo, null);
}
}

View File

@@ -24,10 +24,10 @@ import org.springframework.data.mapping.model.PersistentEntity;
*/
public class AfterSaveEvent<E> extends MongoMappingEvent<E> {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
public AfterSaveEvent(E source, DBObject dbo) {
super(source, dbo);
}
public AfterSaveEvent(E source, DBObject dbo) {
super(source, dbo);
}
}

View File

@@ -21,10 +21,9 @@ package org.springframework.data.document.mongodb.mapping.event;
*/
public class BeforeConvertEvent<T> extends MongoMappingEvent<T> {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
public BeforeConvertEvent(T source) {
super(source, null);
}
public BeforeConvertEvent(T source) {
super(source, null);
}
}

View File

@@ -23,10 +23,10 @@ import com.mongodb.DBObject;
*/
public class BeforeSaveEvent<E> extends MongoMappingEvent<E> {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
public BeforeSaveEvent(E source, DBObject dbo) {
super(source, dbo);
}
public BeforeSaveEvent(E source, DBObject dbo) {
super(source, dbo);
}
}

View File

@@ -24,21 +24,21 @@ import org.springframework.context.ApplicationEvent;
*/
public class MongoMappingEvent<T> extends ApplicationEvent {
private static final long serialVersionUID = 1L;
private final DBObject dbo;
private static final long serialVersionUID = 1L;
private final DBObject dbo;
public MongoMappingEvent(T source, DBObject dbo) {
super(source);
this.dbo = dbo;
}
public MongoMappingEvent(T source, DBObject dbo) {
super(source);
this.dbo = dbo;
}
public DBObject getDBObject() {
return dbo;
}
public DBObject getDBObject() {
return dbo;
}
@SuppressWarnings({"unchecked"})
@Override
public T getSource() {
return (T) super.getSource();
}
@SuppressWarnings({ "unchecked" })
@Override
public T getSource() {
return (T) super.getSource();
}
}

View File

@@ -25,47 +25,48 @@ import org.springframework.data.document.mongodb.MongoDbUtils;
/**
* Base class to encapsulate common configuration settings when connecting to a database
*
*
* @author Mark Pollack
*/
public abstract class AbstractMonitor {
private final Log logger = LogFactory.getLog(getClass());
private final Log logger = LogFactory.getLog(getClass());
protected Mongo mongo;
private String username;
private String password;
protected Mongo mongo;
private String username;
private String password;
/**
* Sets the username to use to connect to the Mongo database
*
* @param username
* The username to use
*/
public void setUsername(String username) {
this.username = username;
}
/**
* Sets the username to use to connect to the Mongo database
*
* @param username The username to use
*/
public void setUsername(String username) {
this.username = username;
}
/**
* Sets the password to use to authenticate with the Mongo database.
*
* @param password
* The password to use
*/
public void setPassword(String password) {
/**
* Sets the password to use to authenticate with the Mongo database.
*
* @param password The password to use
*/
public void setPassword(String password) {
this.password = password;
}
this.password = password;
}
public CommandResult getServerStatus() {
CommandResult result = getDb("admin").command("serverStatus");
if (!result.ok()) {
logger.error("Could not query for server status. Command Result = " + result);
throw new MongoException("could not query for server status. Command Result = " + result);
}
return result;
}
public CommandResult getServerStatus() {
CommandResult result = getDb("admin").command("serverStatus");
if (!result.ok()) {
logger.error("Could not query for server status. Command Result = " + result);
throw new MongoException("could not query for server status. Command Result = " + result);
}
return result;
}
public DB getDb(String databaseName) {
return MongoDbUtils.getDB(mongo, databaseName, username, password == null ? null : password.toCharArray());
}
public DB getDb(String databaseName) {
return MongoDbUtils.getDB(mongo, databaseName, username, password == null ? null : password.toCharArray());
}
}

View File

@@ -23,45 +23,45 @@ import org.springframework.jmx.support.MetricType;
/**
* JMX Metrics for assertions
*
*
* @author Mark Pollack
*/
@ManagedResource(description = "Assertion Metrics")
public class AssertMetrics extends AbstractMonitor {
public AssertMetrics(Mongo mongo) {
this.mongo = mongo;
}
public AssertMetrics(Mongo mongo) {
this.mongo = mongo;
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Regular")
public int getRegular() {
return getBtree("regular");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Regular")
public int getRegular() {
return getBtree("regular");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Warning")
public int getWarning() {
return getBtree("warning");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Warning")
public int getWarning() {
return getBtree("warning");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Msg")
public int getMsg() {
return getBtree("msg");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Msg")
public int getMsg() {
return getBtree("msg");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "User")
public int getUser() {
return getBtree("user");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "User")
public int getUser() {
return getBtree("user");
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Rollovers")
public int getRollovers() {
return getBtree("rollovers");
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Rollovers")
public int getRollovers() {
return getBtree("rollovers");
}
private int getBtree(String key) {
DBObject asserts = (DBObject) getServerStatus().get("asserts");
//Class c = btree.get(key).getClass();
return (Integer) asserts.get(key);
}
private int getBtree(String key) {
DBObject asserts = (DBObject) getServerStatus().get("asserts");
// Class c = btree.get(key).getClass();
return (Integer) asserts.get(key);
}
}

View File

@@ -25,54 +25,51 @@ import org.springframework.jmx.support.MetricType;
/**
* JMX Metrics for Background Flushing
*
*
* @author Mark Pollack
*/
@ManagedResource(description = "Background Flushing Metrics")
public class BackgroundFlushingMetrics extends AbstractMonitor {
public BackgroundFlushingMetrics(Mongo mongo) {
this.mongo = mongo;
}
public BackgroundFlushingMetrics(Mongo mongo) {
this.mongo = mongo;
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Flushes")
public int getFlushes() {
return getFlushingData("flushes", java.lang.Integer.class);
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Flushes")
public int getFlushes() {
return getFlushingData("flushes", java.lang.Integer.class);
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Total ms", unit = "ms")
public int getTotalMs() {
return getFlushingData("total_ms", java.lang.Integer.class);
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Total ms", unit = "ms")
public int getTotalMs() {
return getFlushingData("total_ms", java.lang.Integer.class);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Average ms", unit = "ms")
public double getAverageMs() {
return getFlushingData("average_ms", java.lang.Double.class);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Average ms", unit = "ms")
public double getAverageMs() {
return getFlushingData("average_ms", java.lang.Double.class);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Last Ms", unit = "ms")
public int getLastMs() {
return getFlushingData("last_ms", java.lang.Integer.class);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Last Ms", unit = "ms")
public int getLastMs() {
return getFlushingData("last_ms", java.lang.Integer.class);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Last finished")
public Date getLastFinished() {
return getLast();
}
@SuppressWarnings("unchecked")
private <T> T getFlushingData(String key, Class<T> targetClass) {
DBObject mem = (DBObject) getServerStatus().get("backgroundFlushing");
return (T) mem.get(key);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Last finished")
public Date getLastFinished() {
return getLast();
}
@SuppressWarnings("unchecked")
private <T> T getFlushingData(String key, Class<T> targetClass) {
DBObject mem = (DBObject) getServerStatus().get("backgroundFlushing");
return (T) mem.get(key);
}
private Date getLast() {
DBObject bgFlush = (DBObject) getServerStatus().get("backgroundFlushing");
Date lastFinished = (Date) bgFlush.get("last_finished");
return lastFinished;
}
private Date getLast() {
DBObject bgFlush = (DBObject) getServerStatus().get("backgroundFlushing");
Date lastFinished = (Date) bgFlush.get("last_finished");
return lastFinished;
}
}

View File

@@ -23,52 +23,52 @@ import org.springframework.jmx.support.MetricType;
/**
* JMX Metrics for B-tree index counters
*
*
* @author Mark Pollack
*/
@ManagedResource(description = "Btree Metrics")
public class BtreeIndexCounters extends AbstractMonitor {
public BtreeIndexCounters(Mongo mongo) {
this.mongo = mongo;
}
public BtreeIndexCounters(Mongo mongo) {
this.mongo = mongo;
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Accesses")
public int getAccesses() {
return getBtree("accesses");
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Accesses")
public int getAccesses() {
return getBtree("accesses");
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Hits")
public int getHits() {
return getBtree("hits");
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Hits")
public int getHits() {
return getBtree("hits");
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Misses")
public int getMisses() {
return getBtree("misses");
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Misses")
public int getMisses() {
return getBtree("misses");
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Resets")
public int getResets() {
return getBtree("resets");
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Resets")
public int getResets() {
return getBtree("resets");
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Miss Ratio")
public int getMissRatio() {
return getBtree("missRatio");
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Miss Ratio")
public int getMissRatio() {
return getBtree("missRatio");
}
private int getBtree(String key) {
DBObject indexCounters = (DBObject) getServerStatus().get("indexCounters");
if (indexCounters.get("note") != null) {
String message = (String) indexCounters.get("note");
if (message.contains("not supported")) {
return -1;
}
}
DBObject btree = (DBObject) indexCounters.get("btree");
//Class c = btree.get(key).getClass();
return (Integer) btree.get(key);
}
private int getBtree(String key) {
DBObject indexCounters = (DBObject) getServerStatus().get("indexCounters");
if (indexCounters.get("note") != null) {
String message = (String) indexCounters.get("note");
if (message.contains("not supported")) {
return -1;
}
}
DBObject btree = (DBObject) indexCounters.get("btree");
// Class c = btree.get(key).getClass();
return (Integer) btree.get(key);
}
}

View File

@@ -23,31 +23,31 @@ import org.springframework.jmx.support.MetricType;
/**
* JMX Metrics for Connections
*
*
* @author Mark Pollack
*/
@ManagedResource(description = "Connection metrics")
public class ConnectionMetrics extends AbstractMonitor {
public ConnectionMetrics(Mongo mongo) {
this.mongo = mongo;
}
public ConnectionMetrics(Mongo mongo) {
this.mongo = mongo;
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Current Connections")
public int getCurrent() {
return getConnectionData("current", java.lang.Integer.class);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Current Connections")
public int getCurrent() {
return getConnectionData("current", java.lang.Integer.class);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Available Connections")
public int getAvailable() {
return getConnectionData("available", java.lang.Integer.class);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Available Connections")
public int getAvailable() {
return getConnectionData("available", java.lang.Integer.class);
}
@SuppressWarnings("unchecked")
private <T> T getConnectionData(String key, Class<T> targetClass) {
DBObject mem = (DBObject) getServerStatus().get("connections");
//Class c = mem.get(key).getClass();
return (T) mem.get(key);
}
@SuppressWarnings("unchecked")
private <T> T getConnectionData(String key, Class<T> targetClass) {
DBObject mem = (DBObject) getServerStatus().get("connections");
// Class c = mem.get(key).getClass();
return (T) mem.get(key);
}
}

View File

@@ -23,57 +23,55 @@ import org.springframework.jmx.support.MetricType;
/**
* JMX Metrics for Global Locks
*
*
* @author Mark Pollack
*/
@ManagedResource(description = "Global Lock Metrics")
public class GlobalLockMetrics extends AbstractMonitor {
public GlobalLockMetrics(Mongo mongo) {
this.mongo = mongo;
}
public GlobalLockMetrics(Mongo mongo) {
this.mongo = mongo;
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Total time")
public double getTotalTime() {
return getGlobalLockData("totalTime", java.lang.Double.class);
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Total time")
public double getTotalTime() {
return getGlobalLockData("totalTime", java.lang.Double.class);
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Lock time", unit = "s")
public double getLockTime() {
return getGlobalLockData("lockTime", java.lang.Double.class);
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Lock time", unit = "s")
public double getLockTime() {
return getGlobalLockData("lockTime", java.lang.Double.class);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Lock time")
public double getLockTimeRatio() {
return getGlobalLockData("ratio", java.lang.Double.class);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Lock time")
public double getLockTimeRatio() {
return getGlobalLockData("ratio", java.lang.Double.class);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Current Queue")
public int getCurrentQueueTotal() {
return getCurrentQueue("total");
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Reader Queue")
public int getCurrentQueueReaders() {
return getCurrentQueue("readers");
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Current Queue")
public int getCurrentQueueTotal() {
return getCurrentQueue("total");
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Writer Queue")
public int getCurrentQueueWriters() {
return getCurrentQueue("writers");
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Reader Queue")
public int getCurrentQueueReaders() {
return getCurrentQueue("readers");
}
@SuppressWarnings("unchecked")
private <T> T getGlobalLockData(String key, Class<T> targetClass) {
DBObject globalLock = (DBObject) getServerStatus().get("globalLock");
return (T) globalLock.get(key);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Writer Queue")
public int getCurrentQueueWriters() {
return getCurrentQueue("writers");
}
@SuppressWarnings("unchecked")
private <T> T getGlobalLockData(String key, Class<T> targetClass) {
DBObject globalLock = (DBObject) getServerStatus().get("globalLock");
return (T) globalLock.get(key);
}
private int getCurrentQueue(String key) {
DBObject globalLock = (DBObject) getServerStatus().get("globalLock");
DBObject currentQueue = (DBObject) globalLock.get("currentQueue");
return (Integer) currentQueue.get(key);
}
private int getCurrentQueue(String key) {
DBObject globalLock = (DBObject) getServerStatus().get("globalLock");
DBObject currentQueue = (DBObject) globalLock.get("currentQueue");
return (Integer) currentQueue.get(key);
}
}

View File

@@ -23,50 +23,46 @@ import org.springframework.jmx.support.MetricType;
/**
* JMX Metrics for Memory
*
*
* @author Mark Pollack
*/
@ManagedResource(description = "Memory Metrics")
public class MemoryMetrics extends AbstractMonitor {
public MemoryMetrics(Mongo mongo) {
this.mongo = mongo;
}
public MemoryMetrics(Mongo mongo) {
this.mongo = mongo;
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Memory address size")
public int getBits() {
return getMemData("bits", java.lang.Integer.class);
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Memory address size")
public int getBits() {
return getMemData("bits", java.lang.Integer.class);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Resident in Physical Memory", unit = "MB")
public int getResidentSpace() {
return getMemData("resident", java.lang.Integer.class);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Resident in Physical Memory", unit = "MB")
public int getResidentSpace() {
return getMemData("resident", java.lang.Integer.class);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Virtual Address Space", unit = "MB")
public int getVirtualAddressSpace() {
return getMemData("virtual", java.lang.Integer.class);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Virtual Address Space", unit = "MB")
public int getVirtualAddressSpace() {
return getMemData("virtual", java.lang.Integer.class);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Is memory info supported on this platform")
public boolean getMemoryInfoSupported() {
return getMemData("supported", java.lang.Boolean.class);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Is memory info supported on this platform")
public boolean getMemoryInfoSupported() {
return getMemData("supported", java.lang.Boolean.class);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Memory Mapped Space", unit = "MB")
public int getMemoryMappedSpace() {
return getMemData("mapped", java.lang.Integer.class);
}
@SuppressWarnings("unchecked")
private <T> T getMemData(String key, Class<T> targetClass) {
DBObject mem = (DBObject) getServerStatus().get("mem");
//Class c = mem.get(key).getClass();
return (T) mem.get(key);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Memory Mapped Space", unit = "MB")
public int getMemoryMappedSpace() {
return getMemData("mapped", java.lang.Integer.class);
}
@SuppressWarnings("unchecked")
private <T> T getMemData(String key, Class<T> targetClass) {
DBObject mem = (DBObject) getServerStatus().get("mem");
// Class c = mem.get(key).getClass();
return (T) mem.get(key);
}
}

View File

@@ -23,49 +23,48 @@ import org.springframework.jmx.support.MetricType;
/**
* JMX Metrics for Operation counters
*
*
* @author Mark Pollack
*/
@ManagedResource(description = "Operation Counters")
public class OperationCounters extends AbstractMonitor {
public OperationCounters(Mongo mongo) {
this.mongo = mongo;
}
public OperationCounters(Mongo mongo) {
this.mongo = mongo;
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Insert operation count")
public int getInsertCount() {
return getOpCounter("insert");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Insert operation count")
public int getInsertCount() {
return getOpCounter("insert");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Query operation count")
public int getQueryCount() {
return getOpCounter("query");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Query operation count")
public int getQueryCount() {
return getOpCounter("query");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Update operation count")
public int getUpdateCount() {
return getOpCounter("update");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Update operation count")
public int getUpdateCount() {
return getOpCounter("update");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Delete operation count")
public int getDeleteCount() {
return getOpCounter("delete");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Delete operation count")
public int getDeleteCount() {
return getOpCounter("delete");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "GetMore operation count")
public int getGetMoreCount() {
return getOpCounter("getmore");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "GetMore operation count")
public int getGetMoreCount() {
return getOpCounter("getmore");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Command operation count")
public int getCommandCount() {
return getOpCounter("command");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Command operation count")
public int getCommandCount() {
return getOpCounter("command");
}
private int getOpCounter(String key) {
DBObject opCounters = (DBObject) getServerStatus().get("opcounters");
return (Integer) opCounters.get(key);
}
private int getOpCounter(String key) {
DBObject opCounters = (DBObject) getServerStatus().get("opcounters");
return (Integer) opCounters.get(key);
}
}

View File

@@ -26,41 +26,39 @@ import org.springframework.jmx.support.MetricType;
/**
* Expose basic server information via JMX
*
*
* @author Mark Pollack
*/
@ManagedResource(description = "Server Information")
public class ServerInfo extends AbstractMonitor {
public ServerInfo(Mongo mongo) {
this.mongo = mongo;
}
public ServerInfo(Mongo mongo) {
this.mongo = mongo;
}
@ManagedOperation(description = "Server host name")
public String getHostName() throws UnknownHostException {
return InetAddress.getLocalHost().getHostName();
}
@ManagedOperation(description = "Server host name")
public String getHostName() throws UnknownHostException {
return InetAddress.getLocalHost().getHostName();
}
@ManagedMetric(displayName = "Uptime Estimate")
public double getUptimeEstimate() {
return (Double) getServerStatus().get("uptimeEstimate");
}
@ManagedMetric(displayName = "Uptime Estimate")
public double getUptimeEstimate() {
return (Double) getServerStatus().get("uptimeEstimate");
}
@ManagedOperation(description = "MongoDB Server Version")
public String getVersion() {
return (String) getServerStatus().get("version");
}
@ManagedOperation(description = "MongoDB Server Version")
public String getVersion() {
return (String) getServerStatus().get("version");
}
@ManagedOperation(description = "Local Time")
public String getLocalTime() {
return (String) getServerStatus().get("localTime");
}
@ManagedOperation(description = "Local Time")
public String getLocalTime() {
return (String) getServerStatus().get("localTime");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Server uptime in seconds", unit = "seconds")
public double getUptime() {
return (Double) getServerStatus().get("uptime");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Server uptime in seconds", unit = "seconds")
public double getUptime() {
return (Double) getServerStatus().get("uptime");
}
}

View File

@@ -2,3 +2,4 @@
* MongoDB specific JMX monitoring support.
*/
package org.springframework.data.document.mongodb.monitor;

View File

@@ -2,3 +2,4 @@
* MongoDB core support.
*/
package org.springframework.data.document.mongodb;

View File

@@ -20,72 +20,72 @@ import com.mongodb.util.JSON;
public class BasicQuery extends Query {
private DBObject queryObject = null;
private DBObject queryObject = null;
private DBObject fieldsObject = null;
private DBObject fieldsObject = null;
private DBObject sortObject = null;
private DBObject sortObject = null;
private int skip;
private int skip;
private int limit;
private int limit;
public BasicQuery(String query) {
super();
this.queryObject = (DBObject) JSON.parse(query);
}
public BasicQuery(String query) {
super();
this.queryObject = (DBObject) JSON.parse(query);
}
public BasicQuery(DBObject queryObject) {
super();
this.queryObject = queryObject;
}
public BasicQuery(DBObject queryObject) {
super();
this.queryObject = queryObject;
}
public BasicQuery(String query, String fields) {
this.queryObject = (DBObject) JSON.parse(query);
this.fieldsObject = (DBObject) JSON.parse(fields);
}
public BasicQuery(String query, String fields) {
this.queryObject = (DBObject) JSON.parse(query);
this.fieldsObject = (DBObject) JSON.parse(fields);
}
public BasicQuery(DBObject queryObject, DBObject fieldsObject) {
this.queryObject = queryObject;
this.fieldsObject = fieldsObject;
}
public BasicQuery(DBObject queryObject, DBObject fieldsObject) {
this.queryObject = queryObject;
this.fieldsObject = fieldsObject;
}
@Override
public Query addCriteria(Criteria criteria) {
this.queryObject.putAll(criteria.getCriteriaObject());
return this;
}
@Override
public Query addCriteria(Criteria criteria) {
this.queryObject.putAll(criteria.getCriteriaObject());
return this;
}
public DBObject getQueryObject() {
return this.queryObject;
}
public DBObject getQueryObject() {
return this.queryObject;
}
public DBObject getFieldsObject() {
return fieldsObject;
}
public DBObject getFieldsObject() {
return fieldsObject;
}
public DBObject getSortObject() {
return sortObject;
}
public DBObject getSortObject() {
return sortObject;
}
public void setSortObject(DBObject sortObject) {
this.sortObject = sortObject;
}
public void setSortObject(DBObject sortObject) {
this.sortObject = sortObject;
}
public int getSkip() {
return skip;
}
public int getSkip() {
return skip;
}
public void setSkip(int skip) {
this.skip = skip;
}
public void setSkip(int skip) {
this.skip = skip;
}
public int getLimit() {
return this.limit;
}
public int getLimit() {
return this.limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
}

View File

@@ -30,398 +30,401 @@ import org.springframework.data.document.mongodb.geo.Point;
import org.springframework.util.Assert;
public class Criteria implements CriteriaDefinition {
/**
* Custom "not-null" object as we have to be able to work with {@literal null} values as well.
*/
private static final Object NOT_SET = new Object();
private String key;
/**
* Custom "not-null" object as we have to be able to work with {@literal null} values as well.
*/
private static final Object NOT_SET = new Object();
private List<Criteria> criteriaChain;
private String key;
private LinkedHashMap<String, Object> criteria = new LinkedHashMap<String, Object>();
private List<Criteria> criteriaChain;
private Object isValue = NOT_SET;
private LinkedHashMap<String, Object> criteria = new LinkedHashMap<String, Object>();
public Criteria(String key) {
this.criteriaChain = new ArrayList<Criteria>();
this.criteriaChain.add(this);
this.key = key;
}
private Object isValue = NOT_SET;
protected Criteria(List<Criteria> criteriaChain, String key) {
this.criteriaChain = criteriaChain;
this.criteriaChain.add(this);
this.key = key;
}
/**
* Static factory method to create a Criteria using the provided key
*
* @param key
* @return
*/
public static Criteria where(String key) {
return new Criteria(key);
}
public static Criteria whereId() {
return new Criteria("id");
}
/**
* Static factory method to create a Criteria using the provided key
*
* @param key
* @return
*/
public Criteria and(String key) {
return new Criteria(this.criteriaChain, key);
}
/**
* Creates a criterion using equality
*
* @param o
* @return
*/
public Criteria is(Object o) {
if (isValue != NOT_SET) {
throw new InvalidDocumentStoreApiUsageException(
"Multiple 'is' values declared. You need to use 'and' with multiple criteria");
}
if (this.criteria.size() > 0 && "$not".equals(this.criteria.keySet().toArray()[this.criteria.size() - 1])) {
throw new InvalidDocumentStoreApiUsageException(
"Invalid query: 'not' can't be used with 'is' - use 'ne' instead.");
}
this.isValue = o;
return this;
}
/**
* Creates a criterion using the $ne operator
*
* @param o
* @return
*/
public Criteria ne(Object o) {
criteria.put("$ne", o);
return this;
}
/**
* Creates a criterion using the $lt operator
*
* @param o
* @return
*/
public Criteria lt(Object o) {
criteria.put("$lt", o);
return this;
}
/**
* Creates a criterion using the $lte operator
*
* @param o
* @return
*/
public Criteria lte(Object o) {
criteria.put("$lte", o);
return this;
}
/**
* Creates a criterion using the $gt operator
*
* @param o
* @return
*/
public Criteria gt(Object o) {
criteria.put("$gt", o);
return this;
}
/**
* Creates a criterion using the $gte operator
*
* @param o
* @return
*/
public Criteria gte(Object o) {
criteria.put("$gte", o);
return this;
}
/**
* Creates a criterion using the $in operator
*
* @param o the values to match against
* @return
*/
public Criteria in(Object... o) {
if (o.length > 1 && o[1] instanceof Collection) {
throw new InvalidDocumentStoreApiUsageException("You can only pass in one argument of type " + o[1].getClass().getName());
public Criteria(String key) {
this.criteriaChain = new ArrayList<Criteria>();
this.criteriaChain.add(this);
this.key = key;
}
criteria.put("$in", o);
return this;
}
/**
* Creates a criterion using the $in operator
*
* @param c the collection containing the values to match against
* @return
*/
public Criteria in(Collection<?> c) {
System.out.println(c.getClass());
criteria.put("$in", c.toArray());
return this;
}
protected Criteria(List<Criteria> criteriaChain, String key) {
this.criteriaChain = criteriaChain;
this.criteriaChain.add(this);
this.key = key;
}
/**
* Creates a criterion using the $nin operator
*
* @param o
* @return
*/
public Criteria nin(Object... o) {
criteria.put("$nin", o);
return this;
}
/**
* Static factory method to create a Criteria using the provided key
*
* @param key
* @return
*/
public static Criteria where(String key) {
return new Criteria(key);
}
/**
* Creates a criterion using the $mod operator
*
* @param value
* @param remainder
* @return
*/
public Criteria mod(Number value, Number remainder) {
List<Object> l = new ArrayList<Object>();
l.add(value);
l.add(remainder);
criteria.put("$mod", l);
return this;
}
public static Criteria whereId() {
return new Criteria("id");
}
/**
* Creates a criterion using the $all operator
*
* @param o
* @return
*/
public Criteria all(Object... o) {
criteria.put("$all", o);
return this;
}
/**
* Static factory method to create a Criteria using the provided key
*
* @param key
* @return
*/
public Criteria and(String key) {
return new Criteria(this.criteriaChain, key);
}
/**
* Creates a criterion using the $size operator
*
* @param s
* @return
*/
public Criteria size(int s) {
criteria.put("$size", s);
return this;
}
/**
* Creates a criterion using equality
*
* @param o
* @return
*/
public Criteria is(Object o) {
if (isValue != NOT_SET) {
throw new InvalidDocumentStoreApiUsageException(
"Multiple 'is' values declared. You need to use 'and' with multiple criteria");
}
if (this.criteria.size() > 0 && "$not".equals(this.criteria.keySet().toArray()[this.criteria.size() - 1])) {
throw new InvalidDocumentStoreApiUsageException(
"Invalid query: 'not' can't be used with 'is' - use 'ne' instead.");
}
this.isValue = o;
return this;
}
/**
* Creates a criterion using the $exists operator
*
* @param b
* @return
*/
public Criteria exists(boolean b) {
criteria.put("$exists", b);
return this;
}
/**
* Creates a criterion using the $ne operator
*
* @param o
* @return
*/
public Criteria ne(Object o) {
criteria.put("$ne", o);
return this;
}
/**
* Creates a criterion using the $type operator
*
* @param t
* @return
*/
public Criteria type(int t) {
criteria.put("$type", t);
return this;
}
/**
* Creates a criterion using the $lt operator
*
* @param o
* @return
*/
public Criteria lt(Object o) {
criteria.put("$lt", o);
return this;
}
/**
* Creates a criterion using the $not meta operator which affects the clause directly following
*
* @return
*/
public Criteria not() {
criteria.put("$not", null);
return this;
}
/**
* Creates a criterion using the $lte operator
*
* @param o
* @return
*/
public Criteria lte(Object o) {
criteria.put("$lte", o);
return this;
}
/**
* Creates a criterion using a $regex
*
* @param re
* @return
*/
public Criteria regex(String re) {
criteria.put("$regex", re);
return this;
}
/**
* Creates a criterion using the $gt operator
*
* @param o
* @return
*/
public Criteria gt(Object o) {
criteria.put("$gt", o);
return this;
}
/**
* Creates a geospatial criterion using a $within $center operation
*
* @param circle
* must not be {@literal null}
* @return
*/
public Criteria withinCenter(Circle circle) {
Assert.notNull(circle);
LinkedList<Object> list = new LinkedList<Object>();
list.addLast(circle.getCenter().asArray());
list.add(circle.getRadius());
criteria.put("$within", new BasicDBObject("$center", list));
return this;
}
/**
* Creates a criterion using the $gte operator
*
* @param o
* @return
*/
public Criteria gte(Object o) {
criteria.put("$gte", o);
return this;
}
/**
* Creates a geospatial criterion using a $within $center operation. This is only available for Mongo 1.7 and higher.
*
* @param circle
* must not be {@literal null}
* @return
*/
public Criteria withinCenterSphere(Circle circle) {
Assert.notNull(circle);
LinkedList<Object> list = new LinkedList<Object>();
list.addLast(circle.getCenter().asArray());
list.add(circle.getRadius());
criteria.put("$within", new BasicDBObject("$centerSphere", list));
return this;
}
/**
* Creates a criterion using the $in operator
*
* @param o
* the values to match against
* @return
*/
public Criteria in(Object... o) {
if (o.length > 1 && o[1] instanceof Collection) {
throw new InvalidDocumentStoreApiUsageException("You can only pass in one argument of type "
+ o[1].getClass().getName());
}
criteria.put("$in", o);
return this;
}
/**
* Creates a geospatial criterion using a $within $box operation
*
* @param box
* @return
*/
public Criteria withinBox(Box box) {
Assert.notNull(box);
LinkedList<double[]> list = new LinkedList<double[]>();
list.addLast(box.getLowerLeft().asArray());
list.addLast(box.getUpperRight().asArray());
criteria.put("$within", new BasicDBObject("$box", list));
return this;
}
/**
* Creates a criterion using the $in operator
*
* @param c
* the collection containing the values to match against
* @return
*/
public Criteria in(Collection<?> c) {
System.out.println(c.getClass());
criteria.put("$in", c.toArray());
return this;
}
/**
* Creates a geospatial criterion using a $near operation
*
* @param point
* must not be {@literal null}
* @return
*/
public Criteria near(Point point) {
Assert.notNull(point);
criteria.put("$near", point.asArray());
return this;
}
/**
* Creates a criterion using the $nin operator
*
* @param o
* @return
*/
public Criteria nin(Object... o) {
criteria.put("$nin", o);
return this;
}
/**
* Creates a geospatial criterion using a $nearSphere operation. This is only available for Mongo 1.7 and higher.
*
* @param point
* must not be {@literal null}
* @return
*/
public Criteria nearSphere(Point point) {
Assert.notNull(point);
criteria.put("$nearSphere", point.asArray());
return this;
}
/**
* Creates a criterion using the $mod operator
*
* @param value
* @param remainder
* @return
*/
public Criteria mod(Number value, Number remainder) {
List<Object> l = new ArrayList<Object>();
l.add(value);
l.add(remainder);
criteria.put("$mod", l);
return this;
}
/**
* Creates a geospatical criterion using a $maxDistance operation, for use with $near
*
* @param maxDistance
* @return
*/
public Criteria maxDistance(double maxDistance) {
criteria.put("$maxDistance", maxDistance);
return this;
}
/**
* Creates a criterion using the $all operator
*
* @param o
* @return
*/
public Criteria all(Object... o) {
criteria.put("$all", o);
return this;
}
/**
* Creates a criterion using the $elemMatch operator
*
* @param c
* @return
*/
public Criteria elemMatch(Criteria c) {
criteria.put("$elemMatch", c.getCriteriaObject());
return this;
}
/**
* Creates a criterion using the $size operator
*
* @param s
* @return
*/
public Criteria size(int s) {
criteria.put("$size", s);
return this;
}
/**
* Creates an or query using the $or operator for all of the provided queries
*
* @param queries
*/
public void or(List<Query> queries) {
criteria.put("$or", queries);
}
/**
* Creates a criterion using the $exists operator
*
* @param b
* @return
*/
public Criteria exists(boolean b) {
criteria.put("$exists", b);
return this;
}
public String getKey() {
return this.key;
}
/**
* Creates a criterion using the $type operator
*
* @param t
* @return
*/
public Criteria type(int t) {
criteria.put("$type", t);
return this;
}
/*
* (non-Javadoc)
*
* @see org.springframework.datastore.document.mongodb.query.Criteria#
* getCriteriaObject(java.lang.String)
*/
public DBObject getCriteriaObject() {
if (this.criteriaChain.size() == 1) {
return criteriaChain.get(0).getSingleCriteriaObject();
} else {
DBObject criteriaObject = new BasicDBObject();
for (Criteria c : this.criteriaChain) {
criteriaObject.putAll(c.getSingleCriteriaObject());
}
return criteriaObject;
}
}
/**
* Creates a criterion using the $not meta operator which affects the clause directly following
*
* @return
*/
public Criteria not() {
criteria.put("$not", null);
return this;
}
protected DBObject getSingleCriteriaObject() {
DBObject dbo = new BasicDBObject();
boolean not = false;
for (String k : this.criteria.keySet()) {
if (not) {
DBObject notDbo = new BasicDBObject();
notDbo.put(k, this.criteria.get(k));
dbo.put("$not", notDbo);
not = false;
} else {
if ("$not".equals(k)) {
not = true;
} else {
dbo.put(k, this.criteria.get(k));
}
}
}
DBObject queryCriteria = new BasicDBObject();
if (isValue != NOT_SET) {
queryCriteria.put(this.key, this.isValue);
queryCriteria.putAll(dbo);
} else {
queryCriteria.put(this.key, dbo);
}
return queryCriteria;
}
/**
* Creates a criterion using a $regex
*
* @param re
* @return
*/
public Criteria regex(String re) {
criteria.put("$regex", re);
return this;
}
/**
* Creates a geospatial criterion using a $within $center operation
*
* @param circle
* must not be {@literal null}
* @return
*/
public Criteria withinCenter(Circle circle) {
Assert.notNull(circle);
LinkedList<Object> list = new LinkedList<Object>();
list.addLast(circle.getCenter().asArray());
list.add(circle.getRadius());
criteria.put("$within", new BasicDBObject("$center", list));
return this;
}
/**
* Creates a geospatial criterion using a $within $center operation. This is only available for Mongo 1.7 and higher.
*
* @param circle
* must not be {@literal null}
* @return
*/
public Criteria withinCenterSphere(Circle circle) {
Assert.notNull(circle);
LinkedList<Object> list = new LinkedList<Object>();
list.addLast(circle.getCenter().asArray());
list.add(circle.getRadius());
criteria.put("$within", new BasicDBObject("$centerSphere", list));
return this;
}
/**
* Creates a geospatial criterion using a $within $box operation
*
* @param box
* @return
*/
public Criteria withinBox(Box box) {
Assert.notNull(box);
LinkedList<double[]> list = new LinkedList<double[]>();
list.addLast(box.getLowerLeft().asArray());
list.addLast(box.getUpperRight().asArray());
criteria.put("$within", new BasicDBObject("$box", list));
return this;
}
/**
* Creates a geospatial criterion using a $near operation
*
* @param point
* must not be {@literal null}
* @return
*/
public Criteria near(Point point) {
Assert.notNull(point);
criteria.put("$near", point.asArray());
return this;
}
/**
* Creates a geospatial criterion using a $nearSphere operation. This is only available for Mongo 1.7 and higher.
*
* @param point
* must not be {@literal null}
* @return
*/
public Criteria nearSphere(Point point) {
Assert.notNull(point);
criteria.put("$nearSphere", point.asArray());
return this;
}
/**
* Creates a geospatical criterion using a $maxDistance operation, for use with $near
*
* @param maxDistance
* @return
*/
public Criteria maxDistance(double maxDistance) {
criteria.put("$maxDistance", maxDistance);
return this;
}
/**
* Creates a criterion using the $elemMatch operator
*
* @param c
* @return
*/
public Criteria elemMatch(Criteria c) {
criteria.put("$elemMatch", c.getCriteriaObject());
return this;
}
/**
* Creates an or query using the $or operator for all of the provided queries
*
* @param queries
*/
public void or(List<Query> queries) {
criteria.put("$or", queries);
}
public String getKey() {
return this.key;
}
/*
* (non-Javadoc)
*
* @see org.springframework.datastore.document.mongodb.query.Criteria#
* getCriteriaObject(java.lang.String)
*/
public DBObject getCriteriaObject() {
if (this.criteriaChain.size() == 1) {
return criteriaChain.get(0).getSingleCriteriaObject();
} else {
DBObject criteriaObject = new BasicDBObject();
for (Criteria c : this.criteriaChain) {
criteriaObject.putAll(c.getSingleCriteriaObject());
}
return criteriaObject;
}
}
protected DBObject getSingleCriteriaObject() {
DBObject dbo = new BasicDBObject();
boolean not = false;
for (String k : this.criteria.keySet()) {
if (not) {
DBObject notDbo = new BasicDBObject();
notDbo.put(k, this.criteria.get(k));
dbo.put("$not", notDbo);
not = false;
} else {
if ("$not".equals(k)) {
not = true;
} else {
dbo.put(k, this.criteria.get(k));
}
}
}
DBObject queryCriteria = new BasicDBObject();
if (isValue != NOT_SET) {
queryCriteria.put(this.key, this.isValue);
queryCriteria.putAll(dbo);
} else {
queryCriteria.put(this.key, dbo);
}
return queryCriteria;
}
}

View File

@@ -19,6 +19,6 @@ import com.mongodb.DBObject;
public interface CriteriaDefinition {
DBObject getCriteriaObject();
DBObject getCriteriaObject();
}

View File

@@ -21,41 +21,40 @@ import java.util.Map;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
public class Field {
private Map<String, Integer> criteria = new HashMap<String, Integer>();
private Map<String, Integer> criteria = new HashMap<String, Integer>();
private Map<String, Object> slices = new HashMap<String, Object>();
private Map<String, Object> slices = new HashMap<String, Object>();
public Field include(String key) {
criteria.put(key, Integer.valueOf(1));
return this;
}
public Field include(String key) {
criteria.put(key, Integer.valueOf(1));
return this;
}
public Field exclude(String key) {
criteria.put(key, Integer.valueOf(0));
return this;
}
public Field exclude(String key) {
criteria.put(key, Integer.valueOf(0));
return this;
}
public Field slice(String key, int size) {
slices.put(key, Integer.valueOf(size));
return this;
}
public Field slice(String key, int size) {
slices.put(key, Integer.valueOf(size));
return this;
}
public Field slice(String key, int offset, int size) {
slices.put(key, new Integer[]{Integer.valueOf(offset), Integer.valueOf(size)});
return this;
}
public Field slice(String key, int offset, int size) {
slices.put(key, new Integer[] { Integer.valueOf(offset), Integer.valueOf(size) });
return this;
}
public DBObject getFieldsObject() {
DBObject dbo = new BasicDBObject();
for (String k : criteria.keySet()) {
dbo.put(k, (criteria.get(k)));
}
for (String k : slices.keySet()) {
dbo.put(k, new BasicDBObject("$slice", (slices.get(k))));
}
return dbo;
}
public DBObject getFieldsObject() {
DBObject dbo = new BasicDBObject();
for (String k : criteria.keySet()) {
dbo.put(k, (criteria.get(k)));
}
for (String k : slices.keySet()) {
dbo.put(k, new BasicDBObject("$slice", (slices.get(k))));
}
return dbo;
}
}

View File

@@ -20,74 +20,73 @@ import org.springframework.data.document.mongodb.index.IndexDefinition;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
public class GeospatialIndex implements IndexDefinition {
private String keyField;
private String keyField;
private String name;
private String name;
private Integer min = null;
private Integer min = null;
private Integer max = null;
private Integer bits = null;
private Integer max = null;
public GeospatialIndex(String key) {
keyField = key;
}
private Integer bits = null;
public GeospatialIndex named(String name) {
this.name = name;
return this;
}
public GeospatialIndex(String key) {
keyField = key;
}
public GeospatialIndex withMin(int min) {
this.min = Integer.valueOf(min);
return this;
}
public GeospatialIndex named(String name) {
this.name = name;
return this;
}
public GeospatialIndex withMax(int max) {
this.max = Integer.valueOf(max);
return this;
}
public GeospatialIndex withMin(int min) {
this.min = Integer.valueOf(min);
return this;
}
public GeospatialIndex withBits(int bits) {
this.bits = Integer.valueOf(bits);
return this;
}
public DBObject getIndexKeys() {
DBObject dbo = new BasicDBObject();
dbo.put(keyField, "2d");
return dbo;
}
public GeospatialIndex withMax(int max) {
this.max = Integer.valueOf(max);
return this;
}
public DBObject getIndexOptions() {
if (name == null && min == null && max == null) {
return null;
}
DBObject dbo = new BasicDBObject();
if (name != null) {
dbo.put("name", name);
}
if (min != null) {
dbo.put("min", min);
}
if (max != null) {
dbo.put("max", max);
}
if (bits != null) {
dbo.put("bits", bits);
}
return dbo;
}
public GeospatialIndex withBits(int bits) {
this.bits = Integer.valueOf(bits);
return this;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return String.format("Geo index: %s - Options: %s", getIndexKeys(), getIndexOptions());
}
public DBObject getIndexKeys() {
DBObject dbo = new BasicDBObject();
dbo.put(keyField, "2d");
return dbo;
}
public DBObject getIndexOptions() {
if (name == null && min == null && max == null) {
return null;
}
DBObject dbo = new BasicDBObject();
if (name != null) {
dbo.put("name", name);
}
if (min != null) {
dbo.put("min", min);
}
if (max != null) {
dbo.put("max", max);
}
if (bits != null) {
dbo.put("bits", bits);
}
return dbo;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return String.format("Geo index: %s - Options: %s", getIndexKeys(), getIndexOptions());
}
}

View File

@@ -23,88 +23,86 @@ import org.springframework.data.document.mongodb.index.IndexDefinition;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
public class Index implements IndexDefinition {
public enum Duplicates {
RETAIN,
DROP
}
public enum Duplicates {
RETAIN, DROP
}
private Map<String, Order> fieldSpec = new HashMap<String, Order>();
private Map<String, Order> fieldSpec = new HashMap<String, Order>();
private String name;
private String name;
private boolean unique = false;
private boolean unique = false;
private boolean dropDuplicates = false;
private boolean sparse = false;
private boolean dropDuplicates = false;
public Index() {
}
private boolean sparse = false;
public Index(String key, Order order) {
fieldSpec.put(key, order);
}
public Index() {
}
public Index on(String key, Order order) {
fieldSpec.put(key, order);
return this;
}
public Index(String key, Order order) {
fieldSpec.put(key, order);
}
public Index named(String name) {
this.name = name;
return this;
}
public Index on(String key, Order order) {
fieldSpec.put(key, order);
return this;
}
public Index unique() {
this.unique = true;
return this;
}
public Index sparse() {
this.sparse = true;
return this;
}
public Index named(String name) {
this.name = name;
return this;
}
public Index unique(Duplicates duplicates) {
if (duplicates == Duplicates.DROP) {
this.dropDuplicates = true;
}
return unique();
}
public Index unique() {
this.unique = true;
return this;
}
public DBObject getIndexKeys() {
DBObject dbo = new BasicDBObject();
for (String k : fieldSpec.keySet()) {
dbo.put(k, (fieldSpec.get(k).equals(Order.ASCENDING) ? 1 : -1));
}
return dbo;
}
public Index sparse() {
this.sparse = true;
return this;
}
public DBObject getIndexOptions() {
if (name == null && !unique) {
return null;
}
DBObject dbo = new BasicDBObject();
if (name != null) {
dbo.put("name", name);
}
if (unique) {
dbo.put("unique", true);
}
if (dropDuplicates) {
dbo.put("dropDups", true);
}
if (sparse) {
dbo.put("sparse", true);
}
return dbo;
}
@Override
public String toString() {
return String.format("Index: %s - Options: %s", getIndexKeys(), getIndexOptions());
}
public Index unique(Duplicates duplicates) {
if (duplicates == Duplicates.DROP) {
this.dropDuplicates = true;
}
return unique();
}
public DBObject getIndexKeys() {
DBObject dbo = new BasicDBObject();
for (String k : fieldSpec.keySet()) {
dbo.put(k, (fieldSpec.get(k).equals(Order.ASCENDING) ? 1 : -1));
}
return dbo;
}
public DBObject getIndexOptions() {
if (name == null && !unique) {
return null;
}
DBObject dbo = new BasicDBObject();
if (name != null) {
dbo.put("name", name);
}
if (unique) {
dbo.put("unique", true);
}
if (dropDuplicates) {
dbo.put("dropDups", true);
}
if (sparse) {
dbo.put("sparse", true);
}
return dbo;
}
@Override
public String toString() {
return String.format("Index: %s - Options: %s", getIndexKeys(), getIndexOptions());
}
}

View File

@@ -17,9 +17,9 @@ package org.springframework.data.document.mongodb.query;
/**
* An enum that specifies the ordering for sort or index specifications
*
*
* @author trisberg
*/
public enum Order {
ASCENDING, DESCENDING
ASCENDING, DESCENDING
}

View File

@@ -30,7 +30,7 @@ public class Query {
/**
* Static factory method to create a Query using the provided criteria
*
*
* @param critera
* @return
*/

View File

@@ -31,7 +31,7 @@ import org.springframework.util.Assert;
/**
* A helper class to encapsulate any modifications of a Query object before it gets submitted to the database.
*
*
* @author Jon Brisbin <jbrisbin@vmware.com>
* @author Oliver Gierke
*/
@@ -41,7 +41,7 @@ public class QueryMapper {
/**
* Creates a new {@link QueryMapper} with the given {@link MongoConverter}.
*
*
* @param converter
*/
public QueryMapper(MongoConverter converter) {
@@ -52,7 +52,7 @@ public class QueryMapper {
/**
* Replaces the property keys used in the given {@link DBObject} with the appropriate keys by using the
* {@link PersistentEntity} metadata.
*
*
* @param query
* @param entity
* @return

View File

@@ -21,29 +21,28 @@ import java.util.Map;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
public class Sort {
private Map<String, Order> fieldSpec = new HashMap<String, Order>();
private Map<String, Order> fieldSpec = new HashMap<String, Order>();
public Sort() {
}
public Sort() {
}
public Sort(String key, Order order) {
fieldSpec.put(key, order);
}
public Sort(String key, Order order) {
fieldSpec.put(key, order);
}
public Sort on(String key, Order order) {
fieldSpec.put(key, order);
return this;
}
public Sort on(String key, Order order) {
fieldSpec.put(key, order);
return this;
}
public DBObject getSortObject() {
DBObject dbo = new BasicDBObject();
for (String k : fieldSpec.keySet()) {
dbo.put(k, (fieldSpec.get(k).equals(Order.ASCENDING) ? 1 : -1));
}
return dbo;
}
public DBObject getSortObject() {
DBObject dbo = new BasicDBObject();
for (String k : fieldSpec.keySet()) {
dbo.put(k, (fieldSpec.get(k).equals(Order.ASCENDING) ? 1 : -1));
}
return dbo;
}
}

View File

@@ -32,7 +32,7 @@ public class Update {
/**
* Static factory method to create an Update using the provided key
*
*
* @param key
* @return
*/
@@ -42,7 +42,7 @@ public class Update {
/**
* Update using the $set update modifier
*
*
* @param key
* @param value
* @return
@@ -54,7 +54,7 @@ public class Update {
/**
* Update using the $unset update modifier
*
*
* @param key
* @return
*/
@@ -65,7 +65,7 @@ public class Update {
/**
* Update using the $inc update modifier
*
*
* @param key
* @param inc
* @return
@@ -77,7 +77,7 @@ public class Update {
/**
* Update using the $push update modifier
*
*
* @param key
* @param value
* @return
@@ -89,7 +89,7 @@ public class Update {
/**
* Update using the $pushAll update modifier
*
*
* @param key
* @param values
* @return
@@ -107,7 +107,7 @@ public class Update {
/**
* Update using the $addToSet update modifier
*
*
* @param key
* @param value
* @return
@@ -119,20 +119,19 @@ public class Update {
/**
* Update using the $pop update modifier
*
*
* @param key
* @param pos
* @return
*/
public Update pop(String key, Position pos) {
addMultiFieldOperation("$pop", key,
(pos == Position.FIRST ? -1 : 1));
addMultiFieldOperation("$pop", key, (pos == Position.FIRST ? -1 : 1));
return this;
}
/**
* Update using the $pull update modifier
*
*
* @param key
* @param value
* @return
@@ -144,7 +143,7 @@ public class Update {
/**
* Update using the $pullAll update modifier
*
*
* @param key
* @param values
* @return
@@ -162,7 +161,7 @@ public class Update {
/**
* Update using the $rename update modifier
*
*
* @param oldName
* @param newName
* @return
@@ -181,8 +180,7 @@ public class Update {
}
@SuppressWarnings("unchecked")
protected void addMultiFieldOperation(String operator, String key,
Object value) {
protected void addMultiFieldOperation(String operator, String key, Object value) {
Object existingValue = this.modifierOps.get(operator);
LinkedHashMap<String, Object> keyValueMap;
if (existingValue == null) {
@@ -192,8 +190,8 @@ public class Update {
if (existingValue instanceof LinkedHashMap) {
keyValueMap = (LinkedHashMap<String, Object>) existingValue;
} else {
throw new InvalidDataAccessApiUsageException("Modifier Operations should be a LinkedHashMap but was " +
existingValue.getClass());
throw new InvalidDataAccessApiUsageException("Modifier Operations should be a LinkedHashMap but was "
+ existingValue.getClass());
}
}
keyValueMap.put(key, value);

View File

@@ -2,3 +2,4 @@
* MongoDB specific query and update support.
*/
package org.springframework.data.document.mongodb.query;

View File

@@ -34,165 +34,165 @@ import org.springframework.util.Assert;
/**
* Base class for {@link RepositoryQuery} implementations for Mongo.
*
*
* @author Oliver Gierke
*/
public abstract class AbstractMongoQuery implements RepositoryQuery {
private final MongoQueryMethod method;
private final MongoTemplate template;
private final MongoQueryMethod method;
private final MongoTemplate template;
/**
* Creates a new {@link AbstractMongoQuery} from the given {@link MongoQueryMethod} and {@link MongoTemplate}.
*
* @param method
* @param template
*/
public AbstractMongoQuery(MongoQueryMethod method, MongoTemplate template) {
/**
* Creates a new {@link AbstractMongoQuery} from the given {@link MongoQueryMethod} and {@link MongoTemplate}.
*
* @param method
* @param template
*/
public AbstractMongoQuery(MongoQueryMethod method, MongoTemplate template) {
Assert.notNull(template);
Assert.notNull(method);
Assert.notNull(template);
Assert.notNull(method);
this.method = method;
this.template = template;
}
this.method = method;
this.template = template;
}
/* (non-Javadoc)
* @see org.springframework.data.repository.query.RepositoryQuery#getQueryMethod()
*/
public MongoQueryMethod getQueryMethod() {
/* (non-Javadoc)
* @see org.springframework.data.repository.query.RepositoryQuery#getQueryMethod()
*/
public MongoQueryMethod getQueryMethod() {
return method;
}
return method;
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.query.RepositoryQuery#execute(java .lang.Object[])
*/
public Object execute(Object[] parameters) {
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.query.RepositoryQuery#execute(java .lang.Object[])
*/
public Object execute(Object[] parameters) {
ParameterAccessor accessor = new ParametersParameterAccessor(method.getParameters(), parameters);
Query query = createQuery(new ConvertingParameterAccessor(template.getConverter(), accessor));
ParameterAccessor accessor = new ParametersParameterAccessor(method.getParameters(), parameters);
Query query = createQuery(new ConvertingParameterAccessor(template.getConverter(), accessor));
switch (method.getType()) {
case COLLECTION:
return new CollectionExecution().execute(query);
case PAGING:
return new PagedExecution(accessor.getPageable()).execute(query);
default:
return new SingleEntityExecution().execute(query);
}
}
switch (method.getType()) {
case COLLECTION:
return new CollectionExecution().execute(query);
case PAGING:
return new PagedExecution(accessor.getPageable()).execute(query);
default:
return new SingleEntityExecution().execute(query);
}
}
/**
* Create a {@link Query} instance using the given {@link ParameterAccessor}
*
* @param accessor
* @param converter
* @return
*/
protected abstract Query createQuery(ConvertingParameterAccessor accessor);
/**
* Create a {@link Query} instance using the given {@link ParameterAccessor}
*
* @param accessor
* @param converter
* @return
*/
protected abstract Query createQuery(ConvertingParameterAccessor accessor);
private abstract class Execution {
private abstract class Execution {
abstract Object execute(Query query);
abstract Object execute(Query query);
protected List<?> readCollection(Query query) {
protected List<?> readCollection(Query query) {
MongoEntityInformation<?, ?> metadata = method.getEntityInformation();
MongoEntityInformation<?, ?> metadata = method.getEntityInformation();
String collectionName = metadata.getCollectionName();
return template.find(collectionName, query, metadata.getJavaType());
}
}
String collectionName = metadata.getCollectionName();
return template.find(collectionName, query, metadata.getJavaType());
}
}
/**
* {@link Execution} for collection returning queries.
*
* @author Oliver Gierke
*/
class CollectionExecution extends Execution {
/**
* {@link Execution} for collection returning queries.
*
* @author Oliver Gierke
*/
class CollectionExecution extends Execution {
/*
* (non-Javadoc)
*
* @see org.springframework.data.document.mongodb.repository.MongoQuery.Execution #execute(com.mongodb.DBObject)
*/
@Override
public Object execute(Query query) {
/*
* (non-Javadoc)
*
* @see org.springframework.data.document.mongodb.repository.MongoQuery.Execution #execute(com.mongodb.DBObject)
*/
@Override
public Object execute(Query query) {
return readCollection(query);
}
}
return readCollection(query);
}
}
/**
* {@link Execution} for pagination queries.
*
* @author Oliver Gierke
*/
class PagedExecution extends Execution {
/**
* {@link Execution} for pagination queries.
*
* @author Oliver Gierke
*/
class PagedExecution extends Execution {
private final Pageable pageable;
private final Pageable pageable;
/**
* Creates a new {@link PagedExecution}.
*
* @param pageable
*/
public PagedExecution(Pageable pageable) {
/**
* Creates a new {@link PagedExecution}.
*
* @param pageable
*/
public PagedExecution(Pageable pageable) {
Assert.notNull(pageable);
this.pageable = pageable;
}
Assert.notNull(pageable);
this.pageable = pageable;
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.document.mongodb.repository.MongoQuery.Execution #execute(com.mongodb.DBObject)
*/
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
Object execute(Query query) {
/*
* (non-Javadoc)
*
* @see org.springframework.data.document.mongodb.repository.MongoQuery.Execution #execute(com.mongodb.DBObject)
*/
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
Object execute(Query query) {
MongoEntityInformation<?, ?> metadata = method.getEntityInformation();
int count = getCollectionCursor(metadata.getCollectionName(), query.getQueryObject()).count();
MongoEntityInformation<?, ?> metadata = method.getEntityInformation();
int count = getCollectionCursor(metadata.getCollectionName(), query.getQueryObject()).count();
List<?> result = template.find(metadata.getCollectionName(), applyPagination(query, pageable),
metadata.getJavaType());
List<?> result = template.find(metadata.getCollectionName(), applyPagination(query, pageable),
metadata.getJavaType());
return new PageImpl(result, pageable, count);
}
return new PageImpl(result, pageable, count);
}
private DBCursor getCollectionCursor(String collectionName, final DBObject query) {
private DBCursor getCollectionCursor(String collectionName, final DBObject query) {
return template.execute(collectionName, new CollectionCallback<DBCursor>() {
return template.execute(collectionName, new CollectionCallback<DBCursor>() {
public DBCursor doInCollection(DBCollection collection) {
public DBCursor doInCollection(DBCollection collection) {
return collection.find(query);
}
});
}
}
return collection.find(query);
}
});
}
}
/**
* {@link Execution} to return a single entity.
*
* @author Oliver Gierke
*/
class SingleEntityExecution extends Execution {
/**
* {@link Execution} to return a single entity.
*
* @author Oliver Gierke
*/
class SingleEntityExecution extends Execution {
/*
* (non-Javadoc)
*
* @see org.springframework.data.document.mongodb.repository.MongoQuery.Execution #execute(com.mongodb.DBObject)
*/
@Override
Object execute(Query query) {
/*
* (non-Javadoc)
*
* @see org.springframework.data.document.mongodb.repository.MongoQuery.Execution #execute(com.mongodb.DBObject)
*/
@Override
Object execute(Query query) {
List<?> result = readCollection(query);
return result.isEmpty() ? null : result.get(0);
}
}
List<?> result = readCollection(query);
return result.isEmpty() ? null : result.get(0);
}
}
}

View File

@@ -28,160 +28,160 @@ import org.springframework.data.repository.query.ParameterAccessor;
/**
* Custom {@link ParameterAccessor} that uses a {@link MongoWriter} to serialize parameters into Mongo format.
*
*
* @author Oliver Gierke
*/
public class ConvertingParameterAccessor implements ParameterAccessor {
private final MongoWriter<Object> writer;
private final ParameterAccessor delegate;
/**
* Creates a new {@link ConvertingParameterAccessor} with the given {@link MongoWriter} and delegate.
*
* @param writer
*/
public ConvertingParameterAccessor(MongoWriter<Object> writer, ParameterAccessor delegate) {
this.writer = writer;
this.delegate = delegate;
}
private final MongoWriter<Object> writer;
private final ParameterAccessor delegate;
/*
* (non-Javadoc)
*
* @see java.lang.Iterable#iterator()
*/
public Iterator<Object> iterator() {
return new ConvertingIterator(delegate.iterator());
}
/**
* Creates a new {@link ConvertingParameterAccessor} with the given {@link MongoWriter} and delegate.
*
* @param writer
*/
public ConvertingParameterAccessor(MongoWriter<Object> writer, ParameterAccessor delegate) {
this.writer = writer;
this.delegate = delegate;
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.query.ParameterAccessor#getPageable()
*/
public Pageable getPageable() {
return delegate.getPageable();
}
/*
* (non-Javadoc)
*
* @see java.lang.Iterable#iterator()
*/
public Iterator<Object> iterator() {
return new ConvertingIterator(delegate.iterator());
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.query.ParameterAccessor#getSort()
*/
public Sort getSort() {
return delegate.getSort();
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.query.ParameterAccessor#getPageable()
*/
public Pageable getPageable() {
return delegate.getPageable();
}
/* (non-Javadoc)
* @see org.springframework.data.repository.query.ParameterAccessor#getBindableParameter(int)
*/
public Object getBindableValue(int index) {
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.query.ParameterAccessor#getSort()
*/
public Sort getSort() {
return delegate.getSort();
}
return getConvertedValue(delegate.getBindableValue(index));
}
/* (non-Javadoc)
* @see org.springframework.data.repository.query.ParameterAccessor#getBindableParameter(int)
*/
public Object getBindableValue(int index) {
/**
* Converts the given value with the underlying {@link MongoWriter}.
*
* @param value
* @return
*/
private Object getConvertedValue(Object value) {
DBObject result = new BasicDBObject();
writer.write(new ValueHolder(value), result);
return ((DBObject) result.get("value")).get("value");
}
return getConvertedValue(delegate.getBindableValue(index));
}
/**
* Custom {@link Iterator} to convert items before returning them.
*
* @author Oliver Gierke
*/
private class ConvertingIterator implements PotentiallyConvertingIterator {
/**
* Converts the given value with the underlying {@link MongoWriter}.
*
* @param value
* @return
*/
private Object getConvertedValue(Object value) {
private final Iterator<Object> delegate;
DBObject result = new BasicDBObject();
writer.write(new ValueHolder(value), result);
return ((DBObject) result.get("value")).get("value");
}
/**
* Creates a new {@link ConvertingIterator} for the given delegate.
*
* @param delegate
*/
public ConvertingIterator(Iterator<Object> delegate) {
this.delegate = delegate;
}
/**
* Custom {@link Iterator} to convert items before returning them.
*
* @author Oliver Gierke
*/
private class ConvertingIterator implements PotentiallyConvertingIterator {
/*
* (non-Javadoc)
*
* @see java.util.Iterator#hasNext()
*/
public boolean hasNext() {
return delegate.hasNext();
}
private final Iterator<Object> delegate;
/*
* (non-Javadoc)
*
* @see java.util.Iterator#next()
*/
public Object next() {
/**
* Creates a new {@link ConvertingIterator} for the given delegate.
*
* @param delegate
*/
public ConvertingIterator(Iterator<Object> delegate) {
this.delegate = delegate;
}
return delegate.next();
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.repository.ConvertingParameterAccessor.PotentiallConvertingIterator#nextConverted()
*/
public Object nextConverted() {
return getConvertedValue(next());
}
/*
* (non-Javadoc)
*
* @see java.util.Iterator#hasNext()
*/
public boolean hasNext() {
return delegate.hasNext();
}
/*
* (non-Javadoc)
*
* @see java.util.Iterator#remove()
*/
public void remove() {
delegate.remove();
}
}
/*
* (non-Javadoc)
*
* @see java.util.Iterator#next()
*/
public Object next() {
/**
* Simple value holder class to allow conversion and accessing the converted value in a deterministic way.
*
* @author Oliver Gierke
*/
private static class ValueHolder {
return delegate.next();
}
private Map<String, Object> value = new HashMap<String, Object>();
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.repository.ConvertingParameterAccessor.PotentiallConvertingIterator#nextConverted()
*/
public Object nextConverted() {
public ValueHolder(Object value) {
return getConvertedValue(next());
}
this.value.put("value", value);
}
/*
* (non-Javadoc)
*
* @see java.util.Iterator#remove()
*/
public void remove() {
delegate.remove();
}
}
@SuppressWarnings("unused")
public Map<String, Object> getValue() {
/**
* Simple value holder class to allow conversion and accessing the converted value in a deterministic way.
*
* @author Oliver Gierke
*/
private static class ValueHolder {
return value;
}
}
private Map<String, Object> value = new HashMap<String, Object>();
/**
* Custom {@link Iterator} that adds a method to access elements in a converted manner.
*
* @author Oliver Gierke
*/
public interface PotentiallyConvertingIterator extends Iterator<Object> {
/**
* Returns the next element which has already been converted.
*
* @return
*/
Object nextConverted();
}
public ValueHolder(Object value) {
this.value.put("value", value);
}
@SuppressWarnings("unused")
public Map<String, Object> getValue() {
return value;
}
}
/**
* Custom {@link Iterator} that adds a method to access elements in a converted manner.
*
* @author Oliver Gierke
*/
public interface PotentiallyConvertingIterator extends Iterator<Object> {
/**
* Returns the next element which has already been converted.
*
* @return
*/
Object nextConverted();
}
}

View File

@@ -23,61 +23,61 @@ import org.springframework.data.mapping.MappingBeanHelper;
import org.springframework.data.repository.support.AbstractEntityInformation;
/**
* {@link MongoEntityInformation} implementation using a {@link BasicMongoPersistentEntity} instance to lookup the necessary
* information.
* {@link MongoEntityInformation} implementation using a {@link BasicMongoPersistentEntity} instance to lookup the
* necessary information.
*
* @author Oliver Gierke
*/
public class MappingMongoEntityInformation<T, ID extends Serializable> extends AbstractEntityInformation<T, ID>
implements MongoEntityInformation<T, ID> {
implements MongoEntityInformation<T, ID> {
private final MongoPersistentEntity<T> entityMetadata;
private final MongoPersistentEntity<T> entityMetadata;
/**
* Creates a new {@link MappingMongoEntityInformation} for the given {@link MongoPersistentEntity}.
*
* @param domainClass
* @param entity
*/
public MappingMongoEntityInformation(MongoPersistentEntity<T> entity) {
super(entity.getType());
this.entityMetadata = entity;
}
/**
* Creates a new {@link MappingMongoEntityInformation} for the given {@link MongoPersistentEntity}.
*
* @param domainClass
* @param entity
*/
public MappingMongoEntityInformation(MongoPersistentEntity<T> entity) {
super(entity.getType());
this.entityMetadata = entity;
}
/* (non-Javadoc)
* @see org.springframework.data.repository.support.EntityInformation#getId(java.lang.Object)
*/
@SuppressWarnings("unchecked")
public ID getId(T entity) {
/* (non-Javadoc)
* @see org.springframework.data.repository.support.EntityInformation#getId(java.lang.Object)
*/
@SuppressWarnings("unchecked")
public ID getId(T entity) {
MongoPersistentProperty idProperty = entityMetadata.getIdProperty();
MongoPersistentProperty idProperty = entityMetadata.getIdProperty();
try {
return (ID) MappingBeanHelper.getProperty(entity, idProperty, idProperty.getType(), false);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
try {
return (ID) MappingBeanHelper.getProperty(entity, idProperty, idProperty.getType(), false);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/* (non-Javadoc)
* @see org.springframework.data.repository.support.EntityInformation#getIdType()
*/
@SuppressWarnings("unchecked")
public Class<ID> getIdType() {
return (Class<ID>) entityMetadata.getIdProperty().getType();
}
/* (non-Javadoc)
* @see org.springframework.data.repository.support.EntityInformation#getIdType()
*/
@SuppressWarnings("unchecked")
public Class<ID> getIdType() {
return (Class<ID>) entityMetadata.getIdProperty().getType();
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.repository.MongoEntityInformation#getCollectionName()
*/
public String getCollectionName() {
return entityMetadata.getCollection();
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.repository.MongoEntityInformation#getCollectionName()
*/
public String getCollectionName() {
return entityMetadata.getCollection();
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.repository.MongoEntityInformation#getIdAttribute()
*/
public String getIdAttribute() {
return entityMetadata.getIdProperty().getName();
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.repository.MongoEntityInformation#getIdAttribute()
*/
public String getIdAttribute() {
return entityMetadata.getIdProperty().getName();
}
}

View File

@@ -46,20 +46,20 @@ import com.mysema.query.apt.Processor;
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class MongoAnnotationProcessor extends AbstractProcessor {
private Class<? extends Annotation> entities, entity, embedded, skip;
private Class<? extends Annotation> entities, entity, embedded, skip;
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Running " + getClass().getSimpleName());
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Running " + getClass().getSimpleName());
DefaultConfiguration configuration = new DefaultConfiguration(roundEnv, processingEnv.getOptions(),
Collections.<String> emptySet(), QueryEntities.class, Document.class, QuerySupertype.class,
QueryEmbeddable.class, QueryEmbedded.class, QueryTransient.class);
configuration.setUnknownAsEmbedded(true);
DefaultConfiguration configuration = new DefaultConfiguration(roundEnv, processingEnv.getOptions(),
Collections.<String> emptySet(), QueryEntities.class, Document.class, QuerySupertype.class,
QueryEmbeddable.class, QueryEmbedded.class, QueryTransient.class);
configuration.setUnknownAsEmbedded(true);
Processor processor = new Processor(processingEnv, roundEnv, configuration);
processor.process();
return true;
}
Processor processor = new Processor(processingEnv, roundEnv, configuration);
processor.process();
return true;
}
}

View File

@@ -21,22 +21,22 @@ import org.springframework.data.repository.support.EntityInformation;
/**
* Mongo specific {@link EntityInformation}.
*
*
* @author Oliver Gierke
*/
public interface MongoEntityInformation<T, ID extends Serializable> extends EntityInformation<T, ID> {
/**
* Returns the name of the collection the entity shall be persisted to.
*
* @return
*/
String getCollectionName();
/**
* Returns the name of the collection the entity shall be persisted to.
*
* @return
*/
String getCollectionName();
/**
* Returns the attribute that the id will be persisted to.
*
* @return
*/
String getIdAttribute();
/**
* Returns the attribute that the id will be persisted to.
*
* @return
*/
String getIdAttribute();
}

View File

@@ -38,174 +38,165 @@ import org.springframework.data.repository.query.parser.Part;
import org.springframework.data.repository.query.parser.Part.Type;
import org.springframework.data.repository.query.parser.PartTree;
/**
* Custom query creator to create Mongo criterias.
*
*
* @author Oliver Gierke
*/
class MongoQueryCreator extends AbstractQueryCreator<Query, Query> {
private static final Log LOG = LogFactory.getLog(MongoQueryCreator.class);
private static final Log LOG = LogFactory.getLog(MongoQueryCreator.class);
/**
* Creates a new {@link MongoQueryCreator} from the given {@link PartTree} and {@link ParametersParameterAccessor}.
*
* @param tree
* @param accessor
*/
public MongoQueryCreator(PartTree tree, ParameterAccessor accessor) {
/**
* Creates a new {@link MongoQueryCreator} from the given {@link PartTree}
* and {@link ParametersParameterAccessor}.
*
* @param tree
* @param accessor
*/
public MongoQueryCreator(PartTree tree, ParameterAccessor accessor) {
super(tree, accessor);
}
super(tree, accessor);
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.query.parser.AbstractQueryCreator#create(org.springframework.data.repository.query.parser.Part, java.util.Iterator)
*/
@Override
protected Query create(Part part, Iterator<Object> iterator) {
Criteria criteria = from(part.getType(), where(part.getProperty().toDotPath()),
(PotentiallyConvertingIterator) iterator);
/*
* (non-Javadoc)
* @see org.springframework.data.repository.query.parser.AbstractQueryCreator#create(org.springframework.data.repository.query.parser.Part, java.util.Iterator)
*/
@Override
protected Query create(Part part, Iterator<Object> iterator) {
return new Query(criteria);
}
Criteria criteria = from(part.getType(),
where(part.getProperty().toDotPath()), (PotentiallyConvertingIterator) iterator);
/*
* (non-Javadoc)
* @see org.springframework.data.repository.query.parser.AbstractQueryCreator#and(org.springframework.data.repository.query.parser.Part, java.lang.Object, java.util.Iterator)
*/
@Override
protected Query and(Part part, Query base, Iterator<Object> iterator) {
return new Query(criteria);
}
Criteria criteria = from(part.getType(), where(part.getProperty().toDotPath()),
(PotentiallyConvertingIterator) iterator);
return base.addCriteria(criteria);
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.query.parser.AbstractQueryCreator
* #or(java.lang.Object, java.lang.Object)
*/
@Override
protected Query or(Query base, Query query) {
/*
* (non-Javadoc)
* @see org.springframework.data.repository.query.parser.AbstractQueryCreator#and(org.springframework.data.repository.query.parser.Part, java.lang.Object, java.util.Iterator)
*/
@Override
protected Query and(Part part, Query base,
Iterator<Object> iterator) {
return new Query().or(base, query);
}
Criteria criteria = from(part.getType(), where(part.getProperty().toDotPath()),
(PotentiallyConvertingIterator) iterator);
return base.addCriteria(criteria);
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.query.parser.AbstractQueryCreator
* #complete(java.lang.Object, org.springframework.data.domain.Sort)
*/
@Override
protected Query complete(Query query, Sort sort) {
if (LOG.isDebugEnabled()) {
LOG.debug("Created query " + query.getQueryObject());
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.query.parser.AbstractQueryCreator
* #or(java.lang.Object, java.lang.Object)
*/
@Override
protected Query or(Query base, Query query) {
return query;
}
return new Query().or(base, query);
}
/**
* Populates the given {@link CriteriaDefinition} depending on the {@link Type} given.
*
* @param type
* @param criteria
* @param parameters
* @return
*/
private Criteria from(Type type, Criteria criteria, PotentiallyConvertingIterator parameters) {
switch (type) {
case GREATER_THAN:
return criteria.gt(parameters.nextConverted());
case LESS_THAN:
return criteria.lt(parameters.nextConverted());
case BETWEEN:
return criteria.gt(parameters.nextConverted()).lt(parameters.nextConverted());
case IS_NOT_NULL:
return criteria.ne(null);
case IS_NULL:
return criteria.is(null);
case NOT_IN:
return criteria.nin(nextAsArray(parameters));
case IN:
return criteria.in(nextAsArray(parameters));
case LIKE:
String value = parameters.next().toString();
return criteria.is(toLikeRegex(value));
case NEAR:
return criteria.near(nextAs(parameters, Point.class));
case WITHIN:
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.query.parser.AbstractQueryCreator
* #complete(java.lang.Object, org.springframework.data.domain.Sort)
*/
@Override
protected Query complete(Query query, Sort sort) {
Object parameter = parameters.next();
if (parameter instanceof Box) {
return criteria.withinBox((Box) parameter);
} else if (parameter instanceof Circle) {
return criteria.withinCenter((Circle) parameter);
}
throw new IllegalArgumentException("Parameter has to be either Box or Circle!");
case SIMPLE_PROPERTY:
return criteria.is(parameters.nextConverted());
case NEGATING_SIMPLE_PROPERTY:
return criteria.not().is(parameters.nextConverted());
}
if (LOG.isDebugEnabled()) {
LOG.debug("Created query " + query.getQueryObject());
}
throw new IllegalArgumentException("Unsupported keyword!");
}
return query;
}
/**
* Returns the next element from the given {@link Iterator} expecting it to be of a certain type.
*
* @param <T>
* @param iterator
* @param type
* @throws IllegalArgumentException
* in case the next element in the iterator is not of the given type.
* @return
*/
@SuppressWarnings("unchecked")
private <T> T nextAs(Iterator<Object> iterator, Class<T> type) {
Object parameter = iterator.next();
if (parameter.getClass().isAssignableFrom(type)) {
return (T) parameter;
}
throw new IllegalArgumentException(String.format("Expected parameter type of %s but got %s!", type,
parameter.getClass()));
}
/**
* Populates the given {@link CriteriaDefinition} depending on the {@link Type} given.
*
* @param type
* @param criteria
* @param parameters
* @return
*/
private Criteria from(Type type, Criteria criteria, PotentiallyConvertingIterator parameters) {
private Object[] nextAsArray(PotentiallyConvertingIterator iterator) {
Object next = iterator.nextConverted();
switch (type) {
case GREATER_THAN:
return criteria.gt(parameters.nextConverted());
case LESS_THAN:
return criteria.lt(parameters.nextConverted());
case BETWEEN:
return criteria.gt(parameters.nextConverted()).lt(parameters.nextConverted());
case IS_NOT_NULL:
return criteria.ne(null);
case IS_NULL:
return criteria.is(null);
case NOT_IN:
return criteria.nin(nextAsArray(parameters));
case IN:
return criteria.in(nextAsArray(parameters));
case LIKE:
String value = parameters.next().toString();
return criteria.is(toLikeRegex(value));
case NEAR:
return criteria.near(nextAs(parameters, Point.class));
case WITHIN:
Object parameter = parameters.next();
if (parameter instanceof Box) {
return criteria.withinBox((Box) parameter);
} else if (parameter instanceof Circle) {
return criteria.withinCenter((Circle) parameter);
}
throw new IllegalArgumentException("Parameter has to be either Box or Circle!");
case SIMPLE_PROPERTY:
return criteria.is(parameters.nextConverted());
case NEGATING_SIMPLE_PROPERTY:
return criteria.not().is(parameters.nextConverted());
}
if (next instanceof Collection) {
return ((Collection<?>) next).toArray();
} else if (next.getClass().isArray()) {
return (Object[]) next;
}
throw new IllegalArgumentException("Unsupported keyword!");
}
return new Object[] { next };
}
/**
* Returns the next element from the given {@link Iterator} expecting it to be of a certain type.
*
* @param <T>
* @param iterator
* @param type
* @throws IllegalArgumentException
* in case the next element in the iterator is not of the given type.
* @return
*/
@SuppressWarnings("unchecked")
private <T> T nextAs(Iterator<Object> iterator, Class<T> type) {
Object parameter = iterator.next();
if (parameter.getClass().isAssignableFrom(type)) {
return (T) parameter;
}
private Pattern toLikeRegex(String source) {
throw new IllegalArgumentException(String.format("Expected parameter type of %s but got %s!", type,
parameter.getClass()));
}
private Object[] nextAsArray(PotentiallyConvertingIterator iterator) {
Object next = iterator.nextConverted();
if (next instanceof Collection) {
return ((Collection<?>) next).toArray();
} else if (next.getClass().isArray()) {
return (Object[]) next;
}
return new Object[]{next};
}
private Pattern toLikeRegex(String source) {
String regex = source.replaceAll("\\*", ".*");
return Pattern.compile(regex);
}
String regex = source.replaceAll("\\*", ".*");
return Pattern.compile(regex);
}
}

View File

@@ -32,68 +32,68 @@ import org.springframework.util.StringUtils;
*/
class MongoQueryMethod extends QueryMethod {
private final Method method;
private final MongoEntityInformation<?, ?> entityInformation;
private final Method method;
private final MongoEntityInformation<?, ?> entityInformation;
/**
* Creates a new {@link MongoQueryMethod} from the given {@link Method}.
*
* @param method
*/
public MongoQueryMethod(Method method, RepositoryMetadata metadata, EntityInformationCreator entityInformationCreator) {
super(method, metadata);
this.method = method;
this.entityInformation = entityInformationCreator.getEntityInformation(ClassUtils.getReturnedDomainClass(method));
}
/**
* Creates a new {@link MongoQueryMethod} from the given {@link Method}.
*
* @param method
*/
public MongoQueryMethod(Method method, RepositoryMetadata metadata, EntityInformationCreator entityInformationCreator) {
super(method, metadata);
this.method = method;
this.entityInformation = entityInformationCreator.getEntityInformation(ClassUtils.getReturnedDomainClass(method));
}
/**
* Returns whether the method has an annotated query.
*
* @return
*/
boolean hasAnnotatedQuery() {
return getAnnotatedQuery() != null;
}
/**
* Returns whether the method has an annotated query.
*
* @return
*/
boolean hasAnnotatedQuery() {
return getAnnotatedQuery() != null;
}
/**
* Returns the query string declared in a {@link Query} annotation or {@literal null} if neither the annotation found
* nor the attribute was specified.
*
* @return
*/
String getAnnotatedQuery() {
/**
* Returns the query string declared in a {@link Query} annotation or {@literal null} if neither the annotation found
* nor the attribute was specified.
*
* @return
*/
String getAnnotatedQuery() {
String query = (String) AnnotationUtils.getValue(getQueryAnnotation());
return StringUtils.hasText(query) ? query : null;
}
String query = (String) AnnotationUtils.getValue(getQueryAnnotation());
return StringUtils.hasText(query) ? query : null;
}
/**
* Returns the field specification to be used for the query.
*
* @return
*/
String getFieldSpecification() {
/**
* Returns the field specification to be used for the query.
*
* @return
*/
String getFieldSpecification() {
String value = (String) AnnotationUtils.getValue(getQueryAnnotation(), "fields");
return StringUtils.hasText(value) ? value : null;
}
String value = (String) AnnotationUtils.getValue(getQueryAnnotation(), "fields");
return StringUtils.hasText(value) ? value : null;
}
/* (non-Javadoc)
* @see org.springframework.data.repository.query.QueryMethod#getEntityMetadata()
*/
@Override
public MongoEntityInformation<?, ?> getEntityInformation() {
/* (non-Javadoc)
* @see org.springframework.data.repository.query.QueryMethod#getEntityMetadata()
*/
@Override
public MongoEntityInformation<?, ?> getEntityInformation() {
return entityInformation;
}
return entityInformation;
}
/**
* Returns the {@link Query} annotation that is applied to the method or {@code null} if none available.
*
* @return
*/
private Query getQueryAnnotation() {
/**
* Returns the {@link Query} annotation that is applied to the method or {@code null} if none available.
*
* @return
*/
private Query getQueryAnnotation() {
return method.getAnnotation(Query.class);
}
return method.getAnnotation(Query.class);
}
}

View File

@@ -23,7 +23,7 @@ import org.springframework.data.repository.PagingAndSortingRepository;
/**
* Mongo specific {@link org.springframework.data.repository.Repository} interface.
*
*
* @author Oliver Gierke
*/
public interface MongoRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {
@@ -34,18 +34,18 @@ public interface MongoRepository<T, ID extends Serializable> extends PagingAndSo
* @see org.springframework.data.repository.Repository#save(java.lang.Iterable)
*/
List<T> save(Iterable<? extends T> entites);
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.Repository#findAll()
*/
List<T> findAll();
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.PagingAndSortingRepository#findAll(org.springframework.data.domain.Sort)
*/
List<T> findAll(Sort sort);
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.Repository#findAll()
*/
List<T> findAll();
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.PagingAndSortingRepository#findAll(org.springframework.data.domain.Sort)
*/
List<T> findAll(Sort sort);
}

View File

@@ -50,272 +50,277 @@ import org.springframework.util.StringUtils;
/**
* {@link org.springframework.beans.factory.FactoryBean} to create {@link MongoRepository} instances.
*
*
* @author Oliver Gierke
*/
public class MongoRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> extends
RepositoryFactoryBeanSupport<T, S, ID> {
RepositoryFactoryBeanSupport<T, S, ID> {
private MongoTemplate template;
private MappingContext<MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
private MongoTemplate template;
private MappingContext<MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
/**
* Configures the {@link MongoTemplate} to be used.
*
* @param template the template to set
*/
public void setTemplate(MongoTemplate template) {
/**
* Configures the {@link MongoTemplate} to be used.
*
* @param template
* the template to set
*/
public void setTemplate(MongoTemplate template) {
this.template = template;
}
this.template = template;
}
/**
* Sets the {@link MappingContext} used with the underlying {@link MongoTemplate}.
*
* @param mappingContext the mappingContext to set
*/
public void setMappingContext(MappingContext<MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
this.mappingContext = mappingContext;
}
/**
* Sets the {@link MappingContext} used with the underlying {@link MongoTemplate}.
*
* @param mappingContext
* the mappingContext to set
*/
public void setMappingContext(MappingContext<MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
this.mappingContext = mappingContext;
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.support.RepositoryFactoryBeanSupport
* #createRepositoryFactory()
*/
@Override
protected RepositoryFactorySupport createRepositoryFactory() {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.support.RepositoryFactoryBeanSupport
* #createRepositoryFactory()
*/
@Override
protected RepositoryFactorySupport createRepositoryFactory() {
MongoRepositoryFactory factory = new MongoRepositoryFactory(template, mappingContext);
factory.addQueryCreationListener(new IndexEnsuringQueryCreationListener(template));
return factory;
}
MongoRepositoryFactory factory = new MongoRepositoryFactory(template, mappingContext);
factory.addQueryCreationListener(new IndexEnsuringQueryCreationListener(template));
return factory;
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.support.RepositoryFactoryBeanSupport
* #afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.support.RepositoryFactoryBeanSupport
* #afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
Assert.notNull(template, "MongoTemplate must not be null!");
Assert.notNull(mappingContext, "MappingContext must not be null!");
}
super.afterPropertiesSet();
Assert.notNull(template, "MongoTemplate must not be null!");
Assert.notNull(mappingContext, "MappingContext must not be null!");
}
/**
* Repository to create {@link MongoRepository} instances.
*
* @author Oliver Gierke
*/
public static class MongoRepositoryFactory extends RepositoryFactorySupport {
/**
* Repository to create {@link MongoRepository} instances.
*
* @author Oliver Gierke
*/
public static class MongoRepositoryFactory extends RepositoryFactorySupport {
private final MongoTemplate template;
private final EntityInformationCreator entityInformationCreator;
private final MongoTemplate template;
private final EntityInformationCreator entityInformationCreator;
/**
* Creates a new {@link MongoRepositoryFactory} with the given {@link MongoTemplate} and {@link MappingContext}.
*
* @param template must not be {@literal null}
* @param mappingContext
*/
public MongoRepositoryFactory(MongoTemplate template, MappingContext<MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
/**
* Creates a new {@link MongoRepositoryFactory} with the given {@link MongoTemplate} and {@link MappingContext}.
*
* @param template
* must not be {@literal null}
* @param mappingContext
*/
public MongoRepositoryFactory(MongoTemplate template,
MappingContext<MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
Assert.notNull(template);
Assert.notNull(mappingContext);
this.template = template;
this.entityInformationCreator = new EntityInformationCreator(mappingContext);
}
Assert.notNull(template);
Assert.notNull(mappingContext);
this.template = template;
this.entityInformationCreator = new EntityInformationCreator(mappingContext);
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.support.RepositoryFactorySupport
* #getRepositoryBaseClass()
*/
@Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.support.RepositoryFactorySupport
* #getRepositoryBaseClass()
*/
@Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
return isQueryDslRepository(metadata.getRepositoryInterface()) ? QueryDslMongoRepository.class
: SimpleMongoRepository.class;
}
return isQueryDslRepository(metadata.getRepositoryInterface()) ? QueryDslMongoRepository.class
: SimpleMongoRepository.class;
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.support.RepositoryFactorySupport
* #getTargetRepository
* (org.springframework.data.repository.support.RepositoryMetadata)
*/
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
protected Object getTargetRepository(RepositoryMetadata metadata) {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.support.RepositoryFactorySupport
* #getTargetRepository
* (org.springframework.data.repository.support.RepositoryMetadata)
*/
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
protected Object getTargetRepository(RepositoryMetadata metadata) {
Class<?> repositoryInterface = metadata.getRepositoryInterface();
MongoEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainClass());
Class<?> repositoryInterface = metadata.getRepositoryInterface();
MongoEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainClass());
if (isQueryDslRepository(repositoryInterface)) {
return new QueryDslMongoRepository(entityInformation, template);
} else {
return new SimpleMongoRepository(entityInformation, template);
}
}
if (isQueryDslRepository(repositoryInterface)) {
return new QueryDslMongoRepository(entityInformation, template);
} else {
return new SimpleMongoRepository(entityInformation, template);
}
}
private static boolean isQueryDslRepository(Class<?> repositoryInterface) {
private static boolean isQueryDslRepository(Class<?> repositoryInterface) {
return QUERY_DSL_PRESENT && QueryDslPredicateExecutor.class.isAssignableFrom(repositoryInterface);
}
return QUERY_DSL_PRESENT && QueryDslPredicateExecutor.class.isAssignableFrom(repositoryInterface);
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.support.RepositoryFactorySupport
* #getQueryLookupStrategy
* (org.springframework.data.repository.query.QueryLookupStrategy.Key)
*/
@Override
protected QueryLookupStrategy getQueryLookupStrategy(Key key) {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.support.RepositoryFactorySupport
* #getQueryLookupStrategy
* (org.springframework.data.repository.query.QueryLookupStrategy.Key)
*/
@Override
protected QueryLookupStrategy getQueryLookupStrategy(Key key) {
return new MongoQueryLookupStrategy();
}
return new MongoQueryLookupStrategy();
}
/**
* {@link QueryLookupStrategy} to create {@link PartTreeMongoQuery} instances.
*
* @author Oliver Gierke
*/
private class MongoQueryLookupStrategy implements QueryLookupStrategy {
/**
* {@link QueryLookupStrategy} to create {@link PartTreeMongoQuery} instances.
*
* @author Oliver Gierke
*/
private class MongoQueryLookupStrategy implements QueryLookupStrategy {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.query.QueryLookupStrategy
* #resolveQuery(java.lang.reflect.Method, java.lang.Class)
*/
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata) {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.query.QueryLookupStrategy
* #resolveQuery(java.lang.reflect.Method, java.lang.Class)
*/
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata) {
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, entityInformationCreator);
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, entityInformationCreator);
if (queryMethod.hasAnnotatedQuery()) {
return new StringBasedMongoQuery(queryMethod, template);
} else {
return new PartTreeMongoQuery(queryMethod, template);
}
}
}
if (queryMethod.hasAnnotatedQuery()) {
return new StringBasedMongoQuery(queryMethod, template);
} else {
return new PartTreeMongoQuery(queryMethod, template);
}
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.support.RepositoryFactorySupport#validate(org.springframework.data.repository.support.RepositoryMetadata)
*/
@Override
protected void validate(RepositoryMetadata metadata) {
/*
* (non-Javadoc)
* @see org.springframework.data.repository.support.RepositoryFactorySupport#validate(org.springframework.data.repository.support.RepositoryMetadata)
*/
@Override
protected void validate(RepositoryMetadata metadata) {
Class<?> idClass = metadata.getIdClass();
if (!MongoPropertyDescriptor.SUPPORTED_ID_CLASSES.contains(idClass)) {
throw new IllegalArgumentException(String.format("Unsupported id class! Only %s are supported!",
StringUtils.collectionToCommaDelimitedString(MongoPropertyDescriptor.SUPPORTED_ID_CLASSES)));
}
}
Class<?> idClass = metadata.getIdClass();
if (!MongoPropertyDescriptor.SUPPORTED_ID_CLASSES.contains(idClass)) {
throw new IllegalArgumentException(String.format("Unsupported id class! Only %s are supported!",
StringUtils.collectionToCommaDelimitedString(MongoPropertyDescriptor.SUPPORTED_ID_CLASSES)));
}
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.support.RepositoryFactorySupport
* #getEntityInformation(java.lang.Class)
*/
@Override
public <T, ID extends Serializable> MongoEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.support.RepositoryFactorySupport
* #getEntityInformation(java.lang.Class)
*/
@Override
public <T, ID extends Serializable> MongoEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
return entityInformationCreator.getEntityInformation(domainClass);
}
}
return entityInformationCreator.getEntityInformation(domainClass);
}
}
/**
* Simple wrapper to to create {@link MongoEntityInformation} instances based on a {@link MappingContext}.
*
* @author Oliver Gierke
*/
static class EntityInformationCreator {
/**
* Simple wrapper to to create {@link MongoEntityInformation} instances based on a {@link MappingContext}.
*
* @author Oliver Gierke
*/
static class EntityInformationCreator {
private final MappingContext<MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
private final MappingContext<MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
public EntityInformationCreator(MappingContext<MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
Assert.notNull(mappingContext);
this.mappingContext = mappingContext;
}
public EntityInformationCreator(MappingContext<MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
Assert.notNull(mappingContext);
this.mappingContext = mappingContext;
}
@SuppressWarnings("unchecked")
public <T, ID extends Serializable> MongoEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
MongoPersistentEntity<T> persistentEntity = (MongoPersistentEntity<T>) mappingContext.getPersistentEntity(domainClass);
return new MappingMongoEntityInformation<T, ID>(persistentEntity);
}
}
@SuppressWarnings("unchecked")
public <T, ID extends Serializable> MongoEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
MongoPersistentEntity<T> persistentEntity = (MongoPersistentEntity<T>) mappingContext
.getPersistentEntity(domainClass);
return new MappingMongoEntityInformation<T, ID>(persistentEntity);
}
}
/**
* {@link QueryCreationListener} inspecting {@link PartTreeMongoQuery}s and creating an index for the properties it
* refers to.
*
* @author Oliver Gierke
*/
private static class IndexEnsuringQueryCreationListener implements QueryCreationListener<PartTreeMongoQuery> {
/**
* {@link QueryCreationListener} inspecting {@link PartTreeMongoQuery}s and creating an index for the properties it
* refers to.
*
* @author Oliver Gierke
*/
private static class IndexEnsuringQueryCreationListener implements QueryCreationListener<PartTreeMongoQuery> {
private static final Set<Type> GEOSPATIAL_TYPES = new HashSet<Part.Type>(Arrays.asList(Type.NEAR, Type.WITHIN));
private static final Log LOG = LogFactory.getLog(IndexEnsuringQueryCreationListener.class);
private final MongoOperations operations;
private static final Set<Type> GEOSPATIAL_TYPES = new HashSet<Part.Type>(Arrays.asList(Type.NEAR, Type.WITHIN));
private static final Log LOG = LogFactory.getLog(IndexEnsuringQueryCreationListener.class);
private final MongoOperations operations;
public IndexEnsuringQueryCreationListener(MongoOperations operations) {
public IndexEnsuringQueryCreationListener(MongoOperations operations) {
this.operations = operations;
}
this.operations = operations;
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.support.QueryCreationListener
* #onCreation(org.springframework.data.repository
* .query.RepositoryQuery)
*/
public void onCreation(PartTreeMongoQuery query) {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.support.QueryCreationListener
* #onCreation(org.springframework.data.repository
* .query.RepositoryQuery)
*/
public void onCreation(PartTreeMongoQuery query) {
PartTree tree = query.getTree();
Index index = new Index();
index.named(query.getQueryMethod().getName());
Sort sort = tree.getSort();
PartTree tree = query.getTree();
Index index = new Index();
index.named(query.getQueryMethod().getName());
Sort sort = tree.getSort();
for (Part part : tree.getParts()) {
if (GEOSPATIAL_TYPES.contains(part.getType())) {
return;
}
String property = part.getProperty().toDotPath();
Order order = toOrder(sort, property);
index.on(property, order);
}
for (Part part : tree.getParts()) {
if (GEOSPATIAL_TYPES.contains(part.getType())) {
return;
}
String property = part.getProperty().toDotPath();
Order order = toOrder(sort, property);
index.on(property, order);
}
MongoEntityInformation<?, ?> metadata = query.getQueryMethod().getEntityInformation();
operations.ensureIndex(metadata.getCollectionName(), index);
LOG.debug(String.format("Created %s!", index));
}
MongoEntityInformation<?, ?> metadata = query.getQueryMethod().getEntityInformation();
operations.ensureIndex(metadata.getCollectionName(), index);
LOG.debug(String.format("Created %s!", index));
}
private static Order toOrder(Sort sort, String property) {
private static Order toOrder(Sort sort, String property) {
if (sort == null) {
return Order.DESCENDING;
}
if (sort == null) {
return Order.DESCENDING;
}
org.springframework.data.domain.Sort.Order order = sort.getOrderFor(property);
return order == null ? Order.DESCENDING : order.isAscending() ? Order.ASCENDING : Order.DESCENDING;
}
}
org.springframework.data.domain.Sort.Order order = sort.getOrderFor(property);
return order == null ? Order.DESCENDING : order.isAscending() ? Order.ASCENDING : Order.DESCENDING;
}
}
}

View File

@@ -23,43 +23,43 @@ import org.springframework.data.repository.query.parser.PartTree;
/**
* {@link RepositoryQuery} implementation for Mongo.
*
*
* @author Oliver Gierke
*/
public class PartTreeMongoQuery extends AbstractMongoQuery {
private final PartTree tree;
private final PartTree tree;
/**
* Creates a new {@link PartTreeMongoQuery} from the given {@link QueryMethod} and {@link MongoTemplate}.
*
* @param method
* @param template
*/
public PartTreeMongoQuery(MongoQueryMethod method, MongoTemplate template) {
/**
* Creates a new {@link PartTreeMongoQuery} from the given {@link QueryMethod} and {@link MongoTemplate}.
*
* @param method
* @param template
*/
public PartTreeMongoQuery(MongoQueryMethod method, MongoTemplate template) {
super(method, template);
this.tree = new PartTree(method.getName(), method.getEntityInformation().getJavaType());
}
super(method, template);
this.tree = new PartTree(method.getName(), method.getEntityInformation().getJavaType());
}
/**
* @return the tree
*/
public PartTree getTree() {
return tree;
}
/**
* @return the tree
*/
public PartTree getTree() {
return tree;
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.document.mongodb.repository.AbstractMongoQuery#createQuery(org.springframework.data.
* document.mongodb.repository.ConvertingParameterAccessor)
*/
@Override
protected Query createQuery(ConvertingParameterAccessor accessor) {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.document.mongodb.repository.AbstractMongoQuery#createQuery(org.springframework.data.
* document.mongodb.repository.ConvertingParameterAccessor)
*/
@Override
protected Query createQuery(ConvertingParameterAccessor accessor) {
MongoQueryCreator creator = new MongoQueryCreator(tree, accessor);
return creator.createQuery();
}
MongoQueryCreator creator = new MongoQueryCreator(tree, accessor);
return creator.createQuery();
}
}

View File

@@ -28,19 +28,19 @@ import java.lang.annotation.*;
@Documented
public @interface Query {
/**
* Takes a MongoDB JSON string to define the actual query to be executed. This one will take precendece over the
* method name then.
*
* @return
*/
String value() default "";
/**
* Takes a MongoDB JSON string to define the actual query to be executed. This one will take precendece over the
* method name then.
*
* @return
*/
String value() default "";
/**
* Defines the fields that should be returned for the given query. Note that only these fields will make it into the
* domain object returned.
*
* @return
*/
String fields() default "";
/**
* Defines the fields that should be returned for the given query. Note that only these fields will make it into the
* domain object returned.
*
* @return
*/
String fields() default "";
}

View File

@@ -40,250 +40,221 @@ import com.mysema.query.types.OrderSpecifier;
import com.mysema.query.types.Predicate;
import com.mysema.query.types.path.PathBuilder;
/**
* Special QueryDsl based repository implementation that allows execution
* {@link Predicate}s in various forms. TODO: Extract {@link EntityPathResolver}
* into Spring Data Commons TODO: Refactor Spring Data JPA to use this common
* Special QueryDsl based repository implementation that allows execution {@link Predicate}s in various forms. TODO:
* Extract {@link EntityPathResolver} into Spring Data Commons TODO: Refactor Spring Data JPA to use this common
* infrastructure
*
* @author Oliver Gierke
*/
public class QueryDslMongoRepository<T, ID extends Serializable> extends
SimpleMongoRepository<T, ID> implements QueryDslPredicateExecutor<T> {
public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleMongoRepository<T, ID> implements
QueryDslPredicateExecutor<T> {
private final MongoConverterTransformer transformer;
private final MongodbSerializer serializer;
private final PathBuilder<T> builder;
private final MongoConverterTransformer transformer;
private final MongodbSerializer serializer;
private final PathBuilder<T> builder;
/**
* Creates a new {@link QueryDslMongoRepository} for the given {@link EntityMetadata} and {@link MongoTemplate}. Uses
* the {@link SimpleEntityPathResolver} to create an {@link EntityPath} for the given domain class.
*
* @param entityInformation
* @param template
*/
public QueryDslMongoRepository(MongoEntityInformation<T, ID> entityInformation, MongoTemplate template) {
/**
* Creates a new {@link QueryDslMongoRepository} for the given
* {@link EntityMetadata} and {@link MongoTemplate}. Uses the
* {@link SimpleEntityPathResolver} to create an {@link EntityPath} for the
* given domain class.
*
* @param entityInformation
* @param template
*/
public QueryDslMongoRepository(
MongoEntityInformation<T, ID> entityInformation, MongoTemplate template) {
this(entityInformation, template, SimpleEntityPathResolver.INSTANCE);
}
this(entityInformation, template, SimpleEntityPathResolver.INSTANCE);
}
/**
* Creates a new {@link QueryDslMongoRepository} for the given {@link MongoEntityInformation}, {@link MongoTemplate}
* and {@link EntityPathResolver}.
*
* @param entityInformation
* @param template
* @param resolver
*/
public QueryDslMongoRepository(MongoEntityInformation<T, ID> entityInformation, MongoTemplate template,
EntityPathResolver resolver) {
super(entityInformation, template);
this.transformer = new MongoConverterTransformer(template.getConverter());
this.serializer = new MongodbSerializer();
/**
* Creates a new {@link QueryDslMongoRepository} for the given {@link MongoEntityInformation},
* {@link MongoTemplate} and {@link EntityPathResolver}.
*
* @param entityInformation
* @param template
* @param resolver
*/
public QueryDslMongoRepository(
MongoEntityInformation<T, ID> entityInformation,
MongoTemplate template, EntityPathResolver resolver) {
EntityPath<T> path = resolver.createPath(entityInformation.getJavaType());
this.builder = new PathBuilder<T>(path.getType(), path.getMetadata());
}
super(entityInformation, template);
this.transformer = new MongoConverterTransformer(template.getConverter());
this.serializer = new MongodbSerializer();
EntityPath<T> path = resolver.createPath(entityInformation.getJavaType());
this.builder = new PathBuilder<T>(path.getType(), path.getMetadata());
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.document.mongodb.repository.QueryDslExecutor
* #findOne(com.mysema.query.types.Predicate)
*/
public T findOne(Predicate predicate) {
return createQueryFor(predicate).uniqueResult();
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.document.mongodb.repository.QueryDslExecutor
* #findOne(com.mysema.query.types.Predicate)
*/
public T findOne(Predicate predicate) {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.document.mongodb.repository.QueryDslExecutor
* #findAll(com.mysema.query.types.Predicate)
*/
public List<T> findAll(Predicate predicate) {
return createQueryFor(predicate).uniqueResult();
}
return createQueryFor(predicate).list();
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.document.mongodb.repository.QueryDslExecutor
* #findAll(com.mysema.query.types.Predicate,
* com.mysema.query.types.OrderSpecifier<?>[])
*/
public List<T> findAll(Predicate predicate, OrderSpecifier<?>... orders) {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.document.mongodb.repository.QueryDslExecutor
* #findAll(com.mysema.query.types.Predicate)
*/
public List<T> findAll(Predicate predicate) {
return createQueryFor(predicate).orderBy(orders).list();
}
return createQueryFor(predicate).list();
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.document.mongodb.repository.QueryDslExecutor
* #findAll(com.mysema.query.types.Predicate,
* org.springframework.data.domain.Pageable)
*/
public Page<T> findAll(Predicate predicate, Pageable pageable) {
MongodbQuery<T> countQuery = createQueryFor(predicate);
MongodbQuery<T> query = createQueryFor(predicate);
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.document.mongodb.repository.QueryDslExecutor
* #findAll(com.mysema.query.types.Predicate,
* com.mysema.query.types.OrderSpecifier<?>[])
*/
public List<T> findAll(Predicate predicate, OrderSpecifier<?>... orders) {
return new PageImpl<T>(applyPagination(query, pageable).list(), pageable, countQuery.count());
}
return createQueryFor(predicate).orderBy(orders).list();
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.document.mongodb.repository.QueryDslExecutor
* #count(com.mysema.query.types.Predicate)
*/
public long count(Predicate predicate) {
return createQueryFor(predicate).count();
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.document.mongodb.repository.QueryDslExecutor
* #findAll(com.mysema.query.types.Predicate,
* org.springframework.data.domain.Pageable)
*/
public Page<T> findAll(Predicate predicate, Pageable pageable) {
/**
* Creates a {@link MongodbQuery} for the given {@link Predicate}.
*
* @param predicate
* @return
*/
private MongodbQuery<T> createQueryFor(Predicate predicate) {
MongodbQuery<T> countQuery = createQueryFor(predicate);
MongodbQuery<T> query = createQueryFor(predicate);
MongodbQuery<T> query = new MongoTemplateQuery(getMongoOperations());
return query.where(predicate);
}
return new PageImpl<T>(applyPagination(query, pageable).list(),
pageable, countQuery.count());
}
/**
* Applies the given {@link Pageable} to the given {@link MongodbQuery}.
*
* @param query
* @param pageable
* @return
*/
private MongodbQuery<T> applyPagination(MongodbQuery<T> query, Pageable pageable) {
if (pageable == null) {
return query;
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.document.mongodb.repository.QueryDslExecutor
* #count(com.mysema.query.types.Predicate)
*/
public long count(Predicate predicate) {
query = query.offset(pageable.getOffset()).limit(pageable.getPageSize());
return applySorting(query, pageable.getSort());
}
return createQueryFor(predicate).count();
}
/**
* Applies the given {@link Sort} to the given {@link MongodbQuery}.
*
* @param query
* @param sort
* @return
*/
private MongodbQuery<T> applySorting(MongodbQuery<T> query, Sort sort) {
if (sort == null) {
return query;
}
/**
* Creates a {@link MongodbQuery} for the given {@link Predicate}.
*
* @param predicate
* @return
*/
private MongodbQuery<T> createQueryFor(Predicate predicate) {
for (Order order : sort) {
query.orderBy(toOrder(order));
}
MongodbQuery<T> query = new MongoTemplateQuery(getMongoOperations());
return query.where(predicate);
}
return query;
}
/**
* Transforms a plain {@link Order} into a QueryDsl specific {@link OrderSpecifier}.
*
* @param order
* @return
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
private OrderSpecifier<?> toOrder(Order order) {
/**
* Applies the given {@link Pageable} to the given {@link MongodbQuery}.
*
* @param query
* @param pageable
* @return
*/
private MongodbQuery<T> applyPagination(MongodbQuery<T> query,
Pageable pageable) {
Expression<Object> property = builder.get(order.getProperty());
if (pageable == null) {
return query;
}
return new OrderSpecifier(order.isAscending() ? com.mysema.query.types.Order.ASC
: com.mysema.query.types.Order.DESC, property);
}
query =
query.offset(pageable.getOffset())
.limit(pageable.getPageSize());
return applySorting(query, pageable.getSort());
}
/**
* Special {@link MongodbQuery} implementation to use our {@link MongoOperations} for actually accessing Mongo.
*
* @author Oliver Gierke
*/
private class MongoTemplateQuery extends MongodbQuery<T> {
public MongoTemplateQuery(MongoOperations operations) {
super(operations.getCollection(getEntityInformation().getCollectionName()), transformer, serializer);
}
}
/**
* Applies the given {@link Sort} to the given {@link MongodbQuery}.
*
* @param query
* @param sort
* @return
*/
private MongodbQuery<T> applySorting(MongodbQuery<T> query, Sort sort) {
/**
* {@link Transformer} implementation to delegate to a {@link MongoConverter}.
*
* @author Oliver Gierke
*/
private class MongoConverterTransformer implements Transformer<DBObject, T> {
if (sort == null) {
return query;
}
private final MongoConverter converter;
for (Order order : sort) {
query.orderBy(toOrder(order));
}
/**
* Creates a new {@link MongoConverterTransformer} with the given {@link MongoConverter}.
*
* @param converter
*/
public MongoConverterTransformer(MongoConverter converter) {
return query;
}
this.converter = converter;
}
/*
* (non-Javadoc)
*
* @see
* org.apache.commons.collections15.Transformer#transform(java.lang.
* Object)
*/
public T transform(DBObject input) {
/**
* Transforms a plain {@link Order} into a QueryDsl specific
* {@link OrderSpecifier}.
*
* @param order
* @return
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
private OrderSpecifier<?> toOrder(Order order) {
Expression<Object> property = builder.get(order.getProperty());
return new OrderSpecifier(
order.isAscending() ? com.mysema.query.types.Order.ASC
: com.mysema.query.types.Order.DESC, property);
}
/**
* Special {@link MongodbQuery} implementation to use our
* {@link MongoOperations} for actually accessing Mongo.
*
* @author Oliver Gierke
*/
private class MongoTemplateQuery extends MongodbQuery<T> {
public MongoTemplateQuery(MongoOperations operations) {
super(operations.getCollection(getEntityInformation()
.getCollectionName()), transformer, serializer);
}
}
/**
* {@link Transformer} implementation to delegate to a
* {@link MongoConverter}.
*
* @author Oliver Gierke
*/
private class MongoConverterTransformer implements Transformer<DBObject, T> {
private final MongoConverter converter;
/**
* Creates a new {@link MongoConverterTransformer} with the given
* {@link MongoConverter}.
*
* @param converter
*/
public MongoConverterTransformer(MongoConverter converter) {
this.converter = converter;
}
/*
* (non-Javadoc)
*
* @see
* org.apache.commons.collections15.Transformer#transform(java.lang.
* Object)
*/
public T transform(DBObject input) {
return converter.read(getEntityInformation().getJavaType(), input);
}
}
return converter.read(getEntityInformation().getJavaType(), input);
}
}
}

View File

@@ -67,7 +67,8 @@ public interface QueryDslPredicateExecutor<T> {
/**
* Returns the number of instances that the given {@link Predicate} will return.
*
* @param predicate the {@link Predicate} to count instances for
* @param predicate
* the {@link Predicate} to count instances for
* @return the number of instances
*/
long count(Predicate predicate);

View File

@@ -21,65 +21,58 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
/**
* Collection of utility methods to apply sorting and pagination to a
* {@link DBCursor}.
*
* Collection of utility methods to apply sorting and pagination to a {@link DBCursor}.
*
* @author Oliver Gierke
*/
abstract class QueryUtils {
private QueryUtils() {
private QueryUtils() {
}
}
/**
* Applies the given {@link Pageable} to the given {@link Query}. Will do nothing if {@link Pageable} is
* {@literal null}.
*
* @param query
* @param pageable
* @return
*/
public static Query applyPagination(Query query, Pageable pageable) {
/**
* Applies the given {@link Pageable} to the given {@link Query}. Will do
* nothing if {@link Pageable} is {@literal null}.
*
* @param query
* @param pageable
* @return
*/
public static Query applyPagination(Query query, Pageable pageable) {
if (pageable == null) {
return query;
}
if (pageable == null) {
return query;
}
query.limit(pageable.getPageSize());
query.skip(pageable.getOffset());
query.limit(pageable.getPageSize());
query.skip(pageable.getOffset());
return applySorting(query, pageable.getSort());
}
return applySorting(query, pageable.getSort());
}
/**
* Applies the given {@link Sort} to the {@link Query}. Will do nothing if {@link Sort} is {@literal null}.
*
* @param query
* @param sort
* @return
*/
public static Query applySorting(Query query, Sort sort) {
if (sort == null) {
return query;
}
/**
* Applies the given {@link Sort} to the {@link Query}. Will do nothing if
* {@link Sort} is {@literal null}.
*
* @param query
* @param sort
* @return
*/
public static Query applySorting(Query query, Sort sort) {
org.springframework.data.document.mongodb.query.Sort bSort = query.sort();
if (sort == null) {
return query;
}
for (Order order : sort) {
bSort.on(order.getProperty(),
order.isAscending() ? org.springframework.data.document.mongodb.query.Order.ASCENDING
: org.springframework.data.document.mongodb.query.Order.DESCENDING);
}
org.springframework.data.document.mongodb.query.Sort bSort =
query.sort();
for (Order order : sort) {
bSort.on(
order.getProperty(),
order.isAscending() ? org.springframework.data.document.mongodb.query.Order.ASCENDING
: org.springframework.data.document.mongodb.query.Order.DESCENDING);
}
return query;
}
return query;
}
}

View File

@@ -40,220 +40,221 @@ import org.springframework.util.Assert;
*/
public class SimpleMongoRepository<T, ID extends Serializable> implements PagingAndSortingRepository<T, ID> {
private final MongoTemplate template;
private final MongoEntityInformation<T, ID> entityInformation;
private final MongoTemplate template;
private final MongoEntityInformation<T, ID> entityInformation;
/**
* Creates a ew {@link SimpleMongoRepository} for the given {@link MongoEntityInformation} and {@link MongoTemplate}.
*
* @param metadata
* @param template
*/
public SimpleMongoRepository(MongoEntityInformation<T, ID> metadata, MongoTemplate template) {
/**
* Creates a ew {@link SimpleMongoRepository} for the given {@link MongoEntityInformation} and {@link MongoTemplate}.
*
* @param metadata
* @param template
*/
public SimpleMongoRepository(MongoEntityInformation<T, ID> metadata, MongoTemplate template) {
Assert.notNull(template);
Assert.notNull(metadata);
this.entityInformation = metadata;
this.template = template;
}
Assert.notNull(template);
Assert.notNull(metadata);
this.entityInformation = metadata;
this.template = template;
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.Repository#save(java.lang.Object)
*/
public T save(T entity) {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.Repository#save(java.lang.Object)
*/
public T save(T entity) {
template.save(entityInformation.getCollectionName(), entity);
return entity;
}
template.save(entityInformation.getCollectionName(), entity);
return entity;
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.Repository#save(java.lang.Iterable)
*/
public List<T> save(Iterable<? extends T> entities) {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.Repository#save(java.lang.Iterable)
*/
public List<T> save(Iterable<? extends T> entities) {
List<T> result = new ArrayList<T>();
List<T> result = new ArrayList<T>();
for (T entity : entities) {
save(entity);
result.add(entity);
}
for (T entity : entities) {
save(entity);
result.add(entity);
}
return result;
}
return result;
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.Repository#findById(java.io.Serializable
* )
*/
public T findOne(ID id) {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.Repository#findById(java.io.Serializable
* )
*/
public T findOne(ID id) {
return template.findOne(entityInformation.getCollectionName(), getIdQuery(id), entityInformation.getJavaType());
}
return template.findOne(entityInformation.getCollectionName(), getIdQuery(id), entityInformation.getJavaType());
}
private Query getIdQuery(Object id) {
return new Query(getIdCriteria(id));
}
private Query getIdQuery(Object id) {
return new Query(getIdCriteria(id));
}
private Criteria getIdCriteria(Object id) {
return where(entityInformation.getIdAttribute()).is(id);
}
private Criteria getIdCriteria(Object id) {
return where(entityInformation.getIdAttribute()).is(id);
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.Repository#exists(java.io.Serializable
* )
*/
public boolean exists(ID id) {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.Repository#exists(java.io.Serializable
* )
*/
public boolean exists(ID id) {
return findOne(id) != null;
}
return findOne(id) != null;
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.Repository#count()
*/
public long count() {
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.Repository#count()
*/
public long count() {
return template.getCollection(entityInformation.getCollectionName()).count();
}
return template.getCollection(entityInformation.getCollectionName()).count();
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.Repository#delete(java.io.Serializable)
*/
public void delete(ID id) {
delete(findOne(id));
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.Repository#delete(java.lang.Object)
*/
public void delete(T entity) {
/*
* (non-Javadoc)
* @see org.springframework.data.repository.Repository#delete(java.io.Serializable)
*/
public void delete(ID id) {
delete(findOne(id));
}
template.remove(entityInformation.getCollectionName(), getIdQuery(entityInformation.getId(entity)), entity.getClass());
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.Repository#delete(java.lang.Object)
*/
public void delete(T entity) {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.Repository#delete(java.lang.Iterable)
*/
public void delete(Iterable<? extends T> entities) {
template.remove(entityInformation.getCollectionName(), getIdQuery(entityInformation.getId(entity)),
entity.getClass());
}
for (T entity : entities) {
delete(entity);
}
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.Repository#delete(java.lang.Iterable)
*/
public void delete(Iterable<? extends T> entities) {
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.Repository#deleteAll()
*/
public void deleteAll() {
for (T entity : entities) {
delete(entity);
}
}
template.remove(entityInformation.getCollectionName(), new Query());
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.Repository#deleteAll()
*/
public void deleteAll() {
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.Repository#findAll()
*/
public List<T> findAll() {
template.remove(entityInformation.getCollectionName(), new Query());
}
return findAll(new Query());
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.Repository#findAll()
*/
public List<T> findAll() {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.PagingAndSortingRepository#findAll
* (org.springframework.data.domain.Pageable)
*/
public Page<T> findAll(final Pageable pageable) {
return findAll(new Query());
}
Long count = count();
List<T> list = findAll(QueryUtils.applyPagination(new Query(), pageable));
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.PagingAndSortingRepository#findAll
* (org.springframework.data.domain.Pageable)
*/
public Page<T> findAll(final Pageable pageable) {
return new PageImpl<T>(list, pageable, count);
}
Long count = count();
List<T> list = findAll(QueryUtils.applyPagination(new Query(), pageable));
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.PagingAndSortingRepository#findAll
* (org.springframework.data.domain.Sort)
*/
public List<T> findAll(final Sort sort) {
return new PageImpl<T>(list, pageable, count);
}
return findAll(QueryUtils.applySorting(new Query(), sort));
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.PagingAndSortingRepository#findAll
* (org.springframework.data.domain.Sort)
*/
public List<T> findAll(final Sort sort) {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.Repository#findAll(java.lang.Iterable
* )
*/
public List<T> findAll(Iterable<ID> ids) {
return findAll(QueryUtils.applySorting(new Query(), sort));
}
Query query = null;
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.Repository#findAll(java.lang.Iterable
* )
*/
public List<T> findAll(Iterable<ID> ids) {
for (ID id : ids) {
if (query == null) {
query = getIdQuery(id);
} else {
query = new Query().or(getIdQuery(id));
}
}
Query query = null;
return findAll(query);
}
for (ID id : ids) {
if (query == null) {
query = getIdQuery(id);
} else {
query = new Query().or(getIdQuery(id));
}
}
private List<T> findAll(Query query) {
return findAll(query);
}
if (query == null) {
return Collections.emptyList();
}
private List<T> findAll(Query query) {
return template.find(entityInformation.getCollectionName(), query, entityInformation.getJavaType());
}
if (query == null) {
return Collections.emptyList();
}
/**
* Returns the underlying {@link MongoOperations} instance.
*
* @return
*/
protected MongoOperations getMongoOperations() {
return template.find(entityInformation.getCollectionName(), query, entityInformation.getJavaType());
}
return this.template;
}
/**
* Returns the underlying {@link MongoOperations} instance.
*
* @return
*/
protected MongoOperations getMongoOperations() {
/**
* @return the entityInformation
*/
protected MongoEntityInformation<T, ID> getEntityInformation() {
return this.template;
}
return entityInformation;
}
/**
* @return the entityInformation
*/
protected MongoEntityInformation<T, ID> getEntityInformation() {
return entityInformation;
}
}

View File

@@ -27,79 +27,79 @@ import org.springframework.data.document.mongodb.query.Query;
/**
* Query to use a plain JSON String to create the {@link Query} to actually execute.
*
*
* @author Oliver Gierke
*/
public class StringBasedMongoQuery extends AbstractMongoQuery {
private static final Pattern PLACEHOLDER = Pattern.compile("\\?(\\d+)");
private static final Log LOG = LogFactory.getLog(StringBasedMongoQuery.class);
private static final Pattern PLACEHOLDER = Pattern.compile("\\?(\\d+)");
private static final Log LOG = LogFactory.getLog(StringBasedMongoQuery.class);
private final String query;
private final String fieldSpec;
private final String query;
private final String fieldSpec;
/**
* Creates a new {@link StringBasedMongoQuery}.
*
* @param method
* @param template
*/
public StringBasedMongoQuery(MongoQueryMethod method, MongoTemplate template) {
super(method, template);
this.query = method.getAnnotatedQuery();
this.fieldSpec = method.getFieldSpecification();
}
/**
* Creates a new {@link StringBasedMongoQuery}.
*
* @param method
* @param template
*/
public StringBasedMongoQuery(MongoQueryMethod method, MongoTemplate template) {
super(method, template);
this.query = method.getAnnotatedQuery();
this.fieldSpec = method.getFieldSpecification();
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.document.mongodb.repository.AbstractMongoQuery#createQuery(org.springframework.data.
* repository.query.SimpleParameterAccessor, org.springframework.data.document.mongodb.support.convert.MongoConverter)
*/
@Override
protected Query createQuery(ConvertingParameterAccessor accessor) {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.document.mongodb.repository.AbstractMongoQuery#createQuery(org.springframework.data.
* repository.query.SimpleParameterAccessor, org.springframework.data.document.mongodb.support.convert.MongoConverter)
*/
@Override
protected Query createQuery(ConvertingParameterAccessor accessor) {
String queryString = replacePlaceholders(query, accessor);
String queryString = replacePlaceholders(query, accessor);
Query query = null;
Query query = null;
if (fieldSpec != null) {
String fieldString = replacePlaceholders(fieldSpec, accessor);
query = new BasicQuery(queryString, fieldString);
} else {
query = new BasicQuery(queryString);
}
if (fieldSpec != null) {
String fieldString = replacePlaceholders(fieldSpec, accessor);
query = new BasicQuery(queryString, fieldString);
} else {
query = new BasicQuery(queryString);
}
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Created query {}", query.getQueryObject()));
}
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Created query {}", query.getQueryObject()));
}
return query;
}
return query;
}
private String replacePlaceholders(String input, ConvertingParameterAccessor accessor) {
private String replacePlaceholders(String input, ConvertingParameterAccessor accessor) {
Matcher matcher = PLACEHOLDER.matcher(input);
String result = input;
Matcher matcher = PLACEHOLDER.matcher(input);
String result = input;
while (matcher.find()) {
String group = matcher.group();
int index = Integer.parseInt(matcher.group(1));
result = input.replace(group, getParameterWithIndex(accessor, index));
}
while (matcher.find()) {
String group = matcher.group();
int index = Integer.parseInt(matcher.group(1));
result = input.replace(group, getParameterWithIndex(accessor, index));
}
return result;
}
return result;
}
private String getParameterWithIndex(ConvertingParameterAccessor accessor, int index) {
Object parameter = accessor.getBindableValue(index);
if (parameter instanceof String || parameter.getClass().isEnum()) {
return String.format("\"%s\"", parameter);
} else if (parameter instanceof ObjectId) {
return String.format("{ '$oid' : '%s' }", parameter);
}
private String getParameterWithIndex(ConvertingParameterAccessor accessor, int index) {
Object parameter = accessor.getBindableValue(index);
if (parameter instanceof String || parameter.getClass().isEnum()) {
return String.format("\"%s\"", parameter);
} else if (parameter instanceof ObjectId) {
return String.format("{ '$oid' : '%s' }", parameter);
}
return parameter.toString();
}
return parameter.toString();
}
}

View File

@@ -2,3 +2,4 @@
* MongoDB specific repository implementation.
*/
package org.springframework.data.document.mongodb.repository;

View File

@@ -26,25 +26,23 @@ import com.mongodb.Mongo;
@Configuration
public class GeoSpatialAppConfig extends AbstractMongoConfiguration {
@Bean
public Mongo mongo() throws Exception {
return new Mongo("localhost");
}
@Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongo(), "geospatial", mappingMongoConverter());
}
@Bean
public LoggingEventListener<MongoMappingEvent> mappingEventsListener() {
return new LoggingEventListener<MongoMappingEvent>();
}
@Bean
public Mongo mongo() throws Exception {
return new Mongo("localhost");
}
public String getMappingBasePackage() {
return "org.springframework.data.document.mongodb";
}
@Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongo(), "geospatial", mappingMongoConverter());
}
@Bean
public LoggingEventListener<MongoMappingEvent> mappingEventsListener() {
return new LoggingEventListener<MongoMappingEvent>();
}
public String getMappingBasePackage() {
return "org.springframework.data.document.mongodb";
}
}

View File

@@ -51,137 +51,134 @@ import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
import com.mongodb.WriteConcern;
/**
* Modified from https://github.com/deftlabs/mongo-java-geospatial-example
*
* @author Mark Pollack
*
*
*/
public class GeoSpatialTests {
private static final Log LOGGER = LogFactory.getLog(GeoSpatialTests.class);
private final String[] collectionsToDrop = new String[]{"newyork"};
private static final Log LOGGER = LogFactory.getLog(GeoSpatialTests.class);
private final String[] collectionsToDrop = new String[] { "newyork" };
ApplicationContext applicationContext;
MongoTemplate template;
ServerInfo serverInfo;
ExpressionParser parser;
ApplicationContext applicationContext;
MongoTemplate template;
ServerInfo serverInfo;
@Before
public void setUp() throws Exception {
Mongo mongo = new Mongo();
serverInfo = new ServerInfo(mongo);
DB db = mongo.getDB("geospatial");
for (String coll : collectionsToDrop) {
db.getCollection(coll).drop();
}
applicationContext = new AnnotationConfigApplicationContext(GeoSpatialAppConfig.class);
template = applicationContext.getBean(MongoTemplate.class);
template.setWriteConcern(WriteConcern.FSYNC_SAFE);
template.ensureIndex(Venue.class, new GeospatialIndex("location"));
indexCreated();
addVenues();
parser = new SpelExpressionParser();
}
ExpressionParser parser;
private void addVenues() {
template.insert(new Venue("Penn Station", -73.99408, 40.75057));
template.insert(new Venue("10gen Office", -73.99171, 40.738868));
template.insert(new Venue("Flatiron Building", -73.988135, 40.741404));
template.insert(new Venue("Players Club", -73.997812, 40.739128));
template.insert(new Venue("City Bakery ", -73.992491, 40.738673));
template.insert(new Venue("Splash Bar", -73.992491, 40.738673));
template.insert(new Venue("Momofuku Milk Bar", -73.985839, 40.731698));
template.insert(new Venue("Shake Shack", -73.98820, 40.74164));
template.insert(new Venue("Penn Station", -73.99408, 40.75057));
template.insert(new Venue("Empire State Building", -73.98602, 40.74894));
//template.insert(new Venue("Washington Square Park", -73.99756, 40.73083));
template.insert(new Venue("Ulaanbaatar, Mongolia", 106.9154, 47.9245));
template.insert(new Venue("Maplewood, NJ", -74.2713, 40.73137));
}
@Before
public void setUp() throws Exception {
Mongo mongo = new Mongo();
serverInfo = new ServerInfo(mongo);
DB db = mongo.getDB("geospatial");
for (String coll : collectionsToDrop) {
db.getCollection(coll).drop();
}
applicationContext = new AnnotationConfigApplicationContext(GeoSpatialAppConfig.class);
template = applicationContext.getBean(MongoTemplate.class);
template.setWriteConcern(WriteConcern.FSYNC_SAFE);
template.ensureIndex(Venue.class, new GeospatialIndex("location"));
indexCreated();
addVenues();
parser = new SpelExpressionParser();
}
/*
public void geoNear() {
GeoNearResult<Venue> geoNearResult = template.geoNear(new Query(Criteria.where("type").is("Office")), Venue.class,
GeoNearCriteria.near(2,3).num(10).maxDistance(10).distanceMultiplier(10).spherical(true));
}*/
private void addVenues() {
@Test
public void withinCenter() {
Circle circle = new Circle(-73.99171, 40.738868, 0.01);
List<Venue> venues = template.find(new Query(Criteria.where("location").withinCenter(circle)), Venue.class);
assertThat(venues.size(), equalTo(7));
}
@Test
@Ignore("run only on v 1.7.0 server or greater")
public void withinCenterSphere() {
Circle circle = new Circle(-73.99171, 40.738868, 0.003712240453784);
List<Venue> venues = template.find(new Query(Criteria.where("location").withinCenterSphere(circle)), Venue.class);
assertThat(venues.size(), equalTo(11));
}
@Test
public void withinBox() {
Box box = new Box(new Point(-73.99756, 40.73083), new Point(-73.988135, 40.741404));
//Box box = newBox.lowerLeft(x,y).upperRight(x,y);
List<Venue> venues = template.find(new Query(Criteria.where("location").withinBox(box)), Venue.class);
assertThat(venues.size(), equalTo(4));
}
@Test
public void nearPoint() {
Point point = new Point(-73.99171, 40.738868);
List<Venue> venues = template.find(new Query(Criteria.where("location").near(point).maxDistance(0.01)), Venue.class);
assertThat(venues.size(), equalTo(7));
}
@Test
@Ignore("run only on v 1.7.0 server or greater")
public void nearSphere() {
Point point = new Point(-73.99171, 40.738868);
List<Venue> venues = template.find(new Query(Criteria.where("location").nearSphere(point).maxDistance(0.003712240453784)), Venue.class);
assertThat(venues.size(), equalTo(11));
}
template.insert(new Venue("Penn Station", -73.99408, 40.75057));
template.insert(new Venue("10gen Office", -73.99171, 40.738868));
template.insert(new Venue("Flatiron Building", -73.988135, 40.741404));
template.insert(new Venue("Players Club", -73.997812, 40.739128));
template.insert(new Venue("City Bakery ", -73.992491, 40.738673));
template.insert(new Venue("Splash Bar", -73.992491, 40.738673));
template.insert(new Venue("Momofuku Milk Bar", -73.985839, 40.731698));
template.insert(new Venue("Shake Shack", -73.98820, 40.74164));
template.insert(new Venue("Penn Station", -73.99408, 40.75057));
template.insert(new Venue("Empire State Building", -73.98602, 40.74894));
// template.insert(new Venue("Washington Square Park", -73.99756, 40.73083));
template.insert(new Venue("Ulaanbaatar, Mongolia", 106.9154, 47.9245));
template.insert(new Venue("Maplewood, NJ", -74.2713, 40.73137));
}
/*
public void geoNear() {
GeoNearResult<Venue> geoNearResult = template.geoNear(new Query(Criteria.where("type").is("Office")), Venue.class,
GeoNearCriteria.near(2,3).num(10).maxDistance(10).distanceMultiplier(10).spherical(true));
}*/
@Test
public void searchAllData() {
assertThat(template, notNullValue());
Venue foundVenue = template.findOne(
new Query(Criteria.where("name").is("Penn Station")), Venue.class);
assertThat(foundVenue, notNullValue());
List<Venue> venues = template.getCollection(Venue.class);
assertThat(venues.size(), equalTo(12));
Collection names = (Collection)parser.parseExpression("![name]").getValue(venues);
assertThat(names.size(), equalTo(12));
org.springframework.util.Assert.notEmpty(names);
}
public void indexCreated() {
List<DBObject> indexInfo = getIndexInfo(Venue.class);
LOGGER.debug(indexInfo);
assertThat(indexInfo.size(), equalTo(2));
assertThat(indexInfo.get(1).get("name").toString(), equalTo("location_2d"));
assertThat(indexInfo.get(1).get("ns").toString(),
equalTo("geospatial.newyork"));
}
@Test
public void withinCenter() {
// TODO move to MongoAdmin
public List<DBObject> getIndexInfo(Class clazz) {
return template.execute(clazz, new CollectionCallback<List<DBObject>>() {
Circle circle = new Circle(-73.99171, 40.738868, 0.01);
List<Venue> venues = template.find(new Query(Criteria.where("location").withinCenter(circle)), Venue.class);
assertThat(venues.size(), equalTo(7));
}
public List<DBObject> doInCollection(DBCollection collection)
throws MongoException, DataAccessException {
return collection.getIndexInfo();
}
});
}
@Test
@Ignore("run only on v 1.7.0 server or greater")
public void withinCenterSphere() {
Circle circle = new Circle(-73.99171, 40.738868, 0.003712240453784);
List<Venue> venues = template.find(new Query(Criteria.where("location").withinCenterSphere(circle)), Venue.class);
assertThat(venues.size(), equalTo(11));
}
@Test
public void withinBox() {
Box box = new Box(new Point(-73.99756, 40.73083), new Point(-73.988135, 40.741404));
// Box box = newBox.lowerLeft(x,y).upperRight(x,y);
List<Venue> venues = template.find(new Query(Criteria.where("location").withinBox(box)), Venue.class);
assertThat(venues.size(), equalTo(4));
}
@Test
public void nearPoint() {
Point point = new Point(-73.99171, 40.738868);
List<Venue> venues = template
.find(new Query(Criteria.where("location").near(point).maxDistance(0.01)), Venue.class);
assertThat(venues.size(), equalTo(7));
}
@Test
@Ignore("run only on v 1.7.0 server or greater")
public void nearSphere() {
Point point = new Point(-73.99171, 40.738868);
List<Venue> venues = template.find(
new Query(Criteria.where("location").nearSphere(point).maxDistance(0.003712240453784)), Venue.class);
assertThat(venues.size(), equalTo(11));
}
@Test
public void searchAllData() {
assertThat(template, notNullValue());
Venue foundVenue = template.findOne(new Query(Criteria.where("name").is("Penn Station")), Venue.class);
assertThat(foundVenue, notNullValue());
List<Venue> venues = template.getCollection(Venue.class);
assertThat(venues.size(), equalTo(12));
Collection names = (Collection) parser.parseExpression("![name]").getValue(venues);
assertThat(names.size(), equalTo(12));
org.springframework.util.Assert.notEmpty(names);
}
public void indexCreated() {
List<DBObject> indexInfo = getIndexInfo(Venue.class);
LOGGER.debug(indexInfo);
assertThat(indexInfo.size(), equalTo(2));
assertThat(indexInfo.get(1).get("name").toString(), equalTo("location_2d"));
assertThat(indexInfo.get(1).get("ns").toString(), equalTo("geospatial.newyork"));
}
// TODO move to MongoAdmin
public List<DBObject> getIndexInfo(Class clazz) {
return template.execute(clazz, new CollectionCallback<List<DBObject>>() {
public List<DBObject> doInCollection(DBCollection collection) throws MongoException, DataAccessException {
return collection.getIndexInfo();
}
});
}
}

Some files were not shown because too many files have changed in this diff Show More