     (.put (get-datastore-service) entities)))
 
 
-(defn- make-query-object [kind ancestor filter sort keys-only?]
+
+;;; ----------------------------------------------------------------------------
+;;; query helper objects and functions
+;;; ----------------------------------------------------------------------------
+
+(defrecord QueryFilter [operator property value])
+
+
+(defrecord QuerySort [property direction])
+
+
+(defn- make-query-object [kind ancestor filters sorts keys-only?]
   (let [kind (cond (nil? kind) kind
                    (string? kind) kind
                    (extends? EntityProtocol kind) (unqualified-name kind)

             (throw err#))))))


(defn query [& {:keys [kind ancestor filter sort keys-only?
                       count-only? in-transaction?
                       limit offset
                       start-cursor end-cursor ; TODO: Implement this.
                       prefetch-size chunk-size]
                :or {keys-only? false, filter [[]], sort [[]],
                     count-only? false, in-transaction? false}}]
  (let [query-object (make-query-object kind ancestor filter sort keys-only?)
        fetch-options-object (make-fetch-options-object limit offset prefetch-size chunk-size)
        prepared-query (if (and in-transaction? *current-transaction*)
                           (.prepare (get-datastore-service) *current-transaction*

        query-object (cond (and (nil? kind) (nil? ancestor-key-object)) (Query.)
                           (nil? kind) (Query. ancestor-key-object)
                           (nil? ancestor-key-object) (Query. kind)
                           :else (Query. kind ancestor-key-object))]
    (when keys-only?
      (.setKeysOnly query-object))
    ;; prepare filters
    (doseq [current-filter filters]
      (let [filter-operator (:operator current-filter)
            filter-property-kw (:property current-filter)
            filter-value (:value current-filter)]
        (cond
         ;; valid filter provided
         (and (not (nil? filter-operator))
              (not (nil? filter-property-kw))
              (not (nil? filter-value))
              (keyword? filter-property-kw))
         (let [filter-property (.substring (str filter-property-kw) 1)]
           (.addFilter query-object filter-property filter-operator filter-value))
         ;; no filter definition
         (and (nil? filter-operator) (nil? filter-property-kw) (nil? filter-value))
         nil
         ;; invalid filter
         :else (throw (RuntimeException. "invalid filter specified in query")))))
    ;; prepare sorts
    (doseq [current-sort sorts]
      (let [sort-property-kw (:property current-sort)
            sort-direction (:direction current-sort)]
        (cond
         ;; valid sort provided
         (and (not (nil? sort-property-kw))
              (not (nil? sort-direction))
              (keyword? sort-property-kw))
         (let [sort-property (.substring (str sort-property-kw) 1)]
           (.addSort query-object sort-property sort-direction))
         ;; no sort definition
         (and (nil? sort-property-kw) (nil? sort-direction))
         nil
         ;; invalid sort
         :else (throw (RuntimeException. "invalid sort specified in query")))))
    query-object))


