r2965: *** 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.4 2002/10/10 16:23:48 kevin Exp $
11 ;;;;
12 ;;;; This file, part of KMRCL, is Copyright (c) 2002 by Kevin M. Rosenberg
13 ;;;;
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 ;;;; *************************************************************************
18
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.
21
22 (in-package :kmrcl)
23
24 (defclass attributes-dsd (mop::standard-direct-slot-definition)
25   ((attributes :initarg :attributes :initform nil 
26                :accessor attributes)))
27
28 (defclass attributes-esd (mop::standard-effective-slot-definition)
29   ((attributes :initarg :attributes :initform nil 
30                :accessor slot-definition-attributes)))
31
32
33 (defclass attributes-class (mop::standard-class)
34   ()
35   )
36
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))
42
43
44 (defmethod mop::compute-effective-slot-definition :around
45            ((cl attributes-class) slot dsds)
46   (declare (ignorable slot))
47   (apply
48    #'make-instance 'attributes-esd 
49    :attributes (remove-duplicates (mapappend #'attributes dsds))
50    (excl::compute-effective-slot-definition-initargs cl dsds))
51   )
52
53
54 #+ignore
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)
59       (remove-duplicates
60        (mapappend #'slot-definition-attributes dsds)))
61     normal-slot))
62
63
64 (defmethod mop::compute-slots ((class attributes-class))
65   (let* ((normal-slots (call-next-method))
66          (alist
67           (mapcar
68            #'(lambda (slot)
69                (let ((attr-list (mapcar #'(lambda (attr) (cons attr nil))
70                                         (slot-definition-attributes slot))))
71                  (when attr-list
72                    (cons (mop::slot-definition-name slot) attr-list))))
73            normal-slots)))
74     (setq alist (delete nil alist))
75     (cons (mop::make-instance 'mop::standard-effective-slot-definition
76             :name 'all-attributes
77             :initform `',alist
78             :initfunction #'(lambda () alist))
79           normal-slots)))
80   
81 (defun slot-attribute (instance slot-name attribute)
82   (cdr (slot-attribute-bucket instance slot-name attribute)))
83
84 (defun (setf slot-attribute) (new-value instance slot-name attribute)
85   (setf (cdr (slot-attribute-bucket instance slot-name attribute))
86     new-value))
87
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)))
91     (unless slot-bucket
92       (error "The slot named ~S of ~S has no attributes."
93              slot-name instance))
94     (let ((attr-bucket (assoc attribute (cdr slot-bucket))))
95       (unless attr-bucket
96         (error "The slot named ~S of ~S has no attributes named ~S."
97                slot-name instance attribute))
98       attr-bucket)))
99
100
101 #||
102 (in-package :kmrcl)
103
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))
109
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))
113   
114 (defclass monitored-credit-rating (credit-rating)
115   ((level :attributes (last-checked interval date-set))
116    (cc :initarg :cc)
117    (id :attributes (verified))
118    )
119   (:metaclass attributes-class))
120 (defparameter mcr (make-instance 'monitored-credit-rating))
121
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))
124
125 ||#