<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -91,5 +91,16 @@
     (is (= (consumer &quot;id&quot;) &quot;103&quot;))
     (is (= (merchant &quot;name&quot;) &quot;portable chairs&quot;))))
 
-(def sku-string &quot;{\&quot;merchant\&quot;: {\&quot;id\&quot;: 11, \&quot;name\&quot;: \&quot;portable chairs\&quot;}, \&quot;active_campaigns\&quot;: [3, 4, 7, 10, 11, 13], \&quot;consumer\&quot;: {\&quot;kind\&quot;: \&quot;visitor\&quot;, \&quot;id\&quot;: 103, \&quot;email_address\&quot;: \&quot;f80a2173-5923-264f-e2d5-cb0f96220220@visitor.cinchcorp.com\&quot;}, \&quot;session\&quot;: {\&quot;uber_session_id\&quot;: \&quot;a96ec02e-0fd3-b030-c14a-1761ffe7d45b\&quot;, \&quot;merchant_session_id\&quot;: \&quot;3c0e276524dc843debaebfd9506138ee\&quot;, \&quot;cinch_session_id\&quot;: \&quot;42e00dc0eae2706a75eee1c1964d4d43\&quot;}, \&quot;api\&quot;: \&quot;0.0.1.0\&quot;, \&quot;inserts\&quot;: [{\&quot;cinch_unit_price\&quot;: 36.95, \&quot;campaign_id\&quot;: -1, \&quot;html_id\&quot;: \&quot;cinch_id_1231729409882\&quot;, \&quot;merchant_product_id\&quot;: \&quot;SS-REG\&quot;, \&quot;sku\&quot;: \&quot;SS-REG Black XL\&quot;, \&quot;merchant_unit_price\&quot;: 36.95, \&quot;insert_type\&quot;: \&quot;campaign\&quot;}]}&quot;)
-(def sku-object (json/decode-from-str sku-string))
\ No newline at end of file
+(def cart-string 
+     &quot;{\&quot;event_type\&quot;: \&quot;cart\&quot;, \&quot;api\&quot;: \&quot;0.0.1.0\&quot;, \&quot;session\&quot;: {\&quot;cinch_session_id\&quot;: \&quot;1948c2cef48e58a6c1f215a545512077\&quot;, \&quot;merchant_session_id\&quot;: \&quot;b768e9911893b91b279e08ac8efde20f\&quot;, \&quot;uber_session_id\&quot;: \&quot;ee2bcc43-dae9-e0f0-40e8-325f96b5f114\&quot;}, \&quot;cart_items\&quot;: [{\&quot;campaign_id\&quot;: -1, \&quot;merchant_product_id\&quot;: \&quot;EZ-30DC-HD\&quot;, \&quot;merchant_unit_price\&quot;: 109.95, \&quot;options\&quot;: null, \&quot;name\&quot;: null, \&quot;cinch_unit_price\&quot;: 109.95, \&quot;sku\&quot;: \&quot;EZ-30DC-HD (Yellow) XX\&quot;, \&quot;quantity\&quot;: 1, \&quot;description\&quot;: null}, {\&quot;campaign_id\&quot;: -1, \&quot;merchant_product_id\&quot;: \&quot;OB-BW-LNGR\&quot;, \&quot;merchant_unit_price\&quot;: 229.95, \&quot;options\&quot;: null, \&quot;name\&quot;: null, \&quot;cinch_unit_price\&quot;: 229.95, \&quot;sku\&quot;: \&quot;OB-BW-LNGR (RED) LL\&quot;, \&quot;quantity\&quot;: 1, \&quot;description\&quot;: null}], \&quot;page\&quot;: {\&quot;merchant_template_name\&quot;: \&quot;index\&quot;, \&quot;referrer\&quot;: \&quot;http://chairs.vasanta.hq.cinchcorp.com/shopping_cart.html?number_of_uploads=0\&quot;, \&quot;request_url\&quot;: \&quot;http://chairs.vasanta.hq.cinchcorp.com/hanging-chairs-c-23.html\&quot;}, \&quot;cart\&quot;: {\&quot;checkout_state\&quot;: 1}, \&quot;merchant\&quot;: {\&quot;name\&quot;: \&quot;Portable Folding Chairs\&quot;, \&quot;id\&quot;: 14}, \&quot;http_client\&quot;: {\&quot;browser_version\&quot;: \&quot;3\&quot;, \&quot;operating_system\&quot;: \&quot;Macintosh\&quot;, \&quot;operating_system_version\&quot;: \&quot;OS X\&quot;, \&quot;ip_address\&quot;: \&quot;192.168.10.10\&quot;, \&quot;browser\&quot;: \&quot;Safari\&quot;}, \&quot;active_campaigns\&quot;: [3, 4, 7, 10, 11, 13], \&quot;consumer\&quot;: {\&quot;email_address\&quot;: \&quot;afd4cb68-bb3b-e51f-ac2a-cb6eefce528f@visitor.cinchcorp.com\&quot;, \&quot;kind\&quot;: \&quot;visitor\&quot;, \&quot;id\&quot;: 103}}&quot;)
+(def cart-object (json/decode-from-str cart-string))
+
+(deftest test-flatten-with-sku 
+  (let [flattened (flatten cart-object)
+	hydrated (hydrate flattened)
+	cart-items (hydrated &quot;cart_items&quot;)
+	cart-item (first cart-items)]
+    (is (= (count cart-items) 2))
+    (is (= (cart-item &quot;sku&quot;) &quot;OB-BW-LNGR (RED) LL&quot;))
+    (is (= (cart-item &quot;merchant_product_id&quot;) &quot;OB-BW-LNGR&quot;))))
+	     
\ No newline at end of file</diff>
      <filename>spec/org/rathore/amit/capjure_spec.clj</filename>
    </modified>
    <modified>
      <diff>@@ -1,27 +1,52 @@
 (use 'clojure.contrib.test-is)
-(import '(java.net URLEncoder))
+(import '(java.net URLEncoder URLDecoder))
 (load-file &quot;spec/org/rathore/amit/capjure_spec.clj&quot;)
 
-
 (in-ns 'capjure-spec)
 (println &quot;**************** running tests ******************&quot;)
 
-;(def keys-config 
-;     {:inserts :merchant_product_id
-;      :cart_items :merchant_product_id
-;      :latest_consumer :merchant_id})
+(defstruct key-config :qualifier :functor)
+(defn add-key-config [keys-config name qualifier functor]
+  (assoc keys-config name (struct key-config qualifier functor)))
+(defn encode-keys []
+  (let [keys-config {}
+	keys-config (add-key-config keys-config 
+				    :inserts :merchant_product_id 
+				    (fn [insert-map]
+				      (insert-map :merchant_product_id)))
+	keys-config (add-key-config keys-config 
+				    :latest_consumer :merchant_id 
+				    (fn [consumer-map]
+				      (consumer-map :merchant_id)))
+	keys-config (add-key-config keys-config 
+				    :cart_items 
+				    :merchant_product_id (fn [cart-item-map]
+							   (let [sku (cart-item-map :sku)
+								 m-pid (cart-item-map :merchant_product_id)]
+							     (cond
+							      (nil? sku) m-pid
+							      :else (str m-pid &quot;@&quot; (URLEncoder/encode sku &quot;UTF-8&quot;))))))]
+    keys-config))
+
+(defn decode-keys []
+  (let [keys-config {}
+	keys-config (add-key-config keys-config 
+				    :inserts :merchant_product_id 
+				    (fn [value] value))
+	keys-config (add-key-config keys-config 
+				    :latest_consumer :merchant_id 
+				    (fn [value] value))
+	keys-config (add-key-config keys-config 
+				    :cart_items 
+				    :merchant_product_id (fn [value]
+							   (cond
+							      (.contains value &quot;@&quot;) (first (.split (URLDecoder/decode value &quot;UTF-8&quot;) &quot;@&quot;))
+							      :else value)))]
+    keys-config))
+
+(def keys-config {:encode (encode-keys) :decode (decode-keys)})
 
 (binding [*hbase-master* &quot;tank.cinchcorp.com:60000&quot;
 	  *primary-keys-config* keys-config]
-  (run-tests))
+  (run-tests)
   (shutdown-agents))
-
-(def keys-config {
-    :inserts (fn [insert-map]
-	     (insert-map :merchant_product_id))
-    :latest_consumer (fn [consumer-map]
-	      (consumer-map :merchant_id))
-    :cart_items (fn [cart-item-map]
-		  (str (cart-item-map :merchant_product_id) &quot;@&quot; (URLEncoder/encode (cart-item-map :sku))))})
-
-;create struct to track primary key, and function associated with it
\ No newline at end of file</diff>
      <filename>spec_suite.clj</filename>
    </modified>
    <modified>
      <diff>@@ -4,11 +4,28 @@
 	'(org.apache.hadoop.hbase.client HTable Scanner)
 	'(org.apache.hadoop.hbase.io BatchUpdate Cell))
 
-
 (def *mock-mode* false)
 (def *hbase-master* &quot;localhost:60000&quot;)
 (def *primary-keys-config* {})
 
+(declare symbol-name)
+(defn encoding-keys []
+  (*primary-keys-config* :encode))
+(defn decoding-keys []
+  (*primary-keys-config* :decode))
+(defn qualifier-for [key-name]
+  (((encoding-keys) key-name) :qualifier))
+(defn encoding-functor-for [key-name]
+  (((encoding-keys) key-name) :functor))
+(defn all-primary-keys []
+  (map #(symbol-name %) (keys (encoding-keys))))
+(defn primary-key [column-family]
+  (first (filter #(.startsWith column-family (str %)) (all-primary-keys))))
+(defn decoding-functor-for [key-name]
+  (((decoding-keys) (keyword key-name)) :functor))
+(defn decode-with-key [key-name value]
+  ((decoding-functor-for key-name) value))
+
 (declare flatten add-to-insert-batch capjure-insert hbase-table read-row read-cell)
 (defn capjure-insert [object-to-save hbase-table-name row-id]
   (let [table (hbase-table hbase-table-name)
@@ -63,10 +80,11 @@
      :else (process-strings key (to-array all)))))
 
 (defn process-maps [key maps]
-  (let [qualifier (*primary-keys-config* key)]
+  (let [qualifier (qualifier-for key)
+	encoding-functor (encoding-functor-for key)]
     (apply merge (map 
 		  (fn [single-map]
-		    (process-map (symbol-name key) (single-map qualifier) (dissoc single-map qualifier)))
+		    (process-map (symbol-name key) (encoding-functor single-map) (dissoc single-map qualifier)))
 		  maps))))
 
 (defn process-map [initial-prefix final-prefix single-map]
@@ -87,17 +105,10 @@
 		(seq bloated_object))))
 
 (declare read-as-hash cell-value-as-string hydrate-pair has-many-strings-hydration has-many-objects-hydration has-one-string-hydration has-one-object-hydration collapse-for-hydration)
-
-(defn all-primary-keys []
-  (map #(symbol-name %) (keys *primary-keys-config*)))
-
 (defn is-from-primary-keys [key-name]
   (let [key-name-str (symbol-name key-name)]
     (some #(.startsWith key-name-str %) (all-primary-keys))))
 
-(defn primary-key [column-family]
-  (first (filter #(.startsWith column-family (str %)) (all-primary-keys))))
-
 (defn column-name-empty? [key-name]
   (= 1 (count (.split key-name &quot;:&quot;))))
 
@@ -144,9 +155,9 @@
 (defn has-many-objects-hydration [hydrated column-family column-name value]
   (let [outer-key (primary-key column-family)
 	inner-key (.substring column-family (+ 1 (count outer-key)) (count column-family))
-	primary-key-name (*primary-keys-config* outer-key)
+	primary-key-name (qualifier-for (keyword outer-key))
 	inner-map (or (hydrated outer-key) {})
-	inner-object (or (inner-map column-name) {(symbol-name (*primary-keys-config* (keyword outer-key))) column-name})]
+	inner-object (or (inner-map column-name) {(symbol-name primary-key-name) (decode-with-key outer-key column-name)})]
     (assoc hydrated outer-key 
 	   (assoc inner-map column-name 
 		  (assoc inner-object inner-key value)))))
@@ -182,5 +193,4 @@
 (defn hbase-table [hbase-table-name]
   (let [h-config (HBaseConfiguration.) 	
 	_ (.set h-config &quot;hbase.master&quot;, *hbase-master*)]
-    (HTable. h-config hbase-table-name)))
-  
\ No newline at end of file
+    (HTable. h-config hbase-table-name)))
\ No newline at end of file</diff>
      <filename>src/org/rathore/amit/capjure.clj</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>2bb2215686f1a0f1ff0a7ff1e9484e3d99d90933</id>
    </parent>
  </parents>
  <author>
    <name>amitrathore</name>
    <email>amitrathore@gmail.com</email>
  </author>
  <url>http://github.com/amitrathore/capjure/commit/ca8347b9006f05b2a55d32ae6ecfdbfc7195f87f</url>
  <id>ca8347b9006f05b2a55d32ae6ecfdbfc7195f87f</id>
  <committed-date>2009-02-02T17:37:46-08:00</committed-date>
  <authored-date>2009-02-02T17:37:46-08:00</authored-date>
  <message>added the possibility of specifying encoding/decoding functions when flattening objects to be stored in hbase</message>
  <tree>a4ea4516d0b49fdd0a5bc4b209a48bc39210066b</tree>
  <committer>
    <name>amitrathore</name>
    <email>amitrathore@gmail.com</email>
  </committer>
</commit>
