Project

General

Profile

1
/**
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
import java.util.*;
28

    
29
import java.sql.PreparedStatement;
30
import java.sql.ResultSet;
31
import java.sql.SQLException;
32
import java.sql.Timestamp;
33

    
34
import org.apache.log4j.Logger;
35
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
import org.dataone.service.types.SystemMetadata;
41
import org.dataone.service.types.Identifier;
42

    
43
import edu.ucsb.nceas.metacat.database.DBConnection;
44
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
45
import edu.ucsb.nceas.metacat.properties.PropertyService;
46
import edu.ucsb.nceas.metacat.shared.ServiceException;
47
import edu.ucsb.nceas.metacat.util.DocumentUtil;
48
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
49

    
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
    public static final String TYPE_SYSTEM_METADATA = "systemmetadata";
62
    public static final String TYPE_IDENTIFIER = "identifier";
63
    public static String DATAONE_SM_DOCTYPE;
64
  
65
    /**
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
        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
    }
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
     * 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
          "origin_member_node, authoritative_member_node, date_modified, submitter " +
123
          "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
                
148
                h.put("guid", guid);
149
                h.put("date_uploaded", new Long(dateUploaded.getTime()).toString());
150
                h.put("rights_holder", rightsHolder);
151
                h.put("checksum", checksum);
152
                h.put("checksum_algorithm", checksumAlgorithm);
153
                h.put("origin_member_node", originMemberNode);
154
                h.put("authoritative_member_node", authoritativeMemberNode);
155
                h.put("date_modified", new Long(dateModified.getTime()).toString());
156
                h.put("submitter", submitter);
157
                
158
                stmt.close();
159
            } 
160
            else
161
            {
162
                stmt.close();
163
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
164
                throw new McdbDocNotFoundException("2Could not find document " + localId);
165
            }
166
            
167
        } 
168
        catch (SQLException e) 
169
        {
170
            e.printStackTrace();
171
            logMetacat.error("Error while getting system metadata info for localid " + localId + " : "  
172
                    + e.getMessage());
173
        } 
174
        finally 
175
        {
176
            // Return database connection to the pool
177
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
178
        }
179
        return h;
180
    }
181
    
182
    /**
183
     * return information on the document with localId.  These are the fields
184
     * from the xml_documents table.  They can be used to contstruct metadata 
185
     * about the object that is stored.
186
     * @param localId
187
     * @return
188
     * @throws McdbDocNotFoundException
189
     */
190
    public Hashtable<String, Object> getDocumentInfo(String localId)
191
        throws McdbDocNotFoundException
