Created
August 27, 2011 03:02
-
-
Save daveray/1174909 to your computer and use it in GitHub Desktop.
Generate match lookup for a Java class
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns match.pojo | |
(:use [match.core :only [IMatchLookup val-at* match]])) | |
(set! *warn-on-reflection* true) | |
(defmacro pojo-match | |
"Generate an implementation of match.core/IMatchLookup for the given Java class. | |
Keys are mapped like this: | |
isVisible -> :visible? | |
getText -> :text | |
" | |
[klass] | |
(let [pattern #"^(is|get)(.*)$" | |
method-names (->> (.getMethods ^Class (resolve klass)) | |
; Methods that have is/get naming | |
(filter (fn [^java.lang.reflect.Method m] | |
(re-find pattern (.getName m)))) | |
; Methods with no args | |
(filter (fn [^java.lang.reflect.Method m] | |
(= 0 (count (.getParameterTypes m))))) | |
; Grab name as a symbol | |
(map (fn [^java.lang.reflect.Method m] | |
(.getName m)))) | |
; TODO Convert camelcase to dashcase | |
keywordize (fn [^String s] | |
(let [[_ pre n] (re-find (re-matcher pattern s)) | |
n (apply str (Character/toLowerCase ^Character (first n)) (rest n)) | |
n (str n (if (= pre "is") "?"))] | |
(keyword n))) | |
this (gensym "this")] | |
`(extend-type ~klass | |
IMatchLookup | |
(~'val-at* [~this k# not-found#] | |
(case k# | |
~@(mapcat | |
(fn [n] [(keywordize n) `(. ~this ~(symbol n))]) | |
method-names) | |
not-found#))))) | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
(pojo-match java.util.Date) | |
(match [(java.util.Date. 2009 10 1 12 30)] | |
[{:year 2009 :month a}] a | |
[{:year (2010 | 2011) :month b}] b | |
:else :wrong) | |
;=> 10 | |
(pojo-match java.io.File) | |
(match [(java.io.File. ".")] | |
[{:directory? true :absolutePath p}] p | |
:else :wrong) | |
;=> /Users/dave/Documents/projects/match/. | |
(pojo-match java.awt.Point) | |
(match [(java.awt.Point. 1001 999)] | |
[{:x 1000 :y y}] y | |
[{:x x :y 999}] x | |
:else :wrong) | |
;=> 1001.0 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment