diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryMethod.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryMethod.java index 2c25d186b5..ad38a8e1b8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryMethod.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryMethod.java @@ -1,237 +1,237 @@ -/* - * Copyright 2011-2014 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.mongodb.repository.query; - -import java.io.Serializable; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.List; - -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.data.geo.GeoPage; -import org.springframework.data.geo.GeoResult; -import org.springframework.data.geo.GeoResults; -import org.springframework.data.mapping.context.MappingContext; -import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; -import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; -import org.springframework.data.mongodb.repository.Meta; -import org.springframework.data.mongodb.repository.Query; -import org.springframework.data.repository.core.RepositoryMetadata; -import org.springframework.data.repository.query.QueryMethod; -import org.springframework.data.util.ClassTypeInformation; -import org.springframework.data.util.TypeInformation; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * Mongo specific implementation of {@link QueryMethod}. - * - * @author Oliver Gierke - * @author Christoph Strobl - */ -public class MongoQueryMethod extends QueryMethod { - - @SuppressWarnings("unchecked") private static final List> GEO_NEAR_RESULTS = Arrays - .asList(GeoResult.class, GeoResults.class, GeoPage.class); - - private final Method method; - private final MappingContext, MongoPersistentProperty> mappingContext; - - private MongoEntityMetadata metadata; - - /** - * Creates a new {@link MongoQueryMethod} from the given {@link Method}. - * - * @param method - */ - public MongoQueryMethod(Method method, RepositoryMetadata metadata, - MappingContext, MongoPersistentProperty> mappingContext) { - - super(method, metadata); - - Assert.notNull(mappingContext, "MappingContext must not be null!"); - - this.method = method; - this.mappingContext = mappingContext; - } - - /* - * (non-Javadoc) - * @see org.springframework.data.repository.query.QueryMethod#getParameters(java.lang.reflect.Method) - */ - @Override - protected MongoParameters createParameters(Method method) { - return new MongoParameters(method, isGeoNearQuery(method)); - } - - /** - * Returns whether the method has an annotated query. - * - * @return - */ - public 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 field specification to be used for the query. - * - * @return - */ - String getFieldSpecification() { - - String value = (String) AnnotationUtils.getValue(getQueryAnnotation(), "fields"); - return StringUtils.hasText(value) ? value : null; - } - - /* - * (non-Javadoc) - * @see org.springframework.data.repository.query.QueryMethod#getEntityInformation() - */ - @Override - @SuppressWarnings("unchecked") - public MongoEntityMetadata getEntityInformation() { - - if (metadata == null) { - - Class returnedObjectType = getReturnedObjectType(); - Class domainClass = getDomainClass(); - - MongoPersistentEntity returnedEntity = mappingContext.getPersistentEntity(getReturnedObjectType()); - MongoPersistentEntity managedEntity = mappingContext.getPersistentEntity(domainClass); - returnedEntity = returnedEntity == null ? managedEntity : returnedEntity; - MongoPersistentEntity collectionEntity = domainClass.isAssignableFrom(returnedObjectType) ? returnedEntity - : managedEntity; - - this.metadata = new SimpleMongoEntityMetadata((Class) returnedEntity.getType(), - collectionEntity.getCollection()); - } - - return this.metadata; - } - - /* - * (non-Javadoc) - * @see org.springframework.data.repository.query.QueryMethod#getParameters() - */ - @Override - public MongoParameters getParameters() { - return (MongoParameters) super.getParameters(); - } - - /** - * Returns whether the query is a geo near query. - * - * @return - */ - public boolean isGeoNearQuery() { - return isGeoNearQuery(this.method); - } - - private boolean isGeoNearQuery(Method method) { - - Class returnType = method.getReturnType(); - - for (Class type : GEO_NEAR_RESULTS) { - if (type.isAssignableFrom(returnType)) { - return true; - } - } - - if (Iterable.class.isAssignableFrom(returnType)) { - TypeInformation from = ClassTypeInformation.fromReturnTypeOf(method); - return GeoResult.class.equals(from.getComponentType().getType()); - } - - return false; - } - - /** - * Returns the {@link Query} annotation that is applied to the method or {@code null} if none available. - * - * @return - */ - Query getQueryAnnotation() { - return method.getAnnotation(Query.class); - } - - TypeInformation getReturnType() { - return ClassTypeInformation.fromReturnTypeOf(method); - } - - /** - * @return return true if {@link Meta} annotation is available. - * @since 1.6 - */ - public boolean hasQueryMetaAttributes() { - return getMetaAnnotation() != null; - } - - /** - * Returns the {@link Meta} annotation that is applied to the method or {@code null} if not available. - * - * @return - * @since 1.6 - */ - Meta getMetaAnnotation() { - return method.getAnnotation(Meta.class); - } - - /** - * Returns the {@link org.springframework.data.mongodb.core.query.Meta} attributes to be applied. - * - * @return never {@literal null}. - * @since 1.6 - */ - public org.springframework.data.mongodb.core.query.Meta getQueryMetaAttributes() { - - Meta meta = getMetaAnnotation(); - if (meta == null) { - return new org.springframework.data.mongodb.core.query.Meta(); - } - - org.springframework.data.mongodb.core.query.Meta metaAttributes = new org.springframework.data.mongodb.core.query.Meta(); - if (meta.maxExcecutionTime() > 0) { - metaAttributes.setMaxTimeMsec(meta.maxExcecutionTime()); - } - - if (meta.maxScanDocuments() > 0) { - metaAttributes.setMaxScan(meta.maxScanDocuments()); - } - - if (StringUtils.hasText(meta.comment())) { - metaAttributes.setComment(meta.comment()); - } - - if (meta.snapshot()) { - metaAttributes.setSnapshot(meta.snapshot()); - } - - return metaAttributes; - } -} +/* + * Copyright 2011-2014 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.mongodb.repository.query; + +import java.io.Serializable; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; + +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.data.geo.GeoPage; +import org.springframework.data.geo.GeoResult; +import org.springframework.data.geo.GeoResults; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; +import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; +import org.springframework.data.mongodb.repository.Meta; +import org.springframework.data.mongodb.repository.Query; +import org.springframework.data.repository.core.RepositoryMetadata; +import org.springframework.data.repository.query.QueryMethod; +import org.springframework.data.util.ClassTypeInformation; +import org.springframework.data.util.TypeInformation; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + * Mongo specific implementation of {@link QueryMethod}. + * + * @author Oliver Gierke + * @author Christoph Strobl + */ +public class MongoQueryMethod extends QueryMethod { + + @SuppressWarnings("unchecked") private static final List> GEO_NEAR_RESULTS = Arrays + .asList(GeoResult.class, GeoResults.class, GeoPage.class); + + private final Method method; + private final MappingContext, MongoPersistentProperty> mappingContext; + + private MongoEntityMetadata metadata; + + /** + * Creates a new {@link MongoQueryMethod} from the given {@link Method}. + * + * @param method + */ + public MongoQueryMethod(Method method, RepositoryMetadata metadata, + MappingContext, MongoPersistentProperty> mappingContext) { + + super(method, metadata); + + Assert.notNull(mappingContext, "MappingContext must not be null!"); + + this.method = method; + this.mappingContext = mappingContext; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.query.QueryMethod#getParameters(java.lang.reflect.Method) + */ + @Override + protected MongoParameters createParameters(Method method) { + return new MongoParameters(method, isGeoNearQuery(method)); + } + + /** + * Returns whether the method has an annotated query. + * + * @return + */ + public 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 field specification to be used for the query. + * + * @return + */ + String getFieldSpecification() { + + String value = (String) AnnotationUtils.getValue(getQueryAnnotation(), "fields"); + return StringUtils.hasText(value) ? value : null; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.query.QueryMethod#getEntityInformation() + */ + @Override + @SuppressWarnings("unchecked") + public MongoEntityMetadata getEntityInformation() { + + if (metadata == null) { + + Class returnedObjectType = getReturnedObjectType(); + Class domainClass = getDomainClass(); + + MongoPersistentEntity returnedEntity = mappingContext.getPersistentEntity(getReturnedObjectType()); + MongoPersistentEntity managedEntity = mappingContext.getPersistentEntity(domainClass); + returnedEntity = returnedEntity == null ? managedEntity : returnedEntity; + MongoPersistentEntity collectionEntity = domainClass.isAssignableFrom(returnedObjectType) ? returnedEntity + : managedEntity; + + this.metadata = new SimpleMongoEntityMetadata((Class) returnedEntity.getType(), + (MongoPersistentEntity) collectionEntity); /*collectionEntity.getCollection());*/ + } + + return this.metadata; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.query.QueryMethod#getParameters() + */ + @Override + public MongoParameters getParameters() { + return (MongoParameters) super.getParameters(); + } + + /** + * Returns whether the query is a geo near query. + * + * @return + */ + public boolean isGeoNearQuery() { + return isGeoNearQuery(this.method); + } + + private boolean isGeoNearQuery(Method method) { + + Class returnType = method.getReturnType(); + + for (Class type : GEO_NEAR_RESULTS) { + if (type.isAssignableFrom(returnType)) { + return true; + } + } + + if (Iterable.class.isAssignableFrom(returnType)) { + TypeInformation from = ClassTypeInformation.fromReturnTypeOf(method); + return GeoResult.class.equals(from.getComponentType().getType()); + } + + return false; + } + + /** + * Returns the {@link Query} annotation that is applied to the method or {@code null} if none available. + * + * @return + */ + Query getQueryAnnotation() { + return method.getAnnotation(Query.class); + } + + TypeInformation getReturnType() { + return ClassTypeInformation.fromReturnTypeOf(method); + } + + /** + * @return return true if {@link Meta} annotation is available. + * @since 1.6 + */ + public boolean hasQueryMetaAttributes() { + return getMetaAnnotation() != null; + } + + /** + * Returns the {@link Meta} annotation that is applied to the method or {@code null} if not available. + * + * @return + * @since 1.6 + */ + Meta getMetaAnnotation() { + return method.getAnnotation(Meta.class); + } + + /** + * Returns the {@link org.springframework.data.mongodb.core.query.Meta} attributes to be applied. + * + * @return never {@literal null}. + * @since 1.6 + */ + public org.springframework.data.mongodb.core.query.Meta getQueryMetaAttributes() { + + Meta meta = getMetaAnnotation(); + if (meta == null) { + return new org.springframework.data.mongodb.core.query.Meta(); + } + + org.springframework.data.mongodb.core.query.Meta metaAttributes = new org.springframework.data.mongodb.core.query.Meta(); + if (meta.maxExcecutionTime() > 0) { + metaAttributes.setMaxTimeMsec(meta.maxExcecutionTime()); + } + + if (meta.maxScanDocuments() > 0) { + metaAttributes.setMaxScan(meta.maxScanDocuments()); + } + + if (StringUtils.hasText(meta.comment())) { + metaAttributes.setComment(meta.comment()); + } + + if (meta.snapshot()) { + metaAttributes.setSnapshot(meta.snapshot()); + } + + return metaAttributes; + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/SimpleMongoEntityMetadata.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/SimpleMongoEntityMetadata.java index e248c604ac..e75540f657 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/SimpleMongoEntityMetadata.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/SimpleMongoEntityMetadata.java @@ -1,60 +1,88 @@ -/* - * Copyright 2012 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.mongodb.repository.query; - -import org.springframework.util.Assert; - -/** - * Bean based implementation of {@link MongoEntityMetadata}. - * - * @author Oliver Gierke - */ -class SimpleMongoEntityMetadata implements MongoEntityMetadata { - - private final Class type; - private final String collectionName; - - /** - * Creates a new {@link SimpleMongoEntityMetadata} using the given type and collection name. - * - * @param type must not be {@literal null}. - * @param collectionName must not be {@literal null} or empty. - */ - public SimpleMongoEntityMetadata(Class type, String collectionName) { - - Assert.notNull(type, "Type must not be null!"); - Assert.hasText(collectionName, "Collection name must not be null or empty!"); - - this.type = type; - this.collectionName = collectionName; - } - - /* - * (non-Javadoc) - * @see org.springframework.data.repository.core.EntityMetadata#getJavaType() - */ - public Class getJavaType() { - return type; - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.repository.query.MongoEntityMetadata#getCollectionName() - */ - public String getCollectionName() { - return collectionName; - } -} +/* + * Copyright 2012 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.mongodb.repository.query; + +import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; +import org.springframework.util.Assert; + +/** + * Bean based implementation of {@link MongoEntityMetadata}. + * + * @author Oliver Gierke + */ +class SimpleMongoEntityMetadata implements MongoEntityMetadata { + + private final Class type; + // One of both won't be null + private final String collectionName; + private final MongoPersistentEntity persistentEntityRef; + + /** + * Creates a new {@link SimpleMongoEntityMetadata} using the given type and collection name. + * + * @param type must not be {@literal null}. + * @param collectionName must not be {@literal null} or empty. + */ + @Deprecated + public SimpleMongoEntityMetadata(Class type, String collectionName) { + + Assert.notNull(type, "Type must not be null!"); + Assert.hasText(collectionName, "Collection name must not be null or empty!"); + + this.type = type; + this.collectionName = collectionName; + this.persistentEntityRef = null; + } + + /** + *

+ * NEW way of getting collectionName, due to improvements in performance done in SpEL it seems to me a plausible + * solution to DATAMONGO-1043 + * http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/expressions + * .html#expressions-compiler-configuration + *

+ * Creates a new {@link SimpleMongoEntityMetadata} using the given type and collection persistent entity reference in + * order to retrieve the collection name at runtime(this allows us to customize at runtime the collection name based on a + * thread local variable for instance) + * + * @param type must not be {@literal null}. + * @param persistentEntityRef must not be {@literal null} + */ + public SimpleMongoEntityMetadata(Class type, MongoPersistentEntity persistentEntityRef) { + Assert.notNull(type, "Type must not be null!"); + Assert.notNull(persistentEntityRef, "PersistentEntityRef must not be null!"); + + this.type = type; + this.collectionName = null; + this.persistentEntityRef = persistentEntityRef; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.core.EntityMetadata#getJavaType() + */ + public Class getJavaType() { + return type; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.repository.query.MongoEntityMetadata#getCollectionName() + */ + public String getCollectionName() { + return this.persistentEntityRef != null ? this.persistentEntityRef.getCollection() : collectionName; + } +}