KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > outerj > daisy > repository > serverimpl > model > LocalSchemaStrategy


1 /*
2  * Copyright 2004 Outerthought bvba and Schaubroeck nv
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.outerj.daisy.repository.serverimpl.model;
17
18 import org.outerj.daisy.repository.commonimpl.schema.*;
19 import org.outerj.daisy.repository.commonimpl.AuthenticatedUser;
20 import org.outerj.daisy.repository.commonimpl.LinkExtractorInfosImpl;
21 import org.outerj.daisy.repository.serverimpl.LocalRepositoryManager;
22 import org.outerj.daisy.jdbcutil.JdbcHelper;
23 import org.outerj.daisy.repository.serverimpl.EventHelper;
24 import org.outerj.daisy.repository.*;
25 import org.outerj.daisy.repository.query.SortOrder;
26 import org.outerj.daisy.repository.schema.*;
27 import org.apache.avalon.framework.logger.Logger;
28 import org.apache.commons.collections.primitives.ArrayLongList;
29 import org.apache.commons.collections.primitives.LongIterator;
30 import org.apache.xmlbeans.XmlObject;
31 import org.outerx.daisy.x10.*;
32
33 import java.math.BigDecimal JavaDoc;
34 import java.sql.*;
35 import java.util.*;
36 import java.util.Date JavaDoc;
37
38 public class LocalSchemaStrategy implements SchemaStrategy {
39     // the code of a static selection list as it will be stored in the database
40
private static final char STATIC_SELECTIONLIST_TYPE = 'S';
41     private static final char LINKQUERY_SELECTIONLIST_TYPE = 'L';
42     private static final char QUERY_SELECTIONLIST_TYPE = 'Q';
43     // the code that is stored in the database if no selection list is present for a field type
44
private static final char NO_SELECTIONLIST_TYPE = 'N';
45     private LocalRepositoryManager.Context context;
46     private Logger logger;
47     private JdbcHelper jdbcHelper;
48     private EventHelper eventHelper;
49
50     public LocalSchemaStrategy(LocalRepositoryManager.Context context, JdbcHelper jdbcHelper) {
51         this.context = context;
52         this.logger = context.getLogger();
53         this.jdbcHelper = jdbcHelper;
54         this.eventHelper = new EventHelper(context, jdbcHelper);
55     }
56
57     public void store(FieldTypeImpl fieldType) throws RepositoryException {
58         FieldTypeImpl.IntimateAccess fieldTypeInt = fieldType.getIntimateAccess(this);
59
60         if (!fieldTypeInt.getCurrentModifier().isInAdministratorRole())
61             throw new RepositoryException("Only Administrators can create or update field types.");
62
63         // do some validity checks
64
if (fieldType.getName() == null || fieldType.getName().length() < 1)
65             throw new RepositoryException("A field type must have a non-null and non-empty name assigned before saving it.");
66
67         Connection conn = null;
68         PreparedStatement stmt = null;
69         try {
70             conn = context.getDataSource().getConnection();
71             jdbcHelper.startTransaction(conn);
72
73             // check the name isn't already in use
74
stmt = conn.prepareStatement("select id from field_types where \"name\" = ?");
75             stmt.setString(1, fieldType.getName());
76             ResultSet rs = stmt.executeQuery();
77             if (rs.next()) {
78                 long id = rs.getLong(1);
79                 if (id != fieldType.getId())
80                     throw new RepositoryException("There is already a field type with the following name: \"" + fieldType.getName() + "\", used by the field type with id " + id);
81             }
82             rs.close();
83             stmt.close();
84
85             boolean isNew = false;
86             long id = fieldType.getId();
87             long labelId = fieldTypeInt.getLabelId();
88             long descriptionId = fieldTypeInt.getDescriptionId();
89             java.util.Date JavaDoc lastModified = new java.util.Date JavaDoc();
90             long lastModifier = fieldTypeInt.getCurrentModifier().getId();
91
92             char selectionListType = NO_SELECTIONLIST_TYPE;
93             if (fieldType.getSelectionList() != null) {
94                 if (fieldType.getSelectionList() instanceof StaticSelectionList) {
95                     selectionListType = STATIC_SELECTIONLIST_TYPE;
96                 } else if (fieldType.getSelectionList() instanceof LinkQuerySelectionList) {
97                     selectionListType = LINKQUERY_SELECTIONLIST_TYPE;
98                 } else if (fieldType.getSelectionList() instanceof QuerySelectionList) {
99                     selectionListType = QUERY_SELECTIONLIST_TYPE;
100                 }
101             }
102             
103             XmlObject eventDescription;
104             if (id == -1) {
105                 logger.debug("a new fieldtype will be inserted in the repository");
106                 isNew = true;
107                 // insert new record
108
id = context.getNextFieldTypeId();
109
110                 labelId = context.getNextLocalizedStringId();
111                 descriptionId = context.getNextLocalizedStringId();
112
113                 stmt = conn.prepareStatement("insert into field_types(id, \"name\", label_id, description_id, \"size\", valuetype, deprecated, acl_allowed, multivalue, selectionlist_type, selectlist_free_entry, last_modified, last_modifier, updatecount) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
114                 stmt.setLong(1, id);
115                 stmt.setString(2, fieldType.getName());
116                 stmt.setLong(3, labelId);
117                 stmt.setLong(4, descriptionId);
118                 stmt.setInt(5, fieldType.getSize());
119                 stmt.setInt(6, fieldType.getValueType().getCode());
120                 stmt.setBoolean(7, fieldType.isDeprecated());
121                 stmt.setBoolean(8, fieldType.isAclAllowed());
122                 stmt.setBoolean(9, fieldType.isMultiValue());
123                 stmt.setString(10, String.valueOf(selectionListType));
124                 stmt.setBoolean(11, fieldType.getAllowFreeEntry());
125                 stmt.setTimestamp(12, new Timestamp(lastModified.getTime()));
126                 stmt.setLong(13, lastModifier);
127                 stmt.setLong(14, 1L);
128                 stmt.execute();
129                 stmt.close();
130                 
131                 // store selectionlist
132
storeSelectionList(selectionListType, fieldType, id, conn);
133
134                 eventDescription = createFieldTypeCreatedEvent(fieldType, id, lastModified);
135             } else {
136                 logger.debug("update existing field type");
137
138                 // check if nobody else changed it in the meantime
139
stmt = conn.prepareStatement("select updatecount from field_types where id = ? " + jdbcHelper.getSharedLockClause());
140                 stmt.setLong(1, id);
141                 rs = stmt.executeQuery();
142                 if (!rs.next()) {
143                     throw new FieldTypeNotFoundException(id);
144                 } else {
145                     long dbUpdateCount = rs.getLong(1);
146                     if (dbUpdateCount != fieldType.getUpdateCount())
147                         throw new RepositoryException("The field type was concurrently changed by someone else.");
148                 }
149                 stmt.close(); // closes resultset too
150

151                 FieldTypeImpl oldFieldType = getFieldTypeById(fieldType.getId(), fieldTypeInt.getCurrentModifier());
152                 long newUpdateCount = fieldType.getUpdateCount() + 1;
153
154                 // update the record
155
stmt = conn.prepareStatement("update field_types set \"name\"=?, deprecated=?, acl_allowed=?, last_modified=?, last_modifier=?, updatecount = ?, selectionlist_type = ?, selectlist_free_entry = ?, \"size\" = ?, multivalue = ? where id=?");
156                 stmt.setString(1, fieldType.getName());
157                 stmt.setBoolean(2, fieldType.isDeprecated());
158                 stmt.setBoolean(3, fieldType.isAclAllowed());
159                 stmt.setTimestamp(4, new Timestamp(lastModified.getTime()));
160                 stmt.setLong(5, lastModifier);
161                 stmt.setLong(6, newUpdateCount);
162                 stmt.setString(7, String.valueOf(selectionListType));
163                 stmt.setBoolean(8, fieldType.getAllowFreeEntry());
164                 stmt.setInt(9, fieldType.getSize());
165                 stmt.setBoolean(10, fieldType.isMultiValue());
166                 stmt.setLong(11, id);
167                 stmt.execute();
168                 stmt.close();
169                 
170                 // remove old selection list, if any
171
deleteSelectionList(id, conn);
172
173                 // store the new selection list, if any
174
storeSelectionList(selectionListType, fieldType, id, conn);
175
176                 eventDescription = createFieldTypeUpdatedEvent(oldFieldType, fieldType, lastModified, newUpdateCount);
177             }
178
179             // store labels and descriptions, do this by deleting all entries and re-inserting them
180
storeLocalizedStrings(labelId, conn, fieldTypeInt.getLabels());
181             storeLocalizedStrings(descriptionId, conn, fieldTypeInt.getDescriptions());
182
183             eventHelper.createEvent(eventDescription, isNew ? "FieldTypeCreated" : "FieldTypeUpdated", conn);
184
185             conn.commit();
186
187             fieldTypeInt.setId(id);
188             fieldTypeInt.setLabelId(labelId);
189             fieldTypeInt.setDescriptionId(descriptionId);
190             fieldTypeInt.setLastModified(lastModified);
191             fieldTypeInt.setLastModifier(lastModifier);
192             fieldTypeInt.setUpdateCount(fieldType.getUpdateCount() + 1);
193
194             if (isNew)
195                 context.getRepositorySchema().fireChangeEvent(RepositorySchemaEventType.FIELD_TYPE_CREATED, id, fieldType.getUpdateCount());
196             else
197                 context.getRepositorySchema().fireChangeEvent(RepositorySchemaEventType.FIELD_TYPE_UPDATED, id, fieldType.getUpdateCount());
198         } catch (Throwable JavaDoc e) {
199             jdbcHelper.rollback(conn);
200             throw new RepositoryException("Error storing field type.", e);
201         } finally {
202             jdbcHelper.closeStatement(stmt);
203             jdbcHelper.closeConnection(conn);
204         }
205
206     }
207
208     private void storeSelectionList(char selectionListType, FieldTypeImpl fieldType, long fieldTypeId, Connection conn) throws SQLException, RepositoryException {
209         if (selectionListType == STATIC_SELECTIONLIST_TYPE) {
210             storeStaticSelectionList(fieldType, conn, fieldTypeId);
211         } else if (selectionListType == LINKQUERY_SELECTIONLIST_TYPE) {
212             storeLinkQuerySelectionList(fieldType, conn, fieldTypeId);
213         } else if (selectionListType == QUERY_SELECTIONLIST_TYPE) {
214             storeQuerySelectionList(fieldType, conn, fieldTypeId);
215         } else if (selectionListType != NO_SELECTIONLIST_TYPE) {
216             throw new RepositoryException("Invalid selection list type: " + selectionListType);
217         }
218     }
219
220     private void deleteSelectionList(long fieldTypeId, Connection conn) throws SQLException {
221         deleteStaticSelectionList(fieldTypeId, conn);
222         deleteLinkQuerySelectionList(fieldTypeId, conn);
223         deleteQuerySelectionList(fieldTypeId, conn);
224     }
225
226     private void deleteStaticSelectionList(long fieldTypeId, Connection conn) throws SQLException {
227         PreparedStatement stmt = null;
228         try {
229             /* load previous persisted label_ids from repository and use these
230              * to clear their corresponding localized strings, in order to avoid
231              * orphaned records in that table (suppose a label_id was created
232              * the previous time but is now no longer in the selection list,
233              * this would otherwise cause an orphaned record in the repository)
234              */

235             stmt = conn.prepareStatement("select label_id from selectionlist_data where fieldtype_id=?");
236             stmt.setLong(1, fieldTypeId);
237             ResultSet rs = stmt.executeQuery();
238             while (rs.next()) {
239                 long oldLabelId = rs.getLong(1);
240                 if (oldLabelId != -1)
241                     deleteLocalizedString(oldLabelId, conn);
242             }
243             stmt.close();
244
245             stmt = conn.prepareStatement("delete from selectionlist_data where fieldtype_id=?");
246             stmt.setLong(1, fieldTypeId);
247             stmt.execute();
248             stmt.close();
249         } finally {
250             jdbcHelper.closeStatement(stmt);
251         }
252     }
253
254     private void deleteLinkQuerySelectionList(long fieldTypeId, Connection conn) throws SQLException {
255         PreparedStatement stmt = null;
256         try {
257             stmt = conn.prepareStatement("delete from linkquerysellist where fieldtype_id = ?");
258             stmt.setLong(1, fieldTypeId);
259             stmt.execute();
260         } finally {
261             jdbcHelper.closeStatement(stmt);
262         }
263     }
264
265     private void deleteQuerySelectionList(long fieldTypeId, Connection conn) throws SQLException {
266         PreparedStatement stmt = null;
267         try {
268             stmt = conn.prepareStatement("delete from querysellist where fieldtype_id = ?");
269             stmt.setLong(1, fieldTypeId);
270             stmt.execute();
271         } finally {
272             jdbcHelper.closeStatement(stmt);
273         }
274     }
275
276     private FieldTypeCreatedDocument createFieldTypeCreatedEvent(FieldTypeImpl fieldType, long newId, Date JavaDoc lastModified) {
277         FieldTypeCreatedDocument fieldTypeCreatedDocument = FieldTypeCreatedDocument.Factory.newInstance();
278         FieldTypeCreatedDocument.FieldTypeCreated fieldTypeCreated = fieldTypeCreatedDocument.addNewFieldTypeCreated();
279
280         FieldTypeDocument.FieldType fieldTypeXml = fieldType.getXml().getFieldType();
281         fieldTypeXml.setLastModified(getCalendar(lastModified));
282         fieldTypeXml.setLastModifier(fieldType.getIntimateAccess(this).getCurrentModifier().getId());
283         fieldTypeXml.setUpdateCount(1);
284         fieldTypeXml.setId(newId);
285
286         fieldTypeCreated.addNewNewFieldType().setFieldType(fieldTypeXml);
287         return fieldTypeCreatedDocument;
288     }
289
290     private FieldTypeUpdatedDocument createFieldTypeUpdatedEvent(FieldTypeImpl oldFieldType, FieldTypeImpl newFieldType, Date JavaDoc lastModified, long newUpdateCount) {
291         FieldTypeUpdatedDocument fieldTypeUpdatedDocument = FieldTypeUpdatedDocument.Factory.newInstance();
292         FieldTypeUpdatedDocument.FieldTypeUpdated fieldTypeUpdated = fieldTypeUpdatedDocument.addNewFieldTypeUpdated();
293
294         fieldTypeUpdated.addNewOldFieldType().setFieldType(oldFieldType.getXml().getFieldType());
295
296         FieldTypeDocument.FieldType newFieldTypeXml = newFieldType.getXml().getFieldType();
297         newFieldTypeXml.setLastModified(getCalendar(lastModified));
298         newFieldTypeXml.setLastModifier(newFieldType.getIntimateAccess(this).getCurrentModifier().getId());
299         newFieldTypeXml.setUpdateCount(newUpdateCount);
300         fieldTypeUpdated.addNewNewFieldType().setFieldType(newFieldTypeXml);
301
302         return fieldTypeUpdatedDocument;
303     }
304
305     private Calendar getCalendar(Date JavaDoc date) {
306         GregorianCalendar calendar = new GregorianCalendar();
307         calendar.setTime(date);
308         return calendar;
309     }
310
311     private void storeStaticSelectionList(FieldTypeImpl fieldType, Connection conn, long id) throws SQLException {
312         PreparedStatement mystmt = null;
313         try {
314             mystmt = conn.prepareStatement("insert into selectionlist_data(fieldtype_id, sequencenr, stringvalue, datevalue, datetimevalue, integervalue, floatvalue, decimalvalue, booleanvalue, link_docid, link_branchid, link_langid, label_id) values (?,?,?,?,?,?,?,?,?,?,?,?,?)");
315
316             ListItem[] selListItems = fieldType.getSelectionList().getItems();
317             for (int i = 0; i < selListItems.length; i++) {
318                 StaticListItemImpl listItem = (StaticListItemImpl)selListItems[i];
319                 StaticListItemImpl.IntimateAccess itemInt = listItem.getIntimateAccess(this);
320                 long localizedLabelId = itemInt.getLocalizedLabelId();
321                 if (localizedLabelId == -1 && !itemInt.getLabels().isEmpty())
322                     localizedLabelId = context.getNextLocalizedStringId();
323
324                 Object JavaDoc listItemValue = listItem.getValue();
325
326                 ValueType fieldValueType = fieldType.getValueType();
327                 String JavaDoc stringValue = (String JavaDoc)(fieldValueType == ValueType.STRING ? listItemValue : null);
328                 Date JavaDoc dateValue = fieldValueType == ValueType.DATE ? new java.sql.Date JavaDoc(((Date JavaDoc)listItemValue).getTime()) : null;
329                 Timestamp datetimeValue = fieldValueType == ValueType.DATETIME ? new Timestamp(((Date JavaDoc)listItemValue).getTime()) : null;
330                 Long JavaDoc integerValue = (Long JavaDoc)(fieldValueType == ValueType.LONG ? listItemValue : null);
331                 Double JavaDoc floatValue = (Double JavaDoc)(fieldValueType == ValueType.DOUBLE ? listItemValue : null);
332                 BigDecimal JavaDoc decimalValue = (BigDecimal JavaDoc)(fieldValueType == ValueType.DECIMAL ? listItemValue : null);
333                 Boolean JavaDoc booleanValue = (Boolean JavaDoc)(fieldValueType == ValueType.BOOLEAN ? listItemValue : null);
334                 Long JavaDoc linkDocId = (fieldValueType == ValueType.LINK ? new Long JavaDoc(((VariantKey)listItemValue).getDocumentId()) : null);
335                 Long JavaDoc linkBranchId = (fieldValueType == ValueType.LINK ? new Long JavaDoc(((VariantKey)listItemValue).getBranchId()) : null);
336                 Long JavaDoc linkLangId = (fieldValueType == ValueType.LINK ? new Long JavaDoc(((VariantKey)listItemValue).getLanguageId()) : null);
337
338                 mystmt.setLong(1, id);
339                 mystmt.setInt(2, i);
340                 mystmt.setString(3, stringValue);
341                 mystmt.setObject(4, dateValue);
342                 mystmt.setObject(5, datetimeValue);
343                 mystmt.setObject(6, integerValue);
344                 mystmt.setObject(7, floatValue);
345                 mystmt.setBigDecimal(8, decimalValue);
346                 mystmt.setObject(9, booleanValue);
347                 mystmt.setObject(10, linkDocId);
348                 mystmt.setObject(11, linkBranchId);
349                 mystmt.setObject(12, linkLangId);
350                 mystmt.setLong(13, localizedLabelId);
351
352                 mystmt.execute();
353                 itemInt.setLocalizedLabelId(localizedLabelId);
354
355                 if (localizedLabelId != -1)
356                     storeLocalizedStrings(localizedLabelId, conn, itemInt.getLabels());
357             }
358         } finally {
359             jdbcHelper.closeStatement(mystmt);
360         }
361     }
362
363     private void storeLinkQuerySelectionList(FieldTypeImpl fieldType, Connection conn, long id) throws SQLException {
364         PreparedStatement stmt = null;
365         try {
366             LinkQuerySelectionList list = (LinkQuerySelectionList)fieldType.getSelectionList();
367             stmt = conn.prepareStatement("insert into linkquerysellist(fieldtype_id, whereclause, filtervariants) values(?, ?, ?)");
368             stmt.setLong(1, id);
369             stmt.setString(2, list.getWhereClause());
370             stmt.setBoolean(3, list.getFilterVariants());
371             stmt.execute();
372         } finally {
373             jdbcHelper.closeStatement(stmt);
374         }
375     }
376
377     private void storeQuerySelectionList(FieldTypeImpl fieldType, Connection conn, long id) throws SQLException {
378         PreparedStatement stmt = null;
379         try {
380             QuerySelectionList list = (QuerySelectionList)fieldType.getSelectionList();
381             stmt = conn.prepareStatement("insert into querysellist(fieldtype_id, query, filtervariants, sort_order) values(?, ?, ?, ?)");
382             stmt.setLong(1, id);
383             stmt.setString(2, list.getQuery());
384             stmt.setBoolean(3, list.getFilterVariants());
385             stmt.setString(4, String.valueOf(list.getSortOrder().getCode()));
386             stmt.execute();
387         } finally {
388             jdbcHelper.closeStatement(stmt);
389         }
390     }
391
392     public void deleteFieldType(long fieldTypeId, AuthenticatedUser user) throws RepositoryException {
393         if (!user.isInAdministratorRole())
394             throw new RepositoryException("Only Administrators can delete field types.");
395
396         Connection conn = null;
397         PreparedStatement stmt = null;
398         try {
399             conn = context.getDataSource().getConnection();
400             jdbcHelper.startTransaction(conn);
401
402             // take a lock on the field type
403
stmt = conn.prepareStatement("select id from field_types where id = ? " + jdbcHelper.getSharedLockClause());
404             stmt.setLong(1, fieldTypeId);
405             ResultSet rs = stmt.executeQuery();
406             if (!rs.next()) {
407                 throw new FieldTypeNotFoundException(fieldTypeId);
408             }
409             stmt.close();
410
411             FieldTypeImpl fieldType = loadFieldType(fieldTypeId, user, conn);
412             FieldTypeImpl.IntimateAccess fieldTypeInt = fieldType.getIntimateAccess(this);
413
414             deleteLocalizedString(fieldTypeInt.getLabelId(), conn);
415             deleteLocalizedString(fieldTypeInt.getDescriptionId(), conn);
416             deleteSelectionList(fieldTypeId, conn);
417
418             stmt = conn.prepareStatement("delete from field_types where id = ?");
419             stmt.setLong(1, fieldTypeId);
420             stmt.execute();
421
422             XmlObject eventDescription = createFieldTypeDeletedEvent(fieldType, user);
423             eventHelper.createEvent(eventDescription, "FieldTypeDeleted", conn);
424
425             conn.commit();
426         } catch (Throwable JavaDoc e) {
427             jdbcHelper.rollback(conn);
428             throw new RepositoryException("Error deleting field type " + fieldTypeId, e);
429         } finally {
430             jdbcHelper.closeStatement(stmt);
431             jdbcHelper.closeConnection(conn);
432         }
433
434         context.getRepositorySchema().fireChangeEvent(RepositorySchemaEventType.FIELD_TYPE_DELETED, fieldTypeId, -1);
435     }
436
437     private FieldTypeDeletedDocument createFieldTypeDeletedEvent(FieldTypeImpl fieldType, AuthenticatedUser deleter) {
438         FieldTypeDeletedDocument fieldTypeDeletedDocument = FieldTypeDeletedDocument.Factory.newInstance();
439         FieldTypeDeletedDocument.FieldTypeDeleted fieldTypeDeleted = fieldTypeDeletedDocument.addNewFieldTypeDeleted();
440         fieldTypeDeleted.addNewDeletedFieldType().setFieldType(fieldType.getXml().getFieldType());
441         fieldTypeDeleted.setDeleterId(deleter.getId());
442         fieldTypeDeleted.setDeletedTime(new GregorianCalendar());
443         return fieldTypeDeletedDocument;
444     }
445
446     public void store(DocumentTypeImpl documentType) throws RepositoryException {
447         DocumentTypeImpl.IntimateAccess documentTypeInt = documentType.getIntimateAccess(this);
448
449         if (!documentTypeInt.getCurrentModifier().isInAdministratorRole())
450             throw new RepositoryException("Only Administrators can create or store Document Types.");
451
452         // do some validity checks on the documentType
453
if (documentType.getName() == null || documentType.getName().length() < 1)
454             throw new RepositoryException("A DocumentType must have a non-null and non-empty name assigned before saving it.");
455
456         Connection conn = null;
457         PreparedStatement stmt = null;
458         try {
459             conn = context.getDataSource().getConnection();
460             jdbcHelper.startTransaction(conn);
461
462             // check the name isn't already in use
463
stmt = conn.prepareStatement("select id from document_types where \"name\" = ?");
464             stmt.setString(1, documentType.getName());
465             ResultSet rs = stmt.executeQuery();
466             if (rs.next()) {
467                 long id = rs.getLong(1);
468                 if (id != documentType.getId())
469                     throw new RepositoryException("There is already a document type with the following name: \"" + documentType.getName() + "\", used by the document type with id " + id);
470             }
471             rs.close();
472             stmt.close();
473
474             // start creating the new entry
475
boolean isNew = false;
476             long id = documentType.getId();
477             long labelId = documentTypeInt.getLabelId();
478             long descriptionId = documentTypeInt.getDescriptionId();
479             java.util.Date JavaDoc lastModified = new java.util.Date JavaDoc();
480             long lastModifier = documentTypeInt.getCurrentModifier().getId();
481             XmlObject eventDescription;
482
483             if (id == -1) {
484                 isNew = true;
485                 // insert new record
486
id = context.getNextDocumentTypeId();
487
488                 labelId = context.getNextLocalizedStringId();
489                 descriptionId = context.getNextLocalizedStringId();
490
491                 stmt = conn.prepareStatement("insert into document_types(id, \"name\", deprecated, label_id, description_id, last_modified, last_modifier, updatecount) values(?,?,?,?,?,?,?,?)");
492                 stmt.setLong(1, id);
493                 stmt.setString(2, documentType.getName());
494                 stmt.setBoolean(3, documentType.isDeprecated());
495                 stmt.setLong(4, labelId);
496                 stmt.setLong(5, descriptionId);
497                 stmt.setTimestamp(6, new Timestamp(lastModified.getTime()));
498                 stmt.setLong(7, lastModifier);
499                 stmt.setLong(8, 1L);
500                 stmt.execute();
501                 stmt.close();
502
503                 eventDescription = createDocumentTypeCreatedEvent(documentType, id, lastModified);
504             } else {
505                 // update existing record
506

507                 // check if nobody else changed it in the meantime
508
stmt = conn.prepareStatement("select updatecount from document_types where id = ? " + jdbcHelper.getSharedLockClause());
509                 stmt.setLong(1, id);
510                 rs = stmt.executeQuery();
511                 if (!rs.next()) {
512                     throw new DocumentTypeNotFoundException(id);
513                 } else {
514                     long dbUpdateCount = rs.getLong(1);
515                     if (dbUpdateCount != documentType.getUpdateCount())
516                         throw new RepositoryException("The document type was concurrently changed by someone else.");
517                 }
518                 stmt.close(); // closes resultset too
519

520                 DocumentTypeImpl oldDocumentType = getDocumentTypeById(documentType.getId(), documentTypeInt.getCurrentModifier());
521                 long newUpdateCount = documentType.getUpdateCount() + 1;
522
523                 // update the record
524
stmt = conn.prepareStatement("update document_types set \"name\"=?, deprecated=?, last_modified=?, last_modifier=?, updatecount=? where id = ?");
525                 stmt.setString(1, documentType.getName());
526                 stmt.setBoolean(2, documentType.isDeprecated());
527                 stmt.setTimestamp(3, new Timestamp(lastModified.getTime()));
528                 stmt.setLong(4, lastModifier);
529                 stmt.setLong(5, newUpdateCount);
530                 stmt.setLong(6, id);
531                 stmt.execute();
532                 stmt.close();
533
534                 eventDescription = createDocumentTypeUpdatedEvent(oldDocumentType, documentType, lastModified, newUpdateCount);
535             }
536
537             // store labels and descriptions, do this by deleting all entries and re-inserting them
538
storeLocalizedStrings(labelId, conn, documentTypeInt.getLabels());
539             storeLocalizedStrings(descriptionId, conn, documentTypeInt.getDescriptions());
540
541             deleteDocumentTypeAssociations(id, conn);
542
543             // store association with field types
544
stmt = conn.prepareStatement("insert into doctypes_fieldtypes(doctype_id, field_id, required, sequencenr) values(?,?,?,?)");
545             FieldTypeUse[] fieldTypeUses = documentType.getFieldTypeUses();
546             for (int i = 0; i < fieldTypeUses.length; i++) {
547                 stmt.setLong(1, id);
548                 stmt.setLong(2, fieldTypeUses[i].getFieldType().getId());
549                 stmt.setBoolean(3, fieldTypeUses[i].isRequired());
550                 stmt.setInt(4, i);
551                 stmt.execute();
552             }
553             stmt.close();
554
555             // store association with part types
556
stmt = conn.prepareStatement("insert into doctype_contentmodel(doctype_id, part_id, required, sequencenr) values(?,?,?,?)");
557             PartTypeUse[] partTypeUses = documentType.getPartTypeUses();
558             for (int i = 0; i < partTypeUses.length; i++) {
559                 stmt.setLong(1, id);
560                 stmt.setLong(2, partTypeUses[i].getPartType().getId());
561                 stmt.setBoolean(3, partTypeUses[i].isRequired());
562                 stmt.setInt(4, i);
563                 stmt.execute();
564             }
565             stmt.close();
566
567             eventHelper.createEvent(eventDescription, isNew ? "DocumentTypeCreated" : "DocumentTypeUpdated", conn);
568
569             conn.commit();
570
571             documentTypeInt.setId(id);
572             documentTypeInt.setLabelId(labelId);
573             documentTypeInt.setDescriptionId(descriptionId);
574             documentTypeInt.setLastModified(lastModified);
575             documentTypeInt.setLastModifier(lastModifier);
576             documentTypeInt.setUpdateCount(documentType.getUpdateCount() + 1);
577
578             if (isNew)
579                 context.getRepositorySchema().fireChangeEvent(RepositorySchemaEventType.DOCUMENT_TYPE_CREATED, id, documentType.getUpdateCount());
580             else
581                 context.getRepositorySchema().fireChangeEvent(RepositorySchemaEventType.DOCUMENT_TYPE_UPDATED, id, documentType.getUpdateCount());
582         } catch (Throwable JavaDoc e) {
583             jdbcHelper.rollback(conn);
584             throw new RepositoryException("Problem storing document type.", e);
585         } finally {
586             jdbcHelper.closeStatement(stmt);
587             jdbcHelper.closeConnection(conn);
588         }
589
590     }
591
592     private DocumentTypeCreatedDocument createDocumentTypeCreatedEvent(DocumentTypeImpl documentType, long newId, Date JavaDoc lastModified) {
593         DocumentTypeCreatedDocument documentTypeCreatedDocument = DocumentTypeCreatedDocument.Factory.newInstance();
594         DocumentTypeCreatedDocument.DocumentTypeCreated documentTypeCreated = documentTypeCreatedDocument.addNewDocumentTypeCreated();
595
596         DocumentTypeDocument.DocumentType documentTypeXml = documentType.getXml().getDocumentType();
597         documentTypeXml.setLastModified(getCalendar(lastModified));
598         documentTypeXml.setLastModifier(documentType.getIntimateAccess(this).getCurrentModifier().getId());
599         documentTypeXml.setUpdateCount(1);
600         documentTypeXml.setId(newId);
601
602         documentTypeCreated.addNewNewDocumentType().setDocumentType(documentTypeXml);
603         return documentTypeCreatedDocument;
604     }
605
606     private DocumentTypeUpdatedDocument createDocumentTypeUpdatedEvent(DocumentTypeImpl oldDocumentType, DocumentTypeImpl newDocumentType, Date JavaDoc lastModified, long newUpdateCount) {
607         DocumentTypeUpdatedDocument documentTypeUpdatedDocument = DocumentTypeUpdatedDocument.Factory.newInstance();
608         DocumentTypeUpdatedDocument.DocumentTypeUpdated documentTypeUpdated = documentTypeUpdatedDocument.addNewDocumentTypeUpdated();
609
610         documentTypeUpdated.addNewOldDocumentType().setDocumentType(oldDocumentType.getXml().getDocumentType());
611
612         DocumentTypeDocument.DocumentType newDocumentTypeXml = newDocumentType.getXml().getDocumentType();
613         newDocumentTypeXml.setLastModified(getCalendar(lastModified));
614         newDocumentTypeXml.setLastModifier(newDocumentType.getIntimateAccess(this).getCurrentModifier().getId());
615         newDocumentTypeXml.setUpdateCount(newUpdateCount);
616         documentTypeUpdated.addNewNewDocumentType().setDocumentType(newDocumentTypeXml);
617
618         return documentTypeUpdatedDocument;
619     }
620
621     public void deleteDocumentType(long documentTypeId, AuthenticatedUser user) throws RepositoryException {
622         if (!user.isInAdministratorRole())
623             throw new RepositoryException("Only Administrators can delete document types.");
624
625         Connection conn = null;
626         PreparedStatement stmt = null;
627         try {
628             conn = context.getDataSource().getConnection();
629             jdbcHelper.startTransaction(conn);
630
631             // lock the document type
632
stmt = conn.prepareStatement("select updatecount from document_types where id = ? " + jdbcHelper.getSharedLockClause());
633             stmt.setLong(1, documentTypeId);
634             ResultSet rs = stmt.executeQuery();
635             if (!rs.next()) {
636                 throw new DocumentTypeNotFoundException(documentTypeId);
637             }
638             stmt.close();
639
640             DocumentTypeImpl documentType = loadDocumentType(documentTypeId, user, conn);
641             DocumentTypeImpl.IntimateAccess documentTypeInt = documentType.getIntimateAccess(this);
642
643             deleteLocalizedString(documentTypeInt.getLabelId(), conn);
644             deleteLocalizedString(documentTypeInt.getDescriptionId(), conn);
645             deleteDocumentTypeAssociations(documentTypeId, conn);
646
647             stmt = conn.prepareStatement("delete from document_types where id = ?");
648             stmt.setLong(1, documentTypeId);
649             stmt.execute();
650
651             XmlObject eventDescription = createDocumentTypeDeletedEvent(documentType, user);
652             eventHelper.createEvent(eventDescription, "DocumentTypeDeleted", conn);
653
654             conn.commit();
655         } catch (Throwable JavaDoc e) {
656             jdbcHelper.rollback(conn);
657             throw new RepositoryException("Error deleting document type " + documentTypeId, e);
658         } finally {
659             jdbcHelper.closeStatement(stmt);
660             jdbcHelper.closeConnection(conn);
661         }
662
663         context.getRepositorySchema().fireChangeEvent(RepositorySchemaEventType.DOCUMENT_TYPE_DELETED, documentTypeId, -1);
664     }
665
666     private void deleteDocumentTypeAssociations(long documentTypeId, Connection conn) throws SQLException {
667         PreparedStatement stmt = null;
668         try {
669             stmt = conn.prepareStatement("delete from doctypes_fieldtypes where doctype_id = ?");
670             stmt.setLong(1, documentTypeId);
671             stmt.execute();
672             stmt.close();
673
674             stmt = conn.prepareStatement("delete from doctype_contentmodel where doctype_id = ?");
675             stmt.setLong(1, documentTypeId);
676             stmt.execute();
677             stmt.close();
678         } finally {
679             jdbcHelper.closeStatement(stmt);
680         }
681     }
682
683     private DocumentTypeDeletedDocument createDocumentTypeDeletedEvent(DocumentTypeImpl documentType, AuthenticatedUser deleter) {
684         DocumentTypeDeletedDocument documentTypeDeletedDocument = DocumentTypeDeletedDocument.Factory.newInstance();
685         DocumentTypeDeletedDocument.DocumentTypeDeleted documentTypeDeleted = documentTypeDeletedDocument.addNewDocumentTypeDeleted();
686         documentTypeDeleted.addNewDeletedDocumentType().setDocumentType(documentType.getXml().getDocumentType());
687         documentTypeDeleted.setDeleterId(deleter.getId());
688         documentTypeDeleted.setDeletedTime(new GregorianCalendar());
689         return documentTypeDeletedDocument;
690     }
691
692     public void store(PartTypeImpl partType) throws RepositoryException {
693         PartTypeImpl.IntimateAccess partTypeInt = partType.getIntimateAccess(this);
694
695         if (!partTypeInt.getCurrentModifier().isInAdministratorRole())
696             throw new RepositoryException("Only Administrators can create or update part types.");
697
698         // do some validity checks on the partType
699

700         if (partType.getMimeTypes() == null)
701             throw new RepositoryException("A part type must have a non-null mime-type assigned before saving it.");
702
703         if (partType.getName() == null || partType.getName().length() < 1)
704             throw new RepositoryException("A part type must have a non-null and non-empty name assigned before saving it.");
705
706         Connection conn = null;
707         PreparedStatement stmt = null;
708         try {
709             conn = context.getDataSource().getConnection();
710             jdbcHelper.startTransaction(conn);
711
712             // check the name isn't already in use
713
stmt = conn.prepareStatement("select part_id from part_types where \"name\" = ?");
714             stmt.setString(1, partType.getName());
715             ResultSet rs = stmt.executeQuery();
716             if (rs.next()) {
717                 long id = rs.getLong(1);
718                 if (id != partType.getId())
719                     throw new RepositoryException("There is already a part type with the following name: \"" + partType.getName() + "\", used by the part type with id " + id);
720             }
721             rs.close();
722             stmt.close();
723
724             // start creating the new entry
725
boolean isNew = false;
726             long id = partType.getId();
727             long labelId = partTypeInt.getLabelId();
728             long descriptionId = partTypeInt.getDescriptionId();
729             java.util.Date JavaDoc lastModified = new java.util.Date JavaDoc();
730             long lastModifier = partTypeInt.getCurrentModifier().getId();
731             XmlObject eventDescription;
732
733             if (id == -1) {
734                 isNew = true;
735                 // insert new record
736
id = context.getNextPartTypeId();
737
738                 labelId = context.getNextLocalizedStringId();
739                 descriptionId = context.getNextLocalizedStringId();
740
741                 stmt = conn.prepareStatement("insert into part_types(part_id, \"name\", mimetype, daisy_html, linkextractor, deprecated, label_id, description_id, last_modified, last_modifier, updatecount) values(?,?,?,?,?,?,?,?,?,?,?)");
742                 stmt.setLong(1, id);
743                 stmt.setString(2, partType.getName());
744                 stmt.setString(3, partType.getMimeTypes().equals("") ? " " : partType.getMimeTypes()); // Workaround for Oracle "empty string becomes null" problem
745
stmt.setBoolean(4, partType.isDaisyHtml());
746                 stmt.setString(5, partType.getLinkExtractor());
747                 stmt.setBoolean(6, partType.isDeprecated());
748                 stmt.setLong(7, labelId);
749                 stmt.setLong(8, descriptionId);
750                 stmt.setTimestamp(9, new Timestamp(lastModified.getTime()));
751                 stmt.setLong(10, lastModifier);
752                 stmt.setLong(11, 1L);
753                 stmt.execute();
754                 stmt.close();
755
756                 eventDescription = createPartTypeCreatedEvent(partType, id, lastModified);
757             } else {
758                 // update existing record
759

760                 // check if nobody else changed it in the meantime
761
stmt = conn.prepareStatement("select updatecount from part_types where part_id = ? " + jdbcHelper.getSharedLockClause());
762                 stmt.setLong(1, id);
763                 rs = stmt.executeQuery();
764                 if (!rs.next()) {
765                     throw new PartTypeNotFoundException(id);
766                 } else {
767                     long dbUpdateCount = rs.getLong(1);
768                     if (dbUpdateCount != partType.getUpdateCount())
769                         throw new RepositoryException("The part type was concurrently changed by someone else.");
770                 }
771                 stmt.close(); // closes resultset too
772

773                 PartTypeImpl oldPartType = getPartTypeById(partType.getId(), partTypeInt.getCurrentModifier());
774                 long newUpdateCount = partType.getUpdateCount() + 1;
775
776                 // update the record
777
stmt = conn.prepareStatement("update part_types set \"name\"=?, mimetype=?, daisy_html=?, linkextractor=?, deprecated=?, last_modified=?, last_modifier=?, updatecount=? where part_id = ?");
778                 stmt.setString(1, partType.getName());
779                 stmt.setString(2, partType.getMimeTypes());
780                 stmt.setBoolean(3, partType.isDaisyHtml());
781                 stmt.setString(4, partType.getLinkExtractor());
782                 stmt.setBoolean(5, partType.isDeprecated());
783                 stmt.setTimestamp(6, new Timestamp(lastModified.getTime()));
784                 stmt.setLong(7, lastModifier);
785                 stmt.setLong(8, partType.getUpdateCount() + 1);
786                 stmt.setLong(9, id);
787                 stmt.execute();
788                 stmt.close();
789
790                 eventDescription = createPartTypeUpdatedEvent(oldPartType, partType, lastModified, newUpdateCount);
791             }
792
793             // store labels and descriptions, do this by deleting all entries and re-inserting them
794
storeLocalizedStrings(labelId, conn, partTypeInt.getLabels());
795             storeLocalizedStrings(descriptionId, conn, partTypeInt.getDescriptions());
796
797             eventHelper.createEvent(eventDescription, isNew ? "PartTypeCreated" : "PartTypeUpdated", conn);
798
799             conn.commit();
800
801             partTypeInt.setId(id);
802             partTypeInt.setLabelId(labelId);
803             partTypeInt.setDescriptionId(descriptionId);
804             partTypeInt.setLastModified(lastModified);
805             partTypeInt.setLastModifier(lastModifier);
806             partTypeInt.setUpdateCount(partType.getUpdateCount() + 1);
807
808             if (isNew)
809                 context.getRepositorySchema().fireChangeEvent(RepositorySchemaEventType.PART_TYPE_CREATED, id, partType.getUpdateCount());
810             else
811                 context.getRepositorySchema().fireChangeEvent(RepositorySchemaEventType.PART_TYPE_UPDATED, id, partType.getUpdateCount());
812         } catch (Throwable JavaDoc e) {
813             jdbcHelper.rollback(conn);
814             throw new RepositoryException("Problem storing part type", e);
815         } finally {
816             jdbcHelper.closeStatement(stmt);
817             jdbcHelper.closeConnection(conn);
818         }
819     }
820
821     private PartTypeCreatedDocument createPartTypeCreatedEvent(PartTypeImpl partType, long newId, Date JavaDoc lastModified) {
822         PartTypeCreatedDocument partTypeCreatedDocument = PartTypeCreatedDocument.Factory.newInstance();
823         PartTypeCreatedDocument.PartTypeCreated partTypeCreated = partTypeCreatedDocument.addNewPartTypeCreated();
824
825         PartTypeDocument.PartType partTypeXml = partType.getXml().getPartType();
826         partTypeXml.setLastModified(getCalendar(lastModified));
827         partTypeXml.setLastModifier(partType.getIntimateAccess(this).getCurrentModifier().getId());
828         partTypeXml.setUpdateCount(1);
829         partTypeXml.setId(newId);
830
831         partTypeCreated.addNewNewPartType().setPartType(partTypeXml);
832         return partTypeCreatedDocument;
833     }
834
835     private PartTypeUpdatedDocument createPartTypeUpdatedEvent(PartTypeImpl oldPartType, PartTypeImpl newPartType, Date JavaDoc lastModified, long newUpdateCount) {
836         PartTypeUpdatedDocument partTypeUpdatedDocument = PartTypeUpdatedDocument.Factory.newInstance();
837         PartTypeUpdatedDocument.PartTypeUpdated partTypeUpdated = partTypeUpdatedDocument.addNewPartTypeUpdated();
838
839         partTypeUpdated.addNewOldPartType().setPartType(oldPartType.getXml().getPartType());
840
841         PartTypeDocument.PartType newPartTypeXml = newPartType.getXml().getPartType();
842         newPartTypeXml.setLastModified(getCalendar(lastModified));
843         newPartTypeXml.setLastModifier(newPartType.getIntimateAccess(this).getCurrentModifier().getId());
844         newPartTypeXml.setUpdateCount(newUpdateCount);
845         partTypeUpdated.addNewNewPartType().setPartType(newPartTypeXml);
846
847         return partTypeUpdatedDocument;
848     }
849
850     public void deletePartType(long partTypeId, AuthenticatedUser user) throws RepositoryException {
851         if (!user.isInAdministratorRole())
852             throw new RepositoryException("Only Administrators can delete part types.");
853
854         Connection conn = null;
855         PreparedStatement stmt = null;
856         try {
857             conn = context.getDataSource().getConnection();
858             jdbcHelper.startTransaction(conn);
859
860             stmt = conn.prepareStatement("select updatecount from part_types where part_id = ? " + jdbcHelper.getSharedLockClause());
861             stmt.setLong(1, partTypeId);
862             ResultSet rs = stmt.executeQuery();
863             if (!rs.next()) {
864                 throw new PartTypeNotFoundException(partTypeId);
865             }
866             stmt.close();
867
868             PartTypeImpl partType = loadPartType(partTypeId, user, conn);
869             PartTypeImpl.IntimateAccess partTypeInt = partType.getIntimateAccess(this);
870
871             deleteLocalizedString(partTypeInt.getLabelId(), conn);
872             deleteLocalizedString(partTypeInt.getDescriptionId(), conn);
873
874             stmt = conn.prepareStatement("delete from part_types where part_id = ?");
875             stmt.setLong(1, partTypeId);
876             stmt.execute();
877
878             XmlObject eventDescription = createPartTypeDeletedEvent(partType, user);
879             eventHelper.createEvent(eventDescription, "PartTypeDeleted", conn);
880
881             conn.commit();
882         } catch (Throwable JavaDoc e) {
883             jdbcHelper.rollback(conn);
884             throw new RepositoryException("Error deleting part type " + partTypeId, e);
885         } finally {
886             jdbcHelper.closeStatement(stmt);
887             jdbcHelper.closeConnection(conn);
888         }
889
890         context.getRepositorySchema().fireChangeEvent(RepositorySchemaEventType.PART_TYPE_DELETED, partTypeId, -1);
891     }
892
893     private PartTypeDeletedDocument createPartTypeDeletedEvent(PartTypeImpl partType, AuthenticatedUser deleter) {
894         PartTypeDeletedDocument partTypeDeletedDocument = PartTypeDeletedDocument.Factory.newInstance();
895         PartTypeDeletedDocument.PartTypeDeleted partTypeDeleted = partTypeDeletedDocument.addNewPartTypeDeleted();
896         partTypeDeleted.addNewDeletedPartType().setPartType(partType.getXml().getPartType());
897         partTypeDeleted.setDeleterId(deleter.getId());
898         partTypeDeleted.setDeletedTime(new GregorianCalendar());
899         return partTypeDeletedDocument;
900     }
901
902     /**
903      * Stores the contents of a LocaleMap in the table containing the localized strings. This
904      * is done by first deleting all entries and then reinserting them.
905      */

