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 6042 cjones
                h.put("docid", localId);
232 5378 berkley
                h.put("docname", docname);
233
                h.put("doctype", doctype);
234
                h.put("user_owner", user_owner);
235
                h.put("user_updated", user_updated);
236
                h.put("server_location", server_location);
237
                h.put("rev", new Integer(rev).toString());
238
                h.put("date_created", date_created);
239
                h.put("date_updated", date_updated);
240
241
                stmt.close();
242
            }
243
            else
244
            {
245
                stmt.close();
246
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
247 5798 berkley
                throw new McdbDocNotFoundException("2Could not find document " + localId);
248 5378 berkley
            }
249 5441 berkley
250 5444 berkley
            String sql2 = "select principal_name, permission, perm_type, perm_order from xml_access " +
251 5441 berkley
            "where docid like '" + localId + "'";
252 5444 berkley
            System.out.println("executing sql: " + sql2);
253 5441 berkley
            PreparedStatement stmt2 = dbConn.prepareStatement(sql2);
254 5442 berkley
            rs = stmt2.executeQuery();
255 5441 berkley
            Vector accessVector = new Vector();
256 5445 berkley
            while(rs.next())
257 5441 berkley
            {
258
                Hashtable accessHash = new Hashtable();
259
                String principal_name = rs.getString(1);
260
                String permission = rs.getString(2);
261
                String permissionType = rs.getString(3);
262
                String permissionOrder = rs.getString(4);
263
                accessHash.put("principal_name", principal_name);
264
                accessHash.put("permission", permission);
265
                accessHash.put("permission_type", permissionType);
266
                accessHash.put("permission_order", permissionOrder);
267 5444 berkley
                System.out.println("accessHash: " + accessHash.toString());
268 5441 berkley
                accessVector.add(accessHash);
269
            }
270
            h.put("access", accessVector);
271 5378 berkley
        }
272
        catch (SQLException e)
273
        {
274 5444 berkley
            e.printStackTrace();
275 5378 berkley
            logMetacat.error("Error while getting document info for localid " + localId + " : "
276
                    + e.getMessage());
277
        }
278
        finally
279
        {
280
            // Return database connection to the pool
281
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
282
        }
283
        return h;
284
    }
285
286
    /**
287
     * return the newest rev for a given localId
288
     * @param localId
289
     * @return
290
     */
291
    public int getLatestRevForLocalId(String localId)
292
        throws McdbDocNotFoundException
293
    {
294 5798 berkley
        try
295
        {
296
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
297
            localId = acc.getDocid();
298
        }
299
        catch(Exception e)
300
        {
301
            //do nothing. just try the localId as it is
302
        }
303 5378 berkley
        int rev = 0;
304
        String sql = "select rev from xml_documents where docid like '" + localId + "'";
305
        DBConnection dbConn = null;
306
        int serialNumber = -1;
307
        try
308
        {
309
            // Get a database connection from the pool
310
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLatestRevForLocalId");
311
            serialNumber = dbConn.getCheckOutSerialNumber();
312
313
            // Execute the insert statement
314
            PreparedStatement stmt = dbConn.prepareStatement(sql);
315
            ResultSet rs = stmt.executeQuery();
316
            if (rs.next())
317
            {
318
                rev = rs.getInt(1);
319
                stmt.close();
320
            }
321
            else
322
            {
323
                stmt.close();
324
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
325 5798 berkley
                throw new McdbDocNotFoundException("While trying to get the latest rev, could not find document " + localId);
326 5378 berkley
            }
327
        }
328
        catch (SQLException e)
329
        {
330
            logMetacat.error("Error while looking up the guid: "
331
                    + e.getMessage());
332
        }
333
        finally
334
        {
335
            // Return database connection to the pool
336
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
337
        }
338
        return rev;
339
    }
340
341
    /**
342 5377 berkley
     * return all local ids in the object store that do not have associated
343
     * system metadata and are not themselves system metadata
344
     */
345
    public List<String> getLocalIdsWithNoSystemMetadata()
