Project

General

Profile

1 5282 jones
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2010 Regents of the University of California and the
4
 *             National Center for Ecological Analysis and Synthesis
5
 *
6
 *   '$Author: jones $'
7
 *     '$Date: 2010-02-03 17:58:12 -0900 (Wed, 03 Feb 2010) $'
8
 * '$Revision: 5211 $'
9
 *
10
 * This program is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation; either version 2 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program; if not, write to the Free Software
22
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
 */
24
25
package edu.ucsb.nceas.metacat;
26
27 5377 berkley
import java.util.*;
28
29 5282 jones
import java.sql.PreparedStatement;
30
import java.sql.ResultSet;
31
import java.sql.SQLException;
32 5895 berkley
import java.sql.Timestamp;
33 5282 jones
34
import org.apache.log4j.Logger;
35 5895 berkley
import org.dataone.service.types.Checksum;
36
import org.dataone.service.types.ChecksumAlgorithm;
37
import org.dataone.service.types.ObjectFormat;
38
import org.dataone.service.types.ObjectInfo;
39
import org.dataone.service.types.ObjectList;
40 5887 berkley
import org.dataone.service.types.SystemMetadata;
41 5895 berkley
import org.dataone.service.types.Identifier;
42 5282 jones
43
import edu.ucsb.nceas.metacat.database.DBConnection;
44
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
45 5887 berkley
import edu.ucsb.nceas.metacat.properties.PropertyService;
46 5895 berkley
import edu.ucsb.nceas.metacat.shared.ServiceException;
47 5286 jones
import edu.ucsb.nceas.metacat.util.DocumentUtil;
48 5895 berkley
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
49 5282 jones
50
/**
51
 * Manage the relationship between Metacat local identifiers (LocalIDs) that are
52
 * codified as the (docid, rev) pair with globally uniqe string identifiers
53
 * (GUIDs) that are opaque strings.  This class provides methods to manage these
54
 * identifiers, and to search for and look up LocalIDs based on their GUID and
55
 * vice versa. IdentifierManager is a singleton.
56
 *
57
 * @author Matthew Jones
58
 */
