This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git
The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
new 93d2fe1 LocaleAndCharset.getCharacterSets(…) should returns a
Collection that implement equals(Object) method.
93d2fe1 is described below
commit 93d2fe1ce38b83bb028872e997f124166cff3cfa
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Tue May 7 12:06:15 2019 +0200
LocaleAndCharset.getCharacterSets(…) should returns a Collection that
implement equals(Object) method.
---
.../sis/internal/jaxb/lan/LocaleAndCharset.java | 12 ++-
.../identification/DefaultDataIdentification.java | 2 +-
.../org/apache/sis/internal/util/AbstractMap.java | 3 +-
.../java/org/apache/sis/internal/util/Bag.java | 104 +++++++++++++++++++++
.../main/java/org/apache/sis/util/ArraysExt.java | 8 +-
.../java/org/apache/sis/internal/util/BagTest.java | 80 ++++++++++++++++
.../apache/sis/test/suite/UtilityTestSuite.java | 1 +
7 files changed, 198 insertions(+), 12 deletions(-)
diff --git
a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/lan/LocaleAndCharset.java
b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/lan/LocaleAndCharset.java
index c99a62e..aaab4d7 100644
---
a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/lan/LocaleAndCharset.java
+++
b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/lan/LocaleAndCharset.java
@@ -20,16 +20,16 @@ import java.util.Map;
import java.util.LinkedHashMap;
import java.util.AbstractSet;
import java.util.AbstractList;
-import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Collections;
import java.util.Locale;
import java.nio.charset.Charset;
import java.util.Iterator;
+import org.apache.sis.internal.util.Bag;
+import org.apache.sis.internal.util.CollectionsExt;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.collection.TableColumn;
import org.apache.sis.util.collection.TreeTable.Node;
-import org.apache.sis.internal.util.CollectionsExt;
/**
@@ -283,6 +283,9 @@ public final class LocaleAndCharset implements Node {
@Override public int size() {
return locales.size();
}
+ @Override public void clear() {
+ locales.clear(); // Default
implementation would invoke Iterator.remove() anyway.
+ }
@Override public boolean contains(Object o) {
return locales.containsKey(o);
}
@@ -313,10 +316,13 @@ public final class LocaleAndCharset implements Node {
if (locales == null) {
return null;
}
- return new AbstractCollection<Charset>() {
+ return new Bag<Charset>() {
@Override public int size() {
return locales.size();
}
+ @Override public void clear() {
+ locales.clear(); // Default
implementation would invoke Iterator.remove() anyway.
+ }
@Override public boolean contains(Object o) {
return locales.containsValue(o);
}
diff --git
a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultDataIdentification.java
b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultDataIdentification.java
index f7bb052..b0e86b3 100644
---
a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultDataIdentification.java
+++
b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultDataIdentification.java
@@ -31,8 +31,8 @@ import org.opengis.metadata.identification.DataIdentification;
import org.apache.sis.internal.jaxb.lan.LocaleAndCharset;
import org.apache.sis.internal.jaxb.lan.OtherLocales;
import org.apache.sis.internal.jaxb.lan.PT_Locale;
-import org.apache.sis.internal.xml.LegacyNamespaces;
import org.apache.sis.internal.jaxb.FilterByVersion;
+import org.apache.sis.internal.xml.LegacyNamespaces;
import org.apache.sis.internal.metadata.Dependencies;
diff --git
a/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java
b/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java
index 7310930..bba1d0d 100644
---
a/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java
+++
b/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java
@@ -22,7 +22,6 @@ import java.util.Objects;
import java.util.Iterator;
import java.util.Collection;
import java.util.Collections;
-import java.util.AbstractCollection;
import java.util.NoSuchElementException;
import org.apache.sis.io.TableAppender;
import org.apache.sis.util.resources.Errors;
@@ -465,7 +464,7 @@ public abstract class AbstractMap<K,V> implements Map<K,V> {
*/
@Override
public Collection<V> values() {
- return new AbstractCollection<V>() {
+ return new Bag<V>() {
@Override public void clear() {
AbstractMap.this.clear();}
@Override public boolean isEmpty() {return
AbstractMap.this.isEmpty();}
@Override public int size() {return
AbstractMap.this.size();}
diff --git
a/core/sis-utility/src/main/java/org/apache/sis/internal/util/Bag.java
b/core/sis-utility/src/main/java/org/apache/sis/internal/util/Bag.java
new file mode 100644
index 0000000..aaf1926
--- /dev/null
+++ b/core/sis-utility/src/main/java/org/apache/sis/internal/util/Bag.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.util;
+
+
+import java.util.Objects;
+import java.util.AbstractCollection;
+import org.apache.sis.util.ArraysExt;
+
+
+/**
+ * A collection in which elements order does not matter (as in {@link
java.util.Set})
+ * but in which duplicated elements are allowed (as in {@link java.util.List}).
+ * The "bag" word is used in ISO specifications for such kind of collection.
+ * This base class is suitable to collection returned by {@link
java.util.Map#values()};
+ * it is not necessarily a good fit for all other subtypes of {@link
AbstractCollection}.
+ *
+ * <p>This abstract class implements the {@link #equals(Object)} and {@link
#hashCode()} methods.
+ * Subclasses need to override at least {@link #size()} and {@link
#iterator()}.</p>
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @version 1.0
+ *
+ * @param <E> type of elements in this bag.
+ *
+ * @since 1.0
+ * @module
+ */
+public abstract class Bag<E> extends AbstractCollection<E> {
+ /**
+ * Creates a new instance.
+ */
+ protected Bag() {
+ }
+
+ /**
+ * Compares this bag with the given object for equality. This method
performs comparisons only
+ * with instances of {@code Bag}, and returns {@code false} for all other
kinds of collection.
+ * We do <strong>not</strong> compare with arbitrary collection
implementations.
+ *
+ * <p><b>Rational:</b> {@link java.util.Collection#equals(Object)}
contract explicitly forbids comparisons
+ * with {@code List} and {@code Set}. The rational explained in {@code
Collection} javadoc applies also to
+ * other kind of {@code Collection} implementations: we can not enforce
{@code Collection.equals(Object)}
+ * to be symmetric in such cases.</p>
+ *
+ * @param other the other object to compare with this bag.
+ * @return {@code true} if the two bags are equal.
+ */
+ @Override
+ public boolean equals(final Object other) {
+ if (other == this) {
+ return true;
+ }
+ if (other instanceof Bag) {
+ int size = size();
+ if (size == ((Bag) other).size()) {
+ final Object[] elements = toArray();
+ ArraysExt.reverse(elements);
+compare: for (final Object oe : (Bag) other) {
+ for (int i=size; --i >= 0;) {
+ if (Objects.equals(elements[i], oe)) {
+ System.arraycopy(elements, i+1, elements, i,
--size - i);
+ continue compare;
+ }
+ }
+ return false;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns a hash code value for this bag, ignoring element order.
+ * This method computes hash code in the same way than {@link
java.util.Set}.
+ *
+ * @return a hash code value.
+ */
+ @Override
+ public int hashCode() {
+ int code = 0;
+ for (final Object value : this) {
+ if (value != null) {
+ code += value.hashCode();
+ }
+ }
+ return code;
+ }
+}
diff --git a/core/sis-utility/src/main/java/org/apache/sis/util/ArraysExt.java
b/core/sis-utility/src/main/java/org/apache/sis/util/ArraysExt.java
index 063e217..018b439 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/util/ArraysExt.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/util/ArraysExt.java
@@ -1241,9 +1241,7 @@ public final class ArraysExt extends Static {
int i = entries.length >>> 1;
int j = i + (entries.length & 1);
while (--i >= 0) {
- final Object tmp = entries[i];
- entries[i] = entries[j];
- entries[j++] = tmp;
+ swap(entries, i, j++);
}
}
}
@@ -1260,9 +1258,7 @@ public final class ArraysExt extends Static {
int i = values.length >>> 1;
int j = i + (values.length & 1);
while (--i >= 0) {
- final int tmp = values[i];
- values[i] = values[j];
- values[j++] = tmp;
+ swap(values, i, j++);
}
}
}
diff --git
a/core/sis-utility/src/test/java/org/apache/sis/internal/util/BagTest.java
b/core/sis-utility/src/test/java/org/apache/sis/internal/util/BagTest.java
new file mode 100644
index 0000000..f638d69
--- /dev/null
+++ b/core/sis-utility/src/test/java/org/apache/sis/internal/util/BagTest.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.util;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+import org.apache.sis.test.TestCase;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+
+/**
+ * Tests {@link Bag}.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @version 1.0
+ * @since 1.0
+ * @module
+ */
+public final strictfp class BagTest extends TestCase {
+ /**
+ * Creates an instance initialized to the given values.
+ */
+ private static Bag<Integer> create(final int... values) {
+ final List<Integer> list = new ArrayList<>(values.length);
+ for (final int v : values) list.add(v);
+ return new Bag<Integer>() {
+ @Override public int size() {return list.size();}
+ @Override public Iterator<Integer> iterator() {return
list.iterator();}
+ };
+ }
+
+ /**
+ * Asserts that the following bags are equal.
+ */
+ private static void assertBagEquals(final Bag<?> b1, final Bag<?> b2) {
+ assertEquals(b1, b2);
+ assertEquals(b2, b1);
+ assertEquals(b1.hashCode(), b2.hashCode());
+ }
+
+ /**
+ * Asserts that the following bags are not equal.
+ */
+ private static void assertBagNotEquals(final Bag<?> b1, final Bag<?> b2) {
+ assertNotEquals(b1, b2);
+ assertNotEquals(b2, b1);
+ assertNotEquals(b1.hashCode(), b2.hashCode());
+ }
+
+ /**
+ * Tests {@link Bag#equals(Object)} and {@link Bag#hashCode()}.
+ */
+ @Test
+ public void testEquals() {
+ Bag<Integer> b1 = create(4, 8, 3, 2);
+ Bag<Integer> b2 = create(8, 2, 3, 4);
+ Bag<Integer> b3 = create(8, 5, 4, 3);
+ assertEquals (b1, b1);
+ assertBagEquals (b1, b2);
+ assertBagNotEquals(b1, b3);
+ assertBagNotEquals(b2, b3);
+ }
+}
diff --git
a/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
b/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
index 57d2de5..81a2737 100644
---
a/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
+++
b/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
@@ -69,6 +69,7 @@ import org.junit.BeforeClass;
org.apache.sis.math.PlaneTest.class,
// Collections.
+ org.apache.sis.internal.util.BagTest.class,
org.apache.sis.internal.util.CheckedArrayListTest.class,
org.apache.sis.internal.util.ListOfUnknownSizeTest.class,
org.apache.sis.internal.system.ReferenceQueueConsumerTest.class,