192
    {
193
        try
194
        {
195
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
196
            localId = acc.getDocid();
197
        }
198
        catch(Exception e)
199
        {
200
            //do nothing. just try the localId as it is
201
        }
202
        Hashtable<String, Object> h = new Hashtable<String, Object>();
203
        String sql = "select docname, doctype, user_owner, user_updated, " +
204
            "server_location, rev, date_created, date_updated from " + 
205
            "xml_documents where docid like '" + localId + "'";
206
        DBConnection dbConn = null;
207
        int serialNumber = -1;
208
        try 
209
        {
210
            // Get a database connection from the pool
211
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getDocumentInfo");
212
            serialNumber = dbConn.getCheckOutSerialNumber();
213

    
214
            // Execute the insert statement
215
            PreparedStatement stmt = dbConn.prepareStatement(sql);
216
            ResultSet rs = stmt.executeQuery();
217
            if (rs.next()) 
218
            {
219
                String docname = rs.getString(1);
220
                String doctype = rs.getString(2);
221
                String user_owner = rs.getString(3);
222
                String user_updated = rs.getString(4);
223
                String server_location = rs.getString(5);
224
                int rev = rs.getInt(6);
225
                String date_created = rs.getString(7);
226
                String date_updated = rs.getString(8);
227
                h.put("docname", docname);
228
                h.put("doctype", doctype);
229
                h.put("user_owner", user_owner);
230
                h.put("user_updated", user_updated);
231
                h.put("server_location", server_location);
232
                h.put("rev", new Integer(rev).toString());
233
                h.put("date_created", date_created);
234
                h.put("date_updated", date_updated);
235
                
236
                stmt.close();
237
            } 
238
            else
239
            {
240
                stmt.close();
241
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
242
                throw new McdbDocNotFoundException("2Could not find document " + localId);
243
            }
244
            
245
            String sql2 = "select principal_name, permission, perm_type, perm_order from xml_access " +
246
            "where docid like '" + localId + "'";
247
            System.out.println("executing sql: " + sql2);
248
            PreparedStatement stmt2 = dbConn.prepareStatement(sql2);
249
            rs = stmt2.executeQuery();
250
            Vector accessVector = new Vector();
251
            while(rs.next())
252
            {
253
                Hashtable accessHash = new Hashtable();
254
                String principal_name = rs.getString(1);
255
                String permission = rs.getString(2);
256
                String permissionType = rs.getString(3);
257
                String permissionOrder = rs.getString(4);
258
                accessHash.put("principal_name", principal_name);
259
                accessHash.put("permission", permission);
260
                accessHash.put("permission_type", permissionType);
261
                accessHash.put("permission_order", permissionOrder);
262
                System.out.println("accessHash: " + accessHash.toString());
263
                accessVector.add(accessHash);
264
            }
265
            h.put("access", accessVector);
266
        } 
267
        catch (SQLException e) 
268
        {
269
            e.printStackTrace();
270
            logMetacat.error("Error while getting document info for localid " + localId + " : "  
271
                    + e.getMessage());
272
        } 
273
        finally 
274
        {
275
            // Return database connection to the pool
276
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
277
        }
278
        return h;
279
    }
280
    
281
    /**
282
     * return the newest rev for a given localId
283
     * @param localId
284
     * @return
285
     */
286
    public int getLatestRevForLocalId(String localId)
287
        throws McdbDocNotFoundException
288
    {
289
        try
290
        {
291
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
292
            localId = acc.getDocid();
293
        }
294
        catch(Exception e)
295
        {
296
            //do nothing. just try the localId as it is
297
        }
298
        int rev = 0;
299
        String sql = "select rev from xml_documents where docid like '" + localId + "'";
300
        DBConnection dbConn = null;
301
        int serialNumber = -1;
302
        try 
303
        {
304
            // Get a database connection from the pool
305
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLatestRevForLocalId");
306
            serialNumber = dbConn.getCheckOutSerialNumber();
307

    
308
            // Execute the insert statement
309
            PreparedStatement stmt = dbConn.prepareStatement(sql);
310
            ResultSet rs = stmt.executeQuery();
311
            if (rs.next()) 
312
            {
313
                rev = rs.getInt(1);
314
                stmt.close();
315
            } 
316
            else
317
            {
318
                stmt.close();
319
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
320
                throw new McdbDocNotFoundException("While trying to get the latest rev, could not find document " + localId);
321
            }
322
        } 
323
        catch (SQLException e) 
324
        {
325
            logMetacat.error("Error while looking up the guid: " 
326
                    + e.getMessage());
327
        } 
328
        finally 
329
        {
330
            // Return database connection to the pool
331
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
332
        }
333
        return rev;
334
    }
335
    
336
    /**
337
     * return all local ids in the object store that do not have associated
338
     * system metadata and are not themselves system metadata
339
     */
340
    public List<String> getLocalIdsWithNoSystemMetadata()
