sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1831086 - in /sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis: filter/ internal/feature/
Date Mon, 07 May 2018 10:43:29 GMT
Author: desruisseaux
Date: Mon May  7 10:43:29 2018
New Revision: 1831086

URL: http://svn.apache.org/viewvc?rev=1831086&view=rev
Log:
Complete revision of filter package, except DefaultFilterFactory which will need a severe
revision of its API (but this task need to be done in GeoAPI first).

Modified:
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/AbstractComparisonOperator.java
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultFilterFactory.java
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultPropertyIsEqualTo.java
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultPropertyName.java
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/package-info.java
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureExpression.java

Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/AbstractComparisonOperator.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/AbstractComparisonOperator.java?rev=1831086&r1=1831085&r2=1831086&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/AbstractComparisonOperator.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/AbstractComparisonOperator.java
[UTF-8] Mon May  7 10:43:29 2018
@@ -67,9 +67,10 @@ abstract class AbstractComparisonOperato
 
     /**
      * Creates a new binary comparison operator.
+     * It is caller responsibility to ensure that no argument is null.
      */
     AbstractComparisonOperator(final Expression expression1, final Expression expression2,
-                                     final boolean matchCase, final MatchAction matchAction)
+                               final boolean matchCase, final MatchAction matchAction)
     {
         this.expression1 = expression1;
         this.expression2 = expression2;
@@ -78,6 +79,12 @@ abstract class AbstractComparisonOperato
     }
 
     /**
+     * Returns the mathematical symbol for this comparison operator.
+     * The symbol should be one of the following: {@literal < > ≤ ≥ = ≠}.
+     */
+    protected abstract char symbol();
+
+    /**
      * Returns the first of the two expressions to be compared by this operator.
      */
     @Override
@@ -115,4 +122,41 @@ abstract class AbstractComparisonOperato
     public final MatchAction getMatchAction() {
         return matchAction;
     }
+
+    /**
+     * Returns a hash code value for this comparison operator.
+     */
+    @Override
+    public final int hashCode() {
+        int hash = (31 * expression1.hashCode() + expression2.hashCode()) * 37 + matchAction.hashCode();
+        if (matchCase) hash = ~hash;
+        return hash ^ symbol();             // Use the symbol as a way to differentiate the
subclasses.
+    }
+
+    /**
+     * Compares this operator with the given object for equality.
+     */
+    @Override
+    public final boolean equals(final Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj != null && obj.getClass() == getClass()) {
+            final AbstractComparisonOperator other = (AbstractComparisonOperator) obj;
+            return matchCase   ==     other.matchCase &&
+                   expression1.equals(other.expression1) &&
+                   expression2.equals(other.expression2) &&
+                   matchAction.equals(other.matchAction);
+        }
+        return false;
+    }
+
+    /**
+     * Returns a string representation of this comparison operator.
+     */
+    @Override
+    public final String toString() {
+        return new StringBuilder(30).append(expression1).append(' ').append(symbol()).append('
')
+                                    .append(expression2).toString();
+    }
 }

Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultFilterFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultFilterFactory.java?rev=1831086&r1=1831085&r2=1831086&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultFilterFactory.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultFilterFactory.java
[UTF-8] Mon May  7 10:43:29 2018
@@ -18,76 +18,14 @@ package org.apache.sis.filter;
 
 import java.util.List;
 import java.util.Set;
