    derived from the java.lang.reflect.Method(s). Overloaded
    methods will yield a variadic Clojure function."
   [client ns fname methods]
-  (intern ns (with-meta (symbol (name fname))
-               {:amazonica/client client
-                :amazonica/methods methods
-                :arglists (sort (map method-arglist methods))})
-          (fn [& args]
-            (if-let [method (best-method methods args)]
-              (if-not args
-                ((fn-call client method))
-                ((fn-call client method args)))
-              (throw (IllegalArgumentException.
-                      (format "Could not determine best method to invoke for %s using arguments %s"
-                              (name fname) args)))))))
+  (let [arglist (sort (map method-arglist methods))]
+   (intern ns (with-meta (symbol (name fname))
+                {:amazonica/client client
+                 :amazonica/methods methods
+                 :arglists arglist})
+           (fn [& args]
+             (if-let [method (best-method methods args)]
+               (if-not args
+                 ((fn-call client method))
+                 ((fn-call client method args)))
+               (throw (IllegalArgumentException.
+                       (format "Could not determine best method to invoke for %s using arguments %s"
+                               (name fname) args))))))))
+
+(defn generate-static-function
+  "Generate a wrapper function defintion"
+  [client fname methods]
+  (let [defn (symbol "defn")
+        class-prefix (str (.getName client) "/" )]
+   (with-out-str
+     (clojure.pprint/pprint
+      `(~defn ~(symbol (name fname))
+        ~@(map (fn [method args]
+                 `([~@args]
+                   (~(symbol (str class-prefix (.getName method))) ~@args)))
+               methods (map method-arglist methods)))))))
+
+(defn generate-function
+  "Generate a wrapper function defintion"
+  [client fname methods]
+  (let [defn (symbol "defn")
+        instance (symbol "instance")
+        type-hint (symbol (str "^" (.getName client)))]
+    (with-out-str
+      (clojure.pprint/pprint
+       `(~defn ~(symbol (name fname))
+         ~@(map (fn [method args]
+                  `([~type-hint ~instance ~@args]
+                    (. ~instance ~(symbol (.getName method)) ~@args)))
+                methods (map method-arglist methods)))))))
+
 
 (def ^:private camel->keyword2
   "Like [[camel->keyword]], but smarter about acronyms and concepts like iSCSI

                        credential
                        client-config)]))))

(swap! client-config assoc :transfer-manager-fn (memoize transfer-manager*))

(defn candidate-client
  [clazz args]
  (let [cred-bound (or *credentials* (:credential args))
        credential (if (map? cred-bound)
                             (merge @credential cred-bound)
                             (or cred-bound @credential))
        config-bound (or *client-config* (:client-config args))
        client-config (merge @client-config config-bound)
        encryption-client (:encryption-client-fn client-config)
        amazon-client (:amazon-client-fn client-config)
        transfer-manager (:transfer-manager-fn client-config)
        crypto (if (even? (count (:args args)))
                   (:encryption (apply hash-map (:args args))))
        client  (if (and crypto (or (= (.getSimpleName clazz) "AmazonS3Client")
                                    (= (.getSimpleName clazz) "TransferManager")))
                    (delay (encryption-client crypto credential client-config))
                    (delay (amazon-client clazz credential client-config)))]
        (if (= (.getSimpleName clazz) "TransferManager")
            (transfer-manager credential client-config crypto)
            @client)))


(defn- fn-call
  "Returns a function that reflectively invokes method on
   clazz with supplied args (if any). The 'method' here is
   the Java method on the Amazon*Client class."
  [clazz method & arg]
  (binding [*client-class* clazz]
    (let [args    (args-from arg)
          arg-arr (prepare-args method (:args args))
          client  (delay (candidate-client clazz args))]
      (fn []
        (try
          (let [java (.invoke method @client arg-arr)
                cloj (marshall java)]
            (if (and
                  @root-unwrapping
                  (map? cloj)
                  (= 1 (count (keys cloj))))
              (-> cloj first second)
              cloj))
          (catch InvocationTargetException ite
            (throw (.getTargetException ite))))))))


























   #(str/replace % #"(?i)iscsi" "ISCSI")
   #(str/replace % #"(?i)openid" "OPENID")))

#_
(defn set-client
  "Intern into the specified namespace all public methods
   from the Amazon*Client class as Clojure functions."