341
    {
342
        Vector<String> ids = new Vector<String>();
343
        //String sql = "select docid from identifier where guid in (select guid from systemmetadata)"; 
344
        //String sql = "select docid from xml_documents where docid not " +
345
        //    "in (select docid from identifier where guid in (select guid from systemmetadata)) " +
346
        //    "and doctype not like '" + DATAONE_SM_DOCTYPE + "'";
347
        String sql = "select docid, rev from xml_documents where docid not in " +
348
            "(select docid from systemmetadata) and (docid not in " +
349
            "(select docid from identifier where guid in (select guid from systemmetadata)))";
350
        DBConnection dbConn = null;
351
        int serialNumber = -1;
352
        try 
353
        {
354
            // Get a database connection from the pool
355
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLocalIdsWithNoSystemMetadata");
356
            serialNumber = dbConn.getCheckOutSerialNumber();
357

    
358
            // Execute the insert statement
359
            PreparedStatement stmt = dbConn.prepareStatement(sql);
360
            ResultSet rs = stmt.executeQuery();
361
            while (rs.next()) 
362
            {
363
                String localid = rs.getString(1);
364
                String rev = rs.getString(2);
365
                localid += "." + rev;
366
                System.out.println("id to add SM for: " + localid);
367
                ids.add(localid);
368
            } 
369
            stmt.close();
370
        } 
371
        catch (SQLException e) 
372
        {
373
            logMetacat.error("Error while looking up the guid: " 
374
                    + e.getMessage());
375
        } 
376
        finally 
377
        {
378
            // Return database connection to the pool
379
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
380
        }
381
        
382
        return ids;
383
    }
384
    
385
    /**
386
     * return a listing of all local ids in the object store
387
     * @return a list of all local ids in metacat
388
     */
389
    public List<String> getAllLocalIds()
390
       throws Exception
391
    {
392
        Vector<String> ids = new Vector<String>();
393
        String sql = "select docid from xml_documents";
394
        DBConnection dbConn = null;
395
        int serialNumber = -1;
396
        try 
397
        {
398
            // Get a database connection from the pool
399
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getAllLocalIds");
400
            serialNumber = dbConn.getCheckOutSerialNumber();
401

    
402
            // Execute the insert statement
403
            PreparedStatement stmt = dbConn.prepareStatement(sql);
404
            ResultSet rs = stmt.executeQuery();
405
            while (rs.next()) 
406
            {
407
                String localid = rs.getString(1);
408
                ids.add(localid);
409
            } 
410
            stmt.close();
411
        } 
412
        catch (SQLException e) 
413
        {
414
            logMetacat.error("Error while looking up the guid: " 
415
                    + e.getMessage());
416
        } 
417
        finally 
418
        {
419
            // Return database connection to the pool
420
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
421
        }
422
        return ids;
423
    }
424
    
425
    /**
426
     * Lookup a GUID from the database, and return the associated LocalID. If
427
     * the identifier is not found, throw an exception.
428
     * 
429
     * @param guid the global identifier to look up
430
     * @return String containing the corresponding LocalId
431
     * @throws McdbDocNotFoundException if the identifier is not found
432
     */
433
    public String getLocalId(String guid) throws McdbDocNotFoundException
434
    {
435
        return this.getLocalId(guid, TYPE_IDENTIFIER);
436
    }
437
    
438
    /**
439
     * Determine if an identifier exists already, returning true if so.
440
     * 
441
     * @param guid the global identifier to look up
442
     * @return boolean true if the identifier exists
443
     */
444
    public boolean identifierExists(String guid)
445
    {
446
        boolean idExists = false;
447
        try {
448
            String id = getLocalId(guid);
449
            if (id != null) {
450
                idExists = true;
451
            }
452
        } catch (McdbDocNotFoundException e) {
453
            idExists = false;
454
        }
455
        return idExists;
456
    }
457
    
458
    /**
459
     * Create a mapping between two identifiers, one representing an 
460
     * unconstrained, globally unique string (guid), and one a localId 
461
     * in the Metacat docid format (scope.id.revision). 
462
     * This mapping allows one to find the global id (guid) from the localId.
463
     * 
464
     * @param guid the global string identifier to be mapped
465
     * @param localId the local identifier to be mapped
466
     */
467
    public void createMapping(String guid, String localId)
468
    {   
469
        createGenericMapping(guid, localId, TYPE_IDENTIFIER);
470
    }
