sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1469283 - in /sis/branches/JDK7/sis-metadata/src: main/java/org/apache/sis/metadata/ test/java/org/apache/sis/metadata/
Date Thu, 18 Apr 2013 11:14:14 GMT
Author: desruisseaux
Date: Thu Apr 18 11:14:13 2013
New Revision: 1469283

URL: http://svn.apache.org/r1469283
Log:
Implemented PropertyInformation.getDomainValue().

Added:
    sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/DomainRange.java
  (with props)
Modified:
    sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java
    sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyInformation.java
    sis/branches/JDK7/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyInformationTest.java

Added: sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/DomainRange.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/DomainRange.java?rev=1469283&view=auto
==============================================================================
--- sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/DomainRange.java
(added)
+++ sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/DomainRange.java
[UTF-8] Thu Apr 18 11:14:13 2013
@@ -0,0 +1,163 @@
+/*
+ * 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.metadata;
+
+import java.util.Locale;
+import org.opengis.util.InternationalString;
+import org.apache.sis.measure.NumberRange;
+import org.apache.sis.measure.RangeFormat;
+import org.apache.sis.measure.ValueRange;
+
+
+/**
+ * The range of values that a metadata property can take, representable as an {@link InternationalString}
+ * in order to make possible to return this range from the {@link PropertyInformation#getDomainValue()}
+ * method.
+ *
+ * @param <E> The type of range elements as a subclass of {@link Number}.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.3
+ * @version 0.3
+ * @module
+ *
+ * @see PropertyInformation#getDomainValue()
+ */
+final class DomainRange<E extends Number & Comparable<? super E>> extends
NumberRange<E>
+        implements InternationalString
+{
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 702771264296112914L;
+
+    /**
+     * The locale-independent string representation,
+     * built by {@link #toString()} when first needed.
+     */
+    private transient volatile String text;
+
+    /**
+     * Constructs a range of the given type with values from the given annotation.
+     * This constructor does not verify if the given type is wide enough for the values of
+     * the given annotation, because those information are usually static. If nevertheless
+     * the given type is not wide enough, then the values are truncated in the same way
+     * than the Java language casts primitive types.
+     *
+     * @param  type  The element type, restricted to one of {@link Byte}, {@link Short},
+     *               {@link Integer}, {@link Long}, {@link Float} or {@link Double}.
+     * @param  range The range of values.
+     * @throws IllegalArgumentException If the given type is not one of the primitive
+     *         wrappers for numeric types.
+     */
+    DomainRange(final Class<E> type, final ValueRange range) throws IllegalArgumentException
{
+        super(type, range);
+    }
+
+    /**
+     * Returns the string representation in the given locale.
+     */
+    @Override
+    public String toString(final Locale locale) {
+        if (locale == null || locale == Locale.ROOT) {
+            return toString();
+        }
+        final RangeFormat format = new RangeFormat(locale, getElementType());
+        return format.format(this);
+    }
+
+    /**
+     * Builds, caches and returns the unlocalized string representation of this range.
+     */
+    @Override
+    public String toString() {
+        String s = text;
+        if (s == null) {
+            text = s = super.toString();
+        }
+        return s;
+    }
+
+    /**
+     * Returns the length of the unlocalized string.
+     */
+    @Override
+    public int length() {
+        return toString().length();
+    }
+
+    /**
+     * Returns the character at the given index in the unlocalized string.
+     */
+    @Override
+    public char charAt(final int index) {
+        return toString().charAt(index);
+    }
+
+    /**
+     * Returns a subsequence of the unlocalized string representation.
+     */
+    @Override
+    public CharSequence subSequence(final int start, final int end) {
+        return toString().subSequence(start, end);
+    }
+
+    /**
+     * Compares the unlocalized string representations. In the special case where the other
instance
+     * is a {@code DomainRange}, actually compares the numerical values for better ordering.
+     */
+    @Override
+    public int compareTo(final InternationalString o) {
+        if (o instanceof DomainRange) {
+            return compareTo((DomainRange<?>) o);
+        }
+        return toString().compareTo(o.toString());
+    }
+
+    /**
+     * Compares this range with the given range object for ordering of minimal values, or
maximal values
+     * if two ranges have the same minimum value.
+     *
+     * <p>Notes:</p>
+     * <ul>
+     *   <li>This method requires {@code DomainRange} instance rather than more generic
{@code NumberRange}
+     *       in order to ensure reciprocity: {@code A.compareTo(B) == -B.compareTo(A)}.</li>
+     *   <li>This ordering is appropriate for {@code DomainRange} because it is close
to the ordering
+     *       of their string representations, but is otherwise not provided for general {@code
Range}
+     *       objects because the ordering criterion would be arbitrary for them (what would
be the
+     *       best ordering of overlapping ranges?).</li>
+     * </ul>
+     */
+    private int compareTo(final DomainRange<?> range) {
+        int c = Double.compare(getMinDouble(), range.getMinDouble());
+        if (c == 0) {
+            boolean b = isMinIncluded();
+            if (b != range.isMinIncluded()) {
+                c = b ? -1 : +1;
+            } else {
+                c = Double.compare(getMaxDouble(), range.getMaxDouble());
+                if (c == 0) {
+                    b = isMaxIncluded();
+                    if (b != range.isMaxIncluded()) {
+                        c = b ? +1 : -1;
+                    }
+                }
+            }
+        }
+        return c;
+    }
+}

