|
17 | 17 | (java.io Serializable Writer) |
18 | 18 | (java.util Map)))) |
19 | 19 |
|
20 | | -#? |
21 | | -(:clj |
22 | | - ;; recreate cljs' caching-hash macro |
23 | | - (defmacro caching-hash [this hash-fn hash-field] |
24 | | - `(do (when-not ~hash-field |
25 | | - (set! ~hash-field (~hash-fn ~this))) |
26 | | - ~hash-field))) |
27 | | - |
28 | 20 | ;; Parsed data format |
29 | 21 | ;; Represents a node of an XML tree |
30 | 22 |
|
|
36 | 28 | ;; also, elements don't have an extmap and degrade to hash-maps also |
37 | 29 | ;; when assoc'ing unknown keys |
38 | 30 |
|
39 | | -(deftype Element [tag attrs content meta |
40 | | - #?(:clj ^:volatile-mutable hash |
41 | | - :cljs ^:mutable hash)] |
| 31 | +;; FIXME hash caching cannot be used: http://dev.clojure.org/jira/browse/CLJ-2092 |
| 32 | + |
| 33 | +(deftype Element [tag attrs content meta] |
42 | 34 |
|
43 | 35 | ;; serializing/cloning, hashing, equality, iteration |
44 | 36 |
|
|
47 | 39 | [Serializable |
48 | 40 | MapEquivalence |
49 | 41 | IHashEq |
50 | | - (hasheq [this] (caching-hash this APersistentMap/mapHasheq hash)) |
| 42 | + (hasheq [this] (APersistentMap/mapHasheq this)) |
51 | 43 | Iterable |
52 | 44 | (iterator [this] (RecordIterator. this [:tag :attrs :content] (RT/iter nil)))] |
53 | 45 | :cljs |
54 | 46 | [ICloneable |
55 | | - (-clone [_] (Element. tag attrs content meta hash)) |
| 47 | + (-clone [_] (Element. tag attrs content meta)) |
56 | 48 | IHash |
57 | | - (-hash [this] (caching-hash this hash-unordered-coll hash)) |
| 49 | + (-hash [this] (hash-unordered-coll this)) |
58 | 50 | IEquiv |
59 | 51 | (-equiv [this other] (or (identical? this other) |
60 | 52 | ^boolean (js/cljs.core.equiv_map this other))) |
|
71 | 63 | (concat [">"] content ["</" qname ">"]) |
72 | 64 | ["/>"]))))) |
73 | 65 | #?@(:clj |
74 | | - [(hashCode [this] (caching-hash this APersistentMap/mapHash hash)) |
| 66 | + [(hashCode [this] (APersistentMap/mapHash this)) |
75 | 67 | (equals [this other] (APersistentMap/mapEquals this other)) |
76 | 68 | IPersistentMap |
77 | 69 | (equiv [this other] (APersistentMap/mapEquals this other))]) |
|
98 | 90 | #?(:cljs IAssociative) |
99 | 91 | (#?(:clj assoc :cljs -assoc) [this k v] |
100 | 92 | (case k |
101 | | - :tag (Element. v attrs content meta nil) |
102 | | - :attrs (Element. tag v content meta nil) |
103 | | - :content (Element. tag attrs v meta nil) |
| 93 | + :tag (Element. v attrs content meta) |
| 94 | + :attrs (Element. tag v content meta) |
| 95 | + :content (Element. tag attrs v meta) |
104 | 96 | (with-meta {:tag tag :attrs attrs :content content k v} meta))) |
105 | 97 | #?(:cljs IMap) |
106 | 98 | (#?(:clj without :cljs -dissoc) [this k] |
|
136 | 128 | (#?(:clj meta :cljs -meta) [this] meta) |
137 | 129 | #?(:cljs IWithMeta) |
138 | 130 | (#?(:clj withMeta :cljs -with-meta) [this next-meta] |
139 | | - (Element. tag attrs content next-meta hash)) |
| 131 | + (Element. tag attrs content next-meta)) |
140 | 132 |
|
141 | 133 | ;; cljs printing is protocol-based |
142 | 134 |
|
|
179 | 171 | (defn element* |
180 | 172 | "Create an xml element from a content collection and optional metadata" |
181 | 173 | ([tag attrs content meta] |
182 | | - (Element. tag (or attrs {}) (remove nil? content) meta nil)) |
| 174 | + (Element. tag (or attrs {}) (remove nil? content) meta)) |
183 | 175 | ([tag attrs content] |
184 | | - (Element. tag (or attrs {}) (remove nil? content) nil nil))) |
| 176 | + (Element. tag (or attrs {}) (remove nil? content) nil))) |
185 | 177 |
|
186 | 178 | #?(:clj |
187 | 179 | ;; Compiler macro for inlining the two constructors |
188 | 180 | (alter-meta! #'element* assoc :inline |
189 | 181 | (fn |
190 | 182 | ([tag attrs content meta] |
191 | | - `(Element. ~tag (or ~attrs {}) (remove nil? ~content) ~meta nil)) |
| 183 | + `(Element. ~tag (or ~attrs {}) (remove nil? ~content) ~meta)) |
192 | 184 | ([tag attrs content] |
193 | | - `(Element. ~tag (or ~attrs {}) (remove nil? ~content) nil nil))))) |
| 185 | + `(Element. ~tag (or ~attrs {}) (remove nil? ~content) nil))))) |
194 | 186 |
|
195 | 187 | (defn element |
196 | 188 | "Create an xml Element from content varargs" |
|
207 | 199 | "Create a Comment node" |
208 | 200 | [content] |
209 | 201 | (Comment. content)) |
| 202 | + |
| 203 | +(defn map->Element [{:keys [tag attrs content] :as el}] |
| 204 | + (element* tag attrs content (meta el))) |
| 205 | + |
| 206 | +(defn tagged-element [el] |
| 207 | + (cond (map? el) (map->Element el) |
| 208 | + ;; TODO support hiccup syntax |
| 209 | + :else (throw (ex-info "Unsupported element representation" |
| 210 | + {:element el})))) |
0 commit comments