Project

General

Profile

1
/**
2
 *   '$Author: tao $'
3
 *     '$Date: 2003-02-04 15:55:01 -0800 (Tue, 04 Feb 2003) $'
4
 * '$Revision: 1388 $'
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20
 
21
package edu.ucsb.nceas.metacat;
22

    
23
import java.sql.*;
24
import java.util.*;
25
import java.net.*;
26

    
27
public class RelationHandler //implements Runnable
28
{
29
  private Thread btThread = null;
30
  private DBConnection connection = null;
31
  private String docid = null;
32
  MetaCatUtil util = new MetaCatUtil();
33
  // The hashtable's key is String vector, subject parentid , relation ship
34
  // prarent id and object parent id. Element is a vetor too. subject, relation
35
  // and object
36
  private Hashtable parentNodeIdList = new Hashtable();
37
  private static final int SUBJECTINDEX = 0;
38
  private static final int RELATIONINDEX = 1;
39
  private static final int OBJECTINDEX = 2;
40
  
41
  /** 
42
   * Constructor for this class.  finds all of the relations to a single xml
43
   * document and writes them to the database.  This includes transitive
44
   * relations.
45
   * @param docid the ID of the XML document to index.
46
   */
47
  public RelationHandler(String docid, DBConnection conn)
48
              throws McdbException, SQLException, AccessionNumberException
49
  {
50
    this.connection = conn;
51
    this.docid = docid;
52
    putRelations();
53
  }
54
  
55
  /**
56
   * insert the relations specified in the triples into xml_relation table
57
   */ 
58
  private void putRelations() 
59
              throws McdbException, SQLException, AccessionNumberException
