(:module :src
:components ((:file "contextl-hacks")
+
(:file "packages")
(:file "rofl")
(:in-layer . attribute-test))))
(let ((d (find-description 'attribute-test-description)))
-
+ (dletf (((described-object d) nil))
(is (equalp "VALUE" (slot-value (find-attribute d 'attribute-1) 'lol::value)))
-
(with-active-layers (attribute-test)
- (is (equalp (attribute-value nil (find-attribute d 'attribute-1))
- (attribute-value nil (find-attribute d 'attribute-2))))
- (is (equalp "VALUE2" (attribute-value nil (find-attribute d 'attribute-1)))))))
+ (is (equalp (attribute-value (find-attribute d 'attribute-1))
+ (attribute-value (find-attribute d 'attribute-2))))
+ (is (equalp "VALUE2" (attribute-value (find-attribute d 'attribute-1))))))))
(deftest test-attribute-property-inheriting ()
(test-attribute-value)
(:in-layer . attribute-property-test))))
(with-active-layers (attribute-property-test)
(let ((d (find-description 'attribute-test-description)))
+ (dletf (((described-object d) nil))
- (is (equalp "VALUE" (slot-value (find-attribute d 'attribute-1) 'lol::value)))
+ (is (equalp "VALUE" (slot-value (find-attribute d 'attribute-1) 'lol::value)))
- (is (equalp "attribute1" (attribute-label (find-attribute d 'attribute-1))))
- (is (equalp "attribute2" (attribute-label (find-attribute d 'attribute-2))))
+ (is (equalp "attribute1" (attribute-label (find-attribute d 'attribute-1))))
+ (is (equalp "attribute2" (attribute-label (find-attribute d 'attribute-2))))
- (with-active-layers (attribute-test)
- (is (equalp (attribute-value nil (find-attribute d 'attribute-1))
- (attribute-value nil (find-attribute d 'attribute-2))))
- (is (equalp "VALUE2" (attribute-value nil (find-attribute d 'attribute-1))))))))
+ (with-active-layers (attribute-test)
+ (is (equalp (attribute-value (find-attribute d 'attribute-1))
+ (attribute-value (find-attribute d 'attribute-2))))
+ (is (equalp "VALUE2" (attribute-value (find-attribute d 'attribute-1)))))))))
(deftest (test-attribute-with-different-class :compile-before-run t) ()
(eval '(progn
((direct-attributes
:accessor attribute-direct-attributes)
(attribute-object
- :accessor attribute-object)
+ :accessor slot-definition-attribute-object)
(attribute-object-initargs
:accessor attribute-object-initargs)))
(:method (description attribute-name property-name)
(ensure-layered-function
(defining-description
- (intern (format nil "~A-~A-~A"
+ (intern (format nil "=PROPERTY-ACCESS-FUNCTION-FOR-~A->~A.~A="
(description-print-name description)
attribute-name
property-name)))
:lambda-list '(description))))
-(define-layered-class standard-attribute ()
- ((description-class :initarg description-class)
+(defvar *init-time-description* nil)
+
+(defmethod attribute-description :around (attribute)
+ (handler-case (call-next-method)
+ (unbound-slot ()
+ (or
+ *init-time-description*
+q (call-next-method)))))
+
+(define-layered-class attribute ()
+ ((description :initarg :description
+ :accessor attribute-description)
(name
:layered-accessor attribute-name
:initarg :name)
:initarg :attribute-class
:initform 'standard-attribute
:layered t)
- (label
+ (keyword
+ :layered-accessor attribute-keyword
+ :initarg :keyword
+ :initform nil
+ :layered t)
+ (object
+ :layered-accessor attribute-object
+ :accessor described-object
+ :special t)))
+
+
+
+
+(define-layered-class standard-attribute (attribute)
+ ((label
:layered-accessor attribute-label
:initarg :label
:initform nil
:layered t
:special t)
(value
- :layered-accessor %attribute-value
+ :layered-accessor attribute-value
:initarg :value
:layered t
:special t)
(activep
:layered-accessor attribute-active-p
- :initarg :activep
+ :initarg :activep ;depreciated
+ :initarg :active
:initform t
:layered t
- :special t)
- (keyword
- :layered-accessor attribute-keyword
- :initarg :keyword
- :initform nil
- :layered t)
-))
+ :special t
+ :documentation
+ "Can be T, NIL or :WHEN. In the latter case, attribute is only active if the attribute value is non-null.")))
+
+
+(define-layered-method attribute-object ((attribute standard-attribute))
+ (if (slot-boundp attribute 'object)
+ (call-next-method)
+ (described-object (attribute-description attribute))))
+
+
+(define-layered-method attribute-value ((attribute standard-attribute))
+ (attribute-value-using-object (attribute-object attribute) attribute))
+
+(define-layered-function attribute-value-using-object (object attribute))
+
+(define-layered-method attribute-value-using-object (object attribute)
+ (let ((fn (handler-case (attribute-function attribute)
+ (unbound-slot () nil))))
+ (if fn
+ (funcall fn object)
+ (slot-value attribute 'value))))
(defun ensure-access-function (class attribute property)
(with-function-access
- (define-layered-function attribute-value (object attribute))
-
- (define-layered-method attribute-value (object attribute)
-
- (let ((fn (handler-case (attribute-function attribute)
- (unbound-slot () nil))))
- (if fn
- (funcall fn object)
- (%attribute-value attribute))))
-
-(defmethod attribute-description (attribute)
- ;(break "description for ~A is (slot-value attribute 'description-name)")
- (find-layer (slot-value attribute 'description-class))
- #+nil (let ((name (slot-value attribute 'description-name)))
- (when name
- (find-description name))))
(defmacro with-attributes (names description &body body)
`(with-slots ,names ,description ,@body))
-(define-layered-function display-attribute (object attribute)
- (:method (object attribute)
- (display-using-description attribute *display* object)))
-
-(define-layered-function display-attribute-label (object attribute)
- (:method (object attribute)
- (format *display* "~A " (attribute-label attribute))
-))
-
-(define-layered-function display-attribute-value (object attribute)
- (:method (object attribute)
- (let ((val (attribute-value object attribute)))
- (if (eq val object)
- (format *display* "~A " val)
- (with-active-descriptions (inline)
- (display *display* val )
-
- )
- ))))
-
-(define-layered-method display-using-description
- ((attribute standard-attribute) display object &rest args)
- (declare (ignore args))
- (when (attribute-label attribute)
- (display-attribute-label object attribute))
- (display-attribute-value object attribute))
+
;; This plist will be used to init the attribute object
;; Once the description itself is properly initiated.
(list :name name
- 'effective-attribute attribute
- 'description-class class))
+ 'effective-attribute attribute))
attribute))
+
+(defmethod slot-value-using-class ((class description-access-class) object slotd)
+ (if (or
+ (eq (slot-definition-name slotd) 'described-object)
+ (not (slot-boundp slotd 'attribute-object)))
+ (call-next-method)
+ (slot-definition-attribute-object slotd)))
(defclass standard-description-class (description-access-class layered-class)
(superclass standard-class))
t)
-(defclass standard-description-object (standard-layer-object)
- ())
+(define-layered-class standard-description-object (standard-layer-object)
+ ((described-object :accessor described-object
+ :special t)))
(defun description-class-name (description-class)
(read-from-string (symbol-name (class-name description-class))))
(attribute-objects
(mapcar
(lambda (slot)
- (setf (attribute-object slot)
- (apply #'make-instance
- 'standard-attribute
- (attribute-object-initargs slot))))
- (class-slots (class-of description))))
+ (let* ((*init-time-description* description)
+ (attribute (apply #'make-instance
+ 'standard-attribute
+ :description description
+ (attribute-object-initargs slot))))
+
+
+ (setf (slot-definition-attribute-object slot) attribute)))
+ (remove 'described-object (class-slots (class-of description))
+ :key #'slot-definition-name)))
(defining-classes (partial-class-defining-classes (class-of description))))
(loop
initargs)))
- (setf (slot-value description (attribute-name attribute))
- attribute))))))))
+ )))))))
;;;; HACK: run this at startup till we figure things out.
(defun initialize-descriptions ()
(defun description-attributes (description)
- (mapcar (curry
- #'slot-value-using-class
- (class-of 'description)
- description)
- (class-slots (class-of description))))
+ (let ((class (class-of description)))
+ (loop :for slot :in (class-slots class)
+ :if (and
+ (not (eq 'described-object
+ (slot-definition-name slot))))
+ :collect (slot-definition-attribute-object slot))))
(let* ((active-attributes
(find-attribute description 'active-attributes))
(attributes (when active-attributes
- (attribute-value *object* active-attributes))))
+ (attribute-value active-attributes))))
(if attributes
(mapcar (lambda (spec)
(find-attribute
(let ((*description* description)
(*display* display)
(*object* object))
+ (dletf (((described-object description) object))
(contextl::funcall-with-special-initargs
(loop
:for (key val) :on args :by #'cddr
(contextl::funcall-with-special-initargs
(let ((attribute (find-attribute description 'active-attributes)))
(when attribute
- (loop for spec in (attribute-value object attribute)
+ (loop for spec in (attribute-value attribute)
if (listp spec)
collect (cons (or
(find-attribute description (car spec))
(error "No attribute matching ~A" (car spec)))
(cdr spec)))))
(lambda ()
- (call-next-method)))))))
+ (call-next-method))))))))
#:standard-db-access-class
#:make-dao-from-row
#:described-db-access-class
+ #:select-only
+ #:select
;; Descriptions
#:find-description
#:define-description
+ #:described-object
#:described-class
#:with-active-descriptions
(slot-value-using-class class dao (class-id-slot-definition class)))))
+(postmodern::def-row-reader symbol-plist-row-reader (fields)
+
+ (let ((symbols (map 'list (lambda (desc)
+ (postmodern::from-sql-name (postmodern::field-name desc))) fields)))
+ (loop :while (postmodern::next-row)
+ :collect (loop :for field :across fields
+ :for symbol :in symbols
+ :nconc (list symbol (postmodern::next-field field))))))
+
+
+(setf postmodern::*result-styles*
+ (nconc (list '(:plists symbol-plist-row-reader nil)
+ '(:plist symbol-plist-row-reader t))
+ postmodern::*result-styles*))
+
+(defun select (&rest query)
+ (query (sql-compile (cons :select query)) :plists))
+
+(defun select-only (num &rest query)
+ (query (sql-compile `(:limit ,(cons :select query) ,num))
+ :plists))
+
(defun make-dao-from-row (type row &key slots)
(let* ((class (find-class type))
(dao (make-instance class))
(setf (slot-value o (attribute-slot-name object)) v))))))
-(define-layered-method attribute-value (object (attribute slot-definition-attribute))
+(define-layered-method attribute-value-using-object (object (attribute slot-definition-attribute))
(if (slot-boundp object (attribute-slot-name attribute))
(slot-value object (attribute-slot-name attribute))
:metaclass 'standard-description-class))
(find-description name)))
+
(defclass described-class ()
())
(ensure-description-for-class class))
-
-
(define-layered-method description-of ((object standard-object))
(or (ignore-errors (find-description (class-name (class-of object))))
(find-description 'standard-object)))
(class :editp nil))
(:in-description editable))
-(define-layered-function (setf attribute-value) (v o a)
+#+nil(define-layered-function (setf attribute-value) (v o a)
(:method (value object attribute)
(let ((setter (attribute-setter attribute)))
(if setter
((attribute standard-attribute) display object &rest args)
(declare (ignore args))
- (format t "Editable? ~A ~A" (attribute-label attribute) (attribute-editp object attribute)))
+ (if (attribute-editp object attribute)
+ (format *display* "This is where we'd edit")
+ (call-next-method)))
\ No newline at end of file
(define-description T ()
((identity :label nil :function #'identity)
- (type :label "Type" :function #'type-of)
+ (type :label "Type of" :function #'type-of)
(class :label "Class" :function #'class-of)
(active-attributes :label "Attributes"
:value nil
(define-layered-method description-of (any-lisp-object)
(find-description 't))
+(define-layered-function display-attribute (object attribute)
+ (:method (object attribute)
+ (display-using-description attribute *display* object)))
+
+(define-layered-function display-attribute-label (object attribute)
+ (:method (object attribute)
+ (format *display* "~A " (attribute-label attribute))))
+
+(define-layered-function display-attribute-value (object attribute)
+ (:method (object attribute)
+ (let ((val (attribute-value attribute)))
+ (if (eql val object)
+ (format *display* "~A " val)
+ (with-active-descriptions (inline)
+ (display *display* val))))))
+
+(define-layered-method display-using-description
+ ((attribute standard-attribute) display object &rest args)
+ (declare (ignore args))
+ (when (attribute-label attribute)
+ (display-attribute-label object attribute))
+ (display-attribute-value object attribute))
+
(define-display ((description t))
(format *display* "~{~A~%~}"
(mapcar
(define-description html-description ()
())
-
(define-description t ()
((css-class :value "lol-description" :activep nil)
(dom-id :function (lambda (x)
(:method (object attribute)
(<:span
:class "lol-attribute-value"
- (<:as-html (with-output-to-string (*display*)
- (display-attribute-value object attribute))))
+ (<:as-html
+ (with-output-to-string (*display*)
+ (display-attribute-value object attribute))))
))
(define-layered-function display-html-attribute (object attribute)
)
(define-display
- :in-description html-description ((description t) (display lol-ucw:component) object )
+ :in-description html-description ((description t)
+ (display lol-ucw:component)
+ object)
(display-html-description description display object))