59
public class IdentifierManager {
60
61 5334 berkley
    public static final String TYPE_SYSTEM_METADATA = "systemmetadata";
62
    public static final String TYPE_IDENTIFIER = "identifier";
63 5887 berkley
    public static String DATAONE_SM_DOCTYPE;
64 5334 berkley
65 5282 jones
    /**
66
     * The single instance of the manager that is always returned.
67
     */
68
    private static IdentifierManager self = null;
69
    private Logger logMetacat = Logger.getLogger(EventLog.class);
70
71
    /**
72
     * A private constructor that initializes the class when getInstance() is
73
     * called.
74
     */
75
    private IdentifierManager()
76
    {
77 5887 berkley
        try
78
        {
79
            DATAONE_SM_DOCTYPE = PropertyService.getProperty("crudService.listObjects.ReturnDoctype");
80
        }
81
        catch(Exception e)
82
        {
83
            throw new RuntimeException("Error getting System Metadata doctype from " +
84
                    "the properties file.  Please make sure crudService.listObjects.ReturnDoctype " +
85
                    "exists in metacat.properties.");
86
        }
87 5282 jones
    }
88
89
    /**
90
     * Return the single instance of the manager after initializing it if it
91
     * wasn't previously initialized.
92
     *
93
     * @return the single IdentifierManager instance
94
     */
95
    public static IdentifierManager getInstance()
96
    {
97
        if (self == null) {
98
            self = new IdentifierManager();
99
        }
100
        return self;
101
    }
102
103
    /**
104 5895 berkley
     * return a hash of all of the info that is in the systemmetadata table
105
     * @param localId
106
     * @return
107
     */
108
    public Hashtable<String, String> getSystemMetadataInfo(String localId)
109
    throws McdbDocNotFoundException
110
    {
111
        try
112
        {
113
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
114
            localId = acc.getDocid();
115
        }
116
        catch(Exception e)
117
        {
118
            //do nothing. just try the localId as it is
119
        }
120
        Hashtable<String, String> h = new Hashtable<String, String>();
121
        String sql = "select guid, date_uploaded, rights_holder, checksum, checksum_algorithm, " +
122 5944 berkley
          "origin_member_node, authoritive_member_node, date_modified, submitter, object_format, size " +
123 5895 berkley
          "from systemmetadata where docid = ?";
124
        DBConnection dbConn = null;
125
        int serialNumber = -1;
126
        try
127
        {
128
            // Get a database connection from the pool
129
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getDocumentInfo");
130
            serialNumber = dbConn.getCheckOutSerialNumber();
131
132
            // Execute the insert statement
133
            PreparedStatement stmt = dbConn.prepareStatement(sql);
134
            stmt.setString(1, localId);
135
            ResultSet rs = stmt.executeQuery();
136
            if (rs.next())
137
            {
138
                String guid = rs.getString(1);
139
                Timestamp dateUploaded = rs.getTimestamp(2);
140
                String rightsHolder = rs.getString(3);
141
                String checksum = rs.getString(4);
142
                String checksumAlgorithm = rs.getString(5);
143
                String originMemberNode = rs.getString(6);
144
                String authoritativeMemberNode = rs.getString(7);
145
                Timestamp dateModified = rs.getTimestamp(8);
146
                String submitter = rs.getString(9);
147 5917 berkley
                String objectFormat = rs.getString(10);
148
                long size = new Long(rs.getString(11)).longValue();
149 5895 berkley
150
                h.put("guid", guid);
151
                h.put("date_uploaded", new Long(dateUploaded.getTime()).toString());
152
                h.put("rights_holder", rightsHolder);
153
                h.put("checksum", checksum);
154
                h.put("checksum_algorithm", checksumAlgorithm);
155
                h.put("origin_member_node", originMemberNode);
156
                h.put("authoritative_member_node", authoritativeMemberNode);
157
                h.put("date_modified", new Long(dateModified.getTime()).toString());
158
                h.put("submitter", submitter);
159 5917 berkley
                h.put("object_format", objectFormat);
160
                h.put("size", new Long(size).toString());
161 5895 berkley
162
                stmt.close();
163
            }
164
            else
165
            {
166
                stmt.close();
167
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
168
                throw new McdbDocNotFoundException("2Could not find document " + localId);
169
            }
170
171
        }
172
        catch (SQLException e)
173
        {
174
            e.printStackTrace();
175
            logMetacat.error("Error while getting system metadata info for localid " + localId + " : "
176
                    + e.getMessage());
177
        }
178
        finally
179
        {
180
            // Return database connection to the pool
181
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
182
        }
183
        return h;
184
    }
185
186
    /**
187 5378 berkley
     * return information on the document with localId.  These are the fields
188
     * from the xml_documents table.  They can be used to contstruct metadata
189
     * about the object that is stored.
190
     * @param localId
191
     * @return
192
     * @throws McdbDocNotFoundException
193
     */
194 5441 berkley
    public Hashtable<String, Object> getDocumentInfo(String localId)
195 5378 berkley
        throws McdbDocNotFoundException
196
    {
197 5798 berkley
        try
198
        {
199
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
200
            localId = acc.getDocid();
201
        }
202
        catch(Exception e)
203
        {
204
            //do nothing. just try the localId as it is
205
        }
206 5441 berkley
        Hashtable<String, Object> h = new Hashtable<String, Object>();
207 5378 berkley
        String sql = "select docname, doctype, user_owner, user_updated, " +
208
            "server_location, rev, date_created, date_updated from " +
209
            "xml_documents where docid like '" + localId + "'";
210
        DBConnection dbConn = null;
211
        int serialNumber = -1;
212
        try
213
        {
214
            // Get a database connection from the pool
215
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getDocumentInfo");
216
            serialNumber = dbConn.getCheckOutSerialNumber();
217
218
            // Execute the insert statement
219
            PreparedStatement stmt = dbConn.prepareStatement(sql);
220
            ResultSet rs = stmt.executeQuery();
221
            if (rs.next())
222
            {
223
                String docname = rs.getString(1);
224
                String doctype = rs.getString(2);
225
                String user_owner = rs.getString(3);
226
                String user_updated = rs.getString(4);
227
                String server_location = rs.getString(5);
228
                int rev = rs.getInt(6);
229
                String date_created = rs.getString(7);
230
                String date_updated = rs.getString(8);
231
                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 5798 berkley
                throw new McdbDocNotFoundException("2Could not find document " + localId);
247 5378 berkley
            }
248 5441 berkley
249 5444 berkley
            String sql2 = "select principal_name, permission, perm_type, perm_order from xml_access " +
250 5441 berkley
            "where docid like '" + localId + "'";
251 5444 berkley
            System.out.println("executing sql: " + sql2);
252 5441 berkley
            PreparedStatement stmt2 = dbConn.prepareStatement(sql2);
253 5442 berkley
            rs = stmt2.executeQuery();
254 5441 berkley
            Vector accessVector = new Vector();
255 5445 berkley
            while(rs.next())
256 5441 berkley
            {
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 5444 berkley
                System.out.println("accessHash: " + accessHash.toString());
267 5441 berkley
                accessVector.add(accessHash);
268
            }
269
            h.put("access", accessVector);
270 5378 berkley
        }
271
        catch (SQLException e)
272
        {
273 5444 berkley
            e.printStackTrace();
274 5378 berkley
            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 5798 berkley
        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 5378 berkley
        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 5798 berkley
                throw new McdbDocNotFoundException("While trying to get the latest rev, could not find document " + localId);
325 5378 berkley
            }
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 5377 berkley
     * 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 5796 berkley
        //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 5798 berkley
        String sql = "select docid, rev from xml_documents where docid not in " +
352 5796 berkley
            "(select docid from systemmetadata) and (docid not in " +
353
            "(select docid from identifier where guid in (select guid from systemmetadata)))";
354 5377 berkley
        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 5798 berkley
                String rev = rs.getString(2);
369
                localid += "." + rev;
370 5796 berkley
                System.out.println("id to add SM for: " + localid);
371 5377 berkley
                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 5282 jones
     * 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 5424 berkley
        return this.getLocalId(guid, TYPE_IDENTIFIER);
440 5282 jones
    }
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 5334 berkley
        createGenericMapping(guid, localId, TYPE_IDENTIFIER);
474 5282 jones
    }