471
    
472
    /**
473
     * 
474
     * @param guid
475
     * @param rev
476
     * @return
477
     */
478
    public String generateLocalId(String guid, int rev)
479
    {
480
        return generateLocalId(guid, rev, false);
481
    }
482

    
483
    /**
484
     * Given a global identifier (guid), create a suitable local identifier that
485
     * follows Metacat's docid semantics and format (scope.id.rev), and create
486
     * a mapping between these two identifiers.  This effectively reserves both
487
     * the global and the local identifier, as they will now be present in the
488
     * identifier mapping table.  If the incoming guid has the syntax of a
489
     * Metacat docid (scope.id.rev), then simply use it.
490
     * 
491
     * @param guid the global string identifier
492
     * @param rev the revision number to be used in the localId
493
     * @return String containing the localId to be used for Metacat operations
494
     */
495
    public String generateLocalId(String guid, int rev, boolean isSystemMetadata) 
496
    {
497
        String localId = "";
498
        boolean conformsToDocidFormat = false;
499
        
500
        // Check if the guid passed in is already in docid (scope.id.rev) format
501
        try {
502
            AccessionNumber acc = new AccessionNumber(guid, "NONE");
503
            if (new Integer(acc.getRev()).intValue() > 0) {
504
                conformsToDocidFormat = true;
505
            }
506
        } catch (NumberFormatException e) {
507
            // No action needed, simply detecting invalid AccessionNumbers
508
        } catch (AccessionNumberException e) {
509
            // No action needed, simply detecting invalid AccessionNumbers
510
        } catch (SQLException e) {
511
            // No action needed, simply detecting invalid AccessionNumbers
512
        }
513
        
514
        if (conformsToDocidFormat) {
515
            // if it conforms, use it for both guid and localId
516
            localId = guid;
517
        } else {
518
            // if not, then generate a new unique localId
519
            localId = DocumentUtil.generateDocumentId(rev);
520
        }
521
        
522
        // Register this new pair in the identifier mapping table
523
        System.out.println("creating mapping in generateLocalId");
524
        if(!isSystemMetadata)
525
        { //don't do this if we're generating for system metadata
526
            createMapping(guid, localId);
527
        }
528
        
529
        return localId;
530
    }
531
    
532
    /**
533
     * given a local identifer, look up the guid.  Throw McdbDocNotFoundException
534
     * if the docid, rev is not found in the identifiers or systemmetadata tables
535
     *
536
     * @param docid the docid to look up
537
     * @param rev the revision of the docid to look up
538
     * @return String containing the mapped guid
539
     * @throws McdbDocNotFoundException if the docid, rev is not found
540
     */
541
    public String getGUID(String docid, int rev)
542
      throws McdbDocNotFoundException
543
    {
544
        System.out.println("getting guid for " + docid);
545
        String query = "select guid from identifier where docid = ? and rev = ?";
546
        String guid = null;
547
        boolean found = false;
548
        
549
        DBConnection dbConn = null;
550
        int serialNumber = -1;
551
        try {
552
            // Get a database connection from the pool
553
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getGUID");
554
            serialNumber = dbConn.getCheckOutSerialNumber();
555
            
556
            // Execute the insert statement
557
            PreparedStatement stmt = dbConn.prepareStatement(query);
558
            stmt.setString(1, docid);
559
            stmt.setInt(2, rev);
560
            ResultSet rs = stmt.executeQuery();
561
            if (rs.next()) 
562
            {
563
                guid = rs.getString(1);
564
            } 
565
            else
566
            {
567
                query = "select guid from systemmetadata where docid = ? and rev = ?";
568
                stmt = dbConn.prepareStatement(query);
569
                stmt.setString(1, docid);
570
                stmt.setInt(2, rev);
571
                rs = stmt.executeQuery();
572
                if(rs.next())
573
                {
574
                    guid = rs.getString(1);
575
                }
576
                else
577
                {
578
                    throw new McdbDocNotFoundException("No guid registered for docid " + docid + "." + rev);
579
                }
580
            }
581
            
582
        } catch (SQLException e) {
583
            logMetacat.error("Error while looking up the guid: " 
584
                    + e.getMessage());
585
        } finally {
586
            // Return database connection to the pool
587
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
588
        }
589
        
590
        return guid;
591
    }
