r2948: *** empty log message ***
[kmrcl.git] / attrib-class.lisp
1 ;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*-
2 ;;;; *************************************************************************
3 ;;;; FILE IDENTIFICATION
4 ;;;;
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
9 ;;;;
10 ;;;; $Id: attrib-class.lisp,v 1.1 2002/10/06 13:21:47 kevin Exp $
11 ;;;;
12 ;;;; This file, part of Genutils, is Copyright (c) 2002 by Kevin M. Rosenberg
13 ;;;;
14 ;;;; Genutils users are granted the rights to distribute and use this software
15 ;;;; as governed by the terms of the GNU General Public License.
16 ;;;; *************************************************************************
17
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.
20
21 (in-package :genutils)
22
23 (defclass attributes-dsd (mop::standard-direct-slot-definition)
24   ((attributes :initarg :attributes :initform nil 
25                :accessor attributes)))
26
27 (defclass attributes-esd (mop::standard-effective-slot-definition)
28   ((attributes :initarg :attributes :initform nil 
29                :accessor slot-definition-attributes)))
30
31
32 (defclass attributes-class (mop::standard-class)
33   ()
34   )
35
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))
41
42
43 (defmethod mop::compute-effective-slot-definition :around
44            ((cl attributes-class) slot dsds)
45   (declare (ignorable slot))
46   (apply
47    #'make-instance 'attributes-esd 
48    :attributes (remove-duplicates (gu:mapappend #'attributes dsds))
49    (excl::compute-effective-slot-definition-initargs cl dsds))
50   )
51
52
53 #+ignore
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)
58       (remove-duplicates
59        (mapappend #'slot-definition-attributes dsds)))
60     normal-slot))
61
62
63 (defmethod mop::compute-slots ((class attributes-class))
64   (let* ((normal-slots (call-next-method))
65          (alist
66           (mapcar
67            #'(lambda (slot)
68                (let ((attr-list (mapcar #'(lambda (attr) (cons attr nil))
69                                         (slot-definition-attributes slot))))
70                  (when attr-list
71                    (cons (mop::slot-definition-name slot) attr-list))))
72            normal-slots)))
73     (setq alist (delete nil alist))
74     (cons (mop::make-instance 'mop::standard-effective-slot-definition
75             :name 'all-attributes
76             :initform `',alist
77             :initfunction #'(lambda () alist))
78           normal-slots)))
79   
80 (defun slot-attribute (instance slot-name attribute)
81   (cdr (slot-attribute-bucket instance slot-name attribute)))
82
83 (defun (setf slot-attribute) (new-value instance slot-name attribute)
84   (setf (cdr (slot-attribute-bucket instance slot-name attribute))
85     new-value))
86
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)))
90     (unless slot-bucket
91       (error "The slot named ~S of ~S has no attributes."
92              slot-name instance))
93     (let ((attr-bucket (assoc attribute (cdr slot-bucket))))
94       (unless attr-bucket
95         (error "The slot named ~S of ~S has no attributes named ~S."
96                slot-name instance attribute))
97       attr-bucket)))
98
99
100 #||
101 (in-package :genutils)
102
103 (defclass credit-rating ()
104   ((level :attributes (date-set time-set))
105    (id :attributes (person-setting)))
106   (:metaclass genutils:attributes-class))
107 (defparameter cr (make-instance 'credit-rating))
108
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))
112   
113 (defclass monitored-credit-rating (credit-rating)
114   ((level :attributes (last-checked interval date-set))
115    (cc :initarg :cc)
116    (id :attributes (verified))
117    )
118   (:metaclass gu:attributes-class))
119 (defparameter mcr (make-instance 'monitored-credit-rating))
120
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))
123
124 ||#