346
    {
347
        Vector<String> ids = new Vector<String>();
348
        //String sql = "select docid from identifier where guid in (select guid from systemmetadata)";
349 5796 berkley
        //String sql = "select docid from xml_documents where docid not " +
350
        //    "in (select docid from identifier where guid in (select guid from systemmetadata)) " +
351
        //    "and doctype not like '" + DATAONE_SM_DOCTYPE + "'";
352 5798 berkley
        String sql = "select docid, rev from xml_documents where docid not in " +
353 5796 berkley
            "(select docid from systemmetadata) and (docid not in " +
354
            "(select docid from identifier where guid in (select guid from systemmetadata)))";
355 5377 berkley
        DBConnection dbConn = null;
356
        int serialNumber = -1;
357
        try
358
        {
359
            // Get a database connection from the pool
360
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLocalIdsWithNoSystemMetadata");
361
            serialNumber = dbConn.getCheckOutSerialNumber();
362
363
            // Execute the insert statement
364
            PreparedStatement stmt = dbConn.prepareStatement(sql);
365
            ResultSet rs = stmt.executeQuery();
366
            while (rs.next())
367
            {
368
                String localid = rs.getString(1);
369 5798 berkley
                String rev = rs.getString(2);
370
                localid += "." + rev;
371 5796 berkley
                System.out.println("id to add SM for: " + localid);
372 5377 berkley
                ids.add(localid);
373
            }
374
            stmt.close();
375
        }
376
        catch (SQLException e)
377
        {
378
            logMetacat.error("Error while looking up the guid: "
379
                    + e.getMessage());
380
        }
381
        finally
382
        {
383
            // Return database connection to the pool
384
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
385
        }
386
387
        return ids;
388
    }
389
390
    /**
391
     * return a listing of all local ids in the object store
392
     * @return a list of all local ids in metacat
393
     */
394
    public List<String> getAllLocalIds()
395
       throws Exception
396
    {
397
        Vector<String> ids = new Vector<String>();
398
        String sql = "select docid from xml_documents";
399
        DBConnection dbConn = null;
400
        int serialNumber = -1;
401
        try
402
        {
403
            // Get a database connection from the pool
404
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getAllLocalIds");
405
            serialNumber = dbConn.getCheckOutSerialNumber();
406
407
            // Execute the insert statement
408
            PreparedStatement stmt = dbConn.prepareStatement(sql);
409
            ResultSet rs = stmt.executeQuery();
410
            while (rs.next())
411
            {
412
                String localid = rs.getString(1);
413
                ids.add(localid);
414
            }
415
            stmt.close();
416
        }
417
        catch (SQLException e)
418
        {
419
            logMetacat.error("Error while looking up the guid: "
420
                    + e.getMessage());
421
        }
422
        finally
423
        {
424
            // Return database connection to the pool
425
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
426
        }
427
        return ids;
428
    }
429
430
    /**
431 5282 jones
     * Lookup a GUID from the database, and return the associated LocalID. If
432
     * the identifier is not found, throw an exception.
433
     *
434
     * @param guid the global identifier to look up
435
     * @return String containing the corresponding LocalId
436
     * @throws McdbDocNotFoundException if the identifier is not found
437
     */
438
    public String getLocalId(String guid) throws McdbDocNotFoundException
439
    {
440 5424 berkley
        return this.getLocalId(guid, TYPE_IDENTIFIER);
441 5282 jones
    }
442
443
    /**
444
     * Determine if an identifier exists already, returning true if so.
445
     *
446
     * @param guid the global identifier to look up
447
     * @return boolean true if the identifier exists
448
     */
449
    public boolean identifierExists(String guid)
450
    {
451
        boolean idExists = false;
452
        try {
453
            String id = getLocalId(guid);
454
            if (id != null) {
455
                idExists = true;
456
            }
457
        } catch (McdbDocNotFoundException e) {
458
            idExists = false;
459
        }
460
        return idExists;
461
    }
462
463
    /**
464
     * Create a mapping between two identifiers, one representing an
465
     * unconstrained, globally unique string (guid), and one a localId
466
     * in the Metacat docid format (scope.id.revision).
467
     * This mapping allows one to find the global id (guid) from the localId.
468
     *
469
     * @param guid the global string identifier to be mapped
470
     * @param localId the local identifier to be mapped
471
     */
