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 6384 cjones
import java.math.BigInteger;
28 5282 jones
import java.sql.PreparedStatement;
29
import java.sql.ResultSet;
30
import java.sql.SQLException;
31 5895 berkley
import java.sql.Timestamp;
32 6107 leinfelder
import java.util.ArrayList;
33
import java.util.Date;
34
import java.util.Hashtable;
35
import java.util.List;
36
import java.util.Vector;
37 5282 jones
38
import org.apache.log4j.Logger;
39 8810 leinfelder
import org.dataone.client.v2.formats.ObjectFormatCache;
40 7010 cjones
import org.dataone.service.exceptions.BaseException;
41 6904 cjones
import org.dataone.service.exceptions.InvalidSystemMetadata;
42 6366 leinfelder
import org.dataone.service.types.v1.AccessPolicy;
43
import org.dataone.service.types.v1.AccessRule;
44
import org.dataone.service.types.v1.Checksum;
45
import org.dataone.service.types.v1.Identifier;
46
import org.dataone.service.types.v1.NodeReference;
47
import org.dataone.service.types.v1.ObjectFormatIdentifier;
48
import org.dataone.service.types.v1.ObjectInfo;
49
import org.dataone.service.types.v1.ObjectList;
50
import org.dataone.service.types.v1.Permission;
51
import org.dataone.service.types.v1.Replica;
52
import org.dataone.service.types.v1.ReplicationPolicy;
53
import org.dataone.service.types.v1.ReplicationStatus;
54
import org.dataone.service.types.v1.Subject;
55 8810 leinfelder
import org.dataone.service.types.v2.SystemMetadata;
56 5282 jones
57 6108 leinfelder
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessAccess;
58 5282 jones
import edu.ucsb.nceas.metacat.database.DBConnection;
59
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
60 7438 leinfelder
import edu.ucsb.nceas.metacat.database.DatabaseService;
61 5887 berkley
import edu.ucsb.nceas.metacat.properties.PropertyService;
62 6108 leinfelder
import edu.ucsb.nceas.metacat.shared.AccessException;
63 6299 leinfelder
import edu.ucsb.nceas.metacat.shared.ServiceException;
64 5286 jones
import edu.ucsb.nceas.metacat.util.DocumentUtil;
65 6299 leinfelder
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
66 7475 leinfelder
import edu.ucsb.nceas.utilities.access.AccessControlInterface;
67
import edu.ucsb.nceas.utilities.access.XMLAccessDAO;
68 5282 jones
69
/**
70
 * Manage the relationship between Metacat local identifiers (LocalIDs) that are
71 6099 leinfelder
 * codified as the (docid, rev) pair with globally unique string identifiers
72 5282 jones
 * (GUIDs) that are opaque strings.  This class provides methods to manage these
73
 * identifiers, and to search for and look up LocalIDs based on their GUID and
74
 * vice versa. IdentifierManager is a singleton.
75
 *
76
 * @author Matthew Jones
77
 */
