1 ;;;; -*- lisp -*- common.lisp -- common functionality used by CL-Trane libraries and projects
3 ;;;; Copyright (c) 2008, Maciej Pasternacki <maciej@pasternacki.net>
4 ;;;; All rights reserved. This file is available on the terms
5 ;;;; detailed in COPYING file included with it.
7 ;; Package for internal use in libraries and projects
8 (defpackage #:trane-common
9 (:use
#:common-lisp
) ; referenced with package name: #:py-configparser
10 (:export
#:id
#:slug
#:slug-dao
11 #:*config
* #:*init-functions
* #:on-init
#:*setup-functions
* #:on-setup
13 #:make-keyword
#:named-lambda
#:random-string
))
15 ;; Package for use outside of project
16 (defpackage #:cl-trane
19 (in-package #:trane-common
)
21 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
22 ;;; Common access methods for database objects
24 (defgeneric id
(object)
25 (:documentation
"Numeric ID or :NULL for DAOs and, if it makes sense, other objects.
27 Usually it will be a reader method automatically defined for ID column of a DAO."))
29 ;;; To enable using integer as a DAO when only ID is needed
30 (defmethod id ((i integer
))
33 ;;; NULL database id for NIL object.
34 (defmethod id ((n null
))
37 (defmethod id ((n string
))
38 (parse-integer n
:junk-allowed t
))
40 (defgeneric slug
(object)
41 (:documentation
"Get short, unique, urlified name of OBJECT."))
43 (defun slug-dao (class slug
)
44 "Select DAO of CLASS having \"slug\" column set to SLUG."
45 (first (postmodern:select-dao class
(:= 'slug slug
))))
47 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
48 ;;; Initialization and setup protocol
50 (defvar *config
* (py-configparser:make-config
)
51 "Parsed configuration file.")
53 (defvar *config-files
* (list "config.ini")
54 "List of default configuration files.")
56 (defun read-configuration (&rest files
)
57 "Read configuration from FILES.
59 If no files are given, read files listed in *CONFIG-FILES*."
60 (py-configparser:read-files
*config
* (or files
*config-files
*)))
62 (defvar *init-functions
* ()
63 "Functions (symbols) that are FUNCALLed on initialization.
65 No assumption about init function order should be made.")
68 "Initialize everything."
70 (mapcar #'funcall
*init-functions
*))
72 (defmacro on-init
(&body body
)
73 "BODY should be sequence of DEFUN forms containing functions
74 that are to be executed on initialization."
76 (loop for defun
in body
77 collect
`(push ,defun
*init-functions
*))))
79 (defvar *setup-functions
* ()
80 "Functions (symbols) that are FUNCALLed on setup.
82 No assumption about setup function order should be made.")
87 (mapcar #'funcall
*setup-functions
*))
89 (defmacro on-setup
(&body body
)
90 "BODY should be sequence of DEFUN forms containing functions
91 that are to be executed on setup."
93 (loop for defun
in body
94 collect
`(push ,defun
*setup-functions
*))))
96 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
100 "Database connection specification")
102 (defmethod hunchentoot:dispatch-request
:around
(dispatch-table)
103 "Take care of database connection during HTTP request."
104 (postmodern:with-connection
*db
*
108 (defun init-db-connection ()
109 "Initialize database connection from config.ini"
111 (py-configparser:get-option
*config
* "db" name
)))
112 (setf *db
* (list (opt "database")
118 (defmethod print-object :around
((timestamp simple-date
:timestamp
) stream
)
121 (multiple-value-bind (year month day hour minute second millisecond
)
122 (simple-date:decode-timestamp timestamp
)
123 (declare (ignore millisecond
))
124 (format stream
"~D-~2,'0D-~2,'0D ~2,'0D:~2,'0D:~2,'0D"
125 year month day hour minute second
))))
127 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
128 ;;; General utility functions
131 (defun make-keyword (str)
132 "Convert a string or symbol to a keyword."
133 (intern (string-upcase (string str
)) :keyword
))
135 (defmacro named-lambda
(name args
&body body
)
136 "Version of LAMBDA that returns anonymous function defined with
137 FLET and named NAME, which it's PRINTed with a name in most Lisp
139 `(flet ((,name
,args
,@body
))
142 (defun random-string (&key
143 (alphabet "123456790abcdefghijklmnopqrstuvwxyz")
146 "Simple random string for initial password to use in account activation process."
147 (coerce (loop for i from
0 to
(+ min-length
(random (- max-length min-length
)))
148 collect
(aref alphabet
(random (length alphabet
))))
151 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
152 ;;; Externally exported symbols
153 (import 'init
:cl-trane
)
154 (import 'setup
:cl-trane
)
155 (export 'init
:cl-trane
)
156 (export 'setup
:cl-trane
)