MY MONSTER IT LIVES!
This commit is contained in:
		
							parent
							
								
									7c9f7f91b4
								
							
						
					
					
						commit
						b69bcaa020
					
				|  | @ -44,7 +44,7 @@ | ||||||
|     (.exists (java.io.File. (first args))) |     (.exists (java.io.File. (first args))) | ||||||
|     (let [application (x/parse (first args))] |     (let [application (x/parse (first args))] | ||||||
|       (h/to-hugsql-queries application) |       (h/to-hugsql-queries application) | ||||||
|       ;; (j/to-json-routes application) |       (j/to-json-routes application) | ||||||
|       (s/to-selmer-routes application) |       (s/to-selmer-routes application) | ||||||
|       (t/to-selmer-templates application)))) |       (t/to-selmer-templates application)))) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,11 +1,14 @@ | ||||||
| (ns ^{:doc "Application Description Language: generate RING routes for REST requests." | (ns ^{:doc "Application Description Language: generate RING routes for REST requests." | ||||||
|       :author "Simon Brooke"} |       :author "Simon Brooke"} | ||||||
|   adl.to-json-routes |   adl.to-json-routes | ||||||
|   (:require [clojure.java.io :refer [file]] |   (:require [clojure.java.io :refer [file make-parents writer]] | ||||||
|  |             [clojure.pprint :refer [pprint]] | ||||||
|             [clojure.string :as s] |             [clojure.string :as s] | ||||||
|  |             [clojure.xml :as x] | ||||||
|             [clj-time.core :as t] |             [clj-time.core :as t] | ||||||
|             [clj-time.format :as f] |             [clj-time.format :as f] | ||||||
|             [adl.utils :refer :all])) |             [adl.utils :refer :all] | ||||||
|  |             [adl.to-hugsql-queries :refer [queries]])) | ||||||
| 
 | 
 | ||||||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||||
| ;;;; | ;;;; | ||||||
|  | @ -34,11 +37,12 @@ | ||||||
| ;;; to-hugsql-queries, because essentially we need one JSON entry point to wrap | ;;; to-hugsql-queries, because essentially we need one JSON entry point to wrap | ||||||
| ;;; each query. | ;;; each query. | ||||||
| 
 | 
 | ||||||