60
  {
61
    String packagetype = null;
62
    String subject = null;
63
    String subjectParentId = null;
64
    String subDoctype = null;
65
    String relationship = null;
66
    String relationshipParentId = null;
67
    String object = null;
68
    String objectParentId = null;
69
    String objDoctype = null;
70
    PreparedStatement pstmt = null; // to get the relations from xml_nodes
71
    PreparedStatement tstmt = null; // to insert each relation into xml_relation
72
   
73
    MetaCatUtil.debugMessage("Running relation handler!", 40);
74
    
75

    
76
    /* 
77
     * PSEUDO-CODE ALGORITHM:
78
     * deletes all of the relations with a docid of @docid.
79
     * for each new relation r in xml_nodes
80
     *   put r into xml_relation
81
     */
82

    
83
    //DocumentImpl xmldoc = new DocumentImpl(conn,docid,false);
84
    packagetype = (new DocumentImpl(docid,false)).getDoctype();
85

    
86
    // first delete the relations for this package document if any
87
    deleteRelations(docid);
88

    
89
    // to put the new relations get them out of xml_nodes
90
    pstmt = connection.prepareStatement
91
                                (QuerySpecification.printPackageSQL(docid));
92
   
93
    //increase usage cont
94
    connection.increaseUsageCount(1);
95
    pstmt.execute();
96
    ResultSet rs = pstmt.getResultSet();
97
    boolean hasmorerows = rs.next();
98
   
99
    while(hasmorerows) {
100
      Vector parentId = new Vector();
101
      Vector sbjReObj = new Vector();
102
      boolean mergeSubject = false;
103
      boolean mergeRelation = false;
104
      boolean mergerObject = false;
105
      subject = rs.getString(1);
106
      subjectParentId = rs.getString(2);
107
      relationship = rs.getString(3);
108
      relationshipParentId = rs.getString(4);
109
      object = rs.getString(5);
110
      objectParentId = rs.getString(6);
111
      
112
     
113
      MetaCatUtil.debugMessage("oringal subjectparentid: " + 
114
                                                subjectParentId, 40);
115
      MetaCatUtil.debugMessage("oringinal subject: "+subject);
116
      MetaCatUtil.debugMessage("oringal relation parentid: "+ 
117
                                relationshipParentId, 40);
118
      MetaCatUtil.debugMessage("oringinal relationship: "+relationship, 40);
119
      MetaCatUtil.debugMessage("oringal objectparentid: "+ 
120
                                objectParentId, 40);
121
      MetaCatUtil.debugMessage("oringinal object: "+object, 40);
122
      
123
      if ( hasSameId(subjectParentId) )
124
      {
125
        // subject was splited and need to conbined
126
        String prefixSubject = getValueFromParentIdList(subjectParentId);
127
        if (prefixSubject !=null && !prefixSubject.equals(subject))
128
        {
129
          MetaCatUtil.debugMessage("merger subject: "+prefixSubject + 
130
                                    subject, 40);
131
          subject = prefixSubject + subject;
132
          mergeSubject = true;
133
        }
134
      }
135
      
136
      if ( hasSameId(relationshipParentId) )
137
      {
138
        // relationship need to be combined
139
        String relationPrefix = getValueFromParentIdList(relationshipParentId);
140
        if (relationPrefix != null && !relationPrefix.equals(relationship))
141
        {
142
          MetaCatUtil.debugMessage("merge relation: "+ relationPrefix + 
143
                                    relationship);
144
          relationship = relationPrefix + relationship;
145
          mergeRelation = true;
146
        }
147
      }
148
      
149
      if ( hasSameId(objectParentId) )
150
      {
151
        String objectPrefix = getValueFromParentIdList(objectParentId);
152
        if (objectPrefix != null && !objectPrefix.equals(object))
153
        {
154
          MetaCatUtil.debugMessage("merge object: "+ objectPrefix + object);
155
          object = objectPrefix + object;
156
          mergerObject = true;
157
        }
158
      }
159
      
160
      if (mergeSubject)
161
      {
162
        removeEntryFromParentIdList(subjectParentId);
163
      }
164
      if (mergeRelation)
165
      {
166
        removeEntryFromParentIdList(relationshipParentId);
167
      }
168
      if (mergerObject)
169
      {
170
        removeEntryFromParentIdList(objectParentId);
171
      }
172
      // Store the parentids into parentId vector
173
      parentId.addElement(subjectParentId);
174
      parentId.addElement(relationshipParentId);
175
      parentId.addElement(objectParentId);
176
      // Store the value into sbjRelObj vector
177
      sbjReObj.addElement(subject);
178
      sbjReObj.addElement(relationship);
179
      sbjReObj.addElement(object);
180
      // Store the parent id and value into hashtable
181
      parentNodeIdList.put(parentId, sbjReObj);
182
      hasmorerows = rs.next();
183
    }
184
    Enumeration en = parentNodeIdList.elements();
185
    if (en.hasMoreElements()) {
186
      tstmt = connection.prepareStatement("INSERT INTO xml_relation (" +
187
                                    "docid,packagetype,subject,subdoctype," +
188
                                    "relationship, object, objdoctype) " + 
189
                                    "VALUES (?, ?, ?, ?, ?, ?, ?)");
190
      //increase usage count
191
      connection.increaseUsageCount(1);
192
    }
193
 
194
    while (en.hasMoreElements())
195
    {
196
      Vector values = (Vector)en.nextElement();
197
      // cut out the revision number for subject and object
198
      subject = (new DocumentIdentifier((String)values.elementAt(SUBJECTINDEX)))
199
                                                        .getIdentifier();
200
      relationship = (String)values.elementAt(RELATIONINDEX);
201
      object = (new DocumentIdentifier((String)values.elementAt(OBJECTINDEX)))
202
                                                      .getIdentifier();
203
     
204
      //subDoctype and objDoctype are N/A
205
      subDoctype = null;
206
      objDoctype = null;
207
      //put the new relation into xml_relation
208
      tstmt.setString(1, docid);
209
      tstmt.setString(2, packagetype);
210
      tstmt.setString(3, subject);
211
      tstmt.setString(4, subDoctype);
212
      tstmt.setString(5, relationship);
213
      tstmt.setString(6, object);
214
      tstmt.setString(7, objDoctype);
215
      tstmt.execute(); 
216
    }
217
    if ( tstmt != null ) {
218
      tstmt.close();
219
    }
220
    pstmt.close();
221
    connection.commit();
222
  }
223
  
224
  /*
225
   * A method to check if a parentid is already in the paretnIdlist
226
   */
227
   public boolean hasSameId(String parentId)
228
   {
229
     boolean hasSame = false;
230
     if (parentId == null || parentId.equals(""))
231
     {
232
       return hasSame;
233
     }
234
     Enumeration en = parentNodeIdList.keys();
235
     // go throught hashtable
236
     while (en.hasMoreElements())
237
     {
238
       Vector keys = (Vector)en.nextElement();
239
       for (int i=0; i<keys.size(); i++)
240
       {
241
         String obj = (String)keys.elementAt(i);
242
         if ( obj != null && obj.equals(parentId) )
243
         {
244
           hasSame = true;
245
         }//if
246
       }//for
247
     }//while
248
     return hasSame;
249
   }
250
  
251
   /*
252
    * Get a value from parentidlist for a given paretnIdlist
253
    */
254
   public String getValueFromParentIdList(String parentId)
