View Javadoc
1   /*
2    * $Source$
3    * $Revision$
4    *
5    * Copyright (C) 2001 Myles Chippendale
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   *     Myles Chippendale <mylesc At paneris.org>
42   *     http://paneris.org/
43   *     29 Stanley Road, Oxford, UK
44   */
45  
46  package org.melati.poem.prepro;
47  
48  /** 
49   * A store for Table Name information extracted from the DSD.
50   * 
51   * Java classes are capitalised, however SQL tables do not necessarily follow any rule. 
52   * To handle this we say that the name of a table in the DSD must be the same as the SQL name. 
53   * It is the SQL name which is stored in the tableInfo record but it is the capitalised one 
54   * which is used as teh class name. 
55   * 
56   */
57  public class TableNamingInfo {
58  
59    static final String POEM = "org.melati.poem";
60  
61    /** This package eg org.melati.example.contacts . */
62    public String packageName = null;
63  
64    /** The fully qualified name of the table persistent  (e.g. `org.melati.poem.User') */
65    public String objectFQName = null;
66  
67    /** The last part of the FQName of the persistent (e.g. `User') */
68    public String capitalisedShortName = null;
69    
70    /** The TableNamingInfo of this Table's superclass 
71     * (or null if this extends Persistent or Table). 
72     */
73    public TableNamingInfo superclass = null;
74  
75    /** 
76     * Does this Table have the same name as another table "higher up" in our
77     * hierarchy (that is a table already dealt with by DSD). 
78     *
79     * If so, we must import the tableFQName before the DSD's package and
80     * before melati in our java source.
81     *
82     * For example <TT>org.paneris.melati.boards.model.UserTable</TT> hides 
83     * <TT>org.melati.poem.UserTable</TT> and so has <TT>hidesOther</TT> true.
84     */
85    public boolean hidesOther = false;
86  
87    /** 
88     *  Does this Table have the same name as another table "lower down" in our
89     *  hierarchy. 
90     *
91     * If so, we must use the tableFQName as the return type in the DatabaseBase
92     * source file, and any tables with ReferenceTypes to this table.
93     * 
94     * For example <TT>org.melati.poem.UserTable</TT> is hidden by 
95     * <TT>org.paneris.melati.boards.model.UserTable</TT> and so has 
96     * <TT>hidden</TT> true.
97     */
98    public boolean hidden = false;
99  
100   public String projectName;
101 
102   public TableNamingInfo extended;
103 
104   /**
105    * Constructor.
106    * @param packageNameIn  the fully qualified java name of this package
107    * @param projectNameIn  the name of this project 
108    * @param nameFromDsd    the name of this table in the db and the dsd, not necessarily with initial capital
109    */
110   public TableNamingInfo(String packageNameIn, String projectNameIn, String nameFromDsd) {
111     packageName = packageNameIn;
112     projectName = projectNameIn; 
113     capitalisedShortName = nameFromDsd.substring(0,1).toUpperCase() + nameFromDsd.substring(1);
114     objectFQName = packageName + "." + capitalisedShortName;
115     superclass = null;
116     hidesOther = false;
117     hidden = false;
118   }
119 
120   /** 
121    * Calculate the type for objects in this Table.
122    *
123    * @return the name for the Persistent class
124    */
125   public String superclassMainUnambiguous() {
126     return (superclass == null)
127             ? "JdbcPersistent"
128             : superclass.mainClassUnambiguous();
129   }
130 
131   /** 
132    * Calculate the full type for the superclass of the Persistent.
133    *
134    * @return the fully qualified name for the superclass
135    */
136   public String superclassMainFQName() {
137     return (superclass == null)
138             ? "org.melati.poem.JdbcPersistent"
139             : superclass.mainClassFQName();
140   }
141 
142   /** 
143    * Calculate the name of the superclass of the Persistent.
144    *
145    * @return the short name for the superclass
146    */
147   public String superclassMainShortName() {
148     return (superclass == null)
149             ? "JdbcPersistent"
150             : superclass.mainClassShortName();
151   }
152 
153   /** 
154    * Calculate the type for this Table.
155    * 
156    * @return the unambiguous name
157    */
158   public String superclassTableUnambiguous() {
159     return (superclass == null)
160             ? getTableClassName()
161             : superclass.tableMainClassUnambiguous();
162   }
163 
164   private String getTableClassName() {
165     return projectName + "Table";
166   }
167 
168   /** 
169    * Calculate the full type for the superclass of this  Table.
170    * 
171    * @return the superclass fully qualified name
172    */
173   public String superclassTableFQName() {
174     return (superclass == null)
175             ? packageName + "." + getTableClassName()
176             : superclass.tableMainClassFQName();
177   }
178   /** 
179    * Calculate the type for the superclass of this  Table.
180    * 
181    * @return the superclass short name
182    */
183   public String superclassTableShortName() {
184     return (superclass == null)
185             ? getTableClassName()
186             : superclass.tableMainClassShortName();
187   }
188 
189   String importMainString() {
190 //    return (hidesOther && !hidden) ? "import " + mainClassFQName() + ";\n" 
191 //                                   : "";
192       return "import " + mainClassFQName() + ";\n";
193   }
194 
195   String importTableString() {
196 //  return (hidesOther && !hidden) ? "import " + tableMainClassFQName() + 
197 //                           ";\n" : "";
198     return "import " + tableMainClassFQName() + ";\n";
199   }
200   String importPersistentString() {
201     return (hidden) ? 
202         "// hidden import " + mainClassFQName() +  ";\n" 
203         : "import " + mainClassFQName() +  ";\n" ;
204   }
205 
206   String baseClassFQName() {
207     return packageName + ".generated." + capitalisedShortName + "Base";
208   }
209 
210   String baseClassShortName() {
211     return capitalisedShortName + "Base";
212   }
213 
214   String baseClassUnambiguous() {
215     return (hidden)
216               ? baseClassFQName()
217               : baseClassShortName();
218   }
219 
220   /**
221    * @return the fully qualified name of the main class for this table
222    */
223   public String mainClassFQName() {
224     return objectFQName;
225   }
226 
227   /**
228    * @return the name of the main class for this table
229    */
230   public String mainClassShortName() {
231     return StringUtils.capitalised(capitalisedShortName);
232   }
233 
234   /**
235    * @return a name for this class which will properly refer to this table
236    * given the import lines we put in all our generated flies
237    */
238   public String mainClassUnambiguous() {
239     return (hidden || hidesOther)
240               ? mainClassFQName()
241               : mainClassShortName();
242   }
243 
244   /**
245    * We need to make sure that this is the
246    * same class as that returned by the root superclass of the same
247    * name because you cannot override a function and change its
248    * return type.
249    *
250    * @return type we should use when calling getXxxxTable().
251    */
252   public String mainClassRootReturnClass() {
253     TableNamingInfo root = getRootSameNamedSuperclass();
254     return (root != null)
255               ? root.mainClassUnambiguous() // should always be mainClassFQName
256               : mainClassUnambiguous();
257   }
258 
259   String tableBaseClassFQName() {
260     return packageName + ".generated." + capitalisedShortName + "TableBase";
261   }
262   String tableBaseClassShortName() {
263     return capitalisedShortName + "TableBase";
264   }
265 
266   String tableBaseClassUnambiguous() {
267     return (hidden)
268               ? tableBaseClassFQName()
269               : tableBaseClassShortName();
270   }
271 
272   String tableMainClassFQName() {
273     return objectFQName + "Table";
274   }
275   String tableMainClassShortName() {
276     return capitalisedShortName + "Table";
277   }
278   String subclassedTableMainClassShortName() {
279     return projectName + capitalisedShortName + "Table";
280   }
281 
282   String tableMainClassUnambiguous() {
283     return (hidden || hidesOther)
284                ? tableMainClassFQName()
285                : tableMainClassShortName();
286   }
287 
288   /**
289    * Find the return type we should use when calling getXxxxObject().
290    * We need to make sure that this is the
291    * same class as that returned by the root superclass of the same
292    * name because you cannot override a function and change its
293    * return type.
294    * <p>
295    * NB if the superclass is abstract then we
296    *
297    * @return the table root return class 
298    */
299   public String tableMainClassRootReturnClass() {
300     TableNamingInfo root = getRootSameNamedSuperclass();
301     return (root != null) // should always be tableMainClassFQName
302               ? root.tableMainClassUnambiguous() 
303               : tableMainClassUnambiguous();
304   }
305 
306   String rootTableAccessorName() {
307     return "get" + tableMainClassShortName();
308   }
309   public String leafTableAccessorName() {
310     if (hidesOther)
311       return "get" + projectName + tableMainClassShortName();
312     else 
313       return "get" + tableMainClassShortName();
314   }
315 
316   /**
317    * Find the top-most superclass of this table which has the same (short) name.
318    * @return the TableNamingInfo of the superclass or null if there is none
319    */
320   protected TableNamingInfo getRootSameNamedSuperclass() {
321     TableNamingInfo curr = this;
322     while (curr != null && curr.superclass != null &&
323              curr.capitalisedShortName.equals(curr.superclass.capitalisedShortName))
324       curr = curr.superclass;
325     return (curr != this) ? curr : null;
326   }
327 
328 }
329