|
43 | 43 | (.getName clazz)))) |
44 | 44 | (first builds)))))) |
45 | 45 |
|
46 | | -(defn- find-setters [^Class builder methods opts] |
| 46 | +(defn- find-setters [^Class builder methods props opts] |
47 | 47 | (let [candidates |
48 | 48 | (filter (fn [^java.lang.reflect.Method m] |
49 | 49 | (and (= 1 (alength ^"[Ljava.lang.Class;" (.getParameterTypes m))) |
50 | 50 | (= builder (.getReturnType m)) |
51 | 51 | (or (not (re-find #"^set[A-Z]" (.getName m))) |
52 | 52 | (not (:ignore-setters? opts))))) |
53 | 53 | methods)] |
54 | | - (reduce (fn [setter-map ^java.lang.reflect.Method m] |
55 | | - (let [prop (keyword |
56 | | - (cond (re-find #"^set[A-Z]" (.getName m)) |
57 | | - (let [^String n (subs (.getName m) 3)] |
58 | | - (str (Character/toLowerCase (.charAt n 0)) (subs n 1))) |
59 | | - (re-find #"^with[A-Z]" (.getName m)) |
60 | | - (let [^String n (subs (.getName m) 4)] |
61 | | - (str (Character/toLowerCase (.charAt n 0)) (subs n 1))) |
62 | | - :else |
63 | | - (.getName m)))] |
| 54 | + (->> candidates |
| 55 | + (reduce |
| 56 | + (fn [setter-map ^java.lang.reflect.Method m] |
| 57 | + (let [prop (keyword |
| 58 | + (cond (re-find #"^set[A-Z]" (.getName m)) |
| 59 | + (let [^String n (subs (.getName m) 3)] |
| 60 | + (str (Character/toLowerCase (.charAt n 0)) (subs n 1))) |
| 61 | + (re-find #"^with[A-Z]" (.getName m)) |
| 62 | + (let [^String n (subs (.getName m) 4)] |
| 63 | + (str (Character/toLowerCase (.charAt n 0)) (subs n 1))) |
| 64 | + :else |
| 65 | + (.getName m)))] |
| 66 | + (if (contains? props prop) |
64 | 67 | (if (contains? setter-map prop) |
65 | | - (throw (IllegalArgumentException. |
66 | | - (str "Duplicate setter found for " prop |
67 | | - " in " (.getName builder) " class"))) |
68 | | - (assoc setter-map prop (#'j/make-setter-fn m))))) |
69 | | - {} |
70 | | - candidates))) |
| 68 | + (let [clazz1 (#'j/get-setter-type (second (get setter-map prop))) |
| 69 | + clazz2 (#'j/get-setter-type m) |
| 70 | + p-val (get props prop)] |
| 71 | + (cond (and (instance? clazz1 p-val) |
| 72 | + (not (instance? clazz2 p-val))) |
| 73 | + setter-map ; existing setter is a better match: |
| 74 | + (and (not (instance? clazz1 p-val)) |
| 75 | + (instance? clazz2 p-val)) |
| 76 | + ;; this setter is a better match: |
| 77 | + (assoc setter-map prop [(#'j/make-setter-fn m) m]) |
| 78 | + :else ; neither is an obviously better match: |
| 79 | + (throw (IllegalArgumentException. |
| 80 | + (str "Duplicate setter found for " prop |
| 81 | + " in " (.getName builder) " class"))))) |
| 82 | + (assoc setter-map prop [(#'j/make-setter-fn m) m])) |
| 83 | + ;; if we are not trying to set this property, ignore the setter: |
| 84 | + setter-map))) |
| 85 | + {}) |
| 86 | + (reduce-kv |
| 87 | + (fn [m k v] |
| 88 | + (assoc m k (first v))) |
| 89 | + {})))) |
71 | 90 |
|
72 | 91 | (defn- build-on [instance setters ^Class clazz props] |
73 | 92 | (reduce-kv (fn [builder k v] |
|
94 | 113 | ;; * B setPropertyName( T ) |
95 | 114 | ;; treat both as setters; thrown exception if they clash |
96 | 115 | ;; (maybe an option to ignore setXyz( T ) methods?) |
97 | | - (find-setters java.util.Locale$Builder (.getMethods java.util.Locale$Builder) {}) |
| 116 | + (find-setters java.util.Locale$Builder (.getMethods java.util.Locale$Builder) {} {}) |
98 | 117 |
|
99 | 118 | ;; general pattern will be to: |
100 | 119 | ;; * get the builder class somehow |
|
113 | 132 | ^Class builder (get-builder-class clazz)] |
114 | 133 | (.invoke (get-builder clazz (.getMethods builder) opts) |
115 | 134 | (build-on (j/to-java builder ^clojure.lang.APersistentMap {}) |
116 | | - (find-setters builder (.getMethods builder) opts) |
| 135 | + (find-setters builder (.getMethods builder) props opts) |
117 | 136 | builder |
118 | 137 | props) |
119 | 138 | nil))) |
|
161 | 180 | ([^Class clazz ^Class builder instance props opts] |
162 | 181 | (.invoke (get-builder clazz (.getMethods builder) opts) |
163 | 182 | (build-on instance |
164 | | - (find-setters builder (.getMethods builder) opts) |
| 183 | + (find-setters builder (.getMethods builder) props opts) |
165 | 184 | builder |
166 | 185 | props) |
167 | 186 | nil))) |
|
0 commit comments