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 5950 berkley
        System.out.println("$$$$$$$$$$$$$$ updating systemmetadata table with additional info");
631 5350 berkley
        int serialNumber = -1;
632
        DBConnection dbConn = null;
633
        try {
634
            // Parse the localId into scope and rev parts
635
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
636
            String docid = acc.getDocid();
637
            int rev = 1;
638
            if(acc.getRev() != null)
639
            {
640
              rev = (new Integer(acc.getRev()).intValue());
641
            }
642
643
            // Get a database connection from the pool
644
            dbConn =
645 5377 berkley
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
646 5350 berkley
            serialNumber = dbConn.getCheckOutSerialNumber();
647
648
            // Execute the insert statement
649
            String query = "update systemmetadata set (docid, rev) = (?, ?) where guid='" + guid + "'";
650 5352 berkley
            //System.out.println("query: " + query + " for params: (guid:" + guid + ", docid=" + docid + ", rev=" + rev + ")");
651 5350 berkley
            PreparedStatement stmt = dbConn.prepareStatement(query);
652
            stmt.setString(1, docid);
653
            stmt.setInt(2, rev);
654
            int rows = stmt.executeUpdate();
655
656
            stmt.close();
657
        } catch (SQLException e) {
658
            e.printStackTrace();
659
            logMetacat.error("SQL error while updating a mapping to the system metadata identifier: "
660
                    + e.getMessage());
661
        } catch (NumberFormatException e) {
662
            e.printStackTrace();
663
            logMetacat.error("NumberFormat error while updating a mapping to the system metadata identifier: "
664
                    + e.getMessage());
665
        } catch (AccessionNumberException e) {
666
            e.printStackTrace();
667
            logMetacat.error("AccessionNumber error while updating a mapping to the system metadata identifier: "
668
                    + e.getMessage());
669
        } finally {
670
            // Return database connection to the pool
671
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
672
        }
673 5950 berkley
        System.out.println("done updating systemmetadata");
674 5350 berkley
    }
675 5334 berkley
676
    /**
677
     * return the localId of a system metadata document based on its guid
678
     */
679 5424 berkley
    public String getSystemMetadataLocalId(String guid)
680 5334 berkley
      throws McdbDocNotFoundException
681
    {
682 5424 berkley
      return this.getLocalId(guid, TYPE_SYSTEM_METADATA);
683 5334 berkley
    }
684
685 5887 berkley
    public void insertAdditionalSystemMetadataFields(long dateUploaded, String rightsHolder,
686
            String checksum, String checksumAlgorithm, String originMemberNode,
687 5917 berkley
            String authoritativeMemberNode, long modifiedDate, String submitter,
688
            String guid, String objectFormat, long size)
689 5887 berkley
    {
690
        DBConnection dbConn = null;
691
        int serialNumber = -1;
692 5957 berkley
693 5887 berkley
        try {
694
            // Get a database connection from the pool
695
            dbConn =
696
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
697
            serialNumber = dbConn.getCheckOutSerialNumber();
698
699
            // Execute the insert statement
700
            String query = "update " + TYPE_SYSTEM_METADATA +
701
                " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
702 5917 berkley
                "origin_member_node, authoritive_member_node, date_modified, " +
703
                "submitter, object_format, size) " +
704
                "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
705 5887 berkley
            PreparedStatement stmt = dbConn.prepareStatement(query);
706
707
            //data values
708
            stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
709
            stmt.setString(2, rightsHolder);
710
            stmt.setString(3, checksum);
711
            stmt.setString(4, checksumAlgorithm);
712
            stmt.setString(5, originMemberNode);
713
            stmt.setString(6, authoritativeMemberNode);
714
            stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
715
            stmt.setString(8, submitter);
716 5917 berkley
            stmt.setString(9, objectFormat);
717
            stmt.setString(10, new Long(size).toString());
718 5887 berkley
            //where clause
719 5917 berkley
            stmt.setString(11, guid);
720 5887 berkley
            System.out.println("stmt: " + stmt.toString());
721
            //execute
722
            int rows = stmt.executeUpdate();
723
724
            stmt.close();
725
        } catch (SQLException e) {
726
            e.printStackTrace();
727 5950 berkley
            logMetacat.error("insertAdditionalSystemMetadataFields: SQL error while creating a mapping to the system metadata identifier: "
728 5887 berkley
                    + e.getMessage());
729
        } catch (NumberFormatException e) {
730
            e.printStackTrace();
731 5950 berkley
            logMetacat.error("insertAdditionalSystemMetadataFields: NumberFormat error while creating a mapping to the system metadata identifier: "
732 5887 berkley
                    + e.getMessage());
733
        } finally {
734
            // Return database connection to the pool
735
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
736
        }
737
    }