472
    public void createMapping(String guid, String localId)
473
    {
474 5334 berkley
        createGenericMapping(guid, localId, TYPE_IDENTIFIER);
475 5282 jones
    }
476 5453 berkley
477
    /**
478
     *
479
     * @param guid
480
     * @param rev
481
     * @return
482
     */
483
    public String generateLocalId(String guid, int rev)
484
    {
485
        return generateLocalId(guid, rev, false);
486
    }
487 5286 jones
488
    /**
489
     * Given a global identifier (guid), create a suitable local identifier that
490
     * follows Metacat's docid semantics and format (scope.id.rev), and create
491
     * a mapping between these two identifiers.  This effectively reserves both
492
     * the global and the local identifier, as they will now be present in the
493
     * identifier mapping table.  If the incoming guid has the syntax of a
494
     * Metacat docid (scope.id.rev), then simply use it.
495
     *
496
     * @param guid the global string identifier
497
     * @param rev the revision number to be used in the localId
498
     * @return String containing the localId to be used for Metacat operations
499
     */
500 5453 berkley
    public String generateLocalId(String guid, int rev, boolean isSystemMetadata)
501 5286 jones
    {
502
        String localId = "";
503
        boolean conformsToDocidFormat = false;
504
505
        // Check if the guid passed in is already in docid (scope.id.rev) format
506
        try {
507
            AccessionNumber acc = new AccessionNumber(guid, "NONE");
508
            if (new Integer(acc.getRev()).intValue() > 0) {
509
                conformsToDocidFormat = true;
510
            }
511
        } catch (NumberFormatException e) {
512
            // No action needed, simply detecting invalid AccessionNumbers
513
        } catch (AccessionNumberException e) {
514
            // No action needed, simply detecting invalid AccessionNumbers
515
        } catch (SQLException e) {
516
            // No action needed, simply detecting invalid AccessionNumbers
517
        }
518
519
        if (conformsToDocidFormat) {
520
            // if it conforms, use it for both guid and localId
521
            localId = guid;
522
        } else {
523
            // if not, then generate a new unique localId
524
            localId = DocumentUtil.generateDocumentId(rev);
525
        }
526
527
        // Register this new pair in the identifier mapping table
528 5453 berkley
        System.out.println("creating mapping in generateLocalId");
529
        if(!isSystemMetadata)
530
        { //don't do this if we're generating for system metadata
531
            createMapping(guid, localId);
532
        }
533 5286 jones
534
        return localId;
535
    }
536 5322 berkley
537
    /**
538
     * given a local identifer, look up the guid.  Throw McdbDocNotFoundException
539 5452 berkley
     * if the docid, rev is not found in the identifiers or systemmetadata tables
540 5322 berkley
     *
541
     * @param docid the docid to look up
542
     * @param rev the revision of the docid to look up
543
     * @return String containing the mapped guid
544
     * @throws McdbDocNotFoundException if the docid, rev is not found
545
     */
546
    public String getGUID(String docid, int rev)
547
      throws McdbDocNotFoundException
548
    {
549 5798 berkley
        System.out.println("getting guid for " + docid);
550 5322 berkley
        String query = "select guid from identifier where docid = ? and rev = ?";
551
        String guid = null;
552 5451 berkley
        boolean found = false;
553 5322 berkley
554
        DBConnection dbConn = null;
555
        int serialNumber = -1;
556
        try {
557
            // Get a database connection from the pool
558 5377 berkley
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getGUID");
559 5322 berkley
            serialNumber = dbConn.getCheckOutSerialNumber();
560
561
            // Execute the insert statement
562
            PreparedStatement stmt = dbConn.prepareStatement(query);
563
            stmt.setString(1, docid);
564
            stmt.setInt(2, rev);
565
            ResultSet rs = stmt.executeQuery();
566 5451 berkley
            if (rs.next())
567
            {
568 5322 berkley
                guid = rs.getString(1);
569 5451 berkley
            }
570
            else
571
            {
572
                query = "select guid from systemmetadata where docid = ? and rev = ?";
573
                stmt = dbConn.prepareStatement(query);
574
                stmt.setString(1, docid);
575
                stmt.setInt(2, rev);
576 5452 berkley
                rs = stmt.executeQuery();
577 5451 berkley
                if(rs.next())
578
                {
579
                    guid = rs.getString(1);
580
                }
581
                else
582
                {
583
                    throw new McdbDocNotFoundException("No guid registered for docid " + docid + "." + rev);
584
                }
585 5322 berkley
            }
586 5451 berkley
587 5322 berkley
        } catch (SQLException e) {
588
            logMetacat.error("Error while looking up the guid: "
589
                    + e.getMessage());
590
        } finally {
591
            // Return database connection to the pool
592
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
593
        }
594
595
        return guid;
596
    }