475 5453 berkley
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 5286 jones
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 5453 berkley
    public String generateLocalId(String guid, int rev, boolean isSystemMetadata)
500 5286 jones
    {
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 5453 berkley
        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 5286 jones
533
        return localId;
534
    }
535 5322 berkley
536
    /**
537
     * given a local identifer, look up the guid.  Throw McdbDocNotFoundException
538 5452 berkley
     * if the docid, rev is not found in the identifiers or systemmetadata tables
539 5322 berkley
     *
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 5798 berkley
        System.out.println("getting guid for " + docid);
549 5322 berkley
        String query = "select guid from identifier where docid = ? and rev = ?";
550
        String guid = null;
551 5451 berkley
        boolean found = false;
552 5322 berkley
553
        DBConnection dbConn = null;
554
        int serialNumber = -1;
555
        try {
556
            // Get a database connection from the pool
557 5377 berkley
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getGUID");
558 5322 berkley
            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 5451 berkley
            if (rs.next())
566
            {
567 5322 berkley
                guid = rs.getString(1);
568 5451 berkley
            }
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 5452 berkley
                rs = stmt.executeQuery();
576 5451 berkley
                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 5322 berkley
            }
585 5451 berkley
586 5322 berkley
        } 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 5333 berkley
597
    /**
598 5887 berkley
     * 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 5333 berkley
     *
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 5334 berkley
        createGenericMapping(guid, localId, TYPE_SYSTEM_METADATA);
608
    }
609
610 5377 berkley
    /**
611 5887 berkley
     * 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 5377 berkley
     * update a mapping
625
     * @param guid
626
     * @param localId
627
     */
628 5350 berkley
    public void updateSystemMetadataMapping(String guid, String localId)
629
    {
630
        int serialNumber = -1;
631
        DBConnection dbConn = null;
632
        try {
633
            // Parse the localId into scope and rev parts
634
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
635
            String docid = acc.getDocid();
636
            int rev = 1;
637
            if(acc.getRev() != null)
638
            {
639
              rev = (new Integer(acc.getRev()).intValue());
640
            }
641
642
            // Get a database connection from the pool
643
            dbConn =
644 5377 berkley
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
645 5350 berkley
            serialNumber = dbConn.getCheckOutSerialNumber();
646
647
            // Execute the insert statement
648
            String query = "update systemmetadata set (docid, rev) = (?, ?) where guid='" + guid + "'";
649 5352 berkley
            //System.out.println("query: " + query + " for params: (guid:" + guid + ", docid=" + docid + ", rev=" + rev + ")");
650 5350 berkley
            PreparedStatement stmt = dbConn.prepareStatement(query);
651
            stmt.setString(1, docid);
652
            stmt.setInt(2, rev);
653
            int rows = stmt.executeUpdate();
654
655
            stmt.close();
656
        } catch (SQLException e) {
657
            e.printStackTrace();
658
            logMetacat.error("SQL error while updating a mapping to the system metadata identifier: "
659
                    + e.getMessage());
660
        } catch (NumberFormatException e) {
661
            e.printStackTrace();
662
            logMetacat.error("NumberFormat error while updating a mapping to the system metadata identifier: "
663
                    + e.getMessage());
664
        } catch (AccessionNumberException e) {
665
            e.printStackTrace();
666
            logMetacat.error("AccessionNumber error while updating a mapping to the system metadata identifier: "
667
                    + e.getMessage());
668
        } finally {
669
            // Return database connection to the pool
670
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
671
        }
672
    }
673 5334 berkley
674
    /**
675
     * return the localId of a system metadata document based on its guid
676
     */
677 5424 berkley
    public String getSystemMetadataLocalId(String guid)
678 5334 berkley
      throws McdbDocNotFoundException
679
    {
680 5424 berkley
      return this.getLocalId(guid, TYPE_SYSTEM_METADATA);
681 5334 berkley
    }
682
683 5887 berkley
    public void insertAdditionalSystemMetadataFields(long dateUploaded, String rightsHolder,
684
            String checksum, String checksumAlgorithm, String originMemberNode,
685 5917 berkley
            String authoritativeMemberNode, long modifiedDate, String submitter,
686
            String guid, String objectFormat, long size)
687 5887 berkley
    {
688
        DBConnection dbConn = null;
689
        int serialNumber = -1;
690
        try {
691
            // Get a database connection from the pool
692
            dbConn =
693
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
694
            serialNumber = dbConn.getCheckOutSerialNumber();
695
696
            // Execute the insert statement
697
            String query = "update " + TYPE_SYSTEM_METADATA +
698
                " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
699 5917 berkley
                "origin_member_node, authoritive_member_node, date_modified, " +
700
                "submitter, object_format, size) " +
701
                "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
702 5887 berkley
            PreparedStatement stmt = dbConn.prepareStatement(query);
703
704
            //data values
705
            stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
706
            stmt.setString(2, rightsHolder);
707
            stmt.setString(3, checksum);
708
            stmt.setString(4, checksumAlgorithm);
709
            stmt.setString(5, originMemberNode);
710
            stmt.setString(6, authoritativeMemberNode);
711
            stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
712
            stmt.setString(8, submitter);
713 5917 berkley
            stmt.setString(9, objectFormat);
714
            stmt.setString(10, new Long(size).toString());
715 5887 berkley
            //where clause
716 5917 berkley
            stmt.setString(11, guid);
717 5887 berkley
            System.out.println("stmt: " + stmt.toString());
718
            //execute
719
            int rows = stmt.executeUpdate();
720
721
            stmt.close();
722
        } catch (SQLException e) {
723
            e.printStackTrace();
724
            logMetacat.error("SQL error while creating a mapping to the system metadata identifier: "
725
                    + e.getMessage());
726
        } catch (NumberFormatException e) {
727
            e.printStackTrace();
728
            logMetacat.error("NumberFormat error while creating a mapping to the system metadata identifier: "
729
                    + e.getMessage());
730
        } finally {
731
            // Return database connection to the pool
732
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
733
        }
734
    }
