View Javadoc
1   package net.avcompris.commons.query.tests;
2   
3   import static com.google.common.base.Preconditions.checkArgument;
4   import static com.google.common.base.Preconditions.checkNotNull;
5   import static net.avcompris.commons.query.impl.FieldUtils.extractPropertyName;
6   import static net.avcompris.commons.query.impl.FieldUtils.isBooleanField;
7   import static net.avcompris.commons.query.impl.FilteringsFactory.instantiate;
8   import static org.apache.commons.lang3.StringUtils.capitalize;
9   
10  import java.lang.reflect.InvocationHandler;
11  import java.lang.reflect.Method;
12  import java.lang.reflect.Proxy;
13  import java.util.ArrayList;
14  import java.util.Collection;
15  import java.util.List;
16  import java.util.stream.Stream;
17  
18  import org.junit.jupiter.params.ParameterizedTest;
19  import org.junit.jupiter.params.provider.Arguments;
20  import org.junit.jupiter.params.provider.MethodSource;
21  
22  import net.avcompris.commons.query.FilterSyntaxException;
23  import net.avcompris.commons.query.Filtering;
24  import net.avcompris.commons.query.Filterings;
25  import net.avcompris.commons.query.impl.Operation;
26  
27  public abstract class AbstractAllFilterByTest<T extends Filtering<U>, U extends Filtering.Field> {
28  
29  	private final Class<?> dtoClass;
30  	// private final String expression;
31  	// private final U field;
32  	// private final Class<? extends Filterings<T, U>> filteringsClass;
33  	private final Filterings<T, U> filterings;
34  
35  //	private final Class<U> contentHandlerClass;
36  
37  	protected AbstractAllFilterByTest(final Class<? extends Filterings<T, U>> filteringsClass,
38  			final Class<?> dtoClass) {
39  
40  		// this.filteringsClass =
41  		checkNotNull(filteringsClass, "filteringsClass");
42  		this.dtoClass = checkNotNull(dtoClass, "dtoClass");
43  		// this.contentHandlerClass = contentHandlerClass;
44  		// this.expression = checkNotNull(expression, "expression");
45  		// this.field = checkNotNull(field, "field");
46  
47  		filterings = instantiate(filteringsClass);
48  
49  		checkArgument(dtoClass.isInterface(), //
50  				"dtoClass should be an interface: %s", dtoClass.getName());
51  	}
52  
53  	@ParameterizedTest(name = "{0}")
54  	@MethodSource("testCases")
55  	public final void testParse(final String expression, final U field) throws Exception {
56  
57  		final String s = expression + " " + newValueFor(field);
58  
59  		parse(s);
60  	}
61  
62  	/*
63  	 * private static String capitalize(final String name) {
64  	 * 
65  	 * final StringBuilder sb = new StringBuilder();
66  	 * 
67  	 * boolean start = true;
68  	 * 
69  	 * for (final char c : name.toCharArray()) {
70  	 * 
71  	 * if (c == '_') {
72  	 * 
73  	 * start = true;
74  	 * 
75  	 * } else if (start) {
76  	 * 
77  	 * sb.append(c);
78  	 * 
79  	 * start = false;
80  	 * 
81  	 * } else {
82  	 * 
83  	 * sb.append(Character.toLowerCase(c)); } }
84  	 * 
85  	 * return sb.toString(); }
86  	 */
87  
88  	@ParameterizedTest(name = "{0}")
89  	@MethodSource("testCases")
90  	public final void testMatch(final String expression, final U field) throws Exception {
91  
92  		final T filtering = filterings.parse(expression + " " + newValueFor(field));
93  
94  		// final Method match = extractMatchMethod(filtering.getClass());
95  
96  		// final Class<?> contentHandlerClass = match.getParameterTypes()[0];
97  
98  		final String prefix;
99  
100 		if (isBooleanField(field)) {
101 
102 			prefix = "is";
103 
104 		} else {
105 
106 			prefix = "get";
107 		}
108 
109 		final String propertyName = extractPropertyName(field);
110 
111 		final String getterMethodName = prefix + capitalize(propertyName);
112 
113 		final Object p = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
114 				new Class<?>[] { dtoClass }, new InvocationHandler() {
115 
116 					@Override
117 					public Object invoke(final Object proxy, final Method method, final Object[] args)
118 							throws Throwable {
119 
120 						final String expectedMethodName = method.getReturnType().isArray() //
121 								? getterMethodName + "s" //
122 								: getterMethodName;
123 
124 						if (!expectedMethodName.contentEquals(method.getName())) {
125 							throw new IllegalStateException(
126 									"method: " + method + ", expectedMethodName: " + expectedMethodName);
127 						}
128 
129 						return randomValueFor(field);
130 					}
131 				});
132 
133 		filtering.match(p);
134 	}
135 
136 	protected abstract Object newValueFor(U field);
137 
138 	protected final Object randomValueFor(final U field) {
139 
140 		return newValueFor(field);
141 	}
142 
143 	protected final T parse(final String expression) throws FilterSyntaxException {
144 
145 		return filterings.parse(expression);
146 	}
147 
148 	protected static <U extends Filtering.Field> Stream<Arguments> testCases(final U[] values) throws Exception {
149 
150 		return parameters(values).stream() //
151 				.map((args) -> Arguments.of(args[0], args[1]));
152 	}
153 
154 	private static <U extends Filtering.Field> Collection<Object[]> parameters(final U[] values) throws Exception {
155 
156 		final List<Object[]> parameters = new ArrayList<>();
157 
158 		for (final U field : values) {
159 
160 			for (final Operation operation : Operation.getOperations(field)) {
161 
162 				final String expression = field + " " + operation;
163 
164 				parameters.add(new Object[] { expression, field });
165 			}
166 		}
167 
168 		return parameters;
169 	}
170 }