   [session module & {:keys [options variables types]}]
   (submit-request (.newModuleInvoke session module) session module options variables types))
 
+;;;;;
+
+(def valid-content-creation-options
+  "Set of valid creation options for Content objects. See
+  https://docs.marklogic.com/javadoc/xcc/com/marklogic/xcc/ContentCreateOptions.html" 
+  #{:buffer-size
+    :collections
+    :encoding
+    
+    :format
+    ;; The following keys correspond to convenience methods in Java
+    ;; that I don't currently find useful or idiomatic in Clojure:
+    ;; :format-binary :format-json :format-text :format-xml
+
+    :graph
+    :language
+    :locale
+    :namespace
+    :permissions
+    :placement-keys
+    :quality
+    :repair-level
+    :resolve-buffer-size
+    :resolve-entities
+    :temporal-collection})
+
+(defn- content-creation-options
+  "Creates a ContentCreateOptions object (to pass to a ContentFactory
+  newContent call) out of the given options map. See
+  `valid-content-creation-options` for supported keywords."
+  [options]
+  (let [cco (ContentCreateOptions.)]
+    (when-not (every? valid-content-creation-options (keys options))
+      ;; TODO switch to spec
+      (throw (IllegalArgumentException. "Invalid content creation option. Keywords passed in `options` must be a subset of `valid-content-creation-options`.")))
+    (when-let [bs (:buffer-size options)]
+      (.setBufferSize cco bs))
+    (when-let [c (:collections options)]
+      (.setCollections cco (into-array String c)))
+    (when-let [e (:encoding options)]
+      (.setEncoding cco e))
+    (when-let [f (:format options)]
+      (.setFormat cco (case f
+                        :xml    DocumentFormat/XML
+                        :json   DocumentFormat/JSON
+                        :text   DocumentFormat/TEXT
+                        :none   DocumentFormat/NONE
+                        :binary DocumentFormat/BINARY)))
+    
+    (when-let [g (:graph options)]
+      (.setGraph cco g))
+    (when-let [lang (:language options)]
+      (.setLanguage cco lang))
+    (when-let [locale (:locale options)]
+      (.setLocale cco locale))
+    (when-let [n (:namespace options)]
+      (.setNamespace cco n))
+    (when-let [permissions (:permissions options)]
+      (.setPermissions cco (into-array ContentPermission
+                                       (reduce (fn [permissions [role capability]]
+                                                 (conj permissions
+                                                       (ContentPermission.
+                                                        (case capability
+                                                          :execute ContentCapability/EXECUTE
+                                                          :insert  ContentCapability/INSERT
+                                                          :read    ContentCapability/READ
+                                                          :update  ContentCapability/UPDATE)
+                                                        role)))
+                                               []
+                                               permissions))))
+    
+    (when-let [pk (:placement-keys options)]
+      (.setPlaceKeys cco pk)) ;; FIXME bigint and long array casts?
+    (when-let [q (:quality options)]
+      (.setQuality cco q))
+    (when-let [rl (:repair-level options)]
+      (.setRepairLevel cco (case rl
+                             :default DocumentRepairLevel/DEFAULT
+                             :full    DocumentRepairLevel/FULL
+                             :none    DocumentRepairLevel/NONE)))
+    (when-let [rbs (:resolve-buffer-size options)]
+      (.setResolveBufferSize cco rbs))
+    (when-let [re (:resolve-entities options)]
+      (.setResolveEntities cco re))
+    (when-let [tc (:temporal-collection options)]
+      (.setTemporalCollection cco tc))
+    cco))
+
+(defn insert-content
+  [session content] ;; XXX Content object?
+  (.insertContent session content))
+
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;; Transactions

  conversion, transactions."
  (:require [clojure.data.json :as json])
  (:import [java.util.logging Logger]
           [com.marklogic.xcc ContentSourceFactory
            Session$TransactionMode
            RequestOptions]
           [com.marklogic.xcc.types ValueType]
           java.net.URI))




;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Working with sessions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defn submit-request
