View Javadoc
1   /*
2    * $Source$
3    * $Revision$
4    *
5    * Copyright (C) 2012 Tim Pizey
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   *     Tim Pizey <timp At paneris.org>
42   *     http://paneris.org/~timp
43   */
44  
45  package org.melati.poem.prepro;
46  
47  import java.util.Vector;
48  import java.io.Writer;
49  import java.io.IOException;
50  
51  /**
52   * A definition of a <tt>StringKeyReferencePoemType</tt> from the DSD.
53   * 
54   * Its member variables are populated from the DSD or defaults.
55   * Its methods are used to generate the java code.
56   */ 
57  public class StringKeyReferenceFieldDef extends FieldDef {
58  
59    private String targetFieldName;
60    private String capitalisedTargetFieldName;
61    private String integrityFix;
62    private int size;
63    
64  
65   /**
66    * Constructor.
67    *
68    * @param lineNo            the line number in the DSD file
69    * @param table             the {@link TableDef} that this <code>Field</code> is 
70    *                          part of 
71    * @param name              the name of this field in this table
72    * @param targetFieldName   the name of the key field in target
73    * @param type              the type of this field, ie the target table name
74    * @param displayOrder      where to place this field in a list
75    * @param qualifiers        all the qualifiers of this field
76    * 
77    * @throws IllegalityException if a semantic inconsistency is detected
78    */
79    public StringKeyReferenceFieldDef(int lineNo, TableDef table, String name, String targetFieldName, int displayOrder,
80                             String type, Vector<FieldQualifier> qualifiers)
81        throws IllegalityException {
82      super(lineNo, table, name, type, "String", displayOrder, qualifiers);
83      this.targetFieldName = targetFieldName;
84      this.capitalisedTargetFieldName = StringUtils.capitalised(targetFieldName);
85      if (size == 0)
86        throw new StringSizeZeroException(this);
87      table.addImport("org.melati.poem.StringKeyReferencePoemType", 
88                        "table");
89      table.addImport("org.melati.poem.NoSuchRowPoemException", 
90                        "persistent");
91      if (integrityFix != null) {
92        table.addImport("org.melati.poem.StandardIntegrityFix", 
93                          "table");
94      }
95      // Note these do not have a '.' in and are 
96      // looked up once all tables have been processed
97      // to enable forward reference within the DSD
98      table.addImport(type,"table");
99      table.addImport(type,"persistent");
100     
101   }
102   
103   /** Due to possible forward references this could be null until we finish parse
104    * @return the possibly null TableNamingInfo
105    */
106   public TableNamingInfo getTargetTableNamingInfo() {
107     return table.dsd.tableNamingStore.tableInfoByPersistentShortName.get(typeShortName);
108   }
109 
110  /**
111   * @param w The base table java file.
112   * @throws IOException 
113   *           if something goes wrong with the file system
114   */   
115   protected void generateColRawAccessors(Writer w) throws IOException {
116     super.generateColRawAccessors(w);
117 
118     w.write(
119       "\n" +
120       "          public Object getRaw(Persistent g)\n" +
121       "              throws AccessPoemException {\n" +
122       "            return ((" + shortestUnambiguousClassname + ")g).get" + capitalisedName + "();\n" +
123       "          }\n" +
124       "\n");
125     w.write(
126       "          public void setRaw(Persistent g, Object raw)\n" +
127       "              throws AccessPoemException {\n" +
128       "            ((" + shortestUnambiguousClassname + ")g).set" + capitalisedName + "((" +
129                    rawType + ")raw);\n" +
130       "          }\n");
131 
132     if (integrityFix != null) {
133       w.write(
134         "\n" +
135         "          public StandardIntegrityFix defaultIntegrityFix() {\n" +
136         "            return StandardIntegrityFix." + integrityFix + ";\n" +
137         "          }\n");
138     }
139   }
140 
141 
142  /**
143   * @param w The base persistent java file.
144   * @throws IOException 
145   *           if something goes wrong with the file system
146   */   
147   public void generateBaseMethods(Writer w) throws IOException {
148     super.generateBaseMethods(w);
149     String targetTableAccessorMethod = getTargetTableNamingInfo().leafTableAccessorName() ;
150 
151 
152     String db = "get" + table.dsd.databaseTablesClassName + "()";
153 
154     
155     
156     w.write(
157       "\n /**\n"
158       + "  * Retrieves the Table Row Object ID. \n" 
159       + "  *\n"
160       + "  * Generated by " 
161       + "org.melati.poem.prepro.StringKeyReferenceFieldDef#generateBaseMethods \n"
162       + "  * @throws AccessPoemException  \n" 
163       + "  *         if the current <code>AccessToken</code> \n"
164       + "  *         does not confer read access rights \n"
165       + "  * @return the TROID as an <code>Integer</code> \n"
166       + "  */\n");
167     w.write("\n" +
168       "  public Integer get" + capitalisedName + "Troid()\n" +
169       "      throws AccessPoemException {\n" +
170       "    String keyValue = get" + capitalisedName + "_unsafe();\n" +
171       "    if (keyValue == null)\n " + 
172       "      return null;\n" + 
173       "    else\n" +
174       "      return " + db + "\n" +
175       "          ." + targetTableAccessorMethod + "()\n" +
176       "            .get"+capitalisedTargetFieldName+"Column()\n" +
177       "              .firstWhereEq(keyValue)\n" + 
178       "                .troid();\n" +
179       "  }\n" +
180       "\n");
181     w.write(
182       "\n /**\n"
183       + "  * Sets persistent reference with access checking. \n" 
184       + "  * \n" 
185       + "  * Generated by " 
186       + "org.melati.poem.prepro.StringKeyReferenceFieldDef" 
187       + "#generateBaseMethods \n"
188       + "  * @param keyValue  a String prime key \n"
189       + "  * @throws AccessPoemException  \n" 
190       + "  *         if the current <code>AccessToken</code> \n"
191       + "  *         does not confer write access rights\n"
192       + "  */\n");
193     w.write(
194       "  public void set" + capitalisedName + "(String keyValue)\n" +
195       "      throws AccessPoemException {\n" +
196       "    set" + capitalisedName + "(" +
197       "keyValue == null ? null : \n" +
198       "        (" + typeShortName + ")"+
199       db + "." + targetTableAccessorMethod + "().\n" +
200       "            get" +capitalisedTargetFieldName+"Column().firstWhereEq(keyValue));\n" +
201       "  }\n" +
202       "\n");
203     
204     w.write(
205         "\n /**\n"
206         + "  * Retrieves the " + capitalisedName + " value, with locking, for this \n"
207         + "  * <code>" + table.nameFromDsd + "</code> <code>Persistent</code>.\n"
208         + ((description != null) ? "  * Field description: \n" 
209                                  + DSD.javadocFormat(2, 3, description)
210                                : "")
211         + "  * \n"
212         + "  * Generated by " 
213         + "org.melati.poem.prepro.StringKeyReferenceFieldDef#generateBaseMethods \n"
214         + "  * @throws AccessPoemException \n"
215         + "  *         if the current <code>AccessToken</code> \n"
216         + "  *         does not confer write access rights \n"
217         + "  * @return the value of the field <code>" + capitalisedName + "</code> for this \n"
218         + "  *         <code>" + table.nameFromDsd + "</code> <code>Persistent</code>  \n"
219         + "  */\n");
220     
221       w.write("\n" +
222               "  public String get" + capitalisedName + "()\n" +
223               "      throws AccessPoemException {\n" +
224               "    readLock();\n" +
225               "    return get" + capitalisedName + "_unsafe();\n" +
226               "  }\n" +
227               "\n");
228 
229     
230     w.write(
231       "\n /**\n"
232       + "  * Retrieves the <code>" + typeShortName + "</code> object referred to.\n"
233       + "  *  \n"
234       + "  * Generated by " 
235       + "org.melati.poem.prepro.StringKeyReferenceFieldDef#generateBaseMethods \n"
236       + "  * @throws AccessPoemException  \n" 
237       + "  *         if the current <code>AccessToken</code> \n"
238       + "  *         does not confer read access rights \n"
239       + "  * @return the <code>" 
240       + capitalisedName 
241       + "</code> as a <code>" 
242       + typeShortName 
243       + "</code> \n"
244       + "  */\n");
245     w.write(
246         "  public " + typeShortName + " get" + capitalisedName + "Referee()\n" +
247         "      throws AccessPoemException, NoSuchRowPoemException {\n" +
248         "    String keyValue = get" + capitalisedName + "_unsafe();\n" +
249         "    if (keyValue == null)\n " + 
250         "      return null;\n" + 
251         "    else\n" +
252         "      return \n" + 
253         "        (" + typeShortName + ")" +
254         db + "." + targetTableAccessorMethod + "()." +
255         "get"+capitalisedTargetFieldName+"Column().firstWhereEq(keyValue);\n" +
256         "  }\n" +
257         "\n");
258     w.write(
259       "\n /**\n"
260       + "  * Set the " + capitalisedName + " having validated it.\n" 
261       + "  * \n"
262       + "  * Generated by org.melati.poem.prepro.StringKeyReferenceFieldDef" 
263       + "#generateBaseMethods \n"
264       + "  * @param cooked  a validated <code>" + typeShortName + "</code>\n"
265       + "  * @throws AccessPoemException  \n" 
266       + "  *         if the current <code>AccessToken</code> \n"
267       + "  *         does not confer write access rights \n"
268       + "  */\n");
269     w.write(
270       "  public void set" + capitalisedName + "(" + typeShortName + " cooked)\n" +
271       "      throws AccessPoemException {\n" +
272       "    " + db + "." + targetTableAccessorMethod + "().\n" + 
273       "      get" + capitalisedTargetFieldName + "Column().\n" +
274       "        getType().assertValidCooked(\n" +
275       "          cooked == null ? null : cooked.getRaw(\"" + targetFieldName + "\"));\n" +
276       "    writeLock();\n" +
277       "    if (cooked == null)\n" +
278       "      set" + capitalisedName + "_unsafe(null);\n" +
279       "    else {\n" +
280       "      cooked.existenceLock();\n" +
281       "      set" + capitalisedName + "_unsafe(cooked.get" + capitalisedTargetFieldName+ "_unsafe());\n" +
282       "    }\n" +
283       "  }\n");
284   }
285 
286  /**
287   * Write out this <code>Field</code>'s java declaration string.
288   *
289   * @param w The base persistent java file.
290   * @throws IOException 
291   *           if something goes wrong with the file system
292   */   
293   public void generateJavaDeclaration(Writer w) throws IOException {
294     w.write("String " + name);
295   }
296 
297  /** @return the Java string for this <code>PoemType</code>. */
298   public String poemTypeJava() {
299     String db = "get" + table.dsd.databaseTablesClassName + "()";
300     String targetTableAccessorMethod = getTargetTableNamingInfo().leafTableAccessorName() ;
301 
302     return
303         "new StringKeyReferencePoemType(" + db + ".\n" + 
304         "                                             " +
305         targetTableAccessorMethod + "(), " + 
306         "\"" + 
307         targetFieldName +
308         "\", " + 
309         isNullable() +
310         ", " + size + ")";
311   }
312   
313   /**
314    * Set the size property. 
315    * 
316    * @param sizeP the size to set
317    */
318   public void setSize(int sizeP) {
319     if (this.size > 0)
320       throw new IllegalityException(lineNumber,
321           "String field size already set to " + this.size
322               + " cannot overwrite with " + sizeP);
323     if (sizeP == 0) throw new RuntimeException("wtf");
324     this.size = sizeP;
325   }
326 
327   public void setIntegrityFix(String integrityFixIn) {
328     this.integrityFix = integrityFixIn;
329   }
330 
331 }