/*
* Copyright (c) [2011-2017] "Pivotal Software, Inc." / "Neo Technology" / "Graph Aware Ltd."
*
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
* You may not use this product except in compliance with the License.
*
* This product may include a number of subcomponents with
* separate copyright notices and license terms. Your use of the source
* code for these subcomponents is subject to the terms and
* conditions of the subcomponent's license, as noted in the LICENSE file.
*
*/
package org.springframework.data.neo4j.repository.query.derived;
import java.util.*;
import org.neo4j.ogm.cypher.Filters;
import org.neo4j.ogm.session.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.neo4j.repository.query.*;
import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.data.repository.query.ResultProcessor;
import org.springframework.data.repository.query.parser.PartTree;
/**
* Specialisation of {@link RepositoryQuery} that handles mapping of derived finders.
*
* @author Mark Angrish
* @author Luanne Misquitta
* @author Jasper Blues
* @author Vince Bickers
* @author Nicolas Mervaillie
* @author Mark Paluch
*/
public class DerivedGraphRepositoryQuery extends AbstractGraphRepositoryQuery {
private static final Logger LOG = LoggerFactory.getLogger(DerivedGraphRepositoryQuery.class);
private final DerivedQueryDefinition queryDefinition;
private final GraphQueryMethod graphQueryMethod;
private final PartTree tree;
public DerivedGraphRepositoryQuery(GraphQueryMethod graphQueryMethod, Session session) {
super(graphQueryMethod, session);
this.graphQueryMethod = graphQueryMethod;
Class<?> domainType = graphQueryMethod.getEntityInformation().getJavaType();
this.tree = new PartTree(graphQueryMethod.getName(), domainType);
this.queryDefinition = new DerivedQueryCreator(tree, domainType).createQuery();
}
@Override
protected Object doExecute(Query params, Object[] parameters) {
if (LOG.isDebugEnabled()) {
LOG.debug("Executing query for method {}", graphQueryMethod.getName());
}
GraphParameterAccessor accessor = new GraphParametersParameterAccessor(graphQueryMethod, parameters);
Class<?> returnType = graphQueryMethod.getMethod().getReturnType();
if (returnType.equals(Void.class)) {
throw new RuntimeException("Derived Queries must have a return type");
}
ResultProcessor processor = graphQueryMethod.getResultProcessor().withDynamicProjection(accessor);
return getExecution(accessor).execute(params, processor.getReturnedType().getDomainType());
}
@Override
protected Query getQuery(Object[] parameters) {
return new Query(resolveParams(parameters));
}
@Override
protected boolean isCountQuery() {
return tree.isCountProjection();
}
@Override
protected boolean isExistsQuery() {
return tree.isExistsProjection();
}
@Override
protected boolean isDeleteQuery() {
return tree.isDelete();
}
/**
* Sets values from parameters supplied by the finder on {@link org.neo4j.ogm.cypher.Filter} built by the {@link GraphQueryMethod}
*
* @param parameters parameter values supplied by the finder method
* @return List of Parameter with values set
*/
private Filters resolveParams(Object[] parameters) {
Map<Integer, Object> params = new HashMap<>();
for (int i = 0; i < parameters.length; i++) {
if (graphQueryMethod.getQueryDepthParamIndex() == null
|| (graphQueryMethod.getQueryDepthParamIndex() != null && graphQueryMethod.getQueryDepthParamIndex() != i)) {
params.put(i, parameters[i]);
}
}
return new Filters(queryDefinition.getFilters(params));
}
}