Propchange: sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/DomainRange.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/DomainRange.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java?rev=1469283&r1=1469282&r2=1469283&view=diff
==============================================================================
--- sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java
[UTF-8] (original)
+++ sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java
[UTF-8] Thu Apr 18 11:14:13 2013
@@ -544,6 +544,8 @@ final class PropertyAccessor {
      * @param  index The index of the property for which to get the information.
      * @return The information for the property at the given index,
      *         or {@code null} if the index is out of bounds.
+     *
+     * @see PropertyInformation
      */
     @SuppressWarnings({"unchecked","rawtypes"})
     final synchronized ExtendedElementInformation information(final int index) {

Modified: sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyInformation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyInformation.java?rev=1469283&r1=1469282&r2=1469283&view=diff
==============================================================================
--- sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyInformation.java
[UTF-8] (original)
+++ sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyInformation.java
[UTF-8] Thu Apr 18 11:14:13 2013
@@ -33,6 +33,7 @@ import org.apache.sis.measure.ValueRange
 import org.apache.sis.util.iso.Types;
 import org.apache.sis.util.Numbers;
 import org.apache.sis.util.collection.CheckedContainer;
+import org.apache.sis.util.logging.Logging;
 
 
 /**
@@ -44,7 +45,6 @@ import org.apache.sis.util.collection.Ch
  * @param <T> The value type, either the method return type if not a collection,
  *            or the type of elements in the collection otherwise.
  *
- *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3 (derived from geotk-3.05)
  * @version 0.3
@@ -97,6 +97,15 @@ final class PropertyInformation<T> exten
     private final byte maximumOccurs;
 
     /**
+     * The domain of valid values, or {@code null} if none. If non-null, then this is set
to an
+     * instance of {@link ValueRange} at construction time, then replaced by an instance
of
+     * {@link DomainRange} when first needed by the {@link #getDomainValue()} method.
+     *
+     * @see #getDomainValue()
+     */
+    private Object domainValue;
+
+    /**
      * Creates a new {@code PropertyInformation} instance from the annotations on the given
      * getter method.
      *
@@ -133,7 +142,7 @@ final class PropertyInformation<T> exten
         }
         this.minimumOccurs = minimumOccurs;
         this.maximumOccurs = maximumOccurs;
-        // TODO: store the range.
+        this.domainValue   = range;
     }
 
     /**
@@ -253,10 +262,31 @@ final class PropertyInformation<T> exten
 
     /**
      * Returns valid values that can be assigned to the extended element, or {@code null}
if none.
+     * In the particular case of SIS implementation, this method may return a subclass of
{@link NumberRange}.
      */
     @Override
+    @SuppressWarnings("unchecked")
     public InternationalString getDomainValue() {
-        return null; // TODO: A NumberRange subclass implementing InternationalString?
+        Object domain = domainValue;
+        if (domain != null) {
+            if (!(domain instanceof DomainRange)) {
+                try {
+                    domain = new DomainRange(elementType, (ValueRange) domain);
+                } catch (IllegalArgumentException e) {
+                    /*
+                     * May happen only if a ValueRange annotation is applied on the wrong
method.
+                     * The JUnit tests ensure that this never happen at least for the SIS
metadata
+                     * implementation. If this error happen anyway, the user probably doesn't
expect
+                     * to have an IllegalArgumentException while he didn't provided any argument.
+                     * Returning null as a fallback is compliant with the method contract.
+                     */
+                    Logging.unexpectedException(PropertyInformation.class, "getDomainValue",
e);
+                    domain = null;
+                }
+                domainValue = domain;
+            }
+        }
+        return (DomainRange) domain;
     }
 
     /**

Modified: sis/branches/JDK7/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyInformationTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyInformationTest.java?rev=1469283&r1=1469282&r2=1469283&view=diff
==============================================================================
--- sis/branches/JDK7/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyInformationTest.java
[UTF-8] (original)
+++ sis/branches/JDK7/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyInformationTest.java
[UTF-8] Thu Apr 18 11:14:13 2013
@@ -24,8 +24,12 @@ import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.metadata.citation.PresentationForm;
 import org.opengis.metadata.ExtendedElementInformation;
+import org.opengis.metadata.acquisition.EnvironmentalRecord;
+import org.apache.sis.metadata.iso.acquisition.DefaultEnvironmentalRecord;
 import org.apache.sis.metadata.iso.citation.HardCodedCitations;
 import org.apache.sis.util.collection.CheckedContainer;
+import org.apache.sis.measure.ValueRange;
+import org.apache.sis.measure.Range;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
@@ -58,6 +62,16 @@ public final strictfp class PropertyInfo
     }
 
     /**
+     * Asserts that the {@linkplain ExtendedElementInformation#getParentEntity() parent entity}
+     * of the given element is {@link Citation}.
+     */
+    private static void assertParentIsCitation(final ExtendedElementInformation information)
{
+        assertInstanceOf("Specific to SIS implementation.", Identifier.class, information);
+        assertEquals("ISO 19115",   ((Identifier) information).getAuthority().getTitle().toString());
+        assertEquals("CI_Citation", getSingleton(information.getParentEntity()));
+    }
+
+    /**
      * Tests the properties of {@link Citation#getTitle()}.
      * The element type is an {@link InternationalString} singleton, which is mandatory.
      *
@@ -73,19 +87,18 @@ public final strictfp class PropertyInfo
      * This is validation code to be shared with {@link PropertyAccessorTest#testInformation()}.
      */
     static void validateTitle(final ExtendedElementInformation information) {
-        assertInstanceOf("SIS-specific", Identifier.class, information);
-        assertEquals("ISO 19115",   ((Identifier) information).getAuthority().getTitle().toString());
-        assertEquals("CI_Citation", getSingleton(information.getParentEntity()));
-        assertEquals("title",       information.getName());
+        assertParentIsCitation(information);
+        assertEquals("title", information.getName());
         final InternationalString definition = information.getDefinition();
         assertEquals("Name by which the cited resource is known.", definition.toString(Locale.ENGLISH));
         // Test other locale here, if any.
 
-        assertInstanceOf("SIS-specific", CheckedContainer.class, information);
+        assertInstanceOf("Specific to SIS implementation.", CheckedContainer.class, information);
         assertEquals(InternationalString.class, ((CheckedContainer<?>) information).getElementType());
         assertEquals(Datatype.CHARACTER_STRING, information.getDataType());
         assertEquals(Obligation.MANDATORY, information.getObligation());
         assertEquals(Integer.valueOf(1), information.getMaximumOccurrence());
+        assertNull(information.getDomainValue());
     }
 
     /**
@@ -104,19 +117,39 @@ public final strictfp class PropertyInfo
      * This is validation code to be shared with {@link PropertyAccessorTest#testInformation()}.
      */
     static void validatePresentationForm(final ExtendedElementInformation information) {
-        assertInstanceOf("SIS-specific", Identifier.class, information);
-        assertEquals("ISO 19115",        ((Identifier) information).getAuthority().getTitle().toString());
-        assertEquals("CI_Citation",      getSingleton(information.getParentEntity()));
+        assertParentIsCitation(information);
         assertEquals("presentationForm", information.getName());
         final InternationalString definition = information.getDefinition();
         assertEquals("Mode in which the resource is represented.", definition.toString(Locale.ENGLISH));
         // Test other locale here, if any.
 
-        assertInstanceOf("SIS-specific", CheckedContainer.class, information);
+        assertInstanceOf("Specific to SIS implementation.", CheckedContainer.class, information);
         assertEquals(PresentationForm.class, ((CheckedContainer<?>) information).getElementType());
         assertEquals(Datatype.CODE_LIST, information.getDataType());
         assertEquals(Obligation.OPTIONAL, information.getObligation());
         assertEquals(Integer.valueOf(Integer.MAX_VALUE), information.getMaximumOccurrence());
+        assertNull(information.getDomainValue());
+    }
+
+    /**
+     * Tests {@link PropertyInformation#getDomainValue()} with a non-null range.
+     *
+     * @throws NoSuchMethodException Should never happen.
+     */
+    @Test
+    public void testGetDomainValue()  throws NoSuchMethodException {
+        final ExtendedElementInformation information = new PropertyInformation<>(HardCodedCitations.ISO_19115,
+                "maxRelativeHumidity", EnvironmentalRecord.class.getMethod("getMaxRelativeHumidity"),
Double.class,
+                DefaultEnvironmentalRecord.class.getMethod("getMaxRelativeHumidity").getAnnotation(ValueRange.class));
+
+        final InternationalString domainValue = information.getDomainValue();
+        assertNotNull(domainValue);
+        assertEquals("[0.0 … 100.0]", domainValue.toString());
+        assertEquals("[0 … 100]", domainValue.toString(Locale.ENGLISH));
+        assertEquals("[0 … 100]", domainValue.toString(Locale.FRENCH));
+        assertInstanceOf("Specific to SIS implementation.", Range.class, domainValue);
+        assertEquals("getMinValue()", Double.valueOf(  0), ((Range) domainValue).getMinValue());
+        assertEquals("getMaxValue()", Double.valueOf(100), ((Range) domainValue).getMaxValue());
     }
 
     /**



Mime
View raw message