78
public class IdentifierManager {
79
80 5334 berkley
    public static final String TYPE_SYSTEM_METADATA = "systemmetadata";
81
    public static final String TYPE_IDENTIFIER = "identifier";
82
83 5282 jones
    /**
84
     * The single instance of the manager that is always returned.
85
     */
86
    private static IdentifierManager self = null;
87 6099 leinfelder
    private Logger logMetacat = Logger.getLogger(IdentifierManager.class);
88 5282 jones
89
    /**
90
     * A private constructor that initializes the class when getInstance() is
91
     * called.
92
     */
93 6099 leinfelder
    private IdentifierManager() {}
94 5282 jones
95
    /**
96
     * Return the single instance of the manager after initializing it if it
97
     * wasn't previously initialized.
98
     *
99
     * @return the single IdentifierManager instance
100
     */
101
    public static IdentifierManager getInstance()
102
    {
103
        if (self == null) {
104
            self = new IdentifierManager();
105
        }
106
        return self;
107
    }
108
109 6097 leinfelder
    public SystemMetadata asSystemMetadata(Date dateUploaded, String rightsHolder,
110
            String checksum, String checksumAlgorithm, String originMemberNode,
111
            String authoritativeMemberNode, Date dateModified, String submitter,
112 6561 leinfelder
            String guid, String fmtidStr, BigInteger size, BigInteger serialVersion) {
113 6097 leinfelder
        SystemMetadata sysMeta = new SystemMetadata();
114
115
        Identifier sysMetaId = new Identifier();
116
        sysMetaId.setValue(guid);
117
        sysMeta.setIdentifier(sysMetaId);
118
        sysMeta.setDateUploaded(dateUploaded);
119
        Subject rightsHolderSubject = new Subject();
120
        rightsHolderSubject.setValue(rightsHolder);
121
        sysMeta.setRightsHolder(rightsHolderSubject);
122
        Checksum checksumObject = new Checksum();
123
        checksumObject.setValue(checksum);
124 6397 leinfelder
        checksumObject.setAlgorithm(checksumAlgorithm);
125 6097 leinfelder
        sysMeta.setChecksum(checksumObject);
126
        NodeReference omn = new NodeReference();
127
        omn.setValue(originMemberNode);
128
        sysMeta.setOriginMemberNode(omn);
129
        NodeReference amn = new NodeReference();
130
        amn.setValue(authoritativeMemberNode);
131
        sysMeta.setAuthoritativeMemberNode(amn);
132
        sysMeta.setDateSysMetadataModified(dateModified);
133
        Subject submitterSubject = new Subject();
134
        submitterSubject.setValue(submitter);
135
        sysMeta.setSubmitter(submitterSubject);
136 7010 cjones
        ObjectFormatIdentifier fmtid = null;
137 6124 cjones
        try {
138 7010 cjones
        	ObjectFormatIdentifier formatId = new ObjectFormatIdentifier();
139
        	formatId.setValue(fmtidStr);
140
        	fmtid = ObjectFormatCache.getInstance().getFormat(formatId).getFormatId();
141 6561 leinfelder
        	sysMeta.setFormatId(fmtid);
142 7010 cjones
143
        } catch (BaseException nfe) {
144
            logMetacat.error("The objectFormat " + fmtidStr +
145 6384 cjones
          	" is not registered. Setting the default format id.");
146 7010 cjones
            fmtid = new ObjectFormatIdentifier();
147
            fmtid.setValue("application/octet-stream");
148
            sysMeta.setFormatId(fmtid);
149
150 6124 cjones
        }
151 6097 leinfelder
        sysMeta.setSize(size);
152 6561 leinfelder
        sysMeta.setSerialVersion(serialVersion);
153 6097 leinfelder
154
        return sysMeta;
155
    }
156
157 5282 jones
    /**
158 5895 berkley
     * return a hash of all of the info that is in the systemmetadata table
159
     * @param localId
160
     * @return
161
     */
162
    public Hashtable<String, String> getSystemMetadataInfo(String localId)
163
    throws McdbDocNotFoundException
164
    {
165
        try
166
        {
167
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
168
            localId = acc.getDocid();
169
        }
170
        catch(Exception e)
171
        {
172
            //do nothing. just try the localId as it is
173
        }
174
        Hashtable<String, String> h = new Hashtable<String, String>();
175
        String sql = "select guid, date_uploaded, rights_holder, checksum, checksum_algorithm, " +
176 5944 berkley
          "origin_member_node, authoritive_member_node, date_modified, submitter, object_format, size " +
177 5895 berkley
          "from systemmetadata where docid = ?";
178
        DBConnection dbConn = null;
179
        int serialNumber = -1;
180
        try
181
        {
182
            // Get a database connection from the pool
183
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getDocumentInfo");
184
            serialNumber = dbConn.getCheckOutSerialNumber();
185
186
            // Execute the insert statement
187
            PreparedStatement stmt = dbConn.prepareStatement(sql);
188
            stmt.setString(1, localId);
189
            ResultSet rs = stmt.executeQuery();
190
            if (rs.next())
191
            {
192
                String guid = rs.getString(1);
193
                Timestamp dateUploaded = rs.getTimestamp(2);
194
                String rightsHolder = rs.getString(3);
195
                String checksum = rs.getString(4);
196
                String checksumAlgorithm = rs.getString(5);
197
                String originMemberNode = rs.getString(6);
198
                String authoritativeMemberNode = rs.getString(7);
199
                Timestamp dateModified = rs.getTimestamp(8);
200
                String submitter = rs.getString(9);
201 5917 berkley
                String objectFormat = rs.getString(10);
202
                long size = new Long(rs.getString(11)).longValue();
203 5895 berkley
204
                h.put("guid", guid);
205
                h.put("date_uploaded", new Long(dateUploaded.getTime()).toString());
206
                h.put("rights_holder", rightsHolder);
207
                h.put("checksum", checksum);
208
                h.put("checksum_algorithm", checksumAlgorithm);
209
                h.put("origin_member_node", originMemberNode);
210
                h.put("authoritative_member_node", authoritativeMemberNode);
211
                h.put("date_modified", new Long(dateModified.getTime()).toString());
212
                h.put("submitter", submitter);
213 5917 berkley
                h.put("object_format", objectFormat);
214
                h.put("size", new Long(size).toString());
215 5895 berkley
216
                stmt.close();
217
            }
218
            else
219
            {
220
                stmt.close();
221
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
222
                throw new McdbDocNotFoundException("2Could not find document " + localId);
223
            }
224
225
        }
226
        catch (SQLException e)
227
        {
228
            e.printStackTrace();
229
            logMetacat.error("Error while getting system metadata info for localid " + localId + " : "
230
                    + e.getMessage());
231
        }
232
        finally
233
        {
234
            // Return database connection to the pool
235
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
236
        }
237
        return h;
238
    }
239
240
    /**
241 6097 leinfelder
     * return a hash of all of the info that is in the systemmetadata table
242 6099 leinfelder
     * @param guid
243 6097 leinfelder
     * @return
244 6108 leinfelder
     * @throws McdbDocNotFoundException
245 6097 leinfelder
     */
246 6099 leinfelder
    public SystemMetadata getSystemMetadata(String guid)
247 6097 leinfelder
    	throws McdbDocNotFoundException
248
    {
249 6099 leinfelder
250 6097 leinfelder
        SystemMetadata sysMeta = new SystemMetadata();
251
        String sql = "select guid, date_uploaded, rights_holder, checksum, checksum_algorithm, " +
252 6375 leinfelder
          "origin_member_node, authoritive_member_node, date_modified, submitter, object_format, size, " +
253 9038 tao
          "replication_allowed, number_replicas, obsoletes, obsoleted_by, serial_version, archived, series_id " +
254 6099 leinfelder
          "from systemmetadata where guid = ?";
255 6097 leinfelder
        DBConnection dbConn = null;
256
        int serialNumber = -1;
257 6533 cjones
        Boolean replicationAllowed = new Boolean(false);
258
        BigInteger numberOfReplicas = new BigInteger("-1");
259 6561 leinfelder
        BigInteger serialVersion = new BigInteger("-1");
260 7428 leinfelder
        Boolean archived = new Boolean(false);
261 6561 leinfelder
262 6097 leinfelder
        try
263
        {
264
            // Get a database connection from the pool
265
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getSystemMetadata");
266
            serialNumber = dbConn.getCheckOutSerialNumber();
267
268
            // Execute the statement
269
            PreparedStatement stmt = dbConn.prepareStatement(sql);
270 6099 leinfelder
            stmt.setString(1, guid);
271 6097 leinfelder
            ResultSet rs = stmt.executeQuery();
272
            if (rs.next())
273
            {
274
                Timestamp dateUploaded = rs.getTimestamp(2);
275
                String rightsHolder = rs.getString(3);
276
                String checksum = rs.getString(4);
277
                String checksumAlgorithm = rs.getString(5);
278
                String originMemberNode = rs.getString(6);
279
                String authoritativeMemberNode = rs.getString(7);
280
                Timestamp dateModified = rs.getTimestamp(8);
281
                String submitter = rs.getString(9);
282 6296 cjones
                String fmtidStr = rs.getString(10);
283 6384 cjones
                BigInteger size = new BigInteger(rs.getString(11));
284 6535 cjones
                replicationAllowed = new Boolean(rs.getBoolean(12));
285 6533 cjones
                numberOfReplicas = new BigInteger(rs.getString(13));
286
                String obsoletes = rs.getString(14);
287
                String obsoletedBy = rs.getString(15);
288 6561 leinfelder
                serialVersion = new BigInteger(rs.getString(16));
289 7428 leinfelder
                archived = new Boolean(rs.getBoolean(17));
290 9038 tao
                String series_id = rs.getString(18);
291 6375 leinfelder
292 6097 leinfelder
                Identifier sysMetaId = new Identifier();
293
                sysMetaId.setValue(guid);
294
                sysMeta.setIdentifier(sysMetaId);
295 6561 leinfelder
                sysMeta.setSerialVersion(serialVersion);
296 6097 leinfelder
                sysMeta.setDateUploaded(dateUploaded);
297
                Subject rightsHolderSubject = new Subject();
298
                rightsHolderSubject.setValue(rightsHolder);
299
                sysMeta.setRightsHolder(rightsHolderSubject);
300
                Checksum checksumObject = new Checksum();
301
                checksumObject.setValue(checksum);
302 6397 leinfelder
                checksumObject.setAlgorithm(checksumAlgorithm);
303 6097 leinfelder
                sysMeta.setChecksum(checksumObject);
304 6519 leinfelder
                if (originMemberNode != null) {
305
	                NodeReference omn = new NodeReference();
306
	                omn.setValue(originMemberNode);
307
	                sysMeta.setOriginMemberNode(omn);
308
                }
309
                if (authoritativeMemberNode != null) {
310
	                NodeReference amn = new NodeReference();
311
	                amn.setValue(authoritativeMemberNode);
312
	                sysMeta.setAuthoritativeMemberNode(amn);
313
                }
314 6097 leinfelder
                sysMeta.setDateSysMetadataModified(dateModified);
315 7639 leinfelder
                if (submitter != null) {
316
	                Subject submitterSubject = new Subject();
317
	                submitterSubject.setValue(submitter);
318
	                sysMeta.setSubmitter(submitterSubject);
319
                }
320 7023 leinfelder
                ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
321
                fmtid.setValue(fmtidStr);
322
            	sysMeta.setFormatId(fmtid);
323 6097 leinfelder
                sysMeta.setSize(size);
324 6423 leinfelder
                if (obsoletes != null) {
325
	                Identifier obsoletesId = new Identifier();
326
	                obsoletesId.setValue(obsoletes);
327
	                sysMeta.setObsoletes(obsoletesId);
328
                }
329
                if (obsoletedBy != null) {
330
		            Identifier obsoletedById = new Identifier();
331
		            obsoletedById.setValue(obsoletedBy);
332
		            sysMeta.setObsoletedBy(obsoletedById);
333
                }
334 7428 leinfelder
                sysMeta.setArchived(archived);
335 9038 tao
                if(series_id != null) {
336
                    Identifier seriesId = new Identifier();
337
                    seriesId.setValue(series_id);
338
                    sysMeta.setSeriesId(seriesId);
339
                }
340 6097 leinfelder
                stmt.close();
341
            }
342
            else
343
            {
344
                stmt.close();
345
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
346 6099 leinfelder
                throw new McdbDocNotFoundException("Could not find " + guid);
347 6097 leinfelder
            }
348
349
        }
350
        catch (SQLException e)
351
        {
352
            e.printStackTrace();
353 6099 leinfelder
            logMetacat.error("Error while getting system metadata for guid " + guid + " : "
354 6097 leinfelder
                    + e.getMessage());
355
        }
356
        finally
357
        {
358
            // Return database connection to the pool
359
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
360
        }
361 6377 leinfelder
362 6533 cjones
        // populate the replication policy
363 6107 leinfelder
        ReplicationPolicy replicationPolicy = new ReplicationPolicy();
364 6533 cjones
        if ( numberOfReplicas != null  && numberOfReplicas.intValue() != -1 ) {
365
            replicationPolicy.setNumberReplicas(numberOfReplicas.intValue());
366
367
        }
368
369
        if ( replicationAllowed != null ) {
370
            replicationPolicy.setReplicationAllowed(replicationAllowed);
371
372
        }
373 6107 leinfelder
        replicationPolicy.setBlockedMemberNodeList(getReplicationPolicy(guid, "blocked"));
374
        replicationPolicy.setPreferredMemberNodeList(getReplicationPolicy(guid, "preferred"));
375 6533 cjones
		    sysMeta.setReplicationPolicy(replicationPolicy);
376 6107 leinfelder
377 6533 cjones
		    // look up replication status
378
		    sysMeta.setReplicaList(getReplicationStatus(guid));
379 6108 leinfelder
380 6533 cjones
		    // look up access policy
381
		    try {
382
		    	sysMeta.setAccessPolicy(getAccessPolicy(guid));
383
		    } catch (AccessException e) {
384
		    	throw new McdbDocNotFoundException(e);
385
		    }
386 6107 leinfelder
387 6097 leinfelder
        return sysMeta;
388
    }
389
390
391 6107 leinfelder
    private List<NodeReference> getReplicationPolicy(String guid, String policy)
392
		throws McdbDocNotFoundException {
393
394
		List<NodeReference> nodes = new ArrayList<NodeReference>();
395
		String sql = "select guid, policy, member_node " +
396 7392 leinfelder
			"from smReplicationPolicy where guid = ? and policy = ?";
397 6107 leinfelder
	    DBConnection dbConn = null;
398
	    int serialNumber = -1;
399
	    try {
400
	        // Get a database connection from the pool
401
	        dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getReplicationPolicy");
402
	        serialNumber = dbConn.getCheckOutSerialNumber();
403
404
	        // Execute the statement
405
	        PreparedStatement stmt = dbConn.prepareStatement(sql);
406
	        stmt.setString(1, guid);
407
	        stmt.setString(2, policy);
408
	        ResultSet rs = stmt.executeQuery();
409
	        while (rs.next())
410
	        {
411
	            String memberNode = rs.getString(3);
412
	            NodeReference node = new NodeReference();
413
	            node.setValue(memberNode);
414
	            nodes.add(node);
415
416
	        }
417
	        stmt.close();
418
419
	    } catch (SQLException e) {
420
	        logMetacat.error("Error while getting system metadata replication policy for guid " + guid, e);
421
	    }
422
	    finally {
423
	        // Return database connection to the pool
424
	        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
425
	    }
426
427
	    return nodes;
428
	}
429 6097 leinfelder
430 6107 leinfelder
    private List<Replica> getReplicationStatus(String guid) throws McdbDocNotFoundException {
431
432
		List<Replica> replicas = new ArrayList<Replica>();
433
		String sql = "select guid, member_node, status, date_verified " +
434 7392 leinfelder
			"from smReplicationStatus where guid = ?";
435 6107 leinfelder
	    DBConnection dbConn = null;
436
	    int serialNumber = -1;
437
	    try {
438
	        // Get a database connection from the pool
439
	        dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getReplicas");
440
	        serialNumber = dbConn.getCheckOutSerialNumber();
441
442
	        // Execute the statement
443
	        PreparedStatement stmt = dbConn.prepareStatement(sql);
444
	        stmt.setString(1, guid);
445
	        ResultSet rs = stmt.executeQuery();
446
	        while (rs.next())
447
	        {
448
	            String memberNode = rs.getString(2);
449
	            String status = rs.getString(3);
450 7399 cjones
	            java.sql.Timestamp verified = rs.getTimestamp(4);
451 6107 leinfelder
452
	            Replica replica = new Replica();
453
	            NodeReference node = new NodeReference();
454
	            node.setValue(memberNode);
455
	            replica.setReplicaMemberNode(node);
456 6454 leinfelder
	            replica.setReplicationStatus(ReplicationStatus.valueOf(status));
457 6107 leinfelder
	            replica.setReplicaVerified(new Date(verified.getTime()));
458
	            replicas.add(replica);
459
	        }
460
	        stmt.close();
461
462
	    } catch (SQLException e) {
463
	        logMetacat.error("Error while getting system metadata replication policy for guid " + guid, e);
464
	    }
465
	    finally {
466
	        // Return database connection to the pool
467
	        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
468
	    }
469
470
	    return replicas;
471
	}
472
473 5378 berkley
474
    /**
475
     * return the newest rev for a given localId
476
     * @param localId
477
     * @return
478
     */
479
    public int getLatestRevForLocalId(String localId)
480
        throws McdbDocNotFoundException
481
    {
482 5798 berkley
        try
483
        {
484
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
485
            localId = acc.getDocid();
486
        }
487
        catch(Exception e)
488
        {
489
            //do nothing. just try the localId as it is
490
        }
491 5378 berkley
        int rev = 0;
492 6595 leinfelder
        String sql = "select rev from xml_documents where docid like ? ";
493 5378 berkley
        DBConnection dbConn = null;
494
        int serialNumber = -1;
495
        try
496
        {
497
            // Get a database connection from the pool
498
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLatestRevForLocalId");
499
            serialNumber = dbConn.getCheckOutSerialNumber();
500
501
            // Execute the insert statement
502
            PreparedStatement stmt = dbConn.prepareStatement(sql);
503 6595 leinfelder
            stmt.setString(1, localId);
504 5378 berkley
            ResultSet rs = stmt.executeQuery();
505
            if (rs.next())
506
            {
507
                rev = rs.getInt(1);
508
                stmt.close();
509
            }
510
            else
511
            {
512
                stmt.close();
513
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
514 5798 berkley
                throw new McdbDocNotFoundException("While trying to get the latest rev, could not find document " + localId);
515 5378 berkley
            }
516
        }
517
        catch (SQLException e)
518
        {
519
            logMetacat.error("Error while looking up the guid: "
520
                    + e.getMessage());
521
        }
522
        finally
523
        {
524
            // Return database connection to the pool
525
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
526
        }
527
        return rev;
528
    }
529
530
    /**
531 5377 berkley
     * return all local ids in the object store that do not have associated
532 6099 leinfelder
     * system metadata
533 5377 berkley
     */
534 7168 leinfelder
    public List<String> getLocalIdsWithNoSystemMetadata(boolean includeRevisions, int serverLocation)
535 5377 berkley
    {
536
        Vector<String> ids = new Vector<String>();
537 6099 leinfelder
        String sql = "select docid, rev from xml_documents " +
538
        		"where docid not in " +
539 6720 leinfelder
        		"(select docid from identifier where guid in (select guid from systemmetadata))";
540 7168 leinfelder
        if (serverLocation > 0) {
541
        	sql = sql + " and server_location = ? ";
542
        }
543 6704 leinfelder
544 6745 leinfelder
        String revisionSql = "select docid, rev from xml_revisions " +
545 6704 leinfelder
				"where docid not in " +
546 6720 leinfelder
				"(select docid from identifier where guid in (select guid from systemmetadata))";
547 7168 leinfelder
        if (serverLocation > 0) {
548
        	revisionSql = revisionSql + " and server_location = ? ";
549
        }
550 6704 leinfelder
551
        if (includeRevisions) {
552
        	sql = sql + " UNION ALL " + revisionSql;
553
        }
554
555 5377 berkley
        DBConnection dbConn = null;
556
        int serialNumber = -1;
557
        try
558
        {
559
            // Get a database connection from the pool
560
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLocalIdsWithNoSystemMetadata");
561
            serialNumber = dbConn.getCheckOutSerialNumber();
562
563
            // Execute the insert statement
564
            PreparedStatement stmt = dbConn.prepareStatement(sql);
565 7168 leinfelder
            // set params based on what we have in the query string
566
            if (serverLocation > 0) {
567
            	stmt.setInt(1, serverLocation);
568
            	if (includeRevisions) {
569
            		stmt.setInt(2, serverLocation);
570
            	}
571
            }
572 5377 berkley
            ResultSet rs = stmt.executeQuery();
573
            while (rs.next())
574
            {
575
                String localid = rs.getString(1);
576 5798 berkley
                String rev = rs.getString(2);
577
                localid += "." + rev;
578 6099 leinfelder
                logMetacat.debug("id to add SM for: " + localid);
579 5377 berkley
                ids.add(localid);
580
            }
581
            stmt.close();
582
        }
583
        catch (SQLException e)
584
        {
585
            logMetacat.error("Error while looking up the guid: "
586
                    + e.getMessage());
587
        }
588
        finally
589
        {
590
            // Return database connection to the pool
591
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
592
        }
593
594
        return ids;
595
    }
596
597
    /**
598
     * return a listing of all local ids in the object store
599
     * @return a list of all local ids in metacat
600
     */
601
    public List<String> getAllLocalIds()
602 6416 rnahf
    // seems to be an unnecessary and restrictive throw -rnahf 13-Sep-2011
603
    //    throws Exception
604 5377 berkley
    {
605
        Vector<String> ids = new Vector<String>();
606
        String sql = "select docid from xml_documents";
607
        DBConnection dbConn = null;
608
        int serialNumber = -1;
609
        try
610
        {
611
            // Get a database connection from the pool
612
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getAllLocalIds");
613
            serialNumber = dbConn.getCheckOutSerialNumber();
614
615
            // Execute the insert statement
616
            PreparedStatement stmt = dbConn.prepareStatement(sql);
617
            ResultSet rs = stmt.executeQuery();
618
            while (rs.next())
619
            {
620
                String localid = rs.getString(1);
621
                ids.add(localid);
622
            }
623
            stmt.close();
624
        }
625
        catch (SQLException e)
626
        {
627
            logMetacat.error("Error while looking up the guid: "
628
                    + e.getMessage());
629
        }
630
        finally
631
        {
632
            // Return database connection to the pool
633
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
634
        }
635
        return ids;
636
    }
637
638 6416 rnahf
639 6118 leinfelder
    /**
640 6416 rnahf
     * return a listing of all guids in the object store
641
     * @return a list of all GUIDs in metacat
642
     */
643 7187 leinfelder
    public List<String> getAllSystemMetadataGUIDs()
644 6416 rnahf
    {
645
        Vector<String> guids = new Vector<String>();
646 7187 leinfelder
        String sql = "select guid from systemmetadata";
647 6416 rnahf
        DBConnection dbConn = null;
648
        int serialNumber = -1;
649
        try
650
        {
651
            // Get a database connection from the pool
652
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getAllGUIDs");
653
            serialNumber = dbConn.getCheckOutSerialNumber();
654
655
            // Execute the insert statement
656
            PreparedStatement stmt = dbConn.prepareStatement(sql);
657
            ResultSet rs = stmt.executeQuery();
658
            while (rs.next())
659
            {
660
                String guid = rs.getString(1);
661
                guids.add(guid);
662
            }
663
            stmt.close();
664
        }
665
        catch (SQLException e)
666
        {
667
            logMetacat.error("Error while retrieving the guid: "
668
                    + e.getMessage());
669
        }
670
        finally
671
        {
672
            // Return database connection to the pool
673
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
674
        }
675
        return guids;
676
    }
677
678
679
680
    /**
681 6118 leinfelder
     * returns a list of system metadata-only guids since the given date
682
     * @return a list of system ids in metacat that do not correspond to objects
683
     * TODO: need to check which server they are on
684
     */
685
    public List<String> getUpdatedSystemMetadataIds(Date since)
686
       throws Exception
687
    {
688
        List<String> ids = new Vector<String>();
689
        String sql =
690
        	"select guid from " + TYPE_SYSTEM_METADATA +
691
        	" where guid not in " +
692
        	" (select guid from " + TYPE_IDENTIFIER + ") " +
693
        	" and date_modified > ?";
694
        DBConnection dbConn = null;
695
        int serialNumber = -1;
696
        try
697
        {
698
            // Get a database connection from the pool
699
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getUpdatedSystemMetadataIds");
700
            serialNumber = dbConn.getCheckOutSerialNumber();
701 6099 leinfelder
702 6118 leinfelder
            // Execute the insert statement
703
            PreparedStatement stmt = dbConn.prepareStatement(sql);
704
            stmt.setDate(1, new java.sql.Date(since.getTime()));
705
            ResultSet rs = stmt.executeQuery();
706
            while (rs.next())
707
            {
708
                String guid = rs.getString(1);
709
                ids.add(guid);
710
            }
711
            stmt.close();
712
        }
713
        catch (SQLException e)
714
        {
715
            logMetacat.error("Error while looking up the updated guids: "
716
                    + e.getMessage());
717
        }
718
        finally
719
        {
720
            // Return database connection to the pool
721
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
722
        }
723
        return ids;
724
    }
725 5282 jones
726 6459 leinfelder
    /**
727
     * returns a list of system metadata-only guids since the given date
728
     * @return a list of system ids in metacat that do not correspond to objects
729
     * TODO: need to check which server they are on
730
     */
731
    public Date getLastModifiedDate() throws Exception {
732
        Date maxDate = null;
733 6118 leinfelder
734 6459 leinfelder
        List<String> ids = new Vector<String>();
735
        String sql =
736
        	"select max(date_modified) from " + TYPE_SYSTEM_METADATA;
737
        DBConnection dbConn = null;
738
        int serialNumber = -1;
739
        try
740
        {
741
            // Get a database connection from the pool
742
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLastModifiedDate");
743
            serialNumber = dbConn.getCheckOutSerialNumber();
744
745
            // Execute the insert statement
746
            PreparedStatement stmt = dbConn.prepareStatement(sql);
747
            ResultSet rs = stmt.executeQuery();
748
            if (rs.next()) {
749
            	maxDate = rs.getDate(1);
750
            }
751
            stmt.close();
752
        }
753
        catch (SQLException e)
754
        {
755
            logMetacat.error("Error while looking up the latest update date: "
756
                    + e.getMessage());
757
        }
758
        finally
759
        {
760
            // Return database connection to the pool
761
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
762
        }
763
        return maxDate;
764
    }
765
766 6118 leinfelder
767 5282 jones
    /**
768
     * Determine if an identifier exists already, returning true if so.
769 7045 leinfelder
     * NOTE: looks in the identifier and system metadata table for a match
770
     * (in that order)
771 5282 jones
     *
772
     * @param guid the global identifier to look up
773
     * @return boolean true if the identifier exists
774
     */
775 9017 tao
    public boolean identifierExists(String guid) throws SQLException
776 5282 jones
    {
777
        boolean idExists = false;
778
        try {
779
            String id = getLocalId(guid);
780
            if (id != null) {
781
                idExists = true;
782
            }
783
        } catch (McdbDocNotFoundException e) {
784 6123 leinfelder
        	// try system metadata only
785 9017 tao
        	    //this will check if the guid field on the system metadata table has the id
786 9030 tao
        		idExists = systemMetadataPIDExists(guid);
787 9017 tao
        		if(!idExists) {
788
        		    //if the guid field of the system metadata table doesn't have the id,
789
        		    //we will check if the serial_id field of the system metadata table has it
790
        		    idExists=systemMetadataSIDExists(guid);
791
        		}
792
793 5282 jones
        }
794
        return idExists;
795
    }
796
797
    /**
798 7045 leinfelder
     * Determine if an identifier mapping exists already,
799
     * returning true if so.
800 5282 jones
     *
801 7045 leinfelder
     * @param guid the global identifier to look up
802
     * @return boolean true if the identifier exists
803
     */
804 9024 tao
    public boolean mappingExists(String guid) throws SQLException
805 7045 leinfelder
    {
806
        boolean idExists = false;
807
        try {
808
            String id = getLocalId(guid);
809
            if (id != null) {
810
                idExists = true;
811
            }
812
        } catch (McdbDocNotFoundException e) {
813
        	// nope!
814
        }
815
        return idExists;
816
    }
817
818
    /**
819
     *
820 5453 berkley
     * @param guid
821
     * @param rev
822
     * @return
823
     */
824
    public String generateLocalId(String guid, int rev)
825
    {
826
        return generateLocalId(guid, rev, false);
827
    }
828 5286 jones
829
    /**
830
     * Given a global identifier (guid), create a suitable local identifier that
831
     * follows Metacat's docid semantics and format (scope.id.rev), and create
832
     * a mapping between these two identifiers.  This effectively reserves both
833
     * the global and the local identifier, as they will now be present in the
834 7070 leinfelder
     * identifier mapping table.
835
     *
836
     * REMOVED feature: If the incoming guid has the syntax of a
837 5286 jones
     * Metacat docid (scope.id.rev), then simply use it.
838 7070 leinfelder
     * WHY: because "test.1.001" becomes "test.1.1" which is not correct for DataONE
839
     * identifier use (those revision numbers are just chartacters and should not be interpreted)
840 5286 jones
     *
841
     * @param guid the global string identifier
842
     * @param rev the revision number to be used in the localId
843
     * @return String containing the localId to be used for Metacat operations
844
     */
845 5453 berkley
    public String generateLocalId(String guid, int rev, boolean isSystemMetadata)
846 5286 jones
    {
847
        String localId = "";
848
        boolean conformsToDocidFormat = false;
849
850 7070 leinfelder
        // BRL -- do not allow Metacat-conforming IDs to be used:
851
        // test.1.001 becomes test.1.1 which is NOT correct for DataONE identifiers
852 5286 jones
        // Check if the guid passed in is already in docid (scope.id.rev) format
853 7070 leinfelder
//        try {
854
//            AccessionNumber acc = new AccessionNumber(guid, "NONE");
855
//            if (new Integer(acc.getRev()).intValue() > 0) {
856
//                conformsToDocidFormat = true;
857
//            }
858
//        } catch (NumberFormatException e) {
859
//            // No action needed, simply detecting invalid AccessionNumbers
860
//        } catch (AccessionNumberException e) {
861
//            // No action needed, simply detecting invalid AccessionNumbers
862
//        } catch (SQLException e) {
863
//            // No action needed, simply detecting invalid AccessionNumbers
864
//        }
865 5286 jones
866
        if (conformsToDocidFormat) {
867
            // if it conforms, use it for both guid and localId
868
            localId = guid;
869
        } else {
870
            // if not, then generate a new unique localId
871
            localId = DocumentUtil.generateDocumentId(rev);
872
        }
873
874
        // Register this new pair in the identifier mapping table
875 6099 leinfelder
        logMetacat.debug("creating mapping in generateLocalId");
876 5453 berkley
        if(!isSystemMetadata)
877
        { //don't do this if we're generating for system metadata
878
            createMapping(guid, localId);
879
        }
880 5286 jones
881
        return localId;
882
    }
883 5322 berkley
884
    /**
885
     * given a local identifer, look up the guid.  Throw McdbDocNotFoundException
886 5452 berkley
     * if the docid, rev is not found in the identifiers or systemmetadata tables
887 5322 berkley
     *
888
     * @param docid the docid to look up
889
     * @param rev the revision of the docid to look up
890
     * @return String containing the mapped guid
891
     * @throws McdbDocNotFoundException if the docid, rev is not found
892
     */
893
    public String getGUID(String docid, int rev)
894
      throws McdbDocNotFoundException
895
    {
896 6099 leinfelder
        logMetacat.debug("getting guid for " + docid);
897 5322 berkley
        String query = "select guid from identifier where docid = ? and rev = ?";
898
        String guid = null;
899
900
        DBConnection dbConn = null;
901
        int serialNumber = -1;
902
        try {
903
            // Get a database connection from the pool
904 5377 berkley
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getGUID");
905 5322 berkley
            serialNumber = dbConn.getCheckOutSerialNumber();
906
907
            // Execute the insert statement
908
            PreparedStatement stmt = dbConn.prepareStatement(query);
909
            stmt.setString(1, docid);
910
            stmt.setInt(2, rev);
911
            ResultSet rs = stmt.executeQuery();
912 5451 berkley
            if (rs.next())
913
            {
914 5322 berkley
                guid = rs.getString(1);
915 5451 berkley
            }
916
            else
917
            {
918 6104 leinfelder
            	throw new McdbDocNotFoundException("No guid registered for docid " + docid + "." + rev);
919 5322 berkley
            }
920 5451 berkley
921 5322 berkley
        } catch (SQLException e) {
922
            logMetacat.error("Error while looking up the guid: "
923
                    + e.getMessage());
924
        } finally {
925
            // Return database connection to the pool
926
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
927
        }
928
929
        return guid;
930
    }
931 5333 berkley
932 9015 tao
    /**
933
     * Get the pid of the head (current) version of objects match the specified sid.
934
     * DataONE defines the latest version as "current" if the object in question has
935
     * a matching SID and no value in the "obsoletedBy" field, regardless if it is "archived" or not.
936 9026 tao
     * If we can't find any pid associated with the sid doesn't have a value in obsoletedBy field,
937
     * the pid associated with the sid  which has the max date_uploaded will be returned
938 9015 tao
     * @param sid specified sid which should match.
939
     * @return the pid of the head version. The null will be returned if there is no pid found.
940 9016 tao
     * @throws SQLException
941 9015 tao
     */
942 9016 tao
    public Identifier getHeadPID(Identifier sid) throws SQLException {
943 9015 tao
        Identifier pid = null;
944
        if(sid != null && sid.getValue() != null && !sid.getValue().trim().equals("")) {
945
            logMetacat.debug("getting pid of the head version for matching the sid: " + sid.getValue());
946
            String sql = "select guid from systemMetadata where obsoleted_by is null and series_id = ?";
947
            DBConnection dbConn = null;
948
            int serialNumber = -1;
949
            try {
950
                // Get a database connection from the pool
951
                dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getHeadPID");
952
                serialNumber = dbConn.getCheckOutSerialNumber();
953
                // Execute the insert statement
954
                PreparedStatement stmt = dbConn.prepareStatement(sql);
955
                stmt.setString(1, sid.getValue());
956
                ResultSet rs = stmt.executeQuery();
957
                if (rs.next())
958
                {
959
                    pid = new Identifier();
960
                    pid.setValue(rs.getString(1));
961
962 9026 tao
                } else {
963
                    //we don't find any pid associated with the sid doesn't have value in obsoletedBy field.
964
                    //The pid associated with the sid  which has the max date_uploaded will be returned.
965
                    sql = "select guid from systemMetadata where series_id = ? and date_uploaded=(select max(date_uploaded) from systemMetadata where series_id = ?)";
966
                    stmt = dbConn.prepareStatement(sql);
967
                    stmt.setString(1, sid.getValue());
968
                    stmt.setString(2, sid.getValue());
969
                    rs = stmt.executeQuery();
970
                    if(rs.next()) {
971
                        pid = new Identifier();
972
                        pid.setValue(rs.getString(1));
973
                    }
974
                }
975 9015 tao
976
            } catch (SQLException e) {
977
                logMetacat.error("Error while get the head pid for the sid "+sid.getValue()+" : "
978
                        + e.getMessage());
979 9016 tao
                throw e;
980 9015 tao
            } finally {
981
                // Return database connection to the pool
982
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
983
            }
984
        }
985
        return pid;
986
    }
987
988 9016 tao
    /**
989 9032 tao
     * Check if the specified sid object exists on the serial id field on the system metadata table
990
     * @param sid
991
     * @return true if it exists; false otherwise.
992
     * @throws SQLException
993
     */
994
    public boolean systemMetadataSIDExists(Identifier sid) throws SQLException {
995
        if (sid != null && sid.getValue() != null && !sid.getValue().trim().equals("")) {
996
            return systemMetadataSIDExists(sid.getValue());
997
        } else {
998
            return false;
999
        }
1000
    }
1001
1002
    /**
1003 9016 tao
     * Check if the specified sid exists on the serial id field on the system metadata table
1004
     * @param id
1005
     * @return true if it exists; false otherwise.
1006
     */
1007 9017 tao
    public boolean systemMetadataSIDExists(String sid) throws SQLException {
1008 9016 tao
        boolean exists = false;
1009 9032 tao
        logMetacat.debug("Check if the  sid: " + sid +" exists on the series_id field of the system metadata table.");
1010 9016 tao
        if(sid != null && !sid.trim().equals("")) {
1011
            String sql = "select guid from systemMetadata where series_id = ?";
1012
            DBConnection dbConn = null;
1013
            int serialNumber = -1;
1014
            try {
1015
                // Get a database connection from the pool
1016
                dbConn = DBConnectionPool.getDBConnection("IdentifierManager.serialIdExists");
1017
                serialNumber = dbConn.getCheckOutSerialNumber();
1018
                // Execute the insert statement
1019
                PreparedStatement stmt = dbConn.prepareStatement(sql);
1020
                stmt.setString(1, sid);
1021
                ResultSet rs = stmt.executeQuery();
1022
                if (rs.next())
1023
                {
1024
                    exists = true;
1025
                }
1026
1027
            } catch (SQLException e) {
1028
                logMetacat.error("Error while checking if the sid "+sid+" exists on the series_id field of the system metadata table: "
1029
                        + e.getMessage());
1030
                throw e;
1031
            } finally {
1032
                // Return database connection to the pool
1033
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1034
            }
1035
        }
1036
        return exists;
1037
    }
1038
1039 9032 tao
    /**
1040
     * Determine if the specified identifier object exists or not.
1041
     * @param pid - the specified identifier
1042
     * @return true if it is exists.
1043
     * @throws SQLException
1044
     * @throws NullPointerException
1045
     */
1046
    public boolean systemMetadataPIDExists(Identifier pid) throws SQLException {
1047
        if (pid != null && pid.getValue() != null && !pid.getValue().trim().equals("")) {
1048
            return systemMetadataPIDExists(pid.getValue());
1049
        } else {
1050
            return false;
1051
        }
1052
    }
1053
1054 9030 tao
    public boolean systemMetadataPIDExists(String guid) throws SQLException {
1055 6123 leinfelder
		logMetacat.debug("looking up system metadata for guid " + guid);
1056
		boolean exists = false;
1057 6337 leinfelder
		String query = "select guid from systemmetadata where guid = ?";
1058 6123 leinfelder
		DBConnection dbConn = null;
1059
		int serialNumber = -1;
1060 9032 tao
		if(guid != null && !guid.trim().equals("")) {
1061
		    try {
1062
	            // Get a database connection from the pool
1063
	            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.systemMetadataExisits");
1064
	            serialNumber = dbConn.getCheckOutSerialNumber();
1065 6123 leinfelder
1066 9032 tao
	            // Execute the insert statement
1067
	            PreparedStatement stmt = dbConn.prepareStatement(query);
1068
	            stmt.setString(1, guid);
1069
	            ResultSet rs = stmt.executeQuery();
1070
	            if (rs.next()) {
1071
	                exists = true;
1072
	            }
1073 6123 leinfelder
1074 9032 tao
	        } catch (SQLException e) {
1075
	            logMetacat.error("Error while looking up the system metadata: "
1076
	                    + e.getMessage());
1077
	            throw e;
1078
	        } finally {
1079
	            // Return database connection to the pool
1080
	            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1081
	        }
1082 6123 leinfelder
		}
1083
		return exists;
1084
	}
1085
1086 5333 berkley
    /**
1087 5887 berkley
     * creates a system metadata mapping and adds additional fields from sysmeta
1088
     * to the table for quick searching.
1089
     *
1090
     * @param guid the id to insert
1091
     * @param localId the systemMetadata object to get the local id for
1092 6108 leinfelder
     * @throws McdbDocNotFoundException
1093 6892 cjones
     * @throws SQLException
1094 6904 cjones
     * @throws InvalidSystemMetadata
1095 5887 berkley
     */
1096 7188 leinfelder
    public void insertOrUpdateSystemMetadata(SystemMetadata sysmeta)
1097 6904 cjones
        throws McdbDocNotFoundException, SQLException, InvalidSystemMetadata {
1098 6277 leinfelder
    	String guid = sysmeta.getIdentifier().getValue();
1099 7188 leinfelder
1100
    	 // Get a database connection from the pool
1101
        DBConnection dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1102
        int serialNumber = dbConn.getCheckOutSerialNumber();
1103 6892 cjones
1104 7188 leinfelder
        try {
1105
        	// use a single transaction for it all
1106
        	dbConn.setAutoCommit(false);
1107
1108
	    	// insert the record if needed
1109 9030 tao
        	if (!IdentifierManager.getInstance().systemMetadataPIDExists(guid)) {
1110 7188 leinfelder
    	        insertSystemMetadata(guid, dbConn);
1111
			}
1112
	        // update with the values
1113
	        updateSystemMetadata(sysmeta, dbConn);
1114
1115
	        // commit if we got here with no errors
1116
	        dbConn.commit();
1117
        } catch (Exception e) {
1118
            e.printStackTrace();
1119
            logMetacat.error("Error while creating " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1120
            dbConn.rollback();
1121
        } finally {
1122
            // Return database connection to the pool
1123
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1124
        }
1125
1126
1127 5887 berkley
    }
1128 6099 leinfelder
1129 5887 berkley
1130
    /**
1131 6079 leinfelder
     * update a mapping
1132
     * @param guid
1133
     * @param localId
1134
     */
1135
    public void updateMapping(String guid, String localId)
1136
    {
1137
1138 6099 leinfelder
        logMetacat.debug("$$$$$$$$$$$$$$ updating mapping table");
1139 5350 berkley
        int serialNumber = -1;
1140
        DBConnection dbConn = null;
1141
        try {
1142
            // Parse the localId into scope and rev parts
1143
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1144
            String docid = acc.getDocid();
1145
            int rev = 1;
1146
            if(acc.getRev() != null)
1147
            {
1148
              rev = (new Integer(acc.getRev()).intValue());
1149
            }
1150
1151
            // Get a database connection from the pool
1152
            dbConn =
1153 6079 leinfelder
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
1154 5350 berkley
            serialNumber = dbConn.getCheckOutSerialNumber();
1155
1156 6099 leinfelder
            // Execute the update statement
1157 6595 leinfelder
            String query = "update " + TYPE_IDENTIFIER + " set (docid, rev) = (?, ?) where guid = ?";
1158 5350 berkley
            PreparedStatement stmt = dbConn.prepareStatement(query);
1159
            stmt.setString(1, docid);
1160
            stmt.setInt(2, rev);
1161 6595 leinfelder
            stmt.setString(3, guid);
1162 5350 berkley
            int rows = stmt.executeUpdate();
1163
1164
            stmt.close();
1165
        } catch (SQLException e) {
1166
            e.printStackTrace();
1167 6079 leinfelder
            logMetacat.error("SQL error while updating a mapping identifier: "
1168 5350 berkley
                    + e.getMessage());
1169
        } catch (NumberFormatException e) {
1170
            e.printStackTrace();
1171 6079 leinfelder
            logMetacat.error("NumberFormat error while updating a mapping identifier: "
1172 5350 berkley
                    + e.getMessage());
1173
        } catch (AccessionNumberException e) {
1174
            e.printStackTrace();
1175 6079 leinfelder
            logMetacat.error("AccessionNumber error while updating a mapping identifier: "
1176 5350 berkley
                    + e.getMessage());
1177
        } finally {
1178
            // Return database connection to the pool
1179
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1180
        }
1181 6099 leinfelder
        logMetacat.debug("done updating mapping");
1182 5350 berkley
    }
1183 6099 leinfelder
1184
    private void updateSystemMetadataFields(long dateUploaded, String rightsHolder,
1185 6892 cjones
        String checksum, String checksumAlgorithm, String originMemberNode,
1186
        String authoritativeMemberNode, long modifiedDate, String submitter,
1187
        String guid, String objectFormat, BigInteger size, boolean archived,
1188
        boolean replicationAllowed, int numberReplicas, String obsoletes,
1189 8810 leinfelder
        String obsoletedBy, BigInteger serialVersion, String seriesId, DBConnection dbConn) throws SQLException  {
1190 7188 leinfelder
1191
        // Execute the insert statement
1192
        String query = "update " + TYPE_SYSTEM_METADATA +
1193
            " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
1194
            "origin_member_node, authoritive_member_node, date_modified, " +
1195
            "submitter, object_format, size, archived, replication_allowed, number_replicas, " +
1196 8810 leinfelder
            "obsoletes, obsoleted_by, serial_version, series_id) " +
1197
            "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
1198 7188 leinfelder
        PreparedStatement stmt = dbConn.prepareStatement(query);
1199 6892 cjones
1200 7188 leinfelder
        //data values
1201
        stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
1202
        stmt.setString(2, rightsHolder);
1203
        stmt.setString(3, checksum);
1204
        stmt.setString(4, checksumAlgorithm);
1205
        stmt.setString(5, originMemberNode);
1206
        stmt.setString(6, authoritativeMemberNode);
1207
        stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
1208
        stmt.setString(8, submitter);
1209
        stmt.setString(9, objectFormat);
1210
        stmt.setString(10, size.toString());
1211
        stmt.setBoolean(11, archived);
1212
        stmt.setBoolean(12, replicationAllowed);
1213
        stmt.setInt(13, numberReplicas);
1214
        stmt.setString(14, obsoletes);
1215
        stmt.setString(15, obsoletedBy);
1216
        stmt.setString(16, serialVersion.toString());
1217 8810 leinfelder
        stmt.setString(17, seriesId);
1218 7188 leinfelder
1219 8810 leinfelder
1220 7188 leinfelder
        //where clause
1221 8810 leinfelder
        stmt.setString(18, guid);
1222 7188 leinfelder
        logMetacat.debug("stmt: " + stmt.toString());
1223
        //execute
1224
        int rows = stmt.executeUpdate();
1225
1226
        stmt.close();
1227
1228
    }
1229
1230
    private void insertReplicationPolicy(String guid, String policy, List<String> memberNodes, DBConnection dbConn) throws SQLException
1231
    {
1232
1233
        // remove existing values first
1234 7392 leinfelder
        String delete = "delete from smReplicationPolicy " +
1235 7188 leinfelder
        "where guid = ? and policy = ?";
1236
        PreparedStatement stmt = dbConn.prepareStatement(delete);
1237
        //data values
1238
        stmt.setString(1, guid);
1239
        stmt.setString(2, policy);
1240
        //execute
1241
        int deletedCount = stmt.executeUpdate();
1242
        stmt.close();
1243 5957 berkley
1244 7188 leinfelder
        for (String memberNode: memberNodes) {
1245 5887 berkley
            // Execute the insert statement
1246 7392 leinfelder
            String insert = "insert into smReplicationPolicy " +
1247 7188 leinfelder
                "(guid, policy, member_node) " +
1248
                "values (?, ?, ?)";
1249
            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1250 5887 berkley
1251
            //data values
1252 7188 leinfelder
            insertStatement.setString(1, guid);
1253
            insertStatement.setString(2, policy);
1254
            insertStatement.setString(3, memberNode);
1255
1256 7392 leinfelder
            logMetacat.debug("smReplicationPolicy sql: " + insertStatement.toString());
1257 6375 leinfelder
1258 5887 berkley
            //execute
1259 7188 leinfelder
            int rows = insertStatement.executeUpdate();
1260
            insertStatement.close();
1261 5887 berkley
        }
1262 7188 leinfelder
1263 5887 berkley
    }
1264
1265 7188 leinfelder
    private void insertReplicationStatus(String guid, List<Replica> replicas, DBConnection dbConn) throws SQLException {
1266
1267
        // remove existing values first
1268 7392 leinfelder
        String delete = "delete from smReplicationStatus " +
1269 7188 leinfelder
        "where guid = ?";
1270
        PreparedStatement stmt = dbConn.prepareStatement(delete);
1271
        //data values
1272
        stmt.setString(1, guid);
1273
        //execute
1274
        int deletedCount = stmt.executeUpdate();
1275
        stmt.close();
1276 6107 leinfelder
1277 7188 leinfelder
        if (replicas != null) {
1278
            for (Replica replica: replicas) {
1279 6107 leinfelder
	            // Execute the insert statement
1280 7392 leinfelder
	            String insert = "insert into smReplicationStatus " +
1281 7188 leinfelder
	                "(guid, member_node, status, date_verified) " +
1282
	                "values (?, ?, ?, ?)";
1283 6107 leinfelder
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1284
1285
	            //data values
1286 7188 leinfelder
	            String memberNode = replica.getReplicaMemberNode().getValue();
1287
	            String status = replica.getReplicationStatus().toString();
1288 7399 cjones
	            java.sql.Timestamp sqlDate = new java.sql.Timestamp(replica.getReplicaVerified().getTime());
1289 6107 leinfelder
	            insertStatement.setString(1, guid);
1290 7188 leinfelder
	            insertStatement.setString(2, memberNode);
1291
	            insertStatement.setString(3, status);
1292 7399 cjones
	            insertStatement.setTimestamp(4, sqlDate);
1293 7188 leinfelder
1294 7392 leinfelder
	            logMetacat.debug("smReplicationStatus sql: " + insertStatement.toString());
1295 7102 leinfelder
1296 6107 leinfelder
	            //execute
1297
	            int rows = insertStatement.executeUpdate();
1298
	            insertStatement.close();
1299
            }
1300
        }
1301 7188 leinfelder
1302 6107 leinfelder
    }
1303
1304 5334 berkley
    /**
1305 5887 berkley
     * Insert the system metadata fields into the db
1306
     * @param sm
1307 6108 leinfelder
     * @throws McdbDocNotFoundException
1308 6892 cjones
     * @throws SQLException
1309 6904 cjones
     * @throws InvalidSystemMetadata
1310 7188 leinfelder
     * @throws AccessException
1311 5887 berkley
     */
1312 7188 leinfelder
    public void updateSystemMetadata(SystemMetadata sm, DBConnection dbConn)
1313
      throws McdbDocNotFoundException, SQLException, InvalidSystemMetadata, AccessException {
1314 6107 leinfelder
1315 6892 cjones
      Boolean replicationAllowed = false;
1316
		  Integer numberReplicas = -1;
1317 6107 leinfelder
    	ReplicationPolicy replicationPolicy = sm.getReplicationPolicy();
1318
    	if (replicationPolicy != null) {
1319
    		replicationAllowed = replicationPolicy.getReplicationAllowed();
1320
    		numberReplicas = replicationPolicy.getNumberReplicas();
1321
    		replicationAllowed = replicationAllowed == null ? false: replicationAllowed;
1322
    		numberReplicas = numberReplicas == null ? -1: numberReplicas;
1323
    	}
1324 6904 cjones
1325 6107 leinfelder
    	// the main systemMetadata fields
1326 6892 cjones
		  updateSystemMetadataFields(
1327 6311 leinfelder
				sm.getDateUploaded() == null ? null: sm.getDateUploaded().getTime(),
1328
				sm.getRightsHolder() == null ? null: sm.getRightsHolder().getValue(),
1329
				sm.getChecksum() == null ? null: sm.getChecksum().getValue(),
1330 6397 leinfelder
				sm.getChecksum() == null ? null: sm.getChecksum().getAlgorithm(),
1331 6311 leinfelder
				sm.getOriginMemberNode() == null ? null: sm.getOriginMemberNode().getValue(),
1332
				sm.getAuthoritativeMemberNode() == null ? null: sm.getAuthoritativeMemberNode().getValue(),
1333
				sm.getDateSysMetadataModified() == null ? null: sm.getDateSysMetadataModified().getTime(),
1334
				sm.getSubmitter() == null ? null: sm.getSubmitter().getValue(),
1335 6904 cjones
		    sm.getIdentifier().getValue(),
1336
		    sm.getFormatId() == null ? null: sm.getFormatId().getValue(),
1337
		    sm.getSize(),
1338
		    sm.getArchived() == null ? false: sm.getArchived(),
1339
		    replicationAllowed,
1340
		    numberReplicas,
1341
		    sm.getObsoletes() == null ? null:sm.getObsoletes().getValue(),
1342
		    sm.getObsoletedBy() == null ? null: sm.getObsoletedBy().getValue(),
1343 7188 leinfelder
		    sm.getSerialVersion(),
1344 8810 leinfelder
		    sm.getSeriesId() == null ? null: sm.getSeriesId().getValue(),
1345 7188 leinfelder
		    dbConn
1346 6561 leinfelder
        );
1347 6097 leinfelder
1348
        String guid = sm.getIdentifier().getValue();
1349
1350 6107 leinfelder
        // save replication policies
1351
        if (replicationPolicy != null) {
1352
		    List<String> nodes = null;
1353
		    String policy = null;
1354
1355 6494 leinfelder
		    // check for null
1356
		    if (replicationPolicy.getBlockedMemberNodeList() != null) {
1357
			    nodes = new ArrayList<String>();
1358
			    policy = "blocked";
1359
			    for (NodeReference node: replicationPolicy.getBlockedMemberNodeList()) {
1360
			    	nodes.add(node.getValue());
1361
			    }
1362 7188 leinfelder
			    this.insertReplicationPolicy(guid, policy, nodes, dbConn);
1363 6107 leinfelder
		    }
1364
1365 6494 leinfelder
		    if (replicationPolicy.getPreferredMemberNodeList() != null) {
1366
			    nodes = new ArrayList<String>();
1367
			    policy = "preferred";
1368
			    for (NodeReference node: replicationPolicy.getPreferredMemberNodeList()) {
1369
			    	nodes.add(node.getValue());
1370
			    }
1371 7188 leinfelder
		        this.insertReplicationPolicy(guid, policy, nodes, dbConn);
1372 6107 leinfelder
		    }
1373
        }
1374 6097 leinfelder
1375 6107 leinfelder
        // save replica information
1376 7188 leinfelder
        this.insertReplicationStatus(guid, sm.getReplicaList(), dbConn);
1377 6107 leinfelder
1378 6108 leinfelder
        // save access policy
1379
        AccessPolicy accessPolicy = sm.getAccessPolicy();
1380
        if (accessPolicy != null) {
1381 7188 leinfelder
			this.insertAccessPolicy(guid, accessPolicy);
1382 6108 leinfelder
        }
1383 5887 berkley
    }
1384
1385
    /**
1386 6108 leinfelder
     * Creates Metacat access rules and inserts them
1387
     * @param accessPolicy
1388
     * @throws McdbDocNotFoundException
1389
     * @throws AccessException
1390
     */
1391
    private void insertAccessPolicy(String guid, AccessPolicy accessPolicy) throws McdbDocNotFoundException, AccessException {
1392
1393 6744 leinfelder
    	// check for the existing permOrder so that we remain compatible with it (DataONE does not care)
1394
        XMLAccessAccess accessController  = new XMLAccessAccess();
1395
		String existingPermOrder = AccessControlInterface.ALLOWFIRST;
1396
        Vector<XMLAccessDAO> existingAccess = accessController.getXMLAccessForDoc(guid);
1397
        if (existingAccess != null && existingAccess.size() > 0) {
1398
        	existingPermOrder = existingAccess.get(0).getPermOrder();
1399
        }
1400
1401 6108 leinfelder
    	List<XMLAccessDAO> accessDAOs = new ArrayList<XMLAccessDAO>();
1402
        for (AccessRule accessRule: accessPolicy.getAllowList()) {
1403
        	List<Subject> subjects = accessRule.getSubjectList();
1404
        	List<Permission> permissions = accessRule.getPermissionList();
1405
        	for (Subject subject: subjects) {
1406 6122 leinfelder
    			XMLAccessDAO accessDAO = new XMLAccessDAO();
1407
        		accessDAO.setPrincipalName(subject.getValue());
1408
    			accessDAO.setGuid(guid);
1409
    			accessDAO.setPermType(AccessControlInterface.ALLOW);
1410 6744 leinfelder
				accessDAO.setPermOrder(existingPermOrder);
1411
    			if (permissions != null) {
1412
	    			for (Permission permission: permissions) {
1413
	    				Long metacatPermission = new Long(convertPermission(permission));
1414
	        			accessDAO.addPermission(metacatPermission);
1415
	    			}
1416 6122 leinfelder
    			}
1417
    			accessDAOs.add(accessDAO);
1418 6108 leinfelder
        	}
1419
        }
1420
1421
1422 6744 leinfelder
        // remove all existing allow records
1423
        accessController.deleteXMLAccessForDoc(guid, AccessControlInterface.ALLOW);
1424
        // add the ones we can for this guid
1425
        accessController.insertAccess(guid, accessDAOs);
1426 6108 leinfelder
1427 6744 leinfelder
1428 6108 leinfelder
    }
1429
1430
    /**
1431
     * Lookup access policy from Metacat
1432
     * @param guid
1433
     * @return
1434
     * @throws McdbDocNotFoundException
1435
     * @throws AccessException
1436
     */
1437 6720 leinfelder
    public AccessPolicy getAccessPolicy(String guid) throws McdbDocNotFoundException, AccessException {
1438 6450 leinfelder
        AccessPolicy accessPolicy = new AccessPolicy();
1439
1440 6122 leinfelder
    	// use GUID to look up the access
1441 6744 leinfelder
        XMLAccessAccess accessController  = new XMLAccessAccess();
1442 6720 leinfelder
        List<XMLAccessDAO> accessDAOs = accessController.getXMLAccessForDoc(guid);
1443
1444 6108 leinfelder
        for (XMLAccessDAO accessDAO: accessDAOs) {
1445 6744 leinfelder
        	// only add allow rule
1446
        	if (accessDAO.getPermType().equals(AccessControlInterface.ALLOW)) {
1447
	        	AccessRule accessRule = new AccessRule();
1448
	        	List <Permission> permissions = convertPermission(accessDAO.getPermission().intValue());
1449 7088 leinfelder
	        	// cannot include if we have no permissions
1450
	        	if (permissions == null || permissions.isEmpty()) {
1451
	        		logMetacat.warn("skipping empty access rule permissions for " + guid);
1452
	        		continue;
1453
	        	}
1454 6744 leinfelder
	        	accessRule.setPermissionList(permissions);
1455
	        	Subject subject = new Subject();
1456
	        	subject.setValue(accessDAO.getPrincipalName());
1457
	        	accessRule.addSubject(subject);
1458
	            accessPolicy.addAllow(accessRule);
1459
        	}
1460 6108 leinfelder
        }
1461
        return accessPolicy;
1462
    }
1463
1464
    public int convertPermission(Permission permission) {
1465
    	if (permission.equals(Permission.READ)) {
1466
    		return AccessControlInterface.READ;
1467
    	}
1468
    	if (permission.equals(Permission.WRITE)) {
1469
    		return AccessControlInterface.WRITE;
1470
    	}
1471
    	if (permission.equals(Permission.CHANGE_PERMISSION)) {
1472
    		return AccessControlInterface.CHMOD;
1473
    	}
1474
		return -1;
1475
    }
1476
1477 6722 leinfelder
    public List<Permission> convertPermission(int permission) {
1478 6744 leinfelder
1479 6722 leinfelder
    	List<Permission> permissions = new ArrayList<Permission>();
1480 6744 leinfelder
    	if (permission == AccessControlInterface.ALL) {
1481 6722 leinfelder
    		permissions.add(Permission.READ);
1482
    		permissions.add(Permission.WRITE);
1483 6744 leinfelder
    		permissions.add(Permission.CHANGE_PERMISSION);
1484 6722 leinfelder
    		return permissions;
1485 6108 leinfelder
    	}
1486 6744 leinfelder
1487
    	if ((permission & AccessControlInterface.CHMOD) == AccessControlInterface.CHMOD) {
1488 6722 leinfelder
    		permissions.add(Permission.CHANGE_PERMISSION);
1489 6108 leinfelder
    	}
1490 6744 leinfelder
    	if ((permission & AccessControlInterface.READ) == AccessControlInterface.READ) {
1491 6722 leinfelder
    		permissions.add(Permission.READ);
1492 6744 leinfelder
    	}
1493
    	if ((permission & AccessControlInterface.WRITE) == AccessControlInterface.WRITE) {
1494 6722 leinfelder
    		permissions.add(Permission.WRITE);
1495 6720 leinfelder
    	}
1496 6744 leinfelder
1497
		return permissions;
1498 6108 leinfelder
    }
1499
1500
    /**
1501 6099 leinfelder
     * Lookup a localId given the GUID. If
1502
     * the identifier is not found, throw an exception.
1503
     *
1504
     * @param guid the global identifier to look up
1505
     * @return String containing the corresponding LocalId
1506
     * @throws McdbDocNotFoundException if the identifier is not found
1507 5334 berkley
     */
1508 9024 tao
    public String getLocalId(String guid) throws McdbDocNotFoundException, SQLException {
1509 5334 berkley
1510
      String db_guid = "";
1511
      String docid = "";
1512
      int rev = 0;
1513
1514 6099 leinfelder
      String query = "select guid, docid, rev from " + TYPE_IDENTIFIER + " where guid = ?";
1515 5334 berkley
1516
      DBConnection dbConn = null;
1517 5333 berkley
      int serialNumber = -1;
1518 5334 berkley
      try {
1519
          // Get a database connection from the pool
1520
          dbConn = DBConnectionPool.getDBConnection("Identifier.getLocalId");
1521
          serialNumber = dbConn.getCheckOutSerialNumber();
1522
1523
          // Execute the insert statement
1524
          PreparedStatement stmt = dbConn.prepareStatement(query);
1525
          stmt.setString(1, guid);
1526
          ResultSet rs = stmt.executeQuery();
1527
          if (rs.next()) {
1528
              db_guid = rs.getString(1);
1529
              docid = rs.getString(2);
1530
              rev = rs.getInt(3);
1531
              assert(db_guid.equals(guid));
1532
          } else {
1533
              throw new McdbDocNotFoundException("Document not found:" + guid);
1534
          }
1535
          stmt.close();
1536
      } catch (SQLException e) {
1537
          logMetacat.error("Error while looking up the local identifier: "
1538
                  + e.getMessage());
1539 9024 tao
          throw e;
1540 5334 berkley
      } finally {
1541
          // Return database connection to the pool
1542
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1543
      }
1544
      return docid + "." + rev;
1545
    }
1546
1547 5377 berkley
    /**
1548 5895 berkley
     * query the systemmetadata table based on the given parameters
1549
     * @param startTime
1550
     * @param endTime
1551
     * @param objectFormat
1552
     * @param replicaStatus
1553
     * @param start
1554
     * @param count
1555
     * @return ObjectList
1556 6299 leinfelder
     * @throws SQLException
1557
     * @throws ServiceException
1558
     * @throws PropertyNotFoundException
1559 5895 berkley
     */
1560 6836 cjones
    public ObjectList querySystemMetadata(Date startTime, Date endTime,
1561
        ObjectFormatIdentifier objectFormatId, boolean replicaStatus,
1562 9072 tao
        int start, int count, Identifier identifier, boolean isSID)
1563 6836 cjones
        throws SQLException, PropertyNotFoundException, ServiceException {
1564 5895 berkley
        ObjectList ol = new ObjectList();
1565 5943 berkley
        DBConnection dbConn = null;
1566
        int serialNumber = -1;
1567 6836 cjones
1568 6299 leinfelder
        try {
1569 7452 leinfelder
            String fieldSql = "select guid, date_uploaded, rights_holder, checksum, "
1570 6836 cjones
                    + "checksum_algorithm, origin_member_node, authoritive_member_node, "
1571
                    + "date_modified, submitter, object_format, size from systemmetadata";
1572 7410 leinfelder
1573
            // handle special case quickly
1574
            String countSql = "select count(guid) from systemmetadata";
1575 7452 leinfelder
1576
            // the clause
1577
            String whereClauseSql = "";
1578 6836 cjones
1579 5895 berkley
            boolean f1 = false;
1580
            boolean f2 = false;
1581
            boolean f3 = false;
1582 9072 tao
            boolean f4 = false;
1583 6836 cjones
1584 9072 tao
1585 6299 leinfelder
            if (startTime != null) {
1586 7452 leinfelder
                whereClauseSql += " where systemmetadata.date_modified >= ?";
1587 5895 berkley
                f1 = true;
1588
            }
1589 6836 cjones
1590 6299 leinfelder
            if (endTime != null) {
1591
                if (!f1) {
1592 7452 leinfelder
                    whereClauseSql += " where systemmetadata.date_modified < ?";
1593 6836 cjones
                } else {
1594 7452 leinfelder
                    whereClauseSql += " and systemmetadata.date_modified < ?";
1595 5917 berkley
                }
1596 5895 berkley
                f2 = true;
1597
            }
1598 6836 cjones
1599 6337 leinfelder
            if (objectFormatId != null) {
1600 6299 leinfelder
                if (!f1 && !f2) {
1601 7452 leinfelder
                    whereClauseSql += " where object_format = ?";
1602 6836 cjones
                } else {
1603 7452 leinfelder
                    whereClauseSql += " and object_format = ?";
1604 5917 berkley
                }
1605 5895 berkley
                f3 = true;
1606
            }
1607 9072 tao
1608
            if(identifier != null && identifier.getValue() != null && !identifier.getValue().equals("")) {
1609
                if (!f1 && !f2 && !f3 ) {
1610
                    if(isSID) {
1611
                        whereClauseSql += " where series_id = ?";
1612
                    } else {
1613
                        whereClauseSql += " where guid = ?";
1614
                    }
1615
1616
                } else {
1617
                    if(isSID) {
1618
                        whereClauseSql += " and series_id = ?";
1619
                    } else {
1620
                        whereClauseSql += " and guid = ?";
1621
                    }
1622
                }
1623
                f4 = true;
1624
            }
1625 6836 cjones
1626 7447 cjones
            if (!replicaStatus) {
1627 7030 cjones
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.nodeId");
1628 9072 tao
                if (!f1 && !f2 && !f3 && !f4) {
1629 7462 leinfelder
                    whereClauseSql += " where authoritive_member_node = '" +
1630 6836 cjones
                        currentNodeId.trim() + "'";
1631
                } else {
1632 7462 leinfelder
                    whereClauseSql += " and authoritive_member_node = '" +
1633 6836 cjones
                        currentNodeId.trim() + "'";
1634 5917 berkley
                }
1635 5895 berkley
            }
1636 7310 leinfelder
1637 9072 tao
1638
1639 7452 leinfelder
            // connection
1640 5943 berkley
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.querySystemMetadata");
1641
            serialNumber = dbConn.getCheckOutSerialNumber();
1642 6836 cjones
1643 7452 leinfelder
            // the field query
1644
            String orderBySql = " order by guid ";
1645
            String fieldQuery = fieldSql + whereClauseSql + orderBySql;
1646
            String finalQuery = DatabaseService.getInstance().getDBAdapter().getPagedQuery(fieldQuery, start, count);
1647
            PreparedStatement fieldStmt = dbConn.prepareStatement(finalQuery);
1648
1649
            // construct the count query and statment
1650
            String countQuery = countSql + whereClauseSql;
1651
            PreparedStatement countStmt = dbConn.prepareStatement(countQuery);
1652
1653 9072 tao
            if (f1 && f2 && f3 && f4) {
1654 7452 leinfelder
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1655
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1656
                fieldStmt.setString(3, objectFormatId.getValue());
1657 9072 tao
                fieldStmt.setString(4, identifier.getValue());
1658 7452 leinfelder
                // count
1659
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1660
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1661
                countStmt.setString(3, objectFormatId.getValue());
1662 9072 tao
                countStmt.setString(4, identifier.getValue());
1663
            } if (f1 && f2 && f3 && !f4) {
1664 7452 leinfelder
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1665
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1666 9072 tao
                fieldStmt.setString(3, objectFormatId.getValue());
1667 7452 leinfelder
                // count
1668
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1669
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1670 9072 tao
                countStmt.setString(3, objectFormatId.getValue());
1671
            } else if (f1 && f2 && !f3 && f4) {
1672 7452 leinfelder
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1673 9072 tao
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1674
                fieldStmt.setString(3, identifier.getValue());
1675
                // count
1676
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1677
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1678
                countStmt.setString(3, identifier.getValue());
1679
            } else if (f1 && f2 && !f3 && !f4) {
1680
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1681
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1682
                // count
1683
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1684
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1685
            } else if (f1 && !f2 && f3 && f4) {
1686
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1687 7452 leinfelder
                fieldStmt.setString(2, objectFormatId.getValue());
1688 9072 tao
                fieldStmt.setString(3, identifier.getValue());
1689 7452 leinfelder
                // count
1690
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1691
                countStmt.setString(2, objectFormatId.getValue());
1692 9072 tao
                countStmt.setString(3, identifier.getValue());
1693
            } else if (f1 && !f2 && f3 && !f4) {
1694 7452 leinfelder
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1695 9072 tao
                fieldStmt.setString(2, objectFormatId.getValue());
1696 7452 leinfelder
                // count
1697
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1698 9072 tao
                countStmt.setString(2, objectFormatId.getValue());
1699
            } else if (f1 && !f2 && !f3 && f4) {
1700
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1701
                fieldStmt.setString(2, identifier.getValue());
1702
                // count
1703
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1704
                countStmt.setString(2, identifier.getValue());
1705
            } else if (f1 && !f2 && !f3 && !f4) {
1706
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1707
                // count
1708
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1709
            } else if (!f1 && f2 && f3 && f4) {
1710 7452 leinfelder
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1711
                fieldStmt.setString(2, objectFormatId.getValue());
1712 9072 tao
                fieldStmt.setString(3, identifier.getValue());
1713 7452 leinfelder
                // count
1714
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1715
                countStmt.setString(2, objectFormatId.getValue());
1716 9072 tao
                countStmt.setString(3, identifier.getValue());
1717
            } else if (!f1 && f2 && f3 && !f4) {
1718
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1719
                fieldStmt.setString(2, objectFormatId.getValue());
1720
                // count
1721
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1722
                countStmt.setString(2, objectFormatId.getValue());
1723
            } else if (!f1 && !f2 && f3 && f4) {
1724 7452 leinfelder
                fieldStmt.setString(1, objectFormatId.getValue());
1725 9072 tao
                fieldStmt.setString(2, identifier.getValue());
1726 7452 leinfelder
                // count
1727
                countStmt.setString(1, objectFormatId.getValue());
1728 9072 tao
                countStmt.setString(2, identifier.getValue());
1729
            } else if (!f1 && !f2 && f3 && !f4) {
1730
                fieldStmt.setString(1, objectFormatId.getValue());
1731
                // count
1732
                countStmt.setString(1, objectFormatId.getValue());
1733
            } else if (!f1 && f2 && !f3 && f4) {
1734 7452 leinfelder
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1735 9072 tao
                fieldStmt.setString(2, identifier.getValue());
1736 7452 leinfelder
                // count
1737
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1738 9072 tao
                countStmt.setString(2, identifier.getValue());
1739
            } else if (!f1 && f2 && !f3 && !f4) {
1740
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1741
                // count
1742
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1743
            } else if (!f1 && !f2 && !f3 && f4) {
1744
                fieldStmt.setString(1, identifier.getValue());
1745
                // count
1746
                countStmt.setString(1, identifier.getValue());
1747
            } else if (!f1 && !f2 && !f3 && !f4) {
1748
                //do nothing
1749 5895 berkley
            }
1750 6836 cjones
1751 7461 leinfelder
            logMetacat.debug("list objects fieldStmt: " + fieldStmt.toString());
1752
1753
            logMetacat.debug("list objects countStmt: " + countStmt.toString());
1754
1755 7452 leinfelder
            // get the total object count no matter what
1756
            int total = 0;
1757
            ResultSet totalResult = countStmt.executeQuery();
1758
            if (totalResult.next()) {
1759
            	total = totalResult.getInt(1);
1760 5895 berkley
            }
1761 7438 leinfelder
1762 7461 leinfelder
            logMetacat.debug("list objects total: " + total);
1763
1764 7452 leinfelder
        	// set the totals
1765
        	ol.setStart(start);
1766
            ol.setCount(count);
1767
            ol.setTotal(total);
1768
1769
            // retrieve the actual records if requested
1770
            if (count != 0) {
1771
1772
                ResultSet rs = fieldStmt.executeQuery();
1773 7410 leinfelder
	            while (rs.next()) {
1774 7438 leinfelder
1775 7410 leinfelder
	                String guid = rs.getString(1);
1776 7461 leinfelder
	                logMetacat.debug("query found object with guid " + guid);
1777 7410 leinfelder
	                // Timestamp dateUploaded = rs.getTimestamp(2);
1778
	                // String rightsHolder = rs.getString(3);
1779
	                String checksum = rs.getString(4);
1780
	                String checksumAlgorithm = rs.getString(5);
1781
	                // String originMemberNode = rs.getString(6);
1782
	                // String authoritiveMemberNode = rs.getString(7);
1783
	                Timestamp dateModified = rs.getTimestamp(8);
1784
	                // String submitter = rs.getString(9);
1785
	                String fmtidStr = rs.getString(10);
1786
	                String sz = rs.getString(11);
1787
	                BigInteger size = new BigInteger("0");
1788
1789
	                if (sz != null && !sz.trim().equals("")) {
1790
	                    size = new BigInteger(rs.getString(11));
1791
	                }
1792
1793
	                ObjectInfo oi = new ObjectInfo();
1794
1795
	                Identifier id = new Identifier();
1796
	                id.setValue(guid);
1797
	                oi.setIdentifier(id);
1798
1799
	                if (dateModified != null) {
1800
	                    oi.setDateSysMetadataModified(dateModified);
1801
	                }
1802
1803
	                Checksum cs = new Checksum();
1804
	                cs.setValue(checksum);
1805
	                try {
1806
	                    // cs.setAlgorithm(ChecksumAlgorithm.valueOf(checksumAlgorithm));
1807
	                    cs.setAlgorithm(checksumAlgorithm);
1808
	                } catch (Exception e) {
1809
	                    logMetacat.error("could not parse checksum algorithm", e);
1810
	                    continue;
1811
	                }
1812
	                oi.setChecksum(cs);
1813
1814
	                // set the format type
1815
	                ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
1816
	                fmtid.setValue(fmtidStr);
1817
	                oi.setFormatId(fmtid);
1818
1819
	                oi.setSize(size);
1820
1821 7438 leinfelder
	                ol.addObjectInfo(oi);
1822
1823 7410 leinfelder
	            }
1824 7452 leinfelder
1825 7461 leinfelder
	            logMetacat.debug("list objects count: " + ol.sizeObjectInfoList());
1826
1827 7452 leinfelder
	            // set the actual count retrieved
1828
	            ol.setCount(ol.sizeObjectInfoList());
1829 7410 leinfelder
1830
	        }
1831
1832 5895 berkley
        }
1833 6836 cjones
1834 6299 leinfelder
        finally {
1835 5943 berkley
            // Return database connection to the pool
1836
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1837
        }
1838 6836 cjones
1839 5895 berkley
        return ol;
1840
    }
1841
1842
    /**
1843 6099 leinfelder
     * create a mapping in the identifier table
1844 5377 berkley
     * @param guid
1845
     * @param localId
1846
     */
1847 6099 leinfelder
    public void createMapping(String guid, String localId)
1848 5453 berkley
    {
1849 5334 berkley
1850
        int serialNumber = -1;
1851 5333 berkley
        DBConnection dbConn = null;
1852
        try {
1853
1854
            // Parse the localId into scope and rev parts
1855
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1856
            String docid = acc.getDocid();
1857 5344 berkley
            int rev = 1;
1858 6099 leinfelder
            if (acc.getRev() != null) {
1859 5344 berkley
              rev = (new Integer(acc.getRev()).intValue());
1860
            }
1861 5333 berkley
1862
            // Get a database connection from the pool
1863 6099 leinfelder
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1864 5333 berkley
            serialNumber = dbConn.getCheckOutSerialNumber();
1865
1866
            // Execute the insert statement
1867 6099 leinfelder
            String query = "insert into " + TYPE_IDENTIFIER + " (guid, docid, rev) values (?, ?, ?)";
1868 5333 berkley
            PreparedStatement stmt = dbConn.prepareStatement(query);
1869
            stmt.setString(1, guid);
1870
            stmt.setString(2, docid);
1871
            stmt.setInt(3, rev);
1872 6099 leinfelder
            logMetacat.debug("mapping query: " + stmt.toString());
1873 5333 berkley
            int rows = stmt.executeUpdate();
1874
1875
            stmt.close();
1876
        } catch (SQLException e) {
1877 5344 berkley
            e.printStackTrace();
1878 6099 leinfelder
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: "
1879 5333 berkley
                    + e.getMessage());
1880
        } catch (NumberFormatException e) {
1881 5344 berkley
            e.printStackTrace();
1882 6099 leinfelder
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: "
1883 5333 berkley
                    + e.getMessage());
1884
        } catch (AccessionNumberException e) {
1885 5344 berkley
            e.printStackTrace();
1886 6099 leinfelder
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: "
1887 5333 berkley
                    + e.getMessage());
1888
        } finally {
1889
            // Return database connection to the pool
1890
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1891
        }