597 5333 berkley
598
    /**
599 5887 berkley
     * creates a mapping for a system metadata document, but DOES NOT add any
600
     * of the extra system metadata information to the table.  You must call
601
     * insertAdditionalSystemMetadataFields to complete the entry
602 5333 berkley
     *
603
     * @param guid the id to insert
604
     * @param localId the systemMetadata object to get the local id for
605
     */
606
    public void createSystemMetadataMapping(String guid, String localId)
607
    {
608 5334 berkley
        createGenericMapping(guid, localId, TYPE_SYSTEM_METADATA);
609
    }
610
611 5377 berkley
    /**
612 5887 berkley
     * creates a system metadata mapping and adds additional fields from sysmeta
613
     * to the table for quick searching.
614
     *
615
     * @param guid the id to insert
616
     * @param localId the systemMetadata object to get the local id for
617
     */
618
    public void createSystemMetadataMapping(SystemMetadata sysmeta, String localId)
619
    {
620
        createGenericMapping(sysmeta.getIdentifier().getValue(), localId, TYPE_SYSTEM_METADATA);
621
        insertAdditionalSystemMetadataFields(sysmeta);
622
    }
623
624
    /**
625 6079 leinfelder
     * update a system metadata mapping
626 5377 berkley
     * @param guid
627
     * @param localId
628
     */
629 5350 berkley
    public void updateSystemMetadataMapping(String guid, String localId)
630
    {
631 6079 leinfelder
    	updateMapping(guid, localId, TYPE_SYSTEM_METADATA);
632
    }
633
634
    /**
635
     * update a mapping
636
     * @param guid
637
     * @param localId
638
     */
639
    public void updateMapping(String guid, String localId)
640
    {
641
    	updateMapping(guid, localId, TYPE_IDENTIFIER);
642
    }
643
644
    /**
645
     * update a mapping
646
     * @param guid
647
     * @param localId
648
     */
649
    private void updateMapping(String guid, String localId, String type)
650
    {
651
    	if (!type.equals(TYPE_IDENTIFIER) && !type.equals(TYPE_SYSTEM_METADATA)) {
652
    		throw new RuntimeException("Cannot create mapping for type " + type +
653
    		            ".  Please choose 'identifier' or 'systemmetadata'.");
654
    	}
655
656
        System.out.println("$$$$$$$$$$$$$$ updating mapping table");
657 5350 berkley
        int serialNumber = -1;
658
        DBConnection dbConn = null;
659
        try {
660
            // Parse the localId into scope and rev parts
661
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
662
            String docid = acc.getDocid();
663
            int rev = 1;
664
            if(acc.getRev() != null)
665
            {
666
              rev = (new Integer(acc.getRev()).intValue());
667
            }
668
669
            // Get a database connection from the pool
670
            dbConn =
671 6079 leinfelder
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
672 5350 berkley
            serialNumber = dbConn.getCheckOutSerialNumber();
673
674
            // Execute the insert statement
675 6079 leinfelder
            String query = "update " + type + " set (docid, rev) = (?, ?) where guid='" + guid + "'";
676 5352 berkley
            //System.out.println("query: " + query + " for params: (guid:" + guid + ", docid=" + docid + ", rev=" + rev + ")");
677 5350 berkley
            PreparedStatement stmt = dbConn.prepareStatement(query);
678
            stmt.setString(1, docid);
679
            stmt.setInt(2, rev);
680
            int rows = stmt.executeUpdate();
681
682
            stmt.close();
683
        } catch (SQLException e) {
684
            e.printStackTrace();
685 6079 leinfelder
            logMetacat.error("SQL error while updating a mapping identifier: "
686 5350 berkley
                    + e.getMessage());
687
        } catch (NumberFormatException e) {
688
            e.printStackTrace();
689 6079 leinfelder
            logMetacat.error("NumberFormat error while updating a mapping identifier: "
690 5350 berkley
                    + e.getMessage());
691
        } catch (AccessionNumberException e) {
692
            e.printStackTrace();
693 6079 leinfelder
            logMetacat.error("AccessionNumber error while updating a mapping identifier: "
694 5350 berkley
                    + e.getMessage());
695
        } finally {
696
            // Return database connection to the pool
697
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
698
        }
699 6079 leinfelder
        System.out.println("done updating mapping");
700 5350 berkley
    }