| (defn file-header [parent-name this-name] | 
 | ||||||
|  | (defn file-header [application] | ||||||
|   (list |   (list | ||||||
|     'ns |     'ns | ||||||
|     (symbol (str parent-name ".routes." this-name)) |     (symbol (str (safe-name (:name (:attrs application))) ".routes.auto-json")) | ||||||
|     (str "JSON routes for " parent-name |     (str "JSON routes for " (:name (:attrs application)) | ||||||
|          " auto-generated by [Application Description Language framework](https://github.com/simon-brooke/adl) at " |          " auto-generated by [Application Description Language framework](https://github.com/simon-brooke/adl) at " | ||||||
|          (f/unparse (f/formatters :basic-date-time) (t/now))) |          (f/unparse (f/formatters :basic-date-time) (t/now))) | ||||||
|     (list |     (list | ||||||
|  | @ -49,15 +53,11 @@ | ||||||
|       '[ring.util.http-response :as response] |       '[ring.util.http-response :as response] | ||||||
|       '[clojure.java.io :as io] |       '[clojure.java.io :as io] | ||||||
|       '[hugsql.core :as hugsql] |       '[hugsql.core :as hugsql] | ||||||
|       (vector (symbol (str parent-name ".db.core")) :as 'db)))) |       (vector (symbol (str (safe-name (:name (:attrs application))) ".db.core")) :as 'db)))) | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| (defn make-safe-name [string] |  | ||||||
|   (s/replace string #"[^a-zA-Z0-9-]" "")) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| (defn declarations [handlers-map] | (defn declarations [handlers-map] | ||||||
|   (cons 'declare (sort (map #(symbol (make-safe-name (name %))) (keys handlers-map))))) |   (cons 'declare (sort (map #(symbol (name %)) (keys handlers-map))))) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| (defn generate-handler-src | (defn generate-handler-src | ||||||
|  | @ -81,12 +81,12 @@ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| (defn handler | (defn handler | ||||||
|   "Generate declarations for handlers from query with this `query-key` in this `queries-map` taken from within |   "Generate declarations for handlers from query with this `query-key` in this `queries-map` | ||||||
|   this `entities-map`. This method must follow the structure of |   taken from within this `application`. This method must follow the structure of | ||||||
|   `to-hugsql-queries/queries` quite closely, because we must generate the same names." |   `to-hugsql-queries/queries` quite closely, because we must generate the same names." | ||||||
|   [query-key queries-map entities-map] |   [query-key queries-map application] | ||||||
|   (let [query (query-key queries-map) |   (let [query (query-key queries-map) | ||||||
|         handler-name (symbol (make-safe-name (name query-key)))] |         handler-name (symbol (name query-key))] | ||||||
|     (hash-map |     (hash-map | ||||||
|       (keyword handler-name) |       (keyword handler-name) | ||||||
|       (merge |       (merge | ||||||
|  | @ -182,6 +182,7 @@ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| (defn defroutes [handlers-map] | (defn defroutes [handlers-map] | ||||||
|  |   "Generate JSON routes for all queries implied by this ADL `application` spec." | ||||||
|   (cons |   (cons | ||||||
|     'defroutes |     'defroutes | ||||||
|     (cons |     (cons | ||||||
|  | @ -190,7 +191,7 @@ | ||||||
|         #(let [handler (handlers-map %)] |         #(let [handler (handlers-map %)] | ||||||
|            (list |            (list | ||||||
|              (symbol (s/upper-case (name (:method handler)))) |              (symbol (s/upper-case (name (:method handler)))) | ||||||
|              (str "/json/auto/" (:name handler)) |              (str "/json/auto/" (safe-name (:name handler))) | ||||||
|              'request |              'request | ||||||
|               (list |               (list | ||||||
|                 'route/restricted |                 'route/restricted | ||||||
|  | @ -199,39 +200,46 @@ | ||||||
|           (keys handlers-map)))))) |           (keys handlers-map)))))) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ;; (defn migrations-to-json-routes | (defn make-handlers-map | ||||||
| ;;   ([migrations-path parent-namespace-name] |   [application] | ||||||
| ;;    (migrations-to-json-routes migrations-path parent-namespace-name "auto-json-routes")) |   (reduce | ||||||
| ;;   ([migrations-path parent-namespace-name namespace-name] |     merge | ||||||
| ;;    (let [output (str (s/replace namespace-name #"-" "_") ".clj") |     {} | ||||||
| ;;          adl-struct (migrations-to-xml migrations-path "Ignored") |     (map | ||||||
| ;;          q (reduce |       (fn [e] | ||||||
| ;;              merge |         (let [qmap (queries application e)] | ||||||
| ;;              {} |           (reduce | ||||||
| ;;              (map |             merge | ||||||
| ;;                #(queries % adl-struct) |             {} | ||||||
| ;;                (vals adl-struct))) |             (map | ||||||
| ;;          h (reduce |               (fn [k] | ||||||
| ;;              merge |                 (handler k qmap application)) | ||||||
| ;;              {} |               (keys qmap))))) | ||||||
| ;;              (map |       (children-with-tag application :entity)))) | ||||||
| ;;                #(handler % q adl-struct) | 
 | ||||||
| ;;                (keys q))) | 
 | ||||||
| ;;          f (cons | (defn to-json-routes | ||||||
| ;;              (file-header parent-namespace-name namespace-name) |   [application] | ||||||
| ;;              ;;                          (pre-declare |   (let [handlers-map (make-handlers-map application) | ||||||
| ;;              (cons |         filepath (str *output-path* (:name (:attrs application)) "/routes/auto_json.clj")] | ||||||
| ;;                (declarations h) |     (make-parents filepath) | ||||||
| ;;                (cons |     (with-open [output (writer filepath)] | ||||||
| ;;                  (defroutes h) |       (binding [*out* output] | ||||||
| ;;                  (map #(:src (h %)) (sort (keys h))))))] |         (doall | ||||||
| ;;      (spit |           (map | ||||||
| ;;        output |             (fn [f] | ||||||
| ;;        (with-out-str |               (pprint f) | ||||||
| ;;          (doall |               (println "\n")) | ||||||
| ;;            (for [expr f] |             (list | ||||||
| ;;              (do |               (file-header application) | ||||||
| ;;                (pprint expr) |               (declarations handlers-map) | ||||||
| ;;                (print "\n\n")))))) |               (defroutes handlers-map)))) | ||||||
| ;;      f |         (doall | ||||||
| ;;      ))) |           (map | ||||||
|  |             (fn [h] | ||||||
|  |               (pprint (:src (handlers-map h))) | ||||||
|  |               (println) | ||||||
|  |               h) | ||||||
|  |             (sort (keys handlers-map)))))))) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | @ -50,6 +50,7 @@ | ||||||
|       '[ring.util.http-response :as response] |       '[ring.util.http-response :as response] | ||||||
|       '[clojure.java.io :as io] |       '[clojure.java.io :as io] | ||||||
|       '[hugsql.core :as hugsql] |       '[hugsql.core :as hugsql] | ||||||
|  |       (vector (symbol (str (:name (:attrs application)) ".layout")) :as 'l) | ||||||
|       (vector (symbol (str (:name (:attrs application)) ".db.core")) :as 'db) |       (vector (symbol (str (:name (:attrs application)) ".db.core")) :as 'db) | ||||||
|       (vector (symbol (str (:name (:attrs application)) ".routes.manual")) :as 'm)))) |       (vector (symbol (str (:name (:attrs application)) ".routes.manual")) :as 'm)))) | ||||||
| 
 | 
 | ||||||
|  | @ -62,7 +63,7 @@ | ||||||
|       (vector 'r) |       (vector 'r) | ||||||
|       (list 'let (vector 'p (list :form-params 'r)) |       (list 'let (vector 'p (list :form-params 'r)) | ||||||
|             (list |             (list | ||||||
|               'layout/render |               'l/render | ||||||
|               (list 'resolve-template (str n ".html")) |               (list 'resolve-template (str n ".html")) | ||||||
|               (merge |               (merge | ||||||
|                 {:title (capitalise (:name (:attrs f))) |                 {:title (capitalise (:name (:attrs f))) | ||||||
|  | @ -79,7 +80,7 @@ | ||||||
|                    (list |                    (list | ||||||
|                      (symbol |                      (symbol | ||||||
|                        (str |                        (str | ||||||
|                          "db/search-" |                          "db/search-strings-" | ||||||
|                          (singularise (:name (:attrs e))))) |                          (singularise (:name (:attrs e))))) | ||||||
|                      'p)}))))))) |                      'p)}))))))) | ||||||
| 
 | 
 | ||||||
|  | @ -111,13 +112,38 @@ | ||||||
|       'defroutes |       'defroutes | ||||||
|       (cons |       (cons | ||||||
|         'auto-selmer-routes |         'auto-selmer-routes | ||||||
|  |         (cons | ||||||
|  |           '(GET | ||||||
|  |              "/index" | ||||||
|  |              request | ||||||
|  |              (route/restricted | ||||||
|  |                (apply (resolve-handler "index") (list request)))) | ||||||
|           (interleave |           (interleave | ||||||
|             (map |             (map | ||||||
|               (fn [r] (make-route 'GET r)) |               (fn [r] (make-route 'GET r)) | ||||||
|               (sort routes)) |               (sort routes)) | ||||||
|             (map |             (map | ||||||
|               (fn [r] (make-route 'POST r)) |               (fn [r] (make-route 'POST r)) | ||||||
|           (sort routes))))))) |               (sort routes)))))))) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | (defn generate-handler-resolver | ||||||
|  |   "Dodgy, dodgy, dodgy. Generate code which will look up functions in the | ||||||
|  |   manual and in this namespace. I'm sure someone who really knew what they | ||||||
|  |   were doing could write this more elegantly." | ||||||
|  |   [application] | ||||||
|  |   (list | ||||||
|  |     'defn | ||||||
|  |     'raw-resolve-handler | ||||||
|  |     "Prefer the manually-written version of the handler with name `n`, if it exists, to the automatically generated one" | ||||||
|  |     (vector 'n) | ||||||
|  |     (list 'try | ||||||
|  |           (list 'eval (list 'symbol (list 'str (:name (:attrs application)) ".routes.manual/" 'n))) | ||||||
|  |           (list 'catch | ||||||
|  |                 'Exception '_ | ||||||
|  |                 (list 'eval | ||||||
|  |                       (list 'symbol | ||||||
|  |                             (list 'str (:name (:attrs application)) ".routes.auto/" 'n))))))) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| (defn to-selmer-routes | (defn to-selmer-routes | ||||||
|  | @ -134,13 +160,13 @@ | ||||||
|                      n |                      n | ||||||
|                      (str "auto/" n)))) |                      (str "auto/" n)))) | ||||||
|         (println) |         (println) | ||||||
|         (pprint '(def resolve-template (memoise raw-resolve-template))) |         (pprint '(def resolve-template (memoize raw-resolve-template))) | ||||||
|         (println) |         (println) | ||||||
|         (pprint '(defn index |         (pprint '(defn index | ||||||
|                    [r] |                    [r] | ||||||
|                    (layout/render |                    (l/render | ||||||
|                      (resolve-template |                      (resolve-template | ||||||
|                        "application-index") |                        "application-index.html") | ||||||
|                      {:title "Administrative menu"}))) |                      {:title "Administrative menu"}))) | ||||||
|         (println) |         (println) | ||||||
|         (doall |         (doall | ||||||
|  | @ -153,14 +179,8 @@ | ||||||
|                     (println)) |                     (println)) | ||||||
|                   (filter (fn [c] (#{:form :list :page} (:tag c))) (children e))))) |                   (filter (fn [c] (#{:form :list :page} (:tag c))) (children e))))) | ||||||
|             (children-with-tag application :entity))) |             (children-with-tag application :entity))) | ||||||
|         (pprint '(defn raw-resolve-handler |         (pprint | ||||||
|                    "Prefer the manually-written version of the handler with name `n`, if it exists, to the automatically generated one" |           (generate-handler-resolver application)) | ||||||
|                    [n] |  | ||||||
|                    (let [s (symbol (str "m." n))] |  | ||||||
|                      (if |  | ||||||
|                        (bound? s) |  | ||||||
|                        (eval s) |  | ||||||
|                        (eval (symbol n)))))) |  | ||||||
|         (println) |         (println) | ||||||
|         (pprint '(def resolve-handler |         (pprint '(def resolve-handler | ||||||
|                    (memoize raw-resolve-handler))) |                    (memoize raw-resolve-handler))) | ||||||
|  |  | ||||||
|  | @ -90,7 +90,7 @@ | ||||||
|      "\n" |      "\n" | ||||||
|      (flatten |      (flatten | ||||||
|        (list |        (list | ||||||
|          "{% extends \"templates/base.html\" %}" |          "{% extends \"base.html\" %}" | ||||||
|          (str "<!-- File " |          (str "<!-- File " | ||||||
|               filename |               filename | ||||||
|               " generated " |               " generated " | ||||||
|  |  | ||||||
|  | @ -181,6 +181,19 @@ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | (defn safe-name | ||||||
|  |   ([string] | ||||||
|  |     (s/replace string #"[^a-zA-Z0-9-]" "")) | ||||||
|  |   ([string convention] | ||||||
|  |    (case convention | ||||||
|  |      (:sql :c) (s/replace string #"[^a-zA-Z0-9_]" "_") | ||||||
|  |      :c-sharp (s/replace (capitalise string) #"[^a-zA-Z0-9]" "") | ||||||
|  |      :java (let | ||||||
|  |              [camel (s/replace (capitalise string) #"[^a-zA-Z0-9]" "")] | ||||||
|  |              (apply str (cons (Character/toUpperCase (first camel)) (rest camel)))) | ||||||
|  |      (safe-name string)))) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| (defn link-table? | (defn link-table? | ||||||
|   "Return true if this `entity` represents a link table." |   "Return true if this `entity` represents a link table." | ||||||
|   [entity] |   [entity] | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue