| 1 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 ; 34 import java.sql.*; 35 import java.util.*; 36 import java.util.Date ; 37 38 public class LocalSchemaStrategy implements SchemaStrategy { 39 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 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 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 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 lastModified = new java.util.Date (); 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 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 storeSelectionList(selectionListType, fieldType, id, conn); 133 134 eventDescription = createFieldTypeCreatedEvent(fieldType, id, lastModified); 135 } else { 136 logger.debug("update existing field type"); 137 138 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(); 151 FieldTypeImpl oldFieldType = getFieldTypeById(fieldType.getId(), fieldTypeInt.getCurrentModifier()); 152 long newUpdateCount = fieldType.getUpdateCount() + 1; 153 154 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 deleteSelectionList(id, conn); 172 173 storeSelectionList(selectionListType, fieldType, id, conn); 175 176 eventDescription = createFieldTypeUpdatedEvent(oldFieldType, fieldType, lastModified, newUpdateCount); 177 } 178 179 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 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 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 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 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 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 listItemValue = listItem.getValue(); 325 326 ValueType fieldValueType = fieldType.getValueType(); 327 String stringValue = (String )(fieldValueType == ValueType.STRING ? listItemValue : null); 328 Date dateValue = fieldValueType == ValueType.DATE ? new java.sql.Date (((Date )listItemValue).getTime()) : null; 329 Timestamp datetimeValue = fieldValueType == ValueType.DATETIME ? new Timestamp(((Date )listItemValue).getTime()) : null; 330 Long integerValue = (Long )(fieldValueType == ValueType.LONG ? listItemValue : null); 331 Double floatValue = (Double )(fieldValueType == ValueType.DOUBLE ? listItemValue : null); 332 BigDecimal decimalValue = (BigDecimal )(fieldValueType == ValueType.DECIMAL ? listItemValue : null); 333 Boolean booleanValue = (Boolean )(fieldValueType == ValueType.BOOLEAN ? listItemValue : null); 334 Long linkDocId = (fieldValueType == ValueType.LINK ? new Long (((VariantKey)listItemValue).getDocumentId()) : null); 335 Long linkBranchId = (fieldValueType == ValueType.LINK ? new Long (((VariantKey)listItemValue).getBranchId()) : null); 336 Long linkLangId = (fieldValueType == ValueType.LINK ? new Long (((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 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 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 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 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 boolean isNew = false; 476 long id = documentType.getId(); 477 long labelId = documentTypeInt.getLabelId(); 478 long descriptionId = documentTypeInt.getDescriptionId(); 479 java.util.Date lastModified = new java.util.Date (); 480 long lastModifier = documentTypeInt.getCurrentModifier().getId(); 481 XmlObject eventDescription; 482 483 if (id == -1) { 484 isNew = true; 485 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 507 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(); 520 DocumentTypeImpl oldDocumentType = getDocumentTypeById(documentType.getId(), documentTypeInt.getCurrentModifier()); 521 long newUpdateCount = documentType.getUpdateCount() + 1; 522 523 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 storeLocalizedStrings(labelId, conn, documentTypeInt.getLabels()); 539 storeLocalizedStrings(descriptionId, conn, documentTypeInt.getDescriptions()); 540 541 deleteDocumentTypeAssociations(id, conn); 542 543 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 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 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 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 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 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 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 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 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 boolean isNew = false; 726 long id = partType.getId(); 727 long labelId = partTypeInt.getLabelId(); 728 long descriptionId = partTypeInt.getDescriptionId(); 729 java.util.Date lastModified = new java.util.Date (); 730 long lastModifier = partTypeInt.getCurrentModifier().getId(); 731 XmlObject eventDescription; 732 733 if (id == -1) { 734 isNew = true; 735 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()); 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 760 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(); 773 PartTypeImpl oldPartType = getPartTypeById(partType.getId(), partTypeInt.getCurrentModifier()); 774 long newUpdateCount = partType.getUpdateCount() + 1; 775 776 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 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 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 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 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 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 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 locale = (String )entry.getKey(); 918 if (locale.equals("")) 919 locale = " "; String label = (String )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 name = rs.getString("name"); 966 String mimeTypes = rs.getString("mimetype").trim(); 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 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 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 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 locale = rs.getString(1).trim(); 1031 String 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 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 } 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 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 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 ("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 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 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 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 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 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 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 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 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 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 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 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 getById(long id, Connection conn) throws RepositoryException { 1294 return loadDocumentType(id, user, conn); 1295 } 1296 }); 1297 } 1298 1299 public Collection getAllOfSomething(String idColumnName, String tableName, String name, IdGettable idGettable) throws RepositoryException { 1300 ArrayLongList ids = new ArrayLongList(50); 1301 1302 Connection conn = null; 1303 PreparedStatement stmt = null; 1304 try { 1305 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 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 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 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 ("Unrecognized ValueType: " + valueType); 1362 } 1363 1364 public static interface FieldValueGetter { 1365 Object getValue(ResultSet rs) throws SQLException; 1366 } 1367 1368 private static FieldValueGetter STRING_FIELD_VALUE_GETTER = new FieldValueGetter() { 1369 public Object 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 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 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 getValue(ResultSet rs) throws SQLException { 1388 return new Long (rs.getLong("integervalue")); 1389 } 1390 }; 1391 1392 private static FieldValueGetter DOUBLE_FIELD_VALUE_GETTER = new FieldValueGetter() { 1393 public Object getValue(ResultSet rs) throws SQLException { 1394 return new Double (rs.getDouble("floatvalue")); 1395 } 1396 }; 1397 1398 private static FieldValueGetter DECIMAL_FIELD_VALUE_GETTER = new FieldValueGetter() { 1399 public Object 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 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 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 |