/* * DISCLAIMER * * Copyright 2017 ArangoDB GmbH, Cologne, Germany * * 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. * * Copyright holder is ArangoDB GmbH, Cologne, Germany */ package com.arangodb.springframework.repository; import java.lang.reflect.Method; import java.util.Optional; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.projection.ProjectionFactory; import org.springframework.data.repository.Repository; import org.springframework.data.repository.core.NamedQueries; import org.springframework.data.repository.core.RepositoryInformation; import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.data.repository.core.support.AnnotationRepositoryMetadata; import org.springframework.data.repository.core.support.DefaultRepositoryMetadata; import org.springframework.data.repository.core.support.RepositoryFactorySupport; import org.springframework.data.repository.query.QueryLookupStrategy; import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.data.util.ClassTypeInformation; import org.springframework.data.util.TypeInformation; import org.springframework.util.Assert; import com.arangodb.ArangoCursor; import com.arangodb.springframework.core.ArangoOperations; import com.arangodb.springframework.core.mapping.ArangoPersistentEntity; import com.arangodb.springframework.core.mapping.ArangoPersistentProperty; import com.arangodb.springframework.repository.query.ArangoQueryMethod; import com.arangodb.springframework.repository.query.DerivedArangoQuery; import com.arangodb.springframework.repository.query.StringBasedArangoQuery; /** * * @author Audrius Malele * @author Mark McCormick * @author Mark Vollmary * @author Christian Lechner */ public class ArangoRepositoryFactory extends RepositoryFactorySupport { private final ArangoOperations arangoOperations; private final MappingContext<? extends ArangoPersistentEntity<?>, ArangoPersistentProperty> context; public ArangoRepositoryFactory(final ArangoOperations arangoOperations) { this.arangoOperations = arangoOperations; this.context = arangoOperations.getConverter().getMappingContext(); } @SuppressWarnings("unchecked") @Override public <T, ID> ArangoEntityInformation<T, ID> getEntityInformation(final Class<T> domainClass) { return new ArangoPersistentEntityInformation<T, ID>( (ArangoPersistentEntity<T>) context.getRequiredPersistentEntity(domainClass)); } @SuppressWarnings({ "rawtypes", "unchecked" }) @Override protected Object getTargetRepository(final RepositoryInformation metadata) { return new SimpleArangoRepository(arangoOperations, metadata.getDomainType()); } @Override protected Class<?> getRepositoryBaseClass(final RepositoryMetadata metadata) { return SimpleArangoRepository.class; } @Override protected RepositoryMetadata getRepositoryMetadata(final Class<?> repositoryInterface) { Assert.notNull(repositoryInterface, "Repository interface must not be null!"); return Repository.class.isAssignableFrom(repositoryInterface) ? new DefaultArangoRepositoryMetadata(repositoryInterface) : new AnnotationArangoRepositoryMetadata(repositoryInterface); } @Override protected Optional<QueryLookupStrategy> getQueryLookupStrategy( final QueryLookupStrategy.Key key, final QueryMethodEvaluationContextProvider evaluationContextProvider) { QueryLookupStrategy strategy = null; switch (key) { case CREATE_IF_NOT_FOUND: strategy = new DefaultArangoQueryLookupStrategy(arangoOperations); break; case CREATE: break; case USE_DECLARED_QUERY: break; } return Optional.ofNullable(strategy); } static class DefaultArangoQueryLookupStrategy implements QueryLookupStrategy { private final ArangoOperations operations; public DefaultArangoQueryLookupStrategy(final ArangoOperations operations) { this.operations = operations; } @Override public RepositoryQuery resolveQuery( final Method method, final RepositoryMetadata metadata, final ProjectionFactory factory, final NamedQueries namedQueries) { final ArangoQueryMethod queryMethod = new ArangoQueryMethod(method, metadata, factory); final String namedQueryName = queryMethod.getNamedQueryName(); if (namedQueries.hasQuery(namedQueryName)) { final String namedQuery = namedQueries.getQuery(namedQueryName); return new StringBasedArangoQuery(namedQuery, queryMethod, operations); } else if (queryMethod.hasAnnotatedQuery()) { return new StringBasedArangoQuery(queryMethod, operations); } else { return new DerivedArangoQuery(queryMethod, operations); } } } static class DefaultArangoRepositoryMetadata extends DefaultRepositoryMetadata { private final TypeInformation<?> typeInformation; public DefaultArangoRepositoryMetadata(final Class<?> repositoryInterface) { super(repositoryInterface); typeInformation = ClassTypeInformation.from(repositoryInterface); } @Override public Class<?> getReturnedDomainClass(final Method method) { if (ArangoCursor.class.isAssignableFrom(method.getReturnType())) { return typeInformation.getReturnType(method).getRequiredComponentType().getType(); } else { return super.getReturnedDomainClass(method); } } } static class AnnotationArangoRepositoryMetadata extends AnnotationRepositoryMetadata { private final TypeInformation<?> typeInformation; public AnnotationArangoRepositoryMetadata(final Class<?> repositoryInterface) { super(repositoryInterface); typeInformation = ClassTypeInformation.from(repositoryInterface); } @Override public Class<?> getReturnedDomainClass(final Method method) { if (ArangoCursor.class.isAssignableFrom(method.getReturnType())) { return typeInformation.getReturnType(method).getRequiredComponentType().getType(); } else { return super.getReturnedDomainClass(method); } } } }