From 40cef30488747a405b8cd5944caa0af7beee88b4 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sat, 7 Sep 2013 14:16:42 -0700 Subject: [PATCH 001/101] Update parent pom to 0.1.2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d1895b9..5e4b8c5 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ org.clojure pom.contrib - 0.0.26 + 0.1.2 From 1019b5f4fed4df31ebfad6db901225c6efb22ff2 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Tue, 20 May 2014 19:24:36 -0700 Subject: [PATCH 002/101] Add CONTRIBUTING.md --- CONTRIBUTING.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..f3275ea --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,14 @@ +This is a [Clojure contrib] project. + +Under the Clojure contrib [guidelines], this project cannot accept +pull requests. All patches must be submitted via [JIRA]. + +See [Contributing] and the [FAQ] on the Clojure development [wiki] for +more information on how to contribute. + +[Clojure contrib]: http://dev.clojure.org/display/doc/Clojure+Contrib +[Contributing]: http://dev.clojure.org/display/community/Contributing +[FAQ]: http://dev.clojure.org/display/community/Contributing+FAQ +[JIRA]: http://dev.clojure.org/jira/browse/JDATA +[guidelines]: http://dev.clojure.org/display/community/Guidelines+for+Clojure+Contrib+committers +[wiki]: http://dev.clojure.org/ From d1661eae5305bb5dddad5599d14cad443c137d67 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Tue, 13 Dec 2016 09:04:40 -0600 Subject: [PATCH 003/101] Update parent pom version --- pom.xml | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/pom.xml b/pom.xml index 5e4b8c5..95e235b 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ java.data 0.1.2-SNAPSHOT - ${project.artifactId} + java.data https://github.com/clojure/java.data/ Utilities for working with Java beans from Clojure @@ -11,7 +11,7 @@ org.clojure pom.contrib - 0.1.2 + 0.2.0 @@ -26,16 +26,6 @@ git@github.com:clojure/java.data.git - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.0.2 - - - - org.clojure From cb0b2ca02d2e337fdc704ddf76bc4b932d5937fd Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Tue, 21 Mar 2017 22:03:57 -0500 Subject: [PATCH 004/101] Update parent pom --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 95e235b..fd8c659 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ org.clojure pom.contrib - 0.2.0 + 0.2.2 From a6eee35cc7088d09c63a70111893dce9c1983a0d Mon Sep 17 00:00:00 2001 From: puredanger Date: Tue, 15 Aug 2017 16:51:01 -0500 Subject: [PATCH 005/101] mark epl file as vendored --- .gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..0d1a34a --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +epl.html linguist-vendored=true From c0baed7f1c55a9ecf3e50e72c1fcc190e43ed3b6 Mon Sep 17 00:00:00 2001 From: Andy Fingerhut Date: Sun, 28 Oct 2012 17:09:43 -0700 Subject: [PATCH 006/101] JDATA-2: Eliminate many occurrences of Clojure reflection in java.data Signed-off-by: puredanger --- src/main/clojure/clojure/java/data.clj | 37 ++++++++++++++------------ 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/main/clojure/clojure/java/data.clj b/src/main/clojure/clojure/java/data.clj index 8f3832a..bf05364 100644 --- a/src/main/clojure/clojure/java/data.clj +++ b/src/main/clojure/clojure/java/data.clj @@ -27,14 +27,15 @@ ;; getters -(defn- is-getter [method] - (and method (= 0 (alength (. method (getParameterTypes)))))) +(defn- is-getter [^java.lang.reflect.Method method] + (and method + (= 0 (alength ^"[Ljava.lang.Class;" (.getParameterTypes method))))) -(defn- make-getter-fn [method] +(defn- make-getter-fn [^java.lang.reflect.Method method] (fn [instance] (from-java (.invoke method instance nil)))) -(defn- add-getter-fn [the-map prop-descriptor] +(defn- add-getter-fn [the-map ^java.beans.PropertyDescriptor prop-descriptor] (let [name (.getName prop-descriptor) method (.getReadMethod prop-descriptor)] (if (and (is-getter method) (not (= "class" name))) @@ -44,24 +45,24 @@ ;; setters -(defn- is-setter [method] +(defn- is-setter [^java.lang.reflect.Method method] (and method (= 1 (alength (. method (getParameterTypes)))))) -(defn- get-setter-type [method] +(defn- get-setter-type [^java.lang.reflect.Method method] (get (.getParameterTypes method) 0)) -(defn- make-setter-fn [method] +(defn- make-setter-fn [^java.lang.reflect.Method method] (fn [instance value] (.invoke method instance (into-array [(to-java (get-setter-type method) value)])))) -(defn- add-setter-fn [the-map prop-descriptor] +(defn- add-setter-fn [the-map ^java.beans.PropertyDescriptor prop-descriptor] (let [name (.getName prop-descriptor) method (.getWriteMethod prop-descriptor)] (if (is-setter method) (assoc the-map (keyword name) (make-setter-fn method)) the-map))) -(defn- add-array-methods [acls] +(defn- add-array-methods [^Class acls] (let [cls (.getComponentType acls) to (fn [_ sequence] (into-array cls (map (partial to-java cls) sequence))) @@ -79,11 +80,12 @@ cls value) value)) -(defmethod to-java [Enum String] [enum value] - (.invoke (.getDeclaredMethod enum "valueOf" (into-array [String])) nil (into-array [value]))) +(defmethod to-java [Enum String] [^Class enum value] + (.invoke (.getDeclaredMethod enum "valueOf" (into-array [String])) + nil (into-array [value]))) -(defn- throw-log-or-ignore-missing-setter [key clazz] +(defn- throw-log-or-ignore-missing-setter [key ^Class clazz] (let [message (str "Missing setter for " key " in " (.getCanonicalName clazz))] (cond (= *to-java-object-missing-setter* :error) (throw (new NoSuchFieldException message)) @@ -149,9 +151,9 @@ (defmacro ^{:private true} defnumbers [& boxes] (cons `do (for [box boxes - :let [box-cls (resolve box) - prim-cls (.get (.getField box-cls "TYPE") - box-cls) + :let [^Class box-cls (resolve box) + ^Class prim-cls (.get (.getField box-cls "TYPE") + box-cls) ;; Clojure 1.3: (assert (class? box-cls) (str box ": no class found")) _ (assert (class? box-cls)) ;; Clojure 1.3: (assert (class? prim-cls) (str box " has no TYPE field")) @@ -177,7 +179,7 @@ (defmethod to-java [javax.xml.datatype.XMLGregorianCalendar clojure.lang.APersistentMap] [clazz props] "Create an XMLGregorianCalendar object given the following keys :year :month :day :hour :minute :second :timezone" - (let [instance (.newInstance clazz) + (let [^javax.xml.datatype.XMLGregorianCalendar instance (.newInstance clazz) undefined javax.xml.datatype.DatatypeConstants/FIELD_UNDEFINED getu #(get %1 %2 undefined)] (doto instance @@ -189,7 +191,8 @@ (.setSecond (getu props :second)) (.setTimezone (getu props :timezone))))) -(defmethod from-java javax.xml.datatype.XMLGregorianCalendar [obj] +(defmethod from-java javax.xml.datatype.XMLGregorianCalendar + [^javax.xml.datatype.XMLGregorianCalendar obj] "Turn an XMLGregorianCalendar object into a clojure map of year, month, day, hour, minute, second and timezone " (let [date {:year (.getYear obj) :month (.getMonth obj) From fa5f91c644b28997dbd0f40d18292f33e64a722d Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Fri, 5 Jan 2018 11:36:36 -0600 Subject: [PATCH 007/101] add deps.edn --- .gitignore | 3 ++- deps.edn | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 deps.edn diff --git a/.gitignore b/.gitignore index c41cc9e..4f51760 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -/target \ No newline at end of file +/target +.cpcache/ diff --git a/deps.edn b/deps.edn new file mode 100644 index 0000000..3ffcee7 --- /dev/null +++ b/deps.edn @@ -0,0 +1 @@ +{:paths ["src/main/clojure"]} From 9eeac03fc605e385b76563063cd964bf924674b1 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Tue, 5 Jun 2018 08:23:49 -0500 Subject: [PATCH 008/101] add missing dependency in deps.edn --- deps.edn | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/deps.edn b/deps.edn index 3ffcee7..82323c5 100644 --- a/deps.edn +++ b/deps.edn @@ -1 +1,3 @@ -{:paths ["src/main/clojure"]} +{:paths ["src/main/clojure"] + :deps + {org.clojure/tools.logging {:mvn/version "0.2.3"}}} From 0f06ca5eb08726e74b2dab8654923894b7ace6af Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Tue, 5 Jun 2018 13:33:44 -0500 Subject: [PATCH 009/101] Add feature compare with bean --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index e38a9ef..3358cf4 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,20 @@ Constructing an instance of YourJavaClass from a Clojure data structure ) ``` +## Feature comparison to `clojure.core/bean` + +Clojure core provides a `bean` function which has some overlap with java.data. Below is a more detailed comparison: + +Dimension | `bean` | `java.data` +-- | ------ | ----------- +find fields | bean introspector | bean introspector - "class" +depth | 1 | recursive without cycle detection +field names | keyword | keyword +extensibility | none | multimethod on class +special casing | none | arrays, iterable, maps, enums, XMLGregorianCalendar +map keys | unhandled | untouched +exception defense | none | none + ## Developer Information * [GitHub project](https://github.com/clojure/java.data) From d31f0f280701b48ae87ca75f5d50c7dc940f9847 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Sat, 20 Oct 2018 19:33:36 -0500 Subject: [PATCH 010/101] Fix typos in README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3358cf4..3c7e699 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Representing an instance of YourJavaClass in a Clojure data structure ``` (defmethod from-java YourJavaClass [instance] - ; your custom logic for turing this instance into a clojure data structure + ; your custom logic for turning this instance into a clojure data structure ) ``` @@ -80,7 +80,7 @@ exception defense | none | none * Release 0.1.1 on 2012-04-29 * Initial release. - * Clojure 1.2 compatiblity + * Clojure 1.2 compatibility ## Copyright and License From cd80477b31b60820ea139ca4979ff41f8c3abcb7 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Sat, 20 Oct 2018 19:35:29 -0500 Subject: [PATCH 011/101] add pr template --- .github/PULL_REQUEST_TEMPLATE | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE new file mode 100644 index 0000000..0a5c486 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE @@ -0,0 +1,14 @@ +Hi! Thanks for your interest in contributing to this project. + +Clojure contrib projects do not use GitHub issues or pull requests, and +require a signed Contributor Agreement. If you would like to contribute, +please read more about the CA and sign that first (this can be done online). + +Then go to this project's issue tracker in JIRA to create tickets, update +tickets, or submit patches. For help in creating tickets and patches, +please see: + +- Signing the CA: https://dev.clojure.org/display/community/Contributing+FAQ +- Creating Tickets: https://dev.clojure.org/display/community/Creating+Tickets +- Developing Patches: https://dev.clojure.org/display/community/Developing+Patches +- Contributing FAQ: https://dev.clojure.org/display/community/Contributing+FAQ From 59724a1de83f1361506ef398e98f70dff03441ba Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sun, 28 Apr 2019 15:08:19 -0700 Subject: [PATCH 012/101] Update links in PR template --- .github/PULL_REQUEST_TEMPLATE | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE index 0a5c486..686625a 100644 --- a/.github/PULL_REQUEST_TEMPLATE +++ b/.github/PULL_REQUEST_TEMPLATE @@ -1,6 +1,6 @@ Hi! Thanks for your interest in contributing to this project. -Clojure contrib projects do not use GitHub issues or pull requests, and +Clojure contrib projects do not use GitHub issues or pull requests, and require a signed Contributor Agreement. If you would like to contribute, please read more about the CA and sign that first (this can be done online). @@ -8,7 +8,7 @@ Then go to this project's issue tracker in JIRA to create tickets, update tickets, or submit patches. For help in creating tickets and patches, please see: -- Signing the CA: https://dev.clojure.org/display/community/Contributing+FAQ -- Creating Tickets: https://dev.clojure.org/display/community/Creating+Tickets -- Developing Patches: https://dev.clojure.org/display/community/Developing+Patches -- Contributing FAQ: https://dev.clojure.org/display/community/Contributing+FAQ +- Signing the CA: https://clojure.org/community/contributing +- Creating Tickets: https://clojure.org/community/creating_tickets +- Developing Patches: https://clojure.org/community/developing_patches +- Contributing FAQ: https://clojure.org/community/contributing From 43429edd20fcb9190883cb6a16093f520b31fffa Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sun, 28 Apr 2019 15:33:18 -0700 Subject: [PATCH 013/101] Update links in CONTRIBUTING.md --- CONTRIBUTING.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f3275ea..87d33f9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,12 +3,10 @@ This is a [Clojure contrib] project. Under the Clojure contrib [guidelines], this project cannot accept pull requests. All patches must be submitted via [JIRA]. -See [Contributing] and the [FAQ] on the Clojure development [wiki] for +See [Contributing] on the Clojure website for more information on how to contribute. -[Clojure contrib]: http://dev.clojure.org/display/doc/Clojure+Contrib -[Contributing]: http://dev.clojure.org/display/community/Contributing -[FAQ]: http://dev.clojure.org/display/community/Contributing+FAQ +[Clojure contrib]: https://clojure.org/community/contrib_libs +[Contributing]: https://clojure.org/community/contributing [JIRA]: http://dev.clojure.org/jira/browse/JDATA -[guidelines]: http://dev.clojure.org/display/community/Guidelines+for+Clojure+Contrib+committers -[wiki]: http://dev.clojure.org/ +[guidelines]: https://clojure.org/community/contrib_howto From 4e5f0f91e57e3277f5b5d174aa3bc465b477104b Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sat, 12 Oct 2019 10:56:14 -0700 Subject: [PATCH 014/101] Fix JDATA-13 by removing all the remaining reflection warnings --- src/main/clojure/clojure/java/data.clj | 27 ++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/main/clojure/clojure/java/data.clj b/src/main/clojure/clojure/java/data.clj index bf05364..aebf8e7 100644 --- a/src/main/clojure/clojure/java/data.clj +++ b/src/main/clojure/clojure/java/data.clj @@ -11,7 +11,8 @@ :doc "Support for recursively converting Java beans to Clojure and vice versa."} clojure.java.data (:use [clojure.tools.logging :only (info)])) - + +(set! *warn-on-reflection* true) (def ^{:dynamic true, @@ -67,8 +68,8 @@ to (fn [_ sequence] (into-array cls (map (partial to-java cls) sequence))) from (fn [obj] (map from-java obj))] - (.addMethod to-java [acls Iterable] to) - (.addMethod from-java acls from) + (.addMethod ^clojure.lang.MultiFn to-java [acls Iterable] to) + (.addMethod ^clojure.lang.MultiFn from-java acls from) {:to to :from from})) ;; common to-java definitions @@ -92,7 +93,7 @@ (= *to-java-object-missing-setter* :log) (info message)))) -(defmethod to-java [Object clojure.lang.APersistentMap] [clazz props] +(defmethod to-java [Object clojure.lang.APersistentMap] [^Class clazz props] "Convert a Clojure map to the specified class using reflection to set the properties" (let [instance (.newInstance clazz) setter-map (reduce add-setter-fn {} (get-property-descriptors clazz))] @@ -142,11 +143,11 @@ (derive clazz ::do-not-convert)) (defmacro ^{:private true} defnumber [box prim prim-getter] - `(let [conv# (fn [_# number#] + `(let [conv# (fn [_# ^Number number#] (~(symbol (str box) "valueOf") (. number# ~prim-getter)))] - (.addMethod to-java [~prim Number] conv#) - (.addMethod to-java [~box Number] conv#))) + (.addMethod ^clojure.lang.MultiFn to-java [~prim Number] conv#) + (.addMethod ^clojure.lang.MultiFn to-java [~box Number] conv#))) (defmacro ^{:private true} defnumbers [& boxes] (cons `do @@ -177,13 +178,19 @@ ;; definitions for interfacting with XMLGregorianCalendar -(defmethod to-java [javax.xml.datatype.XMLGregorianCalendar clojure.lang.APersistentMap] [clazz props] +(defmethod to-java [javax.xml.datatype.XMLGregorianCalendar clojure.lang.APersistentMap] [^Class clazz props] "Create an XMLGregorianCalendar object given the following keys :year :month :day :hour :minute :second :timezone" (let [^javax.xml.datatype.XMLGregorianCalendar instance (.newInstance clazz) undefined javax.xml.datatype.DatatypeConstants/FIELD_UNDEFINED - getu #(get %1 %2 undefined)] + getu #(get %1 %2 undefined) + y (getu props :year)] + ;; .setYear is unique in having an overload on int and BigInteger + ;; whereas the other setters only have an int version so avoiding + ;; reflection means special treatment for .setYear + (if (instance? BigInteger y) + (.setYear instance ^BigInteger y) + (.setYear instance ^int y)) (doto instance - (.setYear (getu props :year)) (.setMonth (getu props :month)) (.setDay (getu props :day)) (.setHour (getu props :hour)) From 0b69c98a5f06a2400b930d76c8195c896f61c60e Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sat, 12 Oct 2019 11:01:55 -0700 Subject: [PATCH 015/101] Prep for 0.1.2 --- README.md | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 3c7e699..dc52b9b 100644 --- a/README.md +++ b/README.md @@ -6,30 +6,30 @@ clojure-contrib ## Releases and Dependency Information -Latest stable release: 0.1.1 +Latest stable release: 0.1.2 * [All Released Versions](http://search.maven.org/#search%7Cga%7C1%7Corg.clojure%20java.data) * [Development Snapshot Versions](https://repository.sonatype.org/index.html#nexus-search;gav~org.clojure~java.data~~~) ### Leiningen -``` -[org.clojure/java.data "0.1.1"] +```clojure +[org.clojure/java.data "0.1.2"] ``` ### Maven -``` +```xml org.clojure java.data - 0.1.1 + 0.1.2 ``` ## Example Usage -``` +```clojure (use 'clojure.java.data) (to-java YourJavaClass clojure-property-map) @@ -38,7 +38,7 @@ Latest stable release: 0.1.1 Representing an instance of YourJavaClass in a Clojure data structure -``` +```clojure (defmethod from-java YourJavaClass [instance] ; your custom logic for turning this instance into a clojure data structure ) @@ -46,7 +46,7 @@ Representing an instance of YourJavaClass in a Clojure data structure Constructing an instance of YourJavaClass from a Clojure data structure -``` +```clojure (defmethod to-java [YourJavaClass clojure.lang.APersistentMap] [clazz props] ; your custom logic for constructing an instance from a property map ) @@ -78,9 +78,12 @@ exception defense | none | none ## Change Log +* Release 0.1.2 on 2019-10-12 + * Fix reflection warnings JDATA-2 and JDATA-13. + * Release 0.1.1 on 2012-04-29 * Initial release. - * Clojure 1.2 compatibility + * Clojure 1.2 compatibility. ## Copyright and License From 10490ab2e32c2333dfc4ae734e1927b01bde65c2 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Sat, 12 Oct 2019 13:34:46 -0500 Subject: [PATCH 016/101] [maven-release-plugin] prepare release java.data-0.1.2 --- pom.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index fd8c659..bd1d000 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 0.1.2-SNAPSHOT + 0.1.2 java.data https://github.com/clojure/java.data/ @@ -24,7 +24,8 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - + java.data-0.1.2 + From 54e712ce9428351067b2d686fa37e0d14d4a0464 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Sat, 12 Oct 2019 13:34:46 -0500 Subject: [PATCH 017/101] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index bd1d000..5572297 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 0.1.2 + 0.1.3-SNAPSHOT java.data https://github.com/clojure/java.data/ @@ -24,7 +24,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - java.data-0.1.2 + HEAD From 048f627fec54f04d77865c48ee7964fd157f396e Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sat, 12 Oct 2019 23:21:18 -0700 Subject: [PATCH 018/101] Fix JDATA-6 Unrolls possible specialized hash map conversions. --- README.md | 3 ++ pom.xml | 3 ++ src/main/clojure/clojure/java/data.clj | 25 ++++++++++++++++- src/test/clojure/clojure/java/test_data.clj | 28 ++++++++++++------- .../java/clojure/java/data/test/TestBean.java | 15 ++++++++++ 5 files changed, 63 insertions(+), 11 deletions(-) create mode 100644 src/test/java/clojure/java/data/test/TestBean.java diff --git a/README.md b/README.md index dc52b9b..65adbfa 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,9 @@ exception defense | none | none ## Change Log +* Unreleased version (master) + * Fix `java.util.Map`/Clojure hash map setter handling JDATA-6. + * Release 0.1.2 on 2019-10-12 * Fix reflection warnings JDATA-2 and JDATA-13. diff --git a/pom.xml b/pom.xml index 5572297..e3205a5 100644 --- a/pom.xml +++ b/pom.xml @@ -18,6 +18,9 @@ Cosmin Stejerean + + Sean Corfield + diff --git a/src/main/clojure/clojure/java/data.clj b/src/main/clojure/clojure/java/data.clj index aebf8e7..3969574 100644 --- a/src/main/clojure/clojure/java/data.clj +++ b/src/main/clojure/clojure/java/data.clj @@ -93,8 +93,31 @@ (= *to-java-object-missing-setter* :log) (info message)))) +;; Clojure hash map conversions + +(defmethod to-java [java.lang.Iterable clojure.lang.APersistentMap] [_ props] + "A Clojure map is already a java.lang.Iterable" + props) + +(defmethod to-java [java.io.Serializable clojure.lang.APersistentMap] [_ props] + "A Clojure map is already a java.io.Serializable" + props) + +(defmethod to-java [java.util.Map clojure.lang.APersistentMap] [_ ^java.util.Map props] + "Convert a Clojure map to a new java.util.HashMap" + (java.util.HashMap. props)) + +(defmethod to-java [java.util.concurrent.Callable clojure.lang.APersistentMap] [_ clazz props] + "A Clojure map is already a java.util.concurrent.Callable" + props) + +(defmethod to-java [java.lang.Runnable clojure.lang.APersistentMap] [_ clazz props] + "A Clojure map is already a java.lang.Runnable" + props) + (defmethod to-java [Object clojure.lang.APersistentMap] [^Class clazz props] - "Convert a Clojure map to the specified class using reflection to set the properties" + "Convert a Clojure map to the specified class using reflection to set the + properties" (let [instance (.newInstance clazz) setter-map (reduce add-setter-fn {} (get-property-descriptors clazz))] (doseq [[key value] props] diff --git a/src/test/clojure/clojure/java/test_data.clj b/src/test/clojure/clojure/java/test_data.clj index f8cfa04..f6503da 100644 --- a/src/test/clojure/clojure/java/test_data.clj +++ b/src/test/clojure/clojure/java/test_data.clj @@ -10,14 +10,14 @@ (:use clojure.java.data) (:use [clojure.tools.logging :only (log* info)]) (:use clojure.test) - (:import (clojure.java.data.test Person Address State Primitive))) + (:import (clojure.java.data.test Person Address State Primitive TestBean))) (deftest clojure-to-java - (let [person (to-java Person {:name "Bob" - :age 30 - :address {:line1 "123 Main St" - :city "Dallas" - :state "TX" + (let [person (to-java Person {:name "Bob" + :age 30 + :address {:line1 "123 Main St" + :city "Dallas" + :state "TX" :zip "75432"}})] (is (= "Bob" (.getName person))) (is (= 30 (.getAge person))) @@ -29,8 +29,8 @@ (deftest clojure-to-java-error-on-missing-setter (binding [*to-java-object-missing-setter* :error] (is (thrown-with-msg? NoSuchFieldException #"Missing setter for :foobar in clojure.java.data.test.Person" - (to-java Person {:name "Bob" :foobar "Baz"}) - )))) + (to-java Person {:name "Bob" :foobar "Baz"}))))) + (deftest clojure-to-java-ignore-on-missing-setter (binding [*to-java-object-missing-setter* :ignore] @@ -41,8 +41,8 @@ `(let [current-var# ~var-name] (alter-var-root (var ~var-name) (fn [ignore#] ~new-value)) ~@body - (alter-var-root (var ~var-name) (fn [ignore#] current-var#))) - ) + (alter-var-root (var ~var-name) (fn [ignore#] current-var#)))) + (deftest clojure-to-java-log-on-missing-setter (binding [*to-java-object-missing-setter* :log] @@ -103,3 +103,11 @@ :stringArray ["Argument" "Vector"]}] (is (= datum (from-java (to-java Primitive datum)))))) + +(deftest jdata-6 + (let [bean-instance (TestBean.) + _ (. bean-instance setFoo {"bar" "baz"}) + bean-instance-as-map (from-java bean-instance) + new-bean-instance (to-java TestBean bean-instance-as-map)] + (is (= {"bar" "baz"} (:foo bean-instance-as-map))) + (is (= {"bar" "baz"} (.getFoo new-bean-instance))))) diff --git a/src/test/java/clojure/java/data/test/TestBean.java b/src/test/java/clojure/java/data/test/TestBean.java new file mode 100644 index 0000000..b8f1385 --- /dev/null +++ b/src/test/java/clojure/java/data/test/TestBean.java @@ -0,0 +1,15 @@ +package clojure.java.data.test; +import java.util.Map; + +public class TestBean { + + private java.util.Map foo; + + public void setFoo(Map foo) { + this.foo = foo; + } + + public Map getFoo() { + return foo; + } +} From 57512251041d41ab30b4a200b15a5673476deefa Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sat, 12 Oct 2019 23:53:51 -0700 Subject: [PATCH 019/101] Add tests to verify that Date and Instant round-trip correctly --- src/main/clojure/clojure/java/data.clj | 50 +++++++++++---------- src/test/clojure/clojure/java/test_data.clj | 10 +++++ 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/src/main/clojure/clojure/java/data.clj b/src/main/clojure/clojure/java/data.clj index 3969574..efe326a 100644 --- a/src/main/clojure/clojure/java/data.clj +++ b/src/main/clojure/clojure/java/data.clj @@ -93,28 +93,47 @@ (= *to-java-object-missing-setter* :log) (info message)))) +;; feature testing macro, based on suggestion from Chas Emerick: +(defmacro ^{:private true} when-available + [sym & body] + (try + (when (resolve sym) + (list* 'do body)) + (catch ClassNotFoundException _#))) + +(defmacro ^{:private true} when-not-available + [sym & body] + (try + (when-not (resolve sym) + (list* 'do body)) + (catch ClassNotFoundException _#))) + ;; Clojure hash map conversions (defmethod to-java [java.lang.Iterable clojure.lang.APersistentMap] [_ props] "A Clojure map is already a java.lang.Iterable" props) -(defmethod to-java [java.io.Serializable clojure.lang.APersistentMap] [_ props] - "A Clojure map is already a java.io.Serializable" - props) - (defmethod to-java [java.util.Map clojure.lang.APersistentMap] [_ ^java.util.Map props] "Convert a Clojure map to a new java.util.HashMap" (java.util.HashMap. props)) -(defmethod to-java [java.util.concurrent.Callable clojure.lang.APersistentMap] [_ clazz props] - "A Clojure map is already a java.util.concurrent.Callable" - props) +(defmethod to-java [java.util.concurrent.Callable clojure.lang.APersistentMap] [_ props] + "A Clojure map is already a java.util.concurrent.Callable" + props) -(defmethod to-java [java.lang.Runnable clojure.lang.APersistentMap] [_ clazz props] +(defmethod to-java [java.lang.Runnable clojure.lang.APersistentMap] [_ props] "A Clojure map is already a java.lang.Runnable" props) +(when-available + java.time.Instant + (defmethod to-java [java.time.Instant clojure.lang.APersistentMap] [_ props] + "Instant->map produces :nano, :epochSecond so do the reverse" + (when-not (and (:nano props) (:epochSecond props)) + (throw (IllegalArgumentException. "java.time.Instant requires :nano and :epochSecond"))) + (java.time.Instant/ofEpochSecond (:epochSecond props) (:nano props)))) + (defmethod to-java [Object clojure.lang.APersistentMap] [^Class clazz props] "Convert a Clojure map to the specified class using reflection to set the properties" @@ -127,21 +146,6 @@ (apply setter [instance value])))) instance)) -;; feature testing macro, based on suggestion from Chas Emerick: -(defmacro ^{:private true} when-available - [sym & body] - (try - (when (resolve sym) - (list* 'do body)) - (catch ClassNotFoundException _#))) - -(defmacro ^{:private true} when-not-available - [sym & body] - (try - (when-not (resolve sym) - (list* 'do body)) - (catch ClassNotFoundException _#))) - (when-available biginteger (defmethod to-java [BigInteger Object] [_ value] (biginteger value))) diff --git a/src/test/clojure/clojure/java/test_data.clj b/src/test/clojure/clojure/java/test_data.clj index f6503da..7139bfa 100644 --- a/src/test/clojure/clojure/java/test_data.clj +++ b/src/test/clojure/clojure/java/test_data.clj @@ -111,3 +111,13 @@ new-bean-instance (to-java TestBean bean-instance-as-map)] (is (= {"bar" "baz"} (:foo bean-instance-as-map))) (is (= {"bar" "baz"} (.getFoo new-bean-instance))))) + +(deftest jdata-8-11-date + (let [d (java.util.Date.)] + (is (= d (to-java java.util.Date (from-java d)))))) + +(when-available + java.time.Instant + (deftest jdata-8-11-instant + (let [t (java.time.Instant/now)] + (is (= t (to-java java.time.Instant (from-java t))))))) From cc56af71fc1145744e6b8e16cab9ad2a4999efe5 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sun, 13 Oct 2019 00:03:54 -0700 Subject: [PATCH 020/101] Fix JDATA-10 by explicitly converting Boolean --- README.md | 1 + src/main/clojure/clojure/java/data.clj | 3 ++- src/test/clojure/clojure/java/test_data.clj | 4 ++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 65adbfa..b3429d8 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,7 @@ exception defense | none | none * Unreleased version (master) * Fix `java.util.Map`/Clojure hash map setter handling JDATA-6. + * Fix `Boolean` conversion JDATA-10. * Release 0.1.2 on 2019-10-12 * Fix reflection warnings JDATA-2 and JDATA-13. diff --git a/src/main/clojure/clojure/java/data.clj b/src/main/clojure/clojure/java/data.clj index efe326a..dd0a30f 100644 --- a/src/main/clojure/clojure/java/data.clj +++ b/src/main/clojure/clojure/java/data.clj @@ -166,7 +166,7 @@ (into {} (for [[key getter-fn] (seq getter-map)] [key (getter-fn instance)])))))) -(doseq [clazz [String Character Byte Short Integer Long Float Double Boolean BigInteger BigDecimal]] +(doseq [clazz [String Character Byte Short Integer Long Float Double BigInteger BigDecimal]] (derive clazz ::do-not-convert)) (defmacro ^{:private true} defnumber [box prim prim-getter] @@ -201,6 +201,7 @@ (prefer-method from-java java.util.Map Iterable) (defmethod from-java nil [_] nil) +(defmethod from-java Boolean [value] (boolean value)) (defmethod from-java Enum [enum] (str enum)) ;; definitions for interfacting with XMLGregorianCalendar diff --git a/src/test/clojure/clojure/java/test_data.clj b/src/test/clojure/clojure/java/test_data.clj index 7139bfa..ad3b15d 100644 --- a/src/test/clojure/clojure/java/test_data.clj +++ b/src/test/clojure/clojure/java/test_data.clj @@ -121,3 +121,7 @@ (deftest jdata-8-11-instant (let [t (java.time.Instant/now)] (is (= t (to-java java.time.Instant (from-java t))))))) + +(deftest jdata-10 + (is (if (:absolute (from-java (java.net.URI. ""))) false true)) + (is (if (:opaque (from-java (java.net.URI. ""))) false true))) From 6cc2c5d6da2ec0c1399c0ee682fd32b857ce7eb5 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sun, 13 Oct 2019 00:25:59 -0700 Subject: [PATCH 021/101] JDATA-6, JDATA-9 test beans --- src/test/clojure/clojure/java/test_data.clj | 16 +++++++-- .../test/{TestBean.java => TestBean6.java} | 2 +- .../clojure/java/data/test/TestBean9.java | 34 +++++++++++++++++++ 3 files changed, 48 insertions(+), 4 deletions(-) rename src/test/java/clojure/java/data/test/{TestBean.java => TestBean6.java} (89%) create mode 100644 src/test/java/clojure/java/data/test/TestBean9.java diff --git a/src/test/clojure/clojure/java/test_data.clj b/src/test/clojure/clojure/java/test_data.clj index ad3b15d..822c113 100644 --- a/src/test/clojure/clojure/java/test_data.clj +++ b/src/test/clojure/clojure/java/test_data.clj @@ -10,7 +10,8 @@ (:use clojure.java.data) (:use [clojure.tools.logging :only (log* info)]) (:use clojure.test) - (:import (clojure.java.data.test Person Address State Primitive TestBean))) + (:import (clojure.java.data.test Person Address State Primitive + TestBean6 TestBean9))) (deftest clojure-to-java (let [person (to-java Person {:name "Bob" @@ -105,10 +106,10 @@ (from-java (to-java Primitive datum)))))) (deftest jdata-6 - (let [bean-instance (TestBean.) + (let [bean-instance (TestBean6.) _ (. bean-instance setFoo {"bar" "baz"}) bean-instance-as-map (from-java bean-instance) - new-bean-instance (to-java TestBean bean-instance-as-map)] + new-bean-instance (to-java TestBean6 bean-instance-as-map)] (is (= {"bar" "baz"} (:foo bean-instance-as-map))) (is (= {"bar" "baz"} (.getFoo new-bean-instance))))) @@ -122,6 +123,15 @@ (let [t (java.time.Instant/now)] (is (= t (to-java java.time.Instant (from-java t))))))) +(deftest jdata-9 + (let [bean-instance (TestBean9.) + _ (.setAString bean-instance "something") + _ (.setABool bean-instance true) + _ (.setABoolean bean-instance false)] + (is (= {:AString "something" :ABool true} + ;; :ABoolean missing because 'is' Boolean is not a getter + (from-java bean-instance))))) + (deftest jdata-10 (is (if (:absolute (from-java (java.net.URI. ""))) false true)) (is (if (:opaque (from-java (java.net.URI. ""))) false true))) diff --git a/src/test/java/clojure/java/data/test/TestBean.java b/src/test/java/clojure/java/data/test/TestBean6.java similarity index 89% rename from src/test/java/clojure/java/data/test/TestBean.java rename to src/test/java/clojure/java/data/test/TestBean6.java index b8f1385..5cb1d70 100644 --- a/src/test/java/clojure/java/data/test/TestBean.java +++ b/src/test/java/clojure/java/data/test/TestBean6.java @@ -1,7 +1,7 @@ package clojure.java.data.test; import java.util.Map; -public class TestBean { +public class TestBean6 { private java.util.Map foo; diff --git a/src/test/java/clojure/java/data/test/TestBean9.java b/src/test/java/clojure/java/data/test/TestBean9.java new file mode 100644 index 0000000..36ea315 --- /dev/null +++ b/src/test/java/clojure/java/data/test/TestBean9.java @@ -0,0 +1,34 @@ +package clojure.java.data.test; +import java.util.Map; + +public class TestBean9 { + + private boolean aBool; + private Boolean aBoolean; + private String aString; + + public void setABool(boolean b) { + this.aBool = b; + } + + public boolean isABool() { + return aBool; + } + + public void setABoolean(Boolean b) { + this.aBoolean = b; + } + + // not a getter because 'is' only works for primitive boolean + public Boolean isABoolean() { + return aBoolean; + } + + public void setAString(String s) { + this.aString = s; + } + + public String getAString() { + return aString; + } +} From 3441ef0ad79fd4e7671c200dcf8ea92258bc3e3b Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sun, 13 Oct 2019 00:39:41 -0700 Subject: [PATCH 022/101] Fix JDATA-12 --- README.md | 1 + src/main/clojure/clojure/java/data.clj | 2 ++ src/test/clojure/clojure/java/test_data.clj | 12 ++++++++++++ 3 files changed, 15 insertions(+) diff --git a/README.md b/README.md index b3429d8..6db5db8 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ exception defense | none | none * Unreleased version (master) * Fix `java.util.Map`/Clojure hash map setter handling JDATA-6. * Fix `Boolean` conversion JDATA-10. + * Fix `SQLException` handling JDATA-12. * Release 0.1.2 on 2019-10-12 * Fix reflection warnings JDATA-2 and JDATA-13. diff --git a/src/main/clojure/clojure/java/data.clj b/src/main/clojure/clojure/java/data.clj index dd0a30f..3b246d2 100644 --- a/src/main/clojure/clojure/java/data.clj +++ b/src/main/clojure/clojure/java/data.clj @@ -201,6 +201,8 @@ (prefer-method from-java java.util.Map Iterable) (defmethod from-java nil [_] nil) +(defmethod from-java java.sql.SQLException [^Object ex] + ((get-method from-java :default) ex)) (defmethod from-java Boolean [value] (boolean value)) (defmethod from-java Enum [enum] (str enum)) diff --git a/src/test/clojure/clojure/java/test_data.clj b/src/test/clojure/clojure/java/test_data.clj index 822c113..6420e1f 100644 --- a/src/test/clojure/clojure/java/test_data.clj +++ b/src/test/clojure/clojure/java/test_data.clj @@ -135,3 +135,15 @@ (deftest jdata-10 (is (if (:absolute (from-java (java.net.URI. ""))) false true)) (is (if (:opaque (from-java (java.net.URI. ""))) false true))) + +(deftest jdata-12 + (let [eek1 (java.sql.SQLException. "SQL 1") + eek2 (java.sql.SQLException. "SQL 2") + eek3 (java.sql.SQLException. "SQL 3")] + (.setNextException eek1 eek2) + (.setNextException eek2 eek3) + (let [ex (from-java eek1)] + (is (= "SQL 1" (get-in ex [:message]))) + (is (= "SQL 2" (get-in ex [:nextException :message]))) + (is (= "SQL 3" (get-in ex [:nextException :nextException :message]))) + (is (nil? (get-in ex [:nextException :nextException :nextException])))))) From d4b47a566b3a8ebba5b8bf9f0d904ae6346ce94d Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sun, 13 Oct 2019 00:43:44 -0700 Subject: [PATCH 023/101] Prep for 0.1.3 release --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 6db5db8..912522d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ clojure-contrib ## Releases and Dependency Information -Latest stable release: 0.1.2 +Latest stable release: 0.1.3 * [All Released Versions](http://search.maven.org/#search%7Cga%7C1%7Corg.clojure%20java.data) * [Development Snapshot Versions](https://repository.sonatype.org/index.html#nexus-search;gav~org.clojure~java.data~~~) @@ -14,7 +14,7 @@ Latest stable release: 0.1.2 ### Leiningen ```clojure -[org.clojure/java.data "0.1.2"] +[org.clojure/java.data "0.1.3"] ``` ### Maven @@ -23,7 +23,7 @@ Latest stable release: 0.1.2 org.clojure java.data - 0.1.2 + 0.1.3 ``` @@ -36,7 +36,7 @@ Latest stable release: 0.1.2 (from-java javaValue) ``` -Representing an instance of YourJavaClass in a Clojure data structure +Representing an instance of `YourJavaClass` in a Clojure data structure ```clojure (defmethod from-java YourJavaClass [instance] @@ -44,7 +44,7 @@ Representing an instance of YourJavaClass in a Clojure data structure ) ``` -Constructing an instance of YourJavaClass from a Clojure data structure +Constructing an instance of `YourJavaClass` from a Clojure data structure ```clojure (defmethod to-java [YourJavaClass clojure.lang.APersistentMap] [clazz props] @@ -62,7 +62,7 @@ find fields | bean introspector | bean introspector - "class" depth | 1 | recursive without cycle detection field names | keyword | keyword extensibility | none | multimethod on class -special casing | none | arrays, iterable, maps, enums, XMLGregorianCalendar +special casing | none | arrays, iterable, maps, enums, Instant, SQLException, XMLGregorianCalendar map keys | unhandled | untouched exception defense | none | none @@ -78,7 +78,7 @@ exception defense | none | none ## Change Log -* Unreleased version (master) +* Release 0.1.3 on 2019-10-13 * Fix `java.util.Map`/Clojure hash map setter handling JDATA-6. * Fix `Boolean` conversion JDATA-10. * Fix `SQLException` handling JDATA-12. From c2f70a163d21a9a1997d2cfcc11eb069adc22e3e Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Sun, 13 Oct 2019 05:44:12 -0500 Subject: [PATCH 024/101] [maven-release-plugin] prepare release java.data-0.1.3 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index e3205a5..ff5c6f9 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 0.1.3-SNAPSHOT + 0.1.3 java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - HEAD + java.data-0.1.3 From 6ba528dc736abb078d1c6c44de3f49fb1f7784ea Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Sun, 13 Oct 2019 05:44:13 -0500 Subject: [PATCH 025/101] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ff5c6f9..21fefda 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 0.1.3 + 0.1.4-SNAPSHOT java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - java.data-0.1.3 + HEAD From 60032a2b525e05460db8a7897cda02dcdf52961d Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sun, 13 Oct 2019 12:40:33 -0700 Subject: [PATCH 026/101] Prep for 0.1.4 release Primarily fixing Clojure map conversion problems introduced in 0.1.3 --- README.md | 9 ++-- src/main/clojure/clojure/java/data.clj | 57 ++++++++++++++------------ 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 912522d..d2069f8 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ clojure-contrib ## Releases and Dependency Information -Latest stable release: 0.1.3 +Latest stable release: 0.1.4 * [All Released Versions](http://search.maven.org/#search%7Cga%7C1%7Corg.clojure%20java.data) * [Development Snapshot Versions](https://repository.sonatype.org/index.html#nexus-search;gav~org.clojure~java.data~~~) @@ -14,7 +14,7 @@ Latest stable release: 0.1.3 ### Leiningen ```clojure -[org.clojure/java.data "0.1.3"] +[org.clojure/java.data "0.1.4"] ``` ### Maven @@ -23,7 +23,7 @@ Latest stable release: 0.1.3 org.clojure java.data - 0.1.3 + 0.1.4 ``` @@ -78,6 +78,9 @@ exception defense | none | none ## Change Log +* Release 0.1.4 on 2019-10-13 + * Fix Clojure hash map conversion problems JDATA-14 (problems introduced in 0.1.3) + * Release 0.1.3 on 2019-10-13 * Fix `java.util.Map`/Clojure hash map setter handling JDATA-6. * Fix `Boolean` conversion JDATA-10. diff --git a/src/main/clojure/clojure/java/data.clj b/src/main/clojure/clojure/java/data.clj index 3b246d2..85fe3b2 100644 --- a/src/main/clojure/clojure/java/data.clj +++ b/src/main/clojure/clojure/java/data.clj @@ -10,7 +10,8 @@ ^{:author "Cosmin Stejerean", :doc "Support for recursively converting Java beans to Clojure and vice versa."} clojure.java.data - (:use [clojure.tools.logging :only (info)])) + (:require [clojure.string :as str] + [clojure.tools.logging :as logger])) (set! *warn-on-reflection* true) @@ -91,7 +92,7 @@ (cond (= *to-java-object-missing-setter* :error) (throw (new NoSuchFieldException message)) (= *to-java-object-missing-setter* :log) - (info message)))) + (logger/info message)))) ;; feature testing macro, based on suggestion from Chas Emerick: (defmacro ^{:private true} when-available @@ -110,22 +111,6 @@ ;; Clojure hash map conversions -(defmethod to-java [java.lang.Iterable clojure.lang.APersistentMap] [_ props] - "A Clojure map is already a java.lang.Iterable" - props) - -(defmethod to-java [java.util.Map clojure.lang.APersistentMap] [_ ^java.util.Map props] - "Convert a Clojure map to a new java.util.HashMap" - (java.util.HashMap. props)) - -(defmethod to-java [java.util.concurrent.Callable clojure.lang.APersistentMap] [_ props] - "A Clojure map is already a java.util.concurrent.Callable" - props) - -(defmethod to-java [java.lang.Runnable clojure.lang.APersistentMap] [_ props] - "A Clojure map is already a java.lang.Runnable" - props) - (when-available java.time.Instant (defmethod to-java [java.time.Instant clojure.lang.APersistentMap] [_ props] @@ -136,15 +121,33 @@ (defmethod to-java [Object clojure.lang.APersistentMap] [^Class clazz props] "Convert a Clojure map to the specified class using reflection to set the - properties" - (let [instance (.newInstance clazz) - setter-map (reduce add-setter-fn {} (get-property-descriptors clazz))] - (doseq [[key value] props] - (let [setter (get setter-map (keyword key))] - (if (nil? setter) - (throw-log-or-ignore-missing-setter key clazz) - (apply setter [instance value])))) - instance)) + properties. If the class is an interface, we can't create an instance of + it, unless the Clojure map already implements it." + (if (.isInterface clazz) + (if (instance? clazz props) + (condp = clazz + ;; make a fresh (mutabl) hash map from the Clojure map + java.util.Map (java.util.HashMap. ^java.util.Map props) + ;; Iterable, Serializable, Runnable, Callable + ;; we should probably figure out actual objects to create... + props) + (throw (IllegalArgumentException. + (str (.getName clazz) " is an interface " + "and cannot be constructed from " + (str/join ", " (map name (keys props))))))) + (let [instance (try (.newInstance clazz) + (catch Throwable t + (throw (IllegalArgumentException. + (str (.getName clazz) + " cannot be constructed") + t)))) + setter-map (reduce add-setter-fn {} (get-property-descriptors clazz))] + (doseq [[key value] props] + (let [setter (get setter-map (keyword key))] + (if (nil? setter) + (throw-log-or-ignore-missing-setter key clazz) + (apply setter [instance value])))) + instance))) (when-available biginteger From 34ff168d3768f11ef5477c16cd17f4908be75a46 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Sun, 13 Oct 2019 14:48:00 -0500 Subject: [PATCH 027/101] [maven-release-plugin] prepare release java.data-0.1.4 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 21fefda..9c9a5e2 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 0.1.4-SNAPSHOT + 0.1.4 java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - HEAD + java.data-0.1.4 From 897a5c36a068642ef6db51025a7ac5d93c243d99 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Sun, 13 Oct 2019 14:48:00 -0500 Subject: [PATCH 028/101] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9c9a5e2..59b1c50 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 0.1.4 + 0.1.5-SNAPSHOT java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - java.data-0.1.4 + HEAD From aff71e16bb845616e89b454e97a6b68d84b76707 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 20 Dec 2019 10:32:59 -0800 Subject: [PATCH 029/101] Fixes JDATA-15 by adding set-properties --- README.md | 21 +++++--- src/main/clojure/clojure/java/data.clj | 48 ++++++++++++------ src/test/clojure/clojure/java/test_data.clj | 55 +++++++++++++++++---- 3 files changed, 92 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index d2069f8..5aee6b5 100644 --- a/README.md +++ b/README.md @@ -30,16 +30,22 @@ Latest stable release: 0.1.4 ## Example Usage ```clojure -(use 'clojure.java.data) - -(to-java YourJavaClass clojure-property-map) -(from-java javaValue) +(require '[clojure.java.data :as j]) + +;; construct YourJavaClass instance from Clojure data structure +;; (usually a Clojure hash map of properties to set on the instance): +(j/to-java YourJavaClass clojure-property-map) +;; represent a javaValue instance in a Clojure data structure: +(j/from-java javaValue) +;; populate javaValue instance from a Clojure property hash map +;; (calls a setter for each key/value pair in the hash map): +(j/set-properties javaValue clojure-property-map) ``` Representing an instance of `YourJavaClass` in a Clojure data structure ```clojure -(defmethod from-java YourJavaClass [instance] +(defmethod j/from-java YourJavaClass [instance] ; your custom logic for turning this instance into a clojure data structure ) ``` @@ -47,7 +53,7 @@ Representing an instance of `YourJavaClass` in a Clojure data structure Constructing an instance of `YourJavaClass` from a Clojure data structure ```clojure -(defmethod to-java [YourJavaClass clojure.lang.APersistentMap] [clazz props] +(defmethod j/to-java [YourJavaClass clojure.lang.APersistentMap] [clazz props] ; your custom logic for constructing an instance from a property map ) ``` @@ -78,6 +84,9 @@ exception defense | none | none ## Change Log +* Release 0.1.5 in progress + * Add `set-properties` to populate an existing object JDATA-15. + * Release 0.1.4 on 2019-10-13 * Fix Clojure hash map conversion problems JDATA-14 (problems introduced in 0.1.3) diff --git a/src/main/clojure/clojure/java/data.clj b/src/main/clojure/clojure/java/data.clj index 85fe3b2..fc0282b 100644 --- a/src/main/clojure/clojure/java/data.clj +++ b/src/main/clojure/clojure/java/data.clj @@ -1,13 +1,13 @@ -;; Copyright (c) Cosmin Stejerean. All rights reserved. The use and -;; distribution terms for this software are covered by the Eclipse Public -;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can -;; be found in the file epl-v10.html at the root of this distribution. By -;; using this software in any fashion, you are agreeing to be bound by the -;; terms of this license. You must not remove this notice, or any other, -;; from this software. +;; Copyright (c) Cosmin Stejerean, Sean Corfield. All rights reserved. +;; The use and distribution terms for this software are covered by the +;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) +;; which can be found in the file epl-v10.html at the root of this +;; distribution. By using this software in any fashion, you are agreeing to +;; be bound by the terms of this license. You must not remove this notice, +;; or any other, from this software. (ns - ^{:author "Cosmin Stejerean", + ^{:author "Cosmin Stejerean, Sean Corfield", :doc "Support for recursively converting Java beans to Clojure and vice versa."} clojure.java.data (:require [clojure.string :as str] @@ -119,6 +119,20 @@ (throw (IllegalArgumentException. "java.time.Instant requires :nano and :epochSecond"))) (java.time.Instant/ofEpochSecond (:epochSecond props) (:nano props)))) +(defn- set-properties-on + "Given an instance, its class, and a hash map of properties, + call the appropriate setters and return the populated object. + + Used by to-java and set-properties below." + [instance ^Class clazz props] + (let [setter-map (reduce add-setter-fn {} (get-property-descriptors clazz))] + (doseq [[key value] props] + (let [setter (get setter-map (keyword key))] + (if (nil? setter) + (throw-log-or-ignore-missing-setter key clazz) + (apply setter [instance value])))) + instance)) + (defmethod to-java [Object clojure.lang.APersistentMap] [^Class clazz props] "Convert a Clojure map to the specified class using reflection to set the properties. If the class is an interface, we can't create an instance of @@ -140,14 +154,8 @@ (throw (IllegalArgumentException. (str (.getName clazz) " cannot be constructed") - t)))) - setter-map (reduce add-setter-fn {} (get-property-descriptors clazz))] - (doseq [[key value] props] - (let [setter (get setter-map (keyword key))] - (if (nil? setter) - (throw-log-or-ignore-missing-setter key clazz) - (apply setter [instance value])))) - instance))) + t))))] + (set-properties-on instance clazz props)))) (when-available biginteger @@ -157,6 +165,14 @@ biginteger (defmethod to-java [BigInteger Object] [_ value] (bigint value))) +;; set properties on existing objects + +(defn set-properties + "Given an existing Java object and a Clojure map, use reflection to + set the properties." + [instance props] + (set-properties-on instance (class instance) props)) + ;; common from-java definitions (defmethod from-java :default [^Object instance] diff --git a/src/test/clojure/clojure/java/test_data.clj b/src/test/clojure/clojure/java/test_data.clj index 6420e1f..6c07aad 100644 --- a/src/test/clojure/clojure/java/test_data.clj +++ b/src/test/clojure/clojure/java/test_data.clj @@ -1,15 +1,16 @@ -;; Copyright (c) Cosmin Stejerean. All rights reserved. The use and -;; distribution terms for this software are covered by the Eclipse Public -;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can -;; be found in the file epl-v10.html at the root of this distribution. By -;; using this software in any fashion, you are agreeing to be bound by the -;; terms of this license. You must not remove this notice, or any other, -;; from this software. +;; Copyright (c) Cosmin Stejerean, Sean Corfield. All rights reserved. +;; The use and distribution terms for this software are covered by the +;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) +;; which can be found in the file epl-v10.html at the root of this +;; distribution. By using this software in any fashion, you are agreeing to +;; be bound by the terms of this license. You must not remove this notice, +;; or any other, from this software. (ns clojure.java.test-data - (:use clojure.java.data) - (:use [clojure.tools.logging :only (log* info)]) - (:use clojure.test) + (:require [clojure.java.data :refer [from-java set-properties to-java + *to-java-object-missing-setter*]] + [clojure.tools.logging :refer [log* info]] + [clojure.test :refer [deftest is testing]]) (:import (clojure.java.data.test Person Address State Primitive TestBean6 TestBean9))) @@ -147,3 +148,37 @@ (is (= "SQL 2" (get-in ex [:nextException :message]))) (is (= "SQL 3" (get-in ex [:nextException :nextException :message]))) (is (nil? (get-in ex [:nextException :nextException :nextException])))))) + +;; set-properties tests + +(deftest jdata-15 + (testing "flat maps" + (let [address (set-properties (new Address) + {:line1 "123 Main St" + :city "Dallas" + :state "TX" + :zip "75432"}) + person (set-properties (new Person) + {:name "Bob" + :age 30 + :address address})] + (is (= "Bob" (.getName person))) + (is (= 30 (.getAge person))) + (is (= "123 Main St" (.. person getAddress getLine1))) + (is (= "Dallas" (.. person getAddress getCity))) + (is (= State/TX (.. person getAddress getState))) + (is (= "75432" (.. person getAddress getZip))))) + (testing "nested map" + (let [person (set-properties (new Person) + {:name "Bob" + :age 30 + :address {:line1 "123 Main St" + :city "Dallas" + :state "TX" + :zip "75432"}})] + (is (= "Bob" (.getName person))) + (is (= 30 (.getAge person))) + (is (= "123 Main St" (.. person getAddress getLine1))) + (is (= "Dallas" (.. person getAddress getCity))) + (is (= State/TX (.. person getAddress getState))) + (is (= "75432" (.. person getAddress getZip)))))) From 05f2cbcf2c685138cf7ee4be9061dbe023cafd51 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 20 Dec 2019 10:59:23 -0800 Subject: [PATCH 030/101] Code cleanup/whitespace bikeshedding --- src/main/clojure/clojure/java/data.clj | 50 ++++++++++++-------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/src/main/clojure/clojure/java/data.clj b/src/main/clojure/clojure/java/data.clj index fc0282b..a2a3f74 100644 --- a/src/main/clojure/clojure/java/data.clj +++ b/src/main/clojure/clojure/java/data.clj @@ -15,11 +15,11 @@ (set! *warn-on-reflection* true) -(def - ^{:dynamic true, - :doc "Specify the behavior of missing setters in to-java in the - default object case, using one of :ignore, :log, :error"} - *to-java-object-missing-setter* :ignore) +(def ^:dynamic + *to-java-object-missing-setter* + "Specify the behavior of missing setters in to-java in the + default object case, using one of :ignore, :log, :error" + :ignore) (defmulti to-java (fn [destination-type value] [destination-type (class value)])) (defmulti from-java class) @@ -44,7 +44,6 @@ (assoc the-map (keyword name) (make-getter-fn method)) the-map))) - ;; setters (defn- is-setter [^java.lang.reflect.Method method] @@ -54,8 +53,8 @@ (get (.getParameterTypes method) 0)) (defn- make-setter-fn [^java.lang.reflect.Method method] - (fn [instance value] - (.invoke method instance (into-array [(to-java (get-setter-type method) value)])))) + (fn [instance value] + (.invoke method instance (into-array [(to-java (get-setter-type method) value)])))) (defn- add-setter-fn [the-map ^java.beans.PropertyDescriptor prop-descriptor] (let [name (.getName prop-descriptor) @@ -67,7 +66,7 @@ (defn- add-array-methods [^Class acls] (let [cls (.getComponentType acls) to (fn [_ sequence] (into-array cls (map (partial to-java cls) - sequence))) + sequence))) from (fn [obj] (map from-java obj))] (.addMethod ^clojure.lang.MultiFn to-java [acls Iterable] to) (.addMethod ^clojure.lang.MultiFn from-java acls from) @@ -77,16 +76,14 @@ (defmethod to-java :default [^Class cls value] (if (.isArray cls) - ; no method for this array type yet - ((:to (add-array-methods cls)) - cls value) + ;; no method for this array type yet + ((:to (add-array-methods cls)) cls value) value)) (defmethod to-java [Enum String] [^Class enum value] (.invoke (.getDeclaredMethod enum "valueOf" (into-array [String])) nil (into-array [value]))) - (defn- throw-log-or-ignore-missing-setter [key ^Class clazz] (let [message (str "Missing setter for " key " in " (.getCanonicalName clazz))] (cond (= *to-java-object-missing-setter* :error) @@ -95,6 +92,7 @@ (logger/info message)))) ;; feature testing macro, based on suggestion from Chas Emerick: + (defmacro ^{:private true} when-available [sym & body] (try @@ -140,21 +138,21 @@ (if (.isInterface clazz) (if (instance? clazz props) (condp = clazz - ;; make a fresh (mutabl) hash map from the Clojure map - java.util.Map (java.util.HashMap. ^java.util.Map props) - ;; Iterable, Serializable, Runnable, Callable - ;; we should probably figure out actual objects to create... - props) + ;; make a fresh (mutabl) hash map from the Clojure map + java.util.Map (java.util.HashMap. ^java.util.Map props) + ;; Iterable, Serializable, Runnable, Callable + ;; we should probably figure out actual objects to create... + props) (throw (IllegalArgumentException. - (str (.getName clazz) " is an interface " - "and cannot be constructed from " - (str/join ", " (map name (keys props))))))) + (str (.getName clazz) " is an interface " + "and cannot be constructed from " + (str/join ", " (map name (keys props))))))) (let [instance (try (.newInstance clazz) (catch Throwable t (throw (IllegalArgumentException. - (str (.getName clazz) - " cannot be constructed") - t))))] + (str (.getName clazz) + " cannot be constructed") + t))))] (set-properties-on instance clazz props)))) (when-available @@ -179,12 +177,10 @@ "Convert a Java object to a Clojure map" (let [clazz (.getClass instance)] (if (.isArray clazz) - ((:from (add-array-methods clazz)) - instance) + ((:from (add-array-methods clazz)) instance) (let [getter-map (reduce add-getter-fn {} (get-property-descriptors clazz))] (into {} (for [[key getter-fn] (seq getter-map)] [key (getter-fn instance)])))))) - (doseq [clazz [String Character Byte Short Integer Long Float Double BigInteger BigDecimal]] (derive clazz ::do-not-convert)) From 259b7ed9a25de5c03856633296d19deb18ea3e28 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 20 Dec 2019 12:15:41 -0800 Subject: [PATCH 031/101] Fixes JDATA-16 by adding constructor support --- README.md | 10 ++++ src/main/clojure/clojure/java/data.clj | 56 ++++++++++++++++++--- src/test/clojure/clojure/java/test_data.clj | 51 ++++++++++++++++++- 3 files changed, 109 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 5aee6b5..2fff8ec 100644 --- a/README.md +++ b/README.md @@ -35,11 +35,20 @@ Latest stable release: 0.1.4 ;; construct YourJavaClass instance from Clojure data structure ;; (usually a Clojure hash map of properties to set on the instance): (j/to-java YourJavaClass clojure-property-map) + ;; represent a javaValue instance in a Clojure data structure: (j/from-java javaValue) + ;; populate javaValue instance from a Clojure property hash map ;; (calls a setter for each key/value pair in the hash map): (j/set-properties javaValue clojure-property-map) + +;; provide constructor arguments via metadata: +(j/to-java YourJavaClass + (with-meta clojure-property-map + {::j/constructor ["constructor" "arguments"]})) +;; constructor arguments must match the parameter types +;; so you may need type hints and coercions on them ``` Representing an instance of `YourJavaClass` in a Clojure data structure @@ -86,6 +95,7 @@ exception defense | none | none * Release 0.1.5 in progress * Add `set-properties` to populate an existing object JDATA-15. + * Add `:clojure.java.data/constructor` metadata support JDATA-16. * Release 0.1.4 on 2019-10-13 * Fix Clojure hash map conversion problems JDATA-14 (problems introduced in 0.1.3) diff --git a/src/main/clojure/clojure/java/data.clj b/src/main/clojure/clojure/java/data.clj index a2a3f74..1646379 100644 --- a/src/main/clojure/clojure/java/data.clj +++ b/src/main/clojure/clojure/java/data.clj @@ -72,6 +72,44 @@ (.addMethod ^clojure.lang.MultiFn from-java acls from) {:to to :from from})) +;; constructor support + +(defn- find-matching-constructors [^Class clazz args] + (let [n (count args)] + (filter (fn [^java.lang.reflect.Constructor ctr] + (and (= n (.getParameterCount ctr)) + (let [pts (map vector (.getParameterTypes ctr) args)] + (every? (fn [[^Class pt arg]] + ;; watch out for boxed types in Clojure + ;; passed to primitive constructor parameters + (cond (.isPrimitive pt) + (and arg ; cannot pass nil to primitive + (or (instance? Number arg) + (instance? Boolean arg))) + (nil? arg) + true ; null is assignable to any non-primitive + :else + (.isAssignableFrom pt (class arg)))) + pts)))) + (.getConstructors clazz)))) + +(defn- find-constructor ^java.lang.reflect.Constructor [^Class clazz args] + (let [candidates (find-matching-constructors clazz args)] + (condp = (count candidates) + 0 (throw (IllegalArgumentException. + (str (.getName clazz) " has no matching constructor" + " for the given argument list"))) + 1 (first candidates) + (throw (IllegalArgumentException. + (str (.getName clazz) " constructor is ambiguous" + " for the given argument list")))))) + +(comment + (find-constructor String ["arg"]) + (find-constructor String [(.getBytes "arg")]) + (find-constructor String [(.getBytes "arg") (int 0) (int 3)]) + (find-constructor String ["too" "many" "arguments"])) + ;; common to-java definitions (defmethod to-java :default [^Class cls value] @@ -147,7 +185,12 @@ (str (.getName clazz) " is an interface " "and cannot be constructed from " (str/join ", " (map name (keys props))))))) - (let [instance (try (.newInstance clazz) + (let [ctr-args (::constructor (meta props)) + ctr (when ctr-args (find-constructor clazz ctr-args)) + instance (try + (if ctr + (.newInstance ctr (object-array ctr-args)) + (.newInstance clazz)) (catch Throwable t (throw (IllegalArgumentException. (str (.getName clazz) @@ -157,11 +200,11 @@ (when-available biginteger - (defmethod to-java [BigInteger Object] [_ value] (biginteger value))) + (defmethod to-java [java.math.BigInteger Object] [_ value] (biginteger value))) (when-not-available biginteger - (defmethod to-java [BigInteger Object] [_ value] (bigint value))) + (defmethod to-java [java.math.BigInteger Object] [_ value] (bigint value))) ;; set properties on existing objects @@ -181,7 +224,8 @@ (let [getter-map (reduce add-getter-fn {} (get-property-descriptors clazz))] (into {} (for [[key getter-fn] (seq getter-map)] [key (getter-fn instance)])))))) -(doseq [clazz [String Character Byte Short Integer Long Float Double BigInteger BigDecimal]] +(doseq [clazz [String Character Byte Short Integer Long Float Double + java.math.BigInteger java.math.BigDecimal]] (derive clazz ::do-not-convert)) (defmacro ^{:private true} defnumber [box prim prim-getter] @@ -232,8 +276,8 @@ ;; .setYear is unique in having an overload on int and BigInteger ;; whereas the other setters only have an int version so avoiding ;; reflection means special treatment for .setYear - (if (instance? BigInteger y) - (.setYear instance ^BigInteger y) + (if (instance? java.math.BigInteger y) + (.setYear instance ^java.math.BigInteger y) (.setYear instance ^int y)) (doto instance (.setMonth (getu props :month)) diff --git a/src/test/clojure/clojure/java/test_data.clj b/src/test/clojure/clojure/java/test_data.clj index 6c07aad..3d4071f 100644 --- a/src/test/clojure/clojure/java/test_data.clj +++ b/src/test/clojure/clojure/java/test_data.clj @@ -7,8 +7,9 @@ ;; or any other, from this software. (ns clojure.java.test-data - (:require [clojure.java.data :refer [from-java set-properties to-java - *to-java-object-missing-setter*]] + (:require [clojure.java.data :as j + :refer [from-java set-properties to-java + *to-java-object-missing-setter*]] [clojure.tools.logging :refer [log* info]] [clojure.test :refer [deftest is testing]]) (:import (clojure.java.data.test Person Address State Primitive @@ -182,3 +183,49 @@ (is (= "Dallas" (.. person getAddress getCity))) (is (= State/TX (.. person getAddress getState))) (is (= "75432" (.. person getAddress getZip)))))) + +;; constructor tests + +(deftest jdata-16 + (testing "just constructor arguments" + (let [^Address address (to-java Address + (with-meta {} + {::j/constructor ["123 Main St" + "Dallas" + (to-java State "TX") + "75432"]})) + person (to-java Person + (with-meta {} + {::j/constructor ["Bob" (biginteger 30) address]}))] + (is (= "Bob" (.getName person))) + (is (= 30 (.getAge person))) + (is (= "123 Main St" (.. person getAddress getLine1))) + (is (= "Dallas" (.. person getAddress getCity))) + (is (= State/TX (.. person getAddress getState))) + (is (= "75432" (.. person getAddress getZip))))) + (testing "mixed constructor arguments and properties" + (let [person (to-java Person + (with-meta {:address {:line1 "123 Main St" + :city "Dallas" + :state "TX" + :zip "75432"}} + {::j/constructor ["Bob" (biginteger 30) nil]}))] + (is (= "Bob" (.getName person))) + (is (= 30 (.getAge person))) + (is (= "123 Main St" (.. person getAddress getLine1))) + (is (= "Dallas" (.. person getAddress getCity))) + (is (= State/TX (.. person getAddress getState))) + (is (= "75432" (.. person getAddress getZip)))) + (let [person (to-java Person + (with-meta {:address {:line1 "123 Main St" + :city "Dallas" + :state "TX" + :zip "75432"} + :age 30} + {::j/constructor ["Bob" nil nil]}))] + (is (= "Bob" (.getName person))) + (is (= 30 (.getAge person))) + (is (= "123 Main St" (.. person getAddress getLine1))) + (is (= "Dallas" (.. person getAddress getCity))) + (is (= State/TX (.. person getAddress getState))) + (is (= "75432" (.. person getAddress getZip)))))) From 55a82c63b485297d520189ad5341b9d3e911bdb8 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 20 Dec 2019 12:23:07 -0800 Subject: [PATCH 032/101] Prep for 0.1.5 release --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2fff8ec..220a0ba 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ clojure-contrib ## Releases and Dependency Information -Latest stable release: 0.1.4 +Latest stable release: 0.1.5 * [All Released Versions](http://search.maven.org/#search%7Cga%7C1%7Corg.clojure%20java.data) * [Development Snapshot Versions](https://repository.sonatype.org/index.html#nexus-search;gav~org.clojure~java.data~~~) @@ -14,7 +14,7 @@ Latest stable release: 0.1.4 ### Leiningen ```clojure -[org.clojure/java.data "0.1.4"] +[org.clojure/java.data "0.1.5"] ``` ### Maven @@ -23,7 +23,7 @@ Latest stable release: 0.1.4 org.clojure java.data - 0.1.4 + 0.1.5 ``` @@ -93,7 +93,7 @@ exception defense | none | none ## Change Log -* Release 0.1.5 in progress +* Release 0.1.5 on 2019-12-20 * Add `set-properties` to populate an existing object JDATA-15. * Add `:clojure.java.data/constructor` metadata support JDATA-16. From 4cc2b2cc4a5810b5296d17b7246c338481fad0ab Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Fri, 20 Dec 2019 14:26:10 -0600 Subject: [PATCH 033/101] [maven-release-plugin] prepare release java.data-0.1.5 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 59b1c50..353ac0a 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 0.1.5-SNAPSHOT + 0.1.5 java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - HEAD + java.data-0.1.5 From 95db1bd569b3be0367ff91685033d20bd6eef823 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Fri, 20 Dec 2019 14:26:10 -0600 Subject: [PATCH 034/101] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 353ac0a..332f0b2 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 0.1.5 + 0.1.6-SNAPSHOT java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - java.data-0.1.5 + HEAD From 20d8562bf451f41bf58ac0b38401648ba21232a3 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Thu, 2 Jan 2020 18:15:38 -0800 Subject: [PATCH 035/101] First cut of JDATA-18 Needs a test suite! --- .../clojure/clojure/java/data/builder.clj | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 src/main/clojure/clojure/java/data/builder.clj diff --git a/src/main/clojure/clojure/java/data/builder.clj b/src/main/clojure/clojure/java/data/builder.clj new file mode 100644 index 0000000..b423a9e --- /dev/null +++ b/src/main/clojure/clojure/java/data/builder.clj @@ -0,0 +1,154 @@ +;; Copyright (c) Sean Corfield. All rights reserved. +;; The use and distribution terms for this software are covered by the +;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) +;; which can be found in the file epl-v10.html at the root of this +;; distribution. By using this software in any fashion, you are agreeing to +;; be bound by the terms of this license. You must not remove this notice, +;; or any other, from this software. + +(ns + ^{:author "Sean Corfield", + :doc "A variant of clojure.java.data/to-java that uses a Builder class + to build the requested class from a hash map of properties."} + clojure.java.data.builder + (:require [clojure.java.data :as j])) + +(set! *warn-on-reflection* true) + +(defn- get-builder-class [^Class clazz] + (try + (resolve (symbol (str (.getName clazz) "$Builder"))) + (catch Throwable _))) + +(defn- get-builder ^java.lang.reflect.Method [^Class clazz methods opts] + (let [build-name (:build-fn opts) + candidates + (filter (fn [^java.lang.reflect.Method m] + (and (= 0 (alength ^"[Ljava.lang.Class;" (.getParameterTypes m))) + (= clazz (.getReturnType m)) + (or (nil? build-name) + (= build-name (.getName m))))) + methods)] + (case (count candidates) + 0 (throw (IllegalArgumentException. + (str "Cannot find builder method that returns " + (.getName clazz)))) + 1 (first candidates) + (let [builds (filter (fn [^java.lang.reflect.Method m] + (= "build" (.getName m))) + candidates)] + (case (count builds) + 0 (throw (IllegalArgumentException. + (str "Cannot find 'build' method that returns " + (.getName clazz)))) + (first builds)))))) + +(defn- find-setters [^Class builder methods opts] + (let [candidates + (filter (fn [^java.lang.reflect.Method m] + (and (= 1 (alength ^"[Ljava.lang.Class;" (.getParameterTypes m))) + (= builder (.getReturnType m)) + (or (not (re-find #"^set[A-Z]" (.getName m))) + (not (:ignore-setters? opts))))) + methods)] + (reduce (fn [setter-map ^java.lang.reflect.Method m] + (let [prop (keyword + (if (re-find #"^set[A-Z]" (.getName m)) + (let [^String n (subs (.getName m) 3)] + (str (Character/toLowerCase (.charAt n 0)) (subs n 1))) + (.getName m)))] + (if (contains? setter-map prop) + (throw (IllegalArgumentException. + (str "Duplicate setter found for " prop + " in " (.getName builder) " class"))) + (assoc setter-map prop (#'j/make-setter-fn m))))) + {} + candidates))) + +(defn- build-on [instance setters ^Class clazz props] + (reduce-kv (fn [builder k v] + (if-let [setter (get setters (keyword k))] + (apply setter [instance v]) + (#'j/throw-log-or-ignore-missing-setter k clazz))) + instance + props)) + +(comment + ;; given a class, see if it has a nested Builder class + ;; otherwise we'll need to be told the builder class + ;; and possibly how to create it + (get-builder-class java.util.Locale) + + ;; from the builder class, look for arity-0 methods then return + ;; the original class -- if there's only one, use it, if there + ;; are multiple and one is called "build", use it, else error + (get-builder java.util.Locale (.getMethods java.util.Locale$Builder) {}) + + ;; setters on a builder will have single arguments and will + ;; return the builder class, and will either be: + ;; * B propertyName( T ) + ;; * B setPropertyName( T ) + ;; treat both as setters; thrown exception if they clash + ;; (maybe an option to ignore setXyz( T ) methods?) + (find-setters java.util.Locale$Builder (.getMethods java.util.Locale$Builder) {}) + + ;; general pattern will be to: + ;; * get the builder class somehow + ;; * get its public methods + ;; * identify its builder method (or be told it) + ;; * identity its setters by name + ;; * construct the builder (or be given an instance?) + ;; * reduce over the input hash map, + ;; * -- if setter matches key, + ;; * -- then invoke, use result (use j/to-java to build value here?) + ;; * -- else either log, ignore, or throw (per j/*to-java-object-missing-setter*) + ;; * invoke builder on result, return that + (let [clazz java.util.Locale + props {:language "fr"} + opts {} + ^Class builder (get-builder-class clazz)] + (.invoke (get-builder clazz (.getMethods builder) opts) + (build-on (j/to-java builder ^clojure.lang.APersistentMap {}) + (find-setters builder (.getMethods builder) opts) + builder + props) + nil))) + +(defn to-java + "Given a class and a hash map of properties, figure out the Builder class, + figure out the setters for the Builder, construct an instance of it and + produce an instance of the original class. + + The following options may be provided: + * :builder-class -- the class that should be used for the builder process; + by default we'll assume an inner class of clazz called 'Builder', + * :builder-props -- properties used to construct and initialize an instance + of the builder class; defaults to an empty hash map; may have + :clojure.java.data/constructor as metadata to provide constructor + arguments for the builder instance, + * :build-fn -- the name of the method in the Builder class to use to + complete the builder process and return the desired class; + by default we'll try to deduce it, preferring 'build' if we find + multiple candidates, + * :ignore-setters? -- a flag to indicate that methods on the builder + class that begin with 'set' should be ignored, which may be + necessary to avoid ambiguous methods that look like builder properties; + by default 'setFooBar` will be treated as a builder property 'fooBar' + if it accepts a single argument and returns a builder instance." + ([clazz props] (to-java clazz props {})) + ([^Class clazz props opts] + (if-let [^Class builder (or (:builder-class opts) + (get-builder-class clazz))] + (.invoke (get-builder clazz (.getMethods builder) opts) + (build-on (j/to-java builder (get opts :builder-props {})) + (find-setters builder (.getMethods builder) opts) + builder + props) + nil)))) + +(comment + (to-java java.util.Locale {:language "fr" :region "EG"} + ;; these options are all defaults + {:builder-class java.util.Locale$Builder + :builder-props {} + :build-fn "build"})) From 77460e17ba41f3e47837607e49799c88367b86f0 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Thu, 2 Jan 2020 21:19:44 -0800 Subject: [PATCH 036/101] Support withProperty in builders --- src/main/clojure/clojure/java/data/builder.clj | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/clojure/clojure/java/data/builder.clj b/src/main/clojure/clojure/java/data/builder.clj index b423a9e..e23caf0 100644 --- a/src/main/clojure/clojure/java/data/builder.clj +++ b/src/main/clojure/clojure/java/data/builder.clj @@ -53,10 +53,14 @@ methods)] (reduce (fn [setter-map ^java.lang.reflect.Method m] (let [prop (keyword - (if (re-find #"^set[A-Z]" (.getName m)) - (let [^String n (subs (.getName m) 3)] - (str (Character/toLowerCase (.charAt n 0)) (subs n 1))) - (.getName m)))] + (cond (re-find #"^set[A-Z]" (.getName m)) + (let [^String n (subs (.getName m) 3)] + (str (Character/toLowerCase (.charAt n 0)) (subs n 1))) + (re-find #"^with[A-Z]" (.getName m)) + (let [^String n (subs (.getName m) 4)] + (str (Character/toLowerCase (.charAt n 0)) (subs n 1))) + :else + (.getName m)))] (if (contains? setter-map prop) (throw (IllegalArgumentException. (str "Duplicate setter found for " prop From 37215cc4f70fe8ab203462d517daefe6639e529f Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Thu, 2 Jan 2020 21:51:06 -0800 Subject: [PATCH 037/101] Throw if we can't deduce the builder class --- src/main/clojure/clojure/java/data/builder.clj | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/clojure/clojure/java/data/builder.clj b/src/main/clojure/clojure/java/data/builder.clj index e23caf0..97d350a 100644 --- a/src/main/clojure/clojure/java/data/builder.clj +++ b/src/main/clojure/clojure/java/data/builder.clj @@ -148,7 +148,9 @@ (find-setters builder (.getMethods builder) opts) builder props) - nil)))) + nil) + (throw (IllegalArgumentException. + (str "Unable to deduce a builder class for " (.getName clazz))))))) (comment (to-java java.util.Locale {:language "fr" :region "EG"} From 36a3f1d86cab11ff5a78cef0a4eff9eea1cb42ce Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Thu, 2 Jan 2020 22:26:39 -0800 Subject: [PATCH 038/101] Support additional builder class/instance combinations --- .../clojure/clojure/java/data/builder.clj | 39 ++++++++++++++----- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/src/main/clojure/clojure/java/data/builder.clj b/src/main/clojure/clojure/java/data/builder.clj index 97d350a..ba3158f 100644 --- a/src/main/clojure/clojure/java/data/builder.clj +++ b/src/main/clojure/clojure/java/data/builder.clj @@ -121,7 +121,17 @@ (defn to-java "Given a class and a hash map of properties, figure out the Builder class, figure out the setters for the Builder, construct an instance of it and - produce an instance of the original class. + produce an instance of the original class. A hash map of options may also + be provided. + + Alternatively, given a class, a builder instance, a hash map of properties, + and a hash map of options, figure out the setters for the builder class, + and use the builder instance to produce an instance of the original class. + + Finally, given a class, a builder class, a builder instance (possibly of a + different class), a hash map of properties, and a hash map of options, + figure out the setters for the builder class, and use the builder instance + to produce an instance of the original class. The following options may be provided: * :builder-class -- the class that should be used for the builder process; @@ -141,19 +151,28 @@ if it accepts a single argument and returns a builder instance." ([clazz props] (to-java clazz props {})) ([^Class clazz props opts] - (if-let [^Class builder (or (:builder-class opts) - (get-builder-class clazz))] - (.invoke (get-builder clazz (.getMethods builder) opts) - (build-on (j/to-java builder (get opts :builder-props {})) - (find-setters builder (.getMethods builder) opts) - builder - props) - nil) + (if-let [builder (or (:builder-class opts) (get-builder-class clazz))] + (to-java clazz builder (j/to-java builder (get opts :builder-props {})) props opts) (throw (IllegalArgumentException. - (str "Unable to deduce a builder class for " (.getName clazz))))))) + (str "Unable to deduce a builder class for " (.getName clazz)))))) + ([clazz instance props opts] + (let [builder (or (:builder-class opts) (class instance))] + (to-java clazz builder instance props opts))) + ([^Class clazz ^Class builder instance props opts] + (.invoke (get-builder clazz (.getMethods builder) opts) + (build-on instance + (find-setters builder (.getMethods builder) opts) + builder + props) + nil))) (comment (to-java java.util.Locale {:language "fr" :region "EG"} + ;; these options are all defaults + {:builder-class java.util.Locale$Builder + :builder-props {} + :build-fn "build"}) + (to-java java.util.Locale (java.util.Locale$Builder.) {:language "fr" :region "EG"} ;; these options are all defaults {:builder-class java.util.Locale$Builder :builder-props {} From 190d6153a13ae156d8adb172fb82bfda1077c3eb Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Thu, 2 Jan 2020 23:14:02 -0800 Subject: [PATCH 039/101] Prep for 0.2.0 release Document new namespace/function --- README.md | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 220a0ba..8de0ac9 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ clojure-contrib ## Releases and Dependency Information -Latest stable release: 0.1.5 +Latest stable release: 0.2.0 * [All Released Versions](http://search.maven.org/#search%7Cga%7C1%7Corg.clojure%20java.data) * [Development Snapshot Versions](https://repository.sonatype.org/index.html#nexus-search;gav~org.clojure~java.data~~~) @@ -14,7 +14,7 @@ Latest stable release: 0.1.5 ### Leiningen ```clojure -[org.clojure/java.data "0.1.5"] +[org.clojure/java.data "0.2.0"] ``` ### Maven @@ -23,7 +23,7 @@ Latest stable release: 0.1.5 org.clojure java.data - 0.1.5 + 0.2.0 ``` @@ -67,6 +67,55 @@ Constructing an instance of `YourJavaClass` from a Clojure data structure ) ``` +### Usage with Builder Classes + +As of 0.2.0, `clojure.java.data` adds a new namespace and a new `to-java` +function that supports the Builder Pattern. Instead of just creating an instance +of the specified class and then setting properties on it, this variant works +with an associated "builder" class (or instance), setting properties on it, +and then producing an instance of the specified class from it. + +In Java, that typically looks like: + +```java +MyClass foo = new MyClass.Builder() + .bar( 42 ) + .quux( "stuff" ) + .build(); +``` + +That becomes: + +```clojure +(require '[clojure.java.data.builder :as builder]) + +(def foo (builder/to-java MyClass {:bar 42 :quux "stuff"})) +``` + +By default, this assumes `MyClass` has a nested class called `Builder`, and the +property methods could be `.bar`, `.setBar`, or `.withBar`, and then a `.build` +method that produces the `MyClass` object. + +You can also specify an options hash map containing any of the following: + +* `:builder-class` -- the class that should be used for the builder process; by default it will assume an inner class of `clazz` called `Builder`, +* `:builder-props` -- properties used to construct and initialize an instance of the builder class; defaults to an empty hash map; may have `:clojure.java.data/constructor` as metadata to provide constructor arguments for the builder instance, +* `:build-fn` -- the name of the method in the `Builder` class to use to complete the builder process and return the desired class; by default it will try to deduce it, preferring `build` if we find multiple candidates, +* `:ignore-setters?` -- a flag to indicate that methods on the builder class that begin with `set` should be ignored, which may be necessary to avoid ambiguous methods that look like builder properties; by default `setFooBar` and `withQuuxIt` will be treated as builder properties `fooBar` and `quuxIt` if they accept a single argument and return a builder instance. + +Additional arities allow you to specify a builder instance, for cases where the +builder is not simply constructed from a (nested) class, and both a builder class +and a builder instance for more complex cases: + +```clojure +;; requires the options hash map, even if it is empty: +(builder/to-java MyClass (MyClass/builder) {:bar 42 :quux "stuff"} {}) + +;; for cases where the type of the builder instance differs from the actual +;; builder class that should be used for property method return types: +(builder/to-java MyClass MyClassBuilder (MyClass/builder) {:bar 42 :quux "stuff"} {}) +``` + ## Feature comparison to `clojure.core/bean` Clojure core provides a `bean` function which has some overlap with java.data. Below is a more detailed comparison: @@ -93,6 +142,9 @@ exception defense | none | none ## Change Log +* Release 0.2.0 on 2020-01-02 + * Add `clojure.java.data.builder/to-java` to construct Java objects from builders using hash maps of properties JDATA-18. + * Release 0.1.5 on 2019-12-20 * Add `set-properties` to populate an existing object JDATA-15. * Add `:clojure.java.data/constructor` metadata support JDATA-16. From 57a231f97aed1584eb03a61d526b9da33870367b Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Thu, 2 Jan 2020 23:15:03 -0800 Subject: [PATCH 040/101] Minor typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8de0ac9..3cc9401 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ Constructing an instance of `YourJavaClass` from a Clojure data structure ### Usage with Builder Classes -As of 0.2.0, `clojure.java.data` adds a new namespace and a new `to-java` +As of 0.2.0, `java.data` adds a new namespace and a new `to-java` function that supports the Builder Pattern. Instead of just creating an instance of the specified class and then setting properties on it, this variant works with an associated "builder" class (or instance), setting properties on it, From a5ea1f4651d31155b1d9f4319b6f19d84eff17e6 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Fri, 3 Jan 2020 01:16:44 -0600 Subject: [PATCH 041/101] [maven-release-plugin] prepare release java.data-0.2.0 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 332f0b2..4077c0e 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 0.1.6-SNAPSHOT + 0.2.0 java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - HEAD + java.data-0.2.0 From a31f533e3ef32057c077fbaad025faf02baf3252 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Fri, 3 Jan 2020 01:16:44 -0600 Subject: [PATCH 042/101] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 4077c0e..fa691c2 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 0.2.0 + 0.2.1-SNAPSHOT java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - java.data-0.2.0 + HEAD From eff36583fca2d862f3d67c7378bdb2cc3b104751 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Tue, 18 Feb 2020 21:26:23 -0800 Subject: [PATCH 043/101] Update parent pom etc --- deps.edn | 2 +- pom.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/deps.edn b/deps.edn index 82323c5..697f601 100644 --- a/deps.edn +++ b/deps.edn @@ -1,3 +1,3 @@ {:paths ["src/main/clojure"] :deps - {org.clojure/tools.logging {:mvn/version "0.2.3"}}} + {org.clojure/tools.logging {:mvn/version "0.6.0"}}} diff --git a/pom.xml b/pom.xml index fa691c2..917e398 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ org.clojure pom.contrib - 0.2.2 + 1.0.0 @@ -34,7 +34,7 @@ org.clojure tools.logging - 0.2.3 + 0.6.0 From 995c4b906c48b2ae96f4af660956cf723dccf4f9 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Tue, 18 Feb 2020 22:17:58 -0800 Subject: [PATCH 044/101] Fixes JDATA-20 by providing some basic builder tests --- .../clojure/clojure/java/data/builder.clj | 3 ++ .../clojure/java/data/builder_test.clj | 41 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 src/test/clojure/clojure/java/data/builder_test.clj diff --git a/src/main/clojure/clojure/java/data/builder.clj b/src/main/clojure/clojure/java/data/builder.clj index ba3158f..7ce4892 100644 --- a/src/main/clojure/clojure/java/data/builder.clj +++ b/src/main/clojure/clojure/java/data/builder.clj @@ -172,6 +172,9 @@ {:builder-class java.util.Locale$Builder :builder-props {} :build-fn "build"}) + (to-java java.util.Locale (java.util.Locale$Builder.) {:language "fr" :region "EG"} + ;; these options are all defaults + {#_#_:builder-class java.util.Locale$Builder}) (to-java java.util.Locale (java.util.Locale$Builder.) {:language "fr" :region "EG"} ;; these options are all defaults {:builder-class java.util.Locale$Builder diff --git a/src/test/clojure/clojure/java/data/builder_test.clj b/src/test/clojure/clojure/java/data/builder_test.clj new file mode 100644 index 0000000..eedb8a8 --- /dev/null +++ b/src/test/clojure/clojure/java/data/builder_test.clj @@ -0,0 +1,41 @@ +;; Copyright (c) Sean Corfield. All rights reserved. +;; The use and distribution terms for this software are covered by the +;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) +;; which can be found in the file epl-v10.html at the root of this +;; distribution. By using this software in any fashion, you are agreeing to +;; be bound by the terms of this license. You must not remove this notice, +;; or any other, from this software. + +(ns + ^{:author "Sean Corfield", + :doc "Tests for the builder aspects of java.data."} + clojure.java.data.builder-test + (:require [clojure.java.data.builder :as b] + [clojure.test :refer [deftest is]])) + +(deftest locale-builder-tests + (let [l (b/to-java java.util.Locale + {:language "fr" :region "FR"})] + (is (= "fr" (.getLanguage l))) + (is (= "FR" (.getCountry l)))) + (let [l (b/to-java java.util.Locale + {:language "fr" :region "FR"} + {:builder-class java.util.Locale$Builder + :builder-props {} + :build-fn "build"})] + (is (= "fr" (.getLanguage l))) + (is (= "FR" (.getCountry l)))) + (let [l (b/to-java java.util.Locale + (java.util.Locale$Builder.) + {:language "fr" :region "FR"} + {})] + (is (= "fr" (.getLanguage l))) + (is (= "FR" (.getCountry l)))) + (let [l (b/to-java java.util.Locale + (java.util.Locale$Builder.) + {:language "fr" :region "FR"} + {:builder-class java.util.Locale$Builder + :builder-props {} + :build-fn "build"})] + (is (= "fr" (.getLanguage l))) + (is (= "FR" (.getCountry l))))) From 15ea56fdf40e9ae072ba3fb7e746b65a0a7a51ac Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Tue, 18 Feb 2020 22:25:51 -0800 Subject: [PATCH 045/101] Prep for first 1.0.N release --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3cc9401..002dbfc 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,9 @@ clojure-contrib ## Releases and Dependency Information -Latest stable release: 0.2.0 +This project follows the version scheme MAJOR.MINOR.COMMITS where MAJOR and MINOR provide some relative indication of the size of the change, but do not follow semantic versioning. In general, all changes endeavor to be non-breaking (by moving to new names rather than by breaking existing names). COMMITS is an ever-increasing counter of commits since the beginning of this repository. + +Latest stable release: 1.0.N * [All Released Versions](http://search.maven.org/#search%7Cga%7C1%7Corg.clojure%20java.data) * [Development Snapshot Versions](https://repository.sonatype.org/index.html#nexus-search;gav~org.clojure~java.data~~~) @@ -14,7 +16,7 @@ Latest stable release: 0.2.0 ### Leiningen ```clojure -[org.clojure/java.data "0.2.0"] +[org.clojure/java.data "1.0.N"] ``` ### Maven @@ -23,7 +25,7 @@ Latest stable release: 0.2.0 org.clojure java.data - 0.2.0 + 1.0.N ``` @@ -142,6 +144,11 @@ exception defense | none | none ## Change Log +* Release 1.0.N on 2020-02-18 + * Switch to 1.0.x versioning. + * Bump `org.clojure/tools.logging` to `0.6.0`. + * Add basic tests for the builder [JDATA-20](https://clojure.atlassian.net/browse/JDATA-20). + * Release 0.2.0 on 2020-01-02 * Add `clojure.java.data.builder/to-java` to construct Java objects from builders using hash maps of properties JDATA-18. From 9d41e2ad665f517de304b6aa900bea3ac353443a Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Tue, 18 Feb 2020 22:29:11 -0800 Subject: [PATCH 046/101] Prep for 1.0.64 release --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 002dbfc..495252b 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ clojure-contrib This project follows the version scheme MAJOR.MINOR.COMMITS where MAJOR and MINOR provide some relative indication of the size of the change, but do not follow semantic versioning. In general, all changes endeavor to be non-breaking (by moving to new names rather than by breaking existing names). COMMITS is an ever-increasing counter of commits since the beginning of this repository. -Latest stable release: 1.0.N +Latest stable release: 1.0.64 * [All Released Versions](http://search.maven.org/#search%7Cga%7C1%7Corg.clojure%20java.data) * [Development Snapshot Versions](https://repository.sonatype.org/index.html#nexus-search;gav~org.clojure~java.data~~~) @@ -16,7 +16,7 @@ Latest stable release: 1.0.N ### Leiningen ```clojure -[org.clojure/java.data "1.0.N"] +[org.clojure/java.data "1.0.64"] ``` ### Maven @@ -25,7 +25,7 @@ Latest stable release: 1.0.N org.clojure java.data - 1.0.N + 1.0.64 ``` @@ -144,7 +144,7 @@ exception defense | none | none ## Change Log -* Release 1.0.N on 2020-02-18 +* Release 1.0.64 on 2020-02-18 * Switch to 1.0.x versioning. * Bump `org.clojure/tools.logging` to `0.6.0`. * Add basic tests for the builder [JDATA-20](https://clojure.atlassian.net/browse/JDATA-20). From 4a19ad6ee042d3974727f11f38189cbf971cad95 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Wed, 19 Feb 2020 00:31:52 -0600 Subject: [PATCH 047/101] [maven-release-plugin] prepare release java.data-1.0.64 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 917e398..f5ec177 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 0.2.1-SNAPSHOT + 1.0.64 java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - HEAD + java.data-1.0.64 From 3c8e271d07331db49466edbfd4059a4c2a871c18 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Wed, 19 Feb 2020 00:31:52 -0600 Subject: [PATCH 048/101] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index f5ec177..19ed2d9 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 1.0.64 + 1.0.65-SNAPSHOT java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - java.data-1.0.64 + HEAD From c7a57a79f83dbb9a5ff49c85bf425e126ecc3ffd Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Fri, 28 Feb 2020 08:43:55 -0600 Subject: [PATCH 049/101] update tools.logging dep --- deps.edn | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deps.edn b/deps.edn index 697f601..7b6eb00 100644 --- a/deps.edn +++ b/deps.edn @@ -1,3 +1,3 @@ {:paths ["src/main/clojure"] :deps - {org.clojure/tools.logging {:mvn/version "0.6.0"}}} + {org.clojure/tools.logging {:mvn/version "1.0.0"}}} diff --git a/pom.xml b/pom.xml index 19ed2d9..431e0cd 100644 --- a/pom.xml +++ b/pom.xml @@ -34,7 +34,7 @@ org.clojure tools.logging - 0.6.0 + 1.0.0 From 17f43ef837001c6a83b1f50de15c83e2be1c977f Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 20 Mar 2020 12:49:24 -0700 Subject: [PATCH 050/101] Improve property/setter documentation --- README.md | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 495252b..174f90f 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,18 @@ Latest stable release: 1.0.64 ;; (usually a Clojure hash map of properties to set on the instance): (j/to-java YourJavaClass clojure-property-map) +;; the 0-arity constructor is called to construct the instance +;; and then the properties are added by calling setters + +;; note that keys in the property map must follow the :camelCase +;; naming of the Java fields to which they correspond, so that +;; the appropriate setter methods can be invoked, e.g., +(j/to-java SomeJavaClass {:stuff 42 :moreStuff "13"}) +;; this is equivalent to: +(let [obj (SomeJavaClass.)] + (.setStuff obj 42) + (.setMoreStuff obj "13")) + ;; represent a javaValue instance in a Clojure data structure: (j/from-java javaValue) @@ -81,7 +93,7 @@ In Java, that typically looks like: ```java MyClass foo = new MyClass.Builder() - .bar( 42 ) + .fooBar( 42 ) .quux( "stuff" ) .build(); ``` @@ -91,12 +103,13 @@ That becomes: ```clojure (require '[clojure.java.data.builder :as builder]) -(def foo (builder/to-java MyClass {:bar 42 :quux "stuff"})) +(def foo (builder/to-java MyClass {:fooBar 42 :quux "stuff"})) ``` By default, this assumes `MyClass` has a nested class called `Builder`, and the -property methods could be `.bar`, `.setBar`, or `.withBar`, and then a `.build` -method that produces the `MyClass` object. +property methods could be `.fooBar`, `.setFooBar`, or `.withFooBar` (and +`.quux`, `.setQuux`, or `.withQuux`), and then a `.build` method +that produces the `MyClass` object. You can also specify an options hash map containing any of the following: @@ -144,6 +157,10 @@ exception defense | none | none ## Change Log +* Release 1.0.next in progress + * Bump `org.clojure/tools.logging` to `1.0.0`. + * Improve documentation around property naming and how it corresponds to setter function names. + * Release 1.0.64 on 2020-02-18 * Switch to 1.0.x versioning. * Bump `org.clojure/tools.logging` to `0.6.0`. From d1b183884a8fe575065cd5b682652d8c4da47ff7 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Mon, 27 Apr 2020 17:56:04 -0700 Subject: [PATCH 051/101] Split changes out; bump tools.logging to 1.1.0 --- CHANGELOG.md | 33 +++++++++++++++++++++++++++++++++ README.md | 33 --------------------------------- deps.edn | 2 +- pom.xml | 2 +- 4 files changed, 35 insertions(+), 35 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..7ae8a21 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,33 @@ +## Change Log + +* Release 1.0.next in progress + * Bump `org.clojure/tools.logging` to `1.1.0`. + * Move change log to a separate file. + * Improve documentation around property naming and how it corresponds to setter function names. + +* Release 1.0.64 on 2020-02-18 + * Switch to 1.0.x versioning. + * Bump `org.clojure/tools.logging` to `0.6.0`. + * Add basic tests for the builder [JDATA-20](https://clojure.atlassian.net/browse/JDATA-20). + +* Release 0.2.0 on 2020-01-02 + * Add `clojure.java.data.builder/to-java` to construct Java objects from builders using hash maps of properties JDATA-18. + +* Release 0.1.5 on 2019-12-20 + * Add `set-properties` to populate an existing object JDATA-15. + * Add `:clojure.java.data/constructor` metadata support JDATA-16. + +* Release 0.1.4 on 2019-10-13 + * Fix Clojure hash map conversion problems JDATA-14 (problems introduced in 0.1.3) + +* Release 0.1.3 on 2019-10-13 + * Fix `java.util.Map`/Clojure hash map setter handling JDATA-6. + * Fix `Boolean` conversion JDATA-10. + * Fix `SQLException` handling JDATA-12. + +* Release 0.1.2 on 2019-10-12 + * Fix reflection warnings JDATA-2 and JDATA-13. + +* Release 0.1.1 on 2012-04-29 + * Initial release. + * Clojure 1.2 compatibility. diff --git a/README.md b/README.md index 174f90f..c6aea9c 100644 --- a/README.md +++ b/README.md @@ -155,39 +155,6 @@ exception defense | none | none * [Compatibility Test Matrix](http://build.clojure.org/job/java.data-test-matrix/) -## Change Log - -* Release 1.0.next in progress - * Bump `org.clojure/tools.logging` to `1.0.0`. - * Improve documentation around property naming and how it corresponds to setter function names. - -* Release 1.0.64 on 2020-02-18 - * Switch to 1.0.x versioning. - * Bump `org.clojure/tools.logging` to `0.6.0`. - * Add basic tests for the builder [JDATA-20](https://clojure.atlassian.net/browse/JDATA-20). - -* Release 0.2.0 on 2020-01-02 - * Add `clojure.java.data.builder/to-java` to construct Java objects from builders using hash maps of properties JDATA-18. - -* Release 0.1.5 on 2019-12-20 - * Add `set-properties` to populate an existing object JDATA-15. - * Add `:clojure.java.data/constructor` metadata support JDATA-16. - -* Release 0.1.4 on 2019-10-13 - * Fix Clojure hash map conversion problems JDATA-14 (problems introduced in 0.1.3) - -* Release 0.1.3 on 2019-10-13 - * Fix `java.util.Map`/Clojure hash map setter handling JDATA-6. - * Fix `Boolean` conversion JDATA-10. - * Fix `SQLException` handling JDATA-12. - -* Release 0.1.2 on 2019-10-12 - * Fix reflection warnings JDATA-2 and JDATA-13. - -* Release 0.1.1 on 2012-04-29 - * Initial release. - * Clojure 1.2 compatibility. - ## Copyright and License Copyright (c) Rich Hickey and contributors. All rights reserved. diff --git a/deps.edn b/deps.edn index 7b6eb00..2472694 100644 --- a/deps.edn +++ b/deps.edn @@ -1,3 +1,3 @@ {:paths ["src/main/clojure"] :deps - {org.clojure/tools.logging {:mvn/version "1.0.0"}}} + {org.clojure/tools.logging {:mvn/version "1.1.0"}}} diff --git a/pom.xml b/pom.xml index 431e0cd..1ba38d3 100644 --- a/pom.xml +++ b/pom.xml @@ -34,7 +34,7 @@ org.clojure tools.logging - 1.0.0 + 1.1.0 From 9f803cbe46f539a35206b4c38dd7cfb276b6e62d Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sun, 31 May 2020 14:12:15 -0700 Subject: [PATCH 052/101] Add from-java-shallow conversion --- CHANGELOG.md | 1 + src/main/clojure/clojure/java/data.clj | 100 +++++++++++++++++++++---- 2 files changed, 85 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ae8a21..6e31c45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## Change Log * Release 1.0.next in progress + * Add `from-java-shallow` to provide functionality similar to `clojure.core/bean` (a shallow conversion) but with options to control behavior (so "dangerous" methods that appear as getters can be omitted). * Bump `org.clojure/tools.logging` to `1.1.0`. * Move change log to a separate file. * Improve documentation around property naming and how it corresponds to setter function names. diff --git a/src/main/clojure/clojure/java/data.clj b/src/main/clojure/clojure/java/data.clj index 1646379..3ebe52e 100644 --- a/src/main/clojure/clojure/java/data.clj +++ b/src/main/clojure/clojure/java/data.clj @@ -21,12 +21,39 @@ default object case, using one of :ignore, :log, :error" :ignore) -(defmulti to-java (fn [destination-type value] [destination-type (class value)])) -(defmulti from-java class) +(defmulti to-java + "Convert Clojure data to an instance of the specified Java class. + Several basic types have obvious conversions, but for a hash map + reflection is used to set the properties. If the class is an interface, we + can't create an instance of it, unless the Clojure map already implements it. + + When java.time.Instant is available (Java 8+), we can convert a hash map + containing :nano and :epochSecond to Instant, as this is the reverse of + Instant->map. + + A XMLGregorianCalendar object can be constructed from the following keys + :year, :month, :day, :hour, :minute, :second, and :timezone." + (fn [destination-type value] [destination-type (class value)])) +(defmulti from-java + "Convert a Java object to a Clojure map." + class) +(defmulti from-java-shallow + "Convert a Java object to a Clojure map (but do not convert deeply). + + The second argument is a hash map that offers some control over the + conversion: + * :add-class -- if true, add :class with the actual class of the object + being converted -- this mimics clojure.core/bean. + * :omit -- a set of properties (keywords) to omit from the conversion + so that unsafe methods are not called." + (fn [obj _] (class obj))) (defn- get-property-descriptors [clazz] (.getPropertyDescriptors (java.beans.Introspector/getBeanInfo clazz))) +(comment + (mapv bean (.getPropertyDescriptors (java.beans.Introspector/getBeanInfo java.sql.Statement)))) + ;; getters (defn- is-getter [^java.lang.reflect.Method method] @@ -37,6 +64,10 @@ (fn [instance] (from-java (.invoke method instance nil)))) +(defn- make-shallow-getter-fn [^java.lang.reflect.Method method] + (fn [instance] + (.invoke method instance nil))) + (defn- add-getter-fn [the-map ^java.beans.PropertyDescriptor prop-descriptor] (let [name (.getName prop-descriptor) method (.getReadMethod prop-descriptor)] @@ -44,6 +75,13 @@ (assoc the-map (keyword name) (make-getter-fn method)) the-map))) +(defn- add-shallow-getter-fn [the-map ^java.beans.PropertyDescriptor prop-descriptor] + (let [name (.getName prop-descriptor) + method (.getReadMethod prop-descriptor)] + (if (and (is-getter method) (not (= "class" name))) + (assoc the-map (keyword name) (make-shallow-getter-fn method)) + the-map))) + ;; setters (defn- is-setter [^java.lang.reflect.Method method] @@ -67,10 +105,12 @@ (let [cls (.getComponentType acls) to (fn [_ sequence] (into-array cls (map (partial to-java cls) sequence))) - from (fn [obj] (map from-java obj))] + from (fn [obj] (map from-java obj)) + from-shallow (fn [obj opts] (map from-java-shallow obj opts))] (.addMethod ^clojure.lang.MultiFn to-java [acls Iterable] to) (.addMethod ^clojure.lang.MultiFn from-java acls from) - {:to to :from from})) + (.addMethod ^clojure.lang.MultiFn from-java-shallow acls from-shallow) + {:to to :from from :from-shallow from-shallow})) ;; constructor support @@ -150,7 +190,6 @@ (when-available java.time.Instant (defmethod to-java [java.time.Instant clojure.lang.APersistentMap] [_ props] - "Instant->map produces :nano, :epochSecond so do the reverse" (when-not (and (:nano props) (:epochSecond props)) (throw (IllegalArgumentException. "java.time.Instant requires :nano and :epochSecond"))) (java.time.Instant/ofEpochSecond (:epochSecond props) (:nano props)))) @@ -170,9 +209,6 @@ instance)) (defmethod to-java [Object clojure.lang.APersistentMap] [^Class clazz props] - "Convert a Clojure map to the specified class using reflection to set the - properties. If the class is an interface, we can't create an instance of - it, unless the Clojure map already implements it." (if (.isInterface clazz) (if (instance? clazz props) (condp = clazz @@ -217,13 +253,22 @@ ;; common from-java definitions (defmethod from-java :default [^Object instance] - "Convert a Java object to a Clojure map" (let [clazz (.getClass instance)] (if (.isArray clazz) ((:from (add-array-methods clazz)) instance) (let [getter-map (reduce add-getter-fn {} (get-property-descriptors clazz))] (into {} (for [[key getter-fn] (seq getter-map)] [key (getter-fn instance)])))))) +(defmethod from-java-shallow :default [^Object instance opts] + (let [clazz (.getClass instance)] + (if (.isArray clazz) + ((:from-shallow (add-array-methods clazz)) instance opts) + (let [getter-map (reduce add-shallow-getter-fn {} (get-property-descriptors clazz))] + (into (if (:add-class opts) {:class (class instance)} {}) + (for [[key getter-fn] (seq getter-map) + :when (not (contains? (:omit opts) key))] + [key (getter-fn instance)])))))) + (doseq [clazz [String Character Byte Short Integer Long Float Double java.math.BigInteger java.math.BigDecimal]] (derive clazz ::do-not-convert)) @@ -253,22 +298,38 @@ (defmethod from-java ::do-not-convert [value] value) (prefer-method from-java ::do-not-convert Object) -(defmethod from-java Iterable [instance] (for [each (seq instance)] (from-java each))) +(defmethod from-java-shallow ::do-not-convert [value _] value) +(prefer-method from-java-shallow ::do-not-convert Object) + +(defmethod from-java Iterable [instance] + (for [each (seq instance)] (from-java each))) (prefer-method from-java Iterable Object) +(defmethod from-java-shallow Iterable [instance opts] + (for [each (seq instance)] (from-java-shallow each opts))) +(prefer-method from-java-shallow Iterable Object) + (defmethod from-java java.util.Map [instance] (into {} instance)) (prefer-method from-java java.util.Map Iterable) +(defmethod from-java-shallow java.util.Map [instance _] (into {} instance)) +(prefer-method from-java-shallow java.util.Map Iterable) + (defmethod from-java nil [_] nil) (defmethod from-java java.sql.SQLException [^Object ex] ((get-method from-java :default) ex)) (defmethod from-java Boolean [value] (boolean value)) (defmethod from-java Enum [enum] (str enum)) +(defmethod from-java-shallow nil [_ _] nil) +(defmethod from-java-shallow java.sql.SQLException [^Object ex opts] + ((get-method from-java-shallow :default) ex opts)) +(defmethod from-java-shallow Boolean [value _] (boolean value)) +(defmethod from-java-shallow Enum [enum _] (str enum)) + ;; definitions for interfacting with XMLGregorianCalendar (defmethod to-java [javax.xml.datatype.XMLGregorianCalendar clojure.lang.APersistentMap] [^Class clazz props] - "Create an XMLGregorianCalendar object given the following keys :year :month :day :hour :minute :second :timezone" (let [^javax.xml.datatype.XMLGregorianCalendar instance (.newInstance clazz) undefined javax.xml.datatype.DatatypeConstants/FIELD_UNDEFINED getu #(get %1 %2 undefined) @@ -287,9 +348,9 @@ (.setSecond (getu props :second)) (.setTimezone (getu props :timezone))))) -(defmethod from-java javax.xml.datatype.XMLGregorianCalendar - [^javax.xml.datatype.XMLGregorianCalendar obj] +(defn- from-xml-gregorian-calendar "Turn an XMLGregorianCalendar object into a clojure map of year, month, day, hour, minute, second and timezone " + [^javax.xml.datatype.XMLGregorianCalendar obj] (let [date {:year (.getYear obj) :month (.getMonth obj) :day (.getDay obj)} @@ -299,9 +360,16 @@ tz {:timezone (.getTimezone obj)} is-undefined? #(= javax.xml.datatype.DatatypeConstants/FIELD_UNDEFINED %1)] (conj {} - (if-not (is-undefined? (:year date)) + (when-not (is-undefined? (:year date)) date) - (if-not (is-undefined? (:hour time)) + (when-not (is-undefined? (:hour time)) time) - (if-not (is-undefined? (:timezone tz)) + (when-not (is-undefined? (:timezone tz)) tz)))) + +(defmethod from-java javax.xml.datatype.XMLGregorianCalendar + [obj] (from-xml-gregorian-calendar obj)) +(defmethod from-java-shallow javax.xml.datatype.XMLGregorianCalendar + [obj {:keys [add-class]}] + (cond-> (from-xml-gregorian-calendar obj) + add-class (assoc :class (class obj)))) From f562857e730b2104769098ef3c264065c062fef7 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sun, 31 May 2020 14:21:40 -0700 Subject: [PATCH 053/101] Prep for 1.0.73 release --- CHANGELOG.md | 2 +- README.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e31c45..154ca8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ ## Change Log -* Release 1.0.next in progress +* Release 1.0.73 on 2020-05-31 * Add `from-java-shallow` to provide functionality similar to `clojure.core/bean` (a shallow conversion) but with options to control behavior (so "dangerous" methods that appear as getters can be omitted). * Bump `org.clojure/tools.logging` to `1.1.0`. * Move change log to a separate file. diff --git a/README.md b/README.md index c6aea9c..753cb36 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ clojure-contrib This project follows the version scheme MAJOR.MINOR.COMMITS where MAJOR and MINOR provide some relative indication of the size of the change, but do not follow semantic versioning. In general, all changes endeavor to be non-breaking (by moving to new names rather than by breaking existing names). COMMITS is an ever-increasing counter of commits since the beginning of this repository. -Latest stable release: 1.0.64 +Latest stable release: 1.0.73 * [All Released Versions](http://search.maven.org/#search%7Cga%7C1%7Corg.clojure%20java.data) * [Development Snapshot Versions](https://repository.sonatype.org/index.html#nexus-search;gav~org.clojure~java.data~~~) @@ -16,7 +16,7 @@ Latest stable release: 1.0.64 ### Leiningen ```clojure -[org.clojure/java.data "1.0.64"] +[org.clojure/java.data "1.0.73"] ``` ### Maven @@ -25,7 +25,7 @@ Latest stable release: 1.0.64 org.clojure java.data - 1.0.64 + 1.0.73 ``` From 81d91ada8087045fa6f1c1806ee1e727e146896b Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Sun, 31 May 2020 16:26:44 -0500 Subject: [PATCH 054/101] [maven-release-plugin] prepare release java.data-1.0.73 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 1ba38d3..8413a6e 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 1.0.65-SNAPSHOT + 1.0.73 java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - HEAD + java.data-1.0.73 From 0cfb310230f5c599e300e0bfa7dc8c68a8c7561f Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Sun, 31 May 2020 16:26:44 -0500 Subject: [PATCH 055/101] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 8413a6e..0cb1e12 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 1.0.73 + 1.0.74-SNAPSHOT java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - java.data-1.0.73 + HEAD From aa05752df0ad7920e00ceb44d461383b2bfa2c61 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sun, 31 May 2020 15:26:58 -0700 Subject: [PATCH 056/101] Fix bug in shallow array conversion --- src/main/clojure/clojure/java/data.clj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/clojure/clojure/java/data.clj b/src/main/clojure/clojure/java/data.clj index 3ebe52e..5c94b9b 100644 --- a/src/main/clojure/clojure/java/data.clj +++ b/src/main/clojure/clojure/java/data.clj @@ -106,7 +106,7 @@ to (fn [_ sequence] (into-array cls (map (partial to-java cls) sequence))) from (fn [obj] (map from-java obj)) - from-shallow (fn [obj opts] (map from-java-shallow obj opts))] + from-shallow (fn [obj opts] (map #(from-java-shallow % opts) obj))] (.addMethod ^clojure.lang.MultiFn to-java [acls Iterable] to) (.addMethod ^clojure.lang.MultiFn from-java acls from) (.addMethod ^clojure.lang.MultiFn from-java-shallow acls from-shallow) @@ -264,7 +264,7 @@ (if (.isArray clazz) ((:from-shallow (add-array-methods clazz)) instance opts) (let [getter-map (reduce add-shallow-getter-fn {} (get-property-descriptors clazz))] - (into (if (:add-class opts) {:class (class instance)} {}) + (into (if (:add-class opts) {:class (class instance)} {}) (for [[key getter-fn] (seq getter-map) :when (not (contains? (:omit opts) key))] [key (getter-fn instance)])))))) From c78448390da080eee275bceaeef5f7eb22b2b60f Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sun, 31 May 2020 16:45:12 -0700 Subject: [PATCH 057/101] Implement configurable exception handling --- CHANGELOG.md | 4 +++ src/main/clojure/clojure/java/data.clj | 34 ++++++++++++++++++++++---- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 154ca8e..a378158 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## Change Log +* Release 1.0.next in progress + * Make exception handling in shallow conversions configurable: an `:exceptions` option may be `:group`, `:omit`, `:quaify`, or `:return`. + * Fix bug in shallow array handling. + * Release 1.0.73 on 2020-05-31 * Add `from-java-shallow` to provide functionality similar to `clojure.core/bean` (a shallow conversion) but with options to control behavior (so "dangerous" methods that appear as getters can be omitted). * Bump `org.clojure/tools.logging` to `1.1.0`. diff --git a/src/main/clojure/clojure/java/data.clj b/src/main/clojure/clojure/java/data.clj index 5c94b9b..b246e7d 100644 --- a/src/main/clojure/clojure/java/data.clj +++ b/src/main/clojure/clojure/java/data.clj @@ -44,6 +44,13 @@ conversion: * :add-class -- if true, add :class with the actual class of the object being converted -- this mimics clojure.core/bean. + * :exceptions -- controls how getter exceptions should be handled: + * :group -- return an :exceptions hash map in the object that + contains all the properties that failed, with their exceptions, + * :omit -- ignore exceptions and omit the properties that caused them, + * :qualify -- return the exception as :/exception and + omit the property itself, + * :return -- simply return the exception as the value of the property. * :omit -- a set of properties (keywords) to omit from the conversion so that unsafe methods are not called." (fn [obj _] (class obj))) @@ -263,11 +270,28 @@ (let [clazz (.getClass instance)] (if (.isArray clazz) ((:from-shallow (add-array-methods clazz)) instance opts) - (let [getter-map (reduce add-shallow-getter-fn {} (get-property-descriptors clazz))] - (into (if (:add-class opts) {:class (class instance)} {}) - (for [[key getter-fn] (seq getter-map) - :when (not (contains? (:omit opts) key))] - [key (getter-fn instance)])))))) + (let [getter-map (reduce add-shallow-getter-fn {} (get-property-descriptors clazz)) + exs (atom []) + pairs (for [[key getter-fn] (seq getter-map) + :when (not (contains? (:omit opts) key)) + :let [[k v] + (if-let [exh (:exceptions opts)] + (try + [key (getter-fn instance)] + (catch Throwable t + (case exh + :group (swap! exs conj [key t]) + :omit nil + :qualify [(keyword (name key) + "exception") t] + :return [key t]))) + [key (getter-fn instance)])] + :when k] + [k v])] + (cond-> {} + (:add-class opts) (assoc :class (class instance)) + (seq @exs) (assoc :exceptions (into {} @exs)) + (seq pairs) (into pairs)))))) (doseq [clazz [String Character Byte Short Integer Long Float Double java.math.BigInteger java.math.BigDecimal]] From a0d6ad4e62f597a547423a7e763803506e01d137 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sun, 31 May 2020 16:47:19 -0700 Subject: [PATCH 058/101] Prep for 1.0.78 release --- CHANGELOG.md | 2 +- README.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a378158..b2f0ce7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ ## Change Log -* Release 1.0.next in progress +* Release 1.0.78 on 2020-05-31 * Make exception handling in shallow conversions configurable: an `:exceptions` option may be `:group`, `:omit`, `:quaify`, or `:return`. * Fix bug in shallow array handling. diff --git a/README.md b/README.md index 753cb36..b28af13 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ clojure-contrib This project follows the version scheme MAJOR.MINOR.COMMITS where MAJOR and MINOR provide some relative indication of the size of the change, but do not follow semantic versioning. In general, all changes endeavor to be non-breaking (by moving to new names rather than by breaking existing names). COMMITS is an ever-increasing counter of commits since the beginning of this repository. -Latest stable release: 1.0.73 +Latest stable release: 1.0.78 * [All Released Versions](http://search.maven.org/#search%7Cga%7C1%7Corg.clojure%20java.data) * [Development Snapshot Versions](https://repository.sonatype.org/index.html#nexus-search;gav~org.clojure~java.data~~~) @@ -16,7 +16,7 @@ Latest stable release: 1.0.73 ### Leiningen ```clojure -[org.clojure/java.data "1.0.73"] +[org.clojure/java.data "1.0.78"] ``` ### Maven @@ -25,7 +25,7 @@ Latest stable release: 1.0.73 org.clojure java.data - 1.0.73 + 1.0.78 ``` From 0dce69cc7c27f59aeff7eb8c90234612aabafd66 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Sun, 31 May 2020 18:53:14 -0500 Subject: [PATCH 059/101] [maven-release-plugin] prepare release java.data-1.0.78 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 0cb1e12..af5f67e 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 1.0.74-SNAPSHOT + 1.0.78 java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - HEAD + java.data-1.0.78 From 1f0e0bb29732661596f517c01d63f0c11c8d4d29 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Sun, 31 May 2020 18:53:15 -0500 Subject: [PATCH 060/101] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index af5f67e..0c60027 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 1.0.78 + 1.0.79-SNAPSHOT java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - java.data-1.0.78 + HEAD From b482f766e2f0213c7ac9055e4f71aea190c444f2 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Thu, 18 Jun 2020 13:05:38 -0500 Subject: [PATCH 061/101] add LICENSE text file --- LICENSE | 205 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e246f6a --- /dev/null +++ b/LICENSE @@ -0,0 +1,205 @@ +Eclipse Public License - v 1.0 + +THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC +LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM +CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + +a) in the case of the initial Contributor, the initial code and documentation + distributed under this Agreement, and +b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + + where such changes and/or additions to the Program originate from and are + distributed by that particular Contributor. A Contribution 'originates' + from a Contributor if it was added to the Program by such Contributor + itself or anyone acting on such Contributor's behalf. Contributions do not + include additions to the Program which: (i) are separate modules of + software distributed in conjunction with the Program under their own + license agreement, and (ii) are not derivative works of the Program. + +"Contributor" means any person or entity that distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which are +necessarily infringed by the use or sale of its Contribution alone or when +combined with the Program. + +"Program" means the Contributions distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement, +including all Contributors. + +2. GRANT OF RIGHTS + a) Subject to the terms of this Agreement, each Contributor hereby grants + Recipient a non-exclusive, worldwide, royalty-free copyright license to + reproduce, prepare derivative works of, publicly display, publicly + perform, distribute and sublicense the Contribution of such Contributor, + if any, and such derivative works, in source code and object code form. + b) Subject to the terms of this Agreement, each Contributor hereby grants + Recipient a non-exclusive, worldwide, royalty-free patent license under + Licensed Patents to make, use, sell, offer to sell, import and otherwise + transfer the Contribution of such Contributor, if any, in source code and + object code form. This patent license shall apply to the combination of + the Contribution and the Program if, at the time the Contribution is + added by the Contributor, such addition of the Contribution causes such + combination to be covered by the Licensed Patents. The patent license + shall not apply to any other combinations which include the Contribution. + No hardware per se is licensed hereunder. + c) Recipient understands that although each Contributor grants the licenses + to its Contributions set forth herein, no assurances are provided by any + Contributor that the Program does not infringe the patent or other + intellectual property rights of any other entity. Each Contributor + disclaims any liability to Recipient for claims brought by any other + entity based on infringement of intellectual property rights or + otherwise. As a condition to exercising the rights and licenses granted + hereunder, each Recipient hereby assumes sole responsibility to secure + any other intellectual property rights needed, if any. For example, if a + third party patent license is required to allow Recipient to distribute + the Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + d) Each Contributor represents that to its knowledge it has sufficient + copyright rights in its Contribution, if any, to grant the copyright + license set forth in this Agreement. + +3. REQUIREMENTS + +A Contributor may choose to distribute the Program in object code form under +its own license agreement, provided that: + + a) it complies with the terms and conditions of this Agreement; and + b) its license agreement: + i) effectively disclaims on behalf of all Contributors all warranties + and conditions, express and implied, including warranties or + conditions of title and non-infringement, and implied warranties or + conditions of merchantability and fitness for a particular purpose; + ii) effectively excludes on behalf of all Contributors all liability for + damages, including direct, indirect, special, incidental and + consequential damages, such as lost profits; + iii) states that any provisions which differ from this Agreement are + offered by that Contributor alone and not by any other party; and + iv) states that source code for the Program is available from such + Contributor, and informs licensees how to obtain it in a reasonable + manner on or through a medium customarily used for software exchange. + +When the Program is made available in source code form: + + a) it must be made available under this Agreement; and + b) a copy of this Agreement must be included with each copy of the Program. + Contributors may not remove or alter any copyright notices contained + within the Program. + +Each Contributor must identify itself as the originator of its Contribution, +if +any, in a manner that reasonably allows subsequent Recipients to identify the +originator of the Contribution. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities with +respect to end users, business partners and the like. While this license is +intended to facilitate the commercial use of the Program, the Contributor who +includes the Program in a commercial product offering should do so in a manner +which does not create potential liability for other Contributors. Therefore, +if a Contributor includes the Program in a commercial product offering, such +Contributor ("Commercial Contributor") hereby agrees to defend and indemnify +every other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits and +other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such Commercial +Contributor in connection with its distribution of the Program in a commercial +product offering. The obligations in this section do not apply to any claims +or Losses relating to any actual or alleged intellectual property +infringement. In order to qualify, an Indemnified Contributor must: +a) promptly notify the Commercial Contributor in writing of such claim, and +b) allow the Commercial Contributor to control, and cooperate with the +Commercial Contributor in, the defense and any related settlement +negotiations. The Indemnified Contributor may participate in any such claim at +its own expense. + +For example, a Contributor might include the Program in a commercial product +offering, Product X. That Contributor is then a Commercial Contributor. If +that Commercial Contributor then makes performance claims, or offers +warranties related to Product X, those performance claims and warranties are +such Commercial Contributor's responsibility alone. Under this section, the +Commercial Contributor would have to defend claims against the other +Contributors related to those performance claims and warranties, and if a +court requires any other Contributor to pay any damages as a result, the +Commercial Contributor must pay those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each +Recipient is solely responsible for determining the appropriateness of using +and distributing the Program and assumes all risks associated with its +exercise of rights under this Agreement , including but not limited to the +risks and costs of program errors, compliance with applicable laws, damage to +or loss of data, programs or equipment, and unavailability or interruption of +operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY +CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION +LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of the +remainder of the terms of this Agreement, and without further action by the +parties hereto, such provision shall be reformed to the minimum extent +necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Program itself +(excluding combinations of the Program with other software or hardware) +infringes such Recipient's patent(s), then such Recipient's rights granted +under Section 2(b) shall terminate as of the date such litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it fails to +comply with any of the material terms or conditions of this Agreement and does +not cure such failure in a reasonable period of time after becoming aware of +such noncompliance. If all Recipient's rights under this Agreement terminate, +Recipient agrees to cease use and distribution of the Program as soon as +reasonably practicable. However, Recipient's obligations under this Agreement +and any licenses granted by Recipient relating to the Program shall continue +and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, but in +order to avoid inconsistency the Agreement is copyrighted and may only be +modified in the following manner. The Agreement Steward reserves the right to +publish new versions (including revisions) of this Agreement from time to +time. No one other than the Agreement Steward has the right to modify this +Agreement. The Eclipse Foundation is the initial Agreement Steward. The +Eclipse Foundation may assign the responsibility to serve as the Agreement +Steward to a suitable separate entity. Each new version of the Agreement will +be given a distinguishing version number. The Program (including +Contributions) may always be distributed subject to the version of the +Agreement under which it was received. In addition, after a new version of the +Agreement is published, Contributor may elect to distribute the Program +(including its Contributions) under the new version. Except as expressly +stated in Sections 2(a) and 2(b) above, Recipient receives no rights or +licenses to the intellectual property of any Contributor under this Agreement, +whether expressly, by implication, estoppel or otherwise. All rights in the +Program not expressly granted under this Agreement are reserved. + +This Agreement is governed by the laws of the State of New York and the +intellectual property laws of the United States of America. No party to this +Agreement will bring a legal action under this Agreement more than one year +after the cause of action arose. Each party waives its rights to a jury trial in +any resulting litigation. + + From 2098a395087e377d93d839dbb00e7cee4df0cf3b Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 17 Jul 2020 16:27:49 -0700 Subject: [PATCH 062/101] JDATA-21 add from-java-deep Guarantee a deep conversion, even on a hash map. Allows for options to control getter exceptions, adding `:class`, and `:omit`'ing problematic getter calls. Also fixes a bug in `from-java-shallow` on getters returning `Boolean` (not being canonicalized). --- src/main/clojure/clojure/java/data.clj | 91 +++++++- src/test/clojure/clojure/java/test_data.clj | 225 ++++++++++++++++---- 2 files changed, 266 insertions(+), 50 deletions(-) diff --git a/src/main/clojure/clojure/java/data.clj b/src/main/clojure/clojure/java/data.clj index b246e7d..213697e 100644 --- a/src/main/clojure/clojure/java/data.clj +++ b/src/main/clojure/clojure/java/data.clj @@ -37,6 +37,24 @@ (defmulti from-java "Convert a Java object to a Clojure map." class) +(defmulti from-java-deep + "Convert a Java object to a Clojure map (converting deeply). + + The second argument is a hash map that offers some control over the + conversion: + * :add-class -- if true, add :class with the actual class of the object + being converted -- this mimics clojure.core/bean. + * :exceptions -- controls how getter exceptions should be handled: + * :group -- return an :exceptions hash map in the object that + contains all the properties that failed, with their exceptions, + * :omit -- ignore exceptions and omit the properties that caused them, + * :qualify -- return the exception as :/exception and + omit the property itself, + * :return -- simply return the exception as the value of the property. + * :omit -- a set of properties (keywords) to omit from the conversion + so that unsafe methods are not called (this applies across the whole + recursive/deep conversion)." + (fn [obj _] (class obj))) (defmulti from-java-shallow "Convert a Java object to a Clojure map (but do not convert deeply). @@ -71,9 +89,16 @@ (fn [instance] (from-java (.invoke method instance nil)))) +(defn- make-deep-getter-fn [^java.lang.reflect.Method method opts] + (fn [instance] + (from-java-deep (.invoke method instance nil) opts))) + (defn- make-shallow-getter-fn [^java.lang.reflect.Method method] (fn [instance] - (.invoke method instance nil))) + (let [r (.invoke method instance nil)] + (if (instance? Boolean r) + (boolean r) + r)))) (defn- add-getter-fn [the-map ^java.beans.PropertyDescriptor prop-descriptor] (let [name (.getName prop-descriptor) @@ -82,6 +107,13 @@ (assoc the-map (keyword name) (make-getter-fn method)) the-map))) +(defn- add-deep-getter-fn [the-map ^java.beans.PropertyDescriptor prop-descriptor opts] + (let [name (.getName prop-descriptor) + method (.getReadMethod prop-descriptor)] + (if (and (is-getter method) (not (= "class" name))) + (assoc the-map (keyword name) (make-deep-getter-fn method opts)) + the-map))) + (defn- add-shallow-getter-fn [the-map ^java.beans.PropertyDescriptor prop-descriptor] (let [name (.getName prop-descriptor) method (.getReadMethod prop-descriptor)] @@ -113,11 +145,13 @@ to (fn [_ sequence] (into-array cls (map (partial to-java cls) sequence))) from (fn [obj] (map from-java obj)) + from-deep (fn [obj opts] (map #(from-java-deep % opts) obj)) from-shallow (fn [obj opts] (map #(from-java-shallow % opts) obj))] (.addMethod ^clojure.lang.MultiFn to-java [acls Iterable] to) (.addMethod ^clojure.lang.MultiFn from-java acls from) + (.addMethod ^clojure.lang.MultiFn from-java-deep acls from-deep) (.addMethod ^clojure.lang.MultiFn from-java-shallow acls from-shallow) - {:to to :from from :from-shallow from-shallow})) + {:to to :from from :from-deep from-deep :from-shallow from-shallow})) ;; constructor support @@ -219,7 +253,7 @@ (if (.isInterface clazz) (if (instance? clazz props) (condp = clazz - ;; make a fresh (mutabl) hash map from the Clojure map + ;; make a fresh (mutable) hash map from the Clojure map java.util.Map (java.util.HashMap. ^java.util.Map props) ;; Iterable, Serializable, Runnable, Callable ;; we should probably figure out actual objects to create... @@ -266,6 +300,33 @@ (let [getter-map (reduce add-getter-fn {} (get-property-descriptors clazz))] (into {} (for [[key getter-fn] (seq getter-map)] [key (getter-fn instance)])))))) +(defmethod from-java-deep :default [^Object instance opts] + (let [clazz (.getClass instance)] + (if (.isArray clazz) + ((:from-deep (add-array-methods clazz)) instance opts) + (let [getter-map (reduce #(add-deep-getter-fn %1 %2 opts) {} (get-property-descriptors clazz)) + exs (atom []) + pairs (for [[key getter-fn] (seq getter-map) + :when (not (contains? (:omit opts) key)) + :let [[k v] + (if-let [exh (:exceptions opts)] + (try + [key (getter-fn instance)] + (catch Throwable t + (case exh + :group (swap! exs conj [key t]) + :omit nil + :qualify [(keyword (name key) + "exception") t] + :return [key t]))) + [key (getter-fn instance)])] + :when k] + [k v])] + (cond-> {} + (:add-class opts) (assoc :class (class instance)) + (seq @exs) (assoc :exceptions (into {} @exs)) + (seq pairs) (into pairs)))))) + (defmethod from-java-shallow :default [^Object instance opts] (let [clazz (.getClass instance)] (if (.isArray clazz) @@ -322,6 +383,9 @@ (defmethod from-java ::do-not-convert [value] value) (prefer-method from-java ::do-not-convert Object) +(defmethod from-java-deep ::do-not-convert [value _] value) +(prefer-method from-java-deep ::do-not-convert Object) + (defmethod from-java-shallow ::do-not-convert [value _] value) (prefer-method from-java-shallow ::do-not-convert Object) @@ -329,6 +393,10 @@ (for [each (seq instance)] (from-java each))) (prefer-method from-java Iterable Object) +(defmethod from-java-deep Iterable [instance opts] + (for [each (seq instance)] (from-java-deep each opts))) +(prefer-method from-java-deep Iterable Object) + (defmethod from-java-shallow Iterable [instance opts] (for [each (seq instance)] (from-java-shallow each opts))) (prefer-method from-java-shallow Iterable Object) @@ -336,6 +404,13 @@ (defmethod from-java java.util.Map [instance] (into {} instance)) (prefer-method from-java java.util.Map Iterable) +(defmethod from-java-deep java.util.Map [instance opts] + (reduce (fn [m [k v]] + (assoc m (from-java-deep k opts) (from-java-deep v opts))) + {} + instance)) +(prefer-method from-java-deep java.util.Map Iterable) + (defmethod from-java-shallow java.util.Map [instance _] (into {} instance)) (prefer-method from-java-shallow java.util.Map Iterable) @@ -345,6 +420,12 @@ (defmethod from-java Boolean [value] (boolean value)) (defmethod from-java Enum [enum] (str enum)) +(defmethod from-java-deep nil [_ _] nil) +(defmethod from-java-deep java.sql.SQLException [^Object ex opts] + ((get-method from-java-deep :default) ex opts)) +(defmethod from-java-deep Boolean [value _] (boolean value)) +(defmethod from-java-deep Enum [enum _] (str enum)) + (defmethod from-java-shallow nil [_ _] nil) (defmethod from-java-shallow java.sql.SQLException [^Object ex opts] ((get-method from-java-shallow :default) ex opts)) @@ -393,6 +474,10 @@ (defmethod from-java javax.xml.datatype.XMLGregorianCalendar [obj] (from-xml-gregorian-calendar obj)) +(defmethod from-java-deep javax.xml.datatype.XMLGregorianCalendar + [obj {:keys [add-class]}] + (cond-> (from-xml-gregorian-calendar obj) + add-class (assoc :class (class obj)))) (defmethod from-java-shallow javax.xml.datatype.XMLGregorianCalendar [obj {:keys [add-class]}] (cond-> (from-xml-gregorian-calendar obj) diff --git a/src/test/clojure/clojure/java/test_data.clj b/src/test/clojure/clojure/java/test_data.clj index 3d4071f..e9bce2d 100644 --- a/src/test/clojure/clojure/java/test_data.clj +++ b/src/test/clojure/clojure/java/test_data.clj @@ -8,8 +8,10 @@ (ns clojure.java.test-data (:require [clojure.java.data :as j - :refer [from-java set-properties to-java + :refer [from-java from-java-deep from-java-shallow + set-properties to-java *to-java-object-missing-setter*]] + [clojure.string :as str] [clojure.tools.logging :refer [log* info]] [clojure.test :refer [deftest is testing]]) (:import (clojure.java.data.test Person Address State Primitive @@ -78,65 +80,183 @@ (defn- to-BigInteger [v] (bigint v))) (deftest java-to-clojure - (let [address (new Address "123 Main St" "Dallas" State/TX "75432") - person (from-java (Person. "Bob" (to-BigInteger 30) address))] - (is (= "Bob" (:name person))) - (is (= 30 (:age person))) - (is (= "123 Main St" (:line1 (:address person)))) - (is (= "TX" (:state (:address person)))))) + (testing "regular" + (let [address (new Address "123 Main St" "Dallas" State/TX "75432") + person (from-java (Person. "Bob" (to-BigInteger 30) address))] + (is (= "Bob" (:name person))) + (is (= 30 (:age person))) + (is (= "123 Main St" (:line1 (:address person)))) + (is (= "TX" (:state (:address person)))))) + (testing "deep" + (let [address (new Address "123 Main St" "Dallas" State/TX "75432") + person (from-java-deep (Person. "Bob" (to-BigInteger 30) address) {})] + (is (= "Bob" (:name person))) + (is (= 30 (:age person))) + (is (= "123 Main St" (:line1 (:address person)))) + (is (= "TX" (:state (:address person)))))) + (testing "shallow" + (let [address (new Address "123 Main St" "Dallas" State/TX "75432") + person (from-java-shallow (Person. "Bob" (to-BigInteger 30) address) {})] + (is (= "Bob" (:name person))) + (is (= 30 (:age person))) + (is (instance? Address (:address person)))))) (deftest primitives - (let [datum {:boolMember true - :boolArray [true false] - :charMember \H - :charArray (map identity "Hello World") - :byteMember 127 - :byteArray [1 2 3] - :shortMember 15000 - :shortArray [13000 14000 15000] - :intMember 18000 - :intArray [1 2 3] - :longMember 60000000 - :longArray [1 2 3] - :floatMember 1.5 - :floatArray [1.5 2.5 3.5] - :doubleMember 1.5 - :doubleArray [1.5 2.0 2.5] - :nestedIntArray [[1 2] [3] [4 5 6] []] - :stringArray ["Argument" "Vector"]}] - (is (= datum - (from-java (to-java Primitive datum)))))) + (testing "regular" + (let [datum {:boolMember true + :boolArray [true false] + :charMember \H + :charArray (map identity "Hello World") + :byteMember 127 + :byteArray [1 2 3] + :shortMember 15000 + :shortArray [13000 14000 15000] + :intMember 18000 + :intArray [1 2 3] + :longMember 60000000 + :longArray [1 2 3] + :floatMember 1.5 + :floatArray [1.5 2.5 3.5] + :doubleMember 1.5 + :doubleArray [1.5 2.0 2.5] + :nestedIntArray [[1 2] [3] [4 5 6] []] + :stringArray ["Argument" "Vector"]}] + (is (= datum + (from-java (to-java Primitive datum)))))) + (testing "deep" + (let [datum {:boolMember true + :boolArray [true false] + :charMember \H + :charArray (map identity "Hello World") + :byteMember 127 + :byteArray [1 2 3] + :shortMember 15000 + :shortArray [13000 14000 15000] + :intMember 18000 + :intArray [1 2 3] + :longMember 60000000 + :longArray [1 2 3] + :floatMember 1.5 + :floatArray [1.5 2.5 3.5] + :doubleMember 1.5 + :doubleArray [1.5 2.0 2.5] + :nestedIntArray [[1 2] [3] [4 5 6] []] + :stringArray ["Argument" "Vector"]}] + (is (= datum + (from-java-deep (to-java Primitive datum) {}))))) + (testing "shallow" + (let [datum {:boolMember true + :boolArray [true false] + :charMember \H + :charArray (map identity "Hello World") + :byteMember 127 + :byteArray [1 2 3] + :shortMember 15000 + :shortArray [13000 14000 15000] + :intMember 18000 + :intArray [1 2 3] + :longMember 60000000 + :longArray [1 2 3] + :floatMember 1.5 + :floatArray [1.5 2.5 3.5] + :doubleMember 1.5 + :doubleArray [1.5 2.0 2.5] + :nestedIntArray [[1 2] [3] [4 5 6] []] + :stringArray ["Argument" "Vector"]}] + (reduce-kv (fn [_ k v] + (if (str/ends-with? (name k) "Array") + (if (= k :nestedIntArray) + (is (= (get datum k) (map #(into [] %) v))) + (is (= (get datum k) (seq v)))) + (is (= (get datum k) v)))) + nil + (from-java-shallow (to-java Primitive datum) {}))))) + +(deftest java-map + (let [datum {"a" "one" "b" 2 "c" (java.net.URI. "")}] + (testing "regular" ; is actually shallow on hash maps + (is (= datum (from-java (to-java java.util.Map datum))))) + (testing "deep" + (is (= (update datum "c" from-java) + (from-java-deep (to-java java.util.Map datum) {})))) + (testing "shallow" + (is (= datum (from-java-shallow (to-java java.util.Map datum) {})))))) (deftest jdata-6 - (let [bean-instance (TestBean6.) - _ (. bean-instance setFoo {"bar" "baz"}) - bean-instance-as-map (from-java bean-instance) - new-bean-instance (to-java TestBean6 bean-instance-as-map)] - (is (= {"bar" "baz"} (:foo bean-instance-as-map))) - (is (= {"bar" "baz"} (.getFoo new-bean-instance))))) + (testing "regular" + (let [bean-instance (TestBean6.) + _ (. bean-instance setFoo {"bar" "baz"}) + bean-instance-as-map (from-java bean-instance) + new-bean-instance (to-java TestBean6 bean-instance-as-map)] + (is (= {"bar" "baz"} (:foo bean-instance-as-map))) + (is (= {"bar" "baz"} (.getFoo new-bean-instance))))) + (testing "deep" + (let [bean-instance (TestBean6.) + _ (. bean-instance setFoo {"bar" "baz"}) + bean-instance-as-map (from-java-deep bean-instance {}) + new-bean-instance (to-java TestBean6 bean-instance-as-map)] + (is (= {"bar" "baz"} (:foo bean-instance-as-map))) + (is (= {"bar" "baz"} (.getFoo new-bean-instance))))) + (testing "shallow" + (let [bean-instance (TestBean6.) + _ (. bean-instance setFoo {"bar" "baz"}) + bean-instance-as-map (from-java-shallow bean-instance {}) + new-bean-instance (to-java TestBean6 bean-instance-as-map)] + (is (= {"bar" "baz"} (:foo bean-instance-as-map))) + (is (= {"bar" "baz"} (.getFoo new-bean-instance)))))) (deftest jdata-8-11-date - (let [d (java.util.Date.)] - (is (= d (to-java java.util.Date (from-java d)))))) + (testing "regular" + (let [d (java.util.Date.)] + (is (= d (to-java java.util.Date (from-java d)))))) + (testing "deep" + (let [d (java.util.Date.)] + (is (= d (to-java java.util.Date (from-java-deep d {})))))) + (testing "shallow" + (let [d (java.util.Date.)] + (is (= d (to-java java.util.Date (from-java-shallow d {}))))))) (when-available java.time.Instant (deftest jdata-8-11-instant - (let [t (java.time.Instant/now)] - (is (= t (to-java java.time.Instant (from-java t))))))) + (testing "regular" + (let [t (java.time.Instant/now)] + (is (= t (to-java java.time.Instant (from-java t)))))) + (testing "deep" + (let [t (java.time.Instant/now)] + (is (= t (to-java java.time.Instant (from-java-deep t {})))))) + (testing "shallow" + (let [t (java.time.Instant/now)] + (is (= t (to-java java.time.Instant (from-java-shallow t {})))))))) (deftest jdata-9 (let [bean-instance (TestBean9.) _ (.setAString bean-instance "something") _ (.setABool bean-instance true) _ (.setABoolean bean-instance false)] - (is (= {:AString "something" :ABool true} - ;; :ABoolean missing because 'is' Boolean is not a getter - (from-java bean-instance))))) + (testing "regular" + (is (= {:AString "something" :ABool true} + ;; :ABoolean missing because 'is' Boolean is not a getter + (from-java bean-instance)))) + (testing "deep" + (is (= {:AString "something" :ABool true} + ;; :ABoolean missing because 'is' Boolean is not a getter + (from-java-deep bean-instance {})))) + (testing "shallow" + (is (= {:AString "something" :ABool true} + ;; :ABoolean missing because 'is' Boolean is not a getter + (from-java-shallow bean-instance {})))))) (deftest jdata-10 - (is (if (:absolute (from-java (java.net.URI. ""))) false true)) - (is (if (:opaque (from-java (java.net.URI. ""))) false true))) + (testing "regular" + (is (if (:absolute (from-java (java.net.URI. ""))) false true)) + (is (if (:opaque (from-java (java.net.URI. ""))) false true))) + (testing "deep" + (is (if (:absolute (from-java-deep (java.net.URI. "") {})) false true)) + (is (if (:opaque (from-java-deep (java.net.URI. "") {})) false true))) + (testing "shallow" + (is (if (:absolute (from-java-shallow (java.net.URI. "") {})) false true)) + (is (if (:opaque (from-java-shallow (java.net.URI. "") {})) false true)))) (deftest jdata-12 (let [eek1 (java.sql.SQLException. "SQL 1") @@ -144,11 +264,22 @@ eek3 (java.sql.SQLException. "SQL 3")] (.setNextException eek1 eek2) (.setNextException eek2 eek3) - (let [ex (from-java eek1)] - (is (= "SQL 1" (get-in ex [:message]))) - (is (= "SQL 2" (get-in ex [:nextException :message]))) - (is (= "SQL 3" (get-in ex [:nextException :nextException :message]))) - (is (nil? (get-in ex [:nextException :nextException :nextException])))))) + (testing "regular" + (let [ex (from-java eek1)] + (is (= "SQL 1" (get-in ex [:message]))) + (is (= "SQL 2" (get-in ex [:nextException :message]))) + (is (= "SQL 3" (get-in ex [:nextException :nextException :message]))) + (is (nil? (get-in ex [:nextException :nextException :nextException]))))) + (testing "deep" + (let [ex (from-java-deep eek1 {})] + (is (= "SQL 1" (get-in ex [:message]))) + (is (= "SQL 2" (get-in ex [:nextException :message]))) + (is (= "SQL 3" (get-in ex [:nextException :nextException :message]))) + (is (nil? (get-in ex [:nextException :nextException :nextException]))))) + (testing "shallow" + (let [ex (from-java-shallow eek1 {})] + (is (= "SQL 1" (get-in ex [:message]))) + (is (instance? java.sql.SQLException (get ex :nextException))))))) ;; set-properties tests From 5c34652bbe583156939768793001dc672453582d Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 17 Jul 2020 16:30:01 -0700 Subject: [PATCH 063/101] Note JDATA-21 and shallow Boolean fixes --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2f0ce7..b16cc99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## Change Log +* Release 1.0.next in progress + * Add `from-java-deep` to guarantee deep conversion with same options as `from-java-shallow` [JDATA-21](https://clojure.atlassian.net/browse/JDATA-21). + * Fixes bug in `from-java-shallow` for getters returning `Boolean` (the value was not canonicalized so `false` could be truthy). + * Release 1.0.78 on 2020-05-31 * Make exception handling in shallow conversions configurable: an `:exceptions` option may be `:group`, `:omit`, `:quaify`, or `:return`. * Fix bug in shallow array handling. From 0a934c89c31ff83ba2e7edf3cc546cca983627c0 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 17 Jul 2020 16:44:12 -0700 Subject: [PATCH 064/101] Make compatible with Clojure 1.7 --- src/test/clojure/clojure/java/test_data.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/clojure/clojure/java/test_data.clj b/src/test/clojure/clojure/java/test_data.clj index e9bce2d..4da6da4 100644 --- a/src/test/clojure/clojure/java/test_data.clj +++ b/src/test/clojure/clojure/java/test_data.clj @@ -164,7 +164,7 @@ :nestedIntArray [[1 2] [3] [4 5 6] []] :stringArray ["Argument" "Vector"]}] (reduce-kv (fn [_ k v] - (if (str/ends-with? (name k) "Array") + (if (.endsWith ^String (name k) "Array") (if (= k :nestedIntArray) (is (= (get datum k) (map #(into [] %) v))) (is (= (get datum k) (seq v)))) From c2bae7ba90c488c43b182561c01f317146c980b1 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 17 Jul 2020 18:46:06 -0700 Subject: [PATCH 065/101] Prep for 1.0.86 --- CHANGELOG.md | 2 +- README.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b16cc99..464a6dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ ## Change Log -* Release 1.0.next in progress +* Release 1.0.86 on 2020-07-17 * Add `from-java-deep` to guarantee deep conversion with same options as `from-java-shallow` [JDATA-21](https://clojure.atlassian.net/browse/JDATA-21). * Fixes bug in `from-java-shallow` for getters returning `Boolean` (the value was not canonicalized so `false` could be truthy). diff --git a/README.md b/README.md index b28af13..1421f38 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ clojure-contrib This project follows the version scheme MAJOR.MINOR.COMMITS where MAJOR and MINOR provide some relative indication of the size of the change, but do not follow semantic versioning. In general, all changes endeavor to be non-breaking (by moving to new names rather than by breaking existing names). COMMITS is an ever-increasing counter of commits since the beginning of this repository. -Latest stable release: 1.0.78 +Latest stable release: 1.0.86 * [All Released Versions](http://search.maven.org/#search%7Cga%7C1%7Corg.clojure%20java.data) * [Development Snapshot Versions](https://repository.sonatype.org/index.html#nexus-search;gav~org.clojure~java.data~~~) @@ -16,7 +16,7 @@ Latest stable release: 1.0.78 ### Leiningen ```clojure -[org.clojure/java.data "1.0.78"] +[org.clojure/java.data "1.0.86"] ``` ### Maven @@ -25,7 +25,7 @@ Latest stable release: 1.0.78 org.clojure java.data - 1.0.78 + 1.0.86 ``` From 5032b597cc965c5329ba0199b42b630811ed64c2 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Fri, 17 Jul 2020 20:47:54 -0500 Subject: [PATCH 066/101] [maven-release-plugin] prepare release java.data-1.0.86 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 0c60027..7bef47c 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 1.0.79-SNAPSHOT + 1.0.86 java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - HEAD + java.data-1.0.86 From cd44059858ba389b2ac4878fdb4e8663e4bbf6f7 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Fri, 17 Jul 2020 20:47:54 -0500 Subject: [PATCH 067/101] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 7bef47c..0bd2951 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 1.0.86 + 1.0.87-SNAPSHOT java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - java.data-1.0.86 + HEAD From 8d002a0b073752a8e4856ff2ff09064a7ca8cd04 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Tue, 1 Sep 2020 13:25:54 -0700 Subject: [PATCH 068/101] Add CLI/deps dependency info --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 1421f38..d6a9c8b 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,12 @@ Latest stable release: 1.0.86 * [All Released Versions](http://search.maven.org/#search%7Cga%7C1%7Corg.clojure%20java.data) * [Development Snapshot Versions](https://repository.sonatype.org/index.html#nexus-search;gav~org.clojure~java.data~~~) +### [CLI/`deps.edn`](https://clojure.org/reference/deps_and_cli) dependency information: + +```clojure +org.clojure/java.data {:mvn/version "1.0.86"} +``` + ### Leiningen ```clojure From e0da4086dba18434ca5c6b3b4f4a38649c2f65a8 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Thu, 18 Feb 2021 08:58:18 -0600 Subject: [PATCH 069/101] update old links --- CONTRIBUTING.md | 2 +- README.md | 13 +++++-------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 87d33f9..0aa519c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,5 +8,5 @@ more information on how to contribute. [Clojure contrib]: https://clojure.org/community/contrib_libs [Contributing]: https://clojure.org/community/contributing -[JIRA]: http://dev.clojure.org/jira/browse/JDATA +[JIRA]: https://clojure.atlassian.net/browse/JDATA [guidelines]: https://clojure.org/community/contrib_howto diff --git a/README.md b/README.md index d6a9c8b..329c5fa 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ This project follows the version scheme MAJOR.MINOR.COMMITS where MAJOR and MINO Latest stable release: 1.0.86 -* [All Released Versions](http://search.maven.org/#search%7Cga%7C1%7Corg.clojure%20java.data) +* [All Released Versions](https://search.maven.org/#search%7Cga%7C1%7Corg.clojure%20java.data) * [Development Snapshot Versions](https://repository.sonatype.org/index.html#nexus-search;gav~org.clojure~java.data~~~) ### [CLI/`deps.edn`](https://clojure.org/reference/deps_and_cli) dependency information: @@ -154,12 +154,9 @@ exception defense | none | none ## Developer Information * [GitHub project](https://github.com/clojure/java.data) - -* [Bug Tracker](http://dev.clojure.org/jira/browse/JDATA) - -* [Continuous Integration](http://build.clojure.org/job/java.data/) - -* [Compatibility Test Matrix](http://build.clojure.org/job/java.data-test-matrix/) +* [Bug Tracker](https://clojure.atlassian.net/browse/JDATA) +* [Continuous Integration](https://build.clojure.org/job/java.data/) +* [Compatibility Test Matrix](https://build.clojure.org/job/java.data-test-matrix/) ## Copyright and License @@ -167,7 +164,7 @@ Copyright (c) Rich Hickey and contributors. All rights reserved. The use and distribution terms for this software are covered by the [Eclipse Public License -1.0](http://opensource.org/licenses/eclipse-1.0.php) which can be +1.0](https://opensource.org/licenses/eclipse-1.0.php) which can be found in the file epl.html at the root of this distribution. By using this software in any fashion, you are agreeing to be bound by the terms of this license. You must not remove this notice, or any other, From 1bf0e08ba246bacae8ce76262b9c53830da5fec6 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Thu, 15 Apr 2021 15:57:46 -0500 Subject: [PATCH 070/101] update parent pom version to latest --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0bd2951..03a78ca 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ org.clojure pom.contrib - 1.0.0 + 1.1.0 From 4085ee0018e0d0b91ecfd13b4f40c4b28b08e4ae Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sat, 16 Oct 2021 23:18:21 -0700 Subject: [PATCH 071/101] 1.0.92 JDATA-22 support Properties/hash-map --- .gitignore | 9 ++++++++- CHANGELOG.md | 3 +++ README.md | 8 ++++---- src/main/clojure/clojure/java/data.clj | 10 ++++++++++ src/test/clojure/clojure/java/test_data.clj | 14 ++++++++++++++ 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 4f51760..dd5cb5d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,9 @@ -/target +.classpath +.clj-kondo/.cache .cpcache/ +.lsp/.cache +.portal +.project +.settings +.socket-repl-port +/target diff --git a/CHANGELOG.md b/CHANGELOG.md index 464a6dc..4027e19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## Change Log +* Release 1.0.92 on 2021-10-16 + * Support `to-java` for `java.util.Properties` and a hash map JDATA-22. + * Release 1.0.86 on 2020-07-17 * Add `from-java-deep` to guarantee deep conversion with same options as `from-java-shallow` [JDATA-21](https://clojure.atlassian.net/browse/JDATA-21). * Fixes bug in `from-java-shallow` for getters returning `Boolean` (the value was not canonicalized so `false` could be truthy). diff --git a/README.md b/README.md index 329c5fa..1a964fd 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ clojure-contrib This project follows the version scheme MAJOR.MINOR.COMMITS where MAJOR and MINOR provide some relative indication of the size of the change, but do not follow semantic versioning. In general, all changes endeavor to be non-breaking (by moving to new names rather than by breaking existing names). COMMITS is an ever-increasing counter of commits since the beginning of this repository. -Latest stable release: 1.0.86 +Latest stable release: 1.0.92 * [All Released Versions](https://search.maven.org/#search%7Cga%7C1%7Corg.clojure%20java.data) * [Development Snapshot Versions](https://repository.sonatype.org/index.html#nexus-search;gav~org.clojure~java.data~~~) @@ -16,13 +16,13 @@ Latest stable release: 1.0.86 ### [CLI/`deps.edn`](https://clojure.org/reference/deps_and_cli) dependency information: ```clojure -org.clojure/java.data {:mvn/version "1.0.86"} +org.clojure/java.data {:mvn/version "1.0.92"} ``` ### Leiningen ```clojure -[org.clojure/java.data "1.0.86"] +[org.clojure/java.data "1.0.92"] ``` ### Maven @@ -31,7 +31,7 @@ org.clojure/java.data {:mvn/version "1.0.86"} org.clojure java.data - 1.0.86 + 1.0.92 ``` diff --git a/src/main/clojure/clojure/java/data.clj b/src/main/clojure/clojure/java/data.clj index 213697e..45c42d3 100644 --- a/src/main/clojure/clojure/java/data.clj +++ b/src/main/clojure/clojure/java/data.clj @@ -249,6 +249,16 @@ (apply setter [instance value])))) instance)) +(defmethod to-java [java.util.Properties clojure.lang.APersistentMap] + [_ props] + (reduce-kv (fn [^java.util.Properties p k v] + (if (or (symbol? k) (keyword? k)) + (.setProperty p (name k) (str v)) + (.setProperty p (str k) (str v))) + p) + (java.util.Properties.) + props)) + (defmethod to-java [Object clojure.lang.APersistentMap] [^Class clazz props] (if (.isInterface clazz) (if (instance? clazz props) diff --git a/src/test/clojure/clojure/java/test_data.clj b/src/test/clojure/clojure/java/test_data.clj index 4da6da4..bcbc559 100644 --- a/src/test/clojure/clojure/java/test_data.clj +++ b/src/test/clojure/clojure/java/test_data.clj @@ -360,3 +360,17 @@ (is (= "Dallas" (.. person getAddress getCity))) (is (= State/TX (.. person getAddress getState))) (is (= "75432" (.. person getAddress getZip)))))) + +(deftest jdata-22 + (testing "Properties with String keys" + (let [props (to-java java.util.Properties {"a" 1 "b" "two"})] + (is (= #{"a" "b"} (.stringPropertyNames props))) + (is (= "1" (.getProperty props "a"))) + (is (= "two" (.getProperty props "b"))) + (is (= "nope" (.getProperty props "c" "nope"))))) + (testing "Properties with Keyword keys" + (let [props (to-java java.util.Properties {:a 1 :b "two"})] + (is (= #{"a" "b"} (.stringPropertyNames props))) + (is (= "1" (.getProperty props "a"))) + (is (= "two" (.getProperty props "b"))) + (is (= "nope" (.getProperty props "c" "nope")))))) From 1a4309f5d8bb06a6a4c3d8003fe60397b9dea811 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Sun, 17 Oct 2021 03:28:57 -0500 Subject: [PATCH 072/101] [maven-release-plugin] prepare release v1.0.92 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 03a78ca..967160d 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 1.0.87-SNAPSHOT + 1.0.92 java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - HEAD + v1.0.92 From b095fcbf017469b4718733dcbbbba19216957cd6 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Sun, 17 Oct 2021 03:28:57 -0500 Subject: [PATCH 073/101] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 967160d..d1fabdd 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 1.0.92 + 1.0.93-SNAPSHOT java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - v1.0.92 + HEAD From a4def8e2ef7403c7e985ab235762c0bd37db9e2d Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Sun, 12 Dec 2021 19:11:28 -0600 Subject: [PATCH 074/101] update to latest tools.logging 1.2.1 --- CHANGELOG.md | 3 +++ deps.edn | 2 +- pom.xml | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4027e19..16546f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## Change Log +* Next + * Update to latest tools.logging 1.2.1 + * Release 1.0.92 on 2021-10-16 * Support `to-java` for `java.util.Properties` and a hash map JDATA-22. diff --git a/deps.edn b/deps.edn index 2472694..3fe5c26 100644 --- a/deps.edn +++ b/deps.edn @@ -1,3 +1,3 @@ {:paths ["src/main/clojure"] :deps - {org.clojure/tools.logging {:mvn/version "1.1.0"}}} + {org.clojure/tools.logging {:mvn/version "1.2.1"}}} diff --git a/pom.xml b/pom.xml index d1fabdd..ae83ef4 100644 --- a/pom.xml +++ b/pom.xml @@ -34,7 +34,7 @@ org.clojure tools.logging - 1.1.0 + 1.2.1 From 2cc8e45ae8e0cf3bada98419c8f8a19fce069e9e Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Sun, 12 Dec 2021 19:27:41 -0600 Subject: [PATCH 075/101] [maven-release-plugin] prepare release v1.0.95 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ae83ef4..9ce523e 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 1.0.93-SNAPSHOT + 1.0.95 java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - HEAD + v1.0.95 From 76227b6ed728a5e601f8c7754fae1d9805c94720 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Sun, 12 Dec 2021 19:27:41 -0600 Subject: [PATCH 076/101] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9ce523e..9843784 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 1.0.95 + 1.0.96-SNAPSHOT java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - v1.0.95 + HEAD From aba3de206bb4990bed7fac63779679b32002e99f Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Sun, 12 Dec 2021 19:31:20 -0600 Subject: [PATCH 077/101] update for release --- CHANGELOG.md | 2 +- README.md | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16546f6..8754f39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ ## Change Log -* Next +* Release 1.0.95 on 2021-12-12 * Update to latest tools.logging 1.2.1 * Release 1.0.92 on 2021-10-16 diff --git a/README.md b/README.md index 1a964fd..a51b521 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ clojure-contrib This project follows the version scheme MAJOR.MINOR.COMMITS where MAJOR and MINOR provide some relative indication of the size of the change, but do not follow semantic versioning. In general, all changes endeavor to be non-breaking (by moving to new names rather than by breaking existing names). COMMITS is an ever-increasing counter of commits since the beginning of this repository. -Latest stable release: 1.0.92 +Latest stable release: 1.0.95 * [All Released Versions](https://search.maven.org/#search%7Cga%7C1%7Corg.clojure%20java.data) * [Development Snapshot Versions](https://repository.sonatype.org/index.html#nexus-search;gav~org.clojure~java.data~~~) @@ -16,13 +16,13 @@ Latest stable release: 1.0.92 ### [CLI/`deps.edn`](https://clojure.org/reference/deps_and_cli) dependency information: ```clojure -org.clojure/java.data {:mvn/version "1.0.92"} +org.clojure/java.data {:mvn/version "1.0.95"} ``` ### Leiningen ```clojure -[org.clojure/java.data "1.0.92"] +[org.clojure/java.data "1.0.95"] ``` ### Maven @@ -31,7 +31,7 @@ org.clojure/java.data {:mvn/version "1.0.92"} org.clojure java.data - 1.0.92 + 1.0.95 ``` From fdaca935959ed133fbb37b61af68c080f8677e81 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Fri, 26 May 2023 15:20:42 -0500 Subject: [PATCH 078/101] add actions --- .github/workflows/release.yml | 19 +++++++++++++++++++ .github/workflows/snapshot.yml | 8 ++++++++ .github/workflows/test.yml | 7 +++++++ README.md | 3 +-- 4 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/snapshot.yml create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..e2718bd --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,19 @@ +name: Release on demand + +on: + workflow_dispatch: + inputs: + releaseVersion: + description: "Version to release" + required: true + snapshotVersion: + description: "Snapshot version after release" + required: true + +jobs: + call-release: + uses: clojure/build.ci/.github/workflows/release.yml@master + with: + releaseVersion: ${{ github.event.inputs.releaseVersion }} + snapshotVersion: ${{ github.event.inputs.snapshotVersion }} + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml new file mode 100644 index 0000000..2472957 --- /dev/null +++ b/.github/workflows/snapshot.yml @@ -0,0 +1,8 @@ +name: Snapshot on demand + +on: [workflow_dispatch] + +jobs: + call-snapshot: + uses: clojure/build.ci/.github/workflows/snapshot.yml@master + secrets: inherit diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..1fa127c --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,7 @@ +name: Test + +on: [push] + +jobs: + call-test: + uses: clojure/build.ci/.github/workflows/test.yml@master diff --git a/README.md b/README.md index a51b521..5f8aaa8 100644 --- a/README.md +++ b/README.md @@ -155,8 +155,7 @@ exception defense | none | none * [GitHub project](https://github.com/clojure/java.data) * [Bug Tracker](https://clojure.atlassian.net/browse/JDATA) -* [Continuous Integration](https://build.clojure.org/job/java.data/) -* [Compatibility Test Matrix](https://build.clojure.org/job/java.data-test-matrix/) +* [Continuous Integration](https://github.com/clojure/java.data/actions/workflows/test.yml) ## Copyright and License From 5e3f667090b282590824a1e99334f6452f7d173f Mon Sep 17 00:00:00 2001 From: JarrodCTaylor Date: Wed, 16 Aug 2023 12:42:31 -0500 Subject: [PATCH 079/101] Added github action to build api docs --- .github/workflows/doc-build.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/workflows/doc-build.yml diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml new file mode 100644 index 0000000..bd38321 --- /dev/null +++ b/.github/workflows/doc-build.yml @@ -0,0 +1,10 @@ +name: Build API Docs + +on: + workflow_dispatch: + +jobs: + call-doc-build-workflow: + uses: clojure/build.ci/.github/workflows/doc-build.yml@master + with: + project: clojure/java.data From d5e6488decca560ad1955b7771c1ecc2cf4a33b6 Mon Sep 17 00:00:00 2001 From: JarrodCTaylor Date: Wed, 30 Aug 2023 22:25:12 -0500 Subject: [PATCH 080/101] Fix EPL license link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5f8aaa8..0724cbb 100644 --- a/README.md +++ b/README.md @@ -163,7 +163,7 @@ Copyright (c) Rich Hickey and contributors. All rights reserved. The use and distribution terms for this software are covered by the [Eclipse Public License -1.0](https://opensource.org/licenses/eclipse-1.0.php) which can be +1.0](https://opensource.org/license/epl-1-0/) which can be found in the file epl.html at the root of this distribution. By using this software in any fashion, you are agreeing to be bound by the terms of this license. You must not remove this notice, or any other, From b6db9f21cb9bcd51c85f969e4fb6f87175e1a69d Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sat, 16 Dec 2023 15:29:44 -0800 Subject: [PATCH 081/101] remove hard dependency on tools.logging --- .gitignore | 2 ++ CHANGELOG.md | 5 ++++- deps.edn | 4 +--- pom.xml | 1 + src/main/clojure/clojure/java/data.clj | 31 ++++++++++++++++++++++---- 5 files changed, 35 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index dd5cb5d..db53108 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,9 @@ +.calva/output-window .classpath .clj-kondo/.cache .cpcache/ .lsp/.cache +.nrepl-port .portal .project .settings diff --git a/CHANGELOG.md b/CHANGELOG.md index 8754f39..5ee8194 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,10 @@ ## Change Log +* Release 1.1.next in progress + * IMPORTANT: `org.clojure/tools.logging` is no longer a dependency. If you currently to bind `*to-java-object-missing-setter*` to `:log` and you do not otherwise have a dependency on `org.clojure/tools.logging` you will need to that to your project's direct dependencies. + * Release 1.0.95 on 2021-12-12 - * Update to latest tools.logging 1.2.1 + * Update `org.clojure/tools.logging` to `1.2.1`. * Release 1.0.92 on 2021-10-16 * Support `to-java` for `java.util.Properties` and a hash map JDATA-22. diff --git a/deps.edn b/deps.edn index 3fe5c26..3ffcee7 100644 --- a/deps.edn +++ b/deps.edn @@ -1,3 +1 @@ -{:paths ["src/main/clojure"] - :deps - {org.clojure/tools.logging {:mvn/version "1.2.1"}}} +{:paths ["src/main/clojure"]} diff --git a/pom.xml b/pom.xml index 9843784..fc4d993 100644 --- a/pom.xml +++ b/pom.xml @@ -35,6 +35,7 @@ org.clojure tools.logging 1.2.1 + test diff --git a/src/main/clojure/clojure/java/data.clj b/src/main/clojure/clojure/java/data.clj index 45c42d3..48dea8f 100644 --- a/src/main/clojure/clojure/java/data.clj +++ b/src/main/clojure/clojure/java/data.clj @@ -10,15 +10,22 @@ ^{:author "Cosmin Stejerean, Sean Corfield", :doc "Support for recursively converting Java beans to Clojure and vice versa."} clojure.java.data - (:require [clojure.string :as str] - [clojure.tools.logging :as logger])) + (:require [clojure.string :as str])) (set! *warn-on-reflection* true) (def ^:dynamic *to-java-object-missing-setter* "Specify the behavior of missing setters in to-java in the - default object case, using one of :ignore, :log, :error" + default object case, using one of :ignore, :log, :error + + The default (:ignore) is to ignore missing setters. + * :log uses clojure.tools.logging/info to log a message. + * :error throws a NoSuchFieldException. + + If you bind this to :log, you must have org.clojure/tools.logging + as a dependency in your project. Otherwise, :log will behave like + :error and throw a NoSuchFieldException." :ignore) (defmulti to-java @@ -203,12 +210,28 @@ (.invoke (.getDeclaredMethod enum "valueOf" (into-array [String])) nil (into-array [value]))) +(declare log-or-throw) +(defmacro defn-log-or-throw [] + (try + (require 'clojure.tools.logging) + `(defn ~'log-or-throw [message#] + (clojure.tools.logging/info message#)) + (catch Throwable _ + `(defn ~'log-or-throw [message#] + (throw (new NoSuchFieldException message#)))))) +(defn-log-or-throw) + (defn- throw-log-or-ignore-missing-setter [key ^Class clazz] (let [message (str "Missing setter for " key " in " (.getCanonicalName clazz))] (cond (= *to-java-object-missing-setter* :error) (throw (new NoSuchFieldException message)) (= *to-java-object-missing-setter* :log) - (logger/info message)))) + (log-or-throw message)))) + +(comment + (binding [*to-java-object-missing-setter* :log] + (throw-log-or-ignore-missing-setter :foo String)) + ) ;; feature testing macro, based on suggestion from Chas Emerick: From 61c0f4fe6893b7044fc4b6eb99b4c83db1eb994c Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sat, 16 Dec 2023 15:46:39 -0800 Subject: [PATCH 082/101] prep for 1.1.103 --- CHANGELOG.md | 2 +- README.md | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ee8194..1a80222 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ ## Change Log -* Release 1.1.next in progress +* Release 1.1.103 on 2023-12-16 * IMPORTANT: `org.clojure/tools.logging` is no longer a dependency. If you currently to bind `*to-java-object-missing-setter*` to `:log` and you do not otherwise have a dependency on `org.clojure/tools.logging` you will need to that to your project's direct dependencies. * Release 1.0.95 on 2021-12-12 diff --git a/README.md b/README.md index 0724cbb..1348bf4 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ clojure-contrib This project follows the version scheme MAJOR.MINOR.COMMITS where MAJOR and MINOR provide some relative indication of the size of the change, but do not follow semantic versioning. In general, all changes endeavor to be non-breaking (by moving to new names rather than by breaking existing names). COMMITS is an ever-increasing counter of commits since the beginning of this repository. -Latest stable release: 1.0.95 +Latest stable release: 1.1.103 * [All Released Versions](https://search.maven.org/#search%7Cga%7C1%7Corg.clojure%20java.data) * [Development Snapshot Versions](https://repository.sonatype.org/index.html#nexus-search;gav~org.clojure~java.data~~~) @@ -16,13 +16,13 @@ Latest stable release: 1.0.95 ### [CLI/`deps.edn`](https://clojure.org/reference/deps_and_cli) dependency information: ```clojure -org.clojure/java.data {:mvn/version "1.0.95"} +org.clojure/java.data {:mvn/version "1.1.103"} ``` ### Leiningen ```clojure -[org.clojure/java.data "1.0.95"] +[org.clojure/java.data "1.1.103"] ``` ### Maven @@ -31,7 +31,7 @@ org.clojure/java.data {:mvn/version "1.0.95"} org.clojure java.data - 1.0.95 + 1.1.103 ``` From 9f577b15ce40305d0239a7aa04541a9bd5096fc1 Mon Sep 17 00:00:00 2001 From: clojure-build Date: Sat, 16 Dec 2023 23:47:40 +0000 Subject: [PATCH 083/101] [maven-release-plugin] prepare release v1.1.103 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index fc4d993..756c235 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 1.0.96-SNAPSHOT + 1.1.103 java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - HEAD + v1.1.103 From 78f2ee6395272b3608ca67c68af081f57439b599 Mon Sep 17 00:00:00 2001 From: clojure-build Date: Sat, 16 Dec 2023 23:47:40 +0000 Subject: [PATCH 084/101] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 756c235..e36d7b2 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 1.1.103 + 1.1.104-SNAPSHOT java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - v1.1.103 + HEAD From 1db6b4772cf2ee4c7f869799b94813602678d898 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Tue, 26 Dec 2023 08:37:52 -0800 Subject: [PATCH 085/101] fix typos in changelog for 1.1.103 Signed-off-by: Sean Corfield --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a80222..27a68e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ ## Change Log * Release 1.1.103 on 2023-12-16 - * IMPORTANT: `org.clojure/tools.logging` is no longer a dependency. If you currently to bind `*to-java-object-missing-setter*` to `:log` and you do not otherwise have a dependency on `org.clojure/tools.logging` you will need to that to your project's direct dependencies. + * IMPORTANT: `org.clojure/tools.logging` is no longer a dependency. If you currently bind `*to-java-object-missing-setter*` to `:log` and you do not otherwise have a dependency on `org.clojure/tools.logging` you will need to add that to your project's direct dependencies. * Release 1.0.95 on 2021-12-12 * Update `org.clojure/tools.logging` to `1.2.1`. From a32f288fcc420a82f1331f9a5e295f149164fe19 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Mon, 19 Feb 2024 13:49:25 -0600 Subject: [PATCH 086/101] update parent pom and dep versions --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index e36d7b2..8e07a96 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ org.clojure pom.contrib - 1.1.0 + 1.2.0 @@ -34,7 +34,7 @@ org.clojure tools.logging - 1.2.1 + 1.3.0 test From 86dc80d897cf85a0b8238c5d46ce723d9afa6535 Mon Sep 17 00:00:00 2001 From: clojure-build Date: Mon, 19 Feb 2024 19:51:54 +0000 Subject: [PATCH 087/101] [maven-release-plugin] prepare release v1.2.107 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 8e07a96..85c12f5 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 1.1.104-SNAPSHOT + 1.2.107 java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - HEAD + v1.2.107 From 91016c87d4d46d735b93166c2688f1bb402c0e98 Mon Sep 17 00:00:00 2001 From: clojure-build Date: Mon, 19 Feb 2024 19:51:54 +0000 Subject: [PATCH 088/101] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 85c12f5..6b302cf 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 1.2.107 + 1.2.108-SNAPSHOT java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - v1.2.107 + HEAD From a01aa36ee0b2badd592c49f5938d34835804a5cd Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Mon, 19 Feb 2024 14:02:04 -0600 Subject: [PATCH 089/101] update for release --- CHANGELOG.md | 3 +++ README.md | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27a68e2..95024c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## Change Log +* Release 1.2.107 on 2024-02-19 + * Update parent pom and tools.logging versions + * Release 1.1.103 on 2023-12-16 * IMPORTANT: `org.clojure/tools.logging` is no longer a dependency. If you currently bind `*to-java-object-missing-setter*` to `:log` and you do not otherwise have a dependency on `org.clojure/tools.logging` you will need to add that to your project's direct dependencies. diff --git a/README.md b/README.md index 1348bf4..99a85ea 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ clojure-contrib This project follows the version scheme MAJOR.MINOR.COMMITS where MAJOR and MINOR provide some relative indication of the size of the change, but do not follow semantic versioning. In general, all changes endeavor to be non-breaking (by moving to new names rather than by breaking existing names). COMMITS is an ever-increasing counter of commits since the beginning of this repository. -Latest stable release: 1.1.103 +Latest stable release: 1.2.107 * [All Released Versions](https://search.maven.org/#search%7Cga%7C1%7Corg.clojure%20java.data) * [Development Snapshot Versions](https://repository.sonatype.org/index.html#nexus-search;gav~org.clojure~java.data~~~) @@ -16,13 +16,13 @@ Latest stable release: 1.1.103 ### [CLI/`deps.edn`](https://clojure.org/reference/deps_and_cli) dependency information: ```clojure -org.clojure/java.data {:mvn/version "1.1.103"} +org.clojure/java.data {:mvn/version "1.2.107"} ``` ### Leiningen ```clojure -[org.clojure/java.data "1.1.103"] +[org.clojure/java.data "1.2.107"] ``` ### Maven @@ -31,7 +31,7 @@ org.clojure/java.data {:mvn/version "1.1.103"} org.clojure java.data - 1.1.103 + 1.2.107 ``` From a8fe6608e53678356a5f451ea3841513f2444883 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sun, 24 Mar 2024 21:16:34 -0700 Subject: [PATCH 090/101] ignore new calva repl path and sort .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index db53108..023f853 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .calva/output-window +.calva/repl.calva-repl .classpath .clj-kondo/.cache .cpcache/ From 2f7e1c1c310308ec30eb03261f67ba1cbe3efed1 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Wed, 22 Jan 2025 15:56:37 -0800 Subject: [PATCH 091/101] fixes JDATA-24 and JDATA-25 Signed-off-by: Sean Corfield --- CHANGELOG.md | 4 ++ .../clojure/clojure/java/data/builder.clj | 59 ++++++++++++------- 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95024c4..3570b80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## Change Log +* Release 1.2.next in progress + * In builders, for overloaded setters (for which we have matching properties), try to pick the "obviously better" match (using `instance?` against the property value), and only throw if we can't pick one [JDATA-25](https://clojure.atlassian.net/browse/JDATA-25). + * In builders, ignore setters for which we do not have matching properties [JDATA-24](https://clojure.atlassian.net/browse/JDATA-24). + * Release 1.2.107 on 2024-02-19 * Update parent pom and tools.logging versions diff --git a/src/main/clojure/clojure/java/data/builder.clj b/src/main/clojure/clojure/java/data/builder.clj index 7ce4892..1bba3d0 100644 --- a/src/main/clojure/clojure/java/data/builder.clj +++ b/src/main/clojure/clojure/java/data/builder.clj @@ -43,7 +43,7 @@ (.getName clazz)))) (first builds)))))) -(defn- find-setters [^Class builder methods opts] +(defn- find-setters [^Class builder methods props opts] (let [candidates (filter (fn [^java.lang.reflect.Method m] (and (= 1 (alength ^"[Ljava.lang.Class;" (.getParameterTypes m))) @@ -51,23 +51,42 @@ (or (not (re-find #"^set[A-Z]" (.getName m))) (not (:ignore-setters? opts))))) methods)] - (reduce (fn [setter-map ^java.lang.reflect.Method m] - (let [prop (keyword - (cond (re-find #"^set[A-Z]" (.getName m)) - (let [^String n (subs (.getName m) 3)] - (str (Character/toLowerCase (.charAt n 0)) (subs n 1))) - (re-find #"^with[A-Z]" (.getName m)) - (let [^String n (subs (.getName m) 4)] - (str (Character/toLowerCase (.charAt n 0)) (subs n 1))) - :else - (.getName m)))] + (->> candidates + (reduce + (fn [setter-map ^java.lang.reflect.Method m] + (let [prop (keyword + (cond (re-find #"^set[A-Z]" (.getName m)) + (let [^String n (subs (.getName m) 3)] + (str (Character/toLowerCase (.charAt n 0)) (subs n 1))) + (re-find #"^with[A-Z]" (.getName m)) + (let [^String n (subs (.getName m) 4)] + (str (Character/toLowerCase (.charAt n 0)) (subs n 1))) + :else + (.getName m)))] + (if (contains? props prop) (if (contains? setter-map prop) - (throw (IllegalArgumentException. - (str "Duplicate setter found for " prop - " in " (.getName builder) " class"))) - (assoc setter-map prop (#'j/make-setter-fn m))))) - {} - candidates))) + (let [clazz1 (#'j/get-setter-type (second (get setter-map prop))) + clazz2 (#'j/get-setter-type m) + p-val (get props prop)] + (cond (and (instance? clazz1 p-val) + (not (instance? clazz2 p-val))) + setter-map ; existing setter is a better match: + (and (not (instance? clazz1 p-val)) + (instance? clazz2 p-val)) + ;; this setter is a better match: + (assoc setter-map prop [(#'j/make-setter-fn m) m]) + :else ; neither is an obviously better match: + (throw (IllegalArgumentException. + (str "Duplicate setter found for " prop + " in " (.getName builder) " class"))))) + (assoc setter-map prop [(#'j/make-setter-fn m) m])) + ;; if we are not trying to set this property, ignore the setter: + setter-map))) + {}) + (reduce-kv + (fn [m k v] + (assoc m k (first v))) + {})))) (defn- build-on [instance setters ^Class clazz props] (reduce-kv (fn [builder k v] @@ -94,7 +113,7 @@ ;; * B setPropertyName( T ) ;; treat both as setters; thrown exception if they clash ;; (maybe an option to ignore setXyz( T ) methods?) - (find-setters java.util.Locale$Builder (.getMethods java.util.Locale$Builder) {}) + (find-setters java.util.Locale$Builder (.getMethods java.util.Locale$Builder) {} {}) ;; general pattern will be to: ;; * get the builder class somehow @@ -113,7 +132,7 @@ ^Class builder (get-builder-class clazz)] (.invoke (get-builder clazz (.getMethods builder) opts) (build-on (j/to-java builder ^clojure.lang.APersistentMap {}) - (find-setters builder (.getMethods builder) opts) + (find-setters builder (.getMethods builder) props opts) builder props) nil))) @@ -161,7 +180,7 @@ ([^Class clazz ^Class builder instance props opts] (.invoke (get-builder clazz (.getMethods builder) opts) (build-on instance - (find-setters builder (.getMethods builder) opts) + (find-setters builder (.getMethods builder) props opts) builder props) nil))) From 9fc509100a17c4de1a26c0b36d981528f6b98a7c Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Wed, 22 Jan 2025 16:01:30 -0800 Subject: [PATCH 092/101] prep for 1.3.113 Signed-off-by: Sean Corfield --- CHANGELOG.md | 2 +- README.md | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3570b80..fbca448 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ ## Change Log -* Release 1.2.next in progress +* Release 1.3.113 on 2025-01-23 * In builders, for overloaded setters (for which we have matching properties), try to pick the "obviously better" match (using `instance?` against the property value), and only throw if we can't pick one [JDATA-25](https://clojure.atlassian.net/browse/JDATA-25). * In builders, ignore setters for which we do not have matching properties [JDATA-24](https://clojure.atlassian.net/browse/JDATA-24). diff --git a/README.md b/README.md index 99a85ea..29ab18a 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ clojure-contrib This project follows the version scheme MAJOR.MINOR.COMMITS where MAJOR and MINOR provide some relative indication of the size of the change, but do not follow semantic versioning. In general, all changes endeavor to be non-breaking (by moving to new names rather than by breaking existing names). COMMITS is an ever-increasing counter of commits since the beginning of this repository. -Latest stable release: 1.2.107 +Latest stable release: 1.3.113 * [All Released Versions](https://search.maven.org/#search%7Cga%7C1%7Corg.clojure%20java.data) * [Development Snapshot Versions](https://repository.sonatype.org/index.html#nexus-search;gav~org.clojure~java.data~~~) @@ -16,13 +16,13 @@ Latest stable release: 1.2.107 ### [CLI/`deps.edn`](https://clojure.org/reference/deps_and_cli) dependency information: ```clojure -org.clojure/java.data {:mvn/version "1.2.107"} +org.clojure/java.data {:mvn/version "1.3.113"} ``` ### Leiningen ```clojure -[org.clojure/java.data "1.2.107"] +[org.clojure/java.data "1.3.113"] ``` ### Maven @@ -31,7 +31,7 @@ org.clojure/java.data {:mvn/version "1.2.107"} org.clojure java.data - 1.2.107 + 1.3.113 ``` From 10dc90de2471fdc3f2ea06152a1d29164a65b320 Mon Sep 17 00:00:00 2001 From: clojure-build Date: Thu, 23 Jan 2025 00:03:35 +0000 Subject: [PATCH 093/101] [maven-release-plugin] prepare release v1.3.113 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 6b302cf..ef2ab96 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 1.2.108-SNAPSHOT + 1.3.113 java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - HEAD + v1.3.113 From 80c55b104f6d623c731b9d47e575e1ee08446fab Mon Sep 17 00:00:00 2001 From: clojure-build Date: Thu, 23 Jan 2025 00:03:35 +0000 Subject: [PATCH 094/101] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ef2ab96..cd9b380 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 1.3.113 + 1.3.114-SNAPSHOT java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - v1.3.113 + HEAD From 6218bae11cf29a14d746efd8a82da78e856f1ebc Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Thu, 20 Feb 2025 21:22:42 -0800 Subject: [PATCH 095/101] add note about difficult-to-convert Java types Signed-off-by: Sean Corfield --- README.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 29ab18a..148d4e8 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,18 @@ # java.data Functions for recursively converting Java beans to Clojure and vice -versa. Future home of Java beans and properties support from the old -clojure-contrib +versa. + +You can perform shallow conversions and deep conversions, and `java.data` +provides quite a bit of control over the conversion process. + +Conversion of Clojure maps etc to specific Java types is generally fairly +straightforward, either via regular construction or via "builder" APIs. + +Some Java types, however, are going to be difficult to convert to Clojure, +e.g., Protobuf is particularly problematic because it is all recursive metadata +about types and values: even when you use `:omit` to avoid deep recursion in +an automated conversion, you are not necessarily going to get a useful result. ## Releases and Dependency Information @@ -59,6 +69,11 @@ org.clojure/java.data {:mvn/version "1.3.113"} ;; represent a javaValue instance in a Clojure data structure: (j/from-java javaValue) +;; from-java is the legacy, default API and offers no control over the +;; conversion process; from-java-shallow and from-java-deep accept options +;; that provide control over which properties to omit, how to handle property +;; methods that fail, etc, and should be preferred over the default from-java + ;; populate javaValue instance from a Clojure property hash map ;; (calls a setter for each key/value pair in the hash map): (j/set-properties javaValue clojure-property-map) From 59ef3a2823756beeb33b119464f64d814c79f5dc Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Fri, 30 May 2025 15:06:01 -0500 Subject: [PATCH 096/101] update to new parent pom --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index cd9b380..6f23cd8 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ org.clojure pom.contrib - 1.2.0 + 1.3.0 From 2ff5a63de60b876faef827b51ffbee33dca6cb65 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Mon, 13 Oct 2025 12:05:31 -0500 Subject: [PATCH 097/101] Fix typo --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fbca448..a28f8d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,7 @@ * Fixes bug in `from-java-shallow` for getters returning `Boolean` (the value was not canonicalized so `false` could be truthy). * Release 1.0.78 on 2020-05-31 - * Make exception handling in shallow conversions configurable: an `:exceptions` option may be `:group`, `:omit`, `:quaify`, or `:return`. + * Make exception handling in shallow conversions configurable: an `:exceptions` option may be `:group`, `:omit`, `:qualify`, or `:return`. * Fix bug in shallow array handling. * Release 1.0.73 on 2020-05-31 From f7772746a36e9fe630f47804c4fdee0ffcd421cf Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Fri, 2 Jan 2026 08:56:53 -0600 Subject: [PATCH 098/101] update permissions in workflows --- .github/workflows/doc-build.yml | 3 +++ .github/workflows/release.yml | 3 +++ .github/workflows/snapshot.yml | 3 +++ .github/workflows/test.yml | 3 +++ 4 files changed, 12 insertions(+) diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index bd38321..3f9b981 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -1,5 +1,8 @@ name: Build API Docs +permissions: + contents: write + on: workflow_dispatch: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e2718bd..286cf95 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,5 +1,8 @@ name: Release on demand +permissions: + contents: write + on: workflow_dispatch: inputs: diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 2472957..9fdad8c 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -1,5 +1,8 @@ name: Snapshot on demand +permissions: + contents: read + on: [workflow_dispatch] jobs: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1fa127c..2cc441a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,5 +1,8 @@ name: Test +permissions: + contents: read + on: [push] jobs: From f843efd7eaade74aa87b8923946baaea40100569 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Fri, 2 Jan 2026 08:58:24 -0600 Subject: [PATCH 099/101] update to latest parent pom --- CHANGELOG.md | 3 +++ pom.xml | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a28f8d2..fdde6d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## Change Log +* next on 2026-01-02 + * Update parent pom and tools.logging versions + * Release 1.3.113 on 2025-01-23 * In builders, for overloaded setters (for which we have matching properties), try to pick the "obviously better" match (using `instance?` against the property value), and only throw if we can't pick one [JDATA-25](https://clojure.atlassian.net/browse/JDATA-25). * In builders, ignore setters for which we do not have matching properties [JDATA-24](https://clojure.atlassian.net/browse/JDATA-24). diff --git a/pom.xml b/pom.xml index 6f23cd8..73305db 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ org.clojure pom.contrib - 1.3.0 + 1.4.0 @@ -34,7 +34,7 @@ org.clojure tools.logging - 1.3.0 + 1.3.1 test From 442d65187aa0e9301703ff19d931e761e346b295 Mon Sep 17 00:00:00 2001 From: clojure-build Date: Fri, 2 Jan 2026 15:01:25 +0000 Subject: [PATCH 100/101] [maven-release-plugin] prepare release v1.4.120 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 73305db..8e89740 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 1.3.114-SNAPSHOT + 1.4.120 java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - HEAD + v1.4.120 From 71284f7dd12a854cbc385a26e9e908a1b0cf801f Mon Sep 17 00:00:00 2001 From: clojure-build Date: Fri, 2 Jan 2026 15:01:25 +0000 Subject: [PATCH 101/101] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 8e89740..71d1304 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 java.data - 1.4.120 + 1.4.121-SNAPSHOT java.data https://github.com/clojure/java.data/ @@ -27,7 +27,7 @@ scm:git:git@github.com:clojure/java.data.git scm:git:git@github.com:clojure/java.data.git git@github.com:clojure/java.data.git - v1.4.120 + HEAD