KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > xquark > mapper > storage > PersistentCollectionInfo


1 /*
2  * This file belongs to the XQuark distribution.
3  * Copyright (C) 2003 Universite de Versailles Saint-Quentin.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307.
18  * You can also get it at http://www.gnu.org/licenses/lgpl.html
19  *
20  * For more information on this software, see http://www.xquark.org.
21  */

22
23 package org.xquark.mapper.storage;
24
25 import java.sql.*;
26 import java.util.NoSuchElementException JavaDoc;
27 import java.util.StringTokenizer JavaDoc;
28
29 import org.xquark.mapper.RepositoryConnection;
30 import org.xquark.mapper.RepositoryException;
31 import org.xquark.mapper.dbms.AbstractConnection;
32 import org.xquark.mapper.dbms.TableInfo;
33 import org.xquark.mapper.metadata.CollectionInfo;
34 import org.xquark.mapper.metadata.RepositoryConstants;
35 import org.xquark.xml.xdbc.Configurable;
36 import org.xquark.xml.xdbc.XMLDBCException;
37 import org.xquark.xml.xdbc.XMLDBCNotRecognizedException;
38
39 /** Data structure that corresponds to the storage table for collection
40  * configuration and is used when creating a collection with the
41  * repository object.
42  * <p>This object contains all its JDBC calls and owns a connection
43  * in order to perform database access on his own</p>
44  */

