/*
* 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;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.neo4j.annotation.Depth;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.query.Parameters;
import org.springframework.data.repository.query.QueryMethod;
import org.springframework.util.StringUtils;
/**
* @author Mark Angrish
* @author Luanne Misquitta
* @author Oliver Gierke
*/
public class GraphQueryMethod extends QueryMethod {
private final Method method;
private final Query queryAnnotation;
private final Integer queryDepthParamIndex;
public GraphQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory) {
super(method, metadata, factory);
this.method = method;
this.queryAnnotation = method.getAnnotation(Query.class);
this.queryDepthParamIndex = getQueryDepthParamIndex(method);
Integer queryDepth = getStaticQueryDepth(method);
if (queryDepth !=null && queryDepthParamIndex!=null) {
throw new IllegalArgumentException(method.getName() + " cannot have both a method @Depth and a parameter @Depth");
}
}
@Override
protected Parameters<?, ?> createParameters(Method method) {
return new GraphParameters(method);
}
@Override
public GraphParameters getParameters() {
return (GraphParameters) super.getParameters();
}
public String getQuery() {
return queryAnnotation.value();
}
public Method getMethod() {
return method;
}
/**
* Returns the name of the named query this method belongs to.
*
* @return
*/
public String getNamedQueryName() {
return String.format("%s.%s", getDomainClass().getSimpleName(), method.getName());
}
public Integer getQueryDepthParamIndex() {
return queryDepthParamIndex;
}
private Integer getQueryDepthParamIndex(Method method) {
Annotation[][] annotations = method.getParameterAnnotations();
for (int i = 0; i < annotations.length; i++) {
if (annotations[i].length > 0) {
for (Annotation annotation : annotations[i]) {
if (annotation.annotationType() == Depth.class) {
if (method.getParameterTypes()[i] == Integer.class || method.getParameterTypes()[i] == int.class) {
return i;
}
else {
throw new IllegalArgumentException("Depth parameter in " + method.getName() + " must be an integer");
}
}
}
}
}
/*
//Java 8 only
Parameter[] parameters = method.getParameters();
for (int i = 0; i < method.getParameterCount(); i++) {
if (parameters[i].isAnnotationPresent(Depth.class)) {
if (parameters[i].getType() == Integer.class || parameters[i].getType() == int.class) {
return i;
}
else {
throw new IllegalArgumentException("Depth parameter in " + method.getName() + " must be an integer");
}
}
}*/
return null;
}
private Integer getStaticQueryDepth(Method method) {
if (method.isAnnotationPresent(Depth.class)) {
return method.getAnnotation(Depth.class).value();
}
return null;
}
public String getCountQueryString() {
return queryAnnotation != null ? queryAnnotation.countQuery() : null;
}
public boolean hasAnnotatedQuery() {
return getAnnotatedQuery() != null;
}
private String getAnnotatedQuery() {
String query = (String) AnnotationUtils.getValue(getQueryAnnotation());
return StringUtils.hasText(query) ? query : null;
}
private Query getQueryAnnotation() {
return AnnotatedElementUtils.findMergedAnnotation(method, Query.class);
}
}