735
736 5334 berkley
    /**
737 5887 berkley
     * Insert the system metadata fields into the db
738
     * @param sm
739
     */
740
    public void insertAdditionalSystemMetadataFields(SystemMetadata sm)
741
    {
742
        insertAdditionalSystemMetadataFields(
743
                sm.getDateUploaded().getTime(),
744
                sm.getRightsHolder().getValue(),
745
                sm.getChecksum().getValue(),
746
                sm.getChecksum().getAlgorithm().name(),
747
                sm.getOriginMemberNode().getValue(),
748
                sm.getAuthoritativeMemberNode().getValue(),
749
                sm.getDateSysMetadataModified().getTime(),
750
                sm.getSubmitter().getValue(),
751 5917 berkley
                sm.getIdentifier().getValue(),
752
                sm.getObjectFormat().toString(),
753
                sm.getSize());
754 5887 berkley
    }
755
756
    /**
757 5334 berkley
     * return a localId based on a guid.  The type can either be 'identifier'
758
     * to get an id from the identifier table or 'systemmetadata' to get
759
     * the identifier from the systemidentifier table
760
     */
761 5424 berkley
    private String getLocalId(String guid, String type)
762 5334 berkley
      throws McdbDocNotFoundException
763
    {
764
      if(!type.equals(TYPE_IDENTIFIER) &&
765
        !type.equals(TYPE_SYSTEM_METADATA))
766
      {
767
        throw new RuntimeException("cannot lookup the identifier for type " + type +
768
          ".  Please choose 'identifier' or 'systemmetadata'.");
769
      }
770
771
      String db_guid = "";
772
      String docid = "";
773
      int rev = 0;
774
775
      String query = "select guid, docid, rev from " + type + " where guid = ?";
776 5352 berkley
      //System.out.println("query: " + query + " for params: (" + guid + ")");
777 5334 berkley
778
      DBConnection dbConn = null;
779 5333 berkley
      int serialNumber = -1;
780 5334 berkley
      try {
781
          // Get a database connection from the pool
782
          dbConn = DBConnectionPool.getDBConnection("Identifier.getLocalId");
783
          serialNumber = dbConn.getCheckOutSerialNumber();
784
785
          // Execute the insert statement
786
          PreparedStatement stmt = dbConn.prepareStatement(query);
787
          stmt.setString(1, guid);
788
          ResultSet rs = stmt.executeQuery();
789
          if (rs.next()) {
790
              db_guid = rs.getString(1);
791
              docid = rs.getString(2);
792
              rev = rs.getInt(3);
793
              assert(db_guid.equals(guid));
794
          } else {
795
              throw new McdbDocNotFoundException("Document not found:" + guid);
796
          }
797
          stmt.close();
798
      } catch (SQLException e) {
799
          logMetacat.error("Error while looking up the local identifier: "
800
                  + e.getMessage());
801
      } finally {
802
          // Return database connection to the pool
803
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
804
      }
805
      return docid + "." + rev;
806
    }
807
808 5377 berkley
    /**
809 5895 berkley
     * query the systemmetadata table based on the given parameters
810
     * @param startTime
811
     * @param endTime
812
     * @param objectFormat
813
     * @param replicaStatus
814
     * @param start
815
     * @param count
816
     * @return ObjectList
817
     */
818
    public ObjectList querySystemMetadata(Date startTime, Date endTime,
819
            ObjectFormat objectFormat, boolean replicaStatus, int start, int count)
