KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > j2ee > persistence > wizard > fromdb > SelectedTables


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.j2ee.persistence.wizard.fromdb;
21
22 import java.io.IOException JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.Collections JavaDoc;
25 import java.util.EnumSet JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.HashSet JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Map JavaDoc;
30 import java.util.Set JavaDoc;
31 import java.util.TreeMap JavaDoc;
32 import javax.swing.event.ChangeEvent JavaDoc;
33 import javax.swing.event.ChangeListener JavaDoc;
34 import org.netbeans.api.project.SourceGroup;
35 import org.netbeans.modules.j2ee.persistence.dd.JavaPersistenceQLKeywords;
36 import org.netbeans.modules.j2ee.persistence.entitygenerator.EntityMember;
37 import org.openide.filesystems.FileObject;
38 import org.openide.util.NbBundle;
39 import org.openide.util.Utilities;
40
41 /**
42  *
43  * @author Andrei Badea
44  */

45 public final class SelectedTables {
46
47     // not private because used in tests
48
enum Problem { NO_JAVA_IDENTIFIER, JPA_QL_IDENTIFIER, ALREADY_EXISTS };
49
50     private final PersistenceGenerator persistenceGen;
51     private final Map JavaDoc<Table, String JavaDoc> table2ClassName = new HashMap JavaDoc<Table, String JavaDoc>();
52     private final Map JavaDoc<Table, Set JavaDoc<Problem>> table2Problems = new TreeMap JavaDoc<Table, Set JavaDoc<Problem>>();
53
54     private final ChangeListener JavaDoc tableClosureListener = new TableClosureListener();
55     private final ChangeSupport changeSupport = new ChangeSupport(this);
56
57     private TableClosure tableClosure;
58     private SourceGroup location;
59     private String JavaDoc packageName;
60     private FileObject targetFolder;
61
62     private Set JavaDoc<Table> validatedTables = Collections.emptySet();
63
64     public SelectedTables(PersistenceGenerator persistenceGen, TableClosure tableClosure, SourceGroup location, String JavaDoc packageName) throws IOException JavaDoc {
65         assert persistenceGen != null;
66
67         this.persistenceGen = persistenceGen;
68         setTableClosureAndTargetFolder(tableClosure, location, packageName);
69     }
70
71     /**
72      * Sets the new table closure and target folder at once. This is needed
73      * in order to avoid multiple validations in the table closure and the target
74      * folder were set separately.
75      */

76     public void setTableClosureAndTargetFolder(TableClosure tableClosure, SourceGroup location, String JavaDoc packageName) throws IOException JavaDoc {
77         assert tableClosure != null;
78
79         boolean tableClosureChanged = changeTableClosure(tableClosure);
80         boolean targetFolderChanged = changeTargetFolder(location, packageName);
81
82         if (tableClosureChanged || targetFolderChanged) {
83             revalidateTables();
84         }
85     }
86
87     /**
88      * Sets the new target folder.
89      */

90     public void setTargetFolder(SourceGroup location, String JavaDoc packageName) throws IOException JavaDoc {
91         if (changeTargetFolder(location, packageName)) {
92             revalidateTables();
93         }
94     }
95
96     /**
97      * Sets the new table closure, returning true
98      * if the new table closure was different than the current value and
99      * false otherwise.
100      */

101     private boolean changeTableClosure(TableClosure tableClosure) {
102         if (!tableClosure.equals(this.tableClosure)) {
103             if (this.tableClosure != null) {
104                 this.tableClosure.removeChangeListener(tableClosureListener);
105             }
106             this.tableClosure = tableClosure;
107             table2ClassName.clear();
108             this.tableClosure.addChangeListener(tableClosureListener);
109             return true;
110         }
111         return false;
112     }
113
114     /**
115      * Sets the new target folder, returning true
116      * if the new target folder was different from the current value and
117      * false otherwise.
118      */

119     private boolean changeTargetFolder(SourceGroup location, String JavaDoc packageName) throws IOException JavaDoc {
120         if (!Utilities.compareObjects(location, this.location) || !Utilities.compareObjects(packageName, this.packageName)) {
121             this.location = location;
122             this.packageName = packageName;
123
124             if (location != null && packageName != null) {
125                 targetFolder = SourceGroupSupport.getFolderForPackage(location, packageName, false);
126             } else {
127                 targetFolder = null;
128             }
129             return true;
130         }
131         return false;
132     }
133
134     /**
135      * Adds a new change listener, which will be called when the list of selected
136      * tables changes, when a class name for a table changes or when the
137      * return value of {@link #getFirstProblemDisplayName} changes.
138      */

139     public void addChangeListener(ChangeListener JavaDoc listener) {
140         changeSupport.addChangeListener(listener);
141     }
142
143     /**
144      * Removes a change listener.
145      */

146     public void removeChangeListener(ChangeListener JavaDoc listener) {
147         changeSupport.removeChangeListener(listener);
148     }
149
150     private void revalidateTables() {
151         validatedTables = Collections.emptySet();
152         table2Problems.clear();
153         validateTables();
154     }
155
156     private void validateTables() {
157         Set JavaDoc<Table> addedTables = new HashSet JavaDoc<Table>(tableClosure.getSelectedTables());
158         addedTables.removeAll(validatedTables);
159
160         Set JavaDoc<Table> removedTables = new HashSet JavaDoc<Table>(validatedTables);
161         removedTables.removeAll(tableClosure.getSelectedTables());
162
163         for (Table table : removedTables) {
164             table2Problems.remove(table);
165         }
166         for (Table table : addedTables) {
167             putProblems(table, validateClassName(getClassName(table)));
168         }
169         validatedTables = new HashSet JavaDoc<Table>(tableClosure.getSelectedTables());
170
171         changeSupport.fireChange();
172     }
173
174     /**
175      * Returns a sorted list of selected tables. This returns the same
176      * tables as {@link TableClosure#getSelectedTables}.
177      */

178     public List JavaDoc<Table> getTables() {
179         List JavaDoc<Table> result = new ArrayList JavaDoc<Table>(tableClosure.getSelectedTables());
180         Collections.sort(result);
181         return result;
182     }
183
184     /**
185      * Returns the class name for the given table.
186      */

187     public String JavaDoc getClassName(Table table) {
188         assert table != null;
189
190         String JavaDoc className = table2ClassName.get(table);
191         if (className == null) {
192             className = EntityMember.makeClassName(table.getName());
193             className = persistenceGen.generateEntityName(className);
194         }
195         return className;
196     }
197
198     /**
199      * Sets the class name for the given table.
200      */

201     public void setClassName(Table table, String JavaDoc className) {
202         assert table != null;
203         assert className != null;
204
205         table2ClassName.put(table, className);
206         putProblems(table, validateClassName(className));
207
208         changeSupport.fireChange();
209     }
210
211     private void putProblems(Table table, Set JavaDoc<Problem> problems) {
212         if (problems.isEmpty()) {
213             table2Problems.remove(table);
214         } else {
215             table2Problems.put(table, problems);
216         }
217     }
218
219     private Set JavaDoc<Problem> validateClassName(String JavaDoc className) {
220         Set JavaDoc<Problem> problems = EnumSet.noneOf(Problem.class);
221         if (!Utilities.isJavaIdentifier(className)) {
222             problems.add(Problem.NO_JAVA_IDENTIFIER);
223         }
224         if (JavaPersistenceQLKeywords.isKeyword(className)) {
225             problems.add(Problem.JPA_QL_IDENTIFIER);
226         }
227         if (targetFolder != null && targetFolder.getFileObject(className, "java") != null) { // NOI18N
228
problems.add(Problem.ALREADY_EXISTS);
229         }
230         return problems;
231     }
232
233     public void ensureUniqueClassNames() {
234         // make sure proposed class names are unique in the target package
235
Set JavaDoc<Table> tables = tableClosure.getSelectedTables();
236         if (targetFolder != null) {
237             for (Table t : tables) {
238                 String JavaDoc className = getClassName(t);
239                 boolean existingFile = (targetFolder.getFileObject(className, "java") != null); // NOI18N
240

241                 if (existingFile){
242                     setClassName(t, className+'1');
243                 }
244             }
245         }
246     }
247
248     /**
249      * Returns the display name of the first problem regarding a table
250      * or its class name (the class name may be an invalid Java identifier or
251      * a JPA QL reserved keyword, or the class might exist in the target
252      * folder.
253      */

254     public String JavaDoc getFirstProblemDisplayName() {
255         Map.Entry JavaDoc<Table, Set JavaDoc<Problem>> firstProblemEntry = getFirstProblemEntry();
256         if (firstProblemEntry == null) {
257             return null;
258         }
259         return getProblemDisplayNameForTable(firstProblemEntry.getKey(),
260             firstProblemEntry.getValue());
261     }
262
263     private Map.Entry JavaDoc<Table, Set JavaDoc<Problem>> getFirstProblemEntry() {
264         Set JavaDoc<Map.Entry JavaDoc<Table, Set JavaDoc<Problem>>> problemEntries = table2Problems.entrySet();
265         if (problemEntries.isEmpty()) {
266             return null;
267         }
268         return problemEntries.iterator().next();
269     }
270
271     private String JavaDoc getProblemDisplayNameForTable(Table table, Set JavaDoc<Problem> problems) {
272         Problem problem = problems.iterator().next();
273         return getProblemDisplayName(problem, getClassName(table));
274     }
275
276     String JavaDoc getProblemDisplayNameForTable(Table table) {
277         Set JavaDoc<Problem> problems = table2Problems.get(table);
278         return ((problems != null) ?
279             getProblemDisplayNameForTable(table, problems) : null);
280     }
281
282     boolean hasProblem(Table table) {
283         return table2Problems.containsKey(table);
284     }
285
286     /**
287      * Not private because used in tests.
288      */

289     Problem getFirstProblem() {
290         Map.Entry JavaDoc<Table, Set JavaDoc<Problem>> firstProblemEntry = getFirstProblemEntry();
291         if (firstProblemEntry == null) {
292             return null;
293         }
294         Set JavaDoc<Problem> problems = firstProblemEntry.getValue();
295         return problems.iterator().next();
296     }
297
298     private static String JavaDoc getProblemDisplayName(Problem problem, String JavaDoc className) {
299         switch (problem) {
300             case NO_JAVA_IDENTIFIER:
301                 return NbBundle.getMessage(SelectedTables.class, "ERR_NoJavaIdentifier", className);
302
303             case JPA_QL_IDENTIFIER:
304                 return NbBundle.getMessage(SelectedTables.class, "ERR_ReservedQLKeyword", className);
305
306             case ALREADY_EXISTS:
307                 return NbBundle.getMessage(SelectedTables.class, "ERR_AlreadyExists", className);
308
309             default:
310                 assert false : problem + " should be handled in getProblemDisplayName()"; // NOI18N
311
}
312         return null;
313     }
314
315     private final class TableClosureListener implements ChangeListener JavaDoc {
316
317         public void stateChanged(ChangeEvent JavaDoc event) {
318             validateTables();
319         }
320     }
321 }
322
Popular Tags