sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] branch geoapi-4.0 updated: LocaleAndCharset.getCharacterSets(…) should returns a Collection that implement equals(Object) method.
Date Tue, 07 May 2019 10:06:57 GMT
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 <martin.desruisseaux@geomatys.com>
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,


Mime
View raw message