738
739 5334 berkley
    /**
740 5887 berkley
     * Insert the system metadata fields into the db
741
     * @param sm
742
     */
743
    public void insertAdditionalSystemMetadataFields(SystemMetadata sm)
744
    {
745
        insertAdditionalSystemMetadataFields(
746
                sm.getDateUploaded().getTime(),
747
                sm.getRightsHolder().getValue(),
748
                sm.getChecksum().getValue(),
749
                sm.getChecksum().getAlgorithm().name(),
750
                sm.getOriginMemberNode().getValue(),
751
                sm.getAuthoritativeMemberNode().getValue(),
752
                sm.getDateSysMetadataModified().getTime(),
753
                sm.getSubmitter().getValue(),
754 5917 berkley
                sm.getIdentifier().getValue(),
755
                sm.getObjectFormat().toString(),
756
                sm.getSize());
757 5887 berkley
    }
758
759
    /**
760 5334 berkley
     * return a localId based on a guid.  The type can either be 'identifier'
761
     * to get an id from the identifier table or 'systemmetadata' to get
762
     * the identifier from the systemidentifier table
763
     */
764 5424 berkley
    private String getLocalId(String guid, String type)
765 5334 berkley
      throws McdbDocNotFoundException
766
    {
767
      if(!type.equals(TYPE_IDENTIFIER) &&
768
        !type.equals(TYPE_SYSTEM_METADATA))
769
      {
770
        throw new RuntimeException("cannot lookup the identifier for type " + type +
771
          ".  Please choose 'identifier' or 'systemmetadata'.");
772
      }
773
774
      String db_guid = "";
775
      String docid = "";
776
      int rev = 0;
777
778
      String query = "select guid, docid, rev from " + type + " where guid = ?";
779 5352 berkley
      //System.out.println("query: " + query + " for params: (" + guid + ")");
780 5334 berkley
781
      DBConnection dbConn = null;
782 5333 berkley
      int serialNumber = -1;
783 5334 berkley
      try {
784
          // Get a database connection from the pool
785
          dbConn = DBConnectionPool.getDBConnection("Identifier.getLocalId");
786
          serialNumber = dbConn.getCheckOutSerialNumber();
787
788
          // Execute the insert statement
789
          PreparedStatement stmt = dbConn.prepareStatement(query);
790
          stmt.setString(1, guid);
791
          ResultSet rs = stmt.executeQuery();
792
          if (rs.next()) {
793
              db_guid = rs.getString(1);
794
              docid = rs.getString(2);
795
              rev = rs.getInt(3);
796
              assert(db_guid.equals(guid));
797
          } else {
798
              throw new McdbDocNotFoundException("Document not found:" + guid);
799
          }
800
          stmt.close();
801
      } catch (SQLException e) {
802
          logMetacat.error("Error while looking up the local identifier: "
803
                  + e.getMessage());
804
      } finally {
805
          // Return database connection to the pool
806
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
807
      }
808
      return docid + "." + rev;
809
    }
810
811 5377 berkley
    /**
812 5895 berkley
     * query the systemmetadata table based on the given parameters
813
     * @param startTime
814
     * @param endTime
815
     * @param objectFormat
816
     * @param replicaStatus
817
     * @param start
818
     * @param count
819
     * @return ObjectList
820
     */
821
    public ObjectList querySystemMetadata(Date startTime, Date endTime,
822
            ObjectFormat objectFormat, boolean replicaStatus, int start, int count)
