Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -18,74 +18,45 @@

import org.cloudfoundry.QueryParameter;
import org.cloudfoundry.reactor.util.AnnotationUtils;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.Exceptions;
import org.cloudfoundry.reactor.util.AnnotationUtils.AnnotatedValue;
import org.cloudfoundry.reactor.util.UriQueryParameter;
import org.cloudfoundry.reactor.util.UriQueryParameterBuilder;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* A builder for Cloud Foundry queries
*/
public final class QueryBuilder {
public final class QueryBuilder implements UriQueryParameterBuilder {

private QueryBuilder() {
public Stream<UriQueryParameter> build(Object instance) {
return AnnotationUtils.streamAnnotatedValues(instance, QueryParameter.class)
.map(QueryBuilder::processValue)
.filter(Objects::nonNull);
}

/**
* Augments a {@link UriComponentsBuilder} with queries based on the methods annotated with {@link QueryParameter}
*
* @param builder the builder to augment
* @param instance the instance to inspect and invoke
*/
public static void augment(UriComponentsBuilder builder, Object instance) {
Arrays.stream(instance.getClass().getMethods())
.sorted(MethodNameComparator.INSTANCE)
.forEach(processMethod(builder, instance));
private static UriQueryParameter processCollection(QueryParameter queryParameter, Object value) {
return processValue(queryParameter.value(), ((Collection<?>) value).stream()
.map(Object::toString)
.map(String::trim)
.collect(Collectors.joining(queryParameter.delimiter())));
}

private static Optional<Object> getValue(Method method, Object instance) {
try {
return Optional.ofNullable(method.invoke(instance));
} catch (IllegalAccessException | InvocationTargetException e) {
throw Exceptions.propagate(e);
private static UriQueryParameter processValue(AnnotatedValue<QueryParameter> annotatedValue) {
QueryParameter queryParameter = annotatedValue.getAnnotation();
Object value = annotatedValue.getValue();
if (value instanceof Collection) {
return processCollection(queryParameter, value);
} else {
return processValue(queryParameter.value(), value.toString());
}
}

private static Consumer<QueryParameter> processAnnotation(UriComponentsBuilder builder, Method method, Object instance) {
return queryParameter -> getValue(method, instance)
.ifPresent(processValue(builder, queryParameter));
}

private static void processCollection(UriComponentsBuilder builder, QueryParameter queryParameter, Object value) {
processValue(builder, queryParameter.value(),
((Collection<?>) value).stream()
.map(o -> o.toString().trim())
.collect(Collectors.joining(queryParameter.delimiter())));
}

private static Consumer<Method> processMethod(UriComponentsBuilder builder, Object instance) {
return method -> AnnotationUtils.findAnnotation(method, QueryParameter.class)
.ifPresent(processAnnotation(builder, method, instance));
}

private static void processValue(UriComponentsBuilder builder, String name, String value) {
builder.queryParam(name, value);
}

private static Consumer<Object> processValue(UriComponentsBuilder builder, QueryParameter queryParameter) {
return value -> {
if (value instanceof Collection) {
processCollection(builder, queryParameter, value);
} else {
processValue(builder, queryParameter.value(), value.toString());
}
};
private static UriQueryParameter processValue(String name, String value) {
return UriQueryParameter.of(name, value);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,13 @@
import org.cloudfoundry.reactor.TokenProvider;
import org.cloudfoundry.reactor.client.QueryBuilder;
import org.cloudfoundry.reactor.util.AbstractReactorOperations;
import org.cloudfoundry.reactor.util.DelegatingUriQueryParameterBuilder;
import org.cloudfoundry.reactor.util.ErrorPayloadMappers;
import org.cloudfoundry.reactor.util.MultipartHttpClientRequest;
import org.cloudfoundry.reactor.util.Operator;
import org.cloudfoundry.reactor.util.UriQueryParameter;
import org.cloudfoundry.reactor.util.UriQueryParameterBuilder;
import org.cloudfoundry.reactor.util.UriQueryParameters;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
Expand All @@ -34,6 +38,7 @@
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;

public abstract class AbstractClientV2Operations extends AbstractReactorOperations {

Expand Down Expand Up @@ -101,14 +106,18 @@ protected final <T> Mono<T> put(Object requestPayload, Class<T> responseType, Fu
.parseBody(responseType));
}

private static Function<UriComponentsBuilder, UriComponentsBuilder> queryTransformer(Object requestPayload) {
private Function<UriComponentsBuilder, UriComponentsBuilder> queryTransformer(Object requestPayload) {
return builder -> {
FilterBuilder.augment(builder, requestPayload);
QueryBuilder.augment(builder, requestPayload);
Stream<UriQueryParameter> parameters = getUriQueryParameterBuilder().build(requestPayload);
UriQueryParameters.set(builder, parameters);
return builder;
};
}

private UriQueryParameterBuilder getUriQueryParameterBuilder() {
return DelegatingUriQueryParameterBuilder.builder().builders(new FilterBuilder(), new QueryBuilder()).build();
}

private Operator attachErrorPayloadMapper(Operator operator) {
return operator.withErrorPayloadMapper(ErrorPayloadMappers.clientV2(this.connectionContext.getObjectMapper()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,89 +17,64 @@
package org.cloudfoundry.reactor.client.v2;

import org.cloudfoundry.client.v2.FilterParameter;
import org.cloudfoundry.reactor.client.MethodNameComparator;
import org.cloudfoundry.reactor.util.AnnotationUtils;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.Exceptions;
import org.cloudfoundry.reactor.util.AnnotationUtils.AnnotatedValue;
import org.cloudfoundry.reactor.util.UriQueryParameter;
import org.cloudfoundry.reactor.util.UriQueryParameterBuilder;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* A builder for Cloud Foundry V2 filters
*/
final class FilterBuilder {
final class FilterBuilder implements UriQueryParameterBuilder {

private FilterBuilder() {
public Stream<UriQueryParameter> build(Object instance) {
return AnnotationUtils.streamAnnotatedValues(instance, FilterParameter.class)
.map(FilterBuilder::processValue)
.filter(Objects::nonNull);
}

/**
* Augments a {@link UriComponentsBuilder} with queries based on the methods annotated with {@link FilterParameter}
*
* @param builder the builder to augment
* @param instance the instance to inspect and invoke
*/
public static void augment(UriComponentsBuilder builder, Object instance) {
Arrays.stream(instance.getClass().getMethods())
.sorted(MethodNameComparator.INSTANCE)
.forEach(processMethod(builder, instance));
}

private static Optional<Object> getValue(Method method, Object instance) {
try {
return Optional.ofNullable(method.invoke(instance));
} catch (IllegalAccessException | InvocationTargetException e) {
throw Exceptions.propagate(e);
}
}

private static Consumer<FilterParameter> processAnnotation(UriComponentsBuilder builder, Method method, Object instance) {
return filterParameter -> getValue(method, instance)
.ifPresent(processValue(builder, filterParameter));
}

private static void processCollection(UriComponentsBuilder builder, FilterParameter filterParameter, Object value) {
private static UriQueryParameter processCollection(FilterParameter filterParameter, Object value) {
List<String> collection = ((Collection<?>) value).stream()
.map(o -> o.toString().trim())
.map(Object::toString)
.map(String::trim)
.collect(Collectors.toList());

if (collection.size() == 1) {
processValue(builder, filterParameter.value(), filterParameter.operation(), collection.get(0));
return processValue(filterParameter.value(), filterParameter.operation(), collection.get(0));
} else if (collection.size() > 1) {
processValue(builder, filterParameter.value(), filterParameter.collectionOperation(), collection);
return processValue(filterParameter.value(), filterParameter.collectionOperation(), collection);
} else {
return null;
}
}

private static Consumer<Method> processMethod(UriComponentsBuilder builder, Object instance) {
return method -> AnnotationUtils.findAnnotation(method, FilterParameter.class)
.ifPresent(processAnnotation(builder, method, instance));
}

private static Consumer<Object> processValue(UriComponentsBuilder builder, FilterParameter filterParameter) {
return value -> {
if (value instanceof Collection) {
processCollection(builder, filterParameter, value);
} else {
processValue(builder, filterParameter.value(), filterParameter.operation(), value.toString().trim());
}
};
private static UriQueryParameter processValue(AnnotatedValue<FilterParameter> annotatedValue) {
FilterParameter filterParameter = annotatedValue.getAnnotation();
Object value = annotatedValue.getValue();
if (value instanceof Collection) {
return processCollection(filterParameter, value);
} else {
return processValue(filterParameter.value(), filterParameter.operation(), value.toString()
.trim());
}
}

private static void processValue(UriComponentsBuilder builder, String name, FilterParameter.Operation operation, Collection<String> collection) {
private static UriQueryParameter processValue(String name, FilterParameter.Operation operation, Collection<String> collection) {
String value = String.join(",", collection);
if (!value.isEmpty()) {
processValue(builder, name, operation, value);
return processValue(name, operation, value);
}
return null;
}

private static void processValue(UriComponentsBuilder builder, String name, FilterParameter.Operation operation, String value) {
builder.queryParam("q", String.format("%s%s%s", name, operation, value));
private static UriQueryParameter processValue(String name, FilterParameter.Operation operation, String value) {
return UriQueryParameter.of("q", String.format("%s%s%s", name, operation, value));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,13 @@
import org.cloudfoundry.reactor.TokenProvider;
import org.cloudfoundry.reactor.client.QueryBuilder;
import org.cloudfoundry.reactor.util.AbstractReactorOperations;
import org.cloudfoundry.reactor.util.DelegatingUriQueryParameterBuilder;
import org.cloudfoundry.reactor.util.ErrorPayloadMappers;
import org.cloudfoundry.reactor.util.MultipartHttpClientRequest;
import org.cloudfoundry.reactor.util.Operator;
import org.cloudfoundry.reactor.util.UriQueryParameter;
import org.cloudfoundry.reactor.util.UriQueryParameterBuilder;
import org.cloudfoundry.reactor.util.UriQueryParameters;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
Expand All @@ -37,6 +41,7 @@
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;

public abstract class AbstractClientV3Operations extends AbstractReactorOperations {

Expand Down Expand Up @@ -129,15 +134,18 @@ private static String extractJobId(HttpClientResponse response) {
return pathSegments.get(pathSegments.size() - 1);
}

private static Function<UriComponentsBuilder, UriComponentsBuilder> queryTransformer(Object requestPayload) {
private Function<UriComponentsBuilder, UriComponentsBuilder> queryTransformer(Object requestPayload) {
return builder -> {
FilterBuilder.augment(builder, requestPayload);
QueryBuilder.augment(builder, requestPayload);

Stream<UriQueryParameter> parameters = getUriQueryParameterBuilder().build(requestPayload);
UriQueryParameters.set(builder, parameters);
return builder;
};
}

private UriQueryParameterBuilder getUriQueryParameterBuilder() {
return DelegatingUriQueryParameterBuilder.builder().builders(new FilterBuilder(), new QueryBuilder()).build();
}

private Operator attachErrorPayloadMapper(Operator operator) {
return operator.withErrorPayloadMapper(ErrorPayloadMappers.clientV3(this.connectionContext.getObjectMapper()));
}
Expand Down
Loading