   {:since "0.0.1"}
   [job-spec]
   (if (:doc job-spec)
-    (let [{:keys [doc ^PrintService printer attrs ^PrintJobtListener listener]
+    (let [{{doc-attrs :attrs} :doc} job-spec
+          {:keys [doc ^PrintService printer attrs ^PrintJobtListener listener]
            :or {printer (printer :default)
                 attrs #{MediaTray/MAIN}
                 listener listeners/basic}} job-spec]
-      (if (and (valid-attrs (:attrs (:job job-spec)) :doc)
+      (if (and (valid-attrs doc-attrs :doc)
                (valid-attrs attrs :job))
-        {:doc (assoc doc :obj (make-doc doc))
-         :printer printer
-         :attrs attrs
-         :listener listener
-         :job (doto (.. printer createPrintJob)
-                (.addPrintJobListener listener))}))))
+        (map->JobSpec {:doc (assoc doc :obj (make-doc doc))
+                       :printer printer
+                       :attrs attrs
+                       :listener listener
+                       :job (doto (.. printer createPrintJob)
+                              (.addPrintJobListener listener))})))))
 
 (defn submit
   "Submits the job object in job-spec for printing."

;;  :attrs #{(Copies. 5) MediaTray/MAIN}
;;  :listener listeners/basic}

(defn job
  "Returns a job-spec map that is the result of
   assoc'ing required values to it. The values are:

  "Returns a keyword representative of the document source's
   type."
  {:since "1.0"}
  [source]
  (cond (try (.. (io/file source) exists) (catch Throwable t)) :file
        (try (URL. source) (catch Throwable t)) :url
        :else nil))

(defn- choose-flavor
  "Attempts to guess the appropriate DocFlavor for the document.
   Returns nil if no suitable DocFlavor is found."
  {:since "1.0"}
  [source]
  (condp = (choose-source-key source)
    :file (:autosense flavors/input-streams)
    :url (:autosense flavors/urls)
    nil))
