Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2010 Regents of the University of California and the
4
 *              National Center for Ecological Analysis and Synthesis
5
 *  Purpose: To test the Access Controls in metacat by JUnit
6
 *
7
 *   '$Author: leinfelder $'
8
 *     '$Date: 2014-08-07 14:28:35 -0700 (Thu, 07 Aug 2014) $'
9
 * '$Revision: 8834 $'
10
 *
11
 * This program is free software; you can redistribute it and/or modify
12
 * it under the terms of the GNU General Public License as published by
13
 * the Free Software Foundation; either version 2 of the License, or
14
 * (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 * along with this program; if not, write to the Free Software
23
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24
 */
25

    
26
package edu.ucsb.nceas.metacat.dataone;
27

    
28
import java.io.InputStream;
29
import java.io.InputStreamReader;
30
import java.io.Reader;
31
import java.math.BigInteger;
32
import java.util.Collections;
33
import java.util.Date;
34
import java.util.Vector;
35

    
36
import junit.framework.Test;
37
import junit.framework.TestSuite;
38

    
39
import org.apache.wicket.protocol.http.mock.MockHttpServletRequest;
40
import org.dataone.client.D1Node;
41
import org.dataone.client.NodeLocator;
42
import org.dataone.client.exception.ClientSideException;
43
import org.dataone.client.v2.CNode;
44
import org.dataone.client.v2.itk.D1Client;
45
import org.dataone.client.v2.formats.ObjectFormatCache;
46
import org.dataone.service.types.v1.AccessPolicy;
47
import org.dataone.service.types.v1.AccessRule;
48
import org.dataone.service.types.v1.Checksum;
49
import org.dataone.service.types.v1.Identifier;
50
import org.dataone.service.types.v2.Node;
51
import org.dataone.service.types.v2.ObjectFormatList;
52
import org.dataone.service.types.v1.NodeReference;
53
import org.dataone.service.types.v1.NodeType;
54
import org.dataone.service.types.v1.Permission;
55
import org.dataone.service.types.v1.Session;
56
import org.dataone.service.types.v1.Subject;
57
import org.dataone.service.types.v2.SystemMetadata;
58
import org.dataone.service.types.v1.comparators.SystemMetadataDateUploadedComparator;
59
import org.dataone.service.types.v1.util.ChecksumUtil;
60
import org.dataone.service.types.v2.util.ObjectFormatServiceImpl;
61
import org.dataone.service.util.Constants;
62
import org.dataone.service.util.TypeMarshaller;
63

    
64

    
65
import edu.ucsb.nceas.MCTestCase;
66
import edu.ucsb.nceas.metacat.client.Metacat;
67
import edu.ucsb.nceas.metacat.client.MetacatFactory;
68

    
69
/**
70
 * A class for testing the scenarios of getting the the head version of an SID chain
71
 */
72
public class SIDTest extends MCTestCase {   
73
    
74
    private static final String OBSOLETES = "obsoletes";
75
    private static final String OBSOLETEDBY = "obsoletedBy";
76
   
77
	/**
78
    * constructor for the test
79
    */
80
    public SIDTest(String name) {
81
        super(name);
82
    }
83
  
84
    /**
85
	 * Establish a testing framework by initializing appropriate objects
86
	 */
87
    public void setUp() throws Exception {
88
    	
89
    }
90

    
91
	/**
92
	 * Release any objects after tests are complete
93
	 */
94
	public void tearDown() {
95
		
96
	}
97
	
98
	/**
99
     * Create a suite of tests to be run together
100
     */
101
    public static Test suite() 
102
    {
103
        TestSuite suite = new TestSuite();
104
        suite.addTest(new SIDTest("initialize"));
105
        suite.addTest(new SIDTest("testCases"));
106
        return suite;
107
    }
108
	
109
	
110
	
111
	/**
112
	 * Run an initial test that always passes to check that the test harness is
113
	 * working.
114
	 */
115
	public void initialize() 
116
	{
117
		assertTrue(1 == 1);
118
	}
119
	
120
	public void testCases() throws Exception {
121
	    testCase1();
122
	    testCase2();
123
	    testCase3();
124
	    testCase4();
125
	    testCase5();
126
	    testCase6();
127
	    testCase7();
128
	    testCase8();
129
	    testCase9();
130
	    testCase10();
131
	    testCase11();
132
	    testCase12();
133
	    testCase13();
134
	    testCase14();
135
	    testCase15();
136
	    testCase16();
137
        testCase17();
138
        testCase18();
139
	}
140
	
141
	/**
142
	 * case 1. P1(S1) <-> P2(S1),  S1 = P2 (Rule 1)
143
	 */
144
	private void testCase1() throws Exception {
145
	    Identifier s1 = new Identifier();
146
        s1.setValue("S1");
147
        Identifier s2 = new Identifier();
148
        s2.setValue("S2");
149
        Identifier p1 = new Identifier();
150
        p1.setValue("P1");
151
        Identifier p2 = new Identifier();
152
        p2.setValue("P2");
153
       
154
        SystemMetadata p1Sys = new SystemMetadata();
155
        p1Sys.setIdentifier(p1);
156
        p1Sys.setSeriesId(s1);
157
        p1Sys.setObsoletedBy(p2);
158
        p1Sys.setDateUploaded(new Date(100));
159
        
160
        SystemMetadata p2Sys = new SystemMetadata();
161
        p2Sys.setIdentifier(p2);
162
        p2Sys.setSeriesId(s1);
163
        p2Sys.setObsoletes(p1);
164
        p2Sys.setDateUploaded(new Date(200));
165
        
166
        Vector<SystemMetadata> chain = new Vector<SystemMetadata>();
167
        chain.add(p1Sys);
168
        chain.add(p2Sys);
169
      
170
        System.out.println("Case 1:");
171
        Identifier head = getHeadVersion(s1, chain);
172
        //System.out.println("The head is "+head.getValue());
173
        assertTrue(head.equals(p2));
174
	}
175
	
176
	
177
	/**
178
     * Case 2. P1(S1) ? P2(S1), S1 = P2, Error condition, P2 not allowed (should not exist) (Rule 2)
179
     */
180
    private void testCase2() throws Exception {
181
        Identifier s1 = new Identifier();
182
        s1.setValue("S1");
183
        Identifier s2 = new Identifier();
184
        s2.setValue("S2");
185
        Identifier p1 = new Identifier();
186
        p1.setValue("P1");
187
        Identifier p2 = new Identifier();
188
        p2.setValue("P2");
189
       
190
        
191
        SystemMetadata p1Sys = new SystemMetadata();
192
        p1Sys.setIdentifier(p1);
193
        p1Sys.setSeriesId(s1);
194
        p1Sys.setDateUploaded(new Date(100));
195
        
196
        SystemMetadata p2Sys = new SystemMetadata();
197
        p2Sys.setIdentifier(p2);
198
        p2Sys.setSeriesId(s1);
199
        p2Sys.setDateUploaded(new Date(200));
200
        
201
        Vector<SystemMetadata> chain = new Vector<SystemMetadata>();
202
        chain.add(p1Sys);
203
        chain.add(p2Sys);
204
      
205
        System.out.println("Case 2:");
206
        Identifier head = getHeadVersion(s1, chain);
207
        //System.out.println("The head is "+head.getValue());
208
        assertTrue(head.equals(p2));
209
    }
210
    
211
    /**
212
     * case 3. P1(S1) <- P2(S1), S1 = P2, Discouraged, but not error condition, S1 = P2 (Rule 2, missingFields)
213
     */
214
    private void testCase3() throws Exception {
215
        Identifier s1 = new Identifier();
216
        s1.setValue("S1");
217
        Identifier s2 = new Identifier();
218
        s2.setValue("S2");
219
        Identifier p1 = new Identifier();
220
        p1.setValue("P1");
221
        Identifier p2 = new Identifier();
222
        p2.setValue("P2");
223
       
224
        
225
        SystemMetadata p1Sys = new SystemMetadata();
226
        p1Sys.setIdentifier(p1);
227
        p1Sys.setSeriesId(s1);
228
        p1Sys.setDateUploaded(new Date(100));
229
        
230
        SystemMetadata p2Sys = new SystemMetadata();
231
        p2Sys.setIdentifier(p2);
232
        p2Sys.setSeriesId(s1);
233
        p2Sys.setObsoletes(p1);
234
        p2Sys.setDateUploaded(new Date(200));
235
        
236
        Vector<SystemMetadata> chain = new Vector<SystemMetadata>();
237
        chain.add(p1Sys);
238
        chain.add(p2Sys);
239
      
240
        System.out.println("Case 3:");
241
        Identifier head = getHeadVersion(s1, chain);
242
        //System.out.println("The head is "+head.getValue());
243
        assertTrue(head.equals(p2));
244
    }
245
    
246
    /**
247
     * case 4. P1(S1) <-> P2(S1) <-> P3(S2), S1 = P2(use Rule 3), S2 = P3 (use Rule 1)
248
     */
249
    private void testCase4() throws Exception {
250
        Identifier s1 = new Identifier();
251
        s1.setValue("S1");
252
        Identifier s2 = new Identifier();
253
        s2.setValue("S2");
254
        Identifier p1 = new Identifier();
255
        p1.setValue("P1");
256
        Identifier p2 = new Identifier();
257
        p2.setValue("P2");
258
        Identifier p3 = new Identifier();
259
        p3.setValue("P3");
260
       
261
        
262
        SystemMetadata p1Sys = new SystemMetadata();
263
        p1Sys.setIdentifier(p1);
264
        p1Sys.setSeriesId(s1);
265
        p1Sys.setObsoletedBy(p2);
266
        p1Sys.setDateUploaded(new Date(100));
267
        
268
        SystemMetadata p2Sys = new SystemMetadata();
269
        p2Sys.setIdentifier(p2);
270
        p2Sys.setSeriesId(s1);
271
        p2Sys.setObsoletes(p1);
272
        p2Sys.setObsoletedBy(p3);
273
        p2Sys.setDateUploaded(new Date(200));
274
        
275
        SystemMetadata p3Sys = new SystemMetadata();
276
        p3Sys.setIdentifier(p3);
277
        p3Sys.setSeriesId(s2);
278
        p3Sys.setObsoletes(p2);
279
        p3Sys.setDateUploaded(new Date(300));
280

    
281
        Vector<SystemMetadata> chain = new Vector<SystemMetadata>();
282
        chain.add(p1Sys);
283
        chain.add(p2Sys);
284
        chain.add(p3Sys);
285
      
286
        System.out.println("Case 4:");
287
        Identifier head = getHeadVersion(s1, chain);
288
        //System.out.println("The head is "+head.getValue());
289
        assertTrue(head.equals(p2));
290
        Identifier head2 = getHeadVersion(s2, chain);
291
        //System.out.println("The head is "+head.getValue());
292
        assertTrue(head2.equals(p3));
293
    }
294
    
295
    /**
296
     * case 5. P1(S1) <- P2(S1) <- P3(S2), S1 = P2 (use Rule 2 or have missing field), S2 = P3  (use Rule 1)
297
     */
298
    private void testCase5() throws Exception {
299
        Identifier s1 = new Identifier();
300
        s1.setValue("S1");
301
        Identifier s2 = new Identifier();
302
        s2.setValue("S2");
303
        Identifier p1 = new Identifier();
304
        p1.setValue("P1");
305
        Identifier p2 = new Identifier();
306
        p2.setValue("P2");
307
        Identifier p3 = new Identifier();
308
        p3.setValue("P3");
309
       
310
        
311
        SystemMetadata p1Sys = new SystemMetadata();
312
        p1Sys.setIdentifier(p1);
313
        p1Sys.setSeriesId(s1);
314
        p1Sys.setDateUploaded(new Date(100));
315
        
316
        SystemMetadata p2Sys = new SystemMetadata();
317
        p2Sys.setIdentifier(p2);
318
        p2Sys.setSeriesId(s1);
319
        p2Sys.setObsoletes(p1);
320
        p2Sys.setDateUploaded(new Date(200));
321
        
322
        SystemMetadata p3Sys = new SystemMetadata();
323
        p3Sys.setIdentifier(p3);
324
        p3Sys.setSeriesId(s2);
325
        p3Sys.setObsoletes(p2);
326
        p3Sys.setDateUploaded(new Date(300));
327

    
328
        Vector<SystemMetadata> chain = new Vector<SystemMetadata>();
329
        chain.add(p1Sys);
330
        chain.add(p2Sys);
331
        chain.add(p3Sys);
332
      
333
        System.out.println("Case 5:");
334
        Identifier head = getHeadVersion(s1, chain);
335
        //System.out.println("The head is "+head.getValue());
336
        assertTrue(head.equals(p2));
337
        Identifier head2 = getHeadVersion(s2, chain);
338
        //System.out.println("The head is "+head.getValue());
339
        assertTrue(head2.equals(p3));
340
    }
341
    
342
    /**
343
     * case 6. P1(S1) <-> P2(S1) <-> P3(), S1 = P2 (use Rule 3)
344
     */
345
    private void testCase6() throws Exception {
346
        Identifier s1 = new Identifier();
347
        s1.setValue("S1");
348
        Identifier s2 = new Identifier();
349
        s2.setValue("S2");
350
        Identifier p1 = new Identifier();
351
        p1.setValue("P1");
352
        Identifier p2 = new Identifier();
353
        p2.setValue("P2");
354
        Identifier p3 = new Identifier();
355
        p3.setValue("P3");
356
       
357
        
358
        SystemMetadata p1Sys = new SystemMetadata();
359
        p1Sys.setIdentifier(p1);
360
        p1Sys.setSeriesId(s1);
361
        p1Sys.setObsoletedBy(p2);
362
        p1Sys.setDateUploaded(new Date(100));
363
        
364
        SystemMetadata p2Sys = new SystemMetadata();
365
        p2Sys.setIdentifier(p2);
366
        p2Sys.setSeriesId(s1);
367
        p2Sys.setObsoletes(p1);
368
        p2Sys.setObsoletedBy(p3);
369
        p2Sys.setDateUploaded(new Date(200));
370
        
371
        SystemMetadata p3Sys = new SystemMetadata();
372
        p3Sys.setIdentifier(p3);
373
        //p3Sys.setSeriesId(s2);
374
        p3Sys.setObsoletes(p2);
375
        p3Sys.setDateUploaded(new Date(300));
376

    
377
        Vector<SystemMetadata> chain = new Vector<SystemMetadata>();
378
        chain.add(p1Sys);
379
        chain.add(p2Sys);
380
        chain.add(p3Sys);
381
      
382
        System.out.println("Case 6:");
383
        Identifier head = getHeadVersion(s1, chain);
384
        //System.out.println("The head is "+head.getValue());
385
        assertTrue(head.equals(p2));
386
    }
387
    
388
    /**
389
     * case 7. P1(S1) <-> P2(S1) <-> P3() <-> P4(S2), S1 = P2 (Rule 3), S2 = P4 (Rule 1)
390
     */
391
    private void testCase7() throws Exception {
392
        Identifier s1 = new Identifier();
393
        s1.setValue("S1");
394
        Identifier s2 = new Identifier();
395
        s2.setValue("S2");
396
        Identifier p1 = new Identifier();
397
        p1.setValue("P1");
398
        Identifier p2 = new Identifier();
399
        p2.setValue("P2");
400
        Identifier p3 = new Identifier();
401
        p3.setValue("P3");
402
        Identifier p4 = new Identifier();
403
        p4.setValue("P4");
404
       
405
        
406
        SystemMetadata p1Sys = new SystemMetadata();
407
        p1Sys.setIdentifier(p1);
408
        p1Sys.setSeriesId(s1);
409
        p1Sys.setObsoletedBy(p2);
410
        p1Sys.setDateUploaded(new Date(100));
411
        
412
        SystemMetadata p2Sys = new SystemMetadata();
413
        p2Sys.setIdentifier(p2);
414
        p2Sys.setSeriesId(s1);
415
        p2Sys.setObsoletes(p1);
416
        p2Sys.setObsoletedBy(p3);
417
        p2Sys.setDateUploaded(new Date(200));
418
        
419
        SystemMetadata p3Sys = new SystemMetadata();
420
        p3Sys.setIdentifier(p3);
421
        //p3Sys.setSeriesId(s2);
422
        p3Sys.setObsoletes(p2);
423
        p3Sys.setObsoletedBy(p4);
424
        p3Sys.setDateUploaded(new Date(300));
425
        
426
        SystemMetadata p4Sys = new SystemMetadata();
427
        p4Sys.setIdentifier(p4);
428
        p4Sys.setSeriesId(s2);
429
        p4Sys.setObsoletes(p3);
430
        p4Sys.setDateUploaded(new Date(400));
431

    
432
        Vector<SystemMetadata> chain = new Vector<SystemMetadata>();
433
        chain.add(p1Sys);
434
        chain.add(p2Sys);
435
        chain.add(p3Sys);
436
        chain.add(p4Sys);
437
      
438
        System.out.println("Case 7:");
439
        Identifier head = getHeadVersion(s1, chain);
440
        //System.out.println("The head is "+head.getValue());
441
        assertTrue(head.equals(p2));
442
        Identifier head2 = getHeadVersion(s2, chain);
443
        //System.out.println("The head is "+head.getValue());
444
        assertTrue(head2.equals(p4));
445
    }
446
    
447
    /**
448
     * case 8. P1(S1) <-> P2(S1) ->  ??  <- P4(S1), S1 = P4, (Rule 1) (Error, but will happen)
449
     */
450
    private void testCase8() throws Exception {
451
        Identifier s1 = new Identifier();
452
        s1.setValue("S1");
453
        Identifier s2 = new Identifier();
454
        s2.setValue("S2");
455
        Identifier p1 = new Identifier();
456
        p1.setValue("P1");
457
        Identifier p2 = new Identifier();
458
        p2.setValue("P2");
459
        Identifier p3 = new Identifier();
460
        p3.setValue("P3");
461
        Identifier p4 = new Identifier();
462
        p4.setValue("P4");
463
       
464
        
465
        SystemMetadata p1Sys = new SystemMetadata();
466
        p1Sys.setIdentifier(p1);
467
        p1Sys.setSeriesId(s1);
468
        p1Sys.setObsoletedBy(p2);
469
        p1Sys.setDateUploaded(new Date(100));
470
        
471
        SystemMetadata p2Sys = new SystemMetadata();
472
        p2Sys.setIdentifier(p2);
473
        p2Sys.setSeriesId(s1);
474
        p2Sys.setObsoletes(p1);
475
        p2Sys.setObsoletedBy(p3);
476
        p2Sys.setDateUploaded(new Date(200));
477
        
478
        
479
        SystemMetadata p4Sys = new SystemMetadata();
480
        p4Sys.setIdentifier(p4);
481
        p4Sys.setSeriesId(s1);
482
        p4Sys.setObsoletes(p3);
483
        p4Sys.setDateUploaded(new Date(400));
484

    
485
        Vector<SystemMetadata> chain = new Vector<SystemMetadata>();
486
        chain.add(p1Sys);
487
        chain.add(p2Sys);
488
        chain.add(p4Sys);
489
      
490
        System.out.println("Case 8:");
491
        Identifier head = getHeadVersion(s1, chain);
492
        //System.out.println("The head is "+head.getValue());
493
        assertTrue(head.equals(p4));
494
    }
495
    
496
    /**
497
     * case 9. P1(S1) <-> P2(S1)  ??  <- P4(S1), S1 = P4 (Rule 2) (??: object was not synchronized)
498
     */
499
    private void testCase9() throws Exception {
500
        Identifier s1 = new Identifier();
501
        s1.setValue("S1");
502
        Identifier s2 = new Identifier();
503
        s2.setValue("S2");
504
        Identifier p1 = new Identifier();
505
        p1.setValue("P1");
506
        Identifier p2 = new Identifier();
507
        p2.setValue("P2");
508
        Identifier p3 = new Identifier();
509
        p3.setValue("P3");
510
        Identifier p4 = new Identifier();
511
        p4.setValue("P4");
512
       
513
        
514
        SystemMetadata p1Sys = new SystemMetadata();
515
        p1Sys.setIdentifier(p1);
516
        p1Sys.setSeriesId(s1);
517
        p1Sys.setObsoletedBy(p2);
518
        p1Sys.setDateUploaded(new Date(100));
519
        
520
        SystemMetadata p2Sys = new SystemMetadata();
521
        p2Sys.setIdentifier(p2);
522
        p2Sys.setSeriesId(s1);
523
        p2Sys.setObsoletes(p1);
524
        p2Sys.setDateUploaded(new Date(200));
525
        
526
        
527
        SystemMetadata p4Sys = new SystemMetadata();
528
        p4Sys.setIdentifier(p4);
529
        p4Sys.setSeriesId(s1);
530
        p4Sys.setObsoletes(p3);
531
        p4Sys.setDateUploaded(new Date(400));
532

    
533
        Vector<SystemMetadata> chain = new Vector<SystemMetadata>();
534
        chain.add(p1Sys);
535
        chain.add(p2Sys);
536
        chain.add(p4Sys);
537
      
538
        System.out.println("Case 9:");
539
        Identifier head = getHeadVersion(s1, chain);
540
        //System.out.println("The head is "+head.getValue());
541
        assertTrue(head.equals(p4));
542
    }
543
    
544
    /**
545
     * case 10: P1(S1) <-> P2(S1) ->  XX  <- P4(S1), S1 = P4, (Rule 1) (XX: object P3 was deleted)
546
     */
547
    private void testCase10() throws Exception {
548
        Identifier s1 = new Identifier();
549
        s1.setValue("S1");
550
        Identifier s2 = new Identifier();
551
        s2.setValue("S2");
552
        Identifier p1 = new Identifier();
553
        p1.setValue("P1");
554
        Identifier p2 = new Identifier();
555
        p2.setValue("P2");
556
        Identifier p3 = new Identifier();
557
        p3.setValue("P3");
558
        Identifier p4 = new Identifier();
559
        p4.setValue("P4");
560
       
561
        
562
        SystemMetadata p1Sys = new SystemMetadata();
563
        p1Sys.setIdentifier(p1);
564
        p1Sys.setSeriesId(s1);
565
        p1Sys.setObsoletedBy(p2);
566
        p1Sys.setDateUploaded(new Date(100));
567
        
568
        SystemMetadata p2Sys = new SystemMetadata();
569
        p2Sys.setIdentifier(p2);
570
        p2Sys.setSeriesId(s1);
571
        p2Sys.setObsoletes(p1);
572
        p2Sys.setObsoletedBy(p3);
573
        p2Sys.setDateUploaded(new Date(200));
574
        
575
        
576
        SystemMetadata p4Sys = new SystemMetadata();
577
        p4Sys.setIdentifier(p4);
578
        p4Sys.setSeriesId(s1);
579
        p4Sys.setObsoletes(p3);
580
        p4Sys.setDateUploaded(new Date(400));
581

    
582
        Vector<SystemMetadata> chain = new Vector<SystemMetadata>();
583
        chain.add(p1Sys);
584
        chain.add(p2Sys);
585
        chain.add(p4Sys);
586
      
587
        System.out.println("Case 10:");
588
        Identifier head = getHeadVersion(s1, chain);
589
        //System.out.println("The head is "+head.getValue());
590
        assertTrue(head.equals(p4));
591
    }
592
    
593
    /**
594
     * case 11: P1(S1) <-> P2(S1) <-> [archived:P3(S1)], S1 = P3, (Rule 1) 
595
     */
596
    private void testCase11() throws Exception {
597
        Identifier s1 = new Identifier();
598
        s1.setValue("S1");
599
        Identifier s2 = new Identifier();
600
        s2.setValue("S2");
601
        Identifier p1 = new Identifier();
602
        p1.setValue("P1");
603
        Identifier p2 = new Identifier();
604
        p2.setValue("P2");
605
        Identifier p3 = new Identifier();
606
        p3.setValue("P3");
607
        Identifier p4 = new Identifier();
608
        p4.setValue("P4");
609
       
610
        
611
        SystemMetadata p1Sys = new SystemMetadata();
612
        p1Sys.setIdentifier(p1);
613
        p1Sys.setSeriesId(s1);
614
        p1Sys.setObsoletedBy(p2);
615
        p1Sys.setDateUploaded(new Date(100));
616
        
617
        SystemMetadata p2Sys = new SystemMetadata();
618
        p2Sys.setIdentifier(p2);
619
        p2Sys.setSeriesId(s1);
620
        p2Sys.setObsoletes(p1);
621
        p2Sys.setObsoletedBy(p3);
622
        p2Sys.setDateUploaded(new Date(200));
623
        
624
        
625
        SystemMetadata p3Sys = new SystemMetadata();
626
        p3Sys.setIdentifier(p3);
627
        p3Sys.setSeriesId(s1);
628
        p3Sys.setObsoletes(p2);
629
        p3Sys.setArchived(true);
630
        p3Sys.setDateUploaded(new Date(300));
631
        
632

    
633
        Vector<SystemMetadata> chain = new Vector<SystemMetadata>();
634
        chain.add(p1Sys);
635
        chain.add(p2Sys);
636
        chain.add(p3Sys);
637
      
638
        System.out.println("Case 11:");
639
        Identifier head = getHeadVersion(s1, chain);
640
        //System.out.println("The head is "+head.getValue());
641
        assertTrue(head.equals(p3));
642
    }
643
    
644
    /**
645
     * case 12. P1(S1) <-> P2(S1) -> ??, S1 = P2, (Rule 4) (Error, but will happen)
646
     * @throws Exception
647
     */
648
    private void testCase12() throws Exception {
649
        Identifier s1 = new Identifier();
650
        s1.setValue("S1");
651
        Identifier s2 = new Identifier();
652
        s2.setValue("S2");
653
        Identifier p1 = new Identifier();
654
        p1.setValue("P1");
655
        Identifier p2 = new Identifier();
656
        p2.setValue("P2");
657
        Identifier p3 = new Identifier();
658
        p3.setValue("P3");
659
        
660
        SystemMetadata p1Sys = new SystemMetadata();
661
        p1Sys.setIdentifier(p1);
662
        p1Sys.setSeriesId(s1);
663
        p1Sys.setObsoletedBy(p2);
664
        p1Sys.setDateUploaded(new Date(100));
665
        
666
        SystemMetadata p2Sys = new SystemMetadata();
667
        p2Sys.setIdentifier(p2);
668
        p2Sys.setSeriesId(s1);
669
        p2Sys.setObsoletes(p1);
670
        p2Sys.setObsoletedBy(p3);
671
        p2Sys.setDateUploaded(new Date(200));
672
        
673

    
674
        Vector<SystemMetadata> chain = new Vector<SystemMetadata>();
675
        chain.add(p1Sys);
676
        chain.add(p2Sys);
677

    
678
        System.out.println("Case 12:");
679
        Identifier head = getHeadVersion(s1, chain);
680
        //System.out.println("The head is "+head.getValue());
681
        assertTrue(head.equals(p2));
682
    }
683
    
684
    /**
685
     * case 13. P1(S1) <- P2(S1) -> ??, S1 = P2
686
     * @throws Exception
687
     */
688
    private void testCase13() throws Exception {
689
        Identifier s1 = new Identifier();
690
        s1.setValue("S1");
691
        Identifier s2 = new Identifier();
692
        s2.setValue("S2");
693
        Identifier p1 = new Identifier();
694
        p1.setValue("P1");
695
        Identifier p2 = new Identifier();
696
        p2.setValue("P2");
697
        Identifier p3 = new Identifier();
698
        p3.setValue("P3");
699
        
700
        SystemMetadata p1Sys = new SystemMetadata();
701
        p1Sys.setIdentifier(p1);
702
        p1Sys.setSeriesId(s1);
703
        p1Sys.setDateUploaded(new Date(100));
704
        
705
        SystemMetadata p2Sys = new SystemMetadata();
706
        p2Sys.setIdentifier(p2);
707
        p2Sys.setSeriesId(s1);
708
        p2Sys.setObsoletes(p1);
709
        p2Sys.setObsoletedBy(p3);
710
        p2Sys.setDateUploaded(new Date(200));
711
        
712

    
713
        Vector<SystemMetadata> chain = new Vector<SystemMetadata>();
714
        chain.add(p1Sys);
715
        chain.add(p2Sys);
716
      
717
        
718
        System.out.println("Case 13:");
719
        Identifier head = getHeadVersion(s1, chain);
720
        //System.out.println("The head is "+head.getValue());
721
        assertTrue(head.equals(p2));
722
    }
723
	
724
	/**
725
	 * Case 14: P1(S1) <- P2(S1) -> P3(S2).
726
	 * It has a missing obsoletedBy fields, we use the uploadedDate field.S1 = P2
727
	 * @throws Exception
728
	 */
729
	private void testCase14() throws Exception {
730
	    Identifier s1 = new Identifier();
731
	    s1.setValue("S1");
732
	    Identifier s2 = new Identifier();
733
        s2.setValue("S2");
734
	    Identifier p1 = new Identifier();
735
	    p1.setValue("P1");
736
	    Identifier p2 = new Identifier();
737
        p2.setValue("P2");
738
        Identifier p3 = new Identifier();
739
        p3.setValue("P3");
740
	    
741
        SystemMetadata p1Sys = new SystemMetadata();
742
	    p1Sys.setIdentifier(p1);
743
	    p1Sys.setSeriesId(s1);
744
	    p1Sys.setDateUploaded(new Date(100));
745
	    
746
	    SystemMetadata p2Sys = new SystemMetadata();
747
        p2Sys.setIdentifier(p2);
748
        p2Sys.setSeriesId(s1);
749
        p2Sys.setObsoletes(p1);
750
        p2Sys.setObsoletedBy(p3);
751
        p2Sys.setDateUploaded(new Date(200));
752
        
753
        SystemMetadata p3Sys = new SystemMetadata();
754
        p3Sys.setIdentifier(p3);
755
        p3Sys.setSeriesId(s2);
756
        p3Sys.setDateUploaded(new Date(300));
757
        
758
        Vector<SystemMetadata> chain = new Vector<SystemMetadata>();
759
        chain.add(p1Sys);
760
        chain.add(p2Sys);
761
        chain.add(p3Sys);
762
        
763
        System.out.println("Case 14:");
764
        Identifier head = getHeadVersion(s1, chain);
765
        //System.out.println("The head is "+head.getValue());
766
        assertTrue(head.equals(p2));
767
	}
768
	
769
	/**
770
     * case 15. P1(S1) <-> P2(S1)  ?? <- P4(S1) <-> P5(S2), S1 = P4 (Rule 1) 
771
     * @throws Exception
772
     */
773
    private void testCase15() throws Exception {
774
        Identifier s1 = new Identifier();
775
        s1.setValue("S1");
776
        Identifier s2 = new Identifier();
777
        s2.setValue("S2");
778
        Identifier p1 = new Identifier();
779
        p1.setValue("P1");
780
        Identifier p2 = new Identifier();
781
        p2.setValue("P2");
782
        Identifier p3 = new Identifier();
783
        p3.setValue("P3");
784
        Identifier p4 = new Identifier();
785
        p4.setValue("P4");
786
        Identifier p5 = new Identifier();
787
        p5.setValue("P5");
788
        
789
        SystemMetadata p1Sys = new SystemMetadata();
790
        p1Sys.setIdentifier(p1);
791
        p1Sys.setSeriesId(s1);
792
        p1Sys.setObsoletedBy(p2);
793
        p1Sys.setDateUploaded(new Date(100));
794
        
795
        SystemMetadata p2Sys = new SystemMetadata();
796
        p2Sys.setIdentifier(p2);
797
        p2Sys.setSeriesId(s1);
798
        p2Sys.setObsoletes(p1);
799
        p2Sys.setDateUploaded(new Date(200));
800
        
801
        SystemMetadata p4Sys = new SystemMetadata();
802
        p4Sys.setIdentifier(p4);
803
        p4Sys.setSeriesId(s1);
804
        p4Sys.setObsoletes(p3);
805
        p4Sys.setObsoletedBy(p5);
806
        p4Sys.setDateUploaded(new Date(400));
807
        
808
        SystemMetadata p5Sys = new SystemMetadata();
809
        p5Sys.setIdentifier(p5);
810
        p5Sys.setSeriesId(s2);
811
        p5Sys.setObsoletes(p4);
812
        p5Sys.setDateUploaded(new Date(500));
813
        
814
        
815
        Vector<SystemMetadata> chain = new Vector<SystemMetadata>();
816
        chain.add(p1Sys);
817
        chain.add(p2Sys);
818
        chain.add(p4Sys);
819
        chain.add(p5Sys);
820
        
821
        System.out.println("Case 15:");
822
        Identifier head = getHeadVersion(s1, chain);
823
        //System.out.println("The head is "+head.getValue());
824
        assertTrue(head.equals(p4));
825
    }
826
    
827
    /**
828
     * case 16. P1(S1) <- P2(S1) -> ?? <-P4(S2) S1 = P2 (two ends, not an ideal chain), S2=P4 (rule1)
829
     * @throws Exception
830
     */
831
    private void testCase16() throws Exception {
832
        Identifier s1 = new Identifier();
833
        s1.setValue("S1");
834
        Identifier s2 = new Identifier();
835
        s2.setValue("S2");
836
        Identifier p1 = new Identifier();
837
        p1.setValue("P1");
838
        Identifier p2 = new Identifier();
839
        p2.setValue("P2");
840
        Identifier p3 = new Identifier();
841
        p3.setValue("P3");
842
        Identifier p4 = new Identifier();
843
        p4.setValue("P4");
844
       
845
        
846
        SystemMetadata p1Sys = new SystemMetadata();
847
        p1Sys.setIdentifier(p1);
848
        p1Sys.setSeriesId(s1);
849
        //p1Sys.setObsoletedBy(p2);
850
        p1Sys.setDateUploaded(new Date(100));
851
        
852
        SystemMetadata p2Sys = new SystemMetadata();
853
        p2Sys.setIdentifier(p2);
854
        p2Sys.setSeriesId(s1);
855
        p2Sys.setObsoletes(p1);
856
        p2Sys.setObsoletedBy(p3);
857
        p2Sys.setDateUploaded(new Date(200));
858
        
859
        SystemMetadata p4Sys = new SystemMetadata();
860
        p4Sys.setIdentifier(p4);
861
        p4Sys.setSeriesId(s2);
862
        p4Sys.setObsoletes(p3);
863
        p4Sys.setDateUploaded(new Date(400));
864
        
865
 
866
        
867
        Vector<SystemMetadata> chain = new Vector<SystemMetadata>();
868
        chain.add(p1Sys);
869
        chain.add(p2Sys);
870
        chain.add(p4Sys);
871
        
872
        
873
        System.out.println("Case 16:");
874
        Identifier head = getHeadVersion(s1, chain);
875
        //System.out.println("The head is "+head.getValue());
876
        assertTrue(head.equals(p2));
877
        Identifier head2 = getHeadVersion(s2, chain);
878
        //System.out.println("The head is "+head.getValue());
879
        assertTrue(head2.equals(p4));
880
    }
881
    
882
    /**
883
     * case 17. P1(S1) <- P2(S1) -> ?? <-P4(S1) S1 = P4 (P1 and P4 are two ends, not an ideal chain)
884
     * @throws Exception
885
     */
886
    private void testCase17() throws Exception {
887
        Identifier s1 = new Identifier();
888
        s1.setValue("S1");
889
        Identifier s2 = new Identifier();
890
        s2.setValue("S2");
891
        Identifier p1 = new Identifier();
892
        p1.setValue("P1");
893
        Identifier p2 = new Identifier();
894
        p2.setValue("P2");
895
        Identifier p3 = new Identifier();
896
        p3.setValue("P3");
897
        Identifier p4 = new Identifier();
898
        p4.setValue("P4");
899
       
900
        
901
        SystemMetadata p1Sys = new SystemMetadata();
902
        p1Sys.setIdentifier(p1);
903
        p1Sys.setSeriesId(s1);
904
        //p1Sys.setObsoletedBy(p2);
905
        p1Sys.setDateUploaded(new Date(100));
906
        
907
        SystemMetadata p2Sys = new SystemMetadata();
908
        p2Sys.setIdentifier(p2);
909
        p2Sys.setSeriesId(s1);
910
        p2Sys.setObsoletes(p1);
911
        p2Sys.setObsoletedBy(p3);
912
        p2Sys.setDateUploaded(new Date(200));
913
        
914
        SystemMetadata p4Sys = new SystemMetadata();
915
        p4Sys.setIdentifier(p4);
916
        p4Sys.setSeriesId(s1);
917
        p4Sys.setObsoletes(p3);
918
        p4Sys.setDateUploaded(new Date(400));
919
        
920
 
921
        
922
        Vector<SystemMetadata> chain = new Vector<SystemMetadata>();
923
        chain.add(p1Sys);
924
        chain.add(p2Sys);
925
        chain.add(p4Sys);
926
        
927
        
928
        System.out.println("Case 17:");
929
        Identifier head = getHeadVersion(s1, chain);
930
        //System.out.println("The head is "+head.getValue());
931
        assertTrue(head.equals(p4));
932
      
933
    }
934
    
935
    /**
936
     * case 18. P1(S1) <->P2(S1) -> ??  ???<-P5(S1) S1 = P5 (P2 is a type 2 end and P4  is a type 1 end, not an ideal chain)
937
     * @throws Exception
938
     */
939
    private void testCase18() throws Exception {
940
        Identifier s1 = new Identifier();
941
        s1.setValue("S1");
942
        Identifier s2 = new Identifier();
943
        s2.setValue("S2");
944
        Identifier p1 = new Identifier();
945
        p1.setValue("P1");
946
        Identifier p2 = new Identifier();
947
        p2.setValue("P2");
948
        Identifier p3 = new Identifier();
949
        p3.setValue("P3");
950
        Identifier p4 = new Identifier();
951
        p4.setValue("P4");
952
        Identifier p5 = new Identifier();
953
        p5.setValue("P5");
954
       
955
        
956
        SystemMetadata p1Sys = new SystemMetadata();
957
        p1Sys.setIdentifier(p1);
958
        p1Sys.setSeriesId(s1);
959
        p1Sys.setObsoletedBy(p2);
960
        p1Sys.setDateUploaded(new Date(100));
961
        
962
        SystemMetadata p2Sys = new SystemMetadata();
963
        p2Sys.setIdentifier(p2);
964
        p2Sys.setSeriesId(s1);
965
        p2Sys.setObsoletes(p1);
966
        p2Sys.setObsoletedBy(p3);
967
        p2Sys.setDateUploaded(new Date(200));
968
        
969
        SystemMetadata p5Sys = new SystemMetadata();
970
        p5Sys.setIdentifier(p5);
971
        p5Sys.setSeriesId(s1);
972
        p5Sys.setObsoletes(p4);
973
        p5Sys.setDateUploaded(new Date(500));
974
        
975
 
976
        
977
        Vector<SystemMetadata> chain = new Vector<SystemMetadata>();
978
        chain.add(p1Sys);
979
        chain.add(p2Sys);
980
        chain.add(p5Sys);
981
        
982
        
983
        System.out.println("Case 18:");
984
        Identifier head = getHeadVersion(s1, chain);
985
        //System.out.println("The head is "+head.getValue());
986
        assertTrue(head.equals(p5));
987
      
988
    }
989
	
990
	
991
	/*
992
	 * completed the obsoletes and obsoletedBy information for the given pid. 
993
	 * We will look up the information from the given chain if its obsoletes or obsoletedBy field is missing.
994
	 */
995
	private void decorateSystemMetadata(SystemMetadata targetSysmeta, Vector<SystemMetadata> chain) {
996
	    if(targetSysmeta != null) {
997
	        if (targetSysmeta.getObsoletes() == null && targetSysmeta.getObsoletedBy() == null) {
998
	            Identifier obsoletes = getRelatedIdentifier(targetSysmeta.getIdentifier(), OBSOLETES, chain);
999
	            if(obsoletes != null) {
1000
	                targetSysmeta.setObsoletedBy(obsoletes);
1001
	            }
1002
	            Identifier obsoleted = getRelatedIdentifier(targetSysmeta.getIdentifier(), OBSOLETEDBY, chain);
1003
	            if(obsoleted != null) {
1004
	                targetSysmeta.setObsoletes(obsoleted);
1005
	            }
1006
	        } else if (targetSysmeta.getObsoletes() != null && targetSysmeta.getObsoletedBy() == null) {
1007
	            Identifier obsoleted = getRelatedIdentifier(targetSysmeta.getIdentifier(), OBSOLETEDBY, chain);
1008
                if(obsoleted != null) {
1009
                    targetSysmeta.setObsoletes(obsoleted);
1010
                }
1011
	            
1012
	        } else if (targetSysmeta.getObsoletes() == null && targetSysmeta.getObsoletedBy() != null) {
1013
	            Identifier obsoletes = getRelatedIdentifier(targetSysmeta.getIdentifier(), OBSOLETES, chain);
1014
                if(obsoletes != null) {
1015
                    targetSysmeta.setObsoletedBy(obsoletes);
1016
                }
1017
            }
1018
	    }
1019
	}
1020
	
1021
	/*
1022
	 * Get the identifier in chain which obsoleted or obsoletedBy the target id.
1023
	 */
1024
	private Identifier getRelatedIdentifier(Identifier target, String keyword, Vector<SystemMetadata> chain) {
1025
	    Identifier identifier = null;
1026
	    if(keyword.equals(OBSOLETES)) {
1027
	        for(SystemMetadata sysmeta :chain) {
1028
	            Identifier obsoletes = sysmeta.getObsoletes();
1029
	            if(obsoletes != null && obsoletes.equals(target)) {
1030
	                identifier = sysmeta.getIdentifier();
1031
	            }
1032
	        }
1033
	    } else if(keyword.equals(OBSOLETEDBY)) {
1034
	        for(SystemMetadata sysmeta :chain) {
1035
	            Identifier obsoletedBy = sysmeta.getObsoletedBy();
1036
	            if(obsoletedBy != null && obsoletedBy.equals(target)) {
1037
	                identifier = sysmeta.getIdentifier();
1038
	            }
1039
	        }
1040
	        
1041
	    }
1042
	    return identifier;
1043
	}
1044
	
1045
	
1046
	/*
1047
	 * Decide if a system metadata object missing a obsoletes or obsoletedBy fields:
1048
	 * 1. The system metadata object has both "oboletes" and "obsoletedBy" fields.
1049
     * 2. If a system metadata object misses "oboletes" field, another system metadata object whose "obsoletedBy" fields points to the identifier doesn't exist.
1050
    *  3. If a system metadata object misses "oboletedBy" field, another system metadata object whose "obsoletes" fields points to the identifier doesn't exist.
1051
	 */
1052
	private boolean hasMissingObsolescenceFields(SystemMetadata targetSysmeta, Vector<SystemMetadata> chain) {
1053
	    boolean has = false;
1054
	    if(targetSysmeta != null) {
1055
            if (targetSysmeta.getObsoletes() == null && targetSysmeta.getObsoletedBy() == null) {
1056
                if(foundIdentifierInAnotherSystemMetadata(targetSysmeta.getIdentifier(), OBSOLETEDBY, chain)) {
1057
                    has = true;
1058
                } else {
1059
                    if(foundIdentifierInAnotherSystemMetadata(targetSysmeta.getIdentifier(), OBSOLETES, chain)) {
1060
                        has = true;
1061
                    }
1062
                }
1063
                
1064
            } else if (targetSysmeta.getObsoletes() != null && targetSysmeta.getObsoletedBy() == null) {
1065
                if(foundIdentifierInAnotherSystemMetadata(targetSysmeta.getIdentifier(), OBSOLETES, chain)) {
1066
                    has = true;
1067
                }
1068
                
1069
            } else if (targetSysmeta.getObsoletes() == null && targetSysmeta.getObsoletedBy() != null) {
1070
                if(foundIdentifierInAnotherSystemMetadata(targetSysmeta.getIdentifier(), OBSOLETEDBY, chain)) {
1071
                    has = true;
1072
                }
1073
            }
1074
        }
1075
	    return has;
1076
	}
1077
	
1078
	/**
1079
	 * Determine if the sepcified identifier exists in the sepcified field in another system metadata object.
1080
	 * @param target
1081
	 * @param fieldName
1082
	 * @param chain
1083
	 * @return true if we found it; false otherwise.
1084
	 */
1085
	private boolean foundIdentifierInAnotherSystemMetadata(Identifier target, String fieldName, Vector<SystemMetadata> chain) {
1086
	    boolean found = false;
1087
	    if(fieldName.equals(OBSOLETES)) {
1088
            for(SystemMetadata sysmeta :chain) {
1089
                Identifier obsoletes = sysmeta.getObsoletes();
1090
                if(obsoletes != null && obsoletes.equals(target)) {
1091
                    System.out.println("missing obsoletedBy");
1092
                    found = true;
1093
                }
1094
            }
1095
        } else if(fieldName.equals(OBSOLETEDBY)) {
1096
            for(SystemMetadata sysmeta :chain) {
1097
                Identifier obsoletedBy = sysmeta.getObsoletedBy();
1098
                if(obsoletedBy != null && obsoletedBy.equals(target)) {
1099
                    System.out.println("missing obsoletes");
1100
                    found = true;
1101
                }
1102
            }
1103
            
1104
        }
1105
	    return found;
1106
	}
1107
	
1108
	/**
1109
	 * Get the head version of the chain
1110
	 * @param sid
1111
	 * @return
1112
	 */
1113
	/*public Identifier getHeadVersion(Identifier sid, Vector<SystemMetadata> chain) {
1114
	    Identifier pid = null;
1115
	    Vector<SystemMetadata> sidChain = new Vector<SystemMetadata>();
1116
	    int noObsoletedByCount =0;
1117
	    boolean hasMissingObsolescenceFields = false;
1118
	    if(chain != null) {
1119
	        for(SystemMetadata sysmeta : chain) {
1120
	            if(sysmeta.getSeriesId() != null && sysmeta.getSeriesId().equals(sid)) {
1121
	                //decorateSystemMetadata(sysmeta, chain);
1122
	                System.out.println("identifier "+sysmeta.getIdentifier().getValue()+" :");
1123
	                if(sysmeta.getObsoletes() == null) {
1124
	                    System.out.println("obsolets "+sysmeta.getObsoletes());
1125
	                } else {
1126
	                    System.out.println("obsolets "+sysmeta.getObsoletes().getValue());
1127
	                }
1128
	                if(sysmeta.getObsoletedBy() == null) {
1129
	                    System.out.println("obsoletedBy "+sysmeta.getObsoletedBy());
1130
	                } else {
1131
	                    System.out.println("obsoletedBy "+sysmeta.getObsoletedBy().getValue());
1132
	                }
1133
	                if(!hasMissingObsolescenceFields) {
1134
	                    if(hasMissingObsolescenceFields(sysmeta, chain)) {
1135
	                        hasMissingObsolescenceFields = true;
1136
	                    }
1137
	                }
1138
	                
1139
	                if(sysmeta.getObsoletedBy() == null) {
1140
	                    pid = sysmeta.getIdentifier();
1141
	                    noObsoletedByCount++;
1142
	                }
1143
	                sidChain.add(sysmeta);
1144
	            }
1145
	        }
1146
	    }
1147
	    
1148
	    if(hasMissingObsolescenceFields) {
1149
	        System.out.println("It has an object whose system metadata has a missing obsoletes or obsoletedBy field.");
1150
	        Collections.sort(sidChain, new SystemMetadataDateUploadedComparator());
1151
            pid =sidChain.lastElement().getIdentifier();
1152
	    } else {
1153
	        if(noObsoletedByCount == 1) {
1154
	            //rule 1 . If there is only one object having NULL value in the chain, return the value
1155
	             System.out.println("rule 1");
1156
	             return pid;
1157
	         } else if (noObsoletedByCount > 1 ) {
1158
	             // rule 2. If there is more than one object having NULL value in the chain, return last dateUploaded
1159
	             System.out.println("rule 2");
1160
	             Collections.sort(sidChain, new SystemMetadataDateUploadedComparator());
1161
	             pid =sidChain.lastElement().getIdentifier();
1162
	             
1163
	         } else if (noObsoletedByCount == 0) {
1164
	             // all pids were obsoleted
1165
	             for(SystemMetadata sysmeta : sidChain) {
1166
	                 //System.out.println("=== the pid in system metadata "+sysmeta.getIdentifier().getValue());
1167
	                 Identifier obsoletedBy = sysmeta.getObsoletedBy();
1168
	                 SystemMetadata sysOfObsoletedBy = getSystemMetadata(obsoletedBy, chain);
1169
	                 if(sysOfObsoletedBy == null) {
1170
	                     //Rule 4 We have a obsoletedBy id without system metadata. So we can't decide if a different sid exists. we have to sort it.
1171
	                     System.out.println("rule 4");
1172
	                     Collections.sort(sidChain, new SystemMetadataDateUploadedComparator());
1173
	                     pid = sidChain.lastElement().getIdentifier();
1174
	                     break;
1175
	                 } else {
1176
	                     Identifier sidOfObsoletedBy = sysOfObsoletedBy.getSeriesId();
1177
	                     if(sidOfObsoletedBy != null && !sidOfObsoletedBy.equals(sid)) {
1178
	                         //rule 3, if everything in {S1} is obsoleted, then select object that is obsoleted by another object that does not have the same SID
1179
	                         System.out.println("rule 3-1 (close with another sid "+sidOfObsoletedBy.getValue()+")");
1180
	                         pid = sysmeta.getIdentifier();
1181
	                         break;
1182
	                     } else if (sidOfObsoletedBy == null ) {
1183
	                         //rule 3, If everything in {S1} is obsoleted, then select object that is obsoleted by another object that does not have the same SID (this case, no sid)
1184
	                         System.out.println("rule 3-2 (close without sid)");
1185
	                         pid = sysmeta.getIdentifier();
1186
	                         break;
1187
	                     }
1188
	                 }
1189
	                 
1190
	             }
1191
	         }
1192
	    }
1193
	    
1194
	    return pid;
1195
	}*/
1196
	
1197
	
1198
	private SystemMetadata getSystemMetadata(Identifier id, Vector<SystemMetadata> chain ){
1199
	    SystemMetadata sysmeta = null;
1200
	    if(id != null) {
1201
	        for(SystemMetadata sys : chain) {
1202
	            if(sys.getIdentifier().equals(id)) {
1203
	                sysmeta = sys;
1204
	                break;
1205
	            }
1206
	        }
1207
	    }
1208
	    return sysmeta;
1209
	}
1210
	
1211
	/**
1212
     * Get the head version of the chain
1213
     * @param sid
1214
     * @return
1215
     */
1216
    public Identifier getHeadVersion(Identifier sid, Vector<SystemMetadata> chain) {
1217
        Identifier pid = null;
1218
        Vector<SystemMetadata> sidChain = new Vector<SystemMetadata>();
1219
        int endCounter =0 ;
1220
        String status = null;
1221
        if(chain != null) {
1222
            for(SystemMetadata sysmeta : chain) {
1223
                if(sysmeta.getSeriesId() != null && sysmeta.getSeriesId().equals(sid)) {
1224
                    status = endStatus(sysmeta, chain);
1225
                    if(status.equals(END1) || status.equals(END2)) {
1226
                        endCounter ++;
1227
                        pid = sysmeta.getIdentifier();
1228
                    }
1229
                    sidChain.add(sysmeta);
1230
                }
1231
            }
1232
            if(endCounter != 1) {
1233
                System.out.println("The chain has "+endCounter+" ends and it is not an ideal chain.");
1234
                Collections.sort(sidChain, new SystemMetadataDateUploadedComparator());
1235
                pid =sidChain.lastElement().getIdentifier();
1236
            } else {
1237
                System.out.println(""+status);
1238
            }
1239
        }
1240
        return pid;
1241
    }
1242
	
1243
	
1244
    /*
1245
     * Rules for ends:
1246
     *  Rule 1. An object in the SID chain doesn't have the "obsoletedBy" field.
1247
     *  Rule 2. An object in the SID chain does have the "obsoletedBy" filed, but the "obsoletedBy" value has different the SID value (including no SID value).
1248
     *  It is tricky if the object in the "obsoletedBy" filed is missing since we don't have the knowledge of its series id. Generally we consider it an end except: 
1249
     *  if there is another object in the chain (has the same series id) obsoletes the missing object, the missing object is not an end.
1250
     */
1251
    private String endStatus(SystemMetadata targetSysmeta, Vector<SystemMetadata> chain) {
1252
        String status = END2;
1253
        if(targetSysmeta.getObsoletedBy() == null) {
1254
            status = END1;
1255
        } else {
1256
            Identifier orgSid = targetSysmeta.getSeriesId();
1257
            Identifier obsoletedBy = targetSysmeta.getObsoletedBy();
1258
            SystemMetadata obsoletedBySys = getSystemMetadata(obsoletedBy, chain);
1259
            if(obsoletedBySys != null) {
1260
                if(obsoletedBySys.getSeriesId() != null && obsoletedBySys.getSeriesId().equals(orgSid)) {
1261
                    status = NOTEND;
1262
                }
1263
            } else {
1264
                // the obsoletedBy doesn't exist
1265
                for(SystemMetadata sys : chain) {
1266
                    if(sys.getSeriesId() != null && sys.getSeriesId().equals(orgSid)) {
1267
                        if(sys.getObsoletes() != null && sys.getObsoletes().equals(obsoletedBy)) {
1268
                            status = NOTEND;
1269
                        }
1270
                    }
1271
                }
1272
            }
1273
        }
1274
        return status;
1275
    }
1276
    
1277
    private static final String END1 = "Rule 1";
1278
    private static final String END2 = "Rule 2";
1279
    private static final String NOTEND = "Not an end";
1280
}
(7-7/9)