Skip to content

Instantly share code, notes, and snippets.

@svdberg
Created March 1, 2012 08:43
Show Gist options
  • Save svdberg/1948393 to your computer and use it in GitHub Desktop.
Save svdberg/1948393 to your computer and use it in GitHub Desktop.
Clojure property resolver
(ns propertyresolver.core
(:refer-clojure :exclude [char])
( :require [ clojure.java.io])
( :use [the.parsatron]))
(defn load-properties [file-name]
(with-open [^java.io.Reader reader (clojure.java.io/reader file-name)]
(let [props (java.util.Properties.)]
(.load props reader)
(into {} (for [[k v] props] [(keyword k) v])))))
(defn load-multiple-properties [paths]
(let [maps (map load-properties paths)]
(merge maps)))
(defparser valid-name-char []
(choice (char \.)
(digit)
(letter)
(char \:)
))
(defparser propertyText []
(choice (char \ )
(char \:)
(letter)
(digit)))
(defparser literal []
(bind
(many1 (propertyText))
(fn [x] (always (clojure.string/join x)))))
(defparser placeholderOpen []
(char \$)
(char \{))
(defparser placeholder []
(bind
(between (placeholderOpen) (char \}) (many1 (valid-name-char)))
(fn [x] (always (str "${" (clojure.string/join x) "}")))))
(defparser property []
(either (placeholder) (literal)))
(defparser properties []
(many1 (property)))
;; A property is:
;; Property => (Literal|Placeholder)+
;; Literal => [A-Za-z.]+
;; PlaceHolder => "${" [A-Za-z0-9.] "}"
(defn parseProperties
"inputstring is a property"
[inputstring]
(run (properties) inputstring))
(defn to_name
"strips off the ${ and }"
[tok]
(let [ pf (drop 2 tok)
takenr (- (count pf) 1)
final (take takenr pf)]
(clojure.string/join final)))
(defn is_keyword [s]
(= (take 2 s) [\$ \{]))
; rebuild the token to the key..
; tokens is a list of lists! flatten..
(defn replace-placeholder [val lookupmap]
(let [tokens (flatten (parseProperties val))]
(clojure.string/join (map #(if (is_keyword %) (replace-placeholder ((keyword (to_name %)) lookupmap) lookupmap) %) tokens))))
(defn expand-placeholders [amap lookupmap]
(let [ keys (keys amap)
new-vals (map #(replace-placeholder % lookupmap) (vals amap))]
(zipmap keys new-vals)))
;;replacement should be recursive to catch chained references
(defn replacep []
(let [properties (load-properties "resources/prod.properties")]
(expand-placeholders properties properties)))
@mrijk
Copy link

mrijk commented Mar 1, 2012

Ziet er strak uit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment