blob: 9ad1f1065f9a43850e68061ff733945171c256e4 [file] [log] [blame]
;; Licensed to the Apache Software Foundation (ASF) under one
;; or more contributor license agreements. See the NOTICE file
;; distributed with this work for additional information
;; regarding copyright ownership. The ASF licenses this file
;; to you under the Apache License, Version 2.0 (the
;; "License"); you may not use this file except in compliance
;; with the License. You may obtain a copy of the License at
;;
;; http://www.apache.org/licenses/LICENSE-2.0
;;
;; Unless required by applicable law or agreed to in writing, software
;; distributed under the License is distributed on an "AS IS" BASIS,
;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;; See the License for the specific language governing permissions and
;; limitations under the License.
(ns org.apache.storm.util
(:import [java.util Map List HashMap])
(:import [org.apache.storm.generated ErrorInfo])
(:import [org.apache.storm.utils Utils])
(:import [java.util List Set])
(:use [clojure walk])
(:use [org.apache.storm log]))
;; name-with-attributes by Konrad Hinsen:
(defn name-with-attributes
"To be used in macro definitions.
Handles optional docstrings and attribute maps for a name to be defined
in a list of macro arguments. If the first macro argument is a string,
it is added as a docstring to name and removed from the macro argument
list. If afterwards the first macro argument is a map, its entries are
added to the name's metadata map and the map is removed from the
macro argument list. The return value is a vector containing the name
with its extended metadata map and the list of unprocessed macro
arguments."
[name macro-args]
(let [[docstring macro-args] (if (string? (first macro-args))
[(first macro-args) (next macro-args)]
[nil macro-args])
[attr macro-args] (if (map? (first macro-args))
[(first macro-args) (next macro-args)]
[{} macro-args])
attr (if docstring
(assoc attr :doc docstring)
attr)
attr (if (meta name)
(conj (meta name) attr)
attr)]
[(with-meta name attr) macro-args]))
(defmacro defnk
"Define a function accepting keyword arguments. Symbols up to the first
keyword in the parameter list are taken as positional arguments. Then
an alternating sequence of keywords and defaults values is expected. The
values of the keyword arguments are available in the function body by
virtue of the symbol corresponding to the keyword (cf. :keys destructuring).
defnk accepts an optional docstring as well as an optional metadata map."
[fn-name & fn-tail]
(let [[fn-name [args & body]] (name-with-attributes fn-name fn-tail)
[pos kw-vals] (split-with symbol? args)
syms (map #(-> % name symbol) (take-nth 2 kw-vals))
values (take-nth 2 (rest kw-vals))
sym-vals (apply hash-map (interleave syms values))
de-map {:keys (vec syms) :or sym-vals}]
`(defn ~fn-name
[~@pos & options#]
(let [~de-map (apply hash-map options#)]
~@body))))
(defmacro thrown-cause?
[klass & body]
`(try
~@body
false
(catch Throwable t#
(let [tc# (Utils/exceptionCauseIsInstanceOf ~klass t#)]
(if (not tc#) (log-error t# "Exception did not match " ~klass))
tc#))))
(defn clojurify-structure
[s]
(if s
(prewalk (fn [x]
(cond (instance? Map x) (into {} x)
(instance? List x) (vec x)
(instance? Set x) (into #{} x)
;; (Boolean. false) does not evaluate to false in an if.
;; This fixes that.
(instance? Boolean x) (boolean x)
true x))
s)))
; move this func form convert.clj due to cyclic load dependency
(defn clojurify-error [^ErrorInfo error]
(if error
{
:error (.get_error error)
:time-secs (.get_error_time_secs error)
:host (.get_host error)
:port (.get_port error)
}
))
;TODO: We're keeping this function around until all the code using it is properly tranlated to java
;TODO: by properly having the for loop IN THE JAVA FUNCTION that originally used this function.
(defn map-val
[afn amap]
(into {}
(for [[k v] amap]
[k (afn v)])))
;TODO: We're keeping this function around until all the code using it is properly tranlated to java
;TODO: by properly having the for loop IN THE JAVA FUNCTION that originally used this function.
(defn filter-key
[afn amap]
(into {} (filter (fn [[k v]] (afn k)) amap)))
;TODO: Once all the other clojure functions (100+ locations) are translated to java, this function becomes moot.
(def not-nil? (complement nil?))
(defmacro dofor [& body]
`(doall (for ~@body)))
(defmacro -<>
([x] x)
([x form] (if (seq? form)
(with-meta
(let [[begin [_ & end]] (split-with #(not= % '<>) form)]
(concat begin [x] end))
(meta form))
(list form x)))
([x form & more] `(-<> (-<> ~x ~form) ~@more)))
(defn hashmap-to-persistent [^HashMap m]
(zipmap (.keySet m) (.values m)))