|
DatabaseDocumentImpl |
|
1 /* 2 * DatabaseDocumentImpl.java 3 * 4 * Copyright (c) 1998-2001, The University of Sheffield. 5 * 6 * This file is part of GATE (see http://gate.ac.uk/), and is free 7 * software, licenced under the GNU Library General Public License, 8 * Version 2, June 1991 (in the distribution as file licence.html, 9 * and also available at http://gate.ac.uk/gate/licence.html). 10 * 11 * Marin Dimitrov, 16/Oct/2001 12 * 13 * $Id: DatabaseDocumentImpl.java,v 1.42 2001/11/29 09:11:38 marin Exp $ 14 */ 15 16 package gate.corpora; 17 18 19 import java.sql.*; 20 import java.io.*; 21 import java.util.*; 22 import java.net.*; 23 24 import junit.framework.*; 25 26 import gate.*; 27 import gate.util.*; 28 import gate.persist.*; 29 import gate.annotation.*; 30 import gate.creole.*; 31 import gate.event.*; 32 33 public class DatabaseDocumentImpl extends DocumentImpl 34 implements DatastoreListener, 35 Document, 36 EventAwareDocument { 37 38 private static final boolean DEBUG = false; 39 40 private boolean isContentRead; 41 private Object contentLock; 42 private Connection jdbcConn; 43 44 private boolean contentChanged; 45 private boolean featuresChanged; 46 private boolean nameChanged; 47 private boolean documentChanged; 48 49 private Collection removedAnotationSets; 50 private Collection addedAnotationSets; 51 52 //this one should be the same as the values returned 53 //in persist.get_id_lot PL/SQL package 54 //it sux actually 55 private static final int SEQUENCE_POOL_SIZE = 10; 56 57 private Integer sequencePool[]; 58 private int poolMarker; 59 60 /** 61 * The listener for the events coming from the features. 62 */ 63 protected EventsHandler eventHandler; 64 65 66 public DatabaseDocumentImpl(Connection conn) { 67 68 //super(); 69 contentLock = new Object(); 70 71 this.namedAnnotSets = new HashMap(); 72 // this.defaultAnnots = new DatabaseAnnotationSetImpl(this); 73 74 this.isContentRead = false; 75 this.jdbcConn = conn; 76 77 this.contentChanged = false; 78 this.featuresChanged = false; 79 this.nameChanged = false; 80 this.documentChanged = false; 81 82 this.removedAnotationSets = new Vector(); 83 this.addedAnotationSets = new Vector(); 84 85 sequencePool = new Integer[this.SEQUENCE_POOL_SIZE]; 86 poolMarker = this.SEQUENCE_POOL_SIZE; 87 } 88 89 public DatabaseDocumentImpl(Connection _conn, 90 String _name, 91 DatabaseDataStore _ds, 92 Long _persistenceID, 93 DocumentContent _content, 94 FeatureMap _features, 95 Boolean _isMarkupAware, 96 URL _sourceURL, 97 Long _urlStartOffset, 98 Long _urlEndOffset, 99 AnnotationSet _default, 100 Map _named) { 101 102 //this.jdbcConn = _conn; 103 this(_conn); 104 105 this.name = _name; 106 this.dataStore = _ds; 107 this.lrPersistentId = _persistenceID; 108 this.content = _content; 109 this.isContentRead = true; 110 this.features = _features; 111 this.markupAware = _isMarkupAware; 112 this.sourceUrl = _sourceURL; 113 this.sourceUrlStartOffset = _urlStartOffset; 114 this.sourceUrlEndOffset = _urlEndOffset; 115 116 //annotations 117 //1. default 118 _setAnnotations(null,_default); 119 120 //2. named (if any) 121 if (null != _named) { 122 Iterator itNamed = _named.values().iterator(); 123 while (itNamed.hasNext()){ 124 AnnotationSet currSet = (AnnotationSet)itNamed.next(); 125 //add them all to the DBAnnotationSet 126 _setAnnotations(currSet.getName(),currSet); 127 } 128 } 129 130 //3. add the listeners for the features 131 if (eventHandler == null) 132 eventHandler = new EventsHandler(); 133 this.features.addFeatureMapListener(eventHandler); 134 135 //4. add self as listener for the data store, so that we'll know when the DS is 136 //synced and we'll clear the isXXXChanged flags 137 this.dataStore.addDatastoreListener(this); 138 } 139 140 /** The content of the document: a String for text; MPEG for video; etc. */ 141 public DocumentContent getContent() { 142 143 //1. assert that no one is reading from DB now 144 synchronized(this.contentLock) { 145 if (false == this.isContentRead) { 146 _readContent(); 147 this.isContentRead = true; 148 } 149 } 150 151 //return content 152 return super.getContent(); 153 } 154 155 private void _readContent() { 156 157 //preconditions 158 if (null == getLRPersistenceId()) { 159 throw new GateRuntimeException("can't construct a DatabaseDocument - not associated " + 160 " with any data store"); 161 } 162 163 if (false == getLRPersistenceId() instanceof Long) { 164 throw new GateRuntimeException("can't construct a DatabaseDocument - " + 165 " invalid persistence ID"); 166 } 167 168 Long lrID = (Long)getLRPersistenceId(); 169 //0. preconditions 170 Assert.assertNotNull(lrID); 171 Assert.assertTrue(false == this.isContentRead); 172 Assert.assertNotNull(this.content); 173 174 //1. read from DB 175 PreparedStatement pstmt = null; 176 ResultSet rs = null; 177 178 try { 179 String sql = " select v1.enc_name, " + 180 " v1.dc_character_content, " + 181 " v1.dc_binary_content, " + 182 " v1.dc_content_type " + 183 " from "+Gate.DB_OWNER+".v_content v1 " + 184 " where v1.lr_id = ? "; 185 186 pstmt = this.jdbcConn.prepareStatement(sql); 187 pstmt.setLong(1,lrID.longValue()); 188 pstmt.execute(); 189 rs = pstmt.getResultSet(); 190 191 rs.next(); 192 193 String encoding = rs.getString(1); 194 Clob clb = rs.getClob(2); 195 Blob blb = rs.getBlob(3); 196 long contentType = rs.getLong(4); 197 198 Assert.assertTrue(DBHelper.CHARACTER_CONTENT == contentType); 199 200 StringBuffer buff = new StringBuffer(); 201 OracleDataStore.readCLOB(clb,buff); 202 203 //2. set data members that were not previously initialized 204 this.content = new DocumentContentImpl(buff.toString()); 205 this.encoding = encoding; 206 } 207 catch(SQLException sqle) { 208 throw new SynchronisationException("can't read content from DB: ["+ sqle.getMessage()+"]"); 209 } 210 catch(IOException ioe) { 211 throw new SynchronisationException(ioe); 212 } 213 finally { 214 try { 215 DBHelper.cleanup(rs); 216 DBHelper.cleanup(pstmt); 217 } 218 catch(PersistenceException pe) { 219 throw new SynchronisationException("JDBC error: ["+ pe.getMessage()+"]"); 220 } 221 } 222 } 223 224 225 /** Get the encoding of the document content source */ 226 public String getEncoding() { 227 228 //1. assert that no one is reading from DB now 229 synchronized(this.contentLock) { 230 if (false == this.isContentRead) { 231 _readContent(); 232 233 this.isContentRead = true; 234 } 235 } 236 237 return super.getEncoding(); 238 } 239 240 /** Returns a map with the named annotation sets. It returns <code>null</code> 241 * if no named annotaton set exists. */ 242 public Map getNamedAnnotationSets() { 243 244 Vector annNames = new Vector(); 245 246 PreparedStatement pstmt = null; 247 ResultSet rs = null; 248 249 //1. get the names of all sets 250 try { 251 String sql = " select as_name " + 252 " from "+Gate.DB_OWNER+".v_annotation_set " + 253 " where lr_id = ? " + 254 " and as_name is not null"; 255 256 pstmt = this.jdbcConn.prepareStatement(sql); 257 pstmt.setLong(1,((Long)this.lrPersistentId).longValue()); 258 pstmt.execute(); 259 rs = pstmt.getResultSet(); 260 261 while (rs.next()) { 262 annNames.add(rs.getString("as_name")); 263 } 264 } 265 catch(SQLException sqle) { 266 throw new SynchronisationException("can't get named annotatios: ["+ sqle.getMessage()+"]"); 267 } 268 finally { 269 try { 270 DBHelper.cleanup(rs); 271 DBHelper.cleanup(pstmt); 272 } 273 catch(PersistenceException pe) { 274 throw new SynchronisationException("JDBC error: ["+ pe.getMessage()+"]"); 275 } 276 } 277 278 //2. read annotations 279 for (int i=0; i< annNames.size(); i++) { 280 //delegate because of the data is already read getAnnotations() will just return 281 getAnnotations((String)annNames.elementAt(i)); 282 } 283 284 //3. delegate to the parent method 285 return super.getNamedAnnotationSets(); 286 287 } // getNamedAnnotationSets 288 289 290 /** Get the default set of annotations. The set is created if it 291 * doesn't exist yet. 292 */ 293 public AnnotationSet getAnnotations() { 294 295 //1. read from DB 296 _getAnnotations(null); 297 298 //2. is there such set in the DB? 299 if (null == this.defaultAnnots) { 300 //create a DatabaseAnnotationSetImpl 301 //NOTE: we create the set and then delegate to the super mehtod, otherwise 302 //the super mehtod will create AnnotationSetImpl instead of DatabaseAnnotationSetImpl 303 //which will not work with DatabaseDocumentImpl 304 AnnotationSet aset = new DatabaseAnnotationSetImpl(this); 305 306 //set internal member 307 this.defaultAnnots = aset; 308 309 //3. fire events 310 fireAnnotationSetAdded(new DocumentEvent(this, 311 DocumentEvent.ANNOTATION_SET_ADDED, 312 null)); 313 } 314 315 //4. delegate 316 return super.getAnnotations(); 317 } // getAnnotations() 318 319 320 /** Get a named set of annotations. Creates a new set if one with this 321 * name doesn't exist yet. 322 * If the provided name is null then it returns the default annotation set. 323 */ 324 public AnnotationSet getAnnotations(String name) { 325 326 //0. preconditions 327 Assert.assertNotNull(name); 328 329 //1. read from DB if the set is there at all 330 _getAnnotations(name); 331 332 //2. is there such set in the DB? 333 if (false == this.namedAnnotSets.keySet().contains(name)) { 334 //create a DatabaseAnnotationSetImpl 335 //NOTE: we create the set and then delegate to the super mehtod, otherwise 336 //the super mehtod will create AnnotationSetImpl instead of DatabaseAnnotationSetImpl 337 //which will not work with DatabaseDocumentImpl 338 AnnotationSet aset = new DatabaseAnnotationSetImpl(this,name); 339 340 //add to internal collection 341 this.namedAnnotSets.put(name,aset); 342 343 //add the set name to the list with the recently created sets 344 this.addedAnotationSets.add(name); 345 346 //3. fire events 347 DocumentEvent evt = new DocumentEvent(this, DocumentEvent.ANNOTATION_SET_ADDED, name); 348 fireAnnotationSetAdded(evt); 349 } 350 351 //3. delegate 352 return super.getAnnotations(name); 353 } 354 355 356 private void _getAnnotations(String name) { 357 358 AnnotationSet as = null; 359 360 //preconditions 361 if (null == getLRPersistenceId()) { 362 throw new GateRuntimeException("can't construct a DatabaseDocument - not associated " + 363 " with any data store"); 364 } 365 366 if (false == getLRPersistenceId() instanceof Long) { 367 throw new GateRuntimeException("can't construct a DatabaseDocument - " + 368 " invalid persistence ID"); 369 } 370 371 //have we already read this set? 372 373 if (null == name) { 374 //default set 375 if (this.defaultAnnots != null) { 376 //the default set is alredy read - do nothing 377 //super methods will take care 378 return; 379 } 380 } 381 else { 382 //named set 383 if (this.namedAnnotSets.containsKey(name)) { 384 //we've already read it - do nothing 385 //super methods will take care 386 return; 387 } 388 } 389 390 391 Long lrID = (Long)getLRPersistenceId(); 392 Long asetID = null; 393 //0. preconditions 394 Assert.assertNotNull(lrID); 395 396 //1. read a-set info 397 PreparedStatement pstmt = null; 398 ResultSet rs = null; 399 try { 400 String sql = " select as_id " + 401 " from "+Gate.DB_OWNER+".v_annotation_set " + 402 " where lr_id = ? "; 403 //do we have aset name? 404 String clause = null; 405 if (null != name) { 406 clause = " and as_name = ? "; 407 } 408 else { 409 clause = " and as_name is null "; 410 } 411 sql = sql + clause; 412 //System.out.println(sql); 413 pstmt = this.jdbcConn.prepareStatement(sql); 414 pstmt.setLong(1,lrID.longValue()); 415 if (null != name) { 416 pstmt.setString(2,name); 417 } 418 pstmt.execute(); 419 rs = pstmt.getResultSet(); 420 421 if (rs.next()) { 422 //ok, there is such aset in the DB 423 asetID = new Long(rs.getLong(1)); 424 } 425 else { 426 //wow, there is no such aset, so create new ... 427 //... by delegating to the super method 428 return; 429 } 430 431 //2. read annotation Features 432 HashMap featuresByAnnotationID = _readFeatures(asetID); 433 434 //3. read annotations 435 AnnotationSetImpl transSet = new AnnotationSetImpl(this); 436 437 try { 438 String sql1 = " select ann_local_id, " + 439 " at_name, " + 440 " start_offset, " + 441 " end_offset " + 442 " from "+Gate.DB_OWNER+".v_annotation " + 443 " where asann_as_id = ? "; 444 445 if (DEBUG) Out.println(">>>>> asetID=["+asetID+"]"); 446 447 pstmt = this.jdbcConn.prepareStatement(sql1); 448 pstmt.setLong(1,asetID.longValue()); 449 pstmt.execute(); 450 rs = pstmt.getResultSet(); 451 452 while (rs.next()) { 453 //1. read data memebers 454 Integer annID = new Integer(rs.getInt(1)); 455 String type = rs.getString(2); 456 Long startOffset = new Long(rs.getLong(3)); 457 Long endOffset = new Long(rs.getLong(4)); 458 459 if (DEBUG) Out.println("annID=["+annID+"]"); 460 if (DEBUG) Out.println("start=["+startOffset+"]"); 461 if (DEBUG) Out.println("end=["+endOffset+"]"); 462 463 //2. get the features 464 FeatureMap fm = (FeatureMap)featuresByAnnotationID.get(annID); 465 //fm may should NOT be null 466 if (null == fm) { 467 fm = new SimpleFeatureMapImpl(); 468 } 469 470 //3. add to annotation set 471 transSet.add(annID,startOffset,endOffset,type,fm); 472 }//while 473 }//read the annotations 474 catch(SQLException sqle) { 475 throw new SynchronisationException("can't read content from DB: [" 476 + sqle.getMessage()+"]"); 477 } 478 catch(InvalidOffsetException oe) { 479 throw new SynchronisationException(oe); 480 } 481 finally { 482 try { 483 DBHelper.cleanup(rs); 484 DBHelper.cleanup(pstmt); 485 } 486 catch(PersistenceException pe) { 487 throw new SynchronisationException("JDBC error: [" 488 + pe.getMessage()+"]"); 489 } 490 }//finally 491 492 //1.5, create a-set 493 if (null == name) { 494 as = new DatabaseAnnotationSetImpl(this, transSet); 495 } 496 else { 497 as = new DatabaseAnnotationSetImpl(this,name, transSet); 498 } 499 500 //1.6 add the new a-set to the list of the a-sets read from the DB 501 // this.loadedAnnotSets.add(as); 502 503 } 504 catch(SQLException sqle) { 505 throw new SynchronisationException("can't read annotations from DB: ["+ sqle.getMessage()+"]"); 506 } 507 finally { 508 try { 509 DBHelper.cleanup(rs); 510 DBHelper.cleanup(pstmt); 511 } 512 catch(PersistenceException pe) { 513 throw new SynchronisationException("JDBC error: ["+ pe.getMessage()+"]"); 514 } 515 } 516 517 518 //4. update internal data members 519 if (name == null) { 520 //default as 521 this.defaultAnnots = as; 522 } 523 else { 524 //named as 525 this.namedAnnotSets.put(name,as); 526 } 527 528 //don't return the new aset, the super method will take care 529 return; 530 } 531 532 533 534 535 private HashMap _readFeatures(Long asetID) { 536 537 PreparedStatement pstmt = null; 538 ResultSet rs = null; 539 540 //1 541 String prevKey = DBHelper.DUMMY_FEATURE_KEY; 542 String currKey = null; 543 544 Integer prevAnnID = null; 545 Integer currAnnID = null; 546 547 Object currFeatureValue = null; 548 Vector currFeatureArray = new Vector(); 549 550 HashMap currFeatures = new HashMap(); 551 FeatureMap annFeatures = null; 552 553 HashMap featuresByAnnotID = new HashMap(); 554 555 //2. read the features from DB 556 try { 557 String sql = " select ann_local_id, " + 558 " ft_key, " + 559 " ft_value_type, " + 560 " ft_number_value, " + 561 " ft_character_value, " + 562 " ft_long_character_value, " + 563 " ft_binary_value " + 564 " from "+Gate.DB_OWNER+".v_annotation_features " + 565 " where set_id = ? " + 566 " order by ann_local_id,ft_key "; 567 //System.out.println(sql); 568 pstmt = this.jdbcConn.prepareStatement(sql); 569 pstmt.setLong(1,asetID.longValue()); 570 pstmt.execute(); 571 rs = pstmt.getResultSet(); 572 573 while (rs.next()) { 574 //NOTE: because there are LOBs in the resulset 575 //the columns should be read in the order they appear 576 //in the query 577 578 prevAnnID = currAnnID; 579 currAnnID = new Integer(rs.getInt(1)); 580 581 //2.1 is this a new Annotation? 582 if (!currAnnID.equals(prevAnnID) && prevAnnID != null) { 583 //new one 584 //2.1.1 normalize the hashmap with the features, and add 585 //the elements into a new FeatureMap 586 annFeatures = new SimpleFeatureMapImpl(); 587 Set entries = currFeatures.entrySet(); 588 Iterator itFeatureArrays = entries.iterator(); 589 590 while(itFeatureArrays.hasNext()) { 591 Map.Entry currEntry = (Map.Entry)itFeatureArrays.next(); 592 String key = (String)currEntry.getKey(); 593 Vector val = (Vector)currEntry.getValue(); 594 595 //add to feature map normalized array 596 Assert.assertTrue(val.size() >= 1); 597 598 if (val.size() == 1) { 599 //the single elemnt of the array 600 annFeatures.put(key,val.firstElement()); 601 } 602 else { 603 //the whole array 604 annFeatures.put(key,val); 605 } 606 }//while 607 608 //2.1.2. add the featuremap for this annotation to the hashmap 609 featuresByAnnotID.put(prevAnnID,annFeatures); 610 //2.1.3. clear temp hashtable with feature vectors 611 currFeatures.clear(); 612 /*??*/ prevAnnID = currAnnID; 613 }//if -- is new annotation 614 615 currKey = rs.getString(2); 616 Long valueType = new Long(rs.getLong(3)); 617 618 //we don't quite know what is the type of the NUMBER 619 //stored in DB 620 Object numberValue = null; 621 622 //for all numeric types + boolean -> read from DB as appropriate 623 //Java object 624 switch(valueType.intValue()) { 625 626 case DBHelper.VALUE_TYPE_BOOLEAN: 627 numberValue = new Boolean(rs.getBoolean(4)); 628 break; 629 630 case DBHelper.VALUE_TYPE_FLOAT: 631 numberValue = new Float(rs.getFloat(4)); 632 break; 633 634 case DBHelper.VALUE_TYPE_INTEGER: 635 numberValue = new Integer(rs.getInt(4)); 636 break; 637 638 case DBHelper.VALUE_TYPE_LONG: 639 numberValue = new Long(rs.getLong(4)); 640 break; 641 642 default: 643 //do nothing, will be handled in the next switch statement 644 } 645 646 //don't forget to read the rest of the current row 647 String stringValue = rs.getString(5); 648 Clob clobValue = rs.getClob(6); 649 Blob blobValue = rs.getBlob(7); 650 651 switch(valueType.intValue()) { 652 653 case DBHelper.VALUE_TYPE_BINARY: 654 throw new MethodNotImplementedException(); 655 656 case DBHelper.VALUE_TYPE_BOOLEAN: 657 case DBHelper.VALUE_TYPE_FLOAT: 658 case DBHelper.VALUE_TYPE_INTEGER: 659 case DBHelper.VALUE_TYPE_LONG: 660 currFeatureValue = numberValue; 661 break; 662 663 case DBHelper.VALUE_TYPE_STRING: 664 //this one is tricky too 665 //if the string is < 4000 bytes long then it's stored as varchar2 666 //otherwise as CLOB 667 if (null == stringValue) { 668 //oops, we got CLOB 669 StringBuffer temp = new StringBuffer(); 670 OracleDataStore.readCLOB(clobValue,temp); 671 currFeatureValue = temp.toString(); 672 } 673 else { 674 currFeatureValue = stringValue; 675 } 676 break; 677 678 default: 679 throw new SynchronisationException("Invalid feature type found in DB"); 680 }//switch 681 682 //ok, we got the key/value pair now 683 //2.2 is this a new feature key? 684 if (false == currFeatures.containsKey(currKey)) { 685 //new key 686 Vector keyValue = new Vector(); 687 keyValue.add(currFeatureValue); 688 currFeatures.put(currKey,keyValue); 689 } 690 else { 691 //key is present, append to existing vector 692 ((Vector)currFeatures.get(currKey)).add(currFeatureValue); 693 } 694 695 prevKey = currKey; 696 }//while 697 698 699 //2.3 process the last Annotation left 700 annFeatures = new SimpleFeatureMapImpl(); 701 702 Set entries = currFeatures.entrySet(); 703 Iterator itFeatureArrays = entries.iterator(); 704 705 while(itFeatureArrays.hasNext()) { 706 Map.Entry currEntry = (Map.Entry)itFeatureArrays.next(); 707 String key = (String)currEntry.getKey(); 708 Vector val = (Vector)currEntry.getValue(); 709 710 //add to feature map normalized array 711 Assert.assertTrue(val.size() >= 1); 712 713 if (val.size() == 1) { 714 //the single elemnt of the array 715 annFeatures.put(key,val.firstElement()); 716 } 717 else { 718 //the whole array 719 annFeatures.put(key,val); 720 } 721 }//while 722 723 //2.3.1. add the featuremap for this annotation to the hashmap 724 if (null != currAnnID) { 725 // do we have features at all for this annotation? 726 featuresByAnnotID.put(currAnnID,annFeatures); 727 } 728 729 //3. return the hashmap 730 return featuresByAnnotID; 731 } 732 catch(SQLException sqle) { 733 throw new SynchronisationException("can't read content from DB: ["+ sqle.getMessage()+"]"); 734 } 735 catch(IOException sqle) { 736 throw new SynchronisationException("can't read content from DB: ["+ sqle.getMessage()+"]"); 737 } 738 finally { 739 try { 740 DBHelper.cleanup(rs); 741 DBHelper.cleanup(pstmt); 742 } 743 catch(PersistenceException pe) { 744 throw new SynchronisationException("JDBC error: ["+ pe.getMessage()+"]"); 745 } 746 } 747 } 748 749 750 /** Set method for the document content */ 751 public void setContent(DocumentContent content) { 752 753 super.setContent(content); 754 755 this.contentChanged = true; 756 } 757 758 /** Set the feature set */ 759 public void setFeatures(FeatureMap features) { 760 //1. save them first, so we can remove the listener 761 FeatureMap oldFeatures = this.features; 762 763 super.setFeatures(features); 764 765 this.featuresChanged = true; 766 767 //4. sort out the listeners 768 if (eventHandler != null) 769 oldFeatures.removeFeatureMapListener(eventHandler); 770 else 771 eventHandler = new EventsHandler(); 772 this.features.addFeatureMapListener(eventHandler); 773 } 774 775 /** Sets the name of this resource*/ 776 public void setName(String name){ 777 super.setName(name); 778 779 this.nameChanged = true; 780 } 781 782 783 private List getAnnotationsForOffset(AnnotationSet aDumpAnnotSet,Long offset){ 784 throw new MethodNotImplementedException(); 785 } 786 787 /** Generate and return the next annotation ID */ 788 /* public Integer getNextAnnotationId() { 789 790 //1.try to get ID fromt he pool 791 if (DEBUG) { 792 Out.println(">>> get annID called..."); 793 } 794 //is there anything left in the pool? 795 if (this.SEQUENCE_POOL_SIZE == this.poolMarker) { 796 //oops, pool is empty 797 fillSequencePool(); 798 this.poolMarker = 0; 799 } 800 801 return this.sequencePool[this.poolMarker++]; 802 803 return super.getNextAnnotationId(); 804 } // getNextAnnotationId 805 806 807 public void setNextAnnotationId(int aNextAnnotationId){ 808 809 //if u get this exception then u definitely don't have an idea what u're doing 810 throw new UnsupportedOperationException("Annotation IDs cannot be changed in " + 811 "database stores"); 812 }// setNextAnnotationId(); 813 814 815 private void fillSequencePool() { 816 817 if(DEBUG) { 818 Out.println("filling ID lot..."); 819 } 820 821 CallableStatement stmt = null; 822 try { 823 stmt = this.jdbcConn.prepareCall( 824 "{ call "+Gate.DB_OWNER+".persist.get_id_lot(?,?,?,?,?,?,?,?,?,?) }"); 825 stmt.registerOutParameter(1,java.sql.Types.BIGINT); 826 stmt.registerOutParameter(2,java.sql.Types.BIGINT); 827 stmt.registerOutParameter(3,java.sql.Types.BIGINT); 828 stmt.registerOutParameter(4,java.sql.Types.BIGINT); 829 stmt.registerOutParameter(5,java.sql.Types.BIGINT); 830 stmt.registerOutParameter(6,java.sql.Types.BIGINT); 831 stmt.registerOutParameter(7,java.sql.Types.BIGINT); 832 stmt.registerOutParameter(8,java.sql.Types.BIGINT); 833 stmt.registerOutParameter(9,java.sql.Types.BIGINT); 834 stmt.registerOutParameter(10,java.sql.Types.BIGINT); 835 stmt.execute(); 836 837 for (int i=0; i < this.SEQUENCE_POOL_SIZE; i++) { 838 //JDBC countsa from 1, not from 0 839 this.sequencePool[0] = new Integer(stmt.getInt(i+1)); 840 } 841 } 842 catch(SQLException sqle) { 843 throw new SynchronisationException("can't get Annotation ID pool: ["+ sqle.getMessage()+"]"); 844 } 845 finally { 846 try { 847 DBHelper.cleanup(stmt); 848 } 849 catch(PersistenceException pe) { 850 throw new SynchronisationException("JDBC error: ["+ pe.getMessage()+"]"); 851 } 852 } 853 } 854 */ 855 856 public boolean isResourceChanged(int changeType) { 857 858 switch(changeType) { 859 860 case EventAwareLanguageResource.DOC_CONTENT: 861 return this.contentChanged; 862 case EventAwareLanguageResource.RES_FEATURES: 863 return this.featuresChanged; 864 case EventAwareLanguageResource.RES_NAME: 865 return this.nameChanged; 866 case EventAwareLanguageResource.DOC_MAIN: 867 return this.documentChanged; 868 default: 869 throw new IllegalArgumentException(); 870 } 871 872 } 873 874 private void _setAnnotations(String setName,Collection annotations) { 875 876 if (null == setName) { 877 Assert.assertTrue(null == this.defaultAnnots); 878 this.defaultAnnots = new DatabaseAnnotationSetImpl(this,annotations); 879 880 //add to the set of loaded a-sets but do not add its annotations to the 881 //list of new annotations 882 // this.loadedAnnotSets.add(this.defaultAnnots); 883 } 884 else { 885 Assert.assertTrue(false == this.namedAnnotSets.containsKey(setName)); 886 AnnotationSet annSet = new DatabaseAnnotationSetImpl(this,setName,annotations); 887 this.namedAnnotSets.put(setName,annSet); 888 889 //add to the set of loaded a-sets but do not add its annotations to the 890 //list of new annotations 891 // this.loadedAnnotSets.add(annSet); 892 } 893 } 894 895 /** Set method for the document's URL */ 896 public void setSourceUrl(URL sourceUrl) { 897 898 this.documentChanged = true; 899 super.setSourceUrl(sourceUrl); 900 } // setSourceUrl 901 902 903 /** Documents may be packed within files; in this case an optional pair of 904 * offsets refer to the location of the document. This method sets the 905 * end offset. 906 */ 907 public void setSourceUrlEndOffset(Long sourceUrlEndOffset) { 908 909 this.documentChanged = true; 910 super.setSourceUrlEndOffset(sourceUrlEndOffset); 911 } // setSourceUrlStartOffset 912 913 914 /** Documents may be packed within files; in this case an optional pair of 915 * offsets refer to the location of the document. This method sets the 916 * start offset. 917 */ 918 public void setSourceUrlStartOffset(Long sourceUrlStartOffset) { 919 920 this.documentChanged = true; 921 super.setSourceUrlStartOffset(sourceUrlStartOffset); 922 } // setSourceUrlStartOffset 923 924 /** Make the document markup-aware. This will trigger the creation 925 * of a DocumentFormat object at Document initialisation time; the 926 * DocumentFormat object will unpack the markup in the Document and 927 * add it as annotations. Documents are <B>not</B> markup-aware by default. 928 * 929 * @param b markup awareness status. 930 */ 931 public void setMarkupAware(Boolean newMarkupAware) { 932 933 this.documentChanged = true; 934 super.setMarkupAware(newMarkupAware); 935 } 936 937 /** 938 * All the events from the features are handled by 939 * this inner class. 940 */ 941 class EventsHandler implements gate.event.FeatureMapListener { 942 public void featureMapUpdated(){ 943 //tell the document that its features have been updated 944 featuresChanged = true; 945 } 946 } 947 948 /** 949 * Overriden to remove the features listener, when the document is closed. 950 */ 951 public void cleanup() { 952 super.cleanup(); 953 if (eventHandler != null) 954 this.features.removeFeatureMapListener(eventHandler); 955 }///inner class EventsHandler 956 957 958 /** 959 * Called by a datastore when a new resource has been adopted 960 */ 961 public void resourceAdopted(DatastoreEvent evt){ 962 } 963 964 /** 965 * Called by a datastore when a resource has been deleted 966 */ 967 public void resourceDeleted(DatastoreEvent evt){ 968 969 Assert.assertNotNull(evt); 970 Assert.assertNotNull(evt.getResourceID()); 971 972 //unregister self as listener from the DataStore 973 if (evt.getResourceID().equals(this.getLRPersistenceId())) { 974 //someone deleted this document 975 getDataStore().removeDatastoreListener(this); 976 } 977 978 }//resourceDeleted 979 980 /** 981 * Called by a datastore when a resource has been wrote into the datastore 982 */ 983 public void resourceWritten(DatastoreEvent evt){ 984 985 Assert.assertNotNull(evt); 986 Assert.assertNotNull(evt.getResourceID()); 987 988 //is the event for us? 989 if (evt.getResourceID().equals(this.getLRPersistenceId())) { 990 //wow, the event is for me 991 //clear all flags, the content is synced with the DB 992 this.contentChanged = 993 this.documentChanged = 994 this.featuresChanged = 995 this.nameChanged = false; 996 997 this.removedAnotationSets.clear(); 998 this.addedAnotationSets.clear(); 999 } 1000 1001 1002 } 1003 1004 public Collection getLoadedAnnotationSets() { 1005 1006 //never return the data member - return a clone 1007 Assert.assertNotNull(this.namedAnnotSets); 1008 Vector result = new Vector(this.namedAnnotSets.values()); 1009 if (null != this.defaultAnnots) { 1010 result.add(this.defaultAnnots); 1011 } 1012 1013 return result; 1014 } 1015 1016 1017 public Collection getRemovedAnnotationSets() { 1018 1019 //return a clone 1020 return new Vector(this.removedAnotationSets); 1021 } 1022 1023 public Collection getAddedAnnotationSets() { 1024 1025 //return a clone 1026 return new Vector(this.addedAnotationSets); 1027 } 1028 1029 public void removeAnnotationSet(String name) { 1030 1031 //1. add to the list of removed a-sets 1032 this.removedAnotationSets.add(name); 1033 1034 //if the set was read from the DB then it is registered as datastore listener and ... 1035 //there may be chnges in it 1036 //NOTE that default set cannot be reoved, so we just ignore it 1037 1038 if (this.namedAnnotSets.keySet().contains(name)) { 1039 //set was loaded 1040 AnnotationSet aset = (AnnotationSet)this.namedAnnotSets.get(name); 1041 1042 Assert.assertNotNull(aset); 1043 Assert.assertTrue(aset instanceof DatabaseAnnotationSetImpl); 1044 1045 //3. unregister it as a DataStoreListener 1046 this.dataStore.removeDatastoreListener((DatastoreListener)aset); 1047 } 1048 1049 //4. delegate 1050 super.removeAnnotationSet(name); 1051 } 1052 1053}
|
DatabaseDocumentImpl |
|