1892
    }
1893 6099 leinfelder
1894
    /**
1895 7017 leinfelder
     * remove a mapping in the identifier table
1896
     * @param guid
1897
     * @param localId
1898
     */
1899
    public void removeMapping(String guid, String localId)
1900
    {
1901
1902
        int serialNumber = -1;
1903
        DBConnection dbConn = null;
1904
        try {
1905
1906
            // Parse the localId into scope and rev parts
1907
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1908
            String docid = acc.getDocid();
1909
            int rev = 1;
1910
            if (acc.getRev() != null) {
1911
              rev = (new Integer(acc.getRev()).intValue());
1912
            }
1913
1914
            // Get a database connection from the pool
1915
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.removeMapping");
1916
            serialNumber = dbConn.getCheckOutSerialNumber();
1917
1918
            // Execute the insert statement
1919
            String query = "DELETE FROM " + TYPE_IDENTIFIER + " WHERE guid = ? AND docid = ? AND rev = ?";
1920
            PreparedStatement stmt = dbConn.prepareStatement(query);
1921
            stmt.setString(1, guid);
1922
            stmt.setString(2, docid);
1923
            stmt.setInt(3, rev);
1924
            logMetacat.debug("remove mapping query: " + stmt.toString());
1925
            int rows = stmt.executeUpdate();
1926
1927
            stmt.close();
1928
        } catch (SQLException e) {
1929
            e.printStackTrace();
1930
            logMetacat.error("removeMapping: SQL error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: "
1931
                    + e.getMessage());
1932
        } catch (NumberFormatException e) {
1933
            e.printStackTrace();
1934
            logMetacat.error("removeMapping: NumberFormat error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: "
1935
                    + e.getMessage());
1936
        } catch (AccessionNumberException e) {
1937
            e.printStackTrace();
1938
            logMetacat.error("removeMapping: AccessionNumber error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: "
1939
                    + e.getMessage());
1940
        } finally {
1941
            // Return database connection to the pool
1942
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1943
        }
1944
    }