592
    
593
    /**
594
     * creates a mapping for a system metadata document, but DOES NOT add any
595
     * of the extra system metadata information to the table.  You must call 
596
     * insertAdditionalSystemMetadataFields to complete the entry
597
     * 
598
     * @param guid the id to insert
599
     * @param localId the systemMetadata object to get the local id for
600
     */
601
    public void createSystemMetadataMapping(String guid, String localId)
602
    {
603
        createGenericMapping(guid, localId, TYPE_SYSTEM_METADATA);
604
    }
605
    
606
    /**
607
     * creates a system metadata mapping and adds additional fields from sysmeta
608
     * to the table for quick searching.
609
     * 
610
     * @param guid the id to insert
611
     * @param localId the systemMetadata object to get the local id for
612
     */
613
    public void createSystemMetadataMapping(SystemMetadata sysmeta, String localId)
614
    {
615
        createGenericMapping(sysmeta.getIdentifier().getValue(), localId, TYPE_SYSTEM_METADATA);
616
        insertAdditionalSystemMetadataFields(sysmeta);
617
    }
618
    
619
    /**
620
     * update a mapping
621
     * @param guid
622
     * @param localId
623
     */
624
    public void updateSystemMetadataMapping(String guid, String localId)
625
    {
626
        int serialNumber = -1;
627
        DBConnection dbConn = null;
628
        try {
629
            // Parse the localId into scope and rev parts
630
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
631
            String docid = acc.getDocid();
632
            int rev = 1;
633
            if(acc.getRev() != null)
634
            {
635
              rev = (new Integer(acc.getRev()).intValue());
636
            }
637

    
638
            // Get a database connection from the pool
639
            dbConn = 
640
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
641
            serialNumber = dbConn.getCheckOutSerialNumber();
642

    
643
            // Execute the insert statement
644
            String query = "update systemmetadata set (docid, rev) = (?, ?) where guid='" + guid + "'";
645
            //System.out.println("query: " + query + " for params: (guid:" + guid + ", docid=" + docid + ", rev=" + rev + ")");
646
            PreparedStatement stmt = dbConn.prepareStatement(query);
647
            stmt.setString(1, docid);
648
            stmt.setInt(2, rev);
649
            int rows = stmt.executeUpdate();
650

    
651
            stmt.close();
652
        } catch (SQLException e) {
653
            e.printStackTrace();
654
            logMetacat.error("SQL error while updating a mapping to the system metadata identifier: " 
655
                    + e.getMessage());
656
        } catch (NumberFormatException e) {
657
            e.printStackTrace();
658
            logMetacat.error("NumberFormat error while updating a mapping to the system metadata identifier: " 
659
                    + e.getMessage());
660
        } catch (AccessionNumberException e) {
661
            e.printStackTrace();
662
            logMetacat.error("AccessionNumber error while updating a mapping to the system metadata identifier: " 
663
                    + e.getMessage());
664
        } finally {
665
            // Return database connection to the pool
666
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
667
        }
668
    }
669
    
670
    /**
671
     * return the localId of a system metadata document based on its guid
672
     */
673
    public String getSystemMetadataLocalId(String guid)
674
      throws McdbDocNotFoundException
675
    {
676
      return this.getLocalId(guid, TYPE_SYSTEM_METADATA);
677
    }
678
    
679
    public void insertAdditionalSystemMetadataFields(long dateUploaded, String rightsHolder,
680
            String checksum, String checksumAlgorithm, String originMemberNode,
681
            String authoritativeMemberNode, long modifiedDate, String submitter, String guid)
