 ;;--------------------------------------------------------------------------------
 ;; impl
 
-(defn- lhs-upsert [old-indeces i ks v]
-  (let [old-index (nth old-indeces i)
-	new-index (mapv (fn [index key] (group index (key v) v)) old-index ks)
-	new-indeces (assoc old-indeces i new-index)]
+;; TODO: return a pair - first is notification fn, second is new-indeces - use swap*! to apply
+
+(defn- derive-joins [v rhs-indeces ks join-fn]
+  (map
+   (fn [args] (apply join-fn v args))
+   (permute [[]] (map (fn [index key] (index (key v))) rhs-indeces ks))))
+
+(defn- lhs-upsert [[old-index & rhs-indeces] ks v join-fn]
+  (let [new-index (mapv (fn [index key] (group index (key v) v)) old-index ks)
+	new-indeces (apply vector new-index rhs-indeces)]
+    (println "JOINS: " (derive-joins v rhs-indeces ks)		;TODO: what should we do with this ?
     new-indeces))
 
 ;;; TODO

  (is (= (->ACE :a 0 :c :e) 
	 (join-ace (->A :a 0 :b :d)(->B :b 0 :c)(->D :d 0 :e)))))

(deftest test-join-model
  (let [as (versioned-optimistic-map-model (str :as) :name :version >)
	bs (versioned-optimistic-map-model (str :bs) :name :version >)

(defn- lhs-upserts [old-indeces i k vs])
(defn- lhs-deletes [old-indeces i k vs])

(defn- lhs-view [indeces i keys join-fn]
  (reify
   View
   ;; singleton changes
   (on-upsert [_ upsertion] (swap! indeces lhs-upsert keys upsertion join-fn) nil)
   (on-delete [_ deletion]  (swap! indeces lhs-delete i keys deletion) nil)
   ;; batch changes
   (on-upserts [_ upsertions] (swap! indeces lhs-upserts i keys upsertions) nil)
   (on-deletes [_ deletions]  (swap! indeces lhs-deletes i keys deletions) nil)))

;; TODO: return a pair - first is notification fn, second is new-indeces - use swap*! to apply

(defn- rhs-upsert [old-indeces i k v]
  (let [old-index (nth old-indeces i)
