Skip to content

Commit

Permalink
Added support for arrays and primitives
Browse files Browse the repository at this point in the history
  • Loading branch information
bendlas authored and cosmin committed Oct 4, 2011
1 parent 0741494 commit 487db74
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 6 deletions.
46 changes: 41 additions & 5 deletions src/main/clojure/clojure/java/data.clj
Expand Up @@ -61,10 +61,23 @@
(assoc the-map (keyword name) (make-setter-fn method))
the-map)))

(defn- add-array-methods [acls]
(let [cls (.getComponentType acls)
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)
{:to to :from from}))

;; common to-java definitions

(defmethod to-java :default [_ value] value)
(defmethod to-java :default [^Class cls value]
(if (.isArray cls)
; no method for this array type yet
((:to (add-array-methods cls))
cls value)
value))

(defmethod to-java [Enum String] [enum value]
(.invoke (.getDeclaredMethod enum "valueOf" (into-array [String])) nil (into-array [value])))
Expand Down Expand Up @@ -92,16 +105,39 @@

;; common from-java definitions

(defmethod from-java Object [instance]
(defmethod from-java :default [^Object instance]
"Convert a Java object to a Clojure map"
(let [clazz (.getClass instance)
getter-map (reduce add-getter-fn {} (get-property-descriptors clazz))]
(into {} (for [[key getter-fn] (seq getter-map)] [key (getter-fn instance)]))))
(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)]))))))


(doseq [clazz [String Character Byte Short Integer Long Float Double Boolean BigInteger BigDecimal]]
(derive clazz ::do-not-convert))

(defmacro ^{:private true} defnumber [box prim prim-getter]
`(let [conv# (fn [_# number#]
(~(symbol (str box) "valueOf")
(. number# ~prim-getter)))]
(.addMethod to-java [~prim Number] conv#)
(.addMethod to-java [~box Number] conv#)))

(defmacro ^{:private true} defnumbers [& boxes]
(cons `do
(for [box boxes
:let [box-cls (resolve box)
prim-cls (.get (.getField box-cls "TYPE")
box-cls)
_ (assert (class? box-cls) (str box ": no class found"))
_ (assert (class? prim-cls) (str box " has no TYPE field"))
prim-getter (symbol (str (.getName prim-cls) "Value"))]]
`(defnumber ~box ~(symbol (str box) "TYPE") ~prim-getter))))

(defnumbers Byte Short Integer Long Float Double)

(defmethod from-java ::do-not-convert [value] value)
(prefer-method from-java ::do-not-convert Object)

Expand Down
24 changes: 23 additions & 1 deletion src/test/clojure/clojure/java/test_data.clj
Expand Up @@ -10,7 +10,7 @@
(:use clojure.java.data)
(:use [clojure.tools.logging :only (log* info)])
(:use clojure.test)
(:import (clojure.java.data.test Person Address State)))
(:import (clojure.java.data.test Person Address State Primitive)))

(deftest clojure-to-java
(let [person (to-java Person {:name "Bob"
Expand Down Expand Up @@ -58,3 +58,25 @@
(is (= 30 (:age person)))
(is (= "123 Main St" (:line1 (:address person))))
(is (= "TX" (:state (: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))))))
133 changes: 133 additions & 0 deletions src/test/java/clojure/java/data/test/Primitive.java
@@ -0,0 +1,133 @@
package clojure.java.data.test;

public class Primitive {
private boolean boolMember;
private boolean[] boolArray;
private char charMember;
private char[] charArray;

private byte byteMember;
private byte[] byteArray;
private short shortMember;
private short[] shortArray;
private int intMember;
private int[] intArray;
private long longMember;
private long[] longArray;
private float floatMember;
private float[] floatArray;
private double doubleMember;
private double[] doubleArray;

private int[][] nestedIntArray;
private String[] stringArray;

public boolean isBoolMember() {
return boolMember;
}
public void setBoolMember(boolean boolMember) {
this.boolMember = boolMember;
}
public boolean[] getBoolArray() {
return boolArray;
}
public void setBoolArray(boolean[] boolArray) {
this.boolArray = boolArray;
}
public char getCharMember() {
return charMember;
}
public void setCharMember(char charMember) {
this.charMember = charMember;
}
public char[] getCharArray() {
return charArray;
}
public void setCharArray(char[] charArray) {
this.charArray = charArray;
}
public byte getByteMember() {
return byteMember;
}
public void setByteMember(byte byteMember) {
this.byteMember = byteMember;
}
public byte[] getByteArray() {
return byteArray;
}
public void setByteArray(byte[] byteArray) {
this.byteArray = byteArray;
}
public short getShortMember() {
return shortMember;
}
public void setShortMember(short shortMember) {
this.shortMember = shortMember;
}
public short[] getShortArray() {
return shortArray;
}
public void setShortArray(short[] shortArray) {
this.shortArray = shortArray;
}
public int getIntMember() {
return intMember;
}
public void setIntMember(int intMember) {
this.intMember = intMember;
}
public int[] getIntArray() {
return intArray;
}
public void setIntArray(int[] intArray) {
this.intArray = intArray;
}
public long getLongMember() {
return longMember;
}
public void setLongMember(long longMember) {
this.longMember = longMember;
}
public long[] getLongArray() {
return longArray;
}
public void setLongArray(long[] longArray) {
this.longArray = longArray;
}
public float getFloatMember() {
return floatMember;
}
public void setFloatMember(float floatMember) {
this.floatMember = floatMember;
}
public float[] getFloatArray() {
return floatArray;
}
public void setFloatArray(float[] floatArray) {
this.floatArray = floatArray;
}
public double getDoubleMember() {
return doubleMember;
}
public void setDoubleMember(double doubleMember) {
this.doubleMember = doubleMember;
}
public double[] getDoubleArray() {
return doubleArray;
}
public void setDoubleArray(double[] doubleArray) {
this.doubleArray = doubleArray;
}
public int[][] getNestedIntArray() {
return nestedIntArray;
}
public void setNestedIntArray(int[][] nestedIntArray) {
this.nestedIntArray = nestedIntArray;
}
public String[] getStringArray() {
return stringArray;
}
public void setStringArray(String[] stringArray) {
this.stringArray = stringArray;
}
}

0 comments on commit 487db74

Please sign in to comment.