Skip to content

Commit 499d148

Browse files
committed
Document symmetry-breaking equals in IonSequence
Fixes #1121
1 parent 900a0b1 commit 499d148

2 files changed

Lines changed: 61 additions & 12 deletions

File tree

‎gradle.properties‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
11
signing.keyId=EMPTY
22
signing.password=EMPTY
33
signing.secretKeyRingFile=EMPTY
4-
5-
ossrhUsername=EMPTY
6-
ossrhPassword=EMPTY

‎src/main/java/com/amazon/ion/IonSequence.java‎

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -426,15 +426,15 @@ public void add(int index, IonValue child)
426426
* </p>
427427
*
428428
* The implementation of {@link List<IonValue>} returned by this method
429-
* implements {@link List#equals(Object)} and
430-
* {@link List#equals(Object)} ()} per the specification of these methods.
429+
* implements {@link List#equals} and {@link List#hashCode()}
430+
* per the specification of these methods.
431431
* However, the existing implementation of {@link IonSequence} does not
432432
* provide a specification compliant {@link List#equals} and
433-
* {@link List#hashCode()}} which results to the following caveats:
433+
* {@link List#hashCode()} which results to the following caveats:
434434
*
435435
* Given:
436436
*
437-
* <code>
437+
* <pre> {@code
438438
* int[] ints = new int[] {1, 2, 3, 4};
439439
* IonList list = SYSTEM.newList(ints);
440440
* IonSexp sexp = SYSTEM.newSexp(ints)
@@ -444,7 +444,7 @@ public void add(int index, IonValue child)
444444
* List<IonValue> dgrmSubList = sexp.subList(0, ints.size())
445445
* List<IonValue> arrayList = new ArrayList<IonValue>();
446446
* for(int i : ints) { arrayList.add(SYSTEM.newInt(i)); }
447-
* </code>
447+
* } </pre>
448448
*
449449
* {@link IonSequence#equals(Object)} always returns false when presented
450450
* with a non {@link IonSequence} instance of {@link List<IonValue>}.
@@ -457,7 +457,7 @@ public void add(int index, IonValue child)
457457
* library we maintain backwards compatibility and support this behaviour
458458
* as-is.
459459
*
460-
* <code>
460+
* <pre> {@code
461461
* list.equals(listSubList) // false
462462
* list.equals(sexpSubList) // false
463463
* list.equals(dgrm) // false
@@ -472,7 +472,7 @@ public void add(int index, IonValue child)
472472
* dgrm.equals(sexpSubList) // false
473473
* dgrm.equals(dgrmSubList) // false
474474
* dgrm.equals(arrayList) // false
475-
*</code>
475+
* } </pre>
476476
*
477477
* However, {@link IonSequence#subList(int, int)} was implemented much
478478
* later and faithfully implements {@link List#equals(Object)} meaning
@@ -483,7 +483,7 @@ public void add(int index, IonValue child)
483483
* no notion of an {@link IonType}, annotations or nullability which
484484
* allows for compliance with the {@link List} specification.
485485
*
486-
* <code>
486+
* <pre> {@code
487487
* listSubList.equals(listSubList); // true
488488
* listSubList.equals(sexpSubList); // true
489489
* listSubList.equals(dgrmSubList); // true
@@ -504,7 +504,7 @@ public void add(int index, IonValue child)
504504
* dgrmSubList.equals(list); // true
505505
* dgrmSubList.equals(sexp); // true
506506
* dgrmSubList.equals(arrayList); // true
507-
* </code>
507+
* } </pre>
508508
*
509509
* @see List#subList(int, int)
510510
*/
@@ -566,4 +566,56 @@ public void add(int index, IonValue child)
566566

567567
public IonSequence clone()
568568
throws UnknownSymbolException;
569+
570+
/**
571+
* The existing implementation of {@link IonSequence} does not
572+
* provide a specification-compliant {@link List#equals} and
573+
* {@link List#hashCode()} which results to the following caveats:
574+
* <p>
575+
* Given:
576+
*
577+
* <pre> {@code
578+
* int[] ints = new int[] {1, 2, 3, 4};
579+
* IonList list = SYSTEM.newList(ints);
580+
* IonSexp sexp = SYSTEM.newSexp(ints)
581+
* IonSexp dgrm = SYSTEM.newDatagram(ints)
582+
* List<IonValue> listSubList = list.subList(0, ints.size())
583+
* List<IonValue> sexpSubList = sexp.subList(0, ints.size())
584+
* List<IonValue> dgrmSubList = sexp.subList(0, ints.size())
585+
* List<IonValue> arrayList = new ArrayList<IonValue>();
586+
* for(int i : ints) { arrayList.add(SYSTEM.newInt(i)); }
587+
* } </pre>
588+
*
589+
* {@link IonSequence#equals(Object)} always returns false when presented
590+
* with a non {@link IonSequence} instance of {@link List<IonValue>}.
591+
* Hence, the following invocations of {@link Object#equals(Object)}
592+
* return false even if the contained elements are equivalent. This
593+
* means that {@link Object#equals(Object)} is not symmetric in these
594+
* cases. The reason for the asymmetry is historical:
595+
* {@link IonSequence} has long violated the contract outlined by the
596+
* {@link List} documentation. For the current major version of this
597+
* library we maintain backwards compatibility and support this behaviour
598+
* as-is.
599+
*
600+
* <pre> {@code
601+
* list.equals(listSubList) // false
602+
* list.equals(sexpSubList) // false
603+
* list.equals(dgrm) // false
604+
* list.equals(arrayList) // false
605+
*
606+
* sexp.equals(listSubList) // false
607+
* sexp.equals(sexpSubList) // false
608+
* sexp.equals(dgrm) // false
609+
* sexp.equals(arrayList) // false
610+
*
611+
* dgrm.equals(listSubList) // false
612+
* dgrm.equals(sexpSubList) // false
613+
* dgrm.equals(dgrmSubList) // false
614+
* dgrm.equals(arrayList) // false
615+
* } </pre>
616+
*
617+
* @param other the object to be compared for equality with this list
618+
* @return {@code true} if the specified object is equal to this list
619+
*/
620+
boolean equals(Object other);
569621
}

0 commit comments

Comments
 (0)