Skip to content

Instantly share code, notes, and snippets.

@daveray
Created August 27, 2011 03:02
Show Gist options
  • Save daveray/1174909 to your computer and use it in GitHub Desktop.
Save daveray/1174909 to your computer and use it in GitHub Desktop.
Generate match lookup for a Java class
(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