Anonymous avatar Anonymous committed ec2b216

Fixed kw-enum in core, added new functions to web and integrated test-is in build.

Comments (0)

Files changed (6)

     Neman targets.
     -->
 
-    <target name='resolve' depends='ivy-install'>
+    <target name='resolve' depends='ivy-install' unless='skip.resolve'>
         <ivy:settings file='${basedir}/ivysettings.xml'/>
         <ivy:resolve file='${basedir}/ivy.xml'/>
         <ivy:retrieve/>
             pubrevision='0.0.1'
             artifactspattern='${build}/[artifact].[ext]'/>
     </target>
+
+    <target name='test' depends='build'>
+        <path id='test.classpath'>
+            <fileset dir='${lib}'>
+                <include name='**/*.jar'/>
+            </fileset>
+        </path>
+
+        <clojure
+            file='${test}/test.clj'
+            classpath='${build.classes}:${src}'
+            classpathref='test.classpath'/>
+    </target>
 </project>
     <property name='dist'  location='${basedir}/dist'/>
     <property name='lib'   location='${basedir}/lib'/>
     <property name='src'   location='${basedir}/src'/>
+    <property name='test' location='${basedir}/tests'/>
 
     <property name='doc.src'        location='${basedir}/docs'/>
     <property name='doc.build'      location='${build}/docs'/>
     <property file='${basedir}/local.properties'/>
     <property file='${basedir}/build.properties'/>
 
+    <macrodef name='clojure'>
+        <attribute name='classpath' default=''/>
+        <attribute name='classpathref' default=''/>
+        <attribute name='file'/>
+        <element name='args' optional='yes' implicit='true'/>
+        <sequential>
+            <java
+                fork='true'
+                classname='clojure.lang.Script'
+                classpath='@{classpath}'
+                classpathref='@{classpathref}'>
+                <arg value='@{file}'/>
+                <arg value='--'/>
+                <args/>
+            </java>
+        </sequential>
+    </macrodef>
+
     <!--
     Apache Ivy (http://ant.apache.org/ivy/).
     -->
         <dependency org='clojure' name='clojure' rev='svn1132'>
             <artifact name='clojure' type='jar'/>
         </dependency>
-        <dependency org='clojure' name='clojure-contrib' rev='svn229'>
+        <dependency org='clojure' name='clojure-contrib' rev='svn328'>
             <artifact name='clojure-contrib' type='jar'/>
         </dependency>
         <dependency org='org.codehaus' name='jackson' rev='0.9.2'>

src/net/ksojat/neman/core.clj

   ([name]       (System/getProperty name))
   ([name value] (System/setProperty name value)))
 
