-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
java_8.clj
88 lines (78 loc) · 3.76 KB
/
java_8.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
;; java 8 annotation tests
(in-ns 'clojure.test-clojure.annotations)
(import [java.lang.annotation Annotation Retention RetentionPolicy Target ElementType]
[javax.xml.ws WebServiceRef WebServiceRefs]
[javax.xml.ws.soap AddressingFeature$Responses])
(definterface Foo (foo []))
(deftype #^{Deprecated true
Retention RetentionPolicy/RUNTIME
javax.annotation.processing.SupportedOptions ["foo" "bar" "baz"]
javax.xml.ws.soap.Addressing {:enabled false :required true}
WebServiceRefs [(WebServiceRef {:name "fred" :type String})
(WebServiceRef {:name "ethel" :mappedName "lucy"})]}
Bar [#^int a
#^{:tag int
Deprecated true
Retention RetentionPolicy/RUNTIME
javax.annotation.processing.SupportedOptions ["foo" "bar" "baz"]
javax.xml.ws.soap.Addressing {:enabled false :required true}
WebServiceRefs [(WebServiceRef {:name "fred" :type String})
(WebServiceRef {:name "ethel" :mappedName "lucy"})]}
b]
Foo (#^{Deprecated true
Retention RetentionPolicy/RUNTIME
javax.annotation.processing.SupportedOptions ["foo" "bar" "baz"]
javax.xml.ws.soap.Addressing {:enabled false :required true}
WebServiceRefs [(WebServiceRef {:name "fred" :type String})
(WebServiceRef {:name "ethel" :mappedName "lucy"})]}
foo [this] 42))
(defn annotation->map
"Converts a Java annotation (which conceals data)
into a map (which makes is usable). Not lazy.
Works recursively. Returns non-annotations unscathed."
[#^java.lang.annotation.Annotation o]
(cond
(instance? Annotation o)
(let [type (.annotationType o)
itfs (-> (into #{type} (supers type)) (disj java.lang.annotation.Annotation))
data-methods (into #{} (mapcat #(.getDeclaredMethods %) itfs))]
(into
{:annotationType (.annotationType o)}
(map
(fn [m] [(keyword (.getName m)) (annotation->map (.invoke m o nil))])
data-methods)))
(or (sequential? o) (.isArray (class o)))
(map annotation->map o)
:else o))
(def expected-annotations
#{{:annotationType java.lang.annotation.Retention, :value RetentionPolicy/RUNTIME}
{:annotationType javax.xml.ws.WebServiceRefs,
:value [{:annotationType javax.xml.ws.WebServiceRef, :name "fred", :mappedName "", :type java.lang.String, :wsdlLocation "", :value javax.xml.ws.Service, :lookup ""}
{:annotationType javax.xml.ws.WebServiceRef, :name "ethel", :mappedName "lucy", :type java.lang.Object, :wsdlLocation "", :value javax.xml.ws.Service, :lookup ""}]}
{:annotationType javax.xml.ws.soap.Addressing, :enabled false, :required true, :responses AddressingFeature$Responses/ALL}
{:annotationType javax.annotation.processing.SupportedOptions, :value ["foo" "bar" "baz"]}
{:annotationType java.lang.Deprecated}})
(deftest test-annotations-on-type
(is (=
expected-annotations
(into #{} (map annotation->map (.getAnnotations Bar))))))
(deftest test-annotations-on-field
(is (=
expected-annotations
(into #{} (map annotation->map (.getAnnotations (.getField Bar "b")))))))
(deftest test-annotations-on-method
(is (=
expected-annotations
(into #{} (map annotation->map (.getAnnotations (.getMethod Bar "foo" nil)))))))
(gen-class :name foo.Bar
:extends clojure.lang.Box
:constructors {^{Deprecated true} [Object] [Object]}
:init init
:prefix "foo")
(defn foo-init [obj]
[[obj] nil])
(deftest test-annotations-on-constructor
(is (some #(instance? Deprecated %)
(for [ctor (.getConstructors (Class/forName "foo.Bar"))
annotation (.getAnnotations ctor)]
annotation))))