Project

General

Profile

1 5282 jones
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2010 Regents of the University of California and the
4
 *             National Center for Ecological Analysis and Synthesis
5
 *
6
 *   '$Author: jones $'
7
 *     '$Date: 2010-02-03 17:58:12 -0900 (Wed, 03 Feb 2010) $'
8
 * '$Revision: 5211 $'
9
 *
10
 * This program is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation; either version 2 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program; if not, write to the Free Software
22
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
 */
24
25
package edu.ucsb.nceas.metacat;
26
27 5377 berkley
import java.util.*;
28
29 5282 jones
import java.sql.PreparedStatement;
30
import java.sql.ResultSet;
31
import java.sql.SQLException;
32 5895 berkley
import java.sql.Timestamp;
33 5282 jones
34
import org.apache.log4j.Logger;
35 5895 berkley
import org.dataone.service.types.Checksum;
36
import org.dataone.service.types.ChecksumAlgorithm;
37
import org.dataone.service.types.ObjectFormat;
38
import org.dataone.service.types.ObjectInfo;
39
import org.dataone.service.types.ObjectList;
40 5887 berkley
import org.dataone.service.types.SystemMetadata;
41 5895 berkley
import org.dataone.service.types.Identifier;
42 5282 jones
43
import edu.ucsb.nceas.metacat.database.DBConnection;
44
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
45 5887 berkley
import edu.ucsb.nceas.metacat.properties.PropertyService;
46 5895 berkley
import edu.ucsb.nceas.metacat.shared.ServiceException;
47 5286 jones
import edu.ucsb.nceas.metacat.util.DocumentUtil;
48 5895 berkley
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
49 5282 jones
50
/**
51
 * Manage the relationship between Metacat local identifiers (LocalIDs) that are
52
 * codified as the (docid, rev) pair with globally uniqe string identifiers
53
 * (GUIDs) that are opaque strings.  This class provides methods to manage these
54
 * identifiers, and to search for and look up LocalIDs based on their GUID and
55
 * vice versa. IdentifierManager is a singleton.
56
 *
57
 * @author Matthew Jones
58
 */