-(defmacro kw-enum
+(defn static-field [cls field]
+  (Reflector/getStaticField cls field))
+
+(defn kw-enum
   ([cls field]
     (if (keyword? field)
-      `(. ~cls ~(symbol (.. (name field) (toUpperCase) (replace "-" "_"))))
+      (static-field cls (.. (name field) toUpperCase (replace "-" "_")))
       field))
 
   ([cls prefix field]
     (if (keyword? field)
-      (kw-enum cls (keyword (str (.toUpperCase prefix) "_" (name field)))))))
+      (static-field cls (.. (str prefix "_" (name field)) toUpperCase (replace "-" "_")))
+      field)))
 
 (defn into-array-of [type s]
   (let [c (count s), a (make-array type c)]

src/net/ksojat/neman/web.clj

    :from-url uuid
    :to-url   str})
 
+; TODO: date and date-map convertors
+
 (defn convertor-regex [type]
   (when type
     (:regex (convertor type))))
 (defn view? [x]
   (true? (::view (meta x))))
 
+(defn value? [x]
+  (= :value x))
+
+(defn convertor? [x]
+  (= :convertor x))
+
 (defn argument-names [view]
   (filter #(not= % nil)
-    (map (fn [[k [t _]]] (if (= t :value) nil k)) (view :args))))
+    (map (fn [[k [t _]]] (if (not (value? t)) k)) (view :args))))
 
 (defn argument-types [view]
-  (filter #(not= % nil)
-    (map (fn [[_ [t x]]] (if (= t :convertor) x)) (view :args))))
+  (into {}
+    (filter #(not= nil %)
+      (map (fn [[n [t x]]] (if (convertor? t) [n x])) (view :args)))))
+
+(defn argument-regex [view]
+  (into {}
+    (map (fn [[k v]] [(name k) (convertor-regex v)]) (argument-types view))))
 
 (defn call-view [view arguments]
   (apply (view :view)
             (recur (rest new-args) x)))
         (assoc view :args (vec old-args))))))
 
+;;
+;; Routes.
+;;
+
+(def rule-pattern #"(?:([^<]*)(?:<([^>]*)>))|([^<^>]*)")
+
+(defn rule-seq [route]
+  (butlast (re-seq rule-pattern route)))
+
+(defn valid-rule? [rule]
+  (not= ["" nil nil ""] rule))
+
+(defn parse-route [route]
+  (let [ps (rule-seq route)] (if (every? valid-rule? ps) ps)))
+
+(defn route-parts [route]
+  (map (fn [[_ path1 arg path2]] [(or path1 path2) arg]) (parse-route route)))
+
+(defn valid-route? [route-parts]
+  (not= nil route-parts))
+
+(defn route-names [route]
+  (filter #(not= nil %)
+    (map (fn [[_ name]] name) (route-parts route))))
+
+(defn route-regex [route arg-regex]
+  (loop [parts (route-parts route), out []]
+    (if (seq parts)
+      (let [[[path arg] & ps] parts]
+        (recur ps (conj out path (arg-regex arg))))
+      (re-pattern (apply str out)))))
+
+(defn route-matcher [route arg-regex]
+  (fn [url-path]
+    (rest (re-matches (route-regex route arg-regex) url-path))))
+
+(defn route-arguments [names arguments]
+  (apply hash-map (interleave names arguments)))
+
+;;
+;; Jetty integration.
+;;
+
 (defn status [status-kw]
   (kw-enum HttpServletResponse "SC" status-kw))
 
-(defn urlmapper [view-fn]
+(defn current-connection []
+  (HttpConnection/getCurrentConnection))
+
+(defn current-request []
+  (.getRequest (current-connection)))
+
+(defn get-request [r]
+  (if (instance? Request r) (cast Request r) (current-request)))
+
+(defn current-response []
+  (.getResponse (current-connection)))
+
+(defn get-response [r]
+  (if (instance? Response r) (cast Response r) (current-response)))
+
+(defn mapper [paths routes]
   (proxy [AbstractHandler] []
     (handle [target #^HttpServletRequest request #^HttpServletResponse response dispatch]
-      (view-fn))))
+      (let [request (get-request request), response (get-response response)]
+        (.setHandled request true)
+        (.setStatus  response (status :ok))
+        (.. response getWriter (println "hi"))))))
+;; Copyright (c) 2008 Krešimir Šojat. All rights reserved.  The use and
+;; distribution terms for this software are covered by the Common
+;; Public License 1.0 (http://www.opensource.org/licenses/cpl1.0.php)
+;; which can be found in the file CPL.TXT at the root of this
+;; distribution.  By using this software in any fashion, you are
+;; agreeing to be bound by the terms of this license.  You must not
+;; remove this notice, or any other, from this software.
+
+(ns user
+  (:require
+    (net.ksojat.neman [web :as web]))
+  (:use clojure.contrib.test-is))
+
+(deftest neman-web-route-parsing
+  (are (= _1 _2)
+    (web/route-parts "/index/<name>") '(["/index/" "name"])
+    (web/route-parts "/show-page")    '(["/show-page" nil])
+    (web/route-parts "<name>")        '(["" "name"])
+    (web/route-parts "<name")         nil
+    (web/route-parts "name>")         nil))
+
+(run-all-tests)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.