823
    {
824
        ObjectList ol = new ObjectList();
825
        int total = 0;
826 5943 berkley
        DBConnection dbConn = null;
827
        int serialNumber = -1;
828 5895 berkley
829
        try
830
        {
831
            String sql = "select guid, date_uploaded, rights_holder, checksum, " +
832
                "checksum_algorithm, origin_member_node, authoritive_member_node, " +
833 5917 berkley
                "date_modified, submitter, object_format, size from systemmetadata";
834 5895 berkley
835
            boolean f1 = false;
836
            boolean f2 = false;
837
            boolean f3 = false;
838
839
            if(startTime != null)
840
            {
841 5917 berkley
                sql += " where systemmetadata.date_modified > ?";
842 5895 berkley
                f1 = true;
843
            }
844
845
            if(endTime != null)
846
            {
847 5917 berkley
                if(!f1)
848
                {
849
                    sql += " where systemmetadata.date_modified < ?";
850
                }
851
                else
852
                {
853
                    sql += " and systemmetadata.date_modified < ?";
854
                }
855 5895 berkley
                f2 = true;
856
            }
857
858
            if(objectFormat != null)
859
            {
860 5917 berkley
                if(!f1 && !f2)
861
                {
862
                    sql += " where object_format = ?";
863
                }
864
                else
865
                {
866
                    sql += " and object_format = ?";
867
                }
868 5895 berkley
                f3 = true;
869
            }
870
871
            if(replicaStatus)
872
            {
873
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.memberNodeId");
874 5917 berkley
                if(!f1 && !f2 && !f3)
875
                {
876
                    sql += " where authoritive_member_node != '" + currentNodeId.trim() + "'";
877
                }
878
                else
879
                {
880
                    sql += " and authoritive_member_node != '" + currentNodeId.trim() + "'";
881
                }
882 5895 berkley
            }
883
884 5943 berkley
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.querySystemMetadata");
885
            serialNumber = dbConn.getCheckOutSerialNumber();
886 5895 berkley
            PreparedStatement stmt = dbConn.prepareStatement(sql);
887
888
            if(f1 && f2 && f3)
889
            {
890
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
891
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
892
                stmt.setString(3, objectFormat.toString());
893
            }
894
            else if(f1 && f2 && !f3)
895
            {
896
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
897
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
898
            }
899
            else if(f1 && !f2 && f3)
900
            {
901
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
902
                stmt.setString(2, objectFormat.toString());
903
            }
904
            else if(f1 && !f2 && !f3)
905
            {
906
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
907
            }
908
            else if(!f1 && f2 && f3)
909
            {
910
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
911
                stmt.setString(2, objectFormat.toString());
912
            }
913
            else if(!f1 && !f2 && f3)
914
            {
915
                stmt.setString(1, objectFormat.toString());
916
            }
917
            else if(!f1 && f2 && !f3)
918
            {
919
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
920
            }
921
922
            //System.out.println("LISTOBJECTS QUERY: " + stmt.toString());
923
924
            ResultSet rs = stmt.executeQuery();
925 5917 berkley
            for(int i=0; i<start; i++)
926 5895 berkley
            {
927 5917 berkley
                if(rs.next())
928
                {
929
                    total++;
930
                }
931
                else
932
                {
933
                    break;
934
                }
935 5895 berkley
            }
936 5917 berkley
937 5895 berkley
            int countIndex = 0;
938
939
            while(rs.next())
940
            {
941
                total++;
942
                if(countIndex >= count)
943
                {
944
                    break;
945
                }
946
                String guid = rs.getString(1);
947
                //System.out.println("query found doc with guid " + guid);
948
                //Timestamp dateUploaded = rs.getTimestamp(2);
949
                //String rightsHolder = rs.getString(3);
950
                String checksum = rs.getString(4);
951
                String checksumAlgorithm = rs.getString(5);
952
                //String originMemberNode = rs.getString(6);
953
                String authoritiveMemberNode = rs.getString(7);
954
                Timestamp dateModified = rs.getTimestamp(8);
955
                //String submitter = rs.getString(9);
956
                String format = rs.getString(10);
957 5917 berkley
                String sz = rs.getString(11);
958
                long size = 0;
959
                if(sz != null && !sz.trim().equals(""))
960
                {
961
                    size = new Long(rs.getString(11)).longValue();
962
                }
963 5895 berkley
964
                ObjectInfo oi = new ObjectInfo();
965
966
                Identifier id = new Identifier();
967
                id.setValue(guid);
968
                oi.setIdentifier(id);
969
970
                oi.setDateSysMetadataModified(new Date(dateModified.getTime()));
971
972
                Checksum cs = new Checksum();
973
                cs.setValue(checksum);
974 5906 berkley
                cs.setAlgorithm(ChecksumAlgorithm.valueOf(checksumAlgorithm));
975 5957 berkley
                //cs.setAlgorithm(ChecksumAlgorithm.convert(checksumAlgorithm));
976 5895 berkley
                oi.setChecksum(cs);
977
978
                ObjectFormat oFormat = ObjectFormat.convert(format);
979
                if(oFormat != null)
980
                {
981
                    oi.setObjectFormat(oFormat);
982
                }
983 5906 berkley
                else
984
                { //if there is no object format, just default to text/plain
985 5917 berkley
                    oi.setObjectFormat(ObjectFormat.OCTET_STREAM);
986 5906 berkley
                }
987 5917 berkley
988
                oi.setSize(size);
989 5895 berkley
990
                ol.addObjectInfo(oi);
991
                countIndex++;
992
            }
993
994
            while(rs.next())
995
            { //expend the resultset to get the total count of possible rows
996
                total++;
997
            }
998
        }
999
        catch(Exception e)
1000
        {
1001
           e.printStackTrace();
1002
           System.out.println("Error querying system metadata: " + e.getMessage());
1003
        }
1004 5943 berkley
        finally
1005
        {
1006
            // Return database connection to the pool
1007
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1008
        }
1009 5895 berkley
1010
        ol.setStart(start);
1011 5922 berkley
        ol.setCount(ol.sizeObjectInfoList());
1012 5895 berkley
        ol.setTotal(total);
1013
1014
        return ol;
1015
    }