1945
1946
    /**
1947 6099 leinfelder
     * create the systemmetadata record
1948
     * @param guid
1949 7188 leinfelder
     * @param dbConn
1950
     * @throws SQLException
1951 6099 leinfelder
     */
1952 7188 leinfelder
    private void insertSystemMetadata(String guid, DBConnection dbConn) throws SQLException
1953 6099 leinfelder
    {
1954
1955 7188 leinfelder
        // Execute the insert statement
1956
        String query = "insert into " + TYPE_SYSTEM_METADATA + " (guid) values (?)";
1957
        PreparedStatement stmt = dbConn.prepareStatement(query);
1958
        stmt.setString(1, guid);
1959
        logMetacat.debug("system metadata query: " + stmt.toString());
1960
        int rows = stmt.executeUpdate();
1961 6099 leinfelder
1962 7188 leinfelder
        stmt.close();
1963
1964 6099 leinfelder
    }
1965 6277 leinfelder
1966 8852 tao
    public boolean deleteSystemMetadata(String guid)
1967 6277 leinfelder
    {
1968 8852 tao
        boolean success = false;
1969 6277 leinfelder
        int serialNumber = -1;
1970
        DBConnection dbConn = null;
1971 6648 leinfelder
        String query = null;
1972
        PreparedStatement stmt = null;
1973
        int rows = 0;
1974 6277 leinfelder
        try {
1975
1976 8852 tao
        	 // Get a database connection from the pool
1977 6648 leinfelder
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.deleteSystemMetadata");
1978 6277 leinfelder
            serialNumber = dbConn.getCheckOutSerialNumber();
1979 8852 tao
            dbConn.setAutoCommit(false);
1980
1981 7392 leinfelder
            // remove the smReplicationPolicy
1982
            query = "delete from smReplicationPolicy " +
1983 6648 leinfelder
            "where guid = ?";
1984
            stmt = dbConn.prepareStatement(query);
1985
            stmt.setString(1, guid);
1986 7392 leinfelder
            logMetacat.debug("delete smReplicationPolicy: " + stmt.toString());
1987 6648 leinfelder
            rows = stmt.executeUpdate();
1988
            stmt.close();
1989
1990 7392 leinfelder
            // remove the smReplicationStatus
1991
            query = "delete from smReplicationStatus " +
1992 6648 leinfelder
            "where guid = ?";
1993
            stmt = dbConn.prepareStatement(query);
1994
            stmt.setString(1, guid);
1995 7392 leinfelder
            logMetacat.debug("delete smReplicationStatus: " + stmt.toString());
1996 6648 leinfelder
            rows = stmt.executeUpdate();
1997
            stmt.close();
1998
1999 8852 tao
            // remove main system metadata entry
2000
            query = "delete from " + TYPE_SYSTEM_METADATA + " where guid = ? ";
2001
            stmt = dbConn.prepareStatement(query);
2002
            stmt.setString(1, guid);
2003
            logMetacat.debug("delete system metadata: " + stmt.toString());
2004
            rows = stmt.executeUpdate();
2005
            stmt.close();
2006
2007
            dbConn.commit();
2008
            dbConn.setAutoCommit(true);
2009
            success = true;
2010 6744 leinfelder
            // TODO: remove the access?
2011 6648 leinfelder
            // Metacat keeps "deleted" documents so we should not remove access rules.
2012
2013 6277 leinfelder
        } catch (Exception e) {
2014
            e.printStackTrace();
2015
            logMetacat.error("Error while deleting " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
2016 6648 leinfelder
            try {
2017
				dbConn.rollback();
2018
			} catch (SQLException sqle) {
2019
	            logMetacat.error("Error while rolling back delete for record: " + guid, sqle );
2020
			}
2021 6277 leinfelder
        } finally {
2022
            // Return database connection to the pool
2023
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2024
        }
2025 8852 tao
        return success;
2026 6277 leinfelder
    }
2027 6862 leinfelder
2028
    public void updateAuthoritativeMemberNodeId(String existingMemberNodeId, String newMemberNodeId)
2029
    {
2030
        DBConnection dbConn = null;
2031
        int serialNumber = -1;
2032
2033
        try {
2034
            // Get a database connection from the pool
2035
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.updateAuthoritativeMemberNodeId");
2036
            serialNumber = dbConn.getCheckOutSerialNumber();
2037
2038
            // Execute the insert statement
2039
            String query = "update " + TYPE_SYSTEM_METADATA +
2040
                " set authoritive_member_node = ? " +
2041
                " where authoritive_member_node = ?";
2042
            PreparedStatement stmt = dbConn.prepareStatement(query);
2043
2044
            //data values
2045
            stmt.setString(1, newMemberNodeId);
2046
            stmt.setString(2, existingMemberNodeId);
2047
2048
            logMetacat.debug("stmt: " + stmt.toString());
2049
            //execute
2050
            int rows = stmt.executeUpdate();
2051
2052
            stmt.close();
2053
        } catch (SQLException e) {
2054
            e.printStackTrace();
2055
            logMetacat.error("updateSystemMetadataFields: SQL error while updating system metadata: "
2056
                    + e.getMessage());
2057
        } catch (NumberFormatException e) {
2058
            e.printStackTrace();
2059
            logMetacat.error("updateSystemMetadataFields: NumberFormat error while updating system metadata: "
2060
                    + e.getMessage());
2061
        } finally {
2062
            // Return database connection to the pool
2063
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2064
        }
2065
    }
2066 5282 jones
}