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