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.4 2002/10/10 16:23:48 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 Lisp Lesser GNU Public License
16 ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
17 ;;;; *************************************************************************
19 ;;;; Defines a metaclass that allows the use of attributes (or subslots)
20 ;;;; on slots. Based on example in AMOP, but modified to use ACL's MOP.
24 (defclass attributes-dsd (mop::standard-direct-slot-definition)
25 ((attributes :initarg :attributes :initform nil
26 :accessor attributes)))
28 (defclass attributes-esd (mop::standard-effective-slot-definition)
29 ((attributes :initarg :attributes :initform nil
30 :accessor slot-definition-attributes)))
33 (defclass attributes-class (mop::standard-class)
37 (defmethod mop::direct-slot-definition-class ((cl attributes-class)
38 &rest iargs &key attributes)
39 (declare (ignorable attributes))
40 ;; (format t "attributes:~s iargs:~s~%" attributes iargs)
41 (find-class 'attributes-dsd))
44 (defmethod mop::compute-effective-slot-definition :around
45 ((cl attributes-class) slot dsds)
46 (declare (ignorable slot))
48 #'make-instance 'attributes-esd
49 :attributes (remove-duplicates (mapappend #'attributes dsds))
50 (excl::compute-effective-slot-definition-initargs cl dsds))
55 (defmethod mop::compute-effective-slot-definition ((cl attributes-class) slot dsds)
56 (declare (ignorable slot))
57 (let ((normal-slot (call-next-method)))
58 (setf (slot-definition-attributes normal-slot)
60 (mapappend #'slot-definition-attributes dsds)))
64 (defmethod mop::compute-slots ((class attributes-class))
65 (let* ((normal-slots (call-next-method))
69 (let ((attr-list (mapcar #'(lambda (attr) (cons attr nil))
70 (slot-definition-attributes slot))))
72 (cons (mop::slot-definition-name slot) attr-list))))
74 (setq alist (delete nil alist))
75 (cons (mop::make-instance 'mop::standard-effective-slot-definition
78 :initfunction #'(lambda () alist))
81 (defun slot-attribute (instance slot-name attribute)
82 (cdr (slot-attribute-bucket instance slot-name attribute)))
84 (defun (setf slot-attribute) (new-value instance slot-name attribute)
85 (setf (cdr (slot-attribute-bucket instance slot-name attribute))
88 (defun slot-attribute-bucket (instance slot-name attribute)
89 (let* ((all-buckets (slot-value instance 'all-attributes))
90 (slot-bucket (assoc slot-name all-buckets)))
92 (error "The slot named ~S of ~S has no attributes."
94 (let ((attr-bucket (assoc attribute (cdr slot-bucket))))
96 (error "The slot named ~S of ~S has no attributes named ~S."
97 slot-name instance attribute))
104 (defclass credit-rating ()
105 ((level :attributes (date-set time-set))
106 (id :attributes (person-setting)))
107 (:metaclass kmrcl:attributes-class))
108 (defparameter cr (make-instance 'credit-rating))
110 (format t "~&date-set: ~a" (slot-attribute cr 'level 'date-set))
111 (setf (slot-attribute cr 'level 'date-set) "12/15/1990")
112 (format t "~&date-set: ~a" (slot-attribute cr 'level 'date-set))
114 (defclass monitored-credit-rating (credit-rating)
115 ((level :attributes (last-checked interval date-set))
117 (id :attributes (verified))
119 (:metaclass attributes-class))
120 (defparameter mcr (make-instance 'monitored-credit-rating))
122 (setf (slot-attribute mcr 'level 'date-set) "01/05/2002")
123 (format t "~&date-set for mcr: ~a" (slot-attribute mcr 'level 'date-set))