1 ;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*-
2 ;;;; *************************************************************************
3 ;;;; FILE IDENTIFICATION
5 ;;;; Name: attrib-class.lisp
6 ;;;; Purpose: Defines metaclass allowing use of attributes on slots
7 ;;;; Programmer: Kevin M. Rosenberg
8 ;;;; Date Started: Apr 2000
10 ;;;; $Id: attrib-class.lisp,v 1.2 2002/10/06 13:30:17 kevin Exp $
12 ;;;; This file, part of Kmrcl, is Copyright (c) 2002 by Kevin M. Rosenberg
14 ;;;; Kmrcl users are granted the rights to distribute and use this software
15 ;;;; as governed by the terms of the GNU General Public License.
16 ;;;; *************************************************************************
18 ;;;; Defines a metaclass that allows the use of attributes (or subslots)
19 ;;;; on slots. Based on example in AMOP, but modified to use ACL's MOP.
23 (defclass attributes-dsd (mop::standard-direct-slot-definition)
24 ((attributes :initarg :attributes :initform nil
25 :accessor attributes)))
27 (defclass attributes-esd (mop::standard-effective-slot-definition)
28 ((attributes :initarg :attributes :initform nil
29 :accessor slot-definition-attributes)))
32 (defclass attributes-class (mop::standard-class)
36 (defmethod mop::direct-slot-definition-class ((cl attributes-class)
37 &rest iargs &key attributes)
38 (declare (ignorable attributes))
39 ;; (format t "attributes:~s iargs:~s~%" attributes iargs)
40 (find-class 'attributes-dsd))
43 (defmethod mop::compute-effective-slot-definition :around
44 ((cl attributes-class) slot dsds)
45 (declare (ignorable slot))
47 #'make-instance 'attributes-esd
48 :attributes (remove-duplicates (gu:mapappend #'attributes dsds))
49 (excl::compute-effective-slot-definition-initargs cl dsds))
54 (defmethod mop::compute-effective-slot-definition ((cl attributes-class) slot dsds)
55 (declare (ignorable slot))
56 (let ((normal-slot (call-next-method)))
57 (setf (slot-definition-attributes normal-slot)
59 (mapappend #'slot-definition-attributes dsds)))
63 (defmethod mop::compute-slots ((class attributes-class))
64 (let* ((normal-slots (call-next-method))
68 (let ((attr-list (mapcar #'(lambda (attr) (cons attr nil))
69 (slot-definition-attributes slot))))
71 (cons (mop::slot-definition-name slot) attr-list))))
73 (setq alist (delete nil alist))
74 (cons (mop::make-instance 'mop::standard-effective-slot-definition
77 :initfunction #'(lambda () alist))
80 (defun slot-attribute (instance slot-name attribute)
81 (cdr (slot-attribute-bucket instance slot-name attribute)))
83 (defun (setf slot-attribute) (new-value instance slot-name attribute)
84 (setf (cdr (slot-attribute-bucket instance slot-name attribute))
87 (defun slot-attribute-bucket (instance slot-name attribute)
88 (let* ((all-buckets (slot-value instance 'all-attributes))
89 (slot-bucket (assoc slot-name all-buckets)))
91 (error "The slot named ~S of ~S has no attributes."
93 (let ((attr-bucket (assoc attribute (cdr slot-bucket))))
95 (error "The slot named ~S of ~S has no attributes named ~S."
96 slot-name instance attribute))
103 (defclass credit-rating ()
104 ((level :attributes (date-set time-set))
105 (id :attributes (person-setting)))
106 (:metaclass kmrcl:attributes-class))
107 (defparameter cr (make-instance 'credit-rating))
109 (format t "~&date-set: ~a" (gu:slot-attribute cr 'level 'date-set))
110 (setf (gu:slot-attribute cr 'level 'date-set) "12/15/1990")
111 (format t "~&date-set: ~a" (gu:slot-attribute cr 'level 'date-set))
113 (defclass monitored-credit-rating (credit-rating)
114 ((level :attributes (last-checked interval date-set))
116 (id :attributes (verified))
118 (:metaclass gu:attributes-class))
119 (defparameter mcr (make-instance 'monitored-credit-rating))
121 (setf (gu:slot-attribute mcr 'level 'date-set) "01/05/2002")
122 (format t "~&date-set for mcr: ~a" (gu:slot-attribute mcr 'level 'date-set))