KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > tools > schemaframework > SchemaManager


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21
22 // Copyright (c) 1998, 2006, Oracle. All rights reserved.
23
package oracle.toplink.essentials.tools.schemaframework;
24
25 import java.io.Writer JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.HashSet JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.Vector JavaDoc;
30 import oracle.toplink.essentials.exceptions.DatabaseException;
31 import oracle.toplink.essentials.exceptions.TopLinkException;
32 import oracle.toplink.essentials.exceptions.ValidationException;
33 import oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor;
34 import oracle.toplink.essentials.internal.sequencing.Sequencing;
35 import oracle.toplink.essentials.logging.SessionLog;
36 import oracle.toplink.essentials.internal.sessions.DatabaseSessionImpl;
37 import oracle.toplink.essentials.descriptors.ClassDescriptor;
38 import oracle.toplink.essentials.internal.sessions.AbstractSession;
39 import oracle.toplink.essentials.sequencing.DefaultSequence;
40 import oracle.toplink.essentials.sequencing.NativeSequence;
41 import oracle.toplink.essentials.sequencing.Sequence;
42 import oracle.toplink.essentials.sequencing.TableSequence;
43
44 /**
45  * <p>
46  * <b>Purpose</b>: Define all user level protocol for development time database manipulation.
47  * <p>
48  * <b>Responsibilities</b>:
49  * <ul>
50  * <li> Define protocol for schema creation.
51  * <li> Define any useful testing specific protocol.
52  * </ul>
53  */

