Project

General

Profile

1 523 berkley
/**
2
 *   '$Author$'
3
 *     '$Date$'
4
 * '$Revision$'
5 669 jones
 *
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 523 berkley
 */
20
21
package edu.ucsb.nceas.metacat;
22
23
import java.sql.*;
24
import java.util.*;
25 662 berkley
import java.net.*;
26 523 berkley
27 797 bojilova
public class RelationHandler //implements Runnable
28 523 berkley
{
29
  private Thread btThread = null;
30 1217 tao
  private DBConnection connection = null;
31 797 bojilova
  private String docid = null;
32 523 berkley
  MetaCatUtil util = new MetaCatUtil();
33 1388 tao
  // 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 523 berkley
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 797 bojilova
   * @param docid the ID of the XML document to index.
46 523 berkley
   */
47 1217 tao
  public RelationHandler(String docid, DBConnection conn)
48 819 bojilova
              throws McdbException, SQLException, AccessionNumberException
49 523 berkley
  {
50 1217 tao
    this.connection = conn;
51 797 bojilova
    this.docid = docid;
52
    putRelations();
53 523 berkley
  }
54
55
  /**
56 797 bojilova
   * insert the relations specified in the triples into xml_relation table
57 683 berkley
   */
58 819 bojilova
  private void putRelations()
59
              throws McdbException, SQLException, AccessionNumberException
60
  {
61
    String packagetype = null;
62
    String subject = null;
63 1388 tao
    String subjectParentId = null;
64 819 bojilova
    String subDoctype = null;
65
    String relationship = null;
66 1388 tao
    String relationshipParentId = null;
67 819 bojilova
    String object = null;
68 1388 tao
    String objectParentId = null;
69 819 bojilova
    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 1388 tao
73
    MetaCatUtil.debugMessage("Running relation handler!", 40);
74
75 797 bojilova
76 819 bojilova
    /*
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 743 jones
83 819 bojilova
    //DocumentImpl xmldoc = new DocumentImpl(conn,docid,false);
84 1217 tao
    packagetype = (new DocumentImpl(docid,false)).getDoctype();
85 797 bojilova
86 819 bojilova
    // first delete the relations for this package document if any
87
    deleteRelations(docid);
88 743 jones
89 819 bojilova
    // to put the new relations get them out of xml_nodes
90 1217 tao
    pstmt = connection.prepareStatement
91
                                (QuerySpecification.printPackageSQL(docid));
92 1388 tao
93 1217 tao
    //increase usage cont
94
    connection.increaseUsageCount(1);
95 819 bojilova
    pstmt.execute();
96
    ResultSet rs = pstmt.getResultSet();
97
    boolean hasmorerows = rs.next();
98 1388 tao
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 1217 tao
      tstmt = connection.prepareStatement("INSERT INTO xml_relation (" +
187 819 bojilova
                                    "docid,packagetype,subject,subdoctype," +
188
                                    "relationship, object, objdoctype) " +
189
                                    "VALUES (?, ?, ?, ?, ?, ?, ?)");
190 1217 tao
      //increase usage count
191
      connection.increaseUsageCount(1);
192 819 bojilova
    }
193 1388 tao
194
    while (en.hasMoreElements())
195
    {
196
      Vector values = (Vector)en.nextElement();
197 819 bojilova
      // cut out the revision number for subject and object
198 1388 tao
      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 819 bojilova
      //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 523 berkley
    }
220 819 bojilova
    pstmt.close();
221 1217 tao
    connection.commit();
222 523 berkley
  }
223 634 berkley
224 1388 tao
  /*
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 634 berkley
  /**
320
   * Deletes all of the relations with a docid of 'docid'.
321 819 bojilova
   * @param docid the docid of the package which relations to delete.
322 634 berkley
   */
323 797 bojilova
  public void deleteRelations(String docid) throws SQLException
324 634 berkley
  {
325 797 bojilova
    try {
326 1217 tao
      PreparedStatement pstmt = connection.prepareStatement(
327 819 bojilova
                                "DELETE FROM xml_relation " +
328
                                "WHERE docid = '" + docid + "'");
329 1217 tao
      //increase usage count
330
      connection.increaseUsageCount(1);
331 634 berkley
      pstmt.execute();
332 645 bojilova
      pstmt.close();
333 797 bojilova
    } catch(SQLException e) {
334 743 jones
      MetaCatUtil.debugMessage("error in RelationHandler.deleteRelations(): " +
335 683 berkley
                          e.getMessage());
336 797 bojilova
      System.out.println("error in RelationHandler.deleteRelations(): " +
337
                          e.getMessage());
338
      throw e;
339 634 berkley
    }
340
  }
341 819 bojilova
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 1217 tao
    PreparedStatement pstmt = null;
351
    DBConnection dbConn = null;
352
    int serialNumber = -1;
353 887 berkley
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 819 bojilova
    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 887 berkley
    */
382 1217 tao
    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 819 bojilova
409
    return aclid;
410
  }
411
412 523 berkley
}