|
29 | 29 | import java.util.Arrays; |
30 | 30 | import java.util.Collections; |
31 | 31 | import java.util.HashMap; |
| 32 | +import java.util.LinkedHashMap; |
32 | 33 | import java.util.List; |
33 | 34 | import java.util.Map; |
34 | 35 | import java.util.UUID; |
| 36 | +import java.util.function.BiConsumer; |
| 37 | +import java.util.function.Consumer; |
35 | 38 | import java.util.function.Predicate; |
36 | 39 |
|
37 | 40 | import static io.jooby.SneakyThrows.throwingConsumer; |
@@ -107,12 +110,14 @@ public RouteAttributesWriter(Elements elements, Types types, ClassWriter writer, |
107 | 110 | this.visitor = visitor; |
108 | 111 | } |
109 | 112 |
|
110 | | - public void process(ExecutableElement method) throws NoSuchMethodException { |
| 113 | + public void process(ExecutableElement method, BiConsumer<String, Object[]> log) |
| 114 | + throws NoSuchMethodException { |
111 | 115 | Method target = Route.class.getDeclaredMethod("attribute", String.class, Object.class); |
112 | 116 | Map<String, Object> attributes = annotationMap(method); |
113 | 117 | for (Map.Entry<String, Object> attribute : attributes.entrySet()) { |
114 | 118 | String name = attribute.getKey(); |
115 | 119 | Object value = attribute.getValue(); |
| 120 | + log.accept(" %s: %s", new Object[]{name, value}); |
116 | 121 |
|
117 | 122 | visitor.visitVarInsn(ALOAD, 2); |
118 | 123 | visitor.visitLdcInsn(name); |
@@ -145,16 +150,26 @@ private Map<String, Object> annotationMap(List<? extends AnnotationMirror> annot |
145 | 150 | String prefix = root == null |
146 | 151 | ? annotation.getAnnotationType().asElement().getSimpleName().toString() |
147 | 152 | : root; |
148 | | - Map<? extends ExecutableElement, ? extends AnnotationValue> values = elements |
149 | | - .getElementValuesWithDefaults(annotation); |
150 | | - for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> attribute : values |
151 | | - .entrySet()) { |
152 | | - Object value = annotationValue(attribute.getValue()); |
153 | | - if (value != null) { |
154 | | - String method = attribute.getKey().getSimpleName().toString(); |
155 | | - String name = method.equals("value") ? prefix : prefix + "." + method; |
156 | | - result.put(name, value); |
157 | | - } |
| 153 | + // Set all values and then override with present values (fix for JDK 11+) |
| 154 | + result.putAll(toMap(elements |
| 155 | + .getElementValuesWithDefaults(annotation), prefix)); |
| 156 | + result.putAll(toMap(annotation.getElementValues(), prefix)); |
| 157 | + } |
| 158 | + return result; |
| 159 | + } |
| 160 | + |
| 161 | + private Map<String, Object> toMap( |
| 162 | + Map<? extends ExecutableElement, ? extends AnnotationValue> values, |
| 163 | + String prefix) { |
| 164 | + Map<String, Object> result = new LinkedHashMap<>(); |
| 165 | + for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> attribute : values |
| 166 | + .entrySet()) { |
| 167 | + Object value = annotationValue(attribute.getValue()); |
| 168 | + if (value != null) { |
| 169 | + String method = attribute.getKey().getSimpleName().toString(); |
| 170 | + String name = method.equals("value") ? prefix : prefix + "." + method; |
| 171 | + // Found value is override on JDK 11 with default annotation value, we trust that spe |
| 172 | + result.putIfAbsent(name, value); |
158 | 173 | } |
159 | 174 | } |
160 | 175 | return result; |
@@ -194,7 +209,9 @@ private void annotationValue(ClassWriter writer, MethodVisitor visitor, Object v |
194 | 209 | .visitMethodInsn(INVOKESTATIC, moduleInternalName, newMap, "()Ljava/util/Map;", false); |
195 | 210 | } else if (value instanceof List) { |
196 | 211 | List values = (List) value; |
197 | | - String componentType = values.get(0) instanceof EnumValue? ((EnumValue) values.get(0)).type : values.get(0).getClass().getName(); |
| 212 | + String componentType = values.get(0) instanceof EnumValue ? |
| 213 | + ((EnumValue) values.get(0)).type : |
| 214 | + values.get(0).getClass().getName(); |
198 | 215 | if (values.size() > 0) { |
199 | 216 | ArrayWriter.write(visitor, componentType, values, throwingConsumer(v -> |
200 | 217 | annotationValue(writer, visitor, v) |
@@ -274,7 +291,8 @@ private void annotationSingleValue(MethodVisitor visitor, Object value) |
274 | 291 | } else if (value instanceof EnumValue) { |
275 | 292 | EnumValue enumValue = (EnumValue) value; |
276 | 293 | Type type = Type.getObjectType(enumValue.type.replace(".", "/")); |
277 | | - visitor.visitFieldInsn(GETSTATIC, type.getInternalName(), enumValue.value, type.getDescriptor()); |
| 294 | + visitor |
| 295 | + .visitFieldInsn(GETSTATIC, type.getInternalName(), enumValue.value, type.getDescriptor()); |
278 | 296 | } |
279 | 297 |
|
280 | 298 | Method wrapper = Primitives.wrapper(value.getClass()); |
|
0 commit comments