701 5334 berkley
702
    /**
703
     * return the localId of a system metadata document based on its guid
704
     */
705 5424 berkley
    public String getSystemMetadataLocalId(String guid)
706 5334 berkley
      throws McdbDocNotFoundException
707
    {
708 5424 berkley
      return this.getLocalId(guid, TYPE_SYSTEM_METADATA);
709 5334 berkley
    }
710
711 5887 berkley
    public void insertAdditionalSystemMetadataFields(long dateUploaded, String rightsHolder,
712
            String checksum, String checksumAlgorithm, String originMemberNode,
713 5917 berkley
            String authoritativeMemberNode, long modifiedDate, String submitter,
714
            String guid, String objectFormat, long size)
715 5887 berkley
    {
716
        DBConnection dbConn = null;
717
        int serialNumber = -1;
718 5957 berkley
719 5887 berkley
        try {
720
            // Get a database connection from the pool
721
            dbConn =
722
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
723
            serialNumber = dbConn.getCheckOutSerialNumber();
724
725
            // Execute the insert statement
726
            String query = "update " + TYPE_SYSTEM_METADATA +
727
                " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
728 5917 berkley
                "origin_member_node, authoritive_member_node, date_modified, " +
729
                "submitter, object_format, size) " +
730
                "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
731 5887 berkley
            PreparedStatement stmt = dbConn.prepareStatement(query);
732
733
            //data values
734
            stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
735
            stmt.setString(2, rightsHolder);
736
            stmt.setString(3, checksum);
737
            stmt.setString(4, checksumAlgorithm);
738
            stmt.setString(5, originMemberNode);
739
            stmt.setString(6, authoritativeMemberNode);
740
            stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
741
            stmt.setString(8, submitter);
742 5917 berkley
            stmt.setString(9, objectFormat);
743
            stmt.setString(10, new Long(size).toString());
744 5887 berkley
            //where clause
745 5917 berkley
            stmt.setString(11, guid);
746 5887 berkley
            System.out.println("stmt: " + stmt.toString());
747
            //execute
748
            int rows = stmt.executeUpdate();
749
750
            stmt.close();
751
        } catch (SQLException e) {
752
            e.printStackTrace();
753 5950 berkley
            logMetacat.error("insertAdditionalSystemMetadataFields: SQL error while creating a mapping to the system metadata identifier: "
754 5887 berkley
                    + e.getMessage());
755
        } catch (NumberFormatException e) {
756
            e.printStackTrace();
757 5950 berkley
            logMetacat.error("insertAdditionalSystemMetadataFields: NumberFormat error while creating a mapping to the system metadata identifier: "
758 5887 berkley
                    + e.getMessage());
759
        } finally {
760
            // Return database connection to the pool
761
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
762
        }
763
    }
764
765 5334 berkley
    /**
766 5887 berkley
     * Insert the system metadata fields into the db
767
     * @param sm
768
     */
769
    public void insertAdditionalSystemMetadataFields(SystemMetadata sm)