682
    {
683
        DBConnection dbConn = null;
684
        int serialNumber = -1;
685
        try {
686
            // Get a database connection from the pool
687
            dbConn = 
688
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
689
            serialNumber = dbConn.getCheckOutSerialNumber();
690

    
691
            // Execute the insert statement
692
            String query = "update " + TYPE_SYSTEM_METADATA + 
693
                " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
694
                "origin_member_node, authoritive_member_node, date_modified, submitter) " +
695
                "= (?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
696
            PreparedStatement stmt = dbConn.prepareStatement(query);
697
            
698
            //data values
699
            stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
700
            stmt.setString(2, rightsHolder);
701
            stmt.setString(3, checksum);
702
            stmt.setString(4, checksumAlgorithm);
703
            stmt.setString(5, originMemberNode);
704
            stmt.setString(6, authoritativeMemberNode);
705
            stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
706
            stmt.setString(8, submitter);
707
            //where clause
708
            stmt.setString(9, guid);
709
            System.out.println("stmt: " + stmt.toString());
710
            //execute
711
            int rows = stmt.executeUpdate();
712

    
713
            stmt.close();
714
        } catch (SQLException e) {
715
            e.printStackTrace();
716
            logMetacat.error("SQL error while creating a mapping to the system metadata identifier: " 
717
                    + e.getMessage());
718
        } catch (NumberFormatException e) {
719
            e.printStackTrace();
720
            logMetacat.error("NumberFormat error while creating a mapping to the system metadata identifier: " 
721
                    + e.getMessage());
722
        } finally {
723
            // Return database connection to the pool
724
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
725
        }
726
    }
727
    
728
    /**
729
     * Insert the system metadata fields into the db
730
     * @param sm
731
     */
732
    public void insertAdditionalSystemMetadataFields(SystemMetadata sm)
733
    {
734
        insertAdditionalSystemMetadataFields(
735
                sm.getDateUploaded().getTime(),
736
                sm.getRightsHolder().getValue(), 
737
                sm.getChecksum().getValue(), 
738
                sm.getChecksum().getAlgorithm().name(), 
739
                sm.getOriginMemberNode().getValue(),
740
                sm.getAuthoritativeMemberNode().getValue(), 
741
                sm.getDateSysMetadataModified().getTime(),
742
                sm.getSubmitter().getValue(), 
743
                sm.getIdentifier().getValue());
744
    }
745
    
746
    /**
747
     * return a localId based on a guid.  The type can either be 'identifier' 
748
     * to get an id from the identifier table or 'systemmetadata' to get
749
     * the identifier from the systemidentifier table
750
     */
751
    private String getLocalId(String guid, String type)
752
      throws McdbDocNotFoundException
753
    {
754
      if(!type.equals(TYPE_IDENTIFIER) &&
755
        !type.equals(TYPE_SYSTEM_METADATA))
756
      {
757
        throw new RuntimeException("cannot lookup the identifier for type " + type +
758
          ".  Please choose 'identifier' or 'systemmetadata'.");
759
      }
760
      
761
      String db_guid = "";
762
      String docid = "";
763
      int rev = 0;
764
      
765
      String query = "select guid, docid, rev from " + type + " where guid = ?";
766
      //System.out.println("query: " + query + " for params: (" + guid + ")");
767
      
768
      DBConnection dbConn = null;
769
      int serialNumber = -1;
770
      try {
771
          // Get a database connection from the pool
772
          dbConn = DBConnectionPool.getDBConnection("Identifier.getLocalId");
773
          serialNumber = dbConn.getCheckOutSerialNumber();
774
          
775
          // Execute the insert statement
776
          PreparedStatement stmt = dbConn.prepareStatement(query);
777
          stmt.setString(1, guid);
778
          ResultSet rs = stmt.executeQuery();
779
          if (rs.next()) {
780
              db_guid = rs.getString(1);
781
              docid = rs.getString(2);
782
              rev = rs.getInt(3);
783
              assert(db_guid.equals(guid));
784
          } else {
785
              throw new McdbDocNotFoundException("Document not found:" + guid);
786
          }
787
          stmt.close();
788
      } catch (SQLException e) {
789
          logMetacat.error("Error while looking up the local identifier: " 
790
                  + e.getMessage());
791
      } finally {
792
          // Return database connection to the pool
793
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
794
      }
795
      return docid + "." + rev;
796
    }
