KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > finalist > jaggenerator > SkeletValidator


1 /*
2  * SkeletValidator.java
3  *
4  * Created on November 25, 2004, 1:10 PM
5  */

6
7 package com.finalist.jaggenerator;
8
9 import com.finalist.jaggenerator.modules.*;
10
11 import javax.swing.tree.TreeNode JavaDoc;
12 import javax.swing.tree.TreePath JavaDoc;
13 import java.util.*;
14
15 /**
16  * @author Rudie Ekkelenkamp.
17  */

18 public class SkeletValidator {
19     private Root root = null;
20     private javax.swing.JTree JavaDoc tree = null;
21     private ConsoleLogger logger = null;
22     private HashMap entitiesByTableName = null;
23
24     /**
25      * Creates a new instance of SkeletValidator
26      */

27     public SkeletValidator(Root root, javax.swing.JTree JavaDoc tree, HashMap entitiesByTableName, ConsoleLogger logger) {
28         this.root = root;
29         this.tree = tree;
30         this.logger = logger;
31         this.entitiesByTableName = entitiesByTableName;
32     }
33
34
35     /**
36      * Check on projectname, description, datasource name, jndi-name and mapping, etc..
37      *
38      * @return null if valid, returns a message string in case of an error.
39      */

40     public String JavaDoc validateSkelet() {
41         boolean atLeastOneCompositePK = false;
42         boolean valid = true;
43         boolean autoGeneratedStringInvalidHibernate = false;
44         boolean isRelatedEntityComposite = false;
45         String JavaDoc message = "";
46         String JavaDoc businessTier = (String JavaDoc) root.config.getTemplateSettings().get(JagGenerator.TEMPLATE_BUSINESS_TIER);
47         String JavaDoc webTier = (String JavaDoc) root.config.getTemplateSettings().get(JagGenerator.TEMPLATE_WEB_TIER);
48         String JavaDoc appServer = (String JavaDoc) root.config.getTemplateSettings().get(JagGenerator.TEMPLATE_APPLICATION_SERVER);
49         String JavaDoc useJava5 = (String JavaDoc) root.config.getTemplateSettings().get(JagGenerator.TEMPLATE_USE_JAVA5);
50
51         // Do some basic checks before generation starts.
52
try {
53             // Make sure the projectname has been set!
54
if (root.app.nameText.getText() == null || "".equals(root.app.nameText.getText())) {
55                 valid = false;
56                 message += "No valid application name has been set in the 'Application settings'.\r\n";
57             } else if (!root.app.nameText.getText().toLowerCase().equals(root.app.nameText.getText())) {
58                 // Check if it is a valid name! Should be lowercase only!
59
valid = false;
60                 message += "No valid application name in the 'Application settings'. Should be only lowercase!.\r\n";
61             }
62         } catch (Exception JavaDoc e) {
63             valid = false;
64             message += "No valid application name has been set in the 'Application settings'.\r\n";
65         }
66
67         try {
68             // Make sure the applicationname has been set!
69
if (root.app.descriptionText.getText() == null || "".equals(root.app.descriptionText.getText())) {
70                 valid = false;
71                 message += "No valid application description has been set in the 'Application settings'.\r\n";
72             } else {
73                 // Check if the first character is uppercase!
74
String JavaDoc firstChar = root.app.descriptionText.getText().substring(0, 1);
75                 if (!firstChar.toUpperCase().equals(firstChar)) {
76                     valid = false;
77                     message += "No valid application description has been set in the 'Application settings'. First character should be uppercase!\r\n";
78                 }
79             }
80         } catch (Exception JavaDoc e) {
81             valid = false;
82             message += "No valid application description has been set in the 'Application settings'.\r\n";
83         }
84
85         try {
86             // Make sure the rootpackage has been set!
87
if (root.app.rootPackageText.getText() == null || "".equals(root.app.rootPackageText.getText())) {
88                 valid = false;
89                 message += "No valid root package set in the 'Application settings'.\r\n";
90             }
91         } catch (Exception JavaDoc e) {
92             valid = false;
93             message += "No valid root package set in the 'Application settings'.\r\n";
94         }
95
96         try {
97             // Make sure the applicationname has been set!
98
if (root.datasource.jdbcURLCombo.getSelectedItem() == null || "".equals(root.datasource.jdbcURLCombo.getSelectedItem())) {
99                 valid = false;
100                 message += "No valid datasource URL set in the Datasource form.\r\n";
101             }
102         } catch (Exception JavaDoc e) {
103             valid = false;
104             message += "No valid datasource URL set in the Datasource form.\r\n";
105         }
106
107         try {
108             // Make sure the datasource has been set!
109
if (root.datasource.jndiText.getText() == null || "".equals(root.datasource.jndiText.getText()) || "jdbc/".equals(root.datasource.jndiText.getText())) {
110                 valid = false;
111                 message += "No valid datasource jndi-name set in the Datasource form.\r\n";
112             }
113         } catch (Exception JavaDoc e) {
114             valid = false;
115             message += "No valid datasource jndi-name set in the Datasource form.\r\n";
116         }
117
118
119         HashMap entityRefs = new HashMap();
120         ArrayList el = root.getEntityEjbs();
121         for (int i = 0; i < el.size(); i++) {
122             Entity e = (Entity) el.get(i);
123             // Create a hashmap with all current entity refs.
124
entityRefs.put(e.getRefName(), null);
125         }
126
127         // Check if there have been entities marked as association entities without having 2 foreign keys.
128
for (int i = 0; i < el.size(); i++) {
129             Entity entity = (Entity) el.get(i);
130             if ("true".equals(entity.getIsAssociationEntity())) {
131                 // Now check if it is a valid association entity.
132
if (entity.getRelations() != null && entity.getRelations().size() == 2 && entity.getFields().size() == 2) {
133                     // It's an entity with exaclty 2 foreign keys (targetMultiple is false).
134
if (((Relation) entity.getRelations().get(0)).isTargetMultiple() &&
135                             ((Relation) entity.getRelations().get(1)).isTargetMultiple()
136                             ) {
137                         // OK, it's a valid association.
138
} else {
139                         // Both relation should be many-to-one relations.
140
valid = false;
141                         message += "Entity " + entity.getName() + " is not a valid assocation Entity.\r\nThere should be exactly 2 many-to-one relations in the assocation entity.\r\n";
142                     }
143                 } else {
144                     // Not valid. Exactly 2 forein keys are required.
145
valid = false;
146                     message += "Entity " + entity.getName() + " is not a valid assocation Entity.\r\nThere should be exactly 2 many-to-one relations in the assocation entity.\r\n";
147                 }
148             }
149
150
151         }
152
153         // Validate that the entity beans 'within' the session beans actually exist..
154
try {
155             ArrayList sl = root.getSessionEjbs();
156             for (int i = 0; i < sl.size(); i++) {
157                 Session s = (Session) sl.get(i);
158                 ArrayList allRefs = s.getEntityRefs();
159                 for (int j = 0; j < allRefs.size(); j++) {
160                     if (!entityRefs.containsKey(allRefs.get(j))) {
161                         valid = false;
162                         message += "The reference " + allRefs.get(j) + " in Service Bean " + s.getRefName() + " doesn't exist .\r\n";
163                     }
164                 }
165                 // Make sure that all the entity refs are defined!
166
}
167         } catch (Exception JavaDoc e) {
168             valid = false;
169             message += "Error in Service Bean.\r\n";
170         }
171
172         // Validate the Primary Keys on the Entity EJBs and composite primary keys.!
173
try {
174             // Make sure the applicationname has been set!
175
ArrayList nl = root.getEntityEjbs();
176             for (int i = 0; i < nl.size(); i++) {
177                 Entity e = (Entity) nl.get(i);
178                 List relations = e.getRelations();
179                 for (int r = 0; r < relations.size(); r++) {
180                     Relation relation = (Relation) relations.get(r);
181                     if (relation.getRelatedEntity().isCompositeKey()) {
182                         // The target entity of a relation shouldn't be a composite.
183
// JAG doesn't support this.
184
isRelatedEntityComposite = true;
185                     }
186
187                 }
188                 //Make sure that a display name maps one of its fields.
189
String JavaDoc displayName = "";
190                 boolean validDisplayName = false;
191                 if (e.getDisplayName() == null || "".equals(e.getDisplayName().toString())) {
192                     // Always valid if not set.
193
validDisplayName = true;
194                 } else {
195                     displayName = e.getDisplayName().toString();
196                 }
197                 
198                 // Iterate over all entity fields. Make sure that autoGeneratedCheckBox has not been
199
// Marked for foreign keys.
200
List fields = e.getFields();
201                 for (int j = 0; j < fields.size(); j++) {
202                     Field field = (Field) fields.get(j);
203                     if (displayName.equals(field.getName().toString())) {
204                         validDisplayName = true;
205                     }
206                     if (field.autoGeneratedCheckBox.isSelected() && field.foreignKeyCheckBox.isSelected() && "false".equals(e.getIsAssociationEntity()) ) {
207                         logger.log("Field: " + field.getName() + " of entity : " + e.getName() + " cannot have autogenerated primary key selected and be a foreign key!");
208                         valid = false;
209                         message += "Field: " + field.getName() + " of entity : " + e.getName() + " cannot have autogenerated primary key selected and be a foreign key!.\r\n";
210                     }
211                     if (field.autoGeneratedCheckBox.isSelected()) {
212                         if ("java.lang.String".equalsIgnoreCase(field.getType())) {
213                             // In this case, check the size.
214
// For the hibernate uuid.hex generator, the size should be >= 32
215
String JavaDoc fieldSize = field.getSize();
216                             try {
217                                 int size = Integer.parseInt(fieldSize);
218                                 if (size < 32) {
219                                     autoGeneratedStringInvalidHibernate = true;
220                                 }
221                             } catch (Exception JavaDoc ex) {
222                                 // Size could not be determined.
223
// Assume that size was not set and the size will be large enough.
224
}
225                         }
226                     }
227
228                 }
229                 if (!validDisplayName) {
230                     // No valid name found for the display name.
231
logger.log("No valid display name set: " + displayName);
232                     valid = false;
233                     message += "Display name " + displayName + " of entity : " + e.getName() + " should be a field of this entity.";
234                 }
235                 if (e.isCompositeCombo.getSelectedItem().equals("true") && e.isAssociationEntity.getSelectedItem().equals("false")) {
236                     // If composite is set to true,
237
// The primary key type should be set, the primary key field should be empty
238
// and the number of fields marked as primary key should be > 1.
239

240                     atLeastOneCompositePK = true;
241
242                     if (e.pKeyTypeText.getText() == null || e.pKeyTypeText.getText().equals("")) {
243                         // The primary key type is empty! This is an error!
244
logger.log("Primary key type is empty, but should be set since composite primary key has been set to true for Entity EJB: " + e.getRefName());
245                         valid = false;
246                         message += "Primary key type is empty, but should be set since composite primary key has been set to true for Entity EJB: " + e.getRefName() + ".\r\n";
247                     }
248
249                     if (e.pKeyText.getText() != null && !e.pKeyText.getText().equals("")) {
250                         // The primary key type is empty! This is an error!
251
logger.log("Primary key should be empty since the since composite primary key has been set to true for Entity EJB: " + e.getRefName());
252                         valid = false;
253                         message += "Primary key should be empty, since composite primary key has been set to true for Entity EJB: " + e.getRefName() + ".\r\n";
254                     }
255
256                     if (e.countPrimaryKeyFields() <= 1) {
257                         logger.log("In the field specifications for Entity EJB: " + e.getRefName() + " there should be more than one field that has been marked as primary key. Now only " + e.countPrimaryKeyFields() + " have been marked as primary key!");
258                         valid = false;
259                         message += "In the field specifications for Entity EJB: " + e.getRefName() + " there should be more than one field that has been marked as primary key. Now only " + e.countPrimaryKeyFields() + " have been marked as primary key!.\r\n";
260                     }
261
262                 } else if ((e.isCompositeCombo.getSelectedItem()).equals("false")) {
263                     if (e.pKeyTypeText.getText() == null || e.pKeyTypeText.getText().equals("")) {
264                         logger.log("No primary key set for entity bean: " + e.getRefName());
265                         valid = false;
266                         message += "No primary key set for entity bean: " + e.getRefName() + ".\r\n";
267                     }
268
269                     if (e.countPrimaryKeyFields() > 1) {
270                         // There should be just 1 primary key selected.
271
if (e.countPrimaryKeyFields() > 1) {
272                             logger.log("More than 1 primary key declared, while composite primary key is set to false for entity bean '" + e.getRefName() + "' .");
273                             valid = false;
274                             message += "More than 1 primary key declared, while composite primary key is set to false for entity bean '" + e.getRefName() + "' .\r\n";
275                         }
276                     }
277
278                     if (e.countPrimaryKeyFields() == 1) {
279                         // In this case we can check if the specified primary field and type, match the selected field.
280
String JavaDoc name = e.getFirstPrimaryKeyFieldName();
281                         String JavaDoc type = e.getPrimaryKeyClass();
282
283                         if ((name == null) || e.pKeyText.getText() == null || !name.equals(e.pKeyText.getText())) {
284                             logger.log("Non-matching primary keys! In entity bean '" + e.getRefName() + "' the field '" + name + "' has been marked as primary key, yet that entity has primary key '" + e.pKeyText.getText() + "'.");
285                             valid = false;
286                             message += "Non-matching primary keys! In entity bean '" + e.getRefName() + "' the field '" + name + "' has been marked as primary key, yet that entity has primary key '" + e.pKeyText.getText() + "'.\r\n";
287                         }
288                         if ((type == null) || e.pKeyTypeText.getText() == null || !type.equals(e.pKeyTypeText.getText())) {
289                             logger.log("Non-matching primary key types! In entity bean '" + e.getRefName() + "' the field '" + name + "' has been marked as primary key and has type '" + type + "', yet the entity has primary key type '" + e.pKeyTypeText.getText() + "'.");
290                             valid = false;
291                             message += "Non-matching primary key types! In entity bean '" + e.getRefName() + "' the field '" + name + "' has been marked as primary key and has type '" + type + "', yet the entity has primary key type '" + e.pKeyTypeText.getText() + "'.\r\n";
292                         }
293                     }
294                 }
295             }
296
297         } catch (Exception JavaDoc e) {
298             valid = false;
299             message += "Error in Entity Bean.\r\n";
300         }
301
302         //check for duplicate relation names within the same entity bean..
303
String JavaDoc badEntity = getEntityWithDuplicateRelationNames();
304         if (badEntity != null) {
305             valid = false;
306             message += "Entity bean " + badEntity + " has more than one relation with the same 'relation name'.\n" +
307                     "This is not allowed! Please rename at least one of the relation names.\r\n";
308         }
309
310         //check for relations that reference tables for which there is no entity bean..
311
List unreferencedEntities = getEntityWithUnreferencedRelations();
312         if (!unreferencedEntities.isEmpty()) {
313             valid = false;
314             StringBuffer JavaDoc tmp = new StringBuffer JavaDoc();
315             Iterator i = unreferencedEntities.iterator();
316             while (i.hasNext()) {
317                 String JavaDoc[] details = (String JavaDoc[]) i.next();
318                 if (!"".equals(details[2])) {
319                     tmp.append("Entity bean '" + details[0] + "' contains a relation '" + details[1] +
320                             "' that references a table '" + details[2] + "',\n" +
321                             "which doesn't correspond to any entity bean. Please either:\n" +
322                             "\ta) delete the relation,\n" +
323                             "\tb) create an entity bean for the table '" + details[2] + "', or\n" +
324                             "\tc) in the relation, correct the 'foreign table' value.\r\n");
325                 }
326             }
327             message += tmp.toString();
328         }
329
330         //check for any relation with empty/invalid data..
331
String JavaDoc relationErrorMessage = getRelationWithInvalidData();
332         if (relationErrorMessage != null) {
333             valid = false;
334             message += relationErrorMessage;
335         }
336         // Check if the related entity is a composite primary key.
337
if (isRelatedEntityComposite) {
338             String JavaDoc msg = "At least one target entity of a relation has a composite primary key. JAG doesn't support this.\r\n";
339             logger.log(msg);
340             valid = false;
341             message += msg;
342         }
343         // check if the Container-managed relations checkbox was unchecked BUT some CMRs are still defined!
344
String JavaDoc templateValue = (String JavaDoc) root.config.getTemplateSettings().get(JagGenerator.TEMPLATE_USE_RELATIONS);
345         if ("false".equalsIgnoreCase(templateValue)) {
346             // CMR was not selected. Make sure no relations are defined in the model!
347

348             // Now check if there are still some relations defined.
349
if (isRelationPresentInModel()) {
350                 valid = false;
351                 message += "The Container-managed relations checkbox in the Configuration screen was unchecked,\r\n" +
352                         "but there are still relations defined in the project.\r\n" +
353                         "Either enable Container-managed relations or remove the relations from the project.\r\n";
354             }
355         }
356
357         // Check business tier specific validations.
358
if (atLeastOneCompositePK) {
359             // In case Hibernate 2 was selected, No composites are supported!
360
if (JagGenerator.TEMPLATE_BUSINESS_TIER_HIBERNATE2.equalsIgnoreCase(businessTier) ||
361                     (JagGenerator.TEMPLATE_BUSINESS_TIER_HIBERNATE3.equalsIgnoreCase(businessTier) &&
362                             "false".equals(useJava5)
363                     )
364                     ) {
365                 logger.log("JAG does not support composite primary keys for Hibernate.");
366                 valid = false;
367                 message += "JAG does not support composite primary keys for Hibernate.\r\n";
368             }
369         }
370
371         if (autoGeneratedStringInvalidHibernate) {
372             // In case Hibernate 2 was selected, autogenerated string's should be at least size 32
373
if (JagGenerator.TEMPLATE_BUSINESS_TIER_HIBERNATE2.equalsIgnoreCase(businessTier) ||
374                     JagGenerator.TEMPLATE_BUSINESS_TIER_HIBERNATE3.equalsIgnoreCase(businessTier)
375                     ) {
376                 String JavaDoc msg = "At least one autogenerated primary key field of type string has size < 32. Hibernate cannot autogenerate this primary key.\r\n";
377                 logger.log(msg);
378                 valid = false;
379                 message += msg;
380             }
381         }
382
383         // Check application server specific validations.
384

385         if (JagGenerator.TEMPLATE_APPLICATION_SERVER_TOMCAT_5.equalsIgnoreCase(appServer)) {
386             // Only Hibernate is supported for deployment on tomcat.
387
// All other business tiers are dependent on an EJB container.
388
if (!JagGenerator.TEMPLATE_BUSINESS_TIER_HIBERNATE2.equalsIgnoreCase(businessTier) &&
389                     !JagGenerator.TEMPLATE_BUSINESS_TIER_HIBERNATE3.equalsIgnoreCase(businessTier)
390                     ) {
391                 String JavaDoc msg = "Only hibernate can be selected for the Tomcat application server.\r\n";
392                 logger.log(msg);
393                 valid = false;
394                 message += msg;
395             }
396
397         }
398
399         if (!JagGenerator.TEMPLATE_APPLICATION_SERVER_JBOSS_4_X.equalsIgnoreCase(appServer)) {
400             if (JagGenerator.TEMPLATE_BUSINESS_TIER_EJB3.equalsIgnoreCase(businessTier)) {
401                 // EJB3 is currently only supported for JBoss 4.X
402
logger.log("EJB3 is only supported for the JBoss 4.x application server.");
403                 valid = false;
404                 message += "EJB3 is only supported for the JBoss 4.x application server.\r\n";
405             }
406         }
407
408         if (!valid) {
409             return message;
410         } else {
411             return null;
412         }
413     }
414
415     private String JavaDoc getEntityWithDuplicateRelationNames() {
416         Iterator entities = root.getEntityEjbs().iterator();
417         while (entities.hasNext()) {
418             Entity entity = (Entity) entities.next();
419             Set relationNames = new HashSet();
420             for (int i = 0; i < entity.getChildCount(); i++) {
421                 TreeNode JavaDoc child = entity.getChildAt(i);
422                 if (child instanceof Relation) {
423                     Relation relation = (Relation) child;
424                     String JavaDoc relName = relation.getName();
425                     if (relationNames.contains(relName)) {
426                         tree.setSelectionPath(new TreePath JavaDoc(relation.getPath()));
427                         return entity.getRefName();
428                     }
429                     relationNames.add(relName);
430                 }
431             }
432         }
433         return null;
434     }
435
436     /**
437      * Finds any invalid relations, whose referenced foreign tables do not correspond to entity beans.
438      *
439      * @return List of String[] (never null), where:
440      * [0] is the name of the entity bean containing the relation
441      * [1] is the name of the relation
442      * [2] is the name of the referenced table, for which there is no entity bean.
443      */

444     private List getEntityWithUnreferencedRelations() {
445         ArrayList result = new ArrayList();
446         Iterator entities = root.getEntityEjbs().iterator();
447         while (entities.hasNext()) {
448             Entity entity = (Entity) entities.next();
449             for (int i = 0; i < entity.getChildCount(); i++) {
450                 TreeNode JavaDoc child = entity.getChildAt(i);
451                 if (child instanceof Relation) {
452                     Relation relation = (Relation) child;
453                     String JavaDoc referencedTable = relation.getForeignTable();
454                     if (entitiesByTableName.get(referencedTable) == null) {
455                         result.add(new String JavaDoc[]{entity.getName().toString(), relation.getName(), referencedTable});
456                     }
457                 }
458             }
459         }
460         return result;
461     }
462
463     private String JavaDoc getRelationWithInvalidData() {
464         Iterator entities = root.getEntityEjbs().iterator();
465         while (entities.hasNext()) {
466             Entity entity = (Entity) entities.next();
467             for (int i = 0; i < entity.getChildCount(); i++) {
468                 TreeNode JavaDoc child = entity.getChildAt(i);
469                 if (child instanceof Relation) {
470                     Relation relation = (Relation) child;
471
472                     String JavaDoc foreignTable = relation.getForeignTable();
473                     if (foreignTable == null || "".equals(foreignTable.trim())) {
474                         return "Relation '" + relation + "' within entity '" + entity.getName() +
475                                 "' has no value for 'foreign table' \n" +
476                                 "(the name of the table at the foreign side of this relation). \n" +
477                                 "Please provide a value!";
478                     }
479
480                     if (entitiesByTableName.get(foreignTable) == null) {
481                         return null;
482                         //this is needed because otherwise this method throws an NPE.
483
//@todo Really should look at improving this validation/error handling mess...
484
}
485
486                     String JavaDoc foreignPkColumn = relation.getForeignColumn();
487                     if (foreignPkColumn == null || "".equals(foreignPkColumn.trim())) {
488                         return "Relation '" + relation + "' within entity '" + entity.getName() +
489                                 "' has no value for 'foreign table primary key' \n" +
490                                 "(the name of the PK imported from table '" + relation.getForeignTable() +
491                                 "' that represents the foreign side of this relation). \n" +
492                                 "Please provide a value!";
493                     }
494
495                     boolean found = false;
496                     List fields = relation.getRelatedEntity().getFields();
497                     Iterator j = fields.iterator();
498                     while (j.hasNext()) {
499                         Field field = (Field) j.next();
500                         if (field.getColumnName().equalsIgnoreCase(foreignPkColumn)) {
501                             found = true;
502                             break;
503                         }
504                     }
505
506                     if (!found) {
507                         return "Relation '" + relation + "' within entity '" + relation.getRelatedEntity().getName() +
508                                 "' has an invalid value (" + foreignPkColumn + ") for 'foreign table primary key' \n" +
509                                 "(the name of the PK imported from table '" + relation.getRelatedEntity().getLocalTableName() +
510                                 "' that represents the foreign side of this relation). \n" +
511                                 "Please provide a valid value!";
512                     }
513
514                 }
515             }
516         }
517         return null;
518     }
519
520     /**
521      * Helper method to check if there are any relations present in the model.
522      */

523     private boolean isRelationPresentInModel() {
524         Iterator entities = root.getEntityEjbs().iterator();
525         while (entities.hasNext()) {
526             Entity entity = (Entity) entities.next();
527             //for every entity..
528
for (int i = 0; i < entity.getChildCount(); i++) {
529                 TreeNode JavaDoc child = entity.getChildAt(i);
530                 //for every relation in that entity..
531
if (child instanceof Relation) {
532                     return true;
533                 }
534             }
535         }
536         return false;
537     }
538
539
540 }
541
Popular Tags