Skip to content

Commit

Permalink
(#1224) Copying nested list inside list/Immutable
Browse files Browse the repository at this point in the history
  • Loading branch information
iakunin committed Nov 10, 2019
1 parent 2eaf3c7 commit 09c4556
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 25 deletions.
5 changes: 5 additions & 0 deletions src/main/java/org/cactoos/collection/Immutable.java
Expand Up @@ -37,6 +37,11 @@
* @todo #898:30min Replace all the Collections.unmodifiableCollection
* with the {@link org.cactoos.collection.Immutable} from the cactoos codebase.
* That should be done because Elegant Object principles are against static methods.
* @todo #1224:30min Original collection should be copied inside this
* immutable decorator. That should be done because otherwise true immutability
* cannot be achieved.
* see: https://github.com/yegor256/cactoos/issues/1224 and
* https://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html
*/
@SuppressWarnings(
{
Expand Down
85 changes: 78 additions & 7 deletions src/main/java/org/cactoos/list/Immutable.java
Expand Up @@ -25,9 +25,19 @@

import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import org.cactoos.Scalar;
import org.cactoos.collection.Sliced;
import org.cactoos.iterable.IterableOf;
import org.cactoos.scalar.And;
import org.cactoos.scalar.Folded;
import org.cactoos.scalar.Or;
import org.cactoos.scalar.SumOfInt;
import org.cactoos.scalar.Unchecked;
import org.cactoos.text.TextOf;
import org.cactoos.text.UncheckedText;

/**
* {@link List} envelope that doesn't allow mutations.
Expand All @@ -36,6 +46,7 @@
*
* @param <T> Element type
* @since 1.16
* @checkstyle ClassDataAbstractionCouplingCheck (500 lines)
* @todo #898:30min Replace all the Collections.unmodifiableList
* with the {@link org.cactoos.list.Immutable} from the cactoos codebase.
* That should be done because Elegant Object principles are against static methods.
Expand All @@ -54,20 +65,51 @@ public final class Immutable<T> implements List<T> {
*/
private final List<T> list;

/**
* Ctor.
* @param items Source array
*/
@SafeVarargs
public Immutable(final T... items) {
this(new IterableOf<>(items));
}

/**
* Ctor.
* @param src Source collection
*/
public Immutable(final Collection<T> src) {
this(new ListOf<>(src));
this(new IterableOf<>(src.iterator()));
}

/**
* Ctor.
* @param src Source list
*/
public Immutable(final List<T> src) {
this.list = new ListOf<>(src);
this(new IterableOf<>(src.iterator()));
}

/**
* Ctor.
* @param src Source iterable
*/
public Immutable(final Iterable<T> src) {
this(() -> {
final List<T> copy = new LinkedList<>();
for (final T item : src) {
copy.add(item);
}
return copy;
});
}

/**
* Ctor.
* @param slr The scalar
*/
public Immutable(final Scalar<List<T>> slr) {
this.list = new Unchecked<>(slr).value();
}

@Override
Expand Down Expand Up @@ -213,17 +255,46 @@ public List<T> subList(final int start, final int end) {
}

@Override
public String toString() {
return this.list.toString();
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings("EQ_UNUSUAL")
public boolean equals(final Object other) {
return new Unchecked<>(
new Or(
() -> other == this,
new And(
() -> other != null,
() -> List.class.isAssignableFrom(other.getClass()),
() -> {
final List<?> compared = (List<?>) other;
final Iterator<?> iterator = compared.iterator();
return new Unchecked<>(
new And(
(T input) -> input.equals(iterator.next()),
this
)
).value();
}
)
)
).value();
}

// @checkstyle MagicNumberCheck (30 lines)
@Override
public int hashCode() {
return this.list.hashCode();
return new Unchecked<>(
new Folded<>(
42,
(hash, entry) -> new SumOfInt(
() -> 37 * hash,
entry::hashCode
).value(),
this
)
).value();
}

@Override
public boolean equals(final Object obj) {
return this.list.equals(obj);
public String toString() {
return new UncheckedText(new TextOf(this)).asString();
}
}
67 changes: 49 additions & 18 deletions src/test/java/org/cactoos/list/ImmutableTest.java
Expand Up @@ -28,6 +28,7 @@
import java.util.List;
import org.cactoos.collection.CollectionOf;
import org.hamcrest.core.IsEqual;
import org.hamcrest.core.IsNot;
import org.junit.Test;
import org.llorllale.cactoos.matchers.Assertion;
import org.llorllale.cactoos.matchers.HasValues;
Expand Down Expand Up @@ -407,41 +408,71 @@ public void immutableSubList() {
}

@Test
public void testToString() {
public void notEqualsToObjectOfAnotherType() {
new Assertion<>(
"toString() must be equals to original",
new Immutable<>(
new ListOf<>("a", "b", "c")
).toString(),
new IsEqual<>(
new ListOf<>("a", "b", "c").toString()
"must not equal to object of another type",
new Immutable<>(),
new IsNot<>(new IsEqual<>(new Object()))
).affirm();
}

@Test
public void notEqualsToListWithDifferentElements() {
new Assertion<>(
"must not equal to List with different elements",
new Immutable<>(1, 2),
new IsNot<>(
new IsEqual<>(new ListOf<>(1, 0))
)
).affirm();
}

@Test
public void isEqualToItself() {
final List<Integer> list = new Immutable<>(1, 2);
new Assertion<>(
"must be equal to itself",
list,
new IsEqual<>(list)
).affirm();
}

@Test
public void isEqualToListWithTheSameElements() {
new Assertion<>(
"must be equal to List with the same elements",
new Immutable<>(1, 2),
new IsEqual<>(new ListOf<>(1, 2))
).affirm();
}

@Test
public void equalToEmptyImmutable() {
new Assertion<>(
"empty Immutable must be equal to empty Immutable",
new Immutable<>(),
new IsEqual<>(new Immutable<>())
).affirm();
}

@Test
public void testHashCode() {
new Assertion<>(
"hashCode() must be equals to original",
new Immutable<>(
new ListOf<>(1, 2, 3)
).hashCode(),
"hashCode() must be equal to hashCode of the corresponding List",
new Immutable<>(1, 2, 3).hashCode(),
new IsEqual<>(
new ListOf<>(1, 2, 3).hashCode()
)
).affirm();
}

@Test
public void testEquals() {
final ListOf<Integer> another = new ListOf<>(4, 5, 6);
public void testToString() {
new Assertion<>(
"equals() must be equals to original",
new Immutable<>(
new ListOf<>(1, 2, 3)
).equals(another),
"toString() must be concatenation of nested elements",
new Immutable<>("a", "b", "c").toString(),
new IsEqual<>(
new ListOf<>(1, 2, 3).equals(another)
"a, b, c"
)
).affirm();
}
Expand Down

0 comments on commit 09c4556

Please sign in to comment.