797
    
798
    /**
799
     * query the systemmetadata table based on the given parameters
800
     * @param startTime
801
     * @param endTime
802
     * @param objectFormat
803
     * @param replicaStatus
804
     * @param start
805
     * @param count
806
     * @return ObjectList
807
     */
808
    public ObjectList querySystemMetadata(Date startTime, Date endTime, 
809
            ObjectFormat objectFormat, boolean replicaStatus, int start, int count)
810
    {
811
        ObjectList ol = new ObjectList();
812
        int total = 0;
813
        
814
        try
815
        {
816
            String sql = "select guid, date_uploaded, rights_holder, checksum, " +
817
                "checksum_algorithm, origin_member_node, authoritive_member_node, " +
818
                "date_modified, submitter, xml_documents.doctype from systemmetadata, " +
819
                "xml_documents where xml_documents.docid in " +
820
                "(select docid from identifier where guid = systemmetadata.guid)";
821
            
822
            boolean f1 = false;
823
            boolean f2 = false;
824
            boolean f3 = false;
825
            
826
            if(startTime != null)
827
            {
828
                sql += " and systemmetadata.date_modified > ?";
829
                f1 = true;
830
            }
831
            
832
            if(endTime != null)
833
            {
834
                sql += " and systemmetadata.date_modified < ?";
835
                f2 = true;
836
            }
837
            
838
            if(objectFormat != null)
839
            {
840
                sql += " and xml_documents.doctype = ?";
841
                f3 = true;
842
            }
843
            
844
            if(replicaStatus)
845
            {
846
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.memberNodeId");
847
                sql += " and authoritive_member_node != '" + currentNodeId.trim() + "'";
848
            }
849
            
850
            DBConnection dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
851
            int serialNumber = dbConn.getCheckOutSerialNumber();
852
            PreparedStatement stmt = dbConn.prepareStatement(sql);
853
            
854
            if(f1 && f2 && f3)
855
            {
856
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
857
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
858
                stmt.setString(3, objectFormat.toString());
859
            }
860
            else if(f1 && f2 && !f3)
861
            {
862
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
863
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
864
            }
865
            else if(f1 && !f2 && f3)
866
            {
867
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
868
                stmt.setString(2, objectFormat.toString());
869
            }
870
            else if(f1 && !f2 && !f3)
871
            {
872
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
873
            }
874
            else if(!f1 && f2 && f3)
875
            {
876
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
877
                stmt.setString(2, objectFormat.toString());
878
            }
879
            else if(!f1 && !f2 && f3)
880
            {
881
                stmt.setString(1, objectFormat.toString());
882
            }
883
            else if(!f1 && f2 && !f3)
884
            {
885
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
886
            }
887
            
888
            //System.out.println("LISTOBJECTS QUERY: " + stmt.toString());
889
            
890
            ResultSet rs = stmt.executeQuery();
891
            for(int i=0; i<start - 1; i++)
892
            {
893
                rs.next();
894
            }
895
            int countIndex = 0;
896
                        
897
            while(rs.next()) 
898
            {
899
                total++;
900
                if(countIndex >= count)
901
                {
902
                    break;
903
                }
904
                String guid = rs.getString(1);
905
                //System.out.println("query found doc with guid " + guid);
906
                //Timestamp dateUploaded = rs.getTimestamp(2);
907
                //String rightsHolder = rs.getString(3);
908
                String checksum = rs.getString(4);
909
                String checksumAlgorithm = rs.getString(5);
910
                //String originMemberNode = rs.getString(6);
911
                String authoritiveMemberNode = rs.getString(7);
912
                Timestamp dateModified = rs.getTimestamp(8);
913
                //String submitter = rs.getString(9);
914
                String format = rs.getString(10);
915
                
916
                ObjectInfo oi = new ObjectInfo();
917
                
918
                Identifier id = new Identifier();
919
                id.setValue(guid);
920
                oi.setIdentifier(id);
921
                
922
                oi.setDateSysMetadataModified(new Date(dateModified.getTime()));
923
                
924
                Checksum cs = new Checksum();
925
                cs.setValue(checksum);
926
                cs.setAlgorithm(ChecksumAlgorithm.convert(checksumAlgorithm));
927
                oi.setChecksum(cs);
928
                
929
                ObjectFormat oFormat = ObjectFormat.convert(format);
930
                if(oFormat != null)
931
                {
932
                    oi.setObjectFormat(oFormat);
933
                }
934
                
935
                ol.addObjectInfo(oi);
936
                countIndex++;
937
            }
938
            
939
            while(rs.next())
940
            { //expend the resultset to get the total count of possible rows
941
                total++;
942
            }
943
        }
944
        catch(Exception e)
945
        {
946
           e.printStackTrace();
947
           System.out.println("Error querying system metadata: " + e.getMessage());
948
        }
949
        
950
        System.out.println("listObjects total: " + total);
951
        ol.setStart(start);
952
        ol.setCount(count);
953
        ol.setTotal(total);
954
        
955
        return ol;
956
    }