770
    {
771
        insertAdditionalSystemMetadataFields(
772
                sm.getDateUploaded().getTime(),
773
                sm.getRightsHolder().getValue(),
774
                sm.getChecksum().getValue(),
775
                sm.getChecksum().getAlgorithm().name(),
776
                sm.getOriginMemberNode().getValue(),
777
                sm.getAuthoritativeMemberNode().getValue(),
778
                sm.getDateSysMetadataModified().getTime(),
779
                sm.getSubmitter().getValue(),
780 5917 berkley
                sm.getIdentifier().getValue(),
781
                sm.getObjectFormat().toString(),
782
                sm.getSize());
783 5887 berkley
    }
784
785
    /**
786 5334 berkley
     * return a localId based on a guid.  The type can either be 'identifier'
787
     * to get an id from the identifier table or 'systemmetadata' to get
788
     * the identifier from the systemidentifier table
789
     */
790 5424 berkley
    private String getLocalId(String guid, String type)
791 5334 berkley
      throws McdbDocNotFoundException
792
    {
793
      if(!type.equals(TYPE_IDENTIFIER) &&
794
        !type.equals(TYPE_SYSTEM_METADATA))
795
      {
796
        throw new RuntimeException("cannot lookup the identifier for type " + type +
797
          ".  Please choose 'identifier' or 'systemmetadata'.");
798
      }
799
800
      String db_guid = "";
801
      String docid = "";
802
      int rev = 0;
803
804
      String query = "select guid, docid, rev from " + type + " where guid = ?";
805 5352 berkley
      //System.out.println("query: " + query + " for params: (" + guid + ")");
806 5334 berkley
807
      DBConnection dbConn = null;
808 5333 berkley
      int serialNumber = -1;
809 5334 berkley
      try {
810
          // Get a database connection from the pool
811
          dbConn = DBConnectionPool.getDBConnection("Identifier.getLocalId");
812
          serialNumber = dbConn.getCheckOutSerialNumber();
813
814
          // Execute the insert statement
815
          PreparedStatement stmt = dbConn.prepareStatement(query);
816
          stmt.setString(1, guid);
817
          ResultSet rs = stmt.executeQuery();
818
          if (rs.next()) {
819
              db_guid = rs.getString(1);
820
              docid = rs.getString(2);
821
              rev = rs.getInt(3);
822
              assert(db_guid.equals(guid));
823
          } else {
824
              throw new McdbDocNotFoundException("Document not found:" + guid);
825
          }
826
          stmt.close();
827
      } catch (SQLException e) {
828
          logMetacat.error("Error while looking up the local identifier: "
829
                  + e.getMessage());
830
      } finally {
831
          // Return database connection to the pool
832
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
833
      }
834
      return docid + "." + rev;
835
    }
836
837 5377 berkley
    /**
838 5895 berkley
     * query the systemmetadata table based on the given parameters
839
     * @param startTime
840
     * @param endTime
841
     * @param objectFormat
842
     * @param replicaStatus
843
     * @param start
844
     * @param count
845
     * @return ObjectList
846
     */
847
    public ObjectList querySystemMetadata(Date startTime, Date endTime,
848
            ObjectFormat objectFormat, boolean replicaStatus, int start, int count)