820
    {
821
        ObjectList ol = new ObjectList();
822
        int total = 0;
823 5943 berkley
        DBConnection dbConn = null;
824
        int serialNumber = -1;
825 5895 berkley
826
        try
827
        {
828
            String sql = "select guid, date_uploaded, rights_holder, checksum, " +
829
                "checksum_algorithm, origin_member_node, authoritive_member_node, " +
830 5917 berkley
                "date_modified, submitter, object_format, size from systemmetadata";
831 5895 berkley
832
            boolean f1 = false;
833
            boolean f2 = false;
834
            boolean f3 = false;
835
836
            if(startTime != null)
837
            {
838 5917 berkley
                sql += " where systemmetadata.date_modified > ?";
839 5895 berkley
                f1 = true;
840
            }
841
842
            if(endTime != null)
843
            {
844 5917 berkley
                if(!f1)
845
                {
846
                    sql += " where systemmetadata.date_modified < ?";
847
                }
848
                else
849
                {
850
                    sql += " and systemmetadata.date_modified < ?";
851
                }
852 5895 berkley
                f2 = true;
853
            }
854
855
            if(objectFormat != null)
856
            {
857 5917 berkley
                if(!f1 && !f2)
858
                {
859
                    sql += " where object_format = ?";
860
                }
861
                else
862
                {
863
                    sql += " and object_format = ?";
864
                }
865 5895 berkley
                f3 = true;
866
            }
867
868
            if(replicaStatus)
869
            {
870
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.memberNodeId");
871 5917 berkley
                if(!f1 && !f2 && !f3)
872
                {
873
                    sql += " where authoritive_member_node != '" + currentNodeId.trim() + "'";
874
                }
875
                else
876
                {
877
                    sql += " and authoritive_member_node != '" + currentNodeId.trim() + "'";
878
                }
879 5895 berkley
            }
880
881 5943 berkley
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.querySystemMetadata");
882
            serialNumber = dbConn.getCheckOutSerialNumber();
883 5895 berkley
            PreparedStatement stmt = dbConn.prepareStatement(sql);
884
885
            if(f1 && f2 && f3)
886
            {
887
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
888
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
889
                stmt.setString(3, objectFormat.toString());
890
            }
891
            else if(f1 && f2 && !f3)
892
            {
893
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
894
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
895
            }
896
            else if(f1 && !f2 && f3)
897
            {
898
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
899
                stmt.setString(2, objectFormat.toString());
900
            }
901
            else if(f1 && !f2 && !f3)
902
            {
903
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
904
            }
905
            else if(!f1 && f2 && f3)
906
            {
907
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
908
                stmt.setString(2, objectFormat.toString());
909
            }
910
            else if(!f1 && !f2 && f3)
911
            {
912
                stmt.setString(1, objectFormat.toString());
913
            }
914
            else if(!f1 && f2 && !f3)
915
            {
916
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
917
            }
918
919
            //System.out.println("LISTOBJECTS QUERY: " + stmt.toString());
920
921
            ResultSet rs = stmt.executeQuery();
922 5917 berkley
            for(int i=0; i<start; i++)
923 5895 berkley
            {
924 5917 berkley
                if(rs.next())
925
                {
926
                    total++;
927
                }
928
                else
929
                {
930
                    break;
931
                }
932 5895 berkley
            }
933 5917 berkley
934 5895 berkley
            int countIndex = 0;
935
936
            while(rs.next())
937
            {
938
                total++;
939
                if(countIndex >= count)
940
                {
941
                    break;
942
                }
943
                String guid = rs.getString(1);
944
                //System.out.println("query found doc with guid " + guid);
945
                //Timestamp dateUploaded = rs.getTimestamp(2);
946
                //String rightsHolder = rs.getString(3);
947
                String checksum = rs.getString(4);
948
                String checksumAlgorithm = rs.getString(5);
949
                //String originMemberNode = rs.getString(6);
950
                String authoritiveMemberNode = rs.getString(7);
951
                Timestamp dateModified = rs.getTimestamp(8);
952
                //String submitter = rs.getString(9);
953
                String format = rs.getString(10);
954 5917 berkley
                String sz = rs.getString(11);
955
                long size = 0;
956
                if(sz != null && !sz.trim().equals(""))
957
                {
958
                    size = new Long(rs.getString(11)).longValue();
959
                }
960 5895 berkley
961
                ObjectInfo oi = new ObjectInfo();
962
963
                Identifier id = new Identifier();
964
                id.setValue(guid);
965
                oi.setIdentifier(id);
966
967
                oi.setDateSysMetadataModified(new Date(dateModified.getTime()));
968
969
                Checksum cs = new Checksum();
970
                cs.setValue(checksum);
971 5906 berkley
                cs.setAlgorithm(ChecksumAlgorithm.valueOf(checksumAlgorithm));
972 5895 berkley
                oi.setChecksum(cs);
973
974
                ObjectFormat oFormat = ObjectFormat.convert(format);
975
                if(oFormat != null)
976
                {
977
                    oi.setObjectFormat(oFormat);
978
                }
979 5906 berkley
                else
980
                { //if there is no object format, just default to text/plain
981 5917 berkley
                    oi.setObjectFormat(ObjectFormat.OCTET_STREAM);
982 5906 berkley
                }
983 5917 berkley
984
                oi.setSize(size);
985 5895 berkley
986
                ol.addObjectInfo(oi);
987
                countIndex++;
988
            }
989
990
            while(rs.next())
991
            { //expend the resultset to get the total count of possible rows
992
                total++;
993
            }
994
        }
995
        catch(Exception e)
996
        {
997
           e.printStackTrace();
998
           System.out.println("Error querying system metadata: " + e.getMessage());
999
        }
1000 5943 berkley
        finally
1001
        {
1002
            // Return database connection to the pool
1003
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1004
        }
1005 5895 berkley
1006
        ol.setStart(start);
1007 5922 berkley
        ol.setCount(ol.sizeObjectInfoList());
1008 5895 berkley
        ol.setTotal(total);
1009
1010
        return ol;
1011
    }
