1 /*
2 * $Source$
3 * $Revision$
4 *
5 * Copyright (C) 2000 William Chesters
6 *
7 * Part of Melati (http://melati.org), a framework for the rapid
8 * development of clean, maintainable web applications.
9 *
10 * Melati is free software; Permission is granted to copy, distribute
11 * and/or modify this software under the terms either:
12 *
13 * a) the GNU General Public License as published by the Free Software
14 * Foundation; either version 2 of the License, or (at your option)
15 * any later version,
16 *
17 * or
18 *
19 * b) any version of the Melati Software License, as published
20 * at http://melati.org
21 *
22 * You should have received a copy of the GNU General Public License and
23 * the Melati Software License along with this program;
24 * if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA to obtain the
26 * GNU General Public License and visit http://melati.org to obtain the
27 * Melati Software License.
28 *
29 * Feel free to contact the Developers of Melati (http://melati.org),
30 * if you would like to work out a different arrangement than the options
31 * outlined here. It is our intention to allow Melati to be used by as
32 * wide an audience as possible.
33 *
34 * This program is distributed in the hope that it will be useful,
35 * but WITHOUT ANY WARRANTY; without even the implied warranty of
36 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37 * GNU General Public License for more details.
38 *
39 * Contact details for copyright holder:
40 *
41 * William Chesters <williamc At paneris.org>
42 * http://paneris.org/~williamc
43 * Obrechtstraat 114, 2517VX Den Haag, The Netherlands
44 */
45
46 package org.melati.poem;
47
48 import java.util.Enumeration;
49 import java.util.Map;
50 import java.util.Hashtable;
51 import org.melati.poem.util.EmptyEnumeration;
52
53 /**
54 * A class which defines the three standard integrity fixes of
55 * <tt>delete</tt>, <tt>clear</tt> and <tt>prevent</tt>.
56 * <p>
57 * These correspond to the SQL ON DELETE CASCADE, ON DELETE SET NULL
58 * and ON DELETE NO ACTION.
59 * </p>
60 */
61 public abstract class StandardIntegrityFix implements IntegrityFix {
62
63 /** The id for a fix. */
64 private final Integer index;
65 /** The name for a fix. */
66 private final String name;
67
68 /**
69 * @return the name
70 */
71 public String getName() {
72 return name;
73 }
74
75 /**
76 * @return the index.
77 */
78 public Integer getIndex() {
79 return index;
80 }
81
82
83 /* private -- makes Sun compiler barf ...
84 An abstract class must be extended so cannot have a private constructor.
85 */
86 StandardIntegrityFix(int index, String name) {
87 this.index = new Integer(index);
88 this.name = name;
89 }
90
91 /* The fixes. */
92 /** Delete referred objects. */
93 public static final StandardIntegrityFix delete;
94 /** Clear (make null) field in referring object. */
95 public static final StandardIntegrityFix clear;
96 /** Disallow the deletion. */
97 public static final StandardIntegrityFix prevent;
98
99 /**
100 * Each {@link StandardIntegrityFix} differs from another by the
101 * way they implement {#referencesTo}.
102 *
103 * <b>delete</b> deletes all references to this {@link Persistent}. <br>
104 * <b>clear</b> sets the references to null. <br>
105 * <b>prevent</b> returns the references, which prevokes an exception
106 *
107 * @see Persistent#delete(Map)
108 * @param referee the {@link Persistent} we are deleting
109 * @param column the {@link Column} of the reference to {@link Persistent}
110 * we are deleting, used in <b>clear</b>
111 * @param refs an {@link Enumeration} of the objects which contain
112 * a reference to the {@link Persistent} we are deleting,
113 * each is deleted, cleared or returned respectively
114 * @param referenceFixOfColumn a {@link Map} keyed on {@link Column}
115 * giving the associated {@link IntegrityFix}, passed in to
116 * the {@link Persistent} referer to delete itself
117 *@return an {@link Enumeration} of the remaining referers, which if
118 * not empty will prevent deletion
119 */
120 @SuppressWarnings("rawtypes")
121 public abstract Enumeration<Persistent> referencesTo(Persistent referee,
122 Column column,
123 Enumeration refs,
124 Map referenceFixOfColumn);
125
126 /**
127 * Create the fixes.
128 */
129 @SuppressWarnings({"rawtypes","unchecked"})
130 private static final StandardIntegrityFix[] fixes = {
131 delete = new StandardIntegrityFix(0, "delete") {
132 public Enumeration<Persistent> referencesTo(Persistent referee, Column column,
133 Enumeration refs,
134 Map referenceFixOfColumn) {
135 while (refs.hasMoreElements()) {
136 Persistent p = (Persistent)refs.nextElement();
137 p.delete(referenceFixOfColumn);
138 }
139 return new EmptyEnumeration<Persistent>();
140 }
141 },
142 clear = new StandardIntegrityFix(1, "clear") {
143 public Enumeration<Persistent> referencesTo(Persistent referrer, Column column,
144 Enumeration refs,
145 Map referenceFixOfColumn) {
146 while (refs.hasMoreElements())
147 column.setRaw((Persistent)refs.nextElement(), null);
148 return new EmptyEnumeration<Persistent>();
149 }
150 },
151 prevent = new StandardIntegrityFix(2, "prevent") {
152 public Enumeration<Persistent> referencesTo(Persistent referrer, Column column,
153 Enumeration refs,
154 Map referenceFixOfColumn) {
155 return refs;
156 }
157 }
158 };
159
160 /**
161 * Get a fix by its index.
162 *
163 * @param i the index
164 * @return the fix at that index
165 */
166 public static StandardIntegrityFix forIndex(int i) {
167 return fixes[i];
168 }
169
170 /**
171 * @return the number of fixes
172 */
173 public static int count() {
174 return fixes.length;
175 }
176
177 private static final Hashtable<String,IntegrityFix> fixOfName = new Hashtable<String,IntegrityFix>();
178
179 static {
180 for (int i = 0; i < fixes.length; ++i)
181 fixOfName.put(fixes[i].name, fixes[i]);
182 }
183
184 /**
185 * Thrown when an invalid {@link StandardIntegrityFix} is specified,
186 * by a typing mistake in the DSD for example.
187 */
188 public static class NameUnrecognisedException extends PoemException {
189 private static final long serialVersionUID = 1L;
190
191 /** The name. */
192 public String name;
193
194 /**
195 * Constructor.
196 * @param name the name of the fix
197 */
198 public NameUnrecognisedException(String name) {
199 this.name = name;
200 }
201
202 /** @return The detail message. */
203 public String getMessage() {
204 return "No integrity fix found which goes by the name `" + name + "'";
205 }
206 }
207
208 /**
209 * Find by name.
210 *
211 * @param name the name
212 * @return the named fix
213 */
214 public static StandardIntegrityFix named(String name) {
215 StandardIntegrityFix it = (StandardIntegrityFix)fixOfName.get(name);
216 if (it == null)
217 throw new NameUnrecognisedException(name);
218 return it;
219 }
220
221 /**
222 * Return the name and index.
223 * {@inheritDoc}
224 * @see java.lang.Object#toString()
225 */
226 public String toString() {
227 return name + "/" + index;
228 }
229
230
231 }