Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filters support #278

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions src/main/java/com/arangodb/springframework/annotation/Filter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* DISCLAIMER
*
* Copyright 2023 Hewlett Packard Enterprise Development LP.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose this should be changed according to CLA

*
* 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 Hewlett Packard Enterprise Development LP.
*/

package com.arangodb.springframework.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.PARAMETER })
public @interface Filter {
String value() default "#filter";
}
12 changes: 12 additions & 0 deletions src/main/java/com/arangodb/springframework/core/util/AqlUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@

import com.arangodb.springframework.core.mapping.ArangoMappingContext;
import com.arangodb.springframework.core.mapping.ArangoPersistentProperty;
import com.arangodb.springframework.repository.query.filter.AqlFilterBuilder;
import com.arangodb.springframework.repository.query.filter.Filterable;
import com.arangodb.springframework.repository.query.search.AqlSearchBuilder;
import com.arangodb.springframework.repository.query.search.Searchable;

import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.lang.Nullable;
Expand All @@ -34,6 +39,7 @@
/**
*
* @author Christian Lechner
* @author Siva Prasad Erigineni
*/
public final class AqlUtils {

Expand Down Expand Up @@ -240,5 +246,11 @@ public static String buildCollectionName(final String collection) {
public static String buildFieldName(final String field) {
return field.contains("-") ? "`" + field + "`" : field;
}
public static String buildFilterClause(Filterable filter) {
return AqlFilterBuilder.of(filter).toFilterStatement();
}
public static String buildSearchClause(Searchable search) {
return AqlSearchBuilder.of(search).toSearchStatement();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* DISCLAIMER
*
* Copyright 2018 ArangoDB GmbH, Cologne, Germany
*
* Copyright 2023 Hewlett Packard Enterprise Development LP.
* 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
Expand All @@ -16,6 +16,7 @@
* limitations under the License.
*
* Copyright holder is ArangoDB GmbH, Cologne, Germany
* Copyright holder is Hewlett Packard Enterprise Development LP.
*/

package com.arangodb.springframework.repository.query;
Expand Down Expand Up @@ -177,6 +178,10 @@ protected AqlQueryOptions mergeQueryOptions(final AqlQueryOptions oldStatic, fin
if (mergedOptions.getAllowDirtyRead() == null) {
mergedOptions.allowDirtyRead(oldStatic.getAllowDirtyRead());
}
if(mergedOptions.getForceOneShardAttributeValue() != null) {
mergedOptions.forceOneShardAttributeValue(oldStatic.getForceOneShardAttributeValue());
}


return mergedOptions;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* DISCLAIMER
*
* Copyright 2018 ArangoDB GmbH, Cologne, Germany
* Copyright 2023 Hewlett Packard Enterprise Development LP.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,6 +17,7 @@
* limitations under the License.
*
* Copyright holder is ArangoDB GmbH, Cologne, Germany
* Copyright holder is Hewlett Packard Enterprise Development LP.
*/

package com.arangodb.springframework.repository.query;
Expand All @@ -26,6 +28,10 @@

import com.arangodb.model.AqlQueryOptions;

import com.arangodb.springframework.repository.query.filter.Filterable;

import com.arangodb.springframework.repository.query.search.Searchable;

/**
*
* @author Christian Lechner
Expand All @@ -39,5 +45,8 @@ public interface ArangoParameterAccessor extends ParameterAccessor {
Map<String, Object> getBindVars();

Map<String, Object> getSpelVars();

Filterable getFilter(String placeholder);

Searchable getSearch();
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* DISCLAIMER
*
* Copyright 2017 ArangoDB GmbH, Cologne, Germany
* Copyright 2023 Hewlett Packard Enterprise Development LP.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,13 +17,15 @@
* limitations under the License.
*
* Copyright holder is ArangoDB GmbH, Cologne, Germany
* Copyright holder is Hewlett Packard Enterprise Development LP.
*/

package com.arangodb.springframework.repository.query;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
Expand All @@ -36,6 +39,9 @@
import org.springframework.data.repository.query.Parameter;
import org.springframework.data.repository.query.Parameters;
import org.springframework.util.Assert;
import com.arangodb.springframework.annotation.Filter;
import com.arangodb.springframework.repository.query.filter.Filterable;
import com.arangodb.springframework.repository.query.search.Searchable;

import com.arangodb.model.AqlQueryOptions;
import com.arangodb.springframework.annotation.BindVars;
Expand All @@ -46,11 +52,14 @@
* @author Mark McCormick
* @author Mark Vollmary
* @author Christian Lechner
* @author Siva Prasad Erigineni
*/
public class ArangoParameters extends Parameters<ArangoParameters, ArangoParameters.ArangoParameter> {

private final int queryOptionsIndex;
private final int bindVarsIndex;
private final Map<String, Integer> filterIndexes;
private final int searchIndex;

public ArangoParameters(final Method method) {
super(method);
Expand All @@ -61,13 +70,18 @@ public ArangoParameters(final Method method) {
assertNonDuplicateParamNames(method);
this.queryOptionsIndex = getIndexOfSpecialParameter(ArangoParameter::isQueryOptions);
this.bindVarsIndex = getIndexOfSpecialParameter(ArangoParameter::isBindVars);
this.filterIndexes = mapFilterIndexes();
this.searchIndex = getIndexOfSpecialParameter(ArangoParameter::isSearch);

}

private ArangoParameters(final List<ArangoParameter> parameters, final int queryOptionsIndex,
final int bindVarsIndex) {
super(parameters);
this.queryOptionsIndex = queryOptionsIndex;
this.bindVarsIndex = bindVarsIndex;
this.filterIndexes = filterIndexes;
this.searchIndex = searchIndex;
}

@Override
Expand All @@ -77,7 +91,7 @@ protected ArangoParameter createParameter(final MethodParameter parameter) {

@Override
protected ArangoParameters createFrom(final List<ArangoParameter> parameters) {
return new ArangoParameters(parameters, this.queryOptionsIndex, this.bindVarsIndex);
return new ArangoParameters(parameters, this.queryOptionsIndex, this.bindVarsIndex, this.filterIndexes, this.searchIndex);
}

public boolean hasQueryOptions() {
Expand All @@ -95,6 +109,9 @@ public boolean hasBindVars() {
public int getBindVarsIndex() {
return this.bindVarsIndex;
}
public boolean hasFilterParameter() { return this.filterIndexes.size() > 0; }

public Map<String, Integer> getFilterIndexes() { return this.filterIndexes; }

private int getIndexOfSpecialParameter(final Predicate<ArangoParameter> condition) {
for (int index = 0; index < getNumberOfParameters(); ++index) {
Expand All @@ -106,6 +123,29 @@ private int getIndexOfSpecialParameter(final Predicate<ArangoParameter> conditio
return -1;
}

public boolean hasSearchParameter() { return this.searchIndex != -1; }

public int getSearchIndex() {
return this.searchIndex;
}

/**
* Returns the index of all Filter parameters indexed by their corresponding placeholders.
*/
private Map<String, Integer> mapFilterIndexes() {
Map<String, Integer> filters = new HashMap<>();

for (int index = 0; index < getNumberOfParameters(); ++index) {
final ArangoParameter param = getParameter(index);
if (param.isFilter()) {
filters.put(param.getPlaceholder(), index);
}
}

return filters;
}


private void assertSingleSpecialParameter(final Predicate<ArangoParameter> condition, final String message) {
boolean found = false;
for (int index = 0; index < getNumberOfParameters(); ++index) {
Expand Down Expand Up @@ -145,6 +185,7 @@ public ArangoParameter(final MethodParameter parameter) {
this.parameter = parameter;
assertCorrectBindParamPattern();
assertCorrectBindVarsType();
assertFilterType();
}

@Override
Expand All @@ -163,6 +204,11 @@ public boolean isBindVars() {
public boolean isSpelParam() {
return parameter.hasParameterAnnotation(SpelParam.class);
}
public boolean isFilter() { return parameter.hasParameterAnnotation(Filter.class); }

public boolean isSearch() {
return Searchable.class.isAssignableFrom(parameter.getParameterType());
}

@Override
public Optional<String> getName() {
Expand All @@ -176,7 +222,11 @@ public Optional<String> getName() {
public String getPlaceholder() {
if (isNamedParameter()) {
return String.format(NAMED_PARAMETER_TEMPLATE, getName().get());
} else {
}
else if (isFilter()) {
return this.parameter.getParameterAnnotation(Filter.class).value();
}
else {
return String.format(POSITION_PARAMETER_TEMPLATE, getIndex());
}
}
Expand Down Expand Up @@ -212,6 +262,14 @@ private void assertCorrectBindVarsType() {
Assert.isTrue(Object.class.equals(valueType), errorMsg);
}
}
private void assertFilterType() {
final String errorMsg = "@Filter parameter must be of type Filterable! Offending parameter: parameter "
+ parameter.getParameterIndex() + " on method" + parameter.getMethod();

if (isFilter()) {
Assert.isTrue(Filterable.class.equals(parameter.getParameterType()), errorMsg);
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* DISCLAIMER
*
* Copyright 2017 ArangoDB GmbH, Cologne, Germany
* Copyright 2023 Hewlett Packard Enterprise Development LP.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,6 +17,7 @@
* limitations under the License.
*
* Copyright holder is ArangoDB GmbH, Cologne, Germany
* Copyright holder is Hewlett Packard Enterprise Development LP.
*/

package com.arangodb.springframework.repository.query;
Expand All @@ -24,7 +26,8 @@
import java.util.stream.Collectors;

import org.springframework.data.repository.query.ParametersParameterAccessor;

import com.arangodb.springframework.repository.query.filter.Filterable;
import com.arangodb.springframework.repository.query.search.Searchable;
import com.arangodb.model.AqlQueryOptions;

/**
Expand Down Expand Up @@ -67,5 +70,16 @@ public Map<String, Object> getSpelVars() {
.filter(ArangoParameters.ArangoParameter::isSpelParam)
.collect(Collectors.toMap(it -> it.getName().get(), it -> getValue(it.getIndex())));
}
@Override
public Filterable getFilter(String placeholder) {
final Integer filterIndex = parameters.getFilterIndexes().get(placeholder);
return filterIndex == null ? null : getValue(filterIndex);
}

@Override
public Searchable getSearch() {
final int searchIndex = parameters.getSearchIndex();
return searchIndex == -1 ? null : getValue(searchIndex);
}

}
Loading