255
   {
256
     String value = null;
257
     int    index = -1; // index in vector keys which has same parentid to 
258
                        // given id
259
     // Check the parameter
260
     if ( parentId == null || parentId.equals("") )
261
     {
262
       return value;
263
     }
264
      
265
     Enumeration en = parentNodeIdList.keys();
266
     // go throught hashtable
267
     while (en.hasMoreElements())
268
     {
269
       Vector keys = (Vector)en.nextElement();
270
       for (int i=0; i<keys.size(); i++)
271
       {
272
         String obj = (String)keys.elementAt(i);
273
         if ( obj != null && obj.equals(parentId) )
274
         {
275
           index = i;
276
         }//if
277
         if (index != -1)
278
         {
279
           // get the element vector to the key
280
           Vector element = (Vector)parentNodeIdList.get(keys);
281
           // get string
282
           value = (String)element.elementAt(index);
283
         }
284
         // reset index
285
         index = -1;
286
       }//for
287
     }//while
288
     MetaCatUtil.debugMessage("The value for given parent id " + parentId +
289
                              "is " + value, 40);
290
     return value;
291
   }
292
   
293
   /*
294
    * A method to remove a entry in hashtable for given parentid
295
    */
296
   private void removeEntryFromParentIdList(String parentId)
297
   {
298
     if (parentId==null || parentId.equals(""))
299
     {
300
       return;
301
     }
302
     
303
     Enumeration en = parentNodeIdList.keys();
304
     // go throught hashtable
305
     while (en.hasMoreElements())
306
     {
307
       Vector keys = (Vector)en.nextElement();
308
       for (int i=0; i<keys.size(); i++)
309
       {
310
         String obj = (String)keys.elementAt(i);
311
         if ( obj != null && obj.equals(parentId) )
312
         {
313
            parentNodeIdList.remove(keys);
314
         }//if
315
       
316
       }//for
317
     }//while
318
   } 
319
  /**
320
   * Deletes all of the relations with a docid of 'docid'.
321
   * @param docid the docid of the package which relations to delete.
322
   */
323
  public void deleteRelations(String docid) throws SQLException
324
  {
325
    try {
326
      PreparedStatement pstmt = connection.prepareStatement(
327
                                "DELETE FROM xml_relation " +
328
                                "WHERE docid = '" + docid + "'");
329
      //increase usage count
330
      connection.increaseUsageCount(1);
331
      pstmt.execute();
332
      pstmt.close();
333
    } catch(SQLException e) {
334
      MetaCatUtil.debugMessage("error in RelationHandler.deleteRelations(): " + 
335
                          e.getMessage());
336
      System.out.println("error in RelationHandler.deleteRelations(): " + 
337
                          e.getMessage());
338
      throw e;
339
    }
340
  }
341

    
342
  /**
343
   * Get the access file id for a package
344
   * @param docid the document identifier of the package
345
   * @return the document identifier of the access file for that package
346
   */
347
  public String getAccessFileID(String docid) throws SQLException
348
  {
349
    String aclid = null;
350
    PreparedStatement pstmt = null;
351
    DBConnection dbConn = null;
352
    int serialNumber = -1;
353
    
354
    StringBuffer sql = new StringBuffer();
355
    sql.append("SELECT docid FROM xml_documents WHERE docid in (SELECT subject ");
356
    sql.append("FROM xml_relation WHERE docid='").append(docid);
357
    sql.append("' AND (");
358
    Vector accessdoctypes = MetaCatUtil.getOptionList(
359
                              MetaCatUtil.getOption("accessdoctype"));
360
    for(int i=0; i<accessdoctypes.size(); i++)
361
    {
362
      String atype = (String)accessdoctypes.elementAt(i);
363
      sql.append("doctype='").append(atype).append("'");
364
      if(i < accessdoctypes.size()-1)
365
      {
366
        sql.append(" OR ");
367
      }
368
    }
369
    sql.append("))");
370
    //System.out.println("new sql script: " + sql.toString());
371
    
372
    /*
373
    PreparedStatement pstmt = 
374
      conn.prepareStatement("SELECT docid FROM xml_documents " +
375
                            "WHERE docid in " +
376
                            "(SELECT subject FROM xml_relation " +
377
                            "WHERE docid = ?) " +
378
                            "AND doctype = ?");
379
    pstmt.setString(1, docid);
380
    pstmt.setString(2, MetaCatUtil.getOption("accessdoctype"));
381
    */
382
    try
383
    {
384
      dbConn=DBConnectionPool.
385
                  getDBConnection("RelationHandler.getAccessFileID");
386
      serialNumber=dbConn.getCheckOutSerialNumber();
387
      pstmt = dbConn.prepareStatement(sql.toString());
388
      pstmt.execute();
389
      ResultSet rs = pstmt.getResultSet();
390
      boolean hasRow = rs.next();
391
      if (hasRow) {
392
        aclid = rs.getString(1);
393
      }
394
      pstmt.close();
395
    }//try
396
    finally
397
    {
398
      try
399
      {
400
        pstmt.close();
401
      }//try
402
      finally
403
      {
404
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
405
      }//finally
406
    }//finally
407
     
408
    
409
    return aclid;
410
  }
411

    
412
}
(46-46/54)