-import org.opengis.filter.And;
-import org.opengis.filter.Filter;
-import org.opengis.filter.FilterFactory2;
-import org.opengis.filter.Id;
-import org.opengis.filter.MatchAction;
-import org.opengis.filter.Not;
-import org.opengis.filter.Or;
-import org.opengis.filter.PropertyIsBetween;
-import org.opengis.filter.PropertyIsEqualTo;
-import org.opengis.filter.PropertyIsGreaterThan;
-import org.opengis.filter.PropertyIsGreaterThanOrEqualTo;
-import org.opengis.filter.PropertyIsLessThan;
-import org.opengis.filter.PropertyIsLessThanOrEqualTo;
-import org.opengis.filter.PropertyIsLike;
-import org.opengis.filter.PropertyIsNil;
-import org.opengis.filter.PropertyIsNotEqualTo;
-import org.opengis.filter.PropertyIsNull;
-import org.opengis.filter.capability.ArithmeticOperators;
-import org.opengis.filter.capability.ComparisonOperators;
-import org.opengis.filter.capability.FilterCapabilities;
-import org.opengis.filter.capability.FunctionName;
-import org.opengis.filter.capability.Functions;
-import org.opengis.filter.capability.GeometryOperand;
-import org.opengis.filter.capability.IdCapabilities;
-import org.opengis.filter.capability.Operator;
-import org.opengis.filter.capability.ScalarCapabilities;
-import org.opengis.filter.capability.SpatialCapabilities;
-import org.opengis.filter.capability.SpatialOperator;
-import org.opengis.filter.capability.SpatialOperators;
-import org.opengis.filter.capability.TemporalCapabilities;
-import org.opengis.filter.capability.TemporalOperand;
-import org.opengis.filter.capability.TemporalOperators;
-import org.opengis.filter.expression.Add;
-import org.opengis.filter.expression.Divide;
-import org.opengis.filter.expression.Expression;
-import org.opengis.filter.expression.Function;
-import org.opengis.filter.expression.Literal;
-import org.opengis.filter.expression.Multiply;
-import org.opengis.filter.expression.PropertyName;
-import org.opengis.filter.expression.Subtract;
-import org.opengis.filter.identity.FeatureId;
-import org.opengis.filter.identity.GmlObjectId;
-import org.opengis.filter.identity.Identifier;
-import org.opengis.filter.sort.SortBy;
-import org.opengis.filter.sort.SortOrder;
-import org.opengis.filter.spatial.BBOX;
-import org.opengis.filter.spatial.Beyond;
-import org.opengis.filter.spatial.Contains;
-import org.opengis.filter.spatial.Crosses;
-import org.opengis.filter.spatial.DWithin;
-import org.opengis.filter.spatial.Disjoint;
-import org.opengis.filter.spatial.Equals;
-import org.opengis.filter.spatial.Intersects;
-import org.opengis.filter.spatial.Overlaps;
-import org.opengis.filter.spatial.Touches;
-import org.opengis.filter.spatial.Within;
-import org.opengis.filter.temporal.After;
-import org.opengis.filter.temporal.AnyInteracts;
-import org.opengis.filter.temporal.Before;
-import org.opengis.filter.temporal.Begins;
-import org.opengis.filter.temporal.BegunBy;
-import org.opengis.filter.temporal.During;
-import org.opengis.filter.temporal.EndedBy;
-import org.opengis.filter.temporal.Ends;
-import org.opengis.filter.temporal.Meets;
-import org.opengis.filter.temporal.MetBy;
-import org.opengis.filter.temporal.OverlappedBy;
-import org.opengis.filter.temporal.TContains;
-import org.opengis.filter.temporal.TEquals;
-import org.opengis.filter.temporal.TOverlaps;
+import org.opengis.filter.*;
+import org.opengis.filter.capability.*;
+import org.opengis.filter.expression.*;
+import org.opengis.filter.identity.*;
+import org.opengis.filter.sort.*;
+import org.opengis.filter.spatial.*;
+import org.opengis.filter.temporal.*;
+import org.opengis.filter.capability.SpatialOperator;       // Resolve ambiguity with org.opengis.filter.spatial.
 import org.opengis.geometry.Envelope;
 import org.opengis.geometry.Geometry;
 import org.opengis.util.GenericName;
