LDAP-269: Basic QueryDSL support.
This commit is contained in:
@@ -18,7 +18,8 @@ dependencies {
|
||||
"com.sun:ldapbp:1.0",
|
||||
"org.springframework:spring-context:$springVersion",
|
||||
"org.springframework:spring-jdbc:$springVersion",
|
||||
"org.springframework:spring-orm:$springVersion"
|
||||
"org.springframework:spring-orm:$springVersion",
|
||||
"com.mysema.querydsl:querydsl-apt:$queryDslVersion"
|
||||
|
||||
testCompile "junit:junit:$junitVersion",
|
||||
"commons-lang:commons-lang:$commonsLangVersion",
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2005-2013 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.ldap.repository.support;
|
||||
|
||||
import com.mysema.query.apt.DefaultConfiguration;
|
||||
import org.springframework.ldap.odm.annotations.Id;
|
||||
|
||||
import javax.annotation.processing.RoundEnvironment;
|
||||
import javax.lang.model.element.VariableElement;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Mattias Hellborg Arthursson
|
||||
* @since 2.0
|
||||
*/
|
||||
class DefaultLdapAnnotationProcessorConfiguration extends DefaultConfiguration {
|
||||
public DefaultLdapAnnotationProcessorConfiguration(
|
||||
RoundEnvironment roundEnv,
|
||||
Map<String, String> options,
|
||||
Collection<String> keywords,
|
||||
Class<? extends Annotation> entitiesAnn,
|
||||
Class<? extends Annotation> entityAnn,
|
||||
Class<? extends Annotation> superTypeAnn,
|
||||
Class<? extends Annotation> embeddableAnn,
|
||||
Class<? extends Annotation> embeddedAnn,
|
||||
Class<? extends Annotation> skipAnn) {
|
||||
|
||||
super(roundEnv, options, keywords, entitiesAnn, entityAnn, superTypeAnn, embeddableAnn, embeddedAnn, skipAnn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBlockedField(VariableElement field) {
|
||||
return super.isBlockedField(field) || field.getAnnotation(Id.class) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidField(VariableElement field) {
|
||||
return super.isValidField(field) && field.getAnnotation(Id.class) == null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2005-2013 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.ldap.repository.support;
|
||||
|
||||
import com.mysema.query.annotations.QueryEntities;
|
||||
import com.mysema.query.apt.AbstractQuerydslProcessor;
|
||||
import com.mysema.query.apt.Configuration;
|
||||
import com.mysema.query.apt.DefaultConfiguration;
|
||||
import org.springframework.ldap.odm.annotations.Entry;
|
||||
import org.springframework.ldap.odm.annotations.Transient;
|
||||
|
||||
import javax.annotation.processing.RoundEnvironment;
|
||||
import javax.annotation.processing.SupportedAnnotationTypes;
|
||||
import javax.annotation.processing.SupportedSourceVersion;
|
||||
import javax.lang.model.SourceVersion;
|
||||
import javax.tools.Diagnostic;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* QueryDSL Annotation Processor to generate QueryDSL classes for entity classes annotated with {@link Entry}.
|
||||
*
|
||||
* @author Mattias Hellborg Arthursson
|
||||
* @since 2.0
|
||||
*/
|
||||
@SupportedAnnotationTypes("org.springframework.ldap.odm.annotations.*")
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_6)
|
||||
public class LdapAnnotationProcessor extends AbstractQuerydslProcessor {
|
||||
@Override
|
||||
protected Configuration createConfiguration(RoundEnvironment roundEnv) {
|
||||
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Running " + getClass().getSimpleName());
|
||||
|
||||
DefaultConfiguration configuration = new DefaultLdapAnnotationProcessorConfiguration(roundEnv, processingEnv.getOptions(),
|
||||
Collections.<String>emptySet(), QueryEntities.class, Entry.class, null, null, null, Transient.class);
|
||||
configuration.setUseFields(true);
|
||||
configuration.setUseGetters(false);
|
||||
|
||||
return configuration;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.ldap.repository.support;
|
||||
|
||||
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
|
||||
import org.springframework.data.repository.core.EntityInformation;
|
||||
import org.springframework.data.repository.core.NamedQueries;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
@@ -30,6 +31,8 @@ import org.springframework.ldap.repository.query.PartTreeLdapRepositoryQuery;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import static org.springframework.data.querydsl.QueryDslUtils.QUERY_DSL_PRESENT;
|
||||
|
||||
/**
|
||||
* Factory to create {@link org.springframework.ldap.repository.LdapRepository} instances.
|
||||
* @author Mattias Hellborg Arthursson
|
||||
@@ -50,15 +53,32 @@ public class LdapRepositoryFactory extends RepositoryFactorySupport {
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
protected Object getTargetRepository(RepositoryMetadata metadata) {
|
||||
return new SimpleLdapRepository(
|
||||
ldapOperations,
|
||||
ldapOperations.getObjectDirectoryMapper(),
|
||||
metadata.getDomainType());
|
||||
if(!isQueryDslRepository(metadata.getRepositoryInterface())) {
|
||||
return new SimpleLdapRepository(
|
||||
ldapOperations,
|
||||
ldapOperations.getObjectDirectoryMapper(),
|
||||
metadata.getDomainType());
|
||||
} else {
|
||||
return new QueryDslLdapRepository(
|
||||
ldapOperations,
|
||||
ldapOperations.getObjectDirectoryMapper(),
|
||||
metadata.getDomainType());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static boolean isQueryDslRepository(Class<?> repositoryInterface) {
|
||||
return QUERY_DSL_PRESENT && QueryDslPredicateExecutor.class.isAssignableFrom(repositoryInterface);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
|
||||
return SimpleLdapRepository.class;
|
||||
if(!isQueryDslRepository(metadata.getRepositoryInterface())) {
|
||||
return SimpleLdapRepository.class;
|
||||
} else {
|
||||
return QueryDslLdapRepository.class;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright 2005-2013 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.ldap.repository.support;
|
||||
|
||||
import com.mysema.query.types.Constant;
|
||||
import com.mysema.query.types.Expression;
|
||||
import com.mysema.query.types.FactoryExpression;
|
||||
import com.mysema.query.types.Operation;
|
||||
import com.mysema.query.types.Operator;
|
||||
import com.mysema.query.types.Ops;
|
||||
import com.mysema.query.types.ParamExpression;
|
||||
import com.mysema.query.types.Path;
|
||||
import com.mysema.query.types.SubQueryExpression;
|
||||
import com.mysema.query.types.TemplateExpression;
|
||||
import com.mysema.query.types.Visitor;
|
||||
import org.springframework.ldap.filter.AndFilter;
|
||||
import org.springframework.ldap.filter.EqualsFilter;
|
||||
import org.springframework.ldap.filter.Filter;
|
||||
import org.springframework.ldap.filter.GreaterThanOrEqualsFilter;
|
||||
import org.springframework.ldap.filter.LessThanOrEqualsFilter;
|
||||
import org.springframework.ldap.filter.LikeFilter;
|
||||
import org.springframework.ldap.filter.NotFilter;
|
||||
import org.springframework.ldap.filter.OrFilter;
|
||||
import org.springframework.ldap.filter.PresentFilter;
|
||||
import org.springframework.ldap.odm.core.ObjectDirectoryMapper;
|
||||
|
||||
/**
|
||||
* Helper class for generating LDAP filters from QueryDSL Expressions.
|
||||
*
|
||||
* @author Mattias Hellborg Arthursson
|
||||
* @since 2.0
|
||||
*/
|
||||
class LdapSerializer implements Visitor<Object, Void> {
|
||||
|
||||
private final ObjectDirectoryMapper odm;
|
||||
private final Class<?> clazz;
|
||||
|
||||
public LdapSerializer(ObjectDirectoryMapper odm, Class<?> clazz) {
|
||||
this.odm = odm;
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
public Filter handle(Expression<?> expression) {
|
||||
return (Filter) expression.accept(this, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(Constant<?> expr, Void context) {
|
||||
return expr.getConstant().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(FactoryExpression<?> expr, Void context) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(Operation<?> expr, Void context) {
|
||||
Operator<?> operator = expr.getOperator();
|
||||
if (operator == Ops.EQ) {
|
||||
return new EqualsFilter(attribute(expr), value(expr));
|
||||
} else if (operator == Ops.AND) {
|
||||
return new AndFilter()
|
||||
.and(handle(expr.getArg(0)))
|
||||
.and(handle(expr.getArg(1)));
|
||||
} else if (operator == Ops.OR) {
|
||||
return new OrFilter()
|
||||
.or(handle(expr.getArg(0)))
|
||||
.or(handle(expr.getArg(1)));
|
||||
} else if (operator == Ops.NOT) {
|
||||
return new NotFilter(handle(expr.getArg(0)));
|
||||
} else if (operator == Ops.LIKE) {
|
||||
return new LikeFilter(attribute(expr), value(expr));
|
||||
} else if (operator == Ops.STARTS_WITH || operator == Ops.STARTS_WITH_IC) {
|
||||
return new LikeFilter(attribute(expr), value(expr) + "*");
|
||||
} else if (operator == Ops.ENDS_WITH || operator == Ops.ENDS_WITH_IC) {
|
||||
return new LikeFilter(attribute(expr), "*" + value(expr));
|
||||
} else if (operator == Ops.STRING_CONTAINS || operator == Ops.STRING_CONTAINS_IC) {
|
||||
return new LikeFilter(attribute(expr), "*" + value(expr) + "*");
|
||||
} else if (operator == Ops.IS_NOT_NULL) {
|
||||
return new PresentFilter(attribute(expr));
|
||||
} else if (operator == Ops.IS_NULL) {
|
||||
return new NotFilter(new PresentFilter(attribute(expr)));
|
||||
} else if (operator == Ops.GOE) {
|
||||
return new GreaterThanOrEqualsFilter(attribute(expr), value(expr));
|
||||
} else if (operator == Ops.LOE) {
|
||||
return new LessThanOrEqualsFilter(attribute(expr), value(expr));
|
||||
}
|
||||
|
||||
|
||||
throw new UnsupportedOperationException("Unsupported operator " + operator.toString());
|
||||
}
|
||||
|
||||
private String value(Operation<?> expr) {
|
||||
return (String) expr.getArg(1).accept(this, null);
|
||||
}
|
||||
|
||||
private String attribute(Operation<?> expr) {
|
||||
return odm.attributeFor(clazz, (String) expr.getArg(0).accept(this, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ParamExpression<?> expr, Void context) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(Path<?> expr, Void context) {
|
||||
return expr.getMetadata().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(SubQueryExpression<?> expr, Void context) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(TemplateExpression<?> expr, Void context) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2005-2013 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.ldap.repository.support;
|
||||
|
||||
import com.mysema.query.DefaultQueryMetadata;
|
||||
import com.mysema.query.FilteredClause;
|
||||
import com.mysema.query.support.QueryMixin;
|
||||
import com.mysema.query.types.EntityPath;
|
||||
import com.mysema.query.types.Predicate;
|
||||
import org.springframework.ldap.core.LdapOperations;
|
||||
import org.springframework.ldap.query.LdapQuery;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.ldap.query.LdapQueryBuilder.query;
|
||||
|
||||
/**
|
||||
* Spring LDAP specific {@link FilteredClause} implementation.
|
||||
*
|
||||
* @author Mattias Hellborg Arthursson
|
||||
* @since 2.0
|
||||
*/
|
||||
public class QueryDslLdapQuery<K> implements FilteredClause<QueryDslLdapQuery<K>> {
|
||||
private final LdapOperations ldapOperations;
|
||||
private final Class<? extends K> clazz;
|
||||
|
||||
private QueryMixin<QueryDslLdapQuery<K>> queryMixin =
|
||||
new QueryMixin<QueryDslLdapQuery<K>>(this, new DefaultQueryMetadata().noValidate());
|
||||
|
||||
private final LdapSerializer filterGenerator;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public QueryDslLdapQuery(LdapOperations ldapOperations, EntityPath<K> entityPath) {
|
||||
this(ldapOperations, (Class<K>) entityPath.getType());
|
||||
}
|
||||
|
||||
public QueryDslLdapQuery(LdapOperations ldapOperations, Class<K> clazz) {
|
||||
this.ldapOperations = ldapOperations;
|
||||
this.clazz = clazz;
|
||||
this.filterGenerator = new LdapSerializer(ldapOperations.getObjectDirectoryMapper(), clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryDslLdapQuery<K> where(Predicate... o) {
|
||||
return queryMixin.where(o);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<K> list() {
|
||||
return (List<K>) ldapOperations.find(buildQuery(), clazz);
|
||||
}
|
||||
|
||||
public K uniqueResult() {
|
||||
return ldapOperations.findOne(buildQuery(), clazz);
|
||||
}
|
||||
|
||||
LdapQuery buildQuery() {
|
||||
return query().filter(filterGenerator.handle(queryMixin.getMetadata().getWhere()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2005-2013 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.ldap.repository.support;
|
||||
|
||||
import com.mysema.query.types.OrderSpecifier;
|
||||
import com.mysema.query.types.Predicate;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
|
||||
import org.springframework.ldap.core.LdapOperations;
|
||||
import org.springframework.ldap.odm.core.ObjectDirectoryMapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Base repository implementation for QueryDSL support.
|
||||
*
|
||||
* @author Mattias Hellborg Arthursson
|
||||
* @since 2.0
|
||||
*/
|
||||
public class QueryDslLdapRepository<T> extends SimpleLdapRepository<T> implements QueryDslPredicateExecutor<T> {
|
||||
|
||||
public QueryDslLdapRepository(LdapOperations ldapOperations,
|
||||
ObjectDirectoryMapper odm,
|
||||
Class<T> clazz) {
|
||||
super(ldapOperations, odm, clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T findOne(Predicate predicate) {
|
||||
return queryFor(predicate).uniqueResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<T> findAll(Predicate predicate) {
|
||||
return queryFor(predicate).list();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count(Predicate predicate) {
|
||||
return findAll(predicate).size();
|
||||
}
|
||||
|
||||
private QueryDslLdapQuery<T> queryFor(Predicate predicate) {
|
||||
return new QueryDslLdapQuery<T>(getLdapOperations(), getClazz())
|
||||
.where(predicate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<T> findAll(Predicate predicate, OrderSpecifier<?>... orders) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<T> findAll(Predicate predicate, Pageable pageable) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import org.springframework.util.Assert;
|
||||
import javax.naming.Name;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.ldap.query.LdapQueryBuilder.query;
|
||||
|
||||
@@ -51,6 +52,14 @@ public class SimpleLdapRepository<T> implements LdapRepository<T> {
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
protected LdapOperations getLdapOperations() {
|
||||
return ldapOperations;
|
||||
}
|
||||
|
||||
protected Class<T> getClazz() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
Filter filter = odm.filterFor(clazz, null);
|
||||
@@ -63,7 +72,7 @@ public class SimpleLdapRepository<T> implements LdapRepository<T> {
|
||||
|
||||
private <S extends T> boolean isNew(S entity, Name id) {
|
||||
if (entity instanceof Persistable) {
|
||||
Persistable persistable = (Persistable) entity;
|
||||
Persistable<?> persistable = (Persistable<?>) entity;
|
||||
return persistable.isNew();
|
||||
} else {
|
||||
return id == null;
|
||||
@@ -119,7 +128,7 @@ public class SimpleLdapRepository<T> implements LdapRepository<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<T> findAll(LdapQuery ldapQuery) {
|
||||
public List<T> findAll(LdapQuery ldapQuery) {
|
||||
Assert.notNull(ldapQuery, "LdapQuery must not be null");
|
||||
return ldapOperations.find(ldapQuery, clazz);
|
||||
}
|
||||
@@ -141,12 +150,12 @@ public class SimpleLdapRepository<T> implements LdapRepository<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<T> findAll() {
|
||||
public List<T> findAll() {
|
||||
return ldapOperations.findAll(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<T> findAll(final Iterable<Name> names) {
|
||||
public List<T> findAll(final Iterable<Name> names) {
|
||||
Iterable<T> found = new TransformingIterable<Name, T>(names, new Function<Name, T>() {
|
||||
@Override
|
||||
public T transform(Name name) {
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.springframework.ldap.repository.support;
|
||||
|
||||
import com.mysema.query.types.Path;
|
||||
import com.mysema.query.types.PathMetadata;
|
||||
import com.mysema.query.types.path.EntityPathBase;
|
||||
import com.mysema.query.types.path.ListPath;
|
||||
import com.mysema.query.types.path.PathInits;
|
||||
import com.mysema.query.types.path.StringPath;
|
||||
import org.springframework.ldap.odm.core.impl.UnitTestPerson;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
|
||||
import static com.mysema.query.types.PathMetadataFactory.forVariable;
|
||||
|
||||
|
||||
/**
|
||||
* QPerson is a Querydsl query type for Person
|
||||
*/
|
||||
@Generated("com.mysema.query.codegen.EntitySerializer")
|
||||
public class QPerson extends EntityPathBase<UnitTestPerson> {
|
||||
|
||||
private static final long serialVersionUID = -1526737794;
|
||||
|
||||
public static final QPerson person = new QPerson("person");
|
||||
|
||||
public final StringPath fullName = createString("fullName");
|
||||
|
||||
public final ListPath<String, StringPath> description = this.<String, StringPath>createList("description", String.class, StringPath.class, PathInits.DIRECT2);
|
||||
|
||||
public final StringPath lastName = createString("lastName");
|
||||
|
||||
public QPerson(String variable) {
|
||||
super(UnitTestPerson.class, forVariable(variable));
|
||||
}
|
||||
|
||||
public QPerson(Path<? extends UnitTestPerson> path) {
|
||||
super(path.getType(), path.getMetadata());
|
||||
}
|
||||
|
||||
public QPerson(PathMetadata<?> metadata) {
|
||||
super(UnitTestPerson.class, metadata);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
package org.springframework.ldap.repository.support;
|
||||
|
||||
import com.mysema.query.types.Expression;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.ldap.filter.Filter;
|
||||
import org.springframework.ldap.odm.core.ObjectDirectoryMapper;
|
||||
import org.springframework.ldap.odm.core.impl.DefaultObjectDirectoryMapper;
|
||||
import org.springframework.ldap.odm.core.impl.UnitTestPerson;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Mattias Hellborg Arthursson
|
||||
*/
|
||||
public class QueryDslFilterGeneratorTest {
|
||||
|
||||
private LdapSerializer tested;
|
||||
private QPerson person;
|
||||
|
||||
@Before
|
||||
public void prepareTestedInstance() {
|
||||
ObjectDirectoryMapper odm = new DefaultObjectDirectoryMapper();
|
||||
tested = new LdapSerializer(odm, UnitTestPerson.class);
|
||||
person = QPerson.person;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsFilter() {
|
||||
Expression<?> expression = person.fullName.eq("John Doe");
|
||||
Filter result = tested.handle(expression);
|
||||
assertEquals("(cn=John Doe)", result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAndFilter() {
|
||||
Expression<?> expression = person.fullName.eq("John Doe").and(person.lastName.eq("Doe"));
|
||||
Filter result = tested.handle(expression);
|
||||
assertEquals("(&(cn=John Doe)(sn=Doe))", result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOrFilter() {
|
||||
Expression<?> expression = person.fullName.eq("John Doe").or(person.lastName.eq("Doe"));
|
||||
Filter result = tested.handle(expression);
|
||||
assertEquals("(|(cn=John Doe)(sn=Doe))", result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOr() {
|
||||
Expression<?> expression = person.fullName.eq("John Doe")
|
||||
.and(person.lastName.eq("Doe").or(person.lastName.eq("Die")));
|
||||
|
||||
Filter result = tested.handle(expression);
|
||||
assertEquals("(&(cn=John Doe)(|(sn=Doe)(sn=Die)))", result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNot() {
|
||||
Expression<?> expression = person.fullName.eq("John Doe").not();
|
||||
Filter result = tested.handle(expression);
|
||||
assertEquals("(!(cn=John Doe))", result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsLike() {
|
||||
Expression<?> expression = person.fullName.like("kalle*");
|
||||
Filter result = tested.handle(expression);
|
||||
assertEquals("(cn=kalle*)", result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartsWith() {
|
||||
Expression<?> expression = person.fullName.startsWith("kalle");
|
||||
Filter result = tested.handle(expression);
|
||||
assertEquals("(cn=kalle*)", result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEndsWith() {
|
||||
Expression<?> expression = person.fullName.endsWith("kalle");
|
||||
Filter result = tested.handle(expression);
|
||||
assertEquals("(cn=*kalle)", result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContains() {
|
||||
Expression<?> expression = person.fullName.contains("kalle");
|
||||
Filter result = tested.handle(expression);
|
||||
assertEquals("(cn=*kalle*)", result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotNull() {
|
||||
Expression<?> expression = person.fullName.isNotNull();
|
||||
Filter result = tested.handle(expression);
|
||||
assertEquals("(cn=*)", result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNull() {
|
||||
Expression<?> expression = person.fullName.isNull();
|
||||
Filter result = tested.handle(expression);
|
||||
assertEquals("(!(cn=*))", result.toString());
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ ext.commonsLoggingVersion = '1.1.1'
|
||||
ext.gsbaseVersion = '2.0.1'
|
||||
ext.log4jVersion = '1.2.15'
|
||||
ext.mockitoVersion = '1.9.5'
|
||||
ext.queryDslVersion = '3.2.4'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
||||
@@ -245,7 +245,9 @@ public class PersonDaoImpl implements PersonDao {
|
||||
Below is a list of the most important changes in Spring LDAP 2.0.
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>Java 1.6 is now required when using Spring LDAP. Spring versions starting at 2.0 and up are still supported.</listitem>
|
||||
<listitem>
|
||||
Java 1.6 is now required when using Spring LDAP. Spring versions starting at 2.0 and up are still supported.
|
||||
</listitem>
|
||||
<listitem>
|
||||
The central API has been updated with Java 5 features such as generics and varargs. As a consequence,
|
||||
the entire <literal>spring-ldap-tiger</literal> module has been deprecated and users are encouraged to migrate
|
||||
@@ -262,6 +264,10 @@ public class PersonDaoImpl implements PersonDao {
|
||||
A custom XML namespace is now provided to simplify configuration of Spring LDAP.
|
||||
See <xref linkend="configuration" /> for more information.
|
||||
</listitem>
|
||||
<listitem>
|
||||
Spring Data Repository and QueryDSL support is now included in Spring LDAP.
|
||||
See <xref linkend="repositories" /> for more information.
|
||||
</listitem>
|
||||
<listitem>
|
||||
<literal>DistinguishedName</literal> and associated classes have been deprecated in favor of standard
|
||||
Java <literal>LdapName</literal>. See <xref linkend="ldap-names" /> for information on how the library
|
||||
|
||||
@@ -1,34 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<chapter id="repositories">
|
||||
<title>Spring LDAP Repositories</title>
|
||||
<title>Spring LDAP Repositories</title>
|
||||
|
||||
<sect1 id="repositories-overview">
|
||||
<title>Overview</title>
|
||||
|
||||
<para>
|
||||
Spring LDAP has built-in support for Spring Data repositories. The basic functionality and configuration is described <ulink
|
||||
url="http://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html">here</ulink>.
|
||||
When working with Spring LDAP repositories, please note the following:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
Spring LDAP repositories can be enabled using an <literal><ldap:repositories></literal> tag in
|
||||
your XML configuration or using an <literal>@EnableLdapRepositories</literal> annotation on a
|
||||
configuration class.
|
||||
</listitem>
|
||||
<listitem>
|
||||
All Spring LDAP repositories must work with entities annotated with the ODM annotations, as described
|
||||
in <xref linkend="odm" />.
|
||||
</listitem>
|
||||
<listitem>
|
||||
Since all ODM managed classes must have a Distinguished Name as ID, all Spring LDAP repositories must
|
||||
have the ID type parameter set to <literal>javax.naming.Name</literal>. Indeed, the built-in
|
||||
<literal>SpringLdapRepository</literal> only takes one type parameter; the managed entity class, defaulting
|
||||
ID to <literal>javax.naming.Name</literal>.
|
||||
</listitem>
|
||||
<listitem>
|
||||
Due to specifics of the LDAP protocol, paging and sorting is not supported for Spring LDAP repositories.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</sect1>
|
||||
<sect1 id="repositories-overview">
|
||||
<title>Overview</title>
|
||||
<para>
|
||||
Spring LDAP has built-in support for Spring Data repositories. The basic functionality and configuration is described <ulink
|
||||
url="http://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html">here</ulink>.
|
||||
When working with Spring LDAP repositories, please note the following:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
Spring LDAP repositories can be enabled using an <literal><ldap:repositories></literal> tag in
|
||||
your XML configuration or using an <literal>@EnableLdapRepositories</literal> annotation on a
|
||||
configuration class.
|
||||
</listitem>
|
||||
<listitem>
|
||||
To include support for <literal>LdapQuery</literal> parameters in automatically generated repositories,
|
||||
have your interface extend <literal>LdapRepository</literal> rather than <literal>CrudRepository</literal>.
|
||||
</listitem>
|
||||
<listitem>
|
||||
All Spring LDAP repositories must work with entities annotated with the ODM annotations, as described
|
||||
in <xref linkend="odm" />.
|
||||
</listitem>
|
||||
<listitem>
|
||||
Since all ODM managed classes must have a Distinguished Name as ID, all Spring LDAP repositories must
|
||||
have the ID type parameter set to <literal>javax.naming.Name</literal>. Indeed, the built-in
|
||||
<literal>SpringLdapRepository</literal> only takes one type parameter; the managed entity class, defaulting
|
||||
ID to <literal>javax.naming.Name</literal>.
|
||||
</listitem>
|
||||
<listitem>
|
||||
Due to specifics of the LDAP protocol, paging and sorting is not supported for Spring LDAP repositories.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</sect1>
|
||||
<sect1 id="querydsl-repositories">
|
||||
<title>QueryDSL support</title>
|
||||
<para>
|
||||
Basic QueryDSL support is included in Spring LDAP. This support includes the following:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
An Annotation Processor, <literal>LdapAnnotationProcessor</literal>, for generating QueryDSL classes
|
||||
based on Spring LDAP ODM annotations. See <xref linkend="odm" /> for more information on the ODM annotations.
|
||||
</listitem>
|
||||
<listitem>
|
||||
A Query implementation, <literal>QueryDslLdapQuery</literal>, for building and executing QueryDSL
|
||||
queries in code.
|
||||
</listitem>
|
||||
<listitem>
|
||||
Spring Data repository support for QueryDSL predicates. <literal>QueryDslPredicateExecutor</literal>
|
||||
includes a number of additional methods with appropriate parameters; extend this interface along with
|
||||
<literal>LdapRepository</literal> to include this support in your repository.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
@@ -3,11 +3,29 @@ repositories {
|
||||
}
|
||||
apply from: JAVA_SCRIPT
|
||||
|
||||
idea.module.excludeDirs = [
|
||||
file('.gradle'),
|
||||
file('build/classes'),
|
||||
file('build/tmp'),
|
||||
file('build/dependency-cache'),
|
||||
file('build/libs')]
|
||||
|
||||
sourceSets {
|
||||
generated {
|
||||
java {
|
||||
srcDirs = ['build/generated-src']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ext.springSecurityVersion='3.0.5.RELEASE'
|
||||
|
||||
dependencies {
|
||||
compile project(":spring-ldap-test"),
|
||||
project(":spring-ldap-core-tiger"),
|
||||
project(":spring-ldap-core-tiger")
|
||||
|
||||
compile "com.mysema.querydsl:querydsl-apt:$queryDslVersion"
|
||||
|
||||
compile("org.springframework.security:spring-security-core:$springSecurityVersion") {
|
||||
exclude group: "org.springframework", module: "spring-expression"
|
||||
exclude group: "org.springframework", module: "spring-core"
|
||||
@@ -33,4 +51,38 @@ dependencies {
|
||||
testCompile("org.springframework.security:spring-security-ldap:$springSecurityVersion") {
|
||||
exclude group: "org.springframework.ldap", module: "spring-ldap-core"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task generateQueryDSL(type: JavaCompile, group: 'build', description: 'Generates the QueryDSL query types') {
|
||||
source = sourceSets.main.java
|
||||
classpath = configurations.compile
|
||||
options.compilerArgs = [
|
||||
"-proc:only",
|
||||
"-processor", "org.springframework.ldap.repository.support.LdapAnnotationProcessor"
|
||||
]
|
||||
destinationDir = sourceSets.generated.java.srcDirs.iterator().next()
|
||||
}
|
||||
|
||||
compileJava {
|
||||
dependsOn generateQueryDSL
|
||||
source generateQueryDSL.destinationDir
|
||||
}
|
||||
|
||||
compileGeneratedJava {
|
||||
dependsOn generateQueryDSL
|
||||
options.warnings = false
|
||||
classpath += sourceSets.main.runtimeClasspath
|
||||
}
|
||||
|
||||
clean {
|
||||
delete sourceSets.generated.java.srcDirs
|
||||
}
|
||||
|
||||
ideaModule.dependsOn generateQueryDSL
|
||||
|
||||
idea {
|
||||
module {
|
||||
sourceDirs += file('build/generated-src')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.springframework.ldap.itest.repositories;
|
||||
|
||||
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
|
||||
import org.springframework.ldap.itest.odm.Person;
|
||||
import org.springframework.ldap.repository.LdapRepository;
|
||||
|
||||
/**
|
||||
* @author Mattias Hellborg Arthursson
|
||||
*/
|
||||
public interface PersonQueryDslRepository extends LdapRepository<Person>, QueryDslPredicateExecutor<Person> {
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2005-2013 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.ldap.itest.odm;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.ldap.core.LdapTemplate;
|
||||
import org.springframework.ldap.itest.AbstractLdapTemplateIntegrationTest;
|
||||
import org.springframework.ldap.repository.support.QueryDslLdapQuery;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* @author Mattias Hellborg Arthursson
|
||||
*/
|
||||
@ContextConfiguration(locations = {"/conf/ldapTemplateTestContext.xml"})
|
||||
public class LdapTemplateQueryDslLdapQueryITest extends AbstractLdapTemplateIntegrationTest {
|
||||
@Autowired
|
||||
private LdapTemplate tested;
|
||||
private QPerson qperson;
|
||||
private QueryDslLdapQuery<Person> query;
|
||||
|
||||
@Before
|
||||
public void prepareTestedInstance() {
|
||||
qperson = QPerson.person;
|
||||
query = new QueryDslLdapQuery<Person>(tested, qperson);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUniqueResult() {
|
||||
Person person = query.where(qperson.commonName.eq("Some Person3")).uniqueResult();
|
||||
|
||||
assertNotNull(person);
|
||||
assertEquals("Some Person3", person.getCommonName());
|
||||
assertEquals("Person3", person.getSurname());
|
||||
assertEquals("Sweden, Company1, Some Person3", person.getDesc().get(0));
|
||||
assertEquals("+46 555-123654", person.getTelephoneNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testList() {
|
||||
List<Person> persons = query.where(qperson.commonName.eq("Some Person3")).list();
|
||||
|
||||
Person person = persons.get(0);
|
||||
assertEquals("Some Person3", person.getCommonName());
|
||||
assertEquals("Person3", person.getSurname());
|
||||
assertEquals("Sweden, Company1, Some Person3", person.getDesc().get(0));
|
||||
assertEquals("+46 555-123654", person.getTelephoneNumber());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2005-2013 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.ldap.itest.repository;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.ldap.itest.AbstractLdapTemplateIntegrationTest;
|
||||
import org.springframework.ldap.itest.odm.Person;
|
||||
import org.springframework.ldap.itest.odm.QPerson;
|
||||
import org.springframework.ldap.itest.repositories.PersonQueryDslRepository;
|
||||
import org.springframework.ldap.support.LdapUtils;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
import javax.naming.Name;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Tests for Spring LDAP automatic repository scan functionality.
|
||||
*
|
||||
* @author Mattias Hellborg Arthursson
|
||||
*/
|
||||
@ContextConfiguration(locations = {"/conf/repositoryScanTestContext.xml"})
|
||||
public class RepositoryScanQueryDslITest extends AbstractLdapTemplateIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private PersonQueryDslRepository tested;
|
||||
|
||||
@Test
|
||||
public void testFindOneWithPredicate() {
|
||||
QPerson person = QPerson.person;
|
||||
|
||||
Person found = tested.findOne(person.commonName.eq("Some Person3"));
|
||||
|
||||
assertNotNull(found);
|
||||
assertEquals("Some Person3", found.getCommonName());
|
||||
assertEquals("Person3", found.getSurname());
|
||||
assertEquals("Sweden, Company1, Some Person3", found.getDesc().get(0));
|
||||
assertEquals("+46 555-123654", found.getTelephoneNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindAllWithPredicate() {
|
||||
QPerson person = QPerson.person;
|
||||
|
||||
Iterable<Person> foundPersons = tested.findAll(person.commonName.eq("Some Person3"));
|
||||
|
||||
Person found = foundPersons.iterator().next();
|
||||
assertEquals("Some Person3", found.getCommonName());
|
||||
assertEquals("Person3", found.getSurname());
|
||||
assertEquals("Sweden, Company1, Some Person3", found.getDesc().get(0));
|
||||
assertEquals("+46 555-123654", found.getTelephoneNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountWithPredicate() {
|
||||
QPerson person = QPerson.person;
|
||||
|
||||
long count = tested.count(person.commonName.eq("Some Person3"));
|
||||
assertEquals(1, count);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user