View Javadoc

1   package org.apache.torque.templates.transformer.om;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import static org.apache.torque.templates.transformer.om.OMColumnTransformer.CURRENT_DATE;
23  import static org.apache.torque.templates.transformer.om.OMColumnTransformer.CURRENT_TIME;
24  import static org.apache.torque.templates.transformer.om.OMColumnTransformer.CURRENT_TIMESTAMP;
25  import static org.apache.torque.templates.transformer.om.OMColumnTransformer.GET_DEFAULT_DATE_METHOD_NAME;
26  import static org.apache.torque.templates.transformer.om.OMColumnTransformer.GET_DEFAULT_TIMESTAMP_METHOD_NAME;
27  import static org.apache.torque.templates.transformer.om.OMColumnTransformer.GET_DEFAULT_TIME_METHOD_NAME;
28  
29  import java.io.InputStreamReader;
30  import java.io.Reader;
31  import java.io.UnsupportedEncodingException;
32  import java.util.List;
33  
34  import org.apache.commons.lang.ObjectUtils;
35  import org.apache.commons.lang.StringUtils;
36  import org.apache.torque.generator.control.ControllerState;
37  import org.apache.torque.generator.processor.string.Camelbacker;
38  import org.apache.torque.generator.processor.string.WrapReservedJavaWords;
39  import org.apache.torque.generator.source.SourceElement;
40  import org.apache.torque.generator.source.transform.AttributeTransformer;
41  import org.apache.torque.generator.source.transform.SourceTransformerException;
42  import org.apache.torque.templates.TemplateOptionName;
43  import org.apache.torque.templates.TorqueSchemaAttributeName;
44  import org.apache.torque.templates.TorqueSchemaElementName;
45  import org.apache.torque.templates.TorqueSchemaIdMethod;
46  import org.apache.torque.templates.TorqueSchemaInheritance;
47  import org.apache.torque.templates.transformer.CollectAttributeSetTrueTransformer;
48  
49  /**
50   * Transforms the tables and views in the OM model.
51   */
52  public class OMTableAndViewTransformer extends AttributeTransformer
53  {
54      /** The transformer for the column child elements. */
55      private static OMColumnTransformer columnTransformer
56              = new OMColumnTransformer();;
57  
58      /** The transformer for the foreign keys referencing this table. */
59      private static OMReferencingForeignKeyTableTransformer
60              referencingForeignKeyTableTransformer
61                  = new OMReferencingForeignKeyTableTransformer();
62  
63      /** The transformer collecting the primary key columns in this table. */
64      private static CollectAttributeSetTrueTransformer primaryKeyTransformer
65              = new CollectAttributeSetTrueTransformer();
66  
67      /** The Camelbacker for producing the java name from the table name. */
68      private static Camelbacker javaNameCamelbacker = new Camelbacker();
69  
70      /** Prevents reserved java words. */
71      private static WrapReservedJavaWords reservedJavaWordsWrapper
72              = new WrapReservedJavaWords();
73  
74      public OMTableAndViewTransformer() throws SourceTransformerException
75      {
76          super(getTransformerProperties());
77      }
78  
79      /**
80       * Returns the Reader to read the transformer properties from.
81       *
82       * @return the reader, not null.
83       */
84      private static Reader getTransformerProperties()
85      {
86          try
87          {
88              return new InputStreamReader(
89                      OMTableAndViewTransformer.class.getResourceAsStream(
90                              "OMTableTransformer.properties"),
91                      "ISO-8859-1");
92          }
93          catch (UnsupportedEncodingException e)
94          {
95              // will not happen
96              throw new RuntimeException(e);
97          }
98      }
99  
100     @Override
101     public SourceElement transform(
102             SourceElement tableElement,
103             ControllerState controllerState)
104         throws SourceTransformerException
105     {
106         checkElementName(tableElement);
107         setJavaNameAttribute(tableElement);
108         setFieldNameAttribute(tableElement);
109         setIdMethodAttribute(tableElement);
110         setSequenceAttributeIfNecessary(tableElement);
111         setBaseClass(tableElement, controllerState);
112 
113         // sets all the attributes defined in OMTableTransformer.properties
114         super.transform(tableElement, controllerState);
115 
116         setManagerClassNameAttributes(tableElement, controllerState);
117         setPeerImplFieldNameAttribute(tableElement);
118         setPeerImplGetterAttribute(tableElement);
119         setPeerImplSetterAttribute(tableElement);
120 
121         setSaveAttributes(tableElement, controllerState);
122 
123         createInheritanceColumnChildIfNecessary(tableElement);
124         primaryKeyTransformer.transform(tableElement, controllerState,
125                 TorqueSchemaElementName.COLUMN,
126                 TorqueSchemaAttributeName.PRIMARY_KEY,
127                 TableChildElementName.PRIMARY_KEYS);
128 
129         // position is one based
130         int columnPosition = 1;
131         for (SourceElement element : tableElement.getChildren(
132                 TorqueSchemaElementName.COLUMN))
133         {
134             columnTransformer.transform(
135                     element,
136                     controllerState,
137                     columnPosition);
138             columnPosition++;
139         }
140 
141         setCreateDefaultDateMethodsAttributes(tableElement);
142 
143         referencingForeignKeyTableTransformer.transform(
144                 tableElement,
145                 controllerState);
146         return tableElement;
147     }
148 
149     /**
150      * Checks that the table element has the correct element name.
151      *
152      * @param tableElement the table element to check, not null.
153      *
154      * @throws IllegalArgumentException if the name of the element is wrong.
155      */
156     private void checkElementName(SourceElement tableElement)
157     {
158         if (!TorqueSchemaElementName.TABLE.getName().equals(
159                 tableElement.getName())
160             && !TorqueSchemaElementName.VIEW.getName().equals(
161                     tableElement.getName()))
162         {
163             throw new IllegalArgumentException("Illegal element Name "
164                     + tableElement.getName());
165         }
166     }
167 
168     /**
169      * Sets the javaName attribute of the table element, if not
170      * already set.
171      *
172      * @param tableElement the table element, not null.
173      *
174      * @throws SourceTransformerException if both attributes javaName and name
175      *         are not set on the tableElement.
176      */
177     public static void setJavaNameAttribute(SourceElement tableElement)
178             throws SourceTransformerException
179     {
180         // set javaName attribute
181         Object javaName = tableElement.getAttribute(
182                 TorqueSchemaAttributeName.JAVA_NAME);
183         if (javaName == null)
184         {
185             Object inputName = tableElement.getAttribute(
186                     TorqueSchemaAttributeName.NAME);
187             if (inputName == null)
188             {
189                 throw new SourceTransformerException("The required attribute "
190                         + TorqueSchemaAttributeName.NAME
191                         + " on element "
192                         + tableElement.getName()
193                         + " is null");
194             }
195             javaName = javaNameCamelbacker.process(inputName.toString());
196             tableElement.setAttribute(
197                     TorqueSchemaAttributeName.JAVA_NAME,
198                     javaName);
199         }
200     }
201 
202     protected void setIdMethodAttribute(SourceElement tableElement)
203             throws SourceTransformerException
204     {
205         Object idMethod = tableElement.getAttribute(
206                 TorqueSchemaAttributeName.ID_METHOD);
207         if (idMethod == null)
208         {
209             idMethod = tableElement.getParent().getAttribute(
210                     TorqueSchemaAttributeName.DEFAULT_ID_METHOD);
211             if (idMethod == null)
212             {
213                 throw new SourceTransformerException("The attribute "
214                         + TorqueSchemaAttributeName.DEFAULT_ID_METHOD
215                         + " is not set on the database element "
216                         + " and no id method is given on table "
217                         + tableElement.getName());
218             }
219             tableElement.setAttribute(
220                     TorqueSchemaAttributeName.ID_METHOD,
221                     idMethod);
222         }
223     }
224 
225     protected void setSequenceAttributeIfNecessary(SourceElement tableElement)
226     {
227         // set sequence attribute
228         if (!TorqueSchemaIdMethod.NATIVE.getName().equals(
229                 tableElement.getAttribute(TorqueSchemaAttributeName.ID_METHOD)))
230         {
231             return;
232         }
233 
234         List<SourceElement> idMethodParams = tableElement.getChildren(
235                 TorqueSchemaElementName.ID_METHOD_PARAMETER);
236         if (idMethodParams.isEmpty()
237             && tableElement.getAttribute(TableAttributeName.SEQUENCE_NAME) == null)
238         {
239             tableElement.setAttribute(
240                     TableAttributeName.SEQUENCE_NAME,
241                     (String) tableElement.getAttribute(
242                           TorqueSchemaAttributeName.NAME)
243                         + "_SEQ");
244         }
245         else
246         {
247             tableElement.setAttribute(
248                     TableAttributeName.SEQUENCE_NAME,
249                         idMethodParams.get(0).getAttribute(
250                             TorqueSchemaAttributeName.VALUE.getName()));
251         }
252     }
253 
254 
255     protected void setManagerClassNameAttributes(
256                 SourceElement tableElement,
257                 ControllerState controllerState)
258             throws SourceTransformerException
259     {
260         // Managers must be named after an interface if there is one.
261         String interfaceName = (String) tableElement.getAttribute(
262                 TorqueSchemaAttributeName.INTERFACE);
263         if (interfaceName == null)
264         {
265             String managerClassName = controllerState.getStringOption(
266                     TemplateOptionName.OM_MANAGER_CLASS_NAME_PREFIX)
267                 + tableElement.getAttribute(TorqueSchemaAttributeName.JAVA_NAME)
268                 + controllerState.getStringOption(
269                     TemplateOptionName.OM_MANAGER_CLASS_NAME_SUFFIX);
270             tableElement.setAttribute(
271                     TableAttributeName.MANAGER_CLASS_NAME,
272                     managerClassName);
273             String baseManagerClassName = controllerState.getStringOption(
274                     "torque.om.className.baseManagerClassNamePrefix")
275                 + tableElement.getAttribute(TorqueSchemaAttributeName.JAVA_NAME)
276                 + controllerState.getStringOption(
277                     "torque.om.className.baseManagerClassNameSuffix");
278             tableElement.setAttribute(
279                     TableAttributeName.BASE_MANAGER_CLASS_NAME,
280                     baseManagerClassName);
281         }
282         else
283         {
284             if (StringUtils.isBlank(interfaceName))
285             {
286                 throw new SourceTransformerException("The attribute "
287                         + TorqueSchemaAttributeName.INTERFACE
288                         + " is blank on table "
289                         + tableElement.getName());
290             }
291             int dotPosition = interfaceName.lastIndexOf(".");
292             if (dotPosition != -1)
293             {
294                 interfaceName = interfaceName.substring(dotPosition + 1);
295             }
296             if (StringUtils.isBlank(interfaceName))
297             {
298                 throw new SourceTransformerException("The attribute "
299                         + TorqueSchemaAttributeName.INTERFACE
300                         + " ends with a dot on table "
301                         + tableElement.getName());
302             }
303 
304             // first character upper case
305             if (interfaceName.length() == 1)
306             {
307                 interfaceName = interfaceName.toUpperCase();
308             }
309             else
310             {
311                 interfaceName = interfaceName.substring(0, 1).toUpperCase()
312                     + interfaceName.substring(1);
313             }
314 
315             String managerClassName = controllerState.getOption(
316                     TemplateOptionName.OM_MANAGER_CLASS_NAME_PREFIX)
317                 + interfaceName
318                 + controllerState.getOption(
319                         TemplateOptionName.OM_MANAGER_CLASS_NAME_SUFFIX);
320             tableElement.setAttribute(
321                     TableAttributeName.MANAGER_CLASS_NAME,
322                     managerClassName);
323             String baseManagerClassName = controllerState.getOption(
324                     "torque.om.className.baseManagerClassNamePrefix")
325                 + interfaceName
326                 + controllerState.getOption(
327                     "torque.om.className.baseManagerClassNameSuffix");
328             tableElement.setAttribute(
329                     TableAttributeName.BASE_MANAGER_CLASS_NAME,
330                     baseManagerClassName);
331         }
332     }
333 
334     public void createInheritanceColumnChildIfNecessary(
335                 SourceElement tableElement)
336             throws SourceTransformerException
337     {
338         boolean inheritanceFound = false;
339         for (SourceElement columnElement : tableElement.getChildren(
340                 TorqueSchemaElementName.COLUMN))
341         {
342             if (TorqueSchemaInheritance.SINGLE.getValue().equals(
343                     columnElement.getAttribute(
344                         TorqueSchemaAttributeName.INHERITANCE)))
345             {
346                 if (inheritanceFound)
347                 {
348                     throw new SourceTransformerException(
349                             "more than one column with "
350                                 + TorqueSchemaAttributeName.INHERITANCE
351                                 + " set to \"single\" found in table "
352                                 + tableElement.getAttribute(
353                                         tableElement.getName()));
354                 }
355                 SourceElement inheritanceColumnElement
356                         = new SourceElement(
357                                 TableChildElementName.INHERITANCE_COLUMN);
358                 inheritanceColumnElement.getChildren().add(columnElement);
359                 tableElement.getChildren().add(inheritanceColumnElement);
360                 inheritanceFound = true;
361             }
362         }
363     }
364 
365     /**
366      * Sets the base class attribute on the table element if it is not
367      * already set.
368      *
369      * @param tableElement the table attribute to process, not null.
370      * @param controllerState the controller state, not null.
371      */
372     private void setBaseClass(
373             SourceElement tableElement,
374             ControllerState controllerState)
375     {
376         Object baseClass = tableElement.getAttribute(
377                 TorqueSchemaAttributeName.BASE_CLASS);
378         if (baseClass == null)
379         {
380             baseClass = tableElement.getParent().getAttribute(
381                     TorqueSchemaAttributeName.BASE_CLASS);
382         }
383         if (baseClass == null)
384         {
385             baseClass = controllerState.getOption(
386                     TemplateOptionName.OM_DB_OBJECT_DEFAULT_BASE_CLASS);
387         }
388         if (baseClass == null)
389         {
390             baseClass = "";
391         }
392         tableElement.setAttribute(
393                 TorqueSchemaAttributeName.BASE_CLASS,
394                 baseClass);
395     }
396 
397     /**
398      * Sets the fieldName attribute of the table element if it is not
399      * already set. The field name can be used to contain a database object
400      * corresponding to the table.
401      * The javaName attribute of the column must be set.
402      *
403      * @param tableElement the table element, not null.
404      */
405     protected void setFieldNameAttribute(SourceElement tableElement)
406     {
407         if (tableElement.getAttribute(JavaFieldAttributeName.FIELD_NAME)
408                 != null)
409         {
410             return;
411         }
412         String javaName = (String) tableElement.getAttribute(
413                 TorqueSchemaAttributeName.JAVA_NAME);
414         String fieldName = StringUtils.uncapitalize(javaName);
415         fieldName = reservedJavaWordsWrapper.process(fieldName);
416         tableElement.setAttribute(
417                 JavaFieldAttributeName.FIELD_NAME,
418                 fieldName);
419     }
420 
421     /**
422      * Sets the peerImplFieldName attribute of the table element if it is not
423      * already set. The field name can be used to contain a peer object
424      * corresponding to the table.
425      * The peerImplClassName attribute of the column must be already set
426      * when this method is called.
427      *
428      * @param tableElement the table element, not null.
429      */
430     protected void setPeerImplFieldNameAttribute(SourceElement tableElement)
431     {
432         if (tableElement.getAttribute(TableAttributeName.PEER_IMPL_FIELD_NAME)
433                 != null)
434         {
435             return;
436         }
437         String peerImplClassName = (String) tableElement.getAttribute(
438                 TableAttributeName.PEER_IMPL_CLASS_NAME);
439         String fieldName = StringUtils.uncapitalize(peerImplClassName);
440         fieldName = reservedJavaWordsWrapper.process(fieldName);
441         tableElement.setAttribute(
442                 TableAttributeName.PEER_IMPL_FIELD_NAME,
443                 fieldName);
444     }
445 
446     /**
447      * Sets the peerImplGetter attribute of the table element if it is not
448      * already set.
449      * The peerImplClassName attribute of the column must be already set
450      * when this method is called.
451      *
452      * @param tableElement the table element, not null.
453      */
454     public static void setPeerImplGetterAttribute(SourceElement tableElement)
455     {
456         if (tableElement.getAttribute(TableAttributeName.PEER_IMPL_GETTER)
457                 != null)
458         {
459             return;
460         }
461         String peerImplClassName = (String) tableElement.getAttribute(
462                 TableAttributeName.PEER_IMPL_CLASS_NAME);
463         String getter = "get" + peerImplClassName;
464         getter = reservedJavaWordsWrapper.process(getter);
465         tableElement.setAttribute(
466                 TableAttributeName.PEER_IMPL_GETTER,
467                 getter);
468     }
469 
470     /**
471      * Sets the peerImplSetter attribute of the table element if it is not
472      * already set.
473      * The peerImplClassName attribute of the column must be already set
474      * when this method is called.
475      *
476      * @param tableElement the table element, not null.
477      */
478     protected void setPeerImplSetterAttribute(SourceElement tableElement)
479     {
480         if (tableElement.getAttribute(TableAttributeName.PEER_IMPL_SETTER)
481                 != null)
482         {
483             return;
484         }
485         String peerImplClassName = (String) tableElement.getAttribute(
486                 TableAttributeName.PEER_IMPL_CLASS_NAME);
487         String setter = "set" + peerImplClassName;
488         setter = reservedJavaWordsWrapper.process(setter);
489         tableElement.setAttribute(
490                 TableAttributeName.PEER_IMPL_SETTER,
491                 setter);
492     }
493 
494     protected void setSaveAttributes(
495             SourceElement tableElement,
496             ControllerState controllerState)
497     {
498         // check save method location definitions (prio descending):
499         //   - Attribute saveMethodsInDbObjects in table
500         //   - option TemplateOptionName.OM_SAVE_METHODS_IN_DB_OBJECTS
501         String saveMethodLocationOptionName
502             = TemplateOptionName.OM_SAVE_METHODS_IN_DB_OBJECTS.getName();
503         String saveMethodLocationAttributeName
504                 = saveMethodLocationOptionName.substring(
505                         saveMethodLocationOptionName.lastIndexOf('.') + 1);
506         boolean saveMethodsInDbObjects;
507         if (tableElement.getAttribute(saveMethodLocationAttributeName) != null)
508         {
509             saveMethodsInDbObjects = Boolean.parseBoolean(
510                     tableElement.getAttribute(saveMethodLocationAttributeName)
511                         .toString());
512         }
513         else
514         {
515             saveMethodsInDbObjects = controllerState.getBooleanOption(
516                     TemplateOptionName.OM_SAVE_METHODS_IN_DB_OBJECTS);
517         }
518 
519         if (!saveMethodsInDbObjects)
520         {
521             tableElement.setAttribute(
522                     TableAttributeName.SAVE_METHOD_INPUT_TYPE,
523                     tableElement.getAttribute(
524                             TableAttributeName.DB_OBJECT_CLASS_NAME));
525             tableElement.setAttribute(
526                     TableAttributeName.SAVE_METHOD_TO_SAVE_VARIABLE,
527                     "toSave");
528         }
529     }
530 
531     protected void setCreateDefaultDateMethodsAttributes(
532             SourceElement tableElement)
533     {
534         for (SourceElement column : tableElement.getChildren(
535                 TorqueSchemaElementName.COLUMN))
536         {
537             if ("java.util.Date".equals(
538                     column.getAttribute(JavaFieldAttributeName.FIELD_TYPE)))
539             {
540                 String defaultValue = ObjectUtils.toString(column.getAttribute(
541                         TorqueSchemaAttributeName.DEFAULT));
542                 if (CURRENT_DATE.equalsIgnoreCase(defaultValue))
543                 {
544                     if (tableElement.getAttribute(
545                             TableAttributeName.GET_CURRENT_DATE_METHOD_NAME)
546                         == null)
547                     {
548                         tableElement.setAttribute(
549                                 TableAttributeName.GET_CURRENT_DATE_METHOD_NAME,
550                                 GET_DEFAULT_DATE_METHOD_NAME);
551                     }
552                 }
553                 else if (CURRENT_TIME.equalsIgnoreCase(defaultValue))
554                 {
555                     if (tableElement.getAttribute(
556                             TableAttributeName.GET_CURRENT_TIME_METHOD_NAME)
557                         == null)
558                     {
559                         tableElement.setAttribute(
560                                 TableAttributeName.GET_CURRENT_TIME_METHOD_NAME,
561                                 GET_DEFAULT_TIME_METHOD_NAME);
562                     }
563                 }
564                 else if (CURRENT_TIMESTAMP.equalsIgnoreCase(defaultValue))
565                 {
566                     if (tableElement.getAttribute(
567                         TableAttributeName.GET_CURRENT_TIMESTAMP_METHOD_NAME)
568                         == null)
569                     {
570                         tableElement.setAttribute(
571                             TableAttributeName.GET_CURRENT_TIMESTAMP_METHOD_NAME,
572                             GET_DEFAULT_TIMESTAMP_METHOD_NAME);
573                     }
574                 }
575             }
576         }
577     }
578 }