|
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