54 public class SchemaManager {
55     protected DatabaseSessionImpl session;
56     protected Writer JavaDoc createSchemaWriter;
57     protected Writer JavaDoc dropSchemaWriter;
58     protected boolean createSQLFiles = true;
59
60     public SchemaManager(DatabaseSessionImpl session) {
61         this.session = session;
62     }
63
64     public SchemaManager(oracle.toplink.essentials.sessions.DatabaseSession session) {
65         this.session = ((DatabaseSessionImpl)session);
66     }
67
68     protected Writer JavaDoc getDropSchemaWriter() {
69         if (null == dropSchemaWriter) {
70             return createSchemaWriter;
71         } else {
72             return dropSchemaWriter;
73         }
74     }
75
76     /**
77      * PUBLIC: If the schema manager is writing to a writer, append this string
78      * to that writer.
79      */

80     public void appendToDDLWriter(String JavaDoc stringToWrite) {
81         // If this method is called, we know that it is the old case and
82
// it would not matter which schemaWriter we use as both the
83
// create and drop schemaWriters are essentially the same.
84
// So just pick one.
85
appendToDDLWriter(createSchemaWriter, stringToWrite);
86     }
87
88     public void appendToDDLWriter(Writer JavaDoc schemaWriter, String JavaDoc stringToWrite) {
89         if (schemaWriter == null) {
90             return;//do nothing. Ignore append request
91
}
92
93         try {
94             schemaWriter.write(stringToWrite);
95             schemaWriter.flush();
96         } catch (java.io.IOException JavaDoc ioException) {
97             throw ValidationException.fileError(ioException);
98         }
99     }
100
101     /**
102      * INTERNAL:
103      * builds the field names based on the type read in from the builder
104      */

105     public void buildFieldTypes(TableDefinition tableDef) {
106         tableDef.buildFieldTypes(getSession());
107     }
108
109     /**
110      * PUBLIC:
111      * Close the schema writer.
112      */

113     public void closeDDLWriter() {
114         closeDDLWriter(createSchemaWriter);
115         if (null != dropSchemaWriter) {
116             closeDDLWriter(dropSchemaWriter);
117         }
118     }
119
120     public void closeDDLWriter(Writer JavaDoc schemaWriter) {
121         if (schemaWriter == null) {
122             return;
123         }
124
125         try {
126             schemaWriter.flush();
127             schemaWriter.close();
128             schemaWriter = null;
129         } catch (java.io.IOException JavaDoc ioException) {
130             throw ValidationException.fileError(ioException);
131         }
132     }
133
134     /**
135      * Use the table definition to add the constraints to the database, this is normally done
136      * in two steps to avoid dependencies.
137      */

138     public void createConstraints(TableDefinition tableDefinition) throws TopLinkException {
139         if (shouldWriteToDatabase()) {
140             tableDefinition.createConstraintsOnDatabase(getSession());
141         } else {
142             tableDefinition.setCreateSQLFiles(createSQLFiles);
143             tableDefinition.createConstraints(getSession(), createSchemaWriter);
144         }
145     }
146
147     /**
148      * Use the definition object to create the schema entity on the database.
149      * This is used for creating tables, views, procedures ... etc ...
150      */

151     public void createObject(DatabaseObjectDefinition databaseObjectDefinition) throws TopLinkException {
152         if (shouldWriteToDatabase()) {
153             databaseObjectDefinition.createOnDatabase(getSession());
154         } else {
155             databaseObjectDefinition.createObject(getSession(), createSchemaWriter);
156             if (createSQLFiles){
157                 this.appendToDDLWriter(createSchemaWriter, getSession().getPlatform().getStoredProcedureTerminationToken());
158             }
159             this.appendToDDLWriter(createSchemaWriter, "\n");
160         }
161     }
162
163     /**
164      * Create all the receiver's sequences on the database for all of the loaded descriptors.
165      */

166     public void createSequences() throws TopLinkException {
167         createOrReplaceSequences(true);
168     }
169
170     /**
171      * Drop and recreate all the receiver's sequences on the database for all of the loaded descriptors.
172      */

173     public void replaceSequences() throws TopLinkException {
174         createOrReplaceSequences(false);
175     }
176
177     /**
178      * Common implementor for createSequence and replaceSequence
179      */

180     protected void createOrReplaceSequences(boolean create) throws TopLinkException {
181         Sequencing sequencing = getSession().getSequencing();
182
183         if ((sequencing == null) || (sequencing.whenShouldAcquireValueForAll() == Sequencing.AFTER_INSERT)) {
184             // Not required on Sybase native etc.
185
return;
186         }
187
188         // Prepare table and sequence definitions
189
// table name mapped to TableDefinition
190
HashMap JavaDoc tableDefinitions = new HashMap JavaDoc();
191
192         // sequence name to SequenceDefinition
193
HashSet JavaDoc sequenceDefinitions = new HashSet JavaDoc();
194
195         // remember the processed - to handle each sequence just once.
196
HashSet JavaDoc processedSequenceNames = new HashSet JavaDoc();
197         buildTableAndSequenceDefinitions(sequenceDefinitions, processedSequenceNames, tableDefinitions);
198         processTableDefinitions(tableDefinitions, create);
199         processSequenceDefinitions(sequenceDefinitions, create);
200     }
201     
202     /**
203      * Common implementor for createSequence and replaceSequence
204      */

205     protected void createOrReplaceSequences(boolean create, boolean drop) throws TopLinkException {
206         Sequencing sequencing = getSession().getSequencing();
207
208         if ((sequencing == null) || (sequencing.whenShouldAcquireValueForAll() == Sequencing.AFTER_INSERT)) {
209             // Not required on Sybase native etc.
210
return;
211         }
212
213         // Prepare table and sequence definitions
214
// table name mapped to TableDefinition
215
HashMap JavaDoc tableDefinitions = new HashMap JavaDoc();
216
217         // sequence name to SequenceDefinition
218
HashSet JavaDoc sequenceDefinitions = new HashSet JavaDoc();
219
220         // remember the processed - to handle each sequence just once.
221
HashSet JavaDoc processedSequenceNames = new HashSet JavaDoc();
222
223         buildTableAndSequenceDefinitions(sequenceDefinitions, processedSequenceNames, tableDefinitions);
224         processTableDefinitions(tableDefinitions, create);
225         processSequenceDefinitions(sequenceDefinitions, drop);
226     }
227
228     private void buildTableAndSequenceDefinitions(final HashSet JavaDoc sequenceDefinitions,
229             final HashSet JavaDoc processedSequenceNames, final HashMap JavaDoc tableDefinitions) {
230         Iterator JavaDoc descriptors = getSession().getDescriptors().values().iterator();
231
232         while (descriptors.hasNext()) {
233             ClassDescriptor descriptor = (ClassDescriptor)descriptors.next();
234
235             if (descriptor.usesSequenceNumbers()) {
236                 String JavaDoc seqName = descriptor.getSequenceNumberName();
237
238                 if (seqName == null) {
239                     seqName = getSession().getDatasourcePlatform().getDefaultSequence().getName();
240                 }
241
242                 if (processedSequenceNames.contains(seqName)) {
243                     continue;
244                 }
245
246                 processedSequenceNames.add(seqName);
247
248                 Sequence sequence = getSession().getDatasourcePlatform().getSequence(seqName);
249
250                 if (sequence.shouldAcquireValueAfterInsert()) {
251                     continue;
252                 }
253
254                 SequenceDefinition sequenceDefinition = buildSequenceDefinition(sequence);
255
256                 if (sequenceDefinition == null) {
257                     continue;
258                 }
259
260                 sequenceDefinitions.add(sequenceDefinition);
261
262                 TableDefinition tableDefinition = sequenceDefinition.buildTableDefinition();
263
264                 if (tableDefinition != null) {
265                     String JavaDoc tableName = tableDefinition.getName();
266                     TableDefinition otherTableDefinition = (TableDefinition)tableDefinitions.get(tableName);
267
268                     if (otherTableDefinition != null) {
269                         // check for a conflict; if there is one - throw a ValidationException
270
} else {
271                         tableDefinitions.put(tableName, tableDefinition);
272                     }
273                 }
274             }
275         }
276     }
277
278     private void processTableDefinitions(final HashMap JavaDoc tableDefinitions, final boolean create) throws TopLinkException {
279
280         // create tables
281
Iterator JavaDoc itTableDefinitions = tableDefinitions.values().iterator();
282
283         while (itTableDefinitions.hasNext()) {
284             TableDefinition tableDefinition = (TableDefinition)itTableDefinitions.next();
285
286             // CR 3870467, do not log stack
287