59
public class IdentifierManager {
60
61 5334 berkley
    public static final String TYPE_SYSTEM_METADATA = "systemmetadata";
62
    public static final String TYPE_IDENTIFIER = "identifier";
63 5887 berkley
    public static String DATAONE_SM_DOCTYPE;
64 5334 berkley
65 5282 jones
    /**
66
     * The single instance of the manager that is always returned.
67
     */
68
    private static IdentifierManager self = null;
69
    private Logger logMetacat = Logger.getLogger(EventLog.class);
70
71
    /**
72
     * A private constructor that initializes the class when getInstance() is
73
     * called.
74
     */
75
    private IdentifierManager()
76
    {
77 5887 berkley
        try
78
        {
79
            DATAONE_SM_DOCTYPE = PropertyService.getProperty("crudService.listObjects.ReturnDoctype");
80
        }
81
        catch(Exception e)
82
        {
83
            throw new RuntimeException("Error getting System Metadata doctype from " +
84
                    "the properties file.  Please make sure crudService.listObjects.ReturnDoctype " +
85
                    "exists in metacat.properties.");
86
        }
87 5282 jones
    }
88
89
    /**
90
     * Return the single instance of the manager after initializing it if it
91
     * wasn't previously initialized.
92
     *
93
     * @return the single IdentifierManager instance
94
     */
95
    public static IdentifierManager getInstance()
96
    {
97
        if (self == null) {
98
            self = new IdentifierManager();
99
        }
100
        return self;
101
    }
102
103
    /**
104 5895 berkley
     * return a hash of all of the info that is in the systemmetadata table
105
     * @param localId
106
     * @return
107
     */
108
    public Hashtable<String, String> getSystemMetadataInfo(String localId)
109
    throws McdbDocNotFoundException
110
    {
111
        try
112
        {
113
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
114
            localId = acc.getDocid();
115
        }
116
        catch(Exception e)
117
        {
118
            //do nothing. just try the localId as it is
119
        }
120
        Hashtable<String, String> h = new Hashtable<String, String>();
121
        String sql = "select guid, date_uploaded, rights_holder, checksum, checksum_algorithm, " +
122 5944 berkley
          "origin_member_node, authoritive_member_node, date_modified, submitter, object_format, size " +
123 5895 berkley
          "from systemmetadata where docid = ?";
124
        DBConnection dbConn = null;
125
        int serialNumber = -1;
126
        try
127
        {
128
            // Get a database connection from the pool
129
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getDocumentInfo");
130
            serialNumber = dbConn.getCheckOutSerialNumber();
131
132
            // Execute the insert statement
133
            PreparedStatement stmt = dbConn.prepareStatement(sql);
134
            stmt.setString(1, localId);
135
            ResultSet rs = stmt.executeQuery();
136
            if (rs.next())
137
            {
138
                String guid = rs.getString(1);
139
                Timestamp dateUploaded = rs.getTimestamp(2);
140
                String rightsHolder = rs.getString(3);
141
                String checksum = rs.getString(4);
142
                String checksumAlgorithm = rs.getString(5);
143
                String originMemberNode = rs.getString(6);
144
                String authoritativeMemberNode = rs.getString(7);
145
                Timestamp dateModified = rs.getTimestamp(8);
146
                String submitter = rs.getString(9);
147 5917 berkley
                String objectFormat = rs.getString(10);
148
                long size = new Long(rs.getString(11)).longValue();
149 5895 berkley
150
                h.put("guid", guid);
151
                h.put("date_uploaded", new Long(dateUploaded.getTime()).toString());
152
                h.put("rights_holder", rightsHolder);
153
                h.put("checksum", checksum);
154
                h.put("checksum_algorithm", checksumAlgorithm);
155
                h.put("origin_member_node", originMemberNode);
156
                h.put("authoritative_member_node", authoritativeMemberNode);
157
                h.put("date_modified", new Long(dateModified.getTime()).toString());
158
                h.put("submitter", submitter);
159 5917 berkley
                h.put("object_format", objectFormat);
160
                h.put("size", new Long(size).toString());
161 5895 berkley
162
                stmt.close();
163
            }
164
            else
165
            {
166
                stmt.close();
167
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
168
                throw new McdbDocNotFoundException("2Could not find document " + localId);
169
            }
170
171
        }
172
        catch (SQLException e)
173
        {
174
            e.printStackTrace();
175
            logMetacat.error("Error while getting system metadata info for localid " + localId + " : "
176
                    + e.getMessage());
177
        }
178
        finally
179
        {
180
            // Return database connection to the pool
181
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
182
        }
183
        return h;
184
    }
185
186
    /**
187 5378 berkley
     * return information on the document with localId.  These are the fields
188
     * from the xml_documents table.  They can be used to contstruct metadata
189
     * about the object that is stored.
190
     * @param localId
191
     * @return
192
     * @throws McdbDocNotFoundException
193
     */
194 5441 berkley
    public Hashtable<String, Object> getDocumentInfo(String localId)
195 5378 berkley
        throws McdbDocNotFoundException
196
    {
197 5798 berkley
        try
198
        {
199
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
200
            localId = acc.getDocid();
201
        }
202
        catch(Exception e)
203
        {
204
            //do nothing. just try the localId as it is
205
        }
206 5441 berkley
        Hashtable<String, Object> h = new Hashtable<String, Object>();
207 5378 berkley
        String sql = "select docname, doctype, user_owner, user_updated, " +
208
            "server_location, rev, date_created, date_updated from " +
209
            "xml_documents where docid like '" + localId + "'";
210
        DBConnection dbConn = null;
211
        int serialNumber = -1;
212
        try
213
        {
214
            // Get a database connection from the pool
215
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getDocumentInfo");
216
            serialNumber = dbConn.getCheckOutSerialNumber();
217
218
            // Execute the insert statement
219
            PreparedStatement stmt = dbConn.prepareStatement(sql);
220
            ResultSet rs = stmt.executeQuery();
221
            if (rs.next())
222
            {
223
                String docname = rs.getString(1);
224
                String doctype = rs.getString(2);
225
                String user_owner = rs.getString(3);
226
                String user_updated = rs.getString(4);
227
                String server_location = rs.getString(5);
228
                int rev = rs.getInt(6);
229
                String date_created = rs.getString(7);
230
                String date_updated = rs.getString(8);
231 6042 cjones
                h.put("docid", localId);
232 5378 berkley
                h.put("docname", docname);
233
                h.put("doctype", doctype);
234
                h.put("user_owner", user_owner);
235
                h.put("user_updated", user_updated);
236
                h.put("server_location", server_location);
237
                h.put("rev", new Integer(rev).toString());
238
                h.put("date_created", date_created);
239
                h.put("date_updated", date_updated);
240
241
                stmt.close();
242
            }
243
            else
244
            {
245
                stmt.close();
246
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
247 5798 berkley
                throw new McdbDocNotFoundException("2Could not find document " + localId);
248 5378 berkley
            }
249 5441 berkley
250 5444 berkley
            String sql2 = "select principal_name, permission, perm_type, perm_order from xml_access " +
251 5441 berkley
            "where docid like '" + localId + "'";
252 5444 berkley
            System.out.println("executing sql: " + sql2);
253 5441 berkley
            PreparedStatement stmt2 = dbConn.prepareStatement(sql2);
254 5442 berkley
            rs = stmt2.executeQuery();
255 5441 berkley
            Vector accessVector = new Vector();
256 5445 berkley
            while(rs.next())
257 5441 berkley
            {
258
                Hashtable accessHash = new Hashtable();
259
                String principal_name = rs.getString(1);
260
                String permission = rs.getString(2);
261
                String permissionType = rs.getString(3);
262
                String permissionOrder = rs.getString(4);
263
                accessHash.put("principal_name", principal_name);
264
                accessHash.put("permission", permission);
265
                accessHash.put("permission_type", permissionType);
266
                accessHash.put("permission_order", permissionOrder);
267 5444 berkley
                System.out.println("accessHash: " + accessHash.toString());
268 5441 berkley
                accessVector.add(accessHash);
269
            }
270
            h.put("access", accessVector);
271 5378 berkley
        }
272
        catch (SQLException e)
273
        {
274 5444 berkley
            e.printStackTrace();
275 5378 berkley
            logMetacat.error("Error while getting document info for localid " + localId + " : "
276
                    + e.getMessage());
277
        }
278
        finally
279
        {
280
            // Return database connection to the pool
281
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
282
        }
283
        return h;
284
    }
285
286
    /**
287
     * return the newest rev for a given localId
288
     * @param localId
289
     * @return
290
     */
291
    public int getLatestRevForLocalId(String localId)
292
        throws McdbDocNotFoundException
293
    {
294 5798 berkley
        try
295
        {
296
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
297
            localId = acc.getDocid();
298
        }
299
        catch(Exception e)
300
        {
301
            //do nothing. just try the localId as it is
302
        }
303 5378 berkley
        int rev = 0;
304
        String sql = "select rev from xml_documents where docid like '" + localId + "'";
305
        DBConnection dbConn = null;
306
        int serialNumber = -1;
307
        try
308
        {
309
            // Get a database connection from the pool
310
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLatestRevForLocalId");
311
            serialNumber = dbConn.getCheckOutSerialNumber();
312
313
            // Execute the insert statement
314
            PreparedStatement stmt = dbConn.prepareStatement(sql);
315
            ResultSet rs = stmt.executeQuery();
316
            if (rs.next())
317
            {
318
                rev = rs.getInt(1);
319
                stmt.close();
320
            }
321
            else
322
            {
323
                stmt.close();
324
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
325 5798 berkley
                throw new McdbDocNotFoundException("While trying to get the latest rev, could not find document " + localId);
326 5378 berkley
            }
327
        }
328
        catch (SQLException e)
329
        {
330
            logMetacat.error("Error while looking up the guid: "
331
                    + e.getMessage());
332
        }
333
        finally
334
        {
335
            // Return database connection to the pool
336
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
337
        }
338
        return rev;
339
    }
340
341
    /**
342 5377 berkley
     * return all local ids in the object store that do not have associated
343
     * system metadata and are not themselves system metadata
344
     */
345
    public List<String> getLocalIdsWithNoSystemMetadata()
346
    {
347
        Vector<String> ids = new Vector<String>();
348
        //String sql = "select docid from identifier where guid in (select guid from systemmetadata)";
349 5796 berkley
        //String sql = "select docid from xml_documents where docid not " +
350
        //    "in (select docid from identifier where guid in (select guid from systemmetadata)) " +
351
        //    "and doctype not like '" + DATAONE_SM_DOCTYPE + "'";
352 5798 berkley
        String sql = "select docid, rev from xml_documents where docid not in " +
353 5796 berkley
            "(select docid from systemmetadata) and (docid not in " +
354
            "(select docid from identifier where guid in (select guid from systemmetadata)))";
355 5377 berkley
        DBConnection dbConn = null;
356
        int serialNumber = -1;
357
        try
358
        {
359
            // Get a database connection from the pool
360
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLocalIdsWithNoSystemMetadata");
361
            serialNumber = dbConn.getCheckOutSerialNumber();
362
363
            // Execute the insert statement
364
            PreparedStatement stmt = dbConn.prepareStatement(sql);
365
            ResultSet rs = stmt.executeQuery();
366
            while (rs.next())
367
            {
368
                String localid = rs.getString(1);
369 5798 berkley
                String rev = rs.getString(2);
370
                localid += "." + rev;
371 5796 berkley
                System.out.println("id to add SM for: " + localid);
372 5377 berkley
                ids.add(localid);
373
            }
374
            stmt.close();
375
        }
376
        catch (SQLException e)
377
        {
378
            logMetacat.error("Error while looking up the guid: "
379
                    + e.getMessage());
380
        }
381
        finally
382
        {
383
            // Return database connection to the pool
384
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
385
        }
386
387
        return ids;
388
    }
389
390
    /**
391
     * return a listing of all local ids in the object store
392
     * @return a list of all local ids in metacat
393
     */
394
    public List<String> getAllLocalIds()
395
       throws Exception
396
    {
397
        Vector<String> ids = new Vector<String>();
398
        String sql = "select docid from xml_documents";
399
        DBConnection dbConn = null;
400
        int serialNumber = -1;
401
        try
402
        {
403
            // Get a database connection from the pool
404
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getAllLocalIds");
405
            serialNumber = dbConn.getCheckOutSerialNumber();
406
407
            // Execute the insert statement
408
            PreparedStatement stmt = dbConn.prepareStatement(sql);
409
            ResultSet rs = stmt.executeQuery();
410
            while (rs.next())
411
            {
412
                String localid = rs.getString(1);
413
                ids.add(localid);
414
            }
415
            stmt.close();
416
        }
417
        catch (SQLException e)
418
        {
419
            logMetacat.error("Error while looking up the guid: "
420
                    + e.getMessage());
421
        }
422
        finally
423
        {
424
            // Return database connection to the pool
425
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
426
        }
427
        return ids;
428
    }
429
430
    /**
431 5282 jones
     * Lookup a GUID from the database, and return the associated LocalID. If
432
     * the identifier is not found, throw an exception.
433
     *
434
     * @param guid the global identifier to look up
435
     * @return String containing the corresponding LocalId
436
     * @throws McdbDocNotFoundException if the identifier is not found
437
     */
438
    public String getLocalId(String guid) throws McdbDocNotFoundException
439
    {
440 5424 berkley
        return this.getLocalId(guid, TYPE_IDENTIFIER);
441 5282 jones
    }
442
443
    /**
444
     * Determine if an identifier exists already, returning true if so.
445
     *
446
     * @param guid the global identifier to look up
447
     * @return boolean true if the identifier exists
448
     */
449
    public boolean identifierExists(String guid)
450
    {
451
        boolean idExists = false;
452
        try {
453
            String id = getLocalId(guid);
454
            if (id != null) {
455
                idExists = true;
456
            }
457
        } catch (McdbDocNotFoundException e) {
458
            idExists = false;
459
        }
460
        return idExists;
461
    }
462
463
    /**
464
     * Create a mapping between two identifiers, one representing an
465
     * unconstrained, globally unique string (guid), and one a localId
466
     * in the Metacat docid format (scope.id.revision).
467
     * This mapping allows one to find the global id (guid) from the localId.
468
     *
469
     * @param guid the global string identifier to be mapped
470
     * @param localId the local identifier to be mapped
471
     */
472
    public void createMapping(String guid, String localId)
473
    {
474 5334 berkley
        createGenericMapping(guid, localId, TYPE_IDENTIFIER);
475 5282 jones
    }
476 5453 berkley
477
    /**
478
     *
479
     * @param guid
480
     * @param rev
481
     * @return
482
     */
483
    public String generateLocalId(String guid, int rev)
484
    {
485
        return generateLocalId(guid, rev, false);
486
    }
487 5286 jones
488
    /**
489
     * Given a global identifier (guid), create a suitable local identifier that
490
     * follows Metacat's docid semantics and format (scope.id.rev), and create
491
     * a mapping between these two identifiers.  This effectively reserves both
492
     * the global and the local identifier, as they will now be present in the
493
     * identifier mapping table.  If the incoming guid has the syntax of a
494
     * Metacat docid (scope.id.rev), then simply use it.
495
     *
496
     * @param guid the global string identifier
497
     * @param rev the revision number to be used in the localId
498
     * @return String containing the localId to be used for Metacat operations
499
     */
500 5453 berkley
    public String generateLocalId(String guid, int rev, boolean isSystemMetadata)
501 5286 jones
    {
502
        String localId = "";
503
        boolean conformsToDocidFormat = false;
504
505
        // Check if the guid passed in is already in docid (scope.id.rev) format
506
        try {
507
            AccessionNumber acc = new AccessionNumber(guid, "NONE");
508
            if (new Integer(acc.getRev()).intValue() > 0) {
509
                conformsToDocidFormat = true;
510
            }
511
        } catch (NumberFormatException e) {
512
            // No action needed, simply detecting invalid AccessionNumbers
513
        } catch (AccessionNumberException e) {
514
            // No action needed, simply detecting invalid AccessionNumbers
515
        } catch (SQLException e) {
516
            // No action needed, simply detecting invalid AccessionNumbers
517
        }
518
519
        if (conformsToDocidFormat) {
520
            // if it conforms, use it for both guid and localId
521
            localId = guid;
522
        } else {
523
            // if not, then generate a new unique localId
524
            localId = DocumentUtil.generateDocumentId(rev);
525
        }
526
527
        // Register this new pair in the identifier mapping table
528 5453 berkley
        System.out.println("creating mapping in generateLocalId");
529
        if(!isSystemMetadata)
530
        { //don't do this if we're generating for system metadata
531
            createMapping(guid, localId);
532
        }
533 5286 jones
534
        return localId;
535
    }
536 5322 berkley
537
    /**
538
     * given a local identifer, look up the guid.  Throw McdbDocNotFoundException
539 5452 berkley
     * if the docid, rev is not found in the identifiers or systemmetadata tables
540 5322 berkley
     *
541
     * @param docid the docid to look up
542
     * @param rev the revision of the docid to look up
543
     * @return String containing the mapped guid
544
     * @throws McdbDocNotFoundException if the docid, rev is not found
545
     */
546
    public String getGUID(String docid, int rev)
547
      throws McdbDocNotFoundException
548
    {
549 5798 berkley
        System.out.println("getting guid for " + docid);
550 5322 berkley
        String query = "select guid from identifier where docid = ? and rev = ?";
551
        String guid = null;
552 5451 berkley
        boolean found = false;
553 5322 berkley
554
        DBConnection dbConn = null;
555
        int serialNumber = -1;
556
        try {
557
            // Get a database connection from the pool
558 5377 berkley
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getGUID");
559 5322 berkley
            serialNumber = dbConn.getCheckOutSerialNumber();
560
561
            // Execute the insert statement
562
            PreparedStatement stmt = dbConn.prepareStatement(query);
563
            stmt.setString(1, docid);
564
            stmt.setInt(2, rev);
565
            ResultSet rs = stmt.executeQuery();
566 5451 berkley
            if (rs.next())
567
            {
568 5322 berkley
                guid = rs.getString(1);
569 5451 berkley
            }
570
            else
571
            {
572
                query = "select guid from systemmetadata where docid = ? and rev = ?";
573
                stmt = dbConn.prepareStatement(query);
574
                stmt.setString(1, docid);
575
                stmt.setInt(2, rev);
576 5452 berkley
                rs = stmt.executeQuery();
577 5451 berkley
                if(rs.next())
578
                {
579
                    guid = rs.getString(1);
580
                }
581
                else
582
                {
583
                    throw new McdbDocNotFoundException("No guid registered for docid " + docid + "." + rev);
584
                }
585 5322 berkley
            }
586 5451 berkley
587 5322 berkley
        } catch (SQLException e) {
588
            logMetacat.error("Error while looking up the guid: "
589
                    + e.getMessage());
590
        } finally {
591
            // Return database connection to the pool
592
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
593
        }
594
595
        return guid;
596
    }
597 5333 berkley
598
    /**
599 5887 berkley
     * creates a mapping for a system metadata document, but DOES NOT add any
600
     * of the extra system metadata information to the table.  You must call
601
     * insertAdditionalSystemMetadataFields to complete the entry
602 5333 berkley
     *
603
     * @param guid the id to insert
604
     * @param localId the systemMetadata object to get the local id for
605
     */
606
    public void createSystemMetadataMapping(String guid, String localId)
607
    {
608 5334 berkley
        createGenericMapping(guid, localId, TYPE_SYSTEM_METADATA);
609
    }
610
611 5377 berkley
    /**
612 5887 berkley
     * creates a system metadata mapping and adds additional fields from sysmeta
613
     * to the table for quick searching.
614
     *
615
     * @param guid the id to insert
616
     * @param localId the systemMetadata object to get the local id for
617
     */
618
    public void createSystemMetadataMapping(SystemMetadata sysmeta, String localId)
619
    {
620
        createGenericMapping(sysmeta.getIdentifier().getValue(), localId, TYPE_SYSTEM_METADATA);
621
        insertAdditionalSystemMetadataFields(sysmeta);
622
    }
623
624
    /**
625 5377 berkley
     * update a mapping
626
     * @param guid
627
     * @param localId
628
     */
629 5350 berkley
    public void updateSystemMetadataMapping(String guid, String localId)
630
    {
631 5950 berkley
        System.out.println("$$$$$$$$$$$$$$ updating systemmetadata table with additional info");
632 5350 berkley
        int serialNumber = -1;
633
        DBConnection dbConn = null;
634
        try {
635
            // Parse the localId into scope and rev parts
636
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
637
            String docid = acc.getDocid();
638
            int rev = 1;
639
            if(acc.getRev() != null)
640
            {
641
              rev = (new Integer(acc.getRev()).intValue());
642
            }
643
644
            // Get a database connection from the pool
645
            dbConn =
646 5377 berkley
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
647 5350 berkley
            serialNumber = dbConn.getCheckOutSerialNumber();
648
649
            // Execute the insert statement
650
            String query = "update systemmetadata set (docid, rev) = (?, ?) where guid='" + guid + "'";
651 5352 berkley
            //System.out.println("query: " + query + " for params: (guid:" + guid + ", docid=" + docid + ", rev=" + rev + ")");
652 5350 berkley
            PreparedStatement stmt = dbConn.prepareStatement(query);
653
            stmt.setString(1, docid);
654
            stmt.setInt(2, rev);
655
            int rows = stmt.executeUpdate();
656
657
            stmt.close();
658
        } catch (SQLException e) {
659
            e.printStackTrace();
660
            logMetacat.error("SQL error while updating a mapping to the system metadata identifier: "
661
                    + e.getMessage());
662
        } catch (NumberFormatException e) {
663
            e.printStackTrace();
664
            logMetacat.error("NumberFormat error while updating a mapping to the system metadata identifier: "
665
                    + e.getMessage());
666
        } catch (AccessionNumberException e) {
667
            e.printStackTrace();
668
            logMetacat.error("AccessionNumber error while updating a mapping to the system metadata identifier: "
669
                    + e.getMessage());
670
        } finally {
671
            // Return database connection to the pool
672
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
673
        }
674 5950 berkley
        System.out.println("done updating systemmetadata");
675 5350 berkley
    }
676 5334 berkley
677
    /**
678
     * return the localId of a system metadata document based on its guid
679
     */
680 5424 berkley
    public String getSystemMetadataLocalId(String guid)
681 5334 berkley
      throws McdbDocNotFoundException
682
    {
683 5424 berkley
      return this.getLocalId(guid, TYPE_SYSTEM_METADATA);
684 5334 berkley
    }
685
686 5887 berkley
    public void insertAdditionalSystemMetadataFields(long dateUploaded, String rightsHolder,
687
            String checksum, String checksumAlgorithm, String originMemberNode,
688 5917 berkley
            String authoritativeMemberNode, long modifiedDate, String submitter,
689
            String guid, String objectFormat, long size)
690 5887 berkley
    {
691
        DBConnection dbConn = null;
692
        int serialNumber = -1;
693 5957 berkley
694 5887 berkley
        try {
695
            // Get a database connection from the pool
696
            dbConn =
697
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
698
            serialNumber = dbConn.getCheckOutSerialNumber();
699
700
            // Execute the insert statement
701
            String query = "update " + TYPE_SYSTEM_METADATA +
702
                " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
703 5917 berkley
                "origin_member_node, authoritive_member_node, date_modified, " +
704
                "submitter, object_format, size) " +
705
                "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
706 5887 berkley
            PreparedStatement stmt = dbConn.prepareStatement(query);
707
708
            //data values
709
            stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
710
            stmt.setString(2, rightsHolder);
711
            stmt.setString(3, checksum);
712
            stmt.setString(4, checksumAlgorithm);
713
            stmt.setString(5, originMemberNode);
714
            stmt.setString(6, authoritativeMemberNode);
715
            stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
716
            stmt.setString(8, submitter);
717 5917 berkley
            stmt.setString(9, objectFormat);
718
            stmt.setString(10, new Long(size).toString());
719 5887 berkley
            //where clause
720 5917 berkley
            stmt.setString(11, guid);
721 5887 berkley
            System.out.println("stmt: " + stmt.toString());
722
            //execute
723
            int rows = stmt.executeUpdate();
724
725
            stmt.close();
726
        } catch (SQLException e) {
727
            e.printStackTrace();
728 5950 berkley
            logMetacat.error("insertAdditionalSystemMetadataFields: SQL error while creating a mapping to the system metadata identifier: "
729 5887 berkley
                    + e.getMessage());
730
        } catch (NumberFormatException e) {
731
            e.printStackTrace();
732 5950 berkley
            logMetacat.error("insertAdditionalSystemMetadataFields: NumberFormat error while creating a mapping to the system metadata identifier: "
733 5887 berkley
                    + e.getMessage());
734
        } finally {
735
            // Return database connection to the pool
736
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
737
        }
738
    }
739
740 5334 berkley
    /**
741 5887 berkley
     * Insert the system metadata fields into the db
742
     * @param sm
743
     */
744
    public void insertAdditionalSystemMetadataFields(SystemMetadata sm)
745
    {
746
        insertAdditionalSystemMetadataFields(
747
                sm.getDateUploaded().getTime(),
748
                sm.getRightsHolder().getValue(),
749
                sm.getChecksum().getValue(),
750
                sm.getChecksum().getAlgorithm().name(),
751
                sm.getOriginMemberNode().getValue(),
752
                sm.getAuthoritativeMemberNode().getValue(),
753
                sm.getDateSysMetadataModified().getTime(),
754
                sm.getSubmitter().getValue(),
755 5917 berkley
                sm.getIdentifier().getValue(),
756
                sm.getObjectFormat().toString(),
757
                sm.getSize());
758 5887 berkley
    }
759
760
    /**
761 5334 berkley
     * return a localId based on a guid.  The type can either be 'identifier'
762
     * to get an id from the identifier table or 'systemmetadata' to get
763
     * the identifier from the systemidentifier table
764
     */
765 5424 berkley
    private String getLocalId(String guid, String type)
766 5334 berkley
      throws McdbDocNotFoundException
767
    {
768
      if(!type.equals(TYPE_IDENTIFIER) &&
769
        !type.equals(TYPE_SYSTEM_METADATA))
770
      {
771
        throw new RuntimeException("cannot lookup the identifier for type " + type +
772
          ".  Please choose 'identifier' or 'systemmetadata'.");
773
      }
774
775
      String db_guid = "";
776
      String docid = "";
777
      int rev = 0;
778
779
      String query = "select guid, docid, rev from " + type + " where guid = ?";
780 5352 berkley
      //System.out.println("query: " + query + " for params: (" + guid + ")");
781 5334 berkley
782
      DBConnection dbConn = null;
783 5333 berkley
      int serialNumber = -1;
784 5334 berkley
      try {
785
          // Get a database connection from the pool
786
          dbConn = DBConnectionPool.getDBConnection("Identifier.getLocalId");
787
          serialNumber = dbConn.getCheckOutSerialNumber();
788
789
          // Execute the insert statement
790
          PreparedStatement stmt = dbConn.prepareStatement(query);
791
          stmt.setString(1, guid);
792
          ResultSet rs = stmt.executeQuery();
793
          if (rs.next()) {
794
              db_guid = rs.getString(1);
795
              docid = rs.getString(2);
796
              rev = rs.getInt(3);
797
              assert(db_guid.equals(guid));
798
          } else {
799
              throw new McdbDocNotFoundException("Document not found:" + guid);
800
          }
801
          stmt.close();
802
      } catch (SQLException e) {
803
          logMetacat.error("Error while looking up the local identifier: "
804
                  + e.getMessage());
805
      } finally {
806
          // Return database connection to the pool
807
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
808
      }
809
      return docid + "." + rev;
810
    }
811
812 5377 berkley
    /**
813 5895 berkley
     * query the systemmetadata table based on the given parameters
814
     * @param startTime
815
     * @param endTime
816
     * @param objectFormat
817
     * @param replicaStatus
818
     * @param start
819
     * @param count
820
     * @return ObjectList
821
     */
822
    public ObjectList querySystemMetadata(Date startTime, Date endTime,
823
            ObjectFormat objectFormat, boolean replicaStatus, int start, int count)
824
    {
825
        ObjectList ol = new ObjectList();
826
        int total = 0;
827 5943 berkley
        DBConnection dbConn = null;
828
        int serialNumber = -1;
829 5895 berkley
830
        try
831
        {
832
            String sql = "select guid, date_uploaded, rights_holder, checksum, " +
833
                "checksum_algorithm, origin_member_node, authoritive_member_node, " +
834 5917 berkley
                "date_modified, submitter, object_format, size from systemmetadata";
835 5895 berkley
836
            boolean f1 = false;
837
            boolean f2 = false;
838
            boolean f3 = false;
839
840
            if(startTime != null)
841
            {
842 5917 berkley
                sql += " where systemmetadata.date_modified > ?";
843 5895 berkley
                f1 = true;
844
            }
845
846
            if(endTime != null)
847
            {
848 5917 berkley
                if(!f1)
849
                {
850
                    sql += " where systemmetadata.date_modified < ?";
851
                }
852
                else
853
                {
854
                    sql += " and systemmetadata.date_modified < ?";
855
                }
856 5895 berkley
                f2 = true;
857
            }
858
859
            if(objectFormat != null)
860
            {
861 5917 berkley
                if(!f1 && !f2)
862
                {
863
                    sql += " where object_format = ?";
864
                }
865
                else
866
                {
867
                    sql += " and object_format = ?";
868
                }
869 5895 berkley
                f3 = true;
870
            }
871
872
            if(replicaStatus)
873
            {
874
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.memberNodeId");
875 5917 berkley
                if(!f1 && !f2 && !f3)
876
                {
877
                    sql += " where authoritive_member_node != '" + currentNodeId.trim() + "'";
878
                }
879
                else
880
                {
881
                    sql += " and authoritive_member_node != '" + currentNodeId.trim() + "'";
882
                }
883 5895 berkley
            }
884
885 5943 berkley
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.querySystemMetadata");
886
            serialNumber = dbConn.getCheckOutSerialNumber();
887 5895 berkley
            PreparedStatement stmt = dbConn.prepareStatement(sql);
888
889
            if(f1 && f2 && f3)
890
            {
891
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
892
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
893
                stmt.setString(3, objectFormat.toString());
894
            }
895
            else if(f1 && f2 && !f3)
896
            {
897
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
898
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
899
            }
900
            else if(f1 && !f2 && f3)
901
            {
902
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
903
                stmt.setString(2, objectFormat.toString());
904
            }
905
            else if(f1 && !f2 && !f3)
906
            {
907
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
908
            }
909
            else if(!f1 && f2 && f3)
910
            {
911
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
912
                stmt.setString(2, objectFormat.toString());
913
            }
914
            else if(!f1 && !f2 && f3)
915
            {
916
                stmt.setString(1, objectFormat.toString());
917
            }
918
            else if(!f1 && f2 && !f3)
919
            {
920
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
921
            }
922
923
            //System.out.println("LISTOBJECTS QUERY: " + stmt.toString());
924
925
            ResultSet rs = stmt.executeQuery();
926 5917 berkley
            for(int i=0; i<start; i++)
927 5895 berkley
            {
928 5917 berkley
                if(rs.next())
929
                {
930
                    total++;
931
                }
932
                else
933
                {
934
                    break;
935
                }
936 5895 berkley
            }
937 5917 berkley
938 5895 berkley
            int countIndex = 0;
939
940
            while(rs.next())
941
            {
942
                total++;
943
                if(countIndex >= count)
944
                {
945
                    break;
946
                }
947
                String guid = rs.getString(1);
948
                //System.out.println("query found doc with guid " + guid);
949
                //Timestamp dateUploaded = rs.getTimestamp(2);
950
                //String rightsHolder = rs.getString(3);
951
                String checksum = rs.getString(4);
952
                String checksumAlgorithm = rs.getString(5);
953
                //String originMemberNode = rs.getString(6);
954
                String authoritiveMemberNode = rs.getString(7);
955
                Timestamp dateModified = rs.getTimestamp(8);
956
                //String submitter = rs.getString(9);
957
                String format = rs.getString(10);
958 5917 berkley
                String sz = rs.getString(11);
959
                long size = 0;
960
                if(sz != null && !sz.trim().equals(""))
961
                {
962
                    size = new Long(rs.getString(11)).longValue();
963
                }
964 5895 berkley
965
                ObjectInfo oi = new ObjectInfo();
966
967
                Identifier id = new Identifier();
968
                id.setValue(guid);
969
                oi.setIdentifier(id);
970
971
                oi.setDateSysMetadataModified(new Date(dateModified.getTime()));
972
973
                Checksum cs = new Checksum();
974
                cs.setValue(checksum);
975 5906 berkley
                cs.setAlgorithm(ChecksumAlgorithm.valueOf(checksumAlgorithm));
976 5957 berkley
                //cs.setAlgorithm(ChecksumAlgorithm.convert(checksumAlgorithm));
977 5895 berkley
                oi.setChecksum(cs);
978
979
                ObjectFormat oFormat = ObjectFormat.convert(format);
980
                if(oFormat != null)
981
                {
982
                    oi.setObjectFormat(oFormat);
983
                }
984 5906 berkley
                else
985
                { //if there is no object format, just default to text/plain
986 5917 berkley
                    oi.setObjectFormat(ObjectFormat.OCTET_STREAM);
987 5906 berkley
                }
988 5917 berkley
989
                oi.setSize(size);
990 5895 berkley
991
                ol.addObjectInfo(oi);
992
                countIndex++;
993
            }
994
995
            while(rs.next())
996
            { //expend the resultset to get the total count of possible rows
997
                total++;
998
            }
999
        }
1000
        catch(Exception e)
1001
        {
1002
           e.printStackTrace();
1003
           System.out.println("Error querying system metadata: " + e.getMessage());
1004
        }
1005 5943 berkley
        finally
1006
        {
1007
            // Return database connection to the pool
1008
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1009
        }
1010 5895 berkley
1011
        ol.setStart(start);
1012 5922 berkley
        ol.setCount(ol.sizeObjectInfoList());
1013 5895 berkley
        ol.setTotal(total);
1014
1015
        return ol;
1016
    }
1017
1018
    /**
1019 5377 berkley
     * create a mapping in the systemmetadata or identifier table
1020
     * @param guid
1021
     * @param localId
1022
     * @param type
1023
     */
1024 5334 berkley
    private void createGenericMapping(String guid, String localId, String type)
1025 5453 berkley
    {
1026 5334 berkley
        if(!type.equals(TYPE_IDENTIFIER) &&
1027
        !type.equals(TYPE_SYSTEM_METADATA))
1028
        {
1029
          throw new RuntimeException("Cannot create mapping for type " + type +
1030
            ".  Please choose 'identifier' or 'systemmetadata'.");
1031
        }
1032
1033
        int serialNumber = -1;
1034 5333 berkley
        DBConnection dbConn = null;
1035
        try {
1036
1037
            // Parse the localId into scope and rev parts
1038
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1039
            String docid = acc.getDocid();
1040 5344 berkley
            int rev = 1;
1041
            if(acc.getRev() != null)
1042
            {
1043
              rev = (new Integer(acc.getRev()).intValue());
1044
            }
1045 5333 berkley
1046
            // Get a database connection from the pool
1047
            dbConn =
1048 5377 berkley
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1049 5333 berkley
            serialNumber = dbConn.getCheckOutSerialNumber();
1050
1051
            // Execute the insert statement
1052 5344 berkley
            String query = "insert into " + type + " (guid, docid, rev) values (?, ?, ?)";
1053 5352 berkley
            //System.out.println("query: " + query + " for params: (" + guid + ", " + docid + ", " + rev + ")");
1054 5333 berkley
            PreparedStatement stmt = dbConn.prepareStatement(query);
1055
            stmt.setString(1, guid);
1056
            stmt.setString(2, docid);
1057
            stmt.setInt(3, rev);
1058 5887 berkley
            System.out.println("generic mapping query: " + stmt.toString());
1059 5333 berkley
            int rows = stmt.executeUpdate();
1060
1061
            stmt.close();
1062
        } catch (SQLException e) {
1063 5344 berkley
            e.printStackTrace();
1064 5950 berkley
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + type + " identifier: "
1065 5333 berkley
                    + e.getMessage());
1066
        } catch (NumberFormatException e) {
1067 5344 berkley
            e.printStackTrace();
1068 5950 berkley
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + type + " identifier: "
1069 5333 berkley
                    + e.getMessage());
1070
        } catch (AccessionNumberException e) {
1071 5344 berkley
            e.printStackTrace();
1072 5950 berkley
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + type + " identifier: "
1073 5333 berkley
                    + e.getMessage());
1074
        } finally {
1075
            // Return database connection to the pool
1076
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1077
        }
1078
    }
1079 5282 jones
}