4 (:import com.interrupt.cc.xpath.lexer.Lexer)
5 (:import com.interrupt.cc.xpath.lexer.LexerException)
6 (:import com.interrupt.cc.xpath.node.Node)
7 (:import com.interrupt.cc.xpath.node.Start)
8 (:import com.interrupt.cc.xpath.parser.Parser)
9 (:import com.interrupt.cc.xpath.parser.ParserException)
10 (:import com.interrupt.cc.xpath.analysis.DepthFirstAdapter)
11 (:import com.interrupt.bob.processor.cc.DepthFirstVisitor)
13 (:import java.io.InputStreamReader)
14 (:import java.io.PushbackReader)
15 (:import java.io.ByteArrayInputStream)
16 (:import java.util.ArrayList)
23 ;; remove the SableCC added <spaces> and `
24 (defn filter-xpath-input [input-string]
25 (clojure.contrib.string/replace-str " " ""
26 (clojure.contrib.string/replace-str "`" "" input-string))
29 ;; build the XPath parser
30 (defn get-pushback-parser [xpath-string]
31 (Parser. (Lexer. (PushbackReader. (InputStreamReader.
32 (ByteArrayInputStream. (. xpath-string getBytes)))
36 ;; the XPath string that the proxy / adapter will use to figure out context directory & XPath expression
37 ;; (def XPATH-string (ref ""))
38 (def xpath-data (ref {}))
40 ;; we're gonna build our eXist URL with this
41 (def URL-build (ref ""))
43 ;; pilfered stack ideas and some implementation from: http://programming-puzzler.blogspot.com/2009/04/adts-in-clojure.html
48 (dosync (alter stack conj e))
49 (println "PUSH stack [" (deref stack) "]" ))
51 (dosync (alter stack pop)))
53 (dosync (alter stack empty?)))
56 (defn get-url-midpoint []
58 (. (deref URL-build) lastIndexOf ;; get the position of substring
59 (:context-parent (deref xpath-data)))
60 (. (:context-parent (deref xpath-data)) length)) ;; plus the char length of the leaf document name
62 (defn get-xpath-part-midpoint []
66 (. (:xpath-string (deref xpath-data)) indexOf
67 (. (:context-parent (deref xpath-data)) substring
69 (. (:context-parent (deref xpath-data)) indexOf ".")))) ]
71 (. (:xpath-string (deref xpath-data)) substring
72 (+ 1 (. (:xpath-string (deref xpath-data)) indexOf "/" (+ 1 b_index)))
77 ;; get DepthFirstAdapter proxy
78 (defn get-adapter-proxy []
80 (proxy [DepthFirstAdapter] []
85 ;; - keep the last/previous token
88 (caseTAbbrevRootDesc [node]
90 (println "caseTAbbrevRootDesc CALLED \t\t\t\t class[" (. node getClass) "] \t\t\t\t" (. node toString))
96 (println "caseTLetter CALLED \t\t\t\t\t class[" (. node getClass) "] \t\t\t\t\t" (. node toString))
100 (caseAPredicatelist [node]
102 (proxy-super inAPredicatelist node) ;; duplicating adapter 'in' call
104 (println "caseAPredicatelist CALLED \t\t\t\t class[" (. node getClass) "] \t\t\t\t" (. node toString) "\t\t filtered " (filter-xpath-input (. node toString)))
105 (doseq [ each_predicate (java.util.ArrayList. (. node getPredicate)) ]
108 (println "DEBUG > each predicate... " each_predicate " predicate expresion[" (. each_predicate getExpr)
109 "] getExprsingle[" (.. each_predicate getExpr getExprsingle) "] ugghhhh!! [" ;; this is where = breaks off: getComparisonexpr -here- getComparisonexprPart
110 ;;(.. each_predicate getExpr getExprsingle getOrexpr getAndexpr getComparisonexpr getComparisonexprPart getRangeexpr) "]" )
111 (.. each_predicate getExpr getExprsingle getOrexpr getAndexpr getComparisonexpr getRangeexpr) "]" )
113 ;; LATER - DON'T traverse children & evaluate... for now
114 ;;(. each_predicate apply this)
117 ;; ** here we are assuming there's only one predicate in the list - getting the 'name' and 'value'
119 (clojure.contrib.string/replace-str "@" ""
120 (clojure.contrib.string/replace-str " " ""
121 (.. each_predicate getExpr getExprsingle getOrexpr getAndexpr getComparisonexpr getRangeexpr toString))))
123 (clojure.contrib.string/replace-str "'" ""
124 (clojure.contrib.string/replace-str " " ""
125 (.. each_predicate getExpr getExprsingle getOrexpr getAndexpr getComparisonexpr getComparisonexprPart getRangeexpr toString))))
126 (println "DEBUG > predicate-name[" predicate-name "] > predicate-value[" predicate-value "]")
129 ;; (peek, then..) pop 'TLetter' & 'RelativePathexpr'
130 (def top (stack-peek))
131 (stack-pop) ;; pop the token
132 (stack-pop) ;; LATER - pop the relativepathpart - we'll have to assume that there's a relative_path_part... for now
134 (println "top of stack["top"] > class["(. top getClass)"]")
136 (instance? com.interrupt.cc.xpath.node.TAbbrevRootDesc top )
139 (instance? com.interrupt.cc.xpath.node.TLetter top )
141 (alter URL-build str (clojure.contrib.string/replace-str " " "" (. top toString) ) "." predicate-value)
142 (alter URL-build str "/"))
144 ;;(instance? com.interrupt.cc.xpath.node.ARootRelativepathexprPartPart top )
145 ;; (dosync (alter URL-build str "/"))
147 (instance? com.interrupt.cc.xpath.node.APredicatelist top )
151 ;; put in a check to see if we are at the leaf document
152 (println "leaf check [" (. (clojure.contrib.string/trim (. top toString)) equals (:leaf-node (deref xpath-data))) "] > top[" (clojure.contrib.string/trim (. top toString)) "] > leaf-node[" (:leaf-node (deref xpath-data)) "]")
154 (if (. (clojure.contrib.string/trim (. top toString)) equals (:leaf-node (deref xpath-data)))
156 (do ;; IF portion here
158 (. (deref URL-build) substring ;; get a substring of our long exist URL
162 ;; (. (deref URL-build) lastIndexOf ;; get the position of substring
163 ;; (:context-parent (deref xpath-data)))
164 ;; (. (:context-parent (deref xpath-data)) length)) ;; plus the char length of the leaf document name
167 ;; write out context directory
169 (alter xpath-data conj
170 { :context-dir thing})
172 ;; write out leaf document
173 (def b_index (+ (. (deref URL-build) lastIndexOf
174 (:context-parent (deref xpath-data)))
175 (. (:context-parent (deref xpath-data)) length)))
177 (println "b_index[" (. (deref URL-build) indexOf "/" (+ 1 b_index)) "]")
178 (alter xpath-data conj
179 { :leaf-document-name
180 (. (deref URL-build) substring
182 (. (deref URL-build) indexOf "/" (+ 1 b_index)))
185 (println "---> We are at the leaf document[" (deref xpath-data) "]" ))
187 (dosync (alter xpath-data conj ;; ELSE, get the child XPath part
188 { :xpath-part (get-xpath-part-midpoint) }))
193 (println "URL-build[" (deref URL-build) "]")
197 (proxy-super outAPredicatelist node) ;; duplicating adapter 'out' call
200 (caseARootRelativepathexprPartPart [node]
202 (println "caseARootRelativepathexprPartPart CALLED \t\t class[" (. node getClass) "] \t\t\t\t" (. node toString))
210 (defn xpath_handler [node handler]
211 (if (instance? com.interrupt.bookkeeping.cc.node.AXpathCommandInput (. node getCommandInput) )
215 (println "xpath_handler > node[" (.. node getClass) "] > getLoad[" (.. node getLoad getText) "]")
216 (println "XPATH input[" (.. node getCommandInput toString) "]")
218 ;; 1. filter out <spaces> and `
219 (def input-string (filter-xpath-input (.. node getCommandInput toString)))
220 (println "input-string \t[" input-string "]")
221 (println "stripped XPath \t[" (clojure.contrib.string/replace-re #"\\[[^\\]]*\\]" "" input-string) "]" )
226 ;; put in whole xpath string
227 (alter xpath-data conj { :xpath-string input-string } )
229 ;; for token substring between last / and [
230 (alter xpath-data conj {
232 (. (:xpath-string (deref xpath-data)) substring
233 (+ (. (:xpath-string (deref xpath-data)) lastIndexOf "/") 1)
234 (. (:xpath-string (deref xpath-data)) lastIndexOf "["))
237 ;; with token, lookup context directory
238 (alter xpath-data conj { :context-parent (working-dir-lookup (:leaf-node (deref xpath-data))) } )
240 (println "LEAF token > " (:leaf-node (deref xpath-data)))
241 (println "LEAF context parent > " (:context-parent (deref xpath-data)))
244 ;; 1.2 build an xpath parser
245 (def tree (.parse (get-pushback-parser input-string)))
247 ;; 2. token - find i) leaf document to search ii) root & xpath expression to feed to RESTful exist
248 (. tree apply (get-adapter-proxy ) )
250 ;; 3. build RESTful call
251 (def db-query (str "_wrap=no&_query="
252 "declare default element namespace '"(namespace-lookup (:leaf-node (deref xpath-data))) "';"
254 ;; TODO - check if we need 'and' conditions
255 ;; "**/<token>[ @option='option_value' [ and @option='option_value' ] ]"
256 "//"(:leaf-node (deref xpath-data))"[ @" predicate-name "='" predicate-value "']"
262 (def db-full-PARENT (str db-base-URL "rootDir/" (:context-dir (deref xpath-data))))
264 ;; 4. make RESTful call & 5. pass result sequece to handler
266 (execute-http-call db-full-PARENT (:leaf-document-name (deref xpath-data)) db-query))