849
    {
850
        ObjectList ol = new ObjectList();
851
        int total = 0;
852 5943 berkley
        DBConnection dbConn = null;
853
        int serialNumber = -1;
854 5895 berkley
855
        try
856
        {
857
            String sql = "select guid, date_uploaded, rights_holder, checksum, " +
858
                "checksum_algorithm, origin_member_node, authoritive_member_node, " +
859 5917 berkley
                "date_modified, submitter, object_format, size from systemmetadata";
860 5895 berkley
861
            boolean f1 = false;
862
            boolean f2 = false;
863
            boolean f3 = false;
864
865
            if(startTime != null)
866
            {
867 5917 berkley
                sql += " where systemmetadata.date_modified > ?";
868 5895 berkley
                f1 = true;
869
            }
870
871
            if(endTime != null)
872
            {
873 5917 berkley
                if(!f1)
874
                {
875
                    sql += " where systemmetadata.date_modified < ?";
876
                }
877
                else
878
                {
879
                    sql += " and systemmetadata.date_modified < ?";
880
                }
881 5895 berkley
                f2 = true;
882
            }
883
884
            if(objectFormat != null)
885
            {
886 5917 berkley
                if(!f1 && !f2)
887
                {
888
                    sql += " where object_format = ?";
889
                }
890
                else
891
                {
892
                    sql += " and object_format = ?";
893
                }
894 5895 berkley
                f3 = true;
895
            }
896
897
            if(replicaStatus)
898
            {
899
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.memberNodeId");
900 5917 berkley
                if(!f1 && !f2 && !f3)
901
                {
902
                    sql += " where authoritive_member_node != '" + currentNodeId.trim() + "'";
903
                }
904
                else
905
                {
906
                    sql += " and authoritive_member_node != '" + currentNodeId.trim() + "'";
907
                }
908 5895 berkley
            }
909
910 5943 berkley
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.querySystemMetadata");
911
            serialNumber = dbConn.getCheckOutSerialNumber();
912 5895 berkley
            PreparedStatement stmt = dbConn.prepareStatement(sql);
913
914
            if(f1 && f2 && f3)
915
            {
916
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
917
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
918
                stmt.setString(3, objectFormat.toString());
919
            }
920
            else if(f1 && f2 && !f3)
921
            {
922
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
923
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
924
            }
925
            else if(f1 && !f2 && f3)
926
            {
927
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
928
                stmt.setString(2, objectFormat.toString());
929
            }
930
            else if(f1 && !f2 && !f3)
931
            {
932
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
933
            }
934
            else if(!f1 && f2 && f3)
935
            {
936
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
937
                stmt.setString(2, objectFormat.toString());
938
            }
939
            else if(!f1 && !f2 && f3)
940
            {
941
                stmt.setString(1, objectFormat.toString());
942
            }
943
            else if(!f1 && f2 && !f3)
944
            {
945
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
946
            }
947
948
            //System.out.println("LISTOBJECTS QUERY: " + stmt.toString());
949
950
            ResultSet rs = stmt.executeQuery();
951 5917 berkley
            for(int i=0; i<start; i++)
952 5895 berkley
            {
953 5917 berkley
                if(rs.next())
954
                {
955
                    total++;
956
                }
957
                else
958
                {
959
                    break;
960
                }
961 5895 berkley
            }
962 5917 berkley
963 5895 berkley
            int countIndex = 0;
964
965
            while(rs.next())
966
            {
967
                total++;
968
                if(countIndex >= count)
969
                {
970
                    break;
971
                }
972
                String guid = rs.getString(1);
973
                //System.out.println("query found doc with guid " + guid);
974
                //Timestamp dateUploaded = rs.getTimestamp(2);
975
                //String rightsHolder = rs.getString(3);
976
                String checksum = rs.getString(4);
977
                String checksumAlgorithm = rs.getString(5);
978
                //String originMemberNode = rs.getString(6);
979
                String authoritiveMemberNode = rs.getString(7);
980
                Timestamp dateModified = rs.getTimestamp(8);
981
                //String submitter = rs.getString(9);
982
                String format = rs.getString(10);
983 5917 berkley
                String sz = rs.getString(11);
984
                long size = 0;
985
                if(sz != null && !sz.trim().equals(""))
986
                {
987
                    size = new Long(rs.getString(11)).longValue();
988
                }
989 5895 berkley
990
                ObjectInfo oi = new ObjectInfo();
991
992
                Identifier id = new Identifier();
993
                id.setValue(guid);
994
                oi.setIdentifier(id);
995
996
                oi.setDateSysMetadataModified(new Date(dateModified.getTime()));
997
998
                Checksum cs = new Checksum();
999
                cs.setValue(checksum);
1000 5906 berkley
                cs.setAlgorithm(ChecksumAlgorithm.valueOf(checksumAlgorithm));
1001 5957 berkley
                //cs.setAlgorithm(ChecksumAlgorithm.convert(checksumAlgorithm));
1002 5895 berkley
                oi.setChecksum(cs);
1003
1004
                ObjectFormat oFormat = ObjectFormat.convert(format);
1005
                if(oFormat != null)
1006
                {
1007
                    oi.setObjectFormat(oFormat);
1008
                }
1009 5906 berkley
                else
1010
                { //if there is no object format, just default to text/plain
1011 5917 berkley
                    oi.setObjectFormat(ObjectFormat.OCTET_STREAM);
1012 5906 berkley
                }
1013 5917 berkley
1014
                oi.setSize(size);
1015 5895 berkley
1016
                ol.addObjectInfo(oi);
1017
                countIndex++;
1018
            }
1019
1020
            while(rs.next())
1021
            { //expend the resultset to get the total count of possible rows
1022
                total++;
1023
            }
1024
        }
1025
        catch(Exception e)
1026
        {
1027
           e.printStackTrace();
1028
           System.out.println("Error querying system metadata: " + e.getMessage());
1029
        }
1030 5943 berkley
        finally
1031
        {
1032
            // Return database connection to the pool
1033
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1034
        }
1035 5895 berkley
1036
        ol.setStart(start);
1037 5922 berkley
        ol.setCount(ol.sizeObjectInfoList());
1038 5895 berkley
        ol.setTotal(total);
1039
1040
        return ol;
1041
    }
