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 system metadata mapping
626
     * @param guid
627
     * @param localId
628
     */
629
    public void updateSystemMetadataMapping(String guid, String localId)
630
    {
631
    	updateMapping(guid, localId, TYPE_SYSTEM_METADATA);
632
    }
633
    
634
    /**
635
     * update a mapping
636
     * @param guid
637
     * @param localId
638
     */
639
    public void updateMapping(String guid, String localId)
640
    {
641
    	updateMapping(guid, localId, TYPE_IDENTIFIER);
642
    }
643
    
644
    /**
645
     * update a mapping
646
     * @param guid
647
     * @param localId
648
     */
649
    private void updateMapping(String guid, String localId, String type)
650
    {
651
    	if (!type.equals(TYPE_IDENTIFIER) && !type.equals(TYPE_SYSTEM_METADATA)) {
652
    		throw new RuntimeException("Cannot create mapping for type " + type +
653
    		            ".  Please choose 'identifier' or 'systemmetadata'.");
654
    	}
655
    	
656
        System.out.println("$$$$$$$$$$$$$$ updating mapping table");
657
        int serialNumber = -1;
658
        DBConnection dbConn = null;
659
        try {
660
            // Parse the localId into scope and rev parts
661
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
662
            String docid = acc.getDocid();
663
            int rev = 1;
664
            if(acc.getRev() != null)
665
            {
666
              rev = (new Integer(acc.getRev()).intValue());
667
            }
668

    
669
            // Get a database connection from the pool
670
            dbConn = 
671
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
672
            serialNumber = dbConn.getCheckOutSerialNumber();
673

    
674
            // Execute the insert statement
675
            String query = "update " + type + " set (docid, rev) = (?, ?) where guid='" + guid + "'";
676
            //System.out.println("query: " + query + " for params: (guid:" + guid + ", docid=" + docid + ", rev=" + rev + ")");
677
            PreparedStatement stmt = dbConn.prepareStatement(query);
678
            stmt.setString(1, docid);
679
            stmt.setInt(2, rev);
680
            int rows = stmt.executeUpdate();
681

    
682
            stmt.close();
683
        } catch (SQLException e) {
684
            e.printStackTrace();
685
            logMetacat.error("SQL error while updating a mapping identifier: " 
686
                    + e.getMessage());
687
        } catch (NumberFormatException e) {
688
            e.printStackTrace();
689
            logMetacat.error("NumberFormat error while updating a mapping identifier: " 
690
                    + e.getMessage());
691
        } catch (AccessionNumberException e) {
692
            e.printStackTrace();
693
            logMetacat.error("AccessionNumber error while updating a mapping identifier: " 
694
                    + e.getMessage());
695
        } finally {
696
            // Return database connection to the pool
697
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
698
        }
699
        System.out.println("done updating mapping");
700
    }
701
    
702
    /**
703
     * return the localId of a system metadata document based on its guid
704
     */
705
    public String getSystemMetadataLocalId(String guid)
706
      throws McdbDocNotFoundException
707
    {
708
      return this.getLocalId(guid, TYPE_SYSTEM_METADATA);
709
    }
710
    
711
    public void insertAdditionalSystemMetadataFields(long dateUploaded, String rightsHolder,
712
            String checksum, String checksumAlgorithm, String originMemberNode,
713
            String authoritativeMemberNode, long modifiedDate, String submitter, 
714
            String guid, String objectFormat, long size)
715
    {
716
        DBConnection dbConn = null;
717
        int serialNumber = -1;
718
        
719
        try {
720
            // Get a database connection from the pool
721
            dbConn = 
722
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
723
            serialNumber = dbConn.getCheckOutSerialNumber();
724

    
725
            // Execute the insert statement
726
            String query = "update " + TYPE_SYSTEM_METADATA + 
727
                " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
728
                "origin_member_node, authoritive_member_node, date_modified, " +
729
                "submitter, object_format, size) " +
730
                "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
731
            PreparedStatement stmt = dbConn.prepareStatement(query);
732
            
733
            //data values
734
            stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
735
            stmt.setString(2, rightsHolder);
736
            stmt.setString(3, checksum);
737
            stmt.setString(4, checksumAlgorithm);
738
            stmt.setString(5, originMemberNode);
739
            stmt.setString(6, authoritativeMemberNode);
740
            stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
741
            stmt.setString(8, submitter);
742
            stmt.setString(9, objectFormat);
743
            stmt.setString(10, new Long(size).toString());
744
            //where clause
745
            stmt.setString(11, guid);
746
            System.out.println("stmt: " + stmt.toString());
747
            //execute
748
            int rows = stmt.executeUpdate();
749

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

    
1062
            // Parse the localId into scope and rev parts
1063
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1064
            String docid = acc.getDocid();
1065
            int rev = 1;
1066
            if(acc.getRev() != null)
1067
            {
1068
              rev = (new Integer(acc.getRev()).intValue());
1069
            }
1070

    
1071
            // Get a database connection from the pool
1072
            dbConn = 
1073
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1074
            serialNumber = dbConn.getCheckOutSerialNumber();
1075

    
1076
            // Execute the insert statement
1077
            String query = "insert into " + type + " (guid, docid, rev) values (?, ?, ?)";
1078
            //System.out.println("query: " + query + " for params: (" + guid + ", " + docid + ", " + rev + ")");
1079
            PreparedStatement stmt = dbConn.prepareStatement(query);
1080
            stmt.setString(1, guid);
1081
            stmt.setString(2, docid);
1082
            stmt.setInt(3, rev);
1083
            System.out.println("generic mapping query: " + stmt.toString());
1084
            int rows = stmt.executeUpdate();
1085

    
1086
            stmt.close();
1087
        } catch (SQLException e) {
1088
            e.printStackTrace();
1089
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + type + " identifier: " 
1090
                    + e.getMessage());
1091
        } catch (NumberFormatException e) {
1092
            e.printStackTrace();
1093
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + type + " identifier: " 
1094
                    + e.getMessage());
1095
        } catch (AccessionNumberException e) {
1096
            e.printStackTrace();
1097
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + type + " identifier: " 
1098
                    + e.getMessage());
1099
        } finally {
1100
            // Return database connection to the pool
1101
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1102
        }
1103
    }
1104
}
1105

    
(37-37/65)