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 5930 berkley
          "origin_member_node, authoritive_member_node, date_modified, submitter, object_format " +
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
824
        try
825
        {
826
            String sql = "select guid, date_uploaded, rights_holder, checksum, " +
827
                "checksum_algorithm, origin_member_node, authoritive_member_node, " +
828 5917 berkley
                "date_modified, submitter, object_format, size from systemmetadata";
829 5895 berkley
830
            boolean f1 = false;
831
            boolean f2 = false;
832
            boolean f3 = false;
833
834
            if(startTime != null)
835
            {
836 5917 berkley
                sql += " where systemmetadata.date_modified > ?";
837 5895 berkley
                f1 = true;
838
            }
839
840
            if(endTime != null)
841
            {
842 5917 berkley
                if(!f1)
843
                {
844
                    sql += " where systemmetadata.date_modified < ?";
845
                }
846
                else
847
                {
848
                    sql += " and systemmetadata.date_modified < ?";
849
                }
850 5895 berkley
                f2 = true;
851
            }
852
853
            if(objectFormat != null)
854
            {
855 5917 berkley
                if(!f1 && !f2)
856
                {
857
                    sql += " where object_format = ?";
858
                }
859
                else
860
                {
861
                    sql += " and object_format = ?";
862
                }
863 5895 berkley
                f3 = true;
864
            }
865
866
            if(replicaStatus)
867
            {
868
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.memberNodeId");
869 5917 berkley
                if(!f1 && !f2 && !f3)
870
                {
871
                    sql += " where authoritive_member_node != '" + currentNodeId.trim() + "'";
872
                }
873
                else
874
                {
875
                    sql += " and authoritive_member_node != '" + currentNodeId.trim() + "'";
876
                }
877 5895 berkley
            }
878
879
            DBConnection dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
880
            int serialNumber = dbConn.getCheckOutSerialNumber();
881
            PreparedStatement stmt = dbConn.prepareStatement(sql);
882
883
            if(f1 && f2 && f3)
884
            {
885
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
886
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
887
                stmt.setString(3, objectFormat.toString());
888
            }
889
            else if(f1 && f2 && !f3)
890
            {
891
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
892
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
893
            }
894
            else if(f1 && !f2 && f3)
895
            {
896
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
897
                stmt.setString(2, objectFormat.toString());
898
            }
899
            else if(f1 && !f2 && !f3)
900
            {
901
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
902
            }
903
            else if(!f1 && f2 && f3)
904
            {
905
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
906
                stmt.setString(2, objectFormat.toString());
907
            }
908
            else if(!f1 && !f2 && f3)
909
            {
910
                stmt.setString(1, objectFormat.toString());
911
            }
912
            else if(!f1 && f2 && !f3)
913
            {
914
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
915
            }
916
917
            //System.out.println("LISTOBJECTS QUERY: " + stmt.toString());
918
919
            ResultSet rs = stmt.executeQuery();
920 5917 berkley
            for(int i=0; i<start; i++)
921 5895 berkley
            {
922 5917 berkley
                if(rs.next())
923
                {
924
                    total++;
925
                }
926
                else
927
                {
928
                    break;
929
                }
930 5895 berkley
            }
931 5917 berkley
932 5895 berkley
            int countIndex = 0;
933
934
            while(rs.next())
935
            {
936
                total++;
937
                if(countIndex >= count)
938
                {
939
                    break;
940
                }
941
                String guid = rs.getString(1);
942
                //System.out.println("query found doc with guid " + guid);
943
                //Timestamp dateUploaded = rs.getTimestamp(2);
944
                //String rightsHolder = rs.getString(3);
945
                String checksum = rs.getString(4);
946
                String checksumAlgorithm = rs.getString(5);
947
                //String originMemberNode = rs.getString(6);
948
                String authoritiveMemberNode = rs.getString(7);
949
                Timestamp dateModified = rs.getTimestamp(8);
950
                //String submitter = rs.getString(9);
951
                String format = rs.getString(10);
952 5917 berkley
                String sz = rs.getString(11);
953
                long size = 0;
954
                if(sz != null && !sz.trim().equals(""))
955
                {
956
                    size = new Long(rs.getString(11)).longValue();
957
                }
958 5895 berkley
959
                ObjectInfo oi = new ObjectInfo();
960
961
                Identifier id = new Identifier();
962
                id.setValue(guid);
963
                oi.setIdentifier(id);
964
965
                oi.setDateSysMetadataModified(new Date(dateModified.getTime()));
966
967
                Checksum cs = new Checksum();
968
                cs.setValue(checksum);
969 5906 berkley
                cs.setAlgorithm(ChecksumAlgorithm.valueOf(checksumAlgorithm));
970 5895 berkley
                oi.setChecksum(cs);
971
972
                ObjectFormat oFormat = ObjectFormat.convert(format);
973
                if(oFormat != null)
974
                {
975
                    oi.setObjectFormat(oFormat);
976
                }
977 5906 berkley
                else
978
                { //if there is no object format, just default to text/plain
979 5917 berkley
                    oi.setObjectFormat(ObjectFormat.OCTET_STREAM);
980 5906 berkley
                }
981 5917 berkley
982
                oi.setSize(size);
983 5895 berkley
984
                ol.addObjectInfo(oi);
985
                countIndex++;
986
            }
987
988
            while(rs.next())
989
            { //expend the resultset to get the total count of possible rows
990
                total++;
991
            }
992
        }
