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

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

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

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

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

    
643
            // Get a database connection from the pool
644
            dbConn = 
645
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
646
            serialNumber = dbConn.getCheckOutSerialNumber();
647

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

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

    
699
            // Execute the insert statement
700
            String query = "update " + TYPE_SYSTEM_METADATA + 
701
                " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
702
                "origin_member_node, authoritive_member_node, date_modified, " +
703
                "submitter, object_format, size) " +
704
                "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
705
            PreparedStatement stmt = dbConn.prepareStatement(query);
706
            
707
            //data values
708
            stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
709
            stmt.setString(2, rightsHolder);
710
            stmt.setString(3, checksum);
711
            stmt.setString(4, checksumAlgorithm);
712
            stmt.setString(5, originMemberNode);
713
            stmt.setString(6, authoritativeMemberNode);
714
            stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
715
            stmt.setString(8, submitter);
716
            stmt.setString(9, objectFormat);
717
            stmt.setString(10, new Long(size).toString());
718
            //where clause
719
            stmt.setString(11, guid);
720
            System.out.println("stmt: " + stmt.toString());
721
            //execute
722
            int rows = stmt.executeUpdate();
723

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

    
1036
            // Parse the localId into scope and rev parts
1037
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1038
            String docid = acc.getDocid();
1039
            int rev = 1;
1040
            if(acc.getRev() != null)
1041
            {
1042
              rev = (new Integer(acc.getRev()).intValue());
1043
            }
1044

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

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

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

    
(37-37/65)