rlm@10: ;; java 6 annotation tests rlm@10: (in-ns 'clojure.test-clojure.annotations) rlm@10: rlm@10: (import [java.lang.annotation Annotation Retention RetentionPolicy Target ElementType] rlm@10: [javax.xml.ws WebServiceRef WebServiceRefs]) rlm@10: (definterface Foo (foo [])) rlm@10: rlm@10: (deftype #^{Deprecated true rlm@10: Retention RetentionPolicy/RUNTIME rlm@10: javax.annotation.processing.SupportedOptions ["foo" "bar" "baz"] rlm@10: javax.xml.ws.soap.Addressing {:enabled false :required true} rlm@10: WebServiceRefs [(WebServiceRef {:name "fred" :type String}) rlm@10: (WebServiceRef {:name "ethel" :mappedName "lucy"})]} rlm@10: Bar [#^int a rlm@10: #^{:tag int rlm@10: Deprecated true rlm@10: Retention RetentionPolicy/RUNTIME rlm@10: javax.annotation.processing.SupportedOptions ["foo" "bar" "baz"] rlm@10: javax.xml.ws.soap.Addressing {:enabled false :required true} rlm@10: WebServiceRefs [(WebServiceRef {:name "fred" :type String}) rlm@10: (WebServiceRef {:name "ethel" :mappedName "lucy"})]} rlm@10: b] rlm@10: Foo (#^{Deprecated true rlm@10: Retention RetentionPolicy/RUNTIME rlm@10: javax.annotation.processing.SupportedOptions ["foo" "bar" "baz"] rlm@10: javax.xml.ws.soap.Addressing {:enabled false :required true} rlm@10: WebServiceRefs [(WebServiceRef {:name "fred" :type String}) rlm@10: (WebServiceRef {:name "ethel" :mappedName "lucy"})]} rlm@10: foo [this] 42)) rlm@10: rlm@10: (defn annotation->map rlm@10: "Converts a Java annotation (which conceals data) rlm@10: into a map (which makes is usable). Not lazy. rlm@10: Works recursively. Returns non-annotations unscathed." rlm@10: [#^java.lang.annotation.Annotation o] rlm@10: (cond rlm@10: (instance? Annotation o) rlm@10: (let [type (.annotationType o) rlm@10: itfs (-> (into #{type} (supers type)) (disj java.lang.annotation.Annotation)) rlm@10: data-methods (into #{} (mapcat #(.getDeclaredMethods %) itfs))] rlm@10: (into rlm@10: {:annotationType (.annotationType o)} rlm@10: (map rlm@10: (fn [m] [(keyword (.getName m)) (annotation->map (.invoke m o nil))]) rlm@10: data-methods))) rlm@10: (or (sequential? o) (.isArray (class o))) rlm@10: (map annotation->map o) rlm@10: :else o)) rlm@10: rlm@10: (def expected-annotations rlm@10: #{{:annotationType java.lang.annotation.Retention, :value RetentionPolicy/RUNTIME} rlm@10: {:annotationType javax.xml.ws.WebServiceRefs, rlm@10: :value [{:annotationType javax.xml.ws.WebServiceRef, :name "fred", :mappedName "", :type java.lang.String, :wsdlLocation "", :value java.lang.Object} rlm@10: {:annotationType javax.xml.ws.WebServiceRef, :name "ethel", :mappedName "lucy", :type java.lang.Object, :wsdlLocation "", :value java.lang.Object}]} rlm@10: {:annotationType javax.xml.ws.soap.Addressing, :enabled false, :required true} rlm@10: {:annotationType javax.annotation.processing.SupportedOptions, :value ["foo" "bar" "baz"]} rlm@10: {:annotationType java.lang.Deprecated}}) rlm@10: rlm@10: (deftest test-annotations-on-type rlm@10: (is (= rlm@10: expected-annotations rlm@10: (into #{} (map annotation->map (.getAnnotations Bar)))))) rlm@10: rlm@10: (deftest test-annotations-on-field rlm@10: (is (= rlm@10: expected-annotations rlm@10: (into #{} (map annotation->map (.getAnnotations (.getField Bar "b"))))))) rlm@10: rlm@10: (deftest test-annotations-on-method rlm@10: (is (= rlm@10: expected-annotations rlm@10: (into #{} (map annotation->map (.getAnnotations (.getMethod Bar "foo" nil))))))) rlm@10: