View Javadoc
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 }