1016
1017
    /**
1018 5377 berkley
     * create a mapping in the systemmetadata or identifier table
1019
     * @param guid
1020
     * @param localId
1021
     * @param type
1022
     */
1023 5334 berkley
    private void createGenericMapping(String guid, String localId, String type)
1024 5453 berkley
    {
1025 5334 berkley
        if(!type.equals(TYPE_IDENTIFIER) &&
1026
        !type.equals(TYPE_SYSTEM_METADATA))
1027
        {
1028
          throw new RuntimeException("Cannot create mapping for type " + type +
1029
            ".  Please choose 'identifier' or 'systemmetadata'.");
1030
        }
1031
1032
        int serialNumber = -1;
1033 5333 berkley
        DBConnection dbConn = null;
1034
        try {
1035
1036
            // Parse the localId into scope and rev parts
1037
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1038
            String docid = acc.getDocid();
1039 5344 berkley
            int rev = 1;
1040
            if(acc.getRev() != null)
1041
            {
1042
              rev = (new Integer(acc.getRev()).intValue());
1043
            }
1044 5333 berkley
1045
            // Get a database connection from the pool
1046
            dbConn =
1047 5377 berkley
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1048 5333 berkley
            serialNumber = dbConn.getCheckOutSerialNumber();
1049
1050
            // Execute the insert statement
1051 5344 berkley
            String query = "insert into " + type + " (guid, docid, rev) values (?, ?, ?)";
1052 5352 berkley
            //System.out.println("query: " + query + " for params: (" + guid + ", " + docid + ", " + rev + ")");
1053 5333 berkley
            PreparedStatement stmt = dbConn.prepareStatement(query);
1054
            stmt.setString(1, guid);
1055
            stmt.setString(2, docid);
1056
            stmt.setInt(3, rev);
1057 5887 berkley
            System.out.println("generic mapping query: " + stmt.toString());
1058 5333 berkley
            int rows = stmt.executeUpdate();
1059
1060
            stmt.close();
1061
        } catch (SQLException e) {
1062 5344 berkley
            e.printStackTrace();
1063 5950 berkley
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + type + " identifier: "
1064 5333 berkley
                    + e.getMessage());
1065
        } catch (NumberFormatException e) {
1066 5344 berkley
            e.printStackTrace();
1067 5950 berkley
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + type + " identifier: "
1068 5333 berkley
                    + e.getMessage());
1069
        } catch (AccessionNumberException e) {
1070 5344 berkley
            e.printStackTrace();
1071 5950 berkley
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + type + " identifier: "
1072 5333 berkley
                    + e.getMessage());
1073
        } finally {
1074
            // Return database connection to the pool
1075
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1076
        }
1077
    }
1078 5282 jones
}