1012
1013
    /**
1014 5377 berkley
     * create a mapping in the systemmetadata or identifier table
1015
     * @param guid
1016
     * @param localId
1017
     * @param type
1018
     */
1019 5334 berkley
    private void createGenericMapping(String guid, String localId, String type)
1020 5453 berkley
    {
1021 5334 berkley
        if(!type.equals(TYPE_IDENTIFIER) &&
1022
        !type.equals(TYPE_SYSTEM_METADATA))
1023
        {
1024
          throw new RuntimeException("Cannot create mapping for type " + type +
1025
            ".  Please choose 'identifier' or 'systemmetadata'.");
1026
        }
1027
1028
        int serialNumber = -1;
1029 5333 berkley
        DBConnection dbConn = null;
1030
        try {
1031
1032
            // Parse the localId into scope and rev parts
1033
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1034
            String docid = acc.getDocid();
1035 5344 berkley
            int rev = 1;
1036
            if(acc.getRev() != null)
1037
            {
1038
              rev = (new Integer(acc.getRev()).intValue());
1039
            }
1040 5333 berkley
1041
            // Get a database connection from the pool
1042
            dbConn =
1043 5377 berkley
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1044 5333 berkley
            serialNumber = dbConn.getCheckOutSerialNumber();
1045
1046
            // Execute the insert statement
1047 5344 berkley
            String query = "insert into " + type + " (guid, docid, rev) values (?, ?, ?)";
1048 5352 berkley
            //System.out.println("query: " + query + " for params: (" + guid + ", " + docid + ", " + rev + ")");
1049 5333 berkley
            PreparedStatement stmt = dbConn.prepareStatement(query);
1050
            stmt.setString(1, guid);
1051
            stmt.setString(2, docid);
1052
            stmt.setInt(3, rev);
1053 5887 berkley
            System.out.println("generic mapping query: " + stmt.toString());
1054 5333 berkley
            int rows = stmt.executeUpdate();
1055
1056
            stmt.close();
1057
        } catch (SQLException e) {
1058 5344 berkley
            e.printStackTrace();
1059 5887 berkley
            logMetacat.warn("SQL error while creating a mapping to the system metadata identifier: "
1060 5333 berkley
                    + e.getMessage());
1061
        } catch (NumberFormatException e) {
1062 5344 berkley
            e.printStackTrace();
1063 5333 berkley
            logMetacat.error("NumberFormat error while creating a mapping to the system metadata identifier: "
1064
                    + e.getMessage());
1065
        } catch (AccessionNumberException e) {
1066 5344 berkley
            e.printStackTrace();
1067 5333 berkley
            logMetacat.error("AccessionNumber error while creating a mapping to the system metadata identifier: "
1068
                    + e.getMessage());
1069
        } finally {
1070
            // Return database connection to the pool
1071
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1072
        }
1073
    }
1074 5282 jones
}