Skip to content
Browse files

initial commit

  • Loading branch information...
0 parents commit 0fb4b5a0f29e70c72e038a27d589f995add0de7e @ngrunwald committed May 25, 2012
Showing with 126 additions and 0 deletions.
  1. +10 −0 .gitignore
  2. +15 −0 README.md
  3. +7 −0 project.clj
  4. +87 −0 src/gavagai/core.clj
  5. +7 −0 test/gavagai/core_test.clj
10 .gitignore
@@ -0,0 +1,10 @@
+/target
+/lib
+/classes
+/checkouts
+pom.xml
+*.jar
+*.class
+.lein-deps-sum
+.lein-failures
+.lein-plugins
15 README.md
@@ -0,0 +1,15 @@
+# gavagai
+
+I'm an app. Or maybe I'm a library? I haven't decided yet.
+
+The choice is up to you!
+
+## Usage
+
+FIXME
+
+## License
+
+Copyright © 2012 FIXME
+
+Distributed under the Eclipse Public License, the same as Clojure.
7 project.clj
@@ -0,0 +1,7 @@
+(defproject gavagai "0.1.0-SNAPSHOT"
+ :description ""
+ :url "https://github.com/ngrunwald/gavagai"
+ :license {:name "Eclipse Public License"
+ :url "http://www.eclipse.org/legal/epl-v10.html"}
+ :dependencies [[org.clojure/clojure "1.4.0"]
+ [de.kotka/lazymap "3.0.0"]])
87 src/gavagai/core.clj
@@ -0,0 +1,87 @@
+(ns gavagai.core
+ (:use [lazymap.core])
+ (:require [clojure.string :as str])
+ (:import [java.beans Introspector]))
+
+(defprotocol Clojurable
+ "Protocol for conversion of Classes"
+ (convert [response] "convert response to Clojure"))
+
+(defn- method->arg
+ [method]
+ (let [name (.getName method)
+ typ (.getReturnType method)
+ conv (str/replace name #"^get" "")
+ norm (str/lower-case (str/replace conv #"(\p{Lower})(\p{Upper})" "$1-$2"))
+ full (if (= (.getName typ) "boolean") (-> norm (str "?") (str/replace #"^is-" "")) norm)]
+ (keyword full)))
+
+(defn get-read-methods
+ [klass]
+ (reduce (fn [acc ^java.beans.PropertyDescriptor pd]
+ (let [method (.getReadMethod pd)]
+ (if (and method
+ (zero? (alength (.getParameterTypes method))))
+ (conj acc method)
+ acc)))
+ #{}
+ (seq (.. Introspector
+ (getBeanInfo klass)
+ (getPropertyDescriptors)))))
+
+(defn- translate-value
+ [src]
+ (try
+ (cond
+ (or (nil? src) (number? src) (string? src) (coll? src) (true? src) (false? src)) src
+ (instance? java.util.Map src) (persistent! (reduce (fn [acc ^java.util.Map$Entry e]
+ (assoc! acc
+ (translate-value (.getKey e))
+ (translate-value (.getValue e))))
+ (transient {}) src))
+ (or (instance? java.util.List src)
+ (.startsWith (.getName (type src)) "[L")) (persistent! (reduce
+ (fn [acc obj]
+ (conj! acc (translate-value obj)))
+ (transient []) src))
+ (extends? Clojurable (class src)) (convert src)
+ :else src)
+ (catch Exception e
+ (println e)
+ src)))
+
+(defmacro make-converter
+ [class-name]
+ (let [klass (Class/forName class-name)
+ read-methods (get-read-methods klass)
+ sig (reduce (fn [acc m]
+ (let [m-name (.getName m)]
+ (assoc acc
+ (keyword (method->arg m))
+ (symbol (str "." m-name)))))
+ {} read-methods)
+ return (gensym "return")]
+ `(fn
+ [~(with-meta return {:tag klass})]
+ (let [res# (lazy-hash-map
+ ~@(let [gets (for [[kw getter] sig]
+ `(~kw (translate-value (~getter ~return))))]
+ (apply concat gets)))]
+ res#))))
+
+(defmacro register-converters
+ ^{:private true}
+ [& conv-defs]
+ `(do ~@(for [class-name conv-defs]
+ `(let [conv# (make-converter ~class-name)]
+ (extend ~(symbol class-name)
+ Clojurable
+ {:convert (fn [return#]
+ (conv# return#))})))))
+
+(def-converters
+ "java.lang.reflect.Method"
+ "java.lang.annotation.Annotation"
+ "java.util.concurrent.ThreadPoolExecutor"
+ "java.util.concurrent.LinkedBlockingQueue")
+
7 test/gavagai/core_test.clj
@@ -0,0 +1,7 @@
+(ns gavagai.core-test
+ (:use clojure.test
+ gavagai.core))
+
+(deftest a-test
+ (testing "FIXME, I fail."
+ (is (= 0 1))))

0 comments on commit 0fb4b5a

Please sign in to comment.
Something went wrong with that request. Please try again.