@@ -95,7 +33,12 @@ import org.apache.sis.util.ArgumentCheck
 
 
 /**
- * Default implementation of GeoAPI filter factory.
+ * Default implementation of GeoAPI filter factory for creation of {@link Filter} and {@link
Expression} instances.
+ *
+ * <div class="warning"><b>Warning:</b> most methods in this class are
still unimplemented.
+ * This is a very early draft subject to changes.
+ * <b>TODO: the API of this class needs severe revision! DO NOT RELEASE.</b>
+ * See <a href="https://github.com/opengeospatial/geoapi/issues/32">GeoAPI issue #32</a>.</div>
  *
  * @author  Johann Sorel (Geomatys)
  * @version 1.0
@@ -103,13 +46,28 @@ import org.apache.sis.util.ArgumentCheck
  * @module
  */
 public class DefaultFilterFactory implements FilterFactory2 {
+    /**
+     * Creates a new factory.
+     */
     public DefaultFilterFactory() {
     }
 
     // SPATIAL FILTERS /////////////////////////////////////////////////////////
 
     /**
-     * {@inheritDoc }
+     * Creates an operator that evaluates to {@code true} when the bounding box of the feature's
geometry overlaps
+     * the given bounding box.
+     *
+     * @param  propertyName  name of geometry property (for a {@link PropertyName} to access
a feature's Geometry)
+     * @param  minx          minimum "x" value (for a literal envelope).
+     * @param  miny          minimum "y" value (for a literal envelope).
+     * @param  maxx          maximum "x" value (for a literal envelope).
+     * @param  maxy          maximum "y" value (for a literal envelope).
+     * @param  srs           identifier of the Coordinate Reference System to use for a literal
envelope.
+     * @return operator that evaluates to {@code true} when the bounding box of the feature's
geometry overlaps
+     *         the bounding box provided in arguments to this method.
+     *
+     * @see #bbox(Expression, Envelope)
      */
     @Override
     public BBOX bbox(final String propertyName, final double minx,
@@ -138,7 +96,15 @@ public class DefaultFilterFactory implem
     }
 
     /**
-     * {@inheritDoc }
+     * Creates an operator that checks if all of a feature's geometry is more distant than
the given distance
+     * from the given geometry.
+     *
+     * @param  propertyName  name of geometry property (for a {@link PropertyName} to access
a feature's Geometry).
+     * @param  geometry      the geometry from which to evaluate the distance.
+     * @param  distance      minimal distance for evaluating the expression as {@code true}.
+     * @param  units         units of the given {@code distance}.
+     * @return operator that evaluates to {@code true} when all of a feature's geometry is
more distant than
+     *         the given distance from the given geometry.
      */
     @Override
     public Beyond beyond(final String propertyName, final Geometry geometry,
@@ -404,6 +370,7 @@ public class DefaultFilterFactory implem
      */
     @Override
     public PropertyName property(final String name) {
+        ArgumentChecks.ensureNonNull("name", name);
         return new DefaultPropertyName(name);
     }
 
@@ -428,9 +395,13 @@ public class DefaultFilterFactory implem
      * {@inheritDoc }
      */
     @Override
-    public PropertyIsEqualTo equal(final Expression expr1,
-            final Expression expr2, final boolean matchCase, MatchAction matchAction) {
-        return new DefaultPropertyIsEqualTo(expr1, expr2, matchCase, matchAction);
+    public PropertyIsEqualTo equal(final Expression expression1, final Expression expression2,
+                                   final boolean matchCase, final MatchAction matchAction)
+    {
+        ArgumentChecks.ensureNonNull("expression1", expression1);
+        ArgumentChecks.ensureNonNull("expression2", expression2);
+        ArgumentChecks.ensureNonNull("matchAction", matchAction);
+        return new DefaultPropertyIsEqualTo(expression1, expression2, matchCase, matchAction);
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultPropertyIsEqualTo.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultPropertyIsEqualTo.java?rev=1831086&r1=1831085&r2=1831086&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultPropertyIsEqualTo.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultPropertyIsEqualTo.java
[UTF-8] Mon May  7 10:43:29 2018
@@ -17,38 +17,76 @@
 package org.apache.sis.filter;
 
 import java.util.Objects;
+import org.apache.sis.util.Numbers;
 import org.opengis.filter.FilterVisitor;
 import org.opengis.filter.MatchAction;
 import org.opengis.filter.PropertyIsEqualTo;
 import org.opengis.filter.expression.Expression;
 
+
 /**
- * Immutable PropertyIsEqualTo filter.
+ * Filter operator that compares that its two sub-expressions are equal to each other.
  *
- * @author Johann Sorel (Geomatys)
+ * @author  Johann Sorel (Geomatys)
  * @version 1.0
  * @since   1.0
  * @module
  */
 final class DefaultPropertyIsEqualTo extends AbstractComparisonOperator implements PropertyIsEqualTo
{
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -5549267988142039640L;
+
+    /**
+     * Creates a new comparison operator.
+     * It is caller responsibility to ensure that no argument is null.
+     */
+    DefaultPropertyIsEqualTo(Expression expression1, Expression expression2, boolean matchCase,
MatchAction matchAction) {
+        super(expression1, expression2, matchCase, matchAction);
+    }
 
-    DefaultPropertyIsEqualTo(Expression exp1, Expression exp2, boolean matchCase, MatchAction
matchAction) {
-        super(exp1, exp2, matchCase, matchAction);
+    /**
+     * Returns the mathematical symbol for this comparison operator.
+     */
+    @Override
+    protected char symbol() {
+        return '=';
     }
 
     /**
-     * {@inheritDoc }
+     * Determines if the test represented by this filter passed.
+     *
+     * @todo Use locale-sensitive {@link java.text.Collator} for string comparisons.
      */
     @Override
     public boolean evaluate(Object object) {
         final Object r1 = expression1.evaluate(object);
         final Object r2 = expression2.evaluate(object);
-        //TODO be more relax on equality testing, for example Date,TimeStamp,Instant or numerics
-        return Objects.equals(r1, r2);
+        if (Objects.equals(r1, r2)) {
+            return true;
+        } else if (r1 instanceof Number && r2 instanceof Number) {
+            @SuppressWarnings("unchecked") final Class<? extends Number> c1 = (Class<?
extends Number>) r1.getClass();
+            @SuppressWarnings("unchecked") final Class<? extends Number> c2 = (Class<?
extends Number>) r2.getClass();
+            if (c1 != c2) {
+                final Class<? extends Number> c = Numbers.widestClass(c1, c2);
+                return Numbers.cast((Number) r1, c).equals(
+                       Numbers.cast((Number) r2, c));
+            }
+        } else if (r1 instanceof CharSequence && r2 instanceof CharSequence) {
+            final String s1 = r1.toString();
+            final String s2 = r2.toString();
+            if (!matchCase) {
+                return s1.equalsIgnoreCase(s2);
+            } else if (r1 != s1 || r2 != s2) {
+                return s1.equals(s2);
+            }
+        }
+        return false;
     }
 
     /**
-     * {@inheritDoc }
+     * Accepts a visitor.
      */
     @Override
     public Object accept(FilterVisitor visitor, Object extraData) {

Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultPropertyName.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultPropertyName.java?rev=1831086&r1=1831085&r2=1831086&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultPropertyName.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultPropertyName.java
[UTF-8] Mon May  7 10:43:29 2018
@@ -17,11 +17,12 @@
 package org.apache.sis.filter;
 
 import java.util.Map;
-import java.util.Objects;
 import java.io.Serializable;
-import org.apache.sis.util.ArgumentChecks;
-import org.apache.sis.util.collection.BackingStoreException;
-import org.apache.sis.feature.builder.FeatureTypeBuilder;
+import org.apache.sis.util.Classes;
+import org.apache.sis.util.resources.Errors;
+import org.apache.sis.feature.DefaultAssociationRole;
+
+import static java.util.Collections.singletonMap;
 
 // Branch-dependent imports
 import org.opengis.feature.Feature;
@@ -35,9 +36,9 @@ import org.opengis.filter.expression.Pro
 
 
 /**
- * Immutable property name expression.
- * A property name does not store any value, it acts as an indirection to a
- * property value of the evaluated feature.
+ * Expression whose value is computed by retrieving the value indicated by the provided name.
+ * A property name does not store any value; it acts as an indirection to a property value
of
+ * the evaluated feature.
  *
  * @author  Johann Sorel (Geomatys)
  * @version 1.0
@@ -50,56 +51,72 @@ final class DefaultPropertyName extends
      */
     private static final long serialVersionUID = -8474562134021521300L;
 
-    private final String property;
+    /**
+     * Name of the property from which to retrieve the value.
+     */
+    private final String name;
 
     /**
+     * Creates a new expression retrieving values from a property of the given name.
+     * It is caller responsibility to ensure that the given name is non-null.
      *
-     * @param property attribute name
+     * @param  name  name of the property (usually a feature attribute).
      */
-    DefaultPropertyName(final String property) {
-        ArgumentChecks.ensureNonNull("property", property);
-        this.property = property;
+    DefaultPropertyName(final String name) {
+        this.name = name;
     }
 
     /**
-     * {@inheritDoc }
+     * Returns the name of the property whose value will be returned by the {@link #evaluate
evaluate} method.
      */
     @Override
     public String getPropertyName() {
-        return property;
+        return name;
     }
 
     /**
-     * {@inheritDoc }
+     * Returns the value of the property of the given name.
+     * The {@code candidate} object can be any of the following type:
+     *
+     * <ul>
+     *   <li>A {@link Feature}, in which case {@link Feature#getPropertyValue(String)}
will be invoked.</li>
+     *   <li>A {@link Map}, in which case {@link Map#get(Object)} will be invoked.</li>
+     * </ul>
+     *
+     * If no value is found for the given property, then this method returns {@code null}.
      */
     @Override
     public Object evaluate(final Object candidate) {
         if (candidate instanceof Feature) {
             try {
-                return ((Feature) candidate).getPropertyValue(property);
+                return ((Feature) candidate).getPropertyValue(name);
             } catch (PropertyNotFoundException ex) {
-                return null;
+                // Null will be returned below.
+                // TODO: report a warning somewhere?
             }
         } else if (candidate instanceof Map<?,?>) {
-            return ((Map<?,?>) candidate).get(property);
+            return ((Map<?,?>) candidate).get(name);
         }
         return null;
     }
 
     /**
-     * {@inheritDoc }
+     * Returns the expected type of values produced by this expression when a feature of
the given type is evaluated.
+     *
+     * @throws IllegalArgumentException if this method can not determine the property type
for the given feature type.
      */
     @Override
-    public PropertyType expectedType(FeatureType type) {
-        PropertyType propertyType = type.getProperty(property);
+    public PropertyType expectedType(final FeatureType type) {
+        PropertyType propertyType = type.getProperty(name);         // May throw IllegalArgumentException.
         while (propertyType instanceof Operation) {
-            IdentifiedType it = ((Operation) propertyType).getResult();
-            if (it instanceof FeatureType) {
-                propertyType = new FeatureTypeBuilder().addAssociation(type).setName(property).build();
-            } else if (it instanceof PropertyType) {
+            final IdentifiedType it = ((Operation) propertyType).getResult();
+            if (it instanceof PropertyType) {
                 propertyType = (PropertyType) it;
+            } else if (it instanceof FeatureType) {
+                propertyType = new DefaultAssociationRole(singletonMap(DefaultAssociationRole.NAME_KEY,
name), type, 1, 1);
             } else {
-                throw new BackingStoreException("Unexpected operation result type "+it);
+                throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalPropertyValueClass_3,
+                            name, PropertyType.class, Classes.getStandardType(Classes.getClass(it))));
             }
         }
         return propertyType;
@@ -114,26 +131,26 @@ final class DefaultPropertyName extends
     }
 
     /**
-     * Returns a hash-code value for this property.
+     * Returns a hash-code value for this expression.
      */
     @Override
     public boolean equals(final Object obj) {
-        return (obj instanceof DefaultPropertyName) && property.equals(((DefaultPropertyName)
obj).property);
+        return (obj instanceof DefaultPropertyName) && name.equals(((DefaultPropertyName)
obj).name);
     }
 
     /**
-     * Returns a hash-code value for this property.
+     * Returns a hash-code value for this expression.
      */
     @Override
     public int hashCode() {
-        return Objects.hashCode(property) ^ (int) serialVersionUID;
+        return name.hashCode() ^ (int) serialVersionUID;
     }
 
     /**
-     * Returns a string representation of this property.
+     * Returns a string representation of this expression.
      */
     @Override
     public String toString() {
-        return '{' + property + '}';
+        return '{' + name + '}';
     }
 }

Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/package-info.java?rev=1831086&r1=1831085&r2=1831086&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/package-info.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/package-info.java
[UTF-8] Mon May  7 10:43:29 2018
@@ -22,7 +22,10 @@
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
  * @version 1.0
- * @since   1.0
+ *
+ * @see <a href="http://docs.opengeospatial.org/is/09-026r2/09-026r2.html">OGC® Filter
Encoding 2.0 Encoding Standard</a>
+ *
+ * @since 1.0
  * @module
  */
 package org.apache.sis.filter;

Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureExpression.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureExpression.java?rev=1831086&r1=1831085&r2=1831086&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureExpression.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureExpression.java
[UTF-8] Mon May  7 10:43:29 2018
@@ -40,6 +40,7 @@ public interface FeatureExpression {
      *
      * @param  type the type of features on which to apply this expression.
      * @return expected expression result type.
+     * @throws IllegalArgumentException if this method can not determine the property type
for the given feature type.
      */
     PropertyType expectedType(FeatureType type);
 }



Mime
View raw message