DATADOC-24 - Added support for using @Query on Mongo repository methods.
Adapted changes from Spring Data Commons. Created ConvertingParameterAccessor that uses a MongoWriter to already convert query method parameters on access. Added @Query annotation to allow defining JSON based queries on query methods using ? placeholders.
This commit is contained in:
@@ -35,7 +35,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-commons-core</artifactId>
|
||||
<version>1.0.0.M3</version>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Logging -->
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,10 +24,10 @@ import org.springframework.data.document.mongodb.MongoTemplate;
|
||||
import org.springframework.data.document.mongodb.query.Query;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.data.repository.query.SimpleParameterAccessor;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.DBCollection;
|
||||
@@ -36,32 +36,30 @@ import com.mongodb.DBObject;
|
||||
|
||||
|
||||
/**
|
||||
* {@link RepositoryQuery} implementation for Mongo.
|
||||
* Base class for {@link RepositoryQuery} implementations for Mongo.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoQuery implements RepositoryQuery {
|
||||
public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
|
||||
private final QueryMethod method;
|
||||
private final MongoTemplate template;
|
||||
private final PartTree tree;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoQuery} from the given {@link QueryMethod} and
|
||||
* Creates a new {@link AbstractMongoQuery} from the given {@link QueryMethod} and
|
||||
* {@link MongoTemplate}.
|
||||
*
|
||||
* @param method
|
||||
* @param template
|
||||
*/
|
||||
public MongoQuery(QueryMethod method, MongoTemplate template) {
|
||||
public AbstractMongoQuery(QueryMethod method, MongoTemplate template) {
|
||||
|
||||
Assert.notNull(template);
|
||||
Assert.notNull(method);
|
||||
|
||||
this.method = method;
|
||||
this.template = template;
|
||||
this.tree = new PartTree(method.getName(), method.getDomainClass());
|
||||
}
|
||||
|
||||
|
||||
@@ -74,22 +72,27 @@ public class MongoQuery implements RepositoryQuery {
|
||||
*/
|
||||
public Object execute(Object[] parameters) {
|
||||
|
||||
SimpleParameterAccessor accessor =
|
||||
new SimpleParameterAccessor(method.getParameters(), parameters);
|
||||
|
||||
MongoQueryCreator creator =
|
||||
new MongoQueryCreator(tree, accessor, template.getConverter());
|
||||
Query query = creator.createQuery();
|
||||
ParameterAccessor accessor =
|
||||
new ParametersParameterAccessor(method.getParameters(), parameters);
|
||||
Query query = createQuery(new ConvertingParameterAccessor(template.getConverter(), accessor));
|
||||
|
||||
if (method.isCollectionQuery()) {
|
||||
return new CollectionExecution().execute(query);
|
||||
} else if (method.isPageQuery()) {
|
||||
return new PagedExecution(creator, accessor.getPageable())
|
||||
.execute(query);
|
||||
return new PagedExecution(accessor.getPageable()).execute(query);
|
||||
} else {
|
||||
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);
|
||||
|
||||
|
||||
private abstract class Execution {
|
||||
|
||||
@@ -133,7 +136,6 @@ public class MongoQuery implements RepositoryQuery {
|
||||
class PagedExecution extends Execution {
|
||||
|
||||
private final Pageable pageable;
|
||||
private final MongoQueryCreator creator;
|
||||
|
||||
|
||||
/**
|
||||
@@ -141,11 +143,9 @@ public class MongoQuery implements RepositoryQuery {
|
||||
*
|
||||
* @param pageable
|
||||
*/
|
||||
public PagedExecution(MongoQueryCreator creator, Pageable pageable) {
|
||||
public PagedExecution(Pageable pageable) {
|
||||
|
||||
Assert.notNull(creator);
|
||||
Assert.notNull(pageable);
|
||||
this.creator = creator;
|
||||
this.pageable = pageable;
|
||||
}
|
||||
|
||||
@@ -161,10 +161,8 @@ public class MongoQuery implements RepositoryQuery {
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
Object execute(Query query) {
|
||||
|
||||
Query countQuery = creator.createQuery();
|
||||
String collectionName = getCollectionName(method.getDomainClass());
|
||||
int count =
|
||||
getCollectionCursor(collectionName, countQuery.getQueryObject()).count();
|
||||
int count = getCollectionCursor(collectionName, query.getQueryObject()).count();
|
||||
|
||||
List<?> result =
|
||||
template.find(collectionName, applyPagination(query, pageable),
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.document.mongodb.repository;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.springframework.data.document.mongodb.MongoWriter;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* (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#getPageable()
|
||||
*/
|
||||
public Pageable getPageable() {
|
||||
return delegate.getPageable();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.query.ParameterAccessor#getSort()
|
||||
*/
|
||||
public Sort getSort() {
|
||||
return delegate.getSort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom {@link Iterator} to convert items before returning them.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private class ConvertingIterator implements Iterator<Object> {
|
||||
|
||||
private final Iterator<Object> delegate;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ConvertingIterator} for the given delegate.
|
||||
*
|
||||
* @param delegate
|
||||
*/
|
||||
public ConvertingIterator(Iterator<Object> delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.util.Iterator#hasNext()
|
||||
*/
|
||||
public boolean hasNext() {
|
||||
return delegate.hasNext();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.util.Iterator#next()
|
||||
*/
|
||||
public Object next() {
|
||||
|
||||
DBObject result = new BasicDBObject();
|
||||
writer.write(new ValueHolder(delegate.next()), result);
|
||||
return result.get("value");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.util.Iterator#remove()
|
||||
*/
|
||||
public void remove() {
|
||||
delegate.remove();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple value holder class to allow conversion and accessing the converted value in a deterministic way.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class ValueHolder {
|
||||
|
||||
private Object value;
|
||||
|
||||
public ValueHolder(Object value) {
|
||||
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public Object getValue() {
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,25 +18,22 @@ package org.springframework.data.document.mongodb.repository;
|
||||
import static org.springframework.data.document.mongodb.query.Criteria.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.data.document.mongodb.MongoConverter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.document.mongodb.query.Criteria;
|
||||
import org.springframework.data.document.mongodb.query.CriteriaDefinition;
|
||||
import org.springframework.data.document.mongodb.query.Query;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.repository.query.SimpleParameterAccessor;
|
||||
import org.springframework.data.repository.query.SimpleParameterAccessor.BindableParameterIterator;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
|
||||
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;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
|
||||
/**
|
||||
* Custom query creator to create Mongo criterias.
|
||||
@@ -45,36 +42,28 @@ import com.mongodb.DBObject;
|
||||
*/
|
||||
class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(MongoQueryCreator.class);
|
||||
private final MongoConverter converter;
|
||||
private static final Logger LOG = LoggerFactory.getLog(MongoQueryCreator.class);
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoQueryCreator} from the given {@link PartTree}
|
||||
* and {@link SimpleParameterAccessor}.
|
||||
* and {@link ParametersParameterAccessor}.
|
||||
*
|
||||
* @param tree
|
||||
* @param accessor
|
||||
*/
|
||||
public MongoQueryCreator(PartTree tree,
|
||||
SimpleParameterAccessor accessor, MongoConverter converter) {
|
||||
public MongoQueryCreator(PartTree tree, ParameterAccessor accessor) {
|
||||
|
||||
super(tree, accessor);
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.document.mongodb.repository.AbstractQueryCreator
|
||||
* #create(org.springframework.data.repository.query.parser.Part,
|
||||
* org.springframework
|
||||
* .data.repository.query.SimpleParameterAccessor.BindableParameterIterator)
|
||||
* @see org.springframework.data.repository.query.parser.AbstractQueryCreator#create(org.springframework.data.repository.query.parser.Part, java.util.Iterator)
|
||||
*/
|
||||
@Override
|
||||
protected Criteria create(Part part, BindableParameterIterator iterator) {
|
||||
protected Criteria create(Part part, Iterator<Object> iterator) {
|
||||
|
||||
return from(part.getType(),
|
||||
where(part.getProperty().toDotPath()), iterator);
|
||||
@@ -83,16 +72,11 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.document.mongodb.repository.AbstractQueryCreator
|
||||
* #handlePart(org.springframework.data.repository.query.parser.Part,
|
||||
* org.springframework
|
||||
* .data.repository.query.SimpleParameterAccessor.BindableParameterIterator)
|
||||
* @see org.springframework.data.repository.query.parser.AbstractQueryCreator#and(org.springframework.data.repository.query.parser.Part, java.lang.Object, java.util.Iterator)
|
||||
*/
|
||||
@Override
|
||||
protected Criteria and(Part part, Criteria base,
|
||||
BindableParameterIterator iterator) {
|
||||
Iterator<Object> iterator) {
|
||||
|
||||
return from(part.getType(), where(part.getProperty().toDotPath()),
|
||||
iterator);
|
||||
@@ -143,16 +127,16 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
* @return
|
||||
*/
|
||||
private Criteria from(Type type, Criteria criteria,
|
||||
BindableParameterIterator parameters) {
|
||||
Iterator<Object> parameters) {
|
||||
|
||||
switch (type) {
|
||||
case GREATER_THAN:
|
||||
return criteria.gt(getConvertedParameter(parameters));
|
||||
return criteria.gt(parameters.next());
|
||||
case LESS_THAN:
|
||||
return criteria.lt(getConvertedParameter(parameters));
|
||||
return criteria.lt(parameters.next());
|
||||
case BETWEEN:
|
||||
return criteria.gt(getConvertedParameter(parameters)).lt(
|
||||
getConvertedParameter(parameters));
|
||||
return criteria.gt(parameters.next()).lt(
|
||||
parameters.next());
|
||||
case IS_NOT_NULL:
|
||||
return criteria.not().is(null);
|
||||
case IS_NULL:
|
||||
@@ -161,22 +145,15 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
String value = parameters.next().toString();
|
||||
return criteria.is(toLikeRegex(value));
|
||||
case SIMPLE_PROPERTY:
|
||||
return criteria.is(getConvertedParameter(parameters));
|
||||
return criteria.is(parameters.next());
|
||||
case NEGATING_SIMPLE_PROPERTY:
|
||||
return criteria.not().is(getConvertedParameter(parameters));
|
||||
return criteria.not().is(parameters.next());
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unsupported keyword!");
|
||||
}
|
||||
|
||||
|
||||
private Object getConvertedParameter(BindableParameterIterator parameters) {
|
||||
|
||||
DBObject result = new BasicDBObject();
|
||||
converter.write(new ValueHolder(parameters.next()), result);
|
||||
return result.get("value");
|
||||
}
|
||||
|
||||
|
||||
private Pattern toLikeRegex(String source) {
|
||||
|
||||
@@ -184,27 +161,5 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
return Pattern.compile(regex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple value holder class to allow conversion and accessing the converted
|
||||
* value in a deterministic way.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class ValueHolder {
|
||||
|
||||
private Object value;
|
||||
|
||||
|
||||
public ValueHolder(Object value) {
|
||||
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public Object getValue() {
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.document.mongodb.repository;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* TODO - Extract methods for {@link #getAnnotatedQuery()} into superclass as it is currently copied from Spring Data
|
||||
* JPA
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class MongoQueryMethod extends QueryMethod {
|
||||
|
||||
private final Method method;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoQueryMethod} from the given {@link Method}.
|
||||
*
|
||||
* @param method
|
||||
*/
|
||||
public MongoQueryMethod(Method method) {
|
||||
super(method);
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
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() {
|
||||
|
||||
String query = (String) AnnotationUtils.getValue(getQueryAnnotation());
|
||||
return StringUtils.hasText(query) ? query : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,6 @@ import org.springframework.data.document.mongodb.MongoTemplate;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.data.repository.support.RepositoryFactoryBeanSupport;
|
||||
import org.springframework.data.repository.support.RepositoryFactorySupport;
|
||||
@@ -126,15 +125,21 @@ public class MongoRepositoryFactoryBean extends
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link QueryLookupStrategy} to create {@link MongoQuery} instances.
|
||||
* {@link QueryLookupStrategy} to create {@link PartTreeMongoQuery} instances.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private class MongoQueryLookupStrategy implements QueryLookupStrategy {
|
||||
|
||||
public RepositoryQuery resolveQuery(Method method) {
|
||||
|
||||
return new MongoQuery(new QueryMethod(method), template);
|
||||
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method);
|
||||
|
||||
if (queryMethod.hasAnnotatedQuery()) {
|
||||
return new StringBasedMongoQuery(queryMethod, template);
|
||||
} else {
|
||||
return new PartTreeMongoQuery(queryMethod, template);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.document.mongodb.repository;
|
||||
|
||||
import org.springframework.data.document.mongodb.MongoTemplate;
|
||||
import org.springframework.data.document.mongodb.query.Query;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Creates a new {@link PartTreeMongoQuery} from the given {@link QueryMethod} and {@link MongoTemplate}.
|
||||
*
|
||||
* @param method
|
||||
* @param template
|
||||
*/
|
||||
public PartTreeMongoQuery(QueryMethod method, MongoTemplate template) {
|
||||
|
||||
super(method, template);
|
||||
this.tree = new PartTree(method.getName(), method.getDomainClass());
|
||||
}
|
||||
|
||||
/*
|
||||
* (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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.document.mongodb.repository;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
|
||||
/**
|
||||
* Annotation to declare finder queries directly on repository methods.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
@Documented
|
||||
public @interface Query {
|
||||
|
||||
String value() default "";
|
||||
}
|
||||
@@ -122,7 +122,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> extends
|
||||
*/
|
||||
public boolean exists(ID id) {
|
||||
|
||||
return findById(id) == null;
|
||||
return findById(id) != null;
|
||||
}
|
||||
|
||||
|
||||
@@ -157,10 +157,13 @@ public class SimpleMongoRepository<T, ID extends Serializable> extends
|
||||
* org.springframework.data.repository.Repository#delete(java.lang.Object)
|
||||
*/
|
||||
public void delete(T entity) {
|
||||
|
||||
Object id = entityInformation.getId(entity);
|
||||
ObjectId objectId = template.getConverter().convertObjectId(id);
|
||||
|
||||
Query query =
|
||||
new Query(where(entityInformation.getFieldName()).is(
|
||||
entityInformation.getId(entity)));
|
||||
new Query(where("_id").is(
|
||||
objectId));
|
||||
template.remove(getCollectionName(getDomainClass()), query);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.document.mongodb.repository;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.document.mongodb.MongoTemplate;
|
||||
import org.springframework.data.document.mongodb.query.BasicQuery;
|
||||
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("\\?");
|
||||
private static final Logger LOG = LoggerFactory.getLogger(StringBasedMongoQuery.class);
|
||||
|
||||
private final String query;
|
||||
|
||||
/**
|
||||
* Creates a new {@link StringBasedMongoQuery}.
|
||||
*
|
||||
* @param method
|
||||
* @param template
|
||||
*/
|
||||
public StringBasedMongoQuery(MongoQueryMethod method, MongoTemplate template) {
|
||||
super(method, template);
|
||||
this.query = method.getAnnotatedQuery();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.document.mongodb.repository.AbstractMongoQuery#createQuery(org.springframework.data.
|
||||
* repository.query.SimpleParameterAccessor, org.springframework.data.document.mongodb.MongoConverter)
|
||||
*/
|
||||
@Override
|
||||
protected Query createQuery(ConvertingParameterAccessor accessor) {
|
||||
|
||||
Matcher matcher = PLACEHOLDER.matcher(query);
|
||||
Iterator<Object> iterator = accessor.iterator();
|
||||
String result = null;
|
||||
|
||||
while (matcher.find()) {
|
||||
String group = matcher.group();
|
||||
result = query.replace(group, String.format("\"%s\"", iterator.next()));
|
||||
}
|
||||
|
||||
Query query = new BasicQuery(result);
|
||||
LOG.debug("Created query {}", query.getQueryObject());
|
||||
|
||||
return query;
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -19,116 +20,146 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* Base class for tests for {@link PersonRepository}.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
protected PersonRepository repository;
|
||||
Person dave, carter, boyd,stefan,leroi;
|
||||
@Autowired
|
||||
protected PersonRepository repository;
|
||||
Person dave, carter, boyd, stefan, leroi;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
repository.deleteAll();
|
||||
|
||||
dave = new Person("Dave", "Matthews", 42);
|
||||
carter = new Person("Carter", "Beauford", 49);
|
||||
boyd = new Person("Boyd", "Tinsley", 45);
|
||||
stefan = new Person("Stefan", "Lessard", 34);
|
||||
leroi = new Person("Leroi", "Moore", 41);
|
||||
|
||||
repository.save(Arrays.asList(dave, carter, boyd, stefan, leroi));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
repository.deleteAll();
|
||||
|
||||
dave = new Person("Dave", "Matthews", 42);
|
||||
carter = new Person("Carter", "Beauford", 49);
|
||||
boyd = new Person("Boyd", "Tinsley", 45);
|
||||
stefan = new Person("Stefan", "Lessard", 34);
|
||||
leroi = new Person("Leroi", "Moore", 41);
|
||||
|
||||
repository.save(Arrays.asList(dave, carter, boyd, stefan, leroi));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void existsWorksCorrectly() {
|
||||
assertThat(repository.exists(dave.getId()), is(true));
|
||||
assertThat(repository.exists(carter.getId()), is(true));
|
||||
assertThat(repository.exists(boyd.getId()), is(true));
|
||||
assertThat(repository.exists(stefan.getId()), is(true));
|
||||
assertThat(repository.exists(leroi.getId()), is(true));
|
||||
assertThat(repository.exists(new ObjectId().toString()), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findsPersonById() throws Exception {
|
||||
|
||||
assertThat(repository.findById(dave.getId()), is(dave));
|
||||
|
||||
assertThat(repository.findById(dave.getId()), is(dave));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findsPersonsByLastname() throws Exception {
|
||||
|
||||
List<Person> result = repository.findByLastname("Beauford");
|
||||
assertThat(result.size(), is(1));
|
||||
assertThat(result, hasItem(carter));
|
||||
}
|
||||
@Test
|
||||
public void findsAllMusicians() throws Exception {
|
||||
List<Person> result = repository.findAll();
|
||||
assertThat(result, hasItems(dave, carter, boyd, stefan, leroi));
|
||||
assertThat(result.size(), is(5));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deletesPersonCorrectly() throws Exception {
|
||||
|
||||
repository.delete(dave);
|
||||
|
||||
List<Person> result = repository.findAll();
|
||||
|
||||
assertThat(result.size(), is(4));
|
||||
assertThat(result, not(hasItem(dave)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findsPersonsByFirstnameLike() throws Exception {
|
||||
|
||||
List<Person> result = repository.findByFirstnameLike("Bo*");
|
||||
assertThat(result.size(), is(1));
|
||||
assertThat(result, hasItem(boyd));
|
||||
}
|
||||
@Test
|
||||
public void findsPersonsByLastname() throws Exception {
|
||||
|
||||
@Test
|
||||
public void findsPagedPersons() throws Exception {
|
||||
|
||||
Page<Person> result =
|
||||
repository.findAll(new PageRequest(1, 2, Direction.ASC,
|
||||
"lastname"));
|
||||
assertThat(result.isFirstPage(), is(false));
|
||||
assertThat(result.isLastPage(), is(false));
|
||||
assertThat(result, hasItems(dave, leroi));
|
||||
}
|
||||
List<Person> result = repository.findByLastname("Beauford");
|
||||
assertThat(result.size(), is(1));
|
||||
assertThat(result, hasItem(carter));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void finsPersonsByFirstname() {
|
||||
|
||||
List<Person> result = repository.findByThePersonsFirstname("Leroi");
|
||||
assertThat(result.size(), is(1));
|
||||
assertThat(result, hasItem(leroi));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executesPagedFinderCorrectly() throws Exception {
|
||||
|
||||
Page<Person> page =
|
||||
repository.findByLastnameLike("*a*", new PageRequest(0, 2,
|
||||
Direction.ASC, "lastname"));
|
||||
assertThat(page.isFirstPage(), is(true));
|
||||
assertThat(page.isLastPage(), is(false));
|
||||
assertThat(page.getNumberOfElements(), is(2));
|
||||
assertThat(page, hasItems(carter, stefan));
|
||||
}
|
||||
@Test
|
||||
public void findsPersonsByFirstnameLike() throws Exception {
|
||||
|
||||
|
||||
@Test
|
||||
public void findsPersonInAgeRangeCorrectly() throws Exception {
|
||||
List<Person> result = repository.findByFirstnameLike("Bo*");
|
||||
assertThat(result.size(), is(1));
|
||||
assertThat(result, hasItem(boyd));
|
||||
}
|
||||
|
||||
List<Person> result = repository.findByAgeBetween(40, 45);
|
||||
assertThat(result.size(), is(2));
|
||||
assertThat(result, hasItems(dave, leroi));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Test
|
||||
public void findsPagedPersons() throws Exception {
|
||||
|
||||
Page<Person> result = repository.findAll(new PageRequest(1, 2, Direction.ASC, "lastname"));
|
||||
assertThat(result.isFirstPage(), is(false));
|
||||
assertThat(result.isLastPage(), is(false));
|
||||
assertThat(result, hasItems(dave, leroi));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executesPagedFinderCorrectly() throws Exception {
|
||||
|
||||
Page<Person> page = repository.findByLastnameLike("*a*", new PageRequest(0, 2, Direction.ASC, "lastname"));
|
||||
assertThat(page.isFirstPage(), is(true));
|
||||
assertThat(page.isLastPage(), is(false));
|
||||
assertThat(page.getNumberOfElements(), is(2));
|
||||
assertThat(page, hasItems(carter, stefan));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findsPersonInAgeRangeCorrectly() throws Exception {
|
||||
|
||||
List<Person> result = repository.findByAgeBetween(40, 45);
|
||||
assertThat(result.size(), is(2));
|
||||
assertThat(result, hasItems(dave, leroi));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findsPersonByShippingAddressesCorrectly() throws Exception {
|
||||
|
||||
Address address = new Address("Foo Street 1", "C0123", "Bar");
|
||||
dave.setShippingAddresses(new HashSet<Address>(asList(address)));
|
||||
|
||||
repository.save(dave);
|
||||
assertThat(repository.findByShippingAddresses(address), is(dave));
|
||||
|
||||
Address address = new Address("Foo Street 1", "C0123", "Bar");
|
||||
dave.setShippingAddresses(new HashSet<Address>(asList(address)));
|
||||
|
||||
repository.save(dave);
|
||||
assertThat(repository.findByShippingAddresses(address), is(dave));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@Test
|
||||
public void findsPersonByAddressCorrectly() throws Exception {
|
||||
|
||||
Address address = new Address("Foo Street 1", "C0123", "Bar");
|
||||
dave.setAddress(address);
|
||||
repository.save(dave);
|
||||
|
||||
List<Person> result = repository.findByAddress(address);
|
||||
assertThat(result.size(), is(1));
|
||||
|
||||
Address address = new Address("Foo Street 1", "C0123", "Bar");
|
||||
dave.setAddress(address);
|
||||
repository.save(dave);
|
||||
|
||||
List<Person> result = repository.findByAddress(address);
|
||||
assertThat(result.size(), is(1));
|
||||
assertThat(result, hasItem(dave));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@Test
|
||||
public void findsPeopleByZipCode() throws Exception {
|
||||
|
||||
Address address = new Address("Foo Street 1", "C0123", "Bar");
|
||||
dave.setAddress(address);
|
||||
repository.save(dave);
|
||||
|
||||
List<Person> result = repository.findByAddressZipCode(address.getZipCode());
|
||||
assertThat(result.size(), is(1));
|
||||
|
||||
Address address = new Address("Foo Street 1", "C0123", "Bar");
|
||||
dave.setAddress(address);
|
||||
repository.save(dave);
|
||||
|
||||
List<Person> result = repository.findByAddressZipCode(address.getZipCode());
|
||||
assertThat(result.size(), is(1));
|
||||
assertThat(result, hasItem(dave));
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.document.mongodb.repository;
|
||||
|
||||
import static org.springframework.data.document.mongodb.repository.StubParameterAccessor.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
@@ -25,8 +27,6 @@ import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.document.mongodb.MongoConverter;
|
||||
import org.springframework.data.document.mongodb.Person;
|
||||
import org.springframework.data.repository.query.Parameters;
|
||||
import org.springframework.data.repository.query.SimpleParameterAccessor;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
|
||||
|
||||
@@ -63,17 +63,13 @@ public class MongoQueryCreatorUnitTests {
|
||||
PartTree tree = new PartTree("findByFirstName", Person.class);
|
||||
|
||||
MongoQueryCreator creator =
|
||||
new MongoQueryCreator(tree, new SimpleParameterAccessor(
|
||||
new Parameters(findByFirstname),
|
||||
new Object[] { "Oliver" }), converter);
|
||||
new MongoQueryCreator(tree, getAccessor(converter, "Oliver"));
|
||||
|
||||
creator.createQuery();
|
||||
|
||||
creator =
|
||||
new MongoQueryCreator(new PartTree("findByFirstNameAndFriend",
|
||||
Person.class), new SimpleParameterAccessor(
|
||||
new Parameters(findByFirstnameAndFriend), new Object[] {
|
||||
"Oliver", new Person() }), converter);
|
||||
Person.class), getAccessor(converter, "Oliver", new Person()));
|
||||
creator.createQuery();
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,16 @@ public interface PersonRepository extends MongoRepository<Person, String> {
|
||||
* @return
|
||||
*/
|
||||
List<Person> findByLastname(String lastname);
|
||||
|
||||
/**
|
||||
* Returns the {@link Person}s with the given firstname. Uses {@link Query} annotation to define the query to be
|
||||
* executed.
|
||||
*
|
||||
* @param firstname
|
||||
* @return
|
||||
*/
|
||||
@Query("{ 'firstname' : ? }")
|
||||
List<Person> findByThePersonsFirstname(String firstname);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.document.mongodb.repository;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.document.mongodb.MongoConverter;
|
||||
import org.springframework.data.document.mongodb.MongoTemplate;
|
||||
import org.springframework.data.document.mongodb.SimpleMongoConverter;
|
||||
import org.springframework.data.document.mongodb.query.BasicQuery;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link StringBasedMongoQuery}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class StringBasedMongoQueryUnitTests {
|
||||
|
||||
@Mock
|
||||
MongoTemplate template;
|
||||
MongoConverter converter = new SimpleMongoConverter();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
when(template.getConverter()).thenReturn(converter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testname() throws Exception {
|
||||
|
||||
Method method = SampleRepository.class.getMethod("findByLastname", String.class);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method);
|
||||
StringBasedMongoQuery mongoQuery = new StringBasedMongoQuery(queryMethod, template);
|
||||
ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, "Matthews");
|
||||
|
||||
org.springframework.data.document.mongodb.query.Query query = mongoQuery.createQuery(accesor);
|
||||
org.springframework.data.document.mongodb.query.Query reference = new BasicQuery("{'lastname' : 'Matthews'}");
|
||||
|
||||
assertThat(query.getQueryObject(), is(reference.getQueryObject()));
|
||||
}
|
||||
|
||||
private interface SampleRepository {
|
||||
|
||||
@Query("{ 'lastname' : ? }")
|
||||
Person findByLastname(String lastname);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.document.mongodb.repository;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.springframework.data.document.mongodb.MongoWriter;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
|
||||
/**
|
||||
* Simple {@link ParameterAccessor} that returns the given parameters unfiltered.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class StubParameterAccessor implements ParameterAccessor {
|
||||
|
||||
/**
|
||||
* Creates a new {@link ConvertingParameterAccessor} backed by a {@link StubParameterAccessor} simply returning the
|
||||
* given parameters converted but unfiltered.
|
||||
*
|
||||
* @param converter
|
||||
* @param parameters
|
||||
* @return
|
||||
*/
|
||||
public static ConvertingParameterAccessor getAccessor(MongoWriter<Object> converter, Object... parameters) {
|
||||
|
||||
return new ConvertingParameterAccessor(converter, new StubParameterAccessor(parameters));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private Object[] values;
|
||||
|
||||
public StubParameterAccessor(Object... values) {
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.query.ParameterAccessor#getPageable()
|
||||
*/
|
||||
public Pageable getPageable() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.query.ParameterAccessor#getSort()
|
||||
*/
|
||||
public Sort getSort() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Iterable#iterator()
|
||||
*/
|
||||
public Iterator<Object> iterator() {
|
||||
return Arrays.asList(values).iterator();
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ Import-Template:
|
||||
org.bson.*;version="0",
|
||||
org.aopalliance.*;version="[1.0.0, 2.0.0)";resolution:=optional,
|
||||
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
|
||||
org.slf4j.*;version="[1.5.0,1.6.0)",
|
||||
org.w3c.dom.*;version="0"
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user