993
        catch(Exception e)
994
        {
995
           e.printStackTrace();
996
           System.out.println("Error querying system metadata: " + e.getMessage());
997
        }
998
999
        ol.setStart(start);
1000 5922 berkley
        ol.setCount(ol.sizeObjectInfoList());
1001 5895 berkley
        ol.setTotal(total);
1002
1003
        return ol;
1004
    }
1005
1006
    /**
1007 5377 berkley
     * create a mapping in the systemmetadata or identifier table
1008
     * @param guid
1009
     * @param localId
1010
     * @param type
1011
     */
1012 5334 berkley
    private void createGenericMapping(String guid, String localId, String type)
1013 5453 berkley
    {
1014 5334 berkley
        if(!type.equals(TYPE_IDENTIFIER) &&
1015
        !type.equals(TYPE_SYSTEM_METADATA))
1016
        {
1017
          throw new RuntimeException("Cannot create mapping for type " + type +
1018
            ".  Please choose 'identifier' or 'systemmetadata'.");
1019
        }
1020
1021
        int serialNumber = -1;
1022 5333 berkley
        DBConnection dbConn = null;
1023
        try {
1024
1025
            // Parse the localId into scope and rev parts
1026
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1027
            String docid = acc.getDocid();
1028 5344 berkley
            int rev = 1;
1029
            if(acc.getRev() != null)
1030
            {
1031
              rev = (new Integer(acc.getRev()).intValue());
1032
            }
1033 5333 berkley
1034
            // Get a database connection from the pool
1035
            dbConn =
1036 5377 berkley
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1037 5333 berkley
            serialNumber = dbConn.getCheckOutSerialNumber();
1038
1039
            // Execute the insert statement
1040 5344 berkley
            String query = "insert into " + type + " (guid, docid, rev) values (?, ?, ?)";
1041 5352 berkley
            //System.out.println("query: " + query + " for params: (" + guid + ", " + docid + ", " + rev + ")");
1042 5333 berkley
            PreparedStatement stmt = dbConn.prepareStatement(query);
1043
            stmt.setString(1, guid);
1044
            stmt.setString(2, docid);
1045
            stmt.setInt(3, rev);
1046 5887 berkley
            System.out.println("generic mapping query: " + stmt.toString());
1047 5333 berkley
            int rows = stmt.executeUpdate();
1048
1049
            stmt.close();
1050
        } catch (SQLException e) {
1051 5344 berkley
            e.printStackTrace();
1052 5887 berkley
            logMetacat.warn("SQL error while creating a mapping to the system metadata identifier: "
1053 5333 berkley
                    + e.getMessage());
1054
        } catch (NumberFormatException e) {
1055 5344 berkley
            e.printStackTrace();
1056 5333 berkley
            logMetacat.error("NumberFormat error while creating a mapping to the system metadata identifier: "
1057
                    + e.getMessage());
1058
        } catch (AccessionNumberException e) {
1059 5344 berkley
            e.printStackTrace();
1060 5333 berkley
            logMetacat.error("AccessionNumber error while creating a mapping to the system metadata identifier: "
1061
                    + e.getMessage());
1062
        } finally {
1063
            // Return database connection to the pool
1064
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1065
        }
1066
    }
1067 5282 jones
}