957
    
958
    /**
959
     * create a mapping in the systemmetadata or identifier table
960
     * @param guid
961
     * @param localId
962
     * @param type
963
     */
964
    private void createGenericMapping(String guid, String localId, String type)
965
    {        
966
        if(!type.equals(TYPE_IDENTIFIER) &&
967
        !type.equals(TYPE_SYSTEM_METADATA))
968
        {
969
          throw new RuntimeException("Cannot create mapping for type " + type +
970
            ".  Please choose 'identifier' or 'systemmetadata'.");
971
        }
972
        
973
        int serialNumber = -1;
974
        DBConnection dbConn = null;
975
        try {
976

    
977
            // Parse the localId into scope and rev parts
978
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
979
            String docid = acc.getDocid();
980
            int rev = 1;
981
            if(acc.getRev() != null)
982
            {
983
              rev = (new Integer(acc.getRev()).intValue());
984
            }
985

    
986
            // Get a database connection from the pool
987
            dbConn = 
988
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
989
            serialNumber = dbConn.getCheckOutSerialNumber();
990

    
991
            // Execute the insert statement
992
            String query = "insert into " + type + " (guid, docid, rev) values (?, ?, ?)";
993
            //System.out.println("query: " + query + " for params: (" + guid + ", " + docid + ", " + rev + ")");
994
            PreparedStatement stmt = dbConn.prepareStatement(query);
995
            stmt.setString(1, guid);
996
            stmt.setString(2, docid);
997
            stmt.setInt(3, rev);
998
            System.out.println("generic mapping query: " + stmt.toString());
999
            int rows = stmt.executeUpdate();
1000

    
1001
            stmt.close();
1002
        } catch (SQLException e) {
1003
            e.printStackTrace();
1004
            logMetacat.warn("SQL error while creating a mapping to the system metadata identifier: " 
1005
                    + e.getMessage());
1006
        } catch (NumberFormatException e) {
1007
            e.printStackTrace();
1008
            logMetacat.error("NumberFormat error while creating a mapping to the system metadata identifier: " 
1009
                    + e.getMessage());
1010
        } catch (AccessionNumberException e) {
1011
            e.printStackTrace();
1012
            logMetacat.error("AccessionNumber error while creating a mapping to the system metadata identifier: " 
1013
                    + e.getMessage());
1014
        } finally {
1015
            // Return database connection to the pool
1016
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1017
        }
1018
    }
1019
}
1020

    
(37-37/65)