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