1
15
16 package gate.persist;
17
18 import java.io.Serializable;
19 import java.net.URL;
20 import java.sql.*;
21 import java.util.*;
22
23 import junit.framework.Assert;
24 import oracle.jdbc.driver.OraclePreparedStatement;
25
26 import gate.*;
27 import gate.annotation.DatabaseAnnotationSetImpl;
28 import gate.annotation.EventAwareAnnotationSet;
29 import gate.corpora.*;
30 import gate.event.*;
31 import gate.security.*;
32 import gate.security.SecurityException;
33 import gate.util.*;
34
35 public abstract class JDBCDataStore extends AbstractFeatureBearer
36 implements DatabaseDataStore,
37 CreoleListener {
38
39
40 private static final boolean DEBUG = false;
41
42
43 private String dbURL;
44 protected String dbSchema;
45 protected int dbType;
46
47 protected String datastoreComment;
48 protected String iconName;
49
50
51
53
57 private String dbID;
58
59
60 protected Session session;
61
62
63 protected String name;
64
65
67 protected transient Connection jdbcConn;
68
69
72 protected transient AccessController ac;
73
74
75 private transient Vector datastoreListeners;
76
77
78 protected transient Vector dependentResources;
79
80
81 protected JDBCDataStore() {
82
83 this.datastoreListeners = new Vector();
84 this.dependentResources = new Vector();
85 }
86
87
88
89
90
94 public String getComment() {
95
96 Assert.assertNotNull(this.datastoreComment);
97 return this.datastoreComment;
98 }
99
100
104 public String getIconName() {
105 Assert.assertNotNull(this.iconName);
106 return this.iconName;
107 }
108
109
110
111
112 public String getLrName(Object lrId)
113 throws PersistenceException {
114
115 if (false == lrId instanceof Long) {
116 throw new IllegalArgumentException();
117 }
118
119 Long ID = (Long)lrId;
120
121 PreparedStatement pstmt = null;
122 ResultSet rset = null;
123
124 try {
125 String sql = " select lr_name " +
126 " from "+this.dbSchema+"t_lang_resource " +
127 " where lr_id = ?";
128
129 pstmt = this.jdbcConn.prepareStatement(sql);
130 pstmt.setLong(1,ID.longValue());
131 pstmt.execute();
132 rset = pstmt.getResultSet();
133
134 rset.next();
135 String result = rset.getString("lr_name");
136
137 return result;
138 }
139 catch(SQLException sqle) {
140 throw new PersistenceException("can't get LR name from DB: ["+ sqle.getMessage()+"]");
141 }
142 finally {
143 DBHelper.cleanup(pstmt);
144 DBHelper.cleanup(rset);
145 }
146 }
147
148
149
150
151 public void setStorageUrl(String storageUrl) throws PersistenceException {
152
153 if (!storageUrl.startsWith("jdbc:")) {
154 throw new PersistenceException("Incorrect JDBC url (should start with \"jdbc:\")");
155 }
156 else {
157 this.dbURL = storageUrl;
158 this.dbSchema = DBHelper.getSchemaPrefix(this.dbURL);
159 this.dbType = DBHelper.getDatabaseType(this.dbURL);
160 Assert.assertNotNull(this.dbSchema);
161 Assert.assertTrue(this.dbType > 0);
162 }
163
164 }
165
166
167 public String getStorageUrl() {
168
169 return this.dbURL;
170 }
171
172
173
178 public void create()
179 throws PersistenceException, UnsupportedOperationException {
180
181 throw new UnsupportedOperationException("create() is not supported for DatabaseDataStore");
182 }
183
184
185
186
187 public void open() throws PersistenceException {
188 try {
189
190 jdbcConn = DBHelper.connect(dbURL);
192
193 this.ac = Factory.createAccessController(dbURL);
196
197 ac.open();
199
200 this.dbID = this.readDatabaseID();
202
203 }
204 catch(SQLException sqle) {
205 throw new PersistenceException("could not get DB connection ["+ sqle.getMessage() +"]");
206 }
207 catch(ClassNotFoundException clse) {
208 throw new PersistenceException("cannot locate JDBC driver ["+ clse.getMessage() +"]");
209 }
210
211 Gate.getCreoleRegister().addCreoleListener(this);
213 }
214
215
216 public void close() throws PersistenceException {
217
218 Gate.getCreoleRegister().removeCreoleListener(this);
220
221 for (int i=0; i< this.dependentResources.size(); i++) {
223 LanguageResource lr = (LanguageResource)this.dependentResources.elementAt(i);
224
225 try {
226 sync(lr);
227 }
228 catch(SecurityException se) {
229 }
234
235 Factory.deleteResource(lr);
237 }
238
239 ac.close();
241
242 DBHelper.disconnect(this.jdbcConn);
243
244 Gate.getDataStoreRegister().remove(this);
246 }
247
248
253 public void delete()
254 throws PersistenceException, UnsupportedOperationException {
255
256 throw new UnsupportedOperationException("delete() is not supported for DatabaseDataStore");
257 }
258
259
264
265 public void delete(String lrClassName, Object lrId)
266 throws PersistenceException,SecurityException {
267 if (false == lrId instanceof Long) {
269 throw new IllegalArgumentException();
270 }
271
272 if (!lrClassName.equals(DBHelper.DOCUMENT_CLASS) &&
273 !lrClassName.equals(DBHelper.CORPUS_CLASS)) {
274 throw new IllegalArgumentException("Only Corpus and Document classes are supported" +
275 " by Database data store");
276 }
277
278 if (null == this.session) {
280 throw new SecurityException("session not set");
281 }
282
283 if (false == this.ac.isValidSession(this.session)) {
284 throw new SecurityException("invalid session supplied");
285 }
286
287 if (false == canWriteLR(lrId)) {
289 throw new SecurityException("insufficient privileges");
290 }
291
292 User lockingUser = this.getLockingUser((Long)lrId);
295 User currUser = this.session.getUser();
296
297 if (null != lockingUser && false == lockingUser.equals(currUser)) {
298 throw new PersistenceException("LR locked by another user");
300 }
301
302 boolean transFailed = false;
303 try {
304 beginTrans();
306
307 if (lrClassName.equals(DBHelper.DOCUMENT_CLASS)) {
309 deleteDocument((Long)lrId);
310 }
311 else {
312 deleteCorpus((Long)lrId);
313 }
314
315 commitTrans();
317 }
318 catch(PersistenceException pe) {
319 transFailed = true;
320 throw(pe);
321 }
322 finally {
323 if (transFailed) {
325 rollbackTrans();
326 }
327 }
328
329
332 boolean resourceFound = false;
334 Iterator it = this.dependentResources.iterator();
335 while (it.hasNext()) {
336 LanguageResource lr = (LanguageResource)it.next();
337 if (lr.getLRPersistenceId().equals(lrId)) {
338 resourceFound = true;
339 it.remove();
340 break;
341 }
342 }
343
344
346 fireResourceDeleted(
348 new DatastoreEvent(this, DatastoreEvent.RESOURCE_DELETED, null, lrId));
349
350 try {
352 unloadLR((Long)lrId);
353 }
354 catch(GateException ge) {
355 Err.prln("can't unload resource from GUI...");
356 }
357 }
358
359
360
361
365 public void sync(LanguageResource lr)
366 throws PersistenceException,SecurityException {
367
368 _sync(lr,true);
370 }
371
372
373
378 public void setAutoSaving(boolean autoSaving)
379 throws UnsupportedOperationException,PersistenceException {
380 try {
381 this.jdbcConn.setAutoCommit(true);
382 }
383 catch(SQLException sqle) {
384 throw new PersistenceException("cannot change autosave mode ["+sqle.getMessage()+"]");
385 }
386
387 }
388
389
390 public boolean isAutoSaving() {
391 throw new MethodNotImplementedException();
392 }
393
394
395 public LanguageResource adopt(LanguageResource lr, SecurityInfo secInfo)
396 throws PersistenceException,SecurityException {
397 return _adopt(lr,secInfo,true);
399 }
400
401
402 protected LanguageResource _adopt(LanguageResource lr,
403 SecurityInfo secInfo,
404 boolean openNewTrans)
405 throws PersistenceException,SecurityException {
406
407 LanguageResource result = null;
408
409 Assert.assertNotNull(lr);
411 Assert.assertNotNull(secInfo);
412 if (false == lr instanceof Document &&
413 false == lr instanceof Corpus) {
414 throw new IllegalArgumentException("only Documents and Corpuses could "+
416 "be serialized in DB");
417 }
418
419 if (false == this.ac.isValidSecurityInfo(secInfo)) {
421 throw new SecurityException("Invalid security settings supplied");
422 }
423
424 if (null == this.session) {
426 throw new SecurityException("user session not set");
427 }
428
429 DataStore currentDS = lr.getDataStore();
431 if(currentDS == null) {
432 }
434 else if(currentDS.equals(this)){ return lr;
436 }
437 else { throw new PersistenceException(
439 "Can't adopt a resource which is already in a different datastore");
440 }
441
442
443 if (false == lr instanceof Document &&
445 false == lr instanceof Corpus) {
446
447 throw new IllegalArgumentException("Database datastore is implemented only for "+
448 "Documents and Corpora");
449 }
450
451 Object persistID = lr.getLRPersistenceId();
453 if (persistID != null) {
454 throw new PersistenceException("This LR is already stored in the " +
455 " database (persistance ID is =["+(Long)persistID+"] )");
456 }
457
458 boolean transFailed = false;
459 try {
460 if (openNewTrans) {
462 beginTrans();
464 }
465
466 if (lr instanceof Document) {
468 result = createDocument((Document)lr,secInfo);
469 }
471 else {
472 result = createCorpus((Corpus)lr,secInfo,true);
474 }
475
476 if (openNewTrans) {
478 commitTrans();
480 }
481 }
482
488 catch(PersistenceException pe) {
489 transFailed = true;
490 throw(pe);
491 }
492 catch(SecurityException se) {
493 transFailed = true;
494 throw(se);
495 }
496 finally {
497 if (transFailed) {
499 System.out.println("trans failed ...rollback");
500 rollbackTrans();
501
508 }
509 }
510
511 fireResourceAdopted(
513 new DatastoreEvent(this, DatastoreEvent.RESOURCE_ADOPTED,
514 result,
515 result.getLRPersistenceId())
516 );
517
518 fireResourceWritten(
520 new DatastoreEvent(this, DatastoreEvent.RESOURCE_WRITTEN,
521 result,
522 result.getLRPersistenceId()
523 )
524 );
525
526 this.dependentResources.add(result);
529
530 return result;
531 }
532
533
534
535 public List getLrTypes() throws PersistenceException {
536
537 Vector lrTypes = new Vector();
538 Statement stmt = null;
539 ResultSet rs = null;
540
541 try {
542 stmt = this.jdbcConn.createStatement();
543 rs = stmt.executeQuery(" SELECT lrtp_type " +
544 " FROM "+this.dbSchema+"t_lr_type LRTYPE ");
545
546 while (rs.next()) {
547 String lrType = rs.getString(1);
549 lrTypes.add(lrType);
550 }
551
552 return lrTypes;
553 }
554 catch(SQLException sqle) {
555 throw new PersistenceException("can't get LR types from DB: ["+ sqle.getMessage()+"]");
556 }
557 finally {
558 DBHelper.cleanup(rs);
559 DBHelper.cleanup(stmt);
560 }
561 }
562
563
564
565 public List getLrIds(String lrType) throws PersistenceException {
566
567 Vector lrIDs = new Vector();
568 PreparedStatement stmt = null;
569 ResultSet rs = null;
570
571 try {
572 stmt = this.jdbcConn.prepareStatement(
573 " SELECT lr_id " +
574 " FROM "+this.dbSchema+"t_lang_resource LR, " +
575 " "+this.dbSchema+"t_lr_type LRTYPE " +
576 " WHERE LR.lr_type_id = LRTYPE.lrtp_id " +
577 " AND LRTYPE.lrtp_type = ? " +
578 " ORDER BY lr_name"
579 );
580 stmt.setString(1,lrType);
581
582 if (this.dbType == DBHelper.ORACLE_DB) {
584 ((OraclePreparedStatement)stmt).setRowPrefetch(DBHelper.CHINK_SIZE_SMALL);
585 }
586
587 stmt.execute();
588 rs = stmt.getResultSet();
589
590 while (rs.next()) {
591 Long lrID = new Long(rs.getLong(1));
593 lrIDs.add(lrID);
594 }
595
596 return lrIDs;
597 }
598 catch(SQLException sqle) {
599 throw new PersistenceException("can't get LR types from DB: ["+ sqle.getMessage()+"]");
600 }
601 finally {
602 DBHelper.cleanup(rs);
603 DBHelper.cleanup(stmt);
604 }
605
606 }
607
608
609
610 public List getLrNames(String lrType) throws PersistenceException {
611
612 Vector lrNames = new Vector();
613 PreparedStatement stmt = null;
614 ResultSet rs = null;
615
616 try {
617 stmt = this.jdbcConn.prepareStatement(
618 " SELECT lr_name " +
619 " FROM "+this.dbSchema+"t_lang_resource LR, " +
620 " t_lr_type LRTYPE " +
621 " WHERE LR.lr_type_id = LRTYPE.lrtp_id " +
622 " AND LRTYPE.lrtp_type = ? " +
623 " ORDER BY lr_name desc"
624 );
625 stmt.setString(1,lrType);
626
627 if (this.dbType == DBHelper.ORACLE_DB) {
629 ((OraclePreparedStatement)stmt).setRowPrefetch(DBHelper.CHINK_SIZE_SMALL);
630 }
631
632 stmt.execute();
633 rs = stmt.getResultSet();
634
635 while (rs.next()) {
636 String lrName = rs.getString(1);
638 lrNames.add(lrName);
639 }
640
641 return lrNames;
642 }
643 catch(SQLException sqle) {
644 throw new PersistenceException("can't get LR types from DB: ["+ sqle.getMessage()+"]");
645 }
646 finally {
647 DBHelper.cleanup(rs);
648 DBHelper.cleanup(stmt);
649 }
650 }
651
652
656 public boolean canReadLR(Object lrID)
657 throws PersistenceException, SecurityException{
658
659 return canAccessLR((Long) lrID,DBHelper.READ_ACCESS);
660 }
661
662
663
664
668 public boolean canWriteLR(Object lrID)
669 throws PersistenceException, SecurityException{
670
671 return canAccessLR((Long) lrID,DBHelper.WRITE_ACCESS);
672 }
673
674
678 protected boolean canAccessLR(Long lrID,int mode)
679 throws PersistenceException, SecurityException{
680
681 throw new MethodNotImplementedException();
683 }
684
685
686
687
694 public void beginTrans()
695 throws PersistenceException,UnsupportedOperationException{
696
697 try {
698 this.jdbcConn.setAutoCommit(false);
699 }
700 catch(SQLException sqle) {
701 throw new PersistenceException("cannot begin transaction, DB error is: ["
702 +sqle.getMessage()+"]");
703 }
704 }
705
706
707
711 public void commitTrans()
712 throws PersistenceException,UnsupportedOperationException{
713
714 try {
715 this.jdbcConn.commit();
716 }
717 catch(SQLException sqle) {
718 throw new PersistenceException("cannot commit transaction, DB error is: ["
719 +sqle.getMessage()+"]");
720 }
721
722 }
723
724
725 public void rollbackTrans()
726 throws PersistenceException,UnsupportedOperationException{
727
728 try {
729 this.jdbcConn.rollback();
730 }
731 catch(SQLException sqle) {
732 throw new PersistenceException("cannot commit transaction, DB error is: ["
733 +sqle.getMessage()+"]");
734 }
735
736 }
737
738
739 public Long timestamp()
740 throws PersistenceException{
741
742 throw new MethodNotImplementedException();
744 }
745
746
747 public void deleteSince(Long timestamp)
748 throws PersistenceException{
749
750 throw new MethodNotImplementedException();
751 }
752
753
754
760
761 public void setName(String name){
762 this.name = name;
763 }
764
765
766 public String getName(){
767 return name;
768 }
769
770
771
772 protected int findFeatureType(Object value) {
773
774 if (null == value)
775 return DBHelper.VALUE_TYPE_NULL;
776 else if (value instanceof Integer)
777 return DBHelper.VALUE_TYPE_INTEGER;
778 else if (value instanceof Long)
779 return DBHelper.VALUE_TYPE_LONG;
780 else if (value instanceof Boolean)
781 return DBHelper.VALUE_TYPE_BOOLEAN;
782 else if (value instanceof Double ||
783 value instanceof Float)
784 return DBHelper.VALUE_TYPE_FLOAT;
785 else if (value instanceof String)
786 return DBHelper.VALUE_TYPE_STRING;
787 else if (value instanceof List) {
788 List arr = (List)value;
790
791 if (arr.isEmpty()) {
792 return DBHelper.VALUE_TYPE_EMPTY_ARR;
793 }
794 else {
795 Object element = arr.get(0);
796
797 if (element instanceof Integer)
798 return DBHelper.VALUE_TYPE_INTEGER_ARR;
799 else if (element instanceof Long)
800 return DBHelper.VALUE_TYPE_LONG_ARR;
801 else if (element instanceof Boolean)
802 return DBHelper.VALUE_TYPE_BOOLEAN_ARR;
803 else if (element instanceof Double ||
804 element instanceof Float)
805 return DBHelper.VALUE_TYPE_FLOAT_ARR;
806 else if (element instanceof String)
807 return DBHelper.VALUE_TYPE_STRING_ARR;
808 }
809 }
810 else if (value instanceof Serializable) {
811 return DBHelper.VALUE_TYPE_BINARY;
812 }
813
814 throw new IllegalArgumentException();
816 }
817
818
819 public String getDatabaseID() {
820 return this.dbID;
821 }
822
823
824
827
831 protected String readDatabaseID() throws PersistenceException{
832
833 PreparedStatement pstmt = null;
834 ResultSet rs = null;
835 String result = null;
836
837 try {
839 String sql = " select par_value_string " +
840 " from "+this.dbSchema+"t_parameter " +
841 " where par_key = ? ";
842
843 pstmt = this.jdbcConn.prepareStatement(sql);
844 pstmt.setString(1,DBHelper.DB_PARAMETER_GUID);
845 pstmt.execute();
846 rs = pstmt.getResultSet();
847
848 if (false == rs.next()) {
849 throw new PersistenceException("Can't read database parameter ["+
850 DBHelper.DB_PARAMETER_GUID+"]");
851 }
852 result = rs.getString(1);
853 }
854 catch(SQLException sqle) {
855 throw new PersistenceException("Can't read database parameter ["+
856 sqle.getMessage()+"]");
857 }
858 finally {
859 DBHelper.cleanup(rs);
860 DBHelper.cleanup(pstmt);
861 }
862
863 if (DEBUG) {
864 Out.println("reult=["+result+"]");
865 }
866
867 return result;
868 }
869
870
871
875 public void removeDatastoreListener(DatastoreListener l) {
876
877 Assert.assertNotNull(this.datastoreListeners);
878
879 synchronized(this.datastoreListeners) {
880 this.datastoreListeners.remove(l);
881 }
882 }
883
884
885
888 public void addDatastoreListener(DatastoreListener l) {
889
890 Assert.assertNotNull(this.datastoreListeners);
891
892
899 synchronized(this.datastoreListeners) {
900 if (false == this.datastoreListeners.contains(l)) {
901 this.datastoreListeners.add(l);
902 }
903 }
904 }
905
906 protected void fireResourceAdopted(DatastoreEvent e) {
907
908 Assert.assertNotNull(datastoreListeners);
909 Vector temp = this.datastoreListeners;
910
911 int count = temp.size();
912 for (int i = 0; i < count; i++) {
913 ((DatastoreListener)temp.elementAt(i)).resourceAdopted(e);
914 }
915 }
916
917
918 protected void fireResourceDeleted(DatastoreEvent e) {
919
920 Assert.assertNotNull(datastoreListeners);
921 Vector temp = this.datastoreListeners;
922
923 int count = temp.size();
924 for (int i = 0; i < count; i++) {
925 ((DatastoreListener)temp.elementAt(i)).resourceDeleted(e);
926 }
927 }
928
929
930 protected void fireResourceWritten(DatastoreEvent e) {
931 Assert.assertNotNull(datastoreListeners);
932 Vector temp = this.datastoreListeners;
933
934 int count = temp.size();
935 for (int i = 0; i < count; i++) {
936 ((DatastoreListener)temp.elementAt(i)).resourceWritten(e);
937 }
938 }
939
940 public void resourceLoaded(CreoleEvent e) {
941 if(DEBUG)
942 System.out.println("resource loaded...");
943 }
944
945 public void resourceRenamed(Resource resource, String oldName,
946 String newName){
947 }
948
949
950 public void resourceUnloaded(CreoleEvent e) {
951
952 Assert.assertNotNull(e.getResource());
953 if(! (e.getResource() instanceof LanguageResource))
954 return;
955
956 LanguageResource lr = (LanguageResource)e.getResource();
958
959 if(lr.getDataStore() != this)
961 return;
962
963 this.dependentResources.remove(lr);
965
966
968 this.removeDatastoreListener((DatastoreListener)lr);
972 }
973
974 public void datastoreOpened(CreoleEvent e) {
975 if(DEBUG)
976 System.out.println("datastore opened...");
977 }
978
979 public void datastoreCreated(CreoleEvent e) {
980 if(DEBUG)
981 System.out.println("datastore created...");
982 }
983
984 public void datastoreClosed(CreoleEvent e) {
985 if(DEBUG)
986 System.out.println("datastore closed...");
987 }
989
990
991 public void setSession(Session s)
992 throws gate.security.SecurityException {
993
994 this.session = s;
995 }
996
997
998
999
1000 public Session getSession(Session s)
1001 throws gate.security.SecurityException {
1002
1003 return this.session;
1004 }
1005
1006
1007 public abstract List findLrIds(List constraints) throws PersistenceException;
1008
1009
1013 public abstract List findLrIds(List constraints, String lrType)
1014 throws PersistenceException;
1015
1016
1017
1018 public SecurityInfo getSecurityInfo(LanguageResource lr)
1019 throws PersistenceException {
1020
1021 Assert.assertNotNull(lr);
1023 Assert.assertNotNull(lr.getLRPersistenceId());
1024 Assert.assertTrue(lr.getLRPersistenceId() instanceof Long);
1025 Assert.assertEquals(this,lr.getDataStore());
1026 Assert.assertTrue(lr instanceof DatabaseDocumentImpl ||
1027 lr instanceof DatabaseCorpusImpl);
1028
1029 PreparedStatement pstmt = null;
1030 ResultSet rs = null;
1031
1032 Long userID = null;
1034 Long groupID = null;
1035 int perm;
1036 try {
1037 String sql = " select lr_owner_user_id, "+
1038 " lr_owner_group_id, " +
1039 " lr_access_mode "+
1040 " from "+this.dbSchema+"t_lang_resource "+
1041 " where lr_id = ?";
1042 pstmt = this.jdbcConn.prepareStatement(sql);
1043 pstmt.setLong(1,((Long)lr.getLRPersistenceId()).longValue());
1044 rs = pstmt.executeQuery();
1045
1046 if (false == rs.next()) {
1047 throw new PersistenceException("Invalid LR ID supplied - no data found");
1048 }
1049
1050 userID = new Long(rs.getLong("lr_owner_user_id"));
1051 groupID = new Long(rs.getLong("lr_owner_group_id"));
1052 perm = rs.getInt("lr_access_mode");
1053
1054 Assert.assertTrue(perm == SecurityInfo.ACCESS_GR_GW ||
1055 perm == SecurityInfo.ACCESS_GR_OW ||
1056 perm == SecurityInfo.ACCESS_OR_OW ||
1057 perm == SecurityInfo.ACCESS_WR_GW);
1058 }
1059 catch(SQLException sqle) {
1060 throw new PersistenceException("Can't read document permissions from DB, error is [" +
1061 sqle.getMessage() +"]");
1062 }
1063 finally {
1064 DBHelper.cleanup(rs);
1065 DBHelper.cleanup(pstmt);
1066 }
1067
1068 User usr = null;
1070 Group grp = null;
1071 try {
1072 usr = this.ac.findUser(userID);
1073 grp = this.ac.findGroup(groupID);
1074 }
1075 catch (SecurityException se) {
1076 throw new PersistenceException("Invalid security settings found in DB [" +
1077 se.getMessage() +"]");
1078 }
1079
1080 SecurityInfo si = new SecurityInfo(perm,usr,grp);
1082
1083
1084 return si;
1085 }
1086
1087
1088 protected Corpus createCorpus(Corpus corp,SecurityInfo secInfo, boolean newTransPerDocument)
1089 throws PersistenceException,SecurityException {
1090
1091 Long lrID = createLR(DBHelper.CORPUS_CLASS,corp.getName(),secInfo,null);
1093
1094 Long corpusID = null;
1096 CallableStatement cstmt = null;
1098 PreparedStatement pstmt = null;
1099 ResultSet rs = null;
1100
1101 try {
1102 if (this.dbType == DBHelper.ORACLE_DB) {
1103 cstmt = this.jdbcConn.prepareCall("{ call "+Gate.DB_OWNER+".persist.create_corpus(?,?) }");
1104 cstmt.setLong(1,lrID.longValue());
1105 cstmt.registerOutParameter(2,java.sql.Types.BIGINT);
1106 cstmt.execute();
1107 corpusID = new Long(cstmt.getLong(2));
1108 }
1109 else if (this.dbType == DBHelper.POSTGRES_DB) {
1110 pstmt = this.jdbcConn.prepareStatement("select persist_create_corpus(?) ");
1111 pstmt.setLong(1,lrID.longValue());
1112 pstmt.execute();
1113 rs = pstmt.getResultSet();
1114
1115 if (false == rs.next()) {
1116 throw new PersistenceException("empty result set");
1117 }
1118
1119 corpusID = new Long(rs.getLong(1));
1120 }
1121 else {
1122 Assert.fail();
1123 }
1124 }
1125 catch(SQLException sqle) {
1126 throw new PersistenceException("can't create corpus [step 2] in DB: ["+ sqle.getMessage()+"]");
1127 }
1128 finally {
1129 DBHelper.cleanup(cstmt);
1130 DBHelper.cleanup(pstmt);
1131 DBHelper.cleanup(rs);
1132 }
1133
1134 Iterator itDocuments = corp.iterator();
1136 Vector dbDocs = new Vector();
1137
1138 while (itDocuments.hasNext()) {
1139 Document doc = (Document)itDocuments.next();
1140
1141 if (doc.getLRPersistenceId() == null) {
1144
1146 if (newTransPerDocument) {
1149 beginTrans();
1150 }
1151
1152 itDocuments.remove();
1156
1157 Document dbDoc = createDocument(doc,corpusID,secInfo);
1159
1160 if (newTransPerDocument) {
1161 commitTrans();
1162 }
1163
1164 dbDocs.add(dbDoc);
1165 fireResourceAdopted(new DatastoreEvent(this,
1167 DatastoreEvent.RESOURCE_ADOPTED,
1168 dbDoc,
1169 dbDoc.getLRPersistenceId()
1170 )
1171 );
1172
1173 fireResourceWritten(new DatastoreEvent(this,
1175 DatastoreEvent.RESOURCE_WRITTEN,
1176 dbDoc,
1177 dbDoc.getLRPersistenceId()
1178 )
1179 );
1180
1181 }
1185 else if (doc.getDataStore().equals(this)) {
1186 fireResourceAdopted(
1188 new DatastoreEvent(this, DatastoreEvent.RESOURCE_ADOPTED,
1189 doc,
1190 doc.getLRPersistenceId()));
1191
1192 fireResourceWritten(
1194 new DatastoreEvent(this, DatastoreEvent.RESOURCE_WRITTEN,
1195 doc,
1196 doc.getLRPersistenceId()));
1197 }
1198 else {
1199 gate.util.Err.prln("document ["+doc.getLRPersistenceId()+"] is adopted from another "+
1202 " datastore. Skipped.");
1203 }
1204 }
1205
1206 if (this.dbType == DBHelper.ORACLE_DB) {
1208 createFeaturesBulk(lrID,DBHelper.FEATURE_OWNER_CORPUS,corp.getFeatures());
1209 }
1210 else if (this.dbType == DBHelper.POSTGRES_DB) {
1211 createFeatures(lrID,DBHelper.FEATURE_OWNER_CORPUS,corp.getFeatures());
1212 }
1213 else {
1214 Assert.fail();
1215 }
1216
1217
1218
1226 Corpus dbCorpus = null;
1227 FeatureMap params = Factory.newFeatureMap();
1228 HashMap initData = new HashMap();
1229
1230 initData.put("DS",this);
1231 initData.put("LR_ID",lrID);
1232 initData.put("CORP_NAME",corp.getName());
1233 initData.put("CORP_FEATURES",corp.getFeatures());
1234 initData.put("CORP_SUPPORT_LIST",dbDocs);
1235
1236 params.put("initData__$$__", initData);
1237
1238 try {
1239 dbCorpus = (Corpus)Factory.createResource("gate.corpora.DatabaseCorpusImpl", params);
1242 }
1243 catch (gate.creole.ResourceInstantiationException ex) {
1244 throw new GateRuntimeException(ex.getMessage());
1245 }
1246
1247 return dbCorpus;
1249 }
1250
1251
1255 protected Document createDocument(Document doc,SecurityInfo secInfo)
1256 throws PersistenceException,SecurityException {
1257
1258 return createDocument(doc,null,secInfo);
1260 }
1261
1262
1263
1267 protected Document createDocument(Document doc, Long corpusID,SecurityInfo secInfo)
1268 throws PersistenceException,SecurityException {
1269
1270 Assert.assertNotNull(doc);
1272 Assert.assertNotNull(secInfo);
1273
1274 if (false == this.ac.isValidSecurityInfo(secInfo)) {
1276 throw new SecurityException("Invalid security settings");
1277 }
1278
1279 AnnotationSet defaultAnnotations = doc.getAnnotations();
1281 DocumentContent docContent = doc.getContent();
1282 FeatureMap docFeatures = doc.getFeatures();
1283 String docName = doc.getName();
1284 URL docURL = doc.getSourceUrl();
1285 Boolean docIsMarkupAware = doc.getMarkupAware();
1286 Long docStartOffset = doc.getSourceUrlStartOffset();
1287 Long docEndOffset = doc.getSourceUrlEndOffset();
1288 String docEncoding = null;
1289 try {
1290 docEncoding = (String)doc.
1291 getParameterValue(Document.DOCUMENT_ENCODING_PARAMETER_NAME);
1292 }
1293 catch(gate.creole.ResourceInstantiationException re) {
1294 throw new PersistenceException("cannot create document: error getting " +
1295 " document encoding ["+re.getMessage()+"]");
1296 }
1297
1298
1299 Long lrID = createLR(DBHelper.DOCUMENT_CLASS,docName,secInfo,null);
1301
1302 Long docID = createDoc(lrID,
1304 docURL,
1305 docEncoding,
1306 docStartOffset,
1307 docEndOffset,
1308 docIsMarkupAware,
1309 corpusID);
1310
1311
1312
1314 if (docContent.size().longValue() > 0) {
1316 updateDocumentContent(docID,docContent);
1318 }
1319
1320
1322 createAnnotationSet(lrID,defaultAnnotations);
1324
1325 Map namedAnns = doc.getNamedAnnotationSets();
1327 if (null != namedAnns) {
1329 Set setAnns = namedAnns.entrySet();
1330 Iterator itAnns = setAnns.iterator();
1331
1332 while (itAnns.hasNext()) {
1333 Map.Entry mapEntry = (Map.Entry)itAnns.next();
1334 AnnotationSet currAnnSet = (AnnotationSet)mapEntry.getValue();
1336
1337 createAnnotationSet(lrID,currAnnSet);
1339 }
1340 }
1341
1342 if (this.dbType == DBHelper.ORACLE_DB) {
1344 createFeaturesBulk(lrID,DBHelper.FEATURE_OWNER_DOCUMENT,docFeatures);
1345 }
1346 else if (this.dbType == DBHelper.POSTGRES_DB) {
1347 createFeatures(lrID,DBHelper.FEATURE_OWNER_DOCUMENT,docFeatures);
1348 }
1349 else {
1350 Assert.fail();
1351 }
1352
1353
1354
1356
1369 Document dbDoc = null;
1370 FeatureMap params = Factory.newFeatureMap();
1371
1372 HashMap initData = new HashMap();
1373 initData.put("JDBC_CONN",this.jdbcConn);
1374 initData.put("DS",this);
1375 initData.put("LR_ID",lrID);
1376 initData.put("DOC_NAME",doc.getName());
1377 initData.put("DOC_CONTENT",doc.getContent());
1378 initData.put("DOC_FEATURES",doc.getFeatures());
1379 initData.put("DOC_MARKUP_AWARE",doc.getMarkupAware());
1380 initData.put("DOC_SOURCE_URL",doc.getSourceUrl());
1381 if(doc instanceof DocumentImpl){
1382 initData.put("DOC_STRING_CONTENT",
1383 ((DocumentImpl)doc).getStringContent());
1384 }
1385 initData.put("DOC_SOURCE_URL_START",doc.getSourceUrlStartOffset());
1386 initData.put("DOC_SOURCE_URL_END",doc.getSourceUrlEndOffset());
1387 initData.put("DOC_DEFAULT_ANNOTATIONS",doc.getAnnotations());
1388 initData.put("DOC_NAMED_ANNOTATION_SETS",doc.getNamedAnnotationSets());
1389
1390 params.put("initData__$$__", initData);
1391
1392 try {
1393 dbDoc = (Document)Factory.createResource("gate.corpora.DatabaseDocumentImpl", params);
1396 }
1397 catch (gate.creole.ResourceInstantiationException ex) {
1398 throw new GateRuntimeException(ex.getMessage());
1399 }
1400
1401 Factory.deleteResource(doc);
1404
1405 return dbDoc;
1406 }
1407
1408 protected abstract Long createLR(String lrType,
1409 String lrName,
1410 SecurityInfo si,
1411 Long lrParentID)
1412 throws PersistenceException,SecurityException;
1413
1414
1415 protected abstract Long createDoc(Long _lrID,
1416 URL _docURL,
1417 String _docEncoding,
1418 Long _docStartOffset,
1419 Long _docEndOffset,
1420 Boolean _docIsMarkupAware,
1421 Long _corpusID)
1422 throws PersistenceException;
1423
1424 protected abstract void updateDocumentContent(Long docID,DocumentContent content)
1425 throws PersistenceException;
1426
1427 protected abstract void createAnnotationSet(Long lrID, AnnotationSet aset)
1428 throws PersistenceException;
1429
1430 protected abstract void createFeaturesBulk(Long entityID, int entityType, FeatureMap features)
1431 throws PersistenceException;
1432
1433 protected abstract void createFeatures(Long entityID, int entityType, FeatureMap features)
1434 throws PersistenceException;
1435
1436
1440 protected void _sync(LanguageResource lr, boolean openNewTrans)
1441 throws PersistenceException,SecurityException {
1442
1443 Assert.assertNotNull(lr);
1445 Long lrID = (Long)lr.getLRPersistenceId();
1446
1447 if (false == lr instanceof Document &&
1448 false == lr instanceof Corpus) {
1449 throw new IllegalArgumentException("only Documents and Corpuses could "+
1451 "be serialized in DB");
1452 }
1453
1454 if( null == lr.getDataStore() || false == lr.getDataStore().equals(this))
1456 throw new PersistenceException(
1457 "This LR is not stored in this DataStore"
1458 );
1459
1460
1461 if (null == this.session) {
1463 throw new SecurityException("session not set");
1464 }
1465
1466 if (false == this.ac.isValidSession(this.session)) {
1467 throw new SecurityException("invalid session supplied");
1468 }
1469
1470 if (false == canWriteLR(lrID)) {
1472 throw new SecurityException("insufficient privileges");
1473 }
1474
1475 User lockingUser = getLockingUser(lr);
1477 User currUser = this.session.getUser();
1478
1479 if (lockingUser != null && false == lockingUser.equals(currUser)) {
1480 throw new PersistenceException("document is locked by another user and cannot be synced");
1481 }
1482
1483
1484 boolean transFailed = false;
1485 try {
1486 if (openNewTrans) {
1488 beginTrans();
1489 }
1490
1491 if (lr instanceof Document) {
1493 syncDocument((Document)lr);
1494 }
1495 else {
1496 syncCorpus((Corpus)lr);
1497 }
1498
1499 if (openNewTrans) {
1501 commitTrans();
1502 }
1503 }
1504 catch(PersistenceException pe) {
1505 transFailed = true;
1506 throw(pe);
1507 }
1508 finally {
1509 if (transFailed) {
1511 rollbackTrans();
1512 }
1513 }
1514
1515 fireResourceWritten(
1517 new DatastoreEvent(this, DatastoreEvent.RESOURCE_WRITTEN, lr, lr.getLRPersistenceId()));
1518 }
1519
1520
1523 protected User getLockingUser(LanguageResource lr)
1524 throws PersistenceException,SecurityException {
1525
1526 Assert.assertNotNull(lr);
1528 Assert.assertTrue(lr instanceof DatabaseDocumentImpl ||
1529 lr instanceof DatabaseCorpusImpl);
1530 Assert.assertNotNull(lr.getLRPersistenceId());
1531 Assert.assertEquals(lr.getDataStore(),this);
1532
1533 return getLockingUser((Long)lr.getLRPersistenceId());
1535 }
1536
1537
1538
1539
1542 protected User getLockingUser(Long lrID)
1543 throws PersistenceException,SecurityException {
1544
1545 if (null == this.session) {
1547 throw new SecurityException("session not set");
1548 }
1549
1550 if (false == this.ac.isValidSession(this.session)) {
1551 throw new SecurityException("invalid session supplied");
1552 }
1553
1554 PreparedStatement pstmt = null;
1556 Long userID = null;
1557 ResultSet rs = null;
1558
1559 try {
1560
1561 String sql = null;
1562
1563 if (this.dbType == DBHelper.ORACLE_DB) {
1564 sql = " select nvl(lr_locking_user_id,0) as user_id" +
1565 " from "+this.dbSchema+"t_lang_resource " +
1566 " where lr_id = ?";
1567 }
1568 else if (this.dbType == DBHelper.POSTGRES_DB) {
1569 sql = " select coalesce(lr_locking_user_id,0) as user_id" +
1570 " from t_lang_resource " +
1571 " where lr_id = ?";
1572 }
1573 else {
1574 throw new IllegalArgumentException();
1575 }
1576
1577 pstmt = this.jdbcConn.prepareStatement(sql);
1578 pstmt.setLong(1,lrID.longValue());
1579 pstmt.execute();
1580 rs = pstmt.getResultSet();
1581
1582 if (false == rs.next()) {
1583 throw new PersistenceException("LR not found in DB");
1584 }
1585
1586 long result = rs.getLong("user_id");
1587
1588 return result == 0 ? null
1589 : this.ac.findUser(new Long(result));
1590 }
1591 catch(SQLException sqle) {
1592 throw new PersistenceException("can't get locking user from DB : ["+ sqle.getMessage()+"]");
1593 }
1594 finally {
1595 DBHelper.cleanup(rs);
1596 DBHelper.cleanup(pstmt);
1597 }
1598 }
1599
1600
1601 protected void syncCorpus(Corpus corp)
1602 throws PersistenceException,SecurityException {
1603
1604 Assert.assertNotNull(corp);
1606 Assert.assertTrue(corp instanceof DatabaseCorpusImpl);
1607 Assert.assertEquals(this,corp.getDataStore());
1608 Assert.assertNotNull(corp.getLRPersistenceId());
1609
1610 EventAwareCorpus dbCorpus = (EventAwareCorpus)corp;
1611
1612 if (dbCorpus.isResourceChanged(EventAwareLanguageResource.RES_NAME)) {
1614 _syncLR(corp);
1615 }
1616
1617 if (dbCorpus.isResourceChanged(EventAwareLanguageResource.RES_FEATURES)) {
1619 _syncFeatures(corp);
1620 }
1621
1622 List removedDocLRIDs = dbCorpus.getRemovedDocuments();
1625 if (removedDocLRIDs.size() > 0) {
1626 _syncRemovedDocumentsFromCorpus(removedDocLRIDs,(Long)corp.getLRPersistenceId());
1627 }
1628
1629 Iterator it = dbCorpus.getLoadedDocuments().iterator();
1632 List newlyAddedDocs = dbCorpus.getAddedDocuments();
1634
1635 while (it.hasNext()) {
1636 Document dbDoc = (Document)it.next();
1637 if (null == dbDoc) {
1640 continue;
1641 }
1642
1643 if (null == dbDoc.getLRPersistenceId()) {
1645
1647 it.remove();
1649
1650 SecurityInfo si = getSecurityInfo(corp);
1652
1653
1654 Document adoptedDoc = null;
1655 try {
1656 adoptedDoc = (Document)_adopt(dbDoc,si,true);
1660
1661 addDocumentToCorpus((Long)adoptedDoc.getLRPersistenceId(),
1663 (Long)corp.getLRPersistenceId());
1664 }
1665 catch(SecurityException se) {
1666 throw new PersistenceException(se);
1667 }
1668
1669 corp.add(adoptedDoc);
1671 }
1672 else {
1673 try {
1676 _sync(dbDoc,true);
1677
1678 fireResourceWritten( new DatastoreEvent(this,
1680 DatastoreEvent.RESOURCE_WRITTEN,
1681 dbDoc,
1682 dbDoc.getLRPersistenceId()
1683 )
1684 );
1685
1686 if (newlyAddedDocs.contains(dbDoc.getLRPersistenceId())) {
1690 addDocumentToCorpus( (Long) dbDoc.getLRPersistenceId(),
1692 (Long) corp.getLRPersistenceId());
1693 }
1694 else {
1695 }
1697 }
1698 catch(SecurityException se) {
1699 gate.util.Err.prln("document cannot be synced: ["+se.getMessage()+"]");
1700 }
1701 }
1702 }
1703 }
1704
1705
1706
1707 protected void syncDocument(Document doc)
1708 throws PersistenceException, SecurityException {
1709
1710 Assert.assertTrue(doc instanceof DatabaseDocumentImpl);
1711 Assert.assertTrue(doc.getLRPersistenceId() instanceof Long);
1712
1713 Long lrID = (Long)doc.getLRPersistenceId();
1714 EventAwareLanguageResource dbDoc = (EventAwareLanguageResource)doc;
1715 if (true == dbDoc.isResourceChanged(EventAwareLanguageResource.RES_NAME)) {
1718 _syncLR(doc);
1719 }
1720
1721 if (true == dbDoc.isResourceChanged(EventAwareLanguageResource.DOC_MAIN)) {
1723 _syncDocumentHeader(doc);
1724 }
1725
1726 if (true == dbDoc.isResourceChanged(EventAwareLanguageResource.DOC_CONTENT)) {
1728 _syncDocumentContent(doc);
1729 }
1730
1731 if (true == dbDoc.isResourceChanged(EventAwareLanguageResource.RES_FEATURES)) {
1733 _syncFeatures(doc);
1734 }
1735
1736 Collection removedSets = ((EventAwareDocument)dbDoc).getRemovedAnnotationSets();
1738 Collection addedSets = ((EventAwareDocument)dbDoc).getAddedAnnotationSets();
1739 if (false == removedSets.isEmpty() || false == addedSets.isEmpty()) {
1740 _syncAnnotationSets(doc,removedSets,addedSets);
1741 }
1742
1743 _syncAnnotations(doc);
1745 }
1746
1747
1748
1752 protected abstract void _syncLR(LanguageResource lr)
1753 throws PersistenceException,SecurityException;
1754
1755
1756 protected abstract void _syncDocumentHeader(Document doc)
1757 throws PersistenceException;
1758
1759
1760 protected abstract void _syncDocumentContent(Document doc)
1761 throws PersistenceException;
1762
1763
1764 protected abstract void _syncFeatures(LanguageResource lr)
1765 throws PersistenceException;
1766
1767
1768 protected void _syncAnnotationSets(Document doc,Collection removedSets,Collection addedSets)
1769 throws PersistenceException {
1770
1771 Assert.assertNotNull(doc);
1773 Assert.assertTrue(doc instanceof DatabaseDocumentImpl);
1774 Assert.assertNotNull(doc.getLRPersistenceId());
1775 Assert.assertEquals(((DatabaseDataStore)doc.getDataStore()).getDatabaseID(),
1776 this.getDatabaseID());
1777 Assert.assertNotNull(removedSets);
1778 Assert.assertNotNull(addedSets);
1779
1780 Long lrID = (Long)doc.getLRPersistenceId();
1781
1782 PreparedStatement stmt = null;
1784
1785 try {
1786
1787 if (this.dbType == DBHelper.ORACLE_DB) {
1788 stmt = this.jdbcConn.prepareCall("{ call "+this.dbSchema+"persist.delete_annotation_set(?,?) }");
1789 }
1790 else if (this.dbType == DBHelper.POSTGRES_DB) {
1791 stmt = this.jdbcConn.prepareStatement("select persist_delete_annotation_set(?,?)");
1792 }
1793 else {
1794 Assert.fail();
1795 }
1796
1797 Iterator it = removedSets.iterator();
1798 while (it.hasNext()) {
1799 String setName = (String)it.next();
1800 stmt.setLong(1,lrID.longValue());
1801 stmt.setString(2,setName);
1802 stmt.execute();
1803 }
1804 }
1805 catch(SQLException sqle) {
1806 throw new PersistenceException("can't remove annotation set from DB: ["+ sqle.getMessage()+"]");
1807 }
1808 finally {
1809 DBHelper.cleanup(stmt);
1810 }
1811
1812 Iterator it = addedSets.iterator();
1814 while (it.hasNext()) {
1815 String setName = (String)it.next();
1816 AnnotationSet aset = doc.getAnnotations(setName);
1817
1818 Assert.assertNotNull(aset);
1819 Assert.assertTrue(aset instanceof DatabaseAnnotationSetImpl);
1820
1821 createAnnotationSet(lrID,aset);
1822 }
1823 }
1824
1825
1826
1827 protected void _syncAnnotations(Document doc)
1828 throws PersistenceException {
1829
1830 Assert.assertNotNull(doc);
1832 Assert.assertTrue(doc instanceof DatabaseDocumentImpl);
1833 Assert.assertNotNull(doc.getLRPersistenceId());
1834 Assert.assertEquals(((DatabaseDataStore)doc.getDataStore()).getDatabaseID(),
1835 this.getDatabaseID());
1836
1837
1838 EventAwareDocument ead = (EventAwareDocument)doc;
1839 Collection loadedSets = ead.getLoadedAnnotationSets();
1842
1843 Iterator it = loadedSets.iterator();
1844 while (it.hasNext()) {
1845 AnnotationSet as = (AnnotationSet)it.next();
1846 if (ead.getAddedAnnotationSets().contains(as.getName()) ||
1849 ead.getRemovedAnnotationSets().contains(as.getName())) {
1850 continue;
1852 }
1853
1854 EventAwareAnnotationSet eas = (EventAwareAnnotationSet)as;
1855 Assert.assertNotNull(as);
1856
1857 Collection anns = null;
1858 anns = eas.getAddedAnnotations();
1859 Assert.assertNotNull(anns);
1860 if (anns.size()>0) {
1861 _syncAddedAnnotations(doc,as,anns);
1862 }
1863
1864 anns = eas.getRemovedAnnotations();
1865 Assert.assertNotNull(anns);
1866 if (anns.size()>0) {
1867 _syncRemovedAnnotations(doc,as,anns);
1868 }
1869
1870 anns = eas.getChangedAnnotations();
1871 Assert.assertNotNull(anns);
1872 if (anns.size()>0) {
1873 _syncChangedAnnotations(doc,as,anns);
1874 }
1875 }
1876 }
1877
1878
1879 protected void _syncAddedAnnotations(Document doc, AnnotationSet as, Collection changes)
1880 throws PersistenceException {
1881
1882 Assert.assertNotNull(doc);
1884 Assert.assertNotNull(as);
1885 Assert.assertNotNull(changes);
1886 Assert.assertTrue(doc instanceof DatabaseDocumentImpl);
1887 Assert.assertTrue(as instanceof DatabaseAnnotationSetImpl);
1888 Assert.assertTrue(changes.size() > 0);
1889
1890
1891 PreparedStatement pstmt = null;
1892 ResultSet rs = null;
1893 CallableStatement cstmt = null;
1894 Long lrID = (Long)doc.getLRPersistenceId();
1895 Long asetID = null;
1896
1897 try {
1898 String sql = " select as_id " +
1900 " from "+this.dbSchema+"v_annotation_set " +
1901 " where lr_id = ? ";
1902 String clause = null;
1904 String name = as.getName();
1905 if (null != name) {
1906 clause = " and as_name = ? ";
1907 }
1908 else {
1909 clause = " and as_name is null ";
1910 }
1911 sql = sql + clause;
1912
1913 pstmt = this.jdbcConn.prepareStatement(sql);
1914 pstmt.setLong(1,lrID.longValue());
1915 if (null != name) {
1916 pstmt.setString(2,name);
1917 }
1918 pstmt.execute();
1919 rs = pstmt.getResultSet();
1920
1921 if (rs.next()) {
1922 asetID = new Long(rs.getLong("as_id"));
1923 }
1924 else {
1925 throw new PersistenceException("cannot find annotation set with" +
1926 " name=["+name+"] , LRID=["+lrID+"] in database");
1927 }
1928
1929 DBHelper.cleanup(rs);
1931 DBHelper.cleanup(pstmt);
1932
1933
1935 if (this.dbType == DBHelper.ORACLE_DB) {
1937
1938 cstmt = this.jdbcConn.prepareCall(
1939 "{ call "+Gate.DB_OWNER+".persist.create_annotation(?,?,?,?,?,?,?,?,?) }");
1940
1941 Long annGlobalID = null;
1942 Iterator it = changes.iterator();
1943
1944 while (it.hasNext()) {
1945
1946 Annotation ann = (Annotation)it.next();
1948
1949 Node start = (Node)ann.getStartNode();
1950 Node end = (Node)ann.getEndNode();
1951 String type = ann.getType();
1952
1953 cstmt.setLong(1,lrID.longValue());
1954 cstmt.setLong(2,ann.getId().longValue());
1955 cstmt.setLong(3,asetID.longValue());
1956 cstmt.setLong(4,start.getId().longValue());
1957 cstmt.setLong(5,start.getOffset().longValue());
1958 cstmt.setLong(6,end.getId().longValue());
1959 cstmt.setLong(7,end.getOffset().longValue());
1960 cstmt.setString(8,type);
1961 cstmt.registerOutParameter(9,java.sql.Types.BIGINT);
1962
1963 cstmt.execute();
1964 annGlobalID = new Long(cstmt.getLong(9));
1965
1966 FeatureMap features = ann.getFeatures();
1968 Assert.assertNotNull(features);
1969
1970 if (this.dbType == DBHelper.ORACLE_DB) {
1971 createFeaturesBulk(annGlobalID,DBHelper.FEATURE_OWNER_ANNOTATION,features);
1972 }
1973 else if (this.dbType == DBHelper.POSTGRES_DB) {
1974 createFeatures(annGlobalID,DBHelper.FEATURE_OWNER_ANNOTATION,features);
1975 }
1976 else {
1977 Assert.fail();
1978 }
1979 }
1980 }
1981 else if (this.dbType == DBHelper.POSTGRES_DB) {
1982
1983 sql = "select persist_create_annotation(?,?,?,?,?,?,?,?)";
1984 pstmt = this.jdbcConn.prepareStatement(sql);
1985
1986 Long annGlobalID = null;
1987 Iterator it = changes.iterator();
1988
1989 while (it.hasNext()) {
1990
1991 Annotation ann = (Annotation)it.next();
1993
1994 Node start = (Node)ann.getStartNode();
1995 Node end = (Node)ann.getEndNode();
1996 String type = ann.getType();
1997
1998 pstmt.setLong(1,lrID.longValue());
1999 pstmt.setLong(2,ann.getId().longValue());
2000 pstmt.setLong(3,asetID.longValue());
2001 pstmt.setLong(4,start.getId().longValue());
2002 pstmt.setLong(5,start.getOffset().longValue());
2003 pstmt.setLong(6,end.getId().longValue());
2004 pstmt.setLong(7,end.getOffset().longValue());
2005 pstmt.setString(8,type);
2006 pstmt.execute();
2007
2008 rs = pstmt.getResultSet();
2009
2010 if (false == rs.next()) {
2011 throw new PersistenceException("empty result set");
2012 }
2013 annGlobalID = new Long(rs.getLong(1));
2014
2015 FeatureMap features = ann.getFeatures();
2017 Assert.assertNotNull(features);
2018 createFeatures(annGlobalID,DBHelper.FEATURE_OWNER_ANNOTATION,features);
2019 }
2020 }
2021
2022 else {
2023 throw new IllegalArgumentException();
2024 }
2025
2026 }
2027 catch(SQLException sqle) {
2028 throw new PersistenceException("can't add annotations in DB : ["+
2029 sqle.getMessage()+"]");
2030 }
2031 finally {
2032 DBHelper.cleanup(rs);
2033 DBHelper.cleanup(pstmt);
2034 DBHelper.cleanup(cstmt);
2035 }
2036 }
2037
2038
2039 protected void _syncRemovedAnnotations(Document doc,AnnotationSet as, Collection changes)
2040 throws PersistenceException {
2041
2042 Assert.assertNotNull(doc);
2044 Assert.assertNotNull(as);
2045 Assert.assertNotNull(changes);
2046 Assert.assertTrue(doc instanceof DatabaseDocumentImpl);
2047 Assert.assertTrue(as instanceof DatabaseAnnotationSetImpl);
2048 Assert.assertTrue(changes.size() > 0);
2049
2050
2051 PreparedStatement pstmt = null;
2052 ResultSet rs = null;
2053 Long lrID = (Long)doc.getLRPersistenceId();
2054 Long docID = null;
2055 Long asetID = null;
2056
2057 try {
2058 String sql = " select as_id, " +
2060 " as_doc_id " +
2061 " from "+this.dbSchema+"v_annotation_set " +
2062 " where lr_id = ? ";
2063 String clause = null;
2065 String name = as.getName();
2066 if (null != name) {
2067 clause = " and as_name = ? ";
2068 }
2069 else {
2070 clause = " and as_name is null ";
2071 }
2072 sql = sql + clause;
2073
2074 pstmt = this.jdbcConn.prepareStatement(sql);
2075 pstmt.setLong(1,lrID.longValue());
2076 if (null != name) {
2077 pstmt.setString(2,name);
2078 }
2079 pstmt.execute();
2080 rs = pstmt.getResultSet();
2081
2082 if (rs.next()) {
2083 asetID = new Long(rs.getLong("as_id"));
2084 docID = new Long(rs.getLong("as_doc_id"));
2085 }
2086 else {
2087 throw new PersistenceException("cannot find annotation set with" +
2088 " name=["+name+"] , LRID=["+lrID+"] in database");
2089 }
2090
2091
2093 DBHelper.cleanup(rs);
2095 DBHelper.cleanup(pstmt);
2096
2097
2099 if (this.dbType == DBHelper.ORACLE_DB) {
2100 pstmt = this.jdbcConn.prepareCall("{ call "+this.dbSchema+"persist.delete_annotation(?,?) }");
2101 }
2102 else if (this.dbType == DBHelper.POSTGRES_DB) {
2103 pstmt = this.jdbcConn.prepareStatement("select persist_delete_annotation(?,?)");
2104 }
2105 else {
2106 throw new IllegalArgumentException();
2107 }
2108
2109 Iterator it = changes.iterator();
2110
2111 while (it.hasNext()) {
2112
2113 Annotation ann = (Annotation)it.next();
2115
2116 pstmt.setLong(1,docID.longValue()); pstmt.setLong(2,ann.getId().longValue());
2118 pstmt.execute();
2119 }
2120 }
2121 catch(SQLException sqle) {
2122 throw new PersistenceException("can't delete annotations in DB : ["+
2123 sqle.getMessage()+"]");
2124 }
2125 finally {
2126 DBHelper.cleanup(rs);
2127 DBHelper.cleanup(pstmt);
2128 }
2129 }
2130
2131
2132
2133 protected void _syncChangedAnnotations(Document doc,AnnotationSet as, Collection changes)
2134 throws PersistenceException {
2135
2136
2139 _syncRemovedAnnotations(doc,as,changes);
2141 _syncAddedAnnotations(doc,as,changes);
2143 }
2144
2145
2150 public LanguageResource getLr(String lrClassName, Object lrPersistenceId)
2151 throws PersistenceException,SecurityException {
2152
2153 LanguageResource result = null;
2154
2155 Assert.assertNotNull(lrPersistenceId);
2157
2158 if (null == this.session) {
2160 throw new SecurityException("session not set");
2161 }
2162
2163 if (false == this.ac.isValidSession(this.session)) {
2164 throw new SecurityException("invalid session supplied");
2165 }
2166
2167 if (false == canReadLR(lrPersistenceId)) {
2169 throw new SecurityException("insufficient privileges");
2170 }
2171
2172 if (lrClassName.equals(DBHelper.DOCUMENT_CLASS)) {
2174 result = readDocument(lrPersistenceId);
2175 Assert.assertTrue(result instanceof DatabaseDocumentImpl);
2176 }
2177 else if (lrClassName.equals(DBHelper.CORPUS_CLASS)) {
2178 result = readCorpus(lrPersistenceId);
2179 Assert.assertTrue(result instanceof DatabaseCorpusImpl);
2180 }
2181 else {
2182 throw new IllegalArgumentException("resource class should be either Document or Corpus");
2183 }
2184
2185 Assert.assertNotNull(result.getDataStore());
2187 Assert.assertTrue(result.getDataStore() instanceof DatabaseDataStore);
2188 Assert.assertNotNull(result.getLRPersistenceId());
2189
2190 addDatastoreListener((DatastoreListener)result);
2192
2193 this.dependentResources.add(result);
2196
2197 return result;
2199 }
2200
2201
2202 private DatabaseDocumentImpl readDocument(Object lrPersistenceId)
2203 throws PersistenceException {
2204
2205 Assert.assertNotNull(lrPersistenceId);
2207
2208 if (false == lrPersistenceId instanceof Long) {
2209 throw new IllegalArgumentException();
2210 }
2211
2212 DatabaseDocumentImpl result = new DatabaseDocumentImpl(this.jdbcConn);
2214
2215 PreparedStatement pstmt = null;
2216 ResultSet rs = null;
2217
2218 try {
2220 String sql = " select lr_name, " +
2221 " lrtp_type, " +
2222 " lr_id, " +
2223 " lr_parent_id, " +
2224 " doc_id, " +
2225 " doc_url, " +
2226 " doc_start, " +
2227 " doc_end, " +
2228 " doc_is_markup_aware " +
2229 " from "+this.dbSchema+"v_document " +
2230 " where lr_id = ? ";
2231
2232 pstmt = this.jdbcConn.prepareStatement(sql);
2233 pstmt.setLong(1,((Long)lrPersistenceId).longValue());
2234 pstmt.execute();
2235 rs = pstmt.getResultSet();
2236
2237 if (false == rs.next()) {
2238 throw new PersistenceException("Invalid LR ID supplied - no data found");
2240 }
2241
2242
2244 String lrName = rs.getString("lr_name");
2246 Assert.assertNotNull(lrName);
2247 result.setName(lrName);
2248
2249 Long parentID = null;
2251 long parent_id = rs.getLong("lr_parent_id");
2252 if (false == rs.wasNull()) {
2253 parentID = new Long(parent_id);
2254
2255 LanguageResource parentLR = this.getLr(DBHelper.DOCUMENT_CLASS,parentID);
2257 Assert.assertNotNull(parentLR);
2258 Assert.assertTrue(parentLR instanceof DatabaseDocumentImpl);
2259
2260 result.setParent(parentLR);
2261 }
2262
2263
2264 if (this.dbType == DBHelper.ORACLE_DB) {
2266 long markup = rs.getLong("doc_is_markup_aware");
2267 Assert.assertTrue(markup == DBHelper.FALSE || markup == DBHelper.TRUE);
2268 if (markup == DBHelper.FALSE) {
2269 result.setMarkupAware(Boolean.FALSE);
2270 }
2271 else {
2272 result.setMarkupAware(Boolean.TRUE);
2273
2274 }
2275 }
2276 else if (this.dbType == DBHelper.POSTGRES_DB) {
2277 boolean markup = rs.getBoolean("doc_is_markup_aware");
2278 result.setMarkupAware(new Boolean(markup));
2279 }
2280 else {
2281 throw new IllegalArgumentException();
2282 }
2283
2284
2285 result.setDataStore(this);
2287
2288 Long persistID = new Long(rs.getLong("lr_id"));
2290 result.setLRPersistenceId(persistID);
2291
2292 String url = rs.getString("doc_url");
2294 if(url != null && url.length() > 0) result.setSourceUrl(new URL(url));
2295
2296 Long start = null;
2298 long longVal = rs.getLong("doc_start");
2299 if (false == rs.wasNull()) {
2302 start = new Long(longVal);
2303 }
2304 result.setSourceUrlStartOffset(start);
2305
2307 Long end = null;
2309 longVal = rs.getLong("doc_end");
2310 if (false == rs.wasNull()) {
2313 end = new Long(longVal);
2314 }
2315 result.setSourceUrlEndOffset(end);
2316
2318 FeatureMap features = readFeatures((Long)lrPersistenceId,DBHelper.FEATURE_OWNER_DOCUMENT);
2320 result.setFeatures(features);
2321
2323 long doc_id = rs.getLong("doc_id");
2325
2326 DBHelper.cleanup(rs);
2328 DBHelper.cleanup(pstmt);
2329
2330 sql = " select max(ann_local_id),'ann_id'" +
2331 " from "+this.dbSchema+"t_annotation " +
2332 " where ann_doc_id = ?" +
2333 " union " +
2334 " select max(node_local_id),'node_id' " +
2335 " from "+this.dbSchema+"t_node " +
2336 " where node_doc_id = ?";
2337
2338 pstmt = this.jdbcConn.prepareStatement(sql);
2339 pstmt.setLong(1,doc_id);
2340 pstmt.setLong(2,doc_id);
2341 pstmt.execute();
2342 rs = pstmt.getResultSet();
2343
2344 int maxAnnID = 0 , maxNodeID = 0;
2345 if (false == rs.next()) {
2347 throw new PersistenceException("Invalid LR ID supplied - no data found");
2349 }
2350 if (rs.getString(2).equals("ann_id"))
2351 maxAnnID = rs.getInt(1);
2352 else
2353 maxNodeID = rs.getInt(1);
2354
2355 if (false == rs.next()) {
2356 throw new PersistenceException("Invalid LR ID supplied - no data found");
2358 }
2359 if (rs.getString(2).equals("node_id"))
2360 maxNodeID = rs.getInt(1);
2361 else
2362 maxAnnID = rs.getInt(1);
2363
2364 result.setNextNodeId(maxNodeID+1);
2365 result.setNextAnnotationId(maxAnnID+1);
2367
2369
2370 }
2380 catch(SQLException sqle) {
2381 throw new PersistenceException("can't read LR from DB: ["+ sqle.getMessage()+"]");
2382 }
2383 catch(Exception e) {
2384 throw new PersistenceException(e);
2385 }
2386 finally {
2387 DBHelper.cleanup(rs);
2388 DBHelper.cleanup(pstmt);
2389 }
2390
2391 return result;
2392 }
2393
2394
2395
2398 private DatabaseCorpusImpl readCorpus(Object lrPersistenceId)
2399 throws PersistenceException {
2400
2401 Assert.assertNotNull(lrPersistenceId);
2403
2404 if (false == lrPersistenceId instanceof Long) {
2405 throw new IllegalArgumentException();
2406 }
2407
2408 PreparedStatement pstmt = null;
2410 ResultSet rs = null;
2411 DatabaseCorpusImpl result = null;
2412
2413 try {
2414 String sql = " select lr_name " +
2415 " from "+this.dbSchema+"t_lang_resource " +
2416 " where lr_id = ? ";
2417 pstmt = this.jdbcConn.prepareStatement(sql);
2418 pstmt.setLong(1,((Long)lrPersistenceId).longValue());
2419 pstmt.execute();
2420 rs = pstmt.getResultSet();
2421
2422 if (false == rs.next()) {
2423 throw new PersistenceException("Invalid LR ID supplied - no data found");
2425 }
2426
2427
2429 String lrName = rs.getString("lr_name");
2431 Assert.assertNotNull(lrName);
2432
2433 FeatureMap features = readFeatures((Long)lrPersistenceId,DBHelper.FEATURE_OWNER_CORPUS);
2435
2436 DBHelper.cleanup(rs);
2438 DBHelper.cleanup(pstmt);
2439
2440 sql = " select lr_id ," +
2441 " lr_name " +
2442 " from "+this.dbSchema+"t_document doc, " +
2443 " "+this.dbSchema+"t_lang_resource lr, " +
2444 " "+this.dbSchema+"t_corpus_document corpdoc, " +
2445 " "+this.dbSchema+"t_corpus corp " +
2446 " where lr.lr_id = doc.doc_lr_id " +
2447 " and doc.doc_id = corpdoc.cd_doc_id " +
2448 " and corpdoc.cd_corp_id = corp.corp_id " +
2449 " and corp_lr_id = ? ";
2450 pstmt = this.jdbcConn.prepareStatement(sql);
2451 pstmt.setLong(1,((Long)lrPersistenceId).longValue());
2452 pstmt.execute();
2453 rs = pstmt.getResultSet();
2454
2455 Vector documentData = new Vector();
2456 while (rs.next()) {
2457 Long docLRID = new Long(rs.getLong("lr_id"));
2458 String docName = rs.getString("lr_name");
2459 documentData.add(new DocumentData(docName, docLRID));
2460 }
2461 DBHelper.cleanup(rs);
2462 DBHelper.cleanup(pstmt);
2463
2464 result = new DatabaseCorpusImpl(lrName,
2465 this,
2466 (Long)lrPersistenceId,
2467 features,
2468 documentData);
2469 }
2470 catch(SQLException sqle) {
2471 throw new PersistenceException("can't read LR from DB: ["+ sqle.getMessage()+"]");
2472 }
2473 catch(Exception e) {
2474 throw new PersistenceException(e);
2475 }
2476 finally {
2477 DBHelper.cleanup(rs);
2478 DBHelper.cleanup(pstmt);
2479 }
2480
2481 return result;
2482 }
2483
2484
2488 protected abstract FeatureMap readFeatures(Long entityID, int entityType)
2489 throws PersistenceException;
2490
2491
2495 protected abstract void deleteDocument(Long lrId)
2496 throws PersistenceException;
2497
2498
2502 protected abstract void deleteCorpus(Long lrId)
2503 throws PersistenceException;
2504
2505
2508 protected void unloadLR(Long lrID)
2509 throws GateException{
2510
2511 Assert.assertNotNull(lrID);
2513
2514 List resources = Gate.getCreoleRegister().getAllInstances("gate.LanguageResource");
2516
2517 Iterator it = resources.iterator();
2518 while (it.hasNext()) {
2519 LanguageResource lr = (LanguageResource)it.next();
2520 if (lrID.equals(lr.getLRPersistenceId()) &&
2521 this.equals(lr.getDataStore())) {
2522 Factory.deleteResource(lr);
2524 break;
2525 }
2526 }
2527 }
2528
2529
2530 protected abstract void _syncRemovedDocumentsFromCorpus(List docLRIDs, Long corpLRID)
2531 throws PersistenceException;
2532
2533
2538 protected abstract void addDocumentToCorpus(Long docID,Long corpID)
2539 throws PersistenceException,SecurityException;
2540
2541
2542}
2543