906     private void storeLocalizedStrings(long id, Connection conn, LocaleMap localizedStrings) throws SQLException {
907         Iterator entryIt = localizedStrings.entrySet().iterator();
908
909         PreparedStatement stmt = null;
910         try {
911             deleteLocalizedString(id, conn);
912
913             stmt = conn.prepareStatement("insert into localized_strings(id, locale, \"value\") values(?,?,?)");
914
915             while (entryIt.hasNext()) {
916                 Map.Entry entry = (Map.Entry)entryIt.next();
917                 String JavaDoc locale = (String JavaDoc)entry.getKey();
918                 if (locale.equals(""))
919                     locale = " "; // Workaround for Oracle "empty string becomes null" problem
920
String JavaDoc label = (String JavaDoc)entry.getValue();
921                 stmt.setLong(1, id);
922                 stmt.setString(2, locale);
923                 stmt.setString(3, label);
924                 stmt.execute();
925             }
926         } finally {
927             jdbcHelper.closeStatement(stmt);
928         }
929     }
930
931     private void deleteLocalizedString(long id, Connection conn) throws SQLException {
932         PreparedStatement stmt = null;
933         try {
934             stmt = conn.prepareStatement("delete from localized_strings where id = ?");
935             stmt.setLong(1, id);
936             stmt.execute();
937         } finally {
938             jdbcHelper.closeStatement(stmt);
939         }
940     }
941
942     public PartTypeImpl getPartTypeById(long id, AuthenticatedUser user) throws RepositoryException {
943         Connection conn = null;
944         try {
945             conn = context.getDataSource().getConnection();
946             jdbcHelper.startTransaction(conn);
947             return loadPartType(id, user, conn);
948         } catch (SQLException e) {
949             throw new RepositoryException("Error retrieving part type with id " + id + ".", e);
950         } finally {
951             jdbcHelper.closeConnection(conn);
952         }
953     }
954
955     private PartTypeImpl loadPartType(long partTypeId, AuthenticatedUser user, Connection conn) throws RepositoryException {
956         PreparedStatement stmt = null;
957         try {
958             stmt = conn.prepareStatement("select \"name\", label_id, description_id, mimetype, daisy_html, linkextractor, deprecated, last_modified, last_modifier, updatecount from part_types where part_id = ?");
959             stmt.setLong(1, partTypeId);
960             ResultSet rs = stmt.executeQuery();
961
962             if (!rs.next())
963                 throw new PartTypeNotFoundException(partTypeId);
964
965             String JavaDoc name = rs.getString("name");
966             String JavaDoc mimeTypes = rs.getString("mimetype").trim(); // the trim() balances the effect of the Oracle work-around in the store method
967

968             PartTypeImpl partType = new PartTypeImpl(name, mimeTypes, this, user);
969             PartTypeImpl.IntimateAccess partTypeInt = partType.getIntimateAccess(this);
970
971             partType.setDaisyHtml(rs.getBoolean("daisy_html"));
972             partTypeInt.setId(partTypeId);
973             partType.setLinkExtractor(rs.getString("linkextractor"));
974             partType.setDeprecated(rs.getBoolean("deprecated"));
975             partTypeInt.setLabelId(rs.getLong("label_id"));
976             partTypeInt.setDescriptionId(rs.getLong("description_id"));
977             partTypeInt.setLastModified(rs.getTimestamp("last_modified"));
978             partTypeInt.setLastModifier(rs.getLong("last_modifier"));
979             partTypeInt.setUpdateCount(rs.getLong("updatecount"));
980
981             loadLocalizedStrings(partTypeInt.getLabelId(), conn, partTypeInt.getLabels());
982             loadLocalizedStrings(partTypeInt.getDescriptionId(), conn, partTypeInt.getDescriptions());
983
984             return partType;
985
986         } catch (PartTypeNotFoundException e) {
987             throw e;
988         } catch (Throwable JavaDoc e) {
989             throw new RepositoryException("Error retrieving part type with id " + partTypeId + ".", e);
990         } finally {
991             jdbcHelper.closeStatement(stmt);
992         }
993     }
994
995     public PartTypeImpl getPartTypeByName(String JavaDoc name, AuthenticatedUser user) throws RepositoryException {
996         Connection conn = null;
997         PreparedStatement stmt = null;
998         long id;
999         try {
1000            conn = context.getDataSource().getConnection();
1001            jdbcHelper.startTransaction(conn);
1002
1003            stmt = conn.prepareStatement("select part_id from part_types where \"name\" = ?");
1004            stmt.setString(1, name);
1005            ResultSet rs = stmt.executeQuery();
1006
1007            if (!rs.next())
1008                throw new PartTypeNotFoundException(name);
1009
1010            id = rs.getLong(1);
1011
1012            return loadPartType(id, user, conn);
1013        } catch (PartTypeNotFoundException e) {
1014            throw e;
1015        } catch (Throwable JavaDoc e) {
1016            throw new RepositoryException("Error retrieving the part type named " + name, e);
1017        } finally {
1018            jdbcHelper.closeStatement(stmt);
1019            jdbcHelper.closeConnection(conn);
1020        }
1021    }
1022
1023    public void loadLocalizedStrings(long id, Connection conn, LocaleMap localizedStrings) throws SQLException {
1024        PreparedStatement stmt = null;
1025        try {
1026            stmt = conn.prepareStatement("select locale, \"value\" from localized_strings where id = ?");
1027            stmt.setLong(1, id);
1028            ResultSet rs = stmt.executeQuery();
1029            while (rs.next()) {
1030                String JavaDoc locale = rs.getString(1).trim();
1031                String JavaDoc value = rs.getString(2);
1032                localizedStrings.put(LocaleHelper.parseLocale(locale), value);
1033            }
1034        } finally {
1035            jdbcHelper.closeStatement(stmt);
1036        }
1037    }
1038
1039
1040    public FieldTypeImpl getFieldTypeById(long id, AuthenticatedUser user) throws RepositoryException {
1041        Connection conn = null;
1042        try {
1043            conn = context.getDataSource().getConnection();
1044            jdbcHelper.startTransaction(conn);
1045            return loadFieldType(id, user, conn);
1046        } catch (SQLException e) {
1047            throw new RepositoryException("Error retrieving field type with id " + id + ".", e);
1048        } finally {
1049            jdbcHelper.closeConnection(conn);
1050        }
1051    }
1052
1053    private FieldTypeImpl loadFieldType(long fieldTypeId, AuthenticatedUser user, Connection conn) throws RepositoryException {
1054        PreparedStatement stmt = null;
1055        try {
1056            stmt = conn.prepareStatement("select \"name\", label_id, description_id, valuetype, \"size\", deprecated, acl_allowed, multivalue, selectionlist_type, selectlist_free_entry, last_modified, last_modifier, updatecount from field_types where id=?");
1057            stmt.setLong(1, fieldTypeId);
1058            ResultSet rs = stmt.executeQuery();
1059
1060            if (!rs.next())
1061                throw new FieldTypeNotFoundException(fieldTypeId);
1062
1063            String JavaDoc name = rs.getString("name");
1064            ValueType type = ValueType.getByCode(rs.getInt("valuetype"));
1065            boolean multiValue = rs.getBoolean("multivalue");
1066
1067            FieldTypeImpl fieldType = new FieldTypeImpl(name, type, multiValue, this, context.getCommonRepository(), user);
1068            FieldTypeImpl.IntimateAccess fieldTypeInt = fieldType.getIntimateAccess(this);
1069            fieldTypeInt.setId(fieldTypeId);
1070            fieldType.setDeprecated(rs.getBoolean("deprecated"));
1071            fieldType.setAclAllowed(rs.getBoolean("acl_allowed"));
1072            fieldTypeInt.setLabelId(rs.getLong("label_id"));
1073            fieldTypeInt.setDescriptionId(rs.getLong("description_id"));
1074            fieldTypeInt.setLastModified(rs.getTimestamp("last_modified"));
1075            fieldTypeInt.setLastModifier(rs.getLong("last_modifier"));
1076            fieldTypeInt.setUpdateCount(rs.getLong("updatecount"));
1077            fieldTypeInt.setSize(rs.getInt("size"));
1078            char selectionListType = rs.getString("selectionlist_type").charAt(0);
1079            fieldTypeInt.setAllowFreeEntry(rs.getBoolean("selectlist_free_entry"));
1080            loadLocalizedStrings(fieldTypeInt.getLabelId(), conn, fieldTypeInt.getLabels());
1081            loadLocalizedStrings(fieldTypeInt.getDescriptionId(), conn, fieldTypeInt.getDescriptions());
1082
1083            stmt.close();
1084
1085            if (selectionListType == NO_SELECTIONLIST_TYPE) {
1086                // do nothing
1087
} else if (selectionListType == STATIC_SELECTIONLIST_TYPE) {
1088                StaticSelectionListImpl selList = (StaticSelectionListImpl)fieldType.createStaticSelectionList();
1089
1090                stmt = conn.prepareStatement("select sequencenr, stringvalue, datevalue, datetimevalue, integervalue, floatvalue, decimalvalue, booleanvalue, link_docid, link_branchid, link_langid, label_id from selectionlist_data where fieldtype_id=? order by sequencenr");
1091                stmt.setLong(1, fieldTypeId);
1092                rs = stmt.executeQuery();
1093
1094                while (rs.next()) {
1095                    FieldValueGetter fieldValueGetter = getValueGetter(type);
1096                    StaticListItem listItem = selList.createStaticListItem(fieldValueGetter.getValue(rs));
1097
1098                    long localizedLabelId = rs.getLong("label_id");
1099                    if (localizedLabelId != -1) {
1100                        StaticListItemImpl listItemImpl = (StaticListItemImpl)listItem;
1101                        StaticListItemImpl.IntimateAccess listItemInt = listItemImpl.getIntimateAccess(this);
1102                        listItemInt.setLocalizedLabelId(localizedLabelId);
1103                        loadLocalizedStrings(localizedLabelId, conn, listItemInt.getLabels());
1104                    }
1105                }
1106                stmt.close();
1107            } else if (selectionListType == LINKQUERY_SELECTIONLIST_TYPE) {
1108                stmt = conn.prepareStatement("select whereclause, filtervariants from linkquerysellist where fieldtype_id = ?");
1109                stmt.setLong(1, fieldTypeId);
1110                rs = stmt.executeQuery();
1111                rs.next();
1112                String JavaDoc whereClause = rs.getString(1);
1113                boolean filterVariants = rs.getBoolean(2);
1114                fieldType.createLinkQuerySelectionList(whereClause, filterVariants);
1115                stmt.close();
1116            } else if (selectionListType == QUERY_SELECTIONLIST_TYPE) {
1117                stmt = conn.prepareStatement("select query, filtervariants, sort_order from querysellist where fieldtype_id = ?");
1118                stmt.setLong(1, fieldTypeId);
1119                rs = stmt.executeQuery();
1120                rs.next();
1121                String JavaDoc query = rs.getString(1);
1122                boolean filterVariants = rs.getBoolean(2);
1123                SortOrder sortOrder = SortOrder.fromCode(rs.getString(3).charAt(0));
1124                fieldType.createQuerySelectionList(query, filterVariants, sortOrder);
1125                stmt.close();
1126            } else {
1127                throw new Exception JavaDoc("Invalid selection list type in repository for field type " + fieldTypeId + " : " + selectionListType);
1128            }
1129
1130            return fieldType;
1131        } catch (FieldTypeNotFoundException e) {
1132            throw e;
1133        } catch (Throwable JavaDoc e) {
1134            throw new RepositoryException("Error retrieving field type with id " + fieldTypeId + ".", e);
1135        } finally {
1136            jdbcHelper.closeStatement(stmt);
1137        }
1138    }
1139
1140    public FieldTypeImpl getFieldTypeByName(String JavaDoc name, AuthenticatedUser user) throws RepositoryException {
1141        Connection conn = null;
1142        PreparedStatement stmt = null;
1143        long id;
1144        try {
1145            conn = context.getDataSource().getConnection();
1146            jdbcHelper.startTransaction(conn);
1147
1148            stmt = conn.prepareStatement("select id from field_types where \"name\" = ?");
1149            stmt.setString(1, name);
1150            ResultSet rs = stmt.executeQuery();
1151
1152            if (!rs.next())
1153                throw new FieldTypeNotFoundException(name);
1154
1155            id = rs.getLong(1);
1156            stmt.close();
1157
1158            return loadFieldType(id, user, conn);
1159        } catch (FieldTypeNotFoundException e) {
1160            throw e;
1161        } catch (Throwable JavaDoc e) {
1162            throw new RepositoryException("Error retrieving the field type named " + name, e);
1163        } finally {
1164            jdbcHelper.closeStatement(stmt);
1165            jdbcHelper.closeConnection(conn);
1166        }
1167    }
1168
1169    public DocumentTypeImpl getDocumentTypeById(long id, AuthenticatedUser user) throws RepositoryException {
1170        Connection conn = null;
1171        try {
1172            conn = context.getDataSource().getConnection();
1173            jdbcHelper.startTransaction(conn);
1174            return loadDocumentType(id, user, conn);
1175        } catch (SQLException e) {
1176            jdbcHelper.rollback(conn);
1177            throw new RepositoryException("Error retrieving document type with id " + id + ".", e);
1178        } finally {
1179            jdbcHelper.closeConnection(conn);
1180        }
1181    }
1182
1183    private DocumentTypeImpl loadDocumentType(long documentTypeId, AuthenticatedUser user, Connection conn) throws RepositoryException {
1184        PreparedStatement stmt = null;
1185        try {
1186            stmt = conn.prepareStatement("select \"name\", deprecated, label_id, description_id, last_modified, last_modifier, updatecount from document_types where id = ?");
1187            stmt.setLong(1, documentTypeId);
1188            ResultSet rs = stmt.executeQuery();
1189
1190            if (!rs.next())
1191                throw new DocumentTypeNotFoundException(documentTypeId);
1192
1193            String JavaDoc name = rs.getString("name");
1194
1195            DocumentTypeImpl docType = new DocumentTypeImpl(name, this, context.getRepositorySchema(), user);
1196            DocumentTypeImpl.IntimateAccess docTypeInt = docType.getIntimateAccess(this);
1197            docTypeInt.setId(documentTypeId);
1198            docType.setDeprecated(rs.getBoolean("deprecated"));
1199            docTypeInt.setLabelId(rs.getLong("label_id"));
1200            docTypeInt.setDescriptionId(rs.getLong("description_id"));
1201            docTypeInt.setLastModified(rs.getTimestamp("last_modified"));
1202            docTypeInt.setLastModifier(rs.getLong("last_modifier"));
1203            docTypeInt.setUpdateCount(rs.getLong("updatecount"));
1204            stmt.close();
1205
1206            loadLocalizedStrings(docTypeInt.getLabelId(), conn, docTypeInt.getLabels());
1207            loadLocalizedStrings(docTypeInt.getDescriptionId(), conn, docTypeInt.getDescriptions());
1208
1209            // load associations with fields (unmodifiable cache copies)
1210
stmt = conn.prepareStatement("select field_id, required from doctypes_fieldtypes where doctype_id = ? order by sequencenr");
1211            stmt.setLong(1, documentTypeId);
1212            rs = stmt.executeQuery();
1213            while (rs.next()) {
1214                long fieldId = rs.getLong(1);
1215                boolean required = rs.getBoolean(2);
1216                FieldType fieldType = context.getRepositorySchema().getFieldTypeById(fieldId, false, user);
1217                docType.addFieldType(fieldType, required);
1218            }
1219            stmt.close();
1220
1221            // load associations with part types (unmodifiable cache copies)
1222
stmt = conn.prepareStatement("select part_id, required from doctype_contentmodel where doctype_id = ? order by sequencenr");
1223            stmt.setLong(1, documentTypeId);
1224            rs = stmt.executeQuery();
1225            while (rs.next()) {
1226                long partId = rs.getLong(1);
1227                boolean required = rs.getBoolean(2);
1228                PartType partType = context.getRepositorySchema().getPartTypeById(partId, false, user);
1229                docType.addPartType(partType, required);
1230            }
1231            stmt.close();
1232
1233            return docType;
1234        } catch (DocumentTypeNotFoundException e) {
1235            throw e;
1236        } catch (Throwable JavaDoc e) {
1237            throw new RepositoryException("Error retrieving document type with id " + documentTypeId + ".", e);
1238        } finally {
1239            jdbcHelper.closeStatement(stmt);
1240        }
1241    }
1242
1243    public DocumentTypeImpl getDocumentTypeByName(String JavaDoc name, AuthenticatedUser user) throws RepositoryException {
1244        Connection conn = null;
1245        PreparedStatement stmt = null;
1246        long id;
1247        try {
1248            conn = context.getDataSource().getConnection();
1249            jdbcHelper.startTransaction(conn);
1250
1251            stmt = conn.prepareStatement("select id from document_types where \"name\" = ?");
1252            stmt.setString(1, name);
1253            ResultSet rs = stmt.executeQuery();
1254
1255            if (!rs.next())
1256                throw new DocumentTypeNotFoundException(name);
1257
1258            id = rs.getLong(1);
1259
1260            return loadDocumentType(id, user, conn);
1261        } catch (DocumentTypeNotFoundException e) {
1262            throw e;
1263        } catch (Throwable JavaDoc e) {
1264            throw new RepositoryException("Error retrieving the document type named " + name, e);
1265        } finally {
1266            jdbcHelper.closeStatement(stmt);
1267            jdbcHelper.closeConnection(conn);
1268        }
1269    }
1270
1271    public Collection getAllPartTypes(final AuthenticatedUser user) throws RepositoryException {
1272        return getAllOfSomething("part_id", "part_types", "PartTypes", new IdGettable() {
1273            public Object JavaDoc getById(long id, Connection conn) throws RepositoryException {
1274                try {
1275                    return loadPartType(id, user, conn);
1276                } catch (PartTypeNotFoundException e) {
1277                    throw new RepositoryException("Strange situation: the part type with ID " + id + " does not exist.");
1278                }
1279            }
1280        });
1281    }
1282
1283    public Collection getAllFieldTypes(final AuthenticatedUser user) throws RepositoryException {
1284        return getAllOfSomething("id", "field_types", "FieldTypes", new IdGettable() {
1285            public Object JavaDoc getById(long id, Connection conn) throws RepositoryException {
1286                return loadFieldType(id, user, conn);
1287            }
1288        });
1289    }
1290
1291    public Collection getAllDocumentTypes(final AuthenticatedUser user) throws RepositoryException {
1292        return getAllOfSomething("id", "document_types", "DocumentTypes", new IdGettable() {
1293            public Object JavaDoc getById(long id, Connection conn) throws RepositoryException {
1294                return loadDocumentType(id, user, conn);
1295            }
1296        });
1297    }
1298
1299    public Collection getAllOfSomething(String JavaDoc idColumnName, String JavaDoc tableName, String JavaDoc name, IdGettable idGettable) throws RepositoryException {
1300        ArrayLongList ids = new ArrayLongList(50);
1301
1302        Connection conn = null;
1303        PreparedStatement stmt = null;
1304        try {
1305            // retrieve the id's of all the objects
1306
conn = context.getDataSource().getConnection();
1307            jdbcHelper.startTransaction(conn);
1308
1309            stmt = conn.prepareStatement("select " + idColumnName + " from " + tableName);
1310            ResultSet rs = stmt.executeQuery();
1311
1312            while (rs.next()) {
1313                long id = rs.getLong(1);
1314                ids.add(id);
1315            }
1316            stmt.close();
1317
1318            // now effectively load the objects
1319
ArrayList objects = new ArrayList();
1320            LongIterator partIdIt = ids.iterator();
1321            while (partIdIt.hasNext()) {
1322                long id = partIdIt.next();
1323                objects.add(idGettable.getById(id, conn));
1324            }
1325
1326            return objects;
1327        } catch (Throwable JavaDoc e) {
1328            throw new RepositoryException("Error retrieving " + name, e);
1329        } finally {
1330            jdbcHelper.closeStatement(stmt);
1331            jdbcHelper.closeConnection(conn);
1332        }
1333    }
1334
1335    public LinkExtractorInfos getLinkExtractors(AuthenticatedUser user) {
1336        return new LinkExtractorInfosImpl(context.getLinkExtractors());
1337    }
1338
1339    interface IdGettable {
1340        public Object JavaDoc getById(long id, Connection conn) throws RepositoryException;
1341    }
1342
1343    public static FieldValueGetter getValueGetter(ValueType valueType) {
1344        if (valueType == ValueType.STRING)
1345            return STRING_FIELD_VALUE_GETTER;
1346        else if (valueType == ValueType.DATE)
1347            return DATE_FIELD_VALUE_GETTER;
1348        else if (valueType == ValueType.DATETIME)
1349            return DATETIME_FIELD_VALUE_GETTER;
1350        else if (valueType == ValueType.LONG)
1351            return LONG_FIELD_VALUE_GETTER;
1352        else if (valueType == ValueType.DOUBLE)
1353            return DOUBLE_FIELD_VALUE_GETTER;
1354        else if (valueType == ValueType.DECIMAL)
1355            return DECIMAL_FIELD_VALUE_GETTER;
1356        else if (valueType == ValueType.BOOLEAN)
1357            return BOOLEAN_FIELD_VALUE_GETTER;
1358        else if (valueType == ValueType.LINK)
1359            return LINK_FIELD_VALUE_GETTER;
1360        else
1361            throw new RuntimeException JavaDoc("Unrecognized ValueType: " + valueType);
1362    }
1363
1364    public static interface FieldValueGetter {
1365        Object JavaDoc getValue(ResultSet rs) throws SQLException;
1366    }
1367
1368    private static FieldValueGetter STRING_FIELD_VALUE_GETTER = new FieldValueGetter() {
1369        public Object JavaDoc getValue(ResultSet rs) throws SQLException {
1370            return rs.getString("stringvalue");
1371        }
1372    };
1373
1374    private static FieldValueGetter DATE_FIELD_VALUE_GETTER = new FieldValueGetter() {
1375        public Object JavaDoc getValue(ResultSet rs) throws SQLException {
1376            return rs.getDate("datevalue");
1377        }
1378    };
1379
1380    private static FieldValueGetter DATETIME_FIELD_VALUE_GETTER = new FieldValueGetter() {
1381        public Object JavaDoc getValue(ResultSet rs) throws SQLException {
1382            return rs.getTimestamp("datetimevalue");
1383        }
1384    };
1385
1386    private static FieldValueGetter LONG_FIELD_VALUE_GETTER = new FieldValueGetter() {
1387        public Object JavaDoc getValue(ResultSet rs) throws SQLException {
1388            return new Long JavaDoc(rs.getLong("integervalue"));
1389        }
1390    };
1391
1392    private static FieldValueGetter DOUBLE_FIELD_VALUE_GETTER = new FieldValueGetter() {
1393        public Object JavaDoc getValue(ResultSet rs) throws SQLException {
1394            return new Double JavaDoc(rs.getDouble("floatvalue"));
1395        }
1396    };
1397
1398    private static FieldValueGetter DECIMAL_FIELD_VALUE_GETTER = new FieldValueGetter() {
1399        public Object JavaDoc getValue(ResultSet rs) throws SQLException {
1400            return rs.getBigDecimal("decimalvalue");
1401        }
1402    };
1403
1404    private static FieldValueGetter BOOLEAN_FIELD_VALUE_GETTER = new FieldValueGetter() {
1405        public Object JavaDoc getValue(ResultSet rs) throws SQLException {
1406            return rs.getBoolean("booleanvalue") ? Boolean.TRUE : Boolean.FALSE;
1407        }
1408    };
1409
1410    private static FieldValueGetter LINK_FIELD_VALUE_GETTER = new FieldValueGetter() {
1411        public Object JavaDoc getValue(ResultSet rs) throws SQLException {
1412            long documentId = rs.getLong("link_docid");
1413            long branchId = rs.getLong("link_branchid");
1414            long languageId = rs.getLong("link_langid");
1415            return new VariantKey(documentId, branchId, languageId);
1416        }
1417    };
1418}
1419
Popular Tags