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, authoritive_member_node, date_modified, submitter, object_format, size " +
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
                String objectFormat = rs.getString(10);
148
                long size = new Long(rs.getString(11)).longValue();
149
                
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
                h.put("object_format", objectFormat);
160
                h.put("size", new Long(size).toString());
161
                
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
     * 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
    public Hashtable<String, Object> getDocumentInfo(String localId)
195
        throws McdbDocNotFoundException
196
    {
197
        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
        Hashtable<String, Object> h = new Hashtable<String, Object>();
207
        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
                h.put("docid", localId);
232
                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
                throw new McdbDocNotFoundException("2Could not find document " + localId);
248
            }
249
            
250
            String sql2 = "select principal_name, permission, perm_type, perm_order from xml_access " +
251
            "where docid like '" + localId + "'";
252
            System.out.println("executing sql: " + sql2);
253
            PreparedStatement stmt2 = dbConn.prepareStatement(sql2);
254
            rs = stmt2.executeQuery();
255
            Vector accessVector = new Vector();
256
            while(rs.next())
257
            {
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
                System.out.println("accessHash: " + accessHash.toString());
268
                accessVector.add(accessHash);
269
            }
270
            h.put("access", accessVector);
271
        } 
272
        catch (SQLException e) 
273
        {
274
            e.printStackTrace();
275
            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
        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
        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
                throw new McdbDocNotFoundException("While trying to get the latest rev, could not find document " + localId);
326
            }
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
     * 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
        //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
        String sql = "select docid, rev from xml_documents where docid not in " +
353
            "(select docid from systemmetadata) and (docid not in " +
354
            "(select docid from identifier where guid in (select guid from systemmetadata)))";
355
        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
                String rev = rs.getString(2);
370
                localid += "." + rev;
371
                System.out.println("id to add SM for: " + localid);
372
                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
     * 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
        return this.getLocalId(guid, TYPE_IDENTIFIER);
441
    }
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
        createGenericMapping(guid, localId, TYPE_IDENTIFIER);
475
    }
476
    
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

    
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
    public String generateLocalId(String guid, int rev, boolean isSystemMetadata) 
501
    {
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
        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
        
534
        return localId;
535
    }
536
    
537
    /**
538
     * given a local identifer, look up the guid.  Throw McdbDocNotFoundException
539
     * if the docid, rev is not found in the identifiers or systemmetadata tables
540
     *
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
        System.out.println("getting guid for " + docid);
550
        String query = "select guid from identifier where docid = ? and rev = ?";
551
        String guid = null;
552
        boolean found = false;
553
        
554
        DBConnection dbConn = null;
555
        int serialNumber = -1;
556
        try {
557
            // Get a database connection from the pool
558
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getGUID");
559
            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
            if (rs.next()) 
567
            {
568
                guid = rs.getString(1);
569
            } 
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
                rs = stmt.executeQuery();
577
                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
            }
586
            
587
        } 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
    
598
    /**
599
     * 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
     * 
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
        createGenericMapping(guid, localId, TYPE_SYSTEM_METADATA);
609
    }
610
    
611
    /**
612
     * 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
     * update a mapping
626
     * @param guid
627
     * @param localId
628
     */
629
    public void updateSystemMetadataMapping(String guid, String localId)
630
    {
631
        System.out.println("$$$$$$$$$$$$$$ updating systemmetadata table with additional info");
632
        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
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
647
            serialNumber = dbConn.getCheckOutSerialNumber();
648

    
649
            // Execute the insert statement
650
            String query = "update systemmetadata set (docid, rev) = (?, ?) where guid='" + guid + "'";
651
            //System.out.println("query: " + query + " for params: (guid:" + guid + ", docid=" + docid + ", rev=" + rev + ")");
652
            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
        System.out.println("done updating systemmetadata");
675
    }
676
    
677
    /**
678
     * return the localId of a system metadata document based on its guid
679
     */
680
    public String getSystemMetadataLocalId(String guid)
681
      throws McdbDocNotFoundException
682
    {
683
      return this.getLocalId(guid, TYPE_SYSTEM_METADATA);
684
    }
685
    
686
    public void insertAdditionalSystemMetadataFields(long dateUploaded, String rightsHolder,
687
            String checksum, String checksumAlgorithm, String originMemberNode,
688
            String authoritativeMemberNode, long modifiedDate, String submitter, 
689
            String guid, String objectFormat, long size)
690
    {
691
        DBConnection dbConn = null;
692
        int serialNumber = -1;
693
        
694
        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
                "origin_member_node, authoritive_member_node, date_modified, " +
704
                "submitter, object_format, size) " +
705
                "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
706
            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
            stmt.setString(9, objectFormat);
718
            stmt.setString(10, new Long(size).toString());
719
            //where clause
720
            stmt.setString(11, guid);
721
            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
            logMetacat.error("insertAdditionalSystemMetadataFields: SQL error while creating a mapping to the system metadata identifier: " 
729
                    + e.getMessage());
730
        } catch (NumberFormatException e) {
731
            e.printStackTrace();
732
            logMetacat.error("insertAdditionalSystemMetadataFields: NumberFormat error while creating a mapping to the system metadata identifier: " 
733
                    + e.getMessage());
734
        } finally {
735
            // Return database connection to the pool
736
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
737
        }
738
    }
739
    
740
    /**
741
     * 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
                sm.getIdentifier().getValue(),
756
                sm.getObjectFormat().toString(),
757
                sm.getSize());
758
    }
759
    
760
    /**
761
     * 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
    private String getLocalId(String guid, String type)
766
      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
      //System.out.println("query: " + query + " for params: (" + guid + ")");
781
      
782
      DBConnection dbConn = null;
783
      int serialNumber = -1;
784
      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
    /**
813
     * 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
        DBConnection dbConn = null;
828
        int serialNumber = -1;
829
        
830
        try
831
        {
832
            String sql = "select guid, date_uploaded, rights_holder, checksum, " +
833
                "checksum_algorithm, origin_member_node, authoritive_member_node, " +
834
                "date_modified, submitter, object_format, size from systemmetadata";
835
            
836
            boolean f1 = false;
837
            boolean f2 = false;
838
            boolean f3 = false;
839
            
840
            if(startTime != null)
841
            {
842
                sql += " where systemmetadata.date_modified > ?";
843
                f1 = true;
844
            }
845
            
846
            if(endTime != null)
847
            {
848
                if(!f1)
849
                {
850
                    sql += " where systemmetadata.date_modified < ?";
851
                }
852
                else
853
                {
854
                    sql += " and systemmetadata.date_modified < ?";
855
                }
856
                f2 = true;
857
            }
858
            
859
            if(objectFormat != null)
860
            {
861
                if(!f1 && !f2)
862
                {
863
                    sql += " where object_format = ?";
864
                }
865
                else 
866
                {
867
                    sql += " and object_format = ?";
868
                }
869
                f3 = true;
870
            }
871
            
872
            if(replicaStatus)
873
            {
874
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.memberNodeId");
875
                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
            }
884
            
885
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.querySystemMetadata");
886
            serialNumber = dbConn.getCheckOutSerialNumber();
887
            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
            for(int i=0; i<start; i++)
927
            {
928
                if(rs.next())
929
                {
930
                    total++;
931
                }
932
                else
933
                {
934
                    break;
935
                }
936
            }
937
            
938
            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
                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
                
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
                cs.setAlgorithm(ChecksumAlgorithm.valueOf(checksumAlgorithm));
976
                //cs.setAlgorithm(ChecksumAlgorithm.convert(checksumAlgorithm));
977
                oi.setChecksum(cs);
978
                
979
                ObjectFormat oFormat = ObjectFormat.convert(format);
980
                if(oFormat != null)
981
                {
982
                    oi.setObjectFormat(oFormat);
983
                }
984
                else
985
                { //if there is no object format, just default to text/plain
986
                    oi.setObjectFormat(ObjectFormat.OCTET_STREAM);
987
                }
988
                                
989
                oi.setSize(size);
990
                
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
        finally 
1006
        {
1007
            // Return database connection to the pool
1008
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1009
        }
1010
        
1011
        ol.setStart(start);
1012
        ol.setCount(ol.sizeObjectInfoList());
1013
        ol.setTotal(total);
1014
        
1015
        return ol;
1016
    }
1017
    
1018
    /**
1019
     * create a mapping in the systemmetadata or identifier table
1020
     * @param guid
1021
     * @param localId
1022
     * @param type
1023
     */
1024
    private void createGenericMapping(String guid, String localId, String type)
1025
    {        
1026
        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
        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
            int rev = 1;
1041
            if(acc.getRev() != null)
1042
            {
1043
              rev = (new Integer(acc.getRev()).intValue());
1044
            }
1045

    
1046
            // Get a database connection from the pool
1047
            dbConn = 
1048
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1049
            serialNumber = dbConn.getCheckOutSerialNumber();
1050

    
1051
            // Execute the insert statement
1052
            String query = "insert into " + type + " (guid, docid, rev) values (?, ?, ?)";
1053
            //System.out.println("query: " + query + " for params: (" + guid + ", " + docid + ", " + rev + ")");
1054
            PreparedStatement stmt = dbConn.prepareStatement(query);
1055
            stmt.setString(1, guid);
1056
            stmt.setString(2, docid);
1057
            stmt.setInt(3, rev);
1058
            System.out.println("generic mapping query: " + stmt.toString());
1059
            int rows = stmt.executeUpdate();
1060

    
1061
            stmt.close();
1062
        } catch (SQLException e) {
1063
            e.printStackTrace();
1064
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + type + " identifier: " 
1065
                    + e.getMessage());
1066
        } catch (NumberFormatException e) {
1067
            e.printStackTrace();
1068
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + type + " identifier: " 
1069
                    + e.getMessage());
1070
        } catch (AccessionNumberException e) {
1071
            e.printStackTrace();
1072
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + type + " identifier: " 
1073
                    + e.getMessage());
1074
        } finally {
1075
            // Return database connection to the pool
1076
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1077
        }
1078
    }
1079
}
1080

    
(37-37/65)