1042
1043
    /**
1044 5377 berkley
     * create a mapping in the systemmetadata or identifier table
1045
     * @param guid
1046
     * @param localId
1047
     * @param type
1048
     */
1049 5334 berkley
    private void createGenericMapping(String guid, String localId, String type)
1050 5453 berkley
    {
1051 5334 berkley
        if(!type.equals(TYPE_IDENTIFIER) &&
1052
        !type.equals(TYPE_SYSTEM_METADATA))
1053
        {
1054
          throw new RuntimeException("Cannot create mapping for type " + type +
1055
            ".  Please choose 'identifier' or 'systemmetadata'.");
1056
        }
1057
1058
        int serialNumber = -1;
1059 5333 berkley
        DBConnection dbConn = null;
1060
        try {
1061
1062
            // Parse the localId into scope and rev parts
1063
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1064
            String docid = acc.getDocid();
1065 5344 berkley
            int rev = 1;
1066
            if(acc.getRev() != null)
1067
            {
1068
              rev = (new Integer(acc.getRev()).intValue());
1069
            }
1070 5333 berkley
1071
            // Get a database connection from the pool
1072
            dbConn =
1073 5377 berkley
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1074 5333 berkley
            serialNumber = dbConn.getCheckOutSerialNumber();
1075
1076
            // Execute the insert statement
1077 5344 berkley
            String query = "insert into " + type + " (guid, docid, rev) values (?, ?, ?)";
1078 5352 berkley
            //System.out.println("query: " + query + " for params: (" + guid + ", " + docid + ", " + rev + ")");
1079 5333 berkley
            PreparedStatement stmt = dbConn.prepareStatement(query);
1080
            stmt.setString(1, guid);
1081
            stmt.setString(2, docid);
1082
            stmt.setInt(3, rev);
1083 5887 berkley
            System.out.println("generic mapping query: " + stmt.toString());
1084 5333 berkley
            int rows = stmt.executeUpdate();
1085
1086
            stmt.close();
1087
        } catch (SQLException e) {
1088 5344 berkley
            e.printStackTrace();
1089 5950 berkley
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + type + " identifier: "
1090 5333 berkley
                    + e.getMessage());
1091
        } catch (NumberFormatException e) {
1092 5344 berkley
            e.printStackTrace();
1093 5950 berkley
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + type + " identifier: "
1094 5333 berkley
                    + e.getMessage());
1095
        } catch (AccessionNumberException e) {
1096 5344 berkley
            e.printStackTrace();
1097 5950 berkley
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + type + " identifier: "
1098 5333 berkley
                    + e.getMessage());
1099
        } finally {
1100
            // Return database connection to the pool
1101
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1102
        }
1103
    }
1104 5282 jones
}