45
46 public class PersistentCollectionInfo implements RepositoryConstants
47 {
48     private static final String JavaDoc RCSRevision = "$Revision: 1.1 $";
49     private static final String JavaDoc RCSName = "$Name: $";
50     
51     /** XMLCollection IDs */
52     private String JavaDoc collectionName = null;
53     private short CID = -1;
54     private short parentCID = 0;
55     private short maxCID = -1;
56     
57     private CollectionInfo config;
58     private TableInfo configTable;
59     private String JavaDoc selectLockStmt;
60
61     /////////////////////////////////////
62
// Storage JDBC variables
63
/////////////////////////////////////
64

65     /** Connection object used by this data object. */
66     private AbstractConnection connection;
67
68     /** java.sql objects used to fetch the whole data set from the database. */
69     private Statement stmt = null;
70     private ResultSet rs = null;
71
72     /** Constructor. This constructor should be used for listing collectionss
73      * an reading configuration.
74      * @param connection the AbstractConnection object used by this object.
75      */

76     public PersistentCollectionInfo(TableInfo configTable, AbstractConnection connection)
77     {
78         this.config = new CollectionInfo(false);
79         this.connection = connection;
80         this.configTable = configTable;
81         initStatements();
82     }
83
84     /** Constructor used for collection creation.
85      * @param name the name of the repository.
86      * @param config a CollectionInfo object.
87      * @param connection the JDBC Connection object used by this object.
88      * @throws RepositoryException application exception.
89      * @see org.xquark.mapper.CollectionInfo#repositoryType
90      */

91     public PersistentCollectionInfo(
92                                     TableInfo configTable,
93                                     String JavaDoc name,
94                                     CollectionInfo config,
95                                     short maxCID,
96                                     AbstractConnection connection
97                                     )
98     {
99         this.connection = connection;
100         this.configTable = configTable;
101         this.config = config;
102         this.collectionName = name;
103         this.maxCID = maxCID;
104         initStatements();
105     }
106     
107     public PersistentCollectionInfo(
108                                     TableInfo configTable,
109                                     String JavaDoc name,
110                                     Configurable config,
111                                     short maxCID,
112                                     AbstractConnection connection
113                                     )
114     {
115         this(configTable, name, new CollectionInfo(config), maxCID, connection);
116     }
117
118     private void initStatements()
119     {
120         selectLockStmt = connection.getLockSelectStatement("CID", configTable.getName(), "ORDER BY CID");
121     }
122
123     /** Returns the string name of the repository.
124      * @return the repository name.
125      */

126     public String JavaDoc getCollectionName()
127     {
128         return this.collectionName;
129     }
130
131     public short getCollectionID()
132     {
133         return CID;
134     }
135
136     public CollectionInfo getCollectionInfo()
137     {
138         return config;
139     }
140     
141     /** Sets the name of the repository.
142      * @param name the collection name.
143      */

144     public void setCollectionName(String JavaDoc name)
145     {
146         collectionName = name;
147     }
148
149     public void setCollectionID(short id)
150     {
151         CID = id;
152     }
153
154     /** Builds a String in order to displays the information of this configuration.
155      * @return the string representing the repository features.
156      */

157     public String JavaDoc toString()
158     {
159         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(super.toString());
160
161         buffer.append("Name:\t\t");
162         buffer.append(collectionName);
163         buffer.append("\nId :\t\t");
164         buffer.append(CID);
165         buffer.append("\n");
166         
167         return buffer.toString();
168     }
169
170     /**
171      * Save this object data into a config table row with batch style.
172      * Automatic flush is proceeded when max size is reached
173      * @throws SQLException if a database access error occurs.
174      */

175     public void createRow()
176     throws SQLException, RepositoryException
177     {
178         PreparedStatement pStmt = null;
179         Statement stmt = null;
180         ResultSet rs =null;
181         int wCID = RepositoryConstants.SEQUENCE_FIRST_VALUE;
182
183         // create a transaction for keeping locks
184
connection.start();
185         
186         try
187         {
188             // select & lock the whole collection table
189
stmt = connection.getConnection().createStatement();
190             rs = stmt.executeQuery(selectLockStmt);
191             
192             while (rs.next())
193             {
194                 if (rs.getShort(1) != wCID)
195                     break;
196                 wCID++;
197             }
198             rs.close();
199             rs = null;
200             stmt.close();
201             stmt = null;
202             
203             if (wCID > maxCID)
204                 throw new RepositoryException(RepositoryException.OUT_OF_RANGE,
205                     "Maximum number of collections is reached");
206             else
207                 CID =(short)wCID;
208             
209             // preparation of PreparedStatement
210
pStmt = connection.getConnection().prepareStatement(configTable.getInsertStatement());
211             pStmt.setString(1, collectionName.toUpperCase());
212             pStmt.setShort(2, CID);
213             pStmt.setShort(3, parentCID);
214             pStmt.setByte(4, config.getType());
215             pStmt.setString(5, config.getDescription());
216             pStmt.setString(6, config.getMappingID());
217             pStmt.setByte(7, config.getDocOIDSize());
218             pStmt.setByte(8, config.getDocOIDSize()); // bucketSize = docSize
219
pStmt.setShort(9, config.getDocOIDPreallocationSize()); // bucketSize = docSize
220
pStmt.setString(10, generateConfigString());
221             pStmt.executeUpdate();
222             
223         }
224         catch (SQLException e)
225         {
226             connection.rollback();
227             throw new RepositoryException(RepositoryException.DB_ERROR,
228                 "JDBC error while creating a new entry in collection table", e);
229         }
230         finally
231         {
232             connection.commit();
233             if (rs != null)
234                 rs.close();
235             if (stmt != null)
236                 stmt.close();
237             if (pStmt != null)
238                 pStmt.close();
239         }
240     }
241
242     /** Free all resources (JDBC)
243      * @throws RepositoryException application error
244      */

245     public void close()
246     {
247         // release statement
248
try {
249             if (rs != null)
250                 rs.close();
251             if (stmt != null)
252                 stmt.close();
253             connection = null;
254         }
255         catch(SQLException e) {
256             // no op
257
}
258     }
259     
260     public void retrieveDataSet()
261     throws SQLException, RepositoryException
262     {
263         retrieveDataSet((short)-1);
264     }
265     /**
266      * Launch the full table entry retrieving.
267      * @param all if true, even system repositories will be retrieved
268      * @throws SQLException if a database access error occurs.
269      */

270     public void retrieveDataSet(short type)
271     throws SQLException, RepositoryException
272     {
273         stmt = connection.getConnection().createStatement();
274         String JavaDoc query = configTable.getSelectAllStatement();
275         if (type >= 0)
276             query += " WHERE TYPE=" + type;
277         try {
278             rs = stmt.executeQuery(query);
279         }
280         catch (SQLException e) {
281             stmt.close();
282             throw e;
283         }
284     }
285
286     /** get the next row from database and store it in the current object.
287      * @throws SQLException if a database access error occurs.
288      * @return true, if a row was fetched, false if no more rows.
289      */

290     public boolean fetchNextRow()
291     throws SQLException, XMLDBCException
292     {
293         if (stmt == null)
294             return false;
295         try {
296             if (fetchNextResult(rs))
297                 return true;
298             else
299             {
300                 config.setWriteProtected(true);
301                 rs.close();
302                 stmt.close();
303                 stmt = null; // prevent closing 2 times
304
return false; // If no more row found
305
}
306         }
307         catch (SQLException e) {
308             rs.close();
309             stmt.close();
310             throw e;
311         }
312     }
313
314     /** get row from the database corresponding to the collection ID passed and store it in he current object.
315      * @param name the name of the collection
316      * @throws SQLException if a database access error occurs.
317      * @return true, if a row was fetched, false if no more rows.
318      */

319     public boolean fetchRow(String JavaDoc name)
320     throws SQLException, XMLDBCException
321     {
322         Statement stmt = connection.getConnection().createStatement();
323         ResultSet rs = null;
324         try {
325             rs = stmt.executeQuery(configTable.getSelectAllStatement()
326                                     + " WHERE NAME='" + name + "'");
327             
328             if (fetchNextResult(rs))
329             {
330                 config.setWriteProtected(true);
331                 return true; // Take first row encountered
332
}
333             else
334                 return false; // If no row found
335
}
336         finally
337         {
338             if (rs != null)
339                 rs.close();
340             stmt.close();
341         }
342     }
343
344     /**
345      * remove row from database corresponding to the collection ID passed.
346      * @param name the name of the collection
347      * @throws SQLException if a database access error occurs.
348      */

349     public void deleteRow(String JavaDoc name)
350     throws SQLException
351     {
352         connection.executeUpdate("DELETE FROM " + configTable.getName()
353             + " WHERE NAME='" + name + "'");
354     }
355     
356     public void deleteRow()
357     throws SQLException
358     {
359         deleteRow(collectionName);
360     }
361     
362     public void rename(String JavaDoc oldName, String JavaDoc newName)
363     throws SQLException
364     {
365         connection.executeUpdate("UPDATE " + configTable.getName()
366             + " SET NAME='" + newName + "' WHERE NAME='" + oldName + "'");
367     }
368     
369     /** Analyse a configuration string and fills object variables.
370      * @param configString the configuration string to parse.
371      */

372     private void parseConfigString(String JavaDoc configString)
373     throws XMLDBCException
374     {
375         String JavaDoc keyword;
376         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(configString, "<");
377         while (st.hasMoreTokens())
378         {
379             try {
380                 keyword = st.nextToken();
381                 if (keyword.startsWith("maxTextDataLength"))
382                     config.setProperty(RepositoryConnection.TEXT_LENGTH_PROPERTY,
383                         keyword.substring(keyword.indexOf('>') + 1));
384                 else if (keyword.startsWith("maxExtraDataLength"))
385                     config.setProperty(RepositoryConnection.EXTRA_DATA_LENGTH_PROPERTY,
386                         keyword.substring(keyword.indexOf('>') + 1));
387                 else if (keyword.startsWith("useSchemaPrefixes"))
388                     config.setFeature(RepositoryConnection.USE_SCHEMA_PREFIXES_FEATURE,
389                         Boolean.valueOf(keyword.substring(keyword.indexOf('>') + 1)).booleanValue());
390             }
391             catch (NoSuchElementException JavaDoc e) {
392                 // no op
393
}
394         }
395     }
396     
397     /** Produces a configuration string ready to be stored in a text columm.
398      * @return the configuration string.
399      */

400     private String JavaDoc generateConfigString()
401     {
402         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
403         try
404         {
405             buf.append("<maxTextDataLength>");
406             buf.append(config.getProperty(RepositoryConnection.TEXT_LENGTH_PROPERTY));
407             buf.append("<maxExtraDataLength>");
408             buf.append(config.getProperty(RepositoryConnection.EXTRA_DATA_LENGTH_PROPERTY));
409             buf.append("<useSchemaPrefixes>");
410             buf.append(config.getFeature(RepositoryConnection.USE_SCHEMA_PREFIXES_FEATURE));
411         }
412         catch (XMLDBCNotRecognizedException e)
413         {
414             // no op : internal use
415
throw new RuntimeException JavaDoc("Internal error: unknown feature or property.");
416         }
417         
418         return buf.toString();
419     }
420     
421     private boolean fetchNextResult(ResultSet rs)
422     throws SQLException, XMLDBCException
423     {
424         if(rs.next())
425         {
426             collectionName = rs.getString(1);
427             CID = rs.getShort(2);
428             parentCID = rs.getShort(3);
429             config.setType(rs.getByte(4));
430             config.setDescription(rs.getString(5));
431             config.setMappingID(rs.getString(6));
432             config.setDocOIDSize(rs.getByte(7));
433             config.setDocOIDPreallocationSize(rs.getShort(9));
434             parseConfigString(rs.getString(10));
435             return true;
436         }
437         else
438             return false; // If no more row found
439
}
440 }
441
Popular Tags