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 e553027 When creating the FeatureType for a query or an expression, provide the
FeatureTypeBuilder where the properties can be appended directly.
e553027 is described below
commit e553027bb7b272d446df6bee508e14cfa730cedf
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Tue Aug 20 18:56:17 2019 +0200
When creating the FeatureType for a query or an expression, provide the FeatureTypeBuilder
where the properties can be appended directly.
---
.../apache/sis/feature/DefaultAttributeType.java | 2 +
.../main/java/org/apache/sis/feature/Features.java | 35 +++++++++++++
.../org/apache/sis/filter/ArithmeticFunction.java | 25 ++++++++--
.../java/org/apache/sis/filter/LeafExpression.java | 51 ++++++++++---------
.../java/org/apache/sis/filter/NamedFunction.java | 43 +++++++++++++---
.../main/java/org/apache/sis/filter/ST_Buffer.java | 26 ++++------
.../java/org/apache/sis/filter/ST_Centroid.java | 26 ++++------
.../java/org/apache/sis/filter/ST_Transform.java | 24 +++------
.../sis/internal/feature/FeatureExpression.java | 57 +++++++++++++---------
.../apache/sis/internal/feature/Geometries.java | 14 ++++++
.../org/apache/sis/internal/feature/Resources.java | 5 ++
.../sis/internal/feature/Resources.properties | 1 +
.../sis/internal/feature/Resources_fr.properties | 1 +
.../sis/internal/storage/query/SimpleQuery.java | 28 +++--------
14 files changed, 211 insertions(+), 127 deletions(-)
diff --git a/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAttributeType.java
b/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAttributeType.java
index cdb8258..535be02 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAttributeType.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAttributeType.java
@@ -235,6 +235,8 @@ public class DefaultAttributeType<V> extends FieldType implements
AttributeType<
* Returns the type of attribute values.
*
* @return the type of attribute values.
+ *
+ * @see Features#getValueClass(PropertyType)
*/
@Override
public final Class<V> getValueClass() {
diff --git a/core/sis-feature/src/main/java/org/apache/sis/feature/Features.java b/core/sis-feature/src/main/java/org/apache/sis/feature/Features.java
index 4852a3f..7ff600f 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/feature/Features.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/feature/Features.java
@@ -137,6 +137,41 @@ public final class Features extends Static {
}
/**
+ * Returns the type of values provided by the given property. For {@linkplain AttributeType
attributes}
+ * (which is the most common case), the value type is given by {@link AttributeType#getValueClass()}.
+ * For {@linkplain FeatureAssociationRole feature associations}, the value type is {@link
Feature}.
+ * For {@linkplain Operation operations}, the value type is determined recursively from
the
+ * {@linkplain Operation#getResult() operation result}.
+ * If the value type can not be determined, then this method returns {@code null}.
+ *
+ * @param type the property for which to get the type of values, or {@code null}.
+ * @return the type of values provided by the given property, or {@code null} if unknown.
+ *
+ * @see AttributeType#getValueClass()
+ *
+ * @since 1.0
+ */
+ public static Class<?> getValueClass(PropertyType type) {
+ while (type instanceof Operation) {
+ final IdentifiedType result = ((Operation) type).getResult();
+ if (result != type && result instanceof PropertyType) {
+ type = (PropertyType) result;
+ } else if (result instanceof FeatureType) {
+ return Feature.class;
+ } else {
+ break;
+ }
+ }
+ if (type instanceof AttributeType<?>) {
+ return ((AttributeType<?>) type).getValueClass();
+ } else if (type instanceof FeatureAssociationRole) {
+ return Feature.class;
+ } else {
+ return null;
+ }
+ }
+
+ /**
* Returns the name of the type of values that the given property can take.
* The type of value can be a {@link Class}, a {@link org.opengis.feature.FeatureType}
* or another {@code PropertyType} depending on given argument:
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/ArithmeticFunction.java
b/core/sis-feature/src/main/java/org/apache/sis/filter/ArithmeticFunction.java
index fdda3dc..3a5705b 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/ArithmeticFunction.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/ArithmeticFunction.java
@@ -20,6 +20,8 @@ import java.math.BigDecimal;
import java.math.BigInteger;
import org.apache.sis.util.Numbers;
import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.feature.builder.FeatureTypeBuilder;
+import org.apache.sis.feature.builder.PropertyTypeBuilder;
import org.apache.sis.internal.feature.FeatureExpression;
import org.apache.sis.internal.util.Numerics;
import org.apache.sis.math.Fraction;
@@ -27,7 +29,6 @@ import org.apache.sis.math.Fraction;
// Branch-dependent imports
import org.opengis.feature.AttributeType;
import org.opengis.feature.FeatureType;
-import org.opengis.feature.PropertyType;
import org.opengis.filter.expression.BinaryExpression;
import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.ExpressionVisitor;
@@ -68,6 +69,20 @@ abstract class ArithmeticFunction extends BinaryFunction implements BinaryExpres
}
/**
+ * Returns the type of results computed by this arithmetic function.
+ */
+ protected abstract AttributeType<Number> expectedType();
+
+ /**
+ * Provides the type of results computed by this expression. That type depends only
+ * on the {@code ArithmeticFunction} subclass and is given by {@link #expectedType()}.
+ */
+ @Override
+ public final PropertyTypeBuilder expectedType(FeatureType ignored, FeatureTypeBuilder
addTo) {
+ return addTo.addProperty(expectedType());
+ }
+
+ /**
* Evaluates this expression based on the content of the given object. This method delegates
to
* {@link #applyAsDouble(double, double)}, {@link #applyAsLong(long, long)} or similar
methods
* depending on the value types.
@@ -123,7 +138,7 @@ abstract class ArithmeticFunction extends BinaryFunction implements BinaryExpres
/** Description of results of the {@value #NAME} expression. */
private static final AttributeType<Number> TYPE = createNumericType(NAME);
- @Override public PropertyType expectedType(FeatureType type) {return TYPE;}
+ @Override protected AttributeType<Number> expectedType() {return TYPE;}
/** Creates a new expression for the {@value #NAME} operation. */
Add(Expression expression1, Expression expression2) {
@@ -157,7 +172,7 @@ abstract class ArithmeticFunction extends BinaryFunction implements BinaryExpres
/** Description of results of the {@value #NAME} expression. */
private static final AttributeType<Number> TYPE = createNumericType(NAME);
- @Override public PropertyType expectedType(FeatureType type) {return TYPE;}
+ @Override protected AttributeType<Number> expectedType() {return TYPE;}
/** Creates a new expression for the {@value #NAME} operation. */
Subtract(Expression expression1, Expression expression2) {
@@ -191,7 +206,7 @@ abstract class ArithmeticFunction extends BinaryFunction implements BinaryExpres
/** Description of results of the {@value #NAME} expression. */
private static final AttributeType<Number> TYPE = createNumericType(NAME);
- @Override public PropertyType expectedType(FeatureType type) {return TYPE;}
+ @Override protected AttributeType<Number> expectedType() {return TYPE;}
/** Creates a new expression for the {@value #NAME} operation. */
Multiply(Expression expression1, Expression expression2) {
@@ -225,7 +240,7 @@ abstract class ArithmeticFunction extends BinaryFunction implements BinaryExpres
/** Description of results of the {@value #NAME} expression. */
private static final AttributeType<Number> TYPE = createNumericType(NAME);
- @Override public PropertyType expectedType(FeatureType type) {return TYPE;}
+ @Override protected AttributeType<Number> expectedType() {return TYPE;}
/** Creates a new expression for the {@value #NAME} operation. */
Divide(Expression expression1, Expression expression2) {
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/LeafExpression.java b/core/sis-feature/src/main/java/org/apache/sis/filter/LeafExpression.java
index 7b90b5a..872ced0 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/LeafExpression.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/LeafExpression.java
@@ -26,8 +26,8 @@ import org.apache.sis.util.ObjectConverters;
import org.apache.sis.util.UnconvertibleObjectException;
import org.apache.sis.util.collection.WeakValueHashMap;
import org.apache.sis.internal.feature.FeatureExpression;
-import org.apache.sis.feature.DefaultAssociationRole;
-import org.apache.sis.util.resources.Errors;
+import org.apache.sis.feature.builder.FeatureTypeBuilder;
+import org.apache.sis.feature.builder.PropertyTypeBuilder;
// Branch-dependent imports
import org.opengis.feature.Feature;
@@ -130,7 +130,7 @@ abstract class LeafExpression extends Node implements Expression, FeatureExpress
* <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}.
+ * If no value is found for the given feature, then this method returns {@code null}.
*/
@Override
public Object evaluate(final Object candidate) {
@@ -146,25 +146,27 @@ abstract class LeafExpression extends Node implements Expression, FeatureExpress
}
/**
- * Returns the expected type of values produced by this expression when a feature
of the given type is evaluated.
+ * Provides the expected type of values produced by this expression when a feature
of the given type is evaluated.
*
+ * @param valueType the type of features to be evaluated by the given expression.
+ * @param addTo where to add the type of properties evaluated by the given
expression.
+ * @return builder of the added property, or {@code null} if this method can not
add a property.
* @throws IllegalArgumentException if this method can not determine the property
type for the given feature type.
*/
@Override
- public PropertyType expectedType(final FeatureType type) {
- PropertyType propertyType = type.getProperty(name); // May throw IllegalArgumentException.
- while (propertyType instanceof Operation) {
- final IdentifiedType it = ((Operation) propertyType).getResult();
- if (it instanceof PropertyType) {
- propertyType = (PropertyType) it;
- } else if (it instanceof FeatureType) {
- return new DefaultAssociationRole(Collections.singletonMap(DefaultAssociationRole.NAME_KEY,
name), type, 1, 1);
+ public PropertyTypeBuilder expectedType(final FeatureType valueType, final FeatureTypeBuilder
addTo) {
+ PropertyType type = valueType.getProperty(name); // May throw IllegalArgumentException.
+ while (type instanceof Operation) {
+ final IdentifiedType result = ((Operation) type).getResult();
+ if (result != type && result instanceof PropertyType) {
+ type = (PropertyType) result;
+ } else if (result instanceof FeatureType) {
+ return addTo.addAssociation((FeatureType) result).setName(name);
} else {
- throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalPropertyValueClass_3,
- name, PropertyType.class, Classes.getStandardType(Classes.getClass(it))));
+ return null;
}
}
- return propertyType;
+ return addTo.addProperty(type);
}
/** Implementation of the visitor pattern. */
@@ -214,21 +216,24 @@ abstract class LeafExpression extends Node implements Expression, FeatureExpress
}
/**
- * Returns the type of values returned by {@link #evaluate(Object)},
- * wrapped in an {@code AttributeType} named "Literal".
+ * Provides the type of values returned by {@link #evaluate(Object)}
+ * wrapped in an {@link AttributeType} named "Literal".
+ *
+ * @param addTo where to add the type of properties evaluated by the given expression.
+ * @return builder of the added property.
*/
@Override
- public AttributeType<?> expectedType(FeatureType ignored) {
+ public PropertyTypeBuilder expectedType(FeatureType ignored, final FeatureTypeBuilder
addTo) {
final Class<?> valueType = value.getClass();
- AttributeType<?> type = TYPES.get(valueType);
- if (type == null) {
+ AttributeType<?> propertyType = TYPES.get(valueType);
+ if (propertyType == null) {
final Class<?> standardType = Classes.getStandardType(valueType);
- type = TYPES.computeIfAbsent(standardType, Literal::newType);
+ propertyType = TYPES.computeIfAbsent(standardType, Literal::newType);
if (valueType != standardType) {
- TYPES.put(valueType, type);
+ TYPES.put(valueType, propertyType);
}
}
- return type;
+ return addTo.addProperty(propertyType);
}
/**
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/NamedFunction.java b/core/sis-feature/src/main/java/org/apache/sis/filter/NamedFunction.java
index c41923e..b02aeae 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/NamedFunction.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/NamedFunction.java
@@ -19,7 +19,6 @@ package org.apache.sis.filter;
import java.util.List;
import java.util.Collection;
import org.opengis.feature.FeatureType;
-import org.opengis.feature.PropertyType;
import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.ExpressionVisitor;
import org.opengis.filter.expression.Function;
@@ -27,8 +26,13 @@ import org.opengis.filter.expression.Literal;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.ObjectConverters;
import org.apache.sis.util.UnconvertibleObjectException;
-import org.apache.sis.internal.feature.FeatureExpression;
import org.apache.sis.internal.util.UnmodifiableArrayList;
+import org.apache.sis.internal.feature.Resources;
+import org.apache.sis.internal.feature.Geometries;
+import org.apache.sis.internal.feature.FeatureExpression;
+import org.apache.sis.feature.builder.FeatureTypeBuilder;
+import org.apache.sis.feature.builder.PropertyTypeBuilder;
+import org.apache.sis.feature.builder.AttributeTypeBuilder;
/**
@@ -150,20 +154,22 @@ abstract class NamedFunction extends Node implements Function {
}
/**
- * Returns the type of results computed by the parameters at given index.
- * This method applies heuristic rules documented in {@link FeatureExpression}.
+ * Copies into the given builder the property type evaluated by the expression at the
specified index.
+ * The property type is determined by the heuristic rules documented in {@link FeatureExpression}.
+ * This method returns the the property type builder for allowing caller to modify the
property.
*
* @param parameter index of the expression for which to get the result type.
* @param valueType the type of features to be evaluated by the given expression.
- * @return expected type resulting from expression evaluation (never null).
+ * @param addTo where to add the type of properties evaluated by the specified
expression.
+ * @return builder of type resulting from expression evaluation (never null).
* @throws IllegalArgumentException if this method can operate only on some feature types
* and the given type is not one of them.
* @throws InvalidExpressionException if this method can not determine the result type
of the expression
* at given index. It may be because that expression is backed by an unsupported
implementation.
*/
- final PropertyType expectedType(final int parameter, final FeatureType valueType) {
+ final PropertyTypeBuilder copyType(final int parameter, final FeatureType valueType,
final FeatureTypeBuilder addTo) {
final Expression expression = parameters.get(parameter);
- final PropertyType pt = FeatureExpression.expectedType(expression, valueType);
+ final PropertyTypeBuilder pt = FeatureExpression.expectedType(expression, valueType,
addTo);
if (pt == null) {
throw new InvalidExpressionException(expression, parameter);
}
@@ -171,6 +177,29 @@ abstract class NamedFunction extends Node implements Function {
}
/**
+ * Copies into the given builder the property type evaluated by the first expression.
+ * That property must be an attribute storing geometric object, otherwise an
+ * {@link IllegalArgumentException} will be thrown.
+ *
+ * @param valueType the type of features to be evaluated by the given expression.
+ * @param addTo where to add the type of properties evaluated by the specified
expression.
+ * @return builder of type resulting from expression evaluation (never null).
+ * @throws IllegalArgumentException if the given feature type does not contain the expected
properties.
+ * @throws InvalidExpressionException if this method can not determine the result type
of the expression
+ * at given index. It may be because that expression is backed by an unsupported
implementation.
+ */
+ final AttributeTypeBuilder<?> copyGeometryType(final FeatureType valueType, final
FeatureTypeBuilder addTo) {
+ final PropertyTypeBuilder type = copyType(0, valueType, addTo);
+ if (type instanceof AttributeTypeBuilder<?>) {
+ AttributeTypeBuilder<?> att = (AttributeTypeBuilder<?>) type;
+ if (Geometries.isKnownType(att.getValueClass())) {
+ return att;
+ }
+ }
+ throw new IllegalArgumentException(Resources.format(Resources.Keys.NotAGeometryAtFirstExpression));
+ }
+
+ /**
* Implementation of the visitor pattern.
* Not used in Apache SIS implementation.
*/
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/ST_Buffer.java b/core/sis-feature/src/main/java/org/apache/sis/filter/ST_Buffer.java
index c41532a..46e8fca 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/ST_Buffer.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/ST_Buffer.java
@@ -16,14 +16,14 @@
*/
package org.apache.sis.filter;
+import org.apache.sis.feature.builder.AttributeTypeBuilder;
import org.apache.sis.feature.builder.FeatureTypeBuilder;
+import org.apache.sis.feature.builder.PropertyTypeBuilder;
import org.apache.sis.internal.feature.FeatureExpression;
import org.apache.sis.internal.feature.Geometries;
import org.apache.sis.util.ArgumentChecks;
import org.locationtech.jts.geom.Geometry;
-import org.opengis.feature.AttributeType;
import org.opengis.feature.FeatureType;
-import org.opengis.feature.PropertyType;
import org.opengis.filter.expression.Expression;
import org.opengis.util.FactoryException;
@@ -95,22 +95,16 @@ final class ST_Buffer extends NamedFunction implements FeatureExpression
{
}
/**
- * Returns the expected type of values produced by this expression when a feature of
the given
- * type is evaluated.
+ * Provides the type of values produced by this expression when a feature of the given
type is evaluated.
*
- * @param valueType the type of features on which to apply the expression.
- * @return expected expression result type.
- * @throws IllegalArgumentException if this method can not determine the property type
for the given feature type.
+ * @param valueType the type of features on which to apply this expression.
+ * @param addTo where to add the type of properties evaluated by this expression.
+ * @return builder of type resulting from expression evaluation (never null).
+ * @throws IllegalArgumentException if the given feature type does not contain the expected
properties.
*/
@Override
- public PropertyType expectedType(final FeatureType valueType) {
- final PropertyType expectedType = expectedType(0, valueType);
- if (expectedType instanceof AttributeType<?>) {
- AttributeType<?> att = (AttributeType<?>) expectedType;
- if (Geometries.isKnownType(att.getValueClass())) {
- return new FeatureTypeBuilder().addAttribute(att).setValueClass(Geometry.class).build();
- }
- }
- throw new IllegalArgumentException("First expression must result in a geometric attribute");
// TODO: localize.
+ public PropertyTypeBuilder expectedType(final FeatureType valueType, final FeatureTypeBuilder
addTo) {
+ final AttributeTypeBuilder<?> pt = copyGeometryType(valueType, addTo);
+ return pt.setValueClass(Geometries.implementation(pt.getValueClass()).rootClass);
}
}
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/ST_Centroid.java b/core/sis-feature/src/main/java/org/apache/sis/filter/ST_Centroid.java
index d1df586..665bcf1 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/ST_Centroid.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/ST_Centroid.java
@@ -16,15 +16,15 @@
*/
package org.apache.sis.filter;
+import org.apache.sis.feature.builder.AttributeTypeBuilder;
import org.apache.sis.feature.builder.FeatureTypeBuilder;
+import org.apache.sis.feature.builder.PropertyTypeBuilder;
import org.apache.sis.internal.feature.FeatureExpression;
import org.apache.sis.internal.feature.Geometries;
import org.apache.sis.util.ArgumentChecks;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.Point;
-import org.opengis.feature.AttributeType;
import org.opengis.feature.FeatureType;
-import org.opengis.feature.PropertyType;
import org.opengis.filter.expression.Expression;
import org.opengis.util.FactoryException;
@@ -93,22 +93,16 @@ final class ST_Centroid extends NamedFunction implements FeatureExpression
{
}
/**
- * Returns the expected type of values produced by this expression when a feature of
the given
- * type is evaluated.
+ * Provides the type of values produced by this expression when a feature of the given
type is evaluated.
*
- * @param valueType the type of features on which to apply the expression.
- * @return expected expression result type.
- * @throws IllegalArgumentException if this method can not determine the property type
for the given feature type.
+ * @param valueType the type of features on which to apply this expression.
+ * @param addTo where to add the type of properties evaluated by this expression.
+ * @return builder of type resulting from expression evaluation (never null).
+ * @throws IllegalArgumentException if the given feature type does not contain the expected
properties.
*/
@Override
- public PropertyType expectedType(final FeatureType valueType) {
- final PropertyType expectedType = expectedType(0, valueType);
- if (expectedType instanceof AttributeType<?>) {
- AttributeType<?> att = (AttributeType<?>) expectedType;
- if (Geometries.isKnownType(att.getValueClass())) {
- return new FeatureTypeBuilder().addAttribute(att).setValueClass(Point.class).build();
- }
- }
- throw new IllegalArgumentException("First expression must result in a geometric attribute");
// TODO: localize.
+ public PropertyTypeBuilder expectedType(final FeatureType valueType, final FeatureTypeBuilder
addTo) {
+ final AttributeTypeBuilder<?> pt = copyGeometryType(valueType, addTo);
+ return pt.setValueClass(Geometries.implementation(pt.getValueClass()).pointClass);
}
}
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/ST_Transform.java b/core/sis-feature/src/main/java/org/apache/sis/filter/ST_Transform.java
index 33059da..7048f03 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/ST_Transform.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/ST_Transform.java
@@ -20,14 +20,13 @@ import java.util.Objects;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
-import org.opengis.feature.AttributeType;
import org.opengis.feature.FeatureType;
-import org.opengis.feature.PropertyType;
import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.Literal;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.TransformException;
import org.opengis.util.FactoryException;
+import org.apache.sis.feature.builder.PropertyTypeBuilder;
import org.apache.sis.feature.builder.FeatureTypeBuilder;
import org.apache.sis.internal.feature.FeatureExpression;
import org.apache.sis.internal.feature.Geometries;
@@ -186,22 +185,15 @@ final class ST_Transform extends NamedFunction implements FeatureExpression
{
}
/**
- * Returns the expected type of values produced by this expression when a feature of
the given
- * type is evaluated.
+ * Provides the type of values produced by this expression when a feature of the given
type is evaluated.
*
- * @param valueType the type of features on which to apply the expression.
- * @return expected expression result type.
- * @throws IllegalArgumentException if this method can not determine the property type
for the given feature type.
+ * @param valueType the type of features on which to apply this expression.
+ * @param addTo where to add the type of properties evaluated by this expression.
+ * @return builder of type resulting from expression evaluation (never null).
+ * @throws IllegalArgumentException if the given feature type does not contain the expected
properties.
*/
@Override
- public PropertyType expectedType(final FeatureType valueType) {
- final PropertyType expectedType = expectedType(0, valueType);
- if (expectedType instanceof AttributeType<?>) {
- AttributeType<?> att = (AttributeType<?>) expectedType;
- if (Geometries.isKnownType(att.getValueClass())) {
- return new FeatureTypeBuilder().addAttribute(att).setCRS(literalCRS ? targetCRS
: null).build();
- }
- }
- throw new IllegalArgumentException("First expression must result in a geometric attribute");
// TODO: localize.
+ public PropertyTypeBuilder expectedType(final FeatureType valueType, final FeatureTypeBuilder
addTo) {
+ return copyGeometryType(valueType, addTo).setCRS(literalCRS ? targetCRS : null);
}
}
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureExpression.java
b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureExpression.java
index 01d954f..1aeea6b 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureExpression.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureExpression.java
@@ -16,73 +16,82 @@
*/
package org.apache.sis.internal.feature;
-// Branch-dependent imports
import org.opengis.feature.FeatureType;
import org.opengis.feature.PropertyType;
+import org.opengis.feature.AttributeType;
import org.opengis.filter.expression.Expression;
import org.apache.sis.internal.util.CollectionsExt;
+import org.apache.sis.feature.builder.FeatureTypeBuilder;
+import org.apache.sis.feature.builder.PropertyTypeBuilder;
/**
* OGC expressions or other functions operating on feature instances.
- * This interface adds an additional method, {@link #expectedType(FeatureType)},
+ * This interface adds an additional method, {@link #expectedType(FeatureType, FeatureTypeBuilder)},
* for fetching in advance the expected type of expression results.
*
* <p>This is an experimental interface which may be removed in any future version.</p>
*
* @author Johann Sorel (Geomatys)
+ * @author Martin Desruisseaux (Geomatys)
* @version 1.0
* @since 1.0
* @module
*/
public interface FeatureExpression {
/**
- * Returns the expected type of values produced by this expression when a feature of
the given
+ * Provides the expected type of values produced by this expression when a feature of
the given
* type is evaluated. The resulting type shall describe a "static" property, i.e. it
can be an
- * {@link org.opengis.feature.AttributeType} or a {@link org.opengis.feature.FeatureAssociationRole}
+ * {@link AttributeType} or a {@link org.opengis.feature.FeatureAssociationRole}
* but not an {@link org.opengis.feature.Operation}.
*
* @param valueType the type of features to be evaluated by the given expression.
- * @return expected type resulting from expression evaluation, or {@code null} if unknown.
+ * @param addTo where to add the type of properties evaluated by this expression.
+ * @return builder of the added property, or {@code null} if this method can not add
a property.
* @throws IllegalArgumentException if this method can operate only on some feature types
* and the given type is not one of them.
*/
- PropertyType expectedType(FeatureType valueType);
+ PropertyTypeBuilder expectedType(FeatureType valueType, FeatureTypeBuilder addTo);
/**
- * Returns the type of results computed by the given expression, or {@code null} if unknown.
- * This method returns the first of the following choices that apply:
+ * Provides the type of results computed by the given expression.
+ * This method executes the first of the following choices that apply:
*
* <ol>
- * <li>If the expression implements {@link FeatureExpression}, delegate to {@link
#expectedType(FeatureType)}.
- * Note that the invoked method may throw an {@link IllegalArgumentException}.</li>
+ * <li>If the expression implements {@link FeatureExpression}, delegate to {@link
#expectedType(FeatureType,
+ * FeatureTypeBuilder)}. Note that the invoked method may throw an {@link IllegalArgumentException}.</li>
* <li>Otherwise if {@link Expression#evaluate(Object, Class)} with a {@code
PropertyType.class} argument
- * returns a non-null value, returns that value.</li>
+ * returns a non-null property, adds that property to the given builder.</li>
* <li>Otherwise if the given feature type contains exactly one property (including
inherited properties),
- * returns that property.</li>
+ * adds that property to the given builder.</li>
* <li>Otherwise returns {@code null}.</li>
* </ol>
*
- * It is caller's responsibility to verify if the returned value is {@code null} and
to throw an exception in such case.
+ * It is caller's responsibility to verify if this method returns {@code null} and to
throw an exception in such case.
* We leave that responsibility to the caller because (s)he may be able to provide better
error messages.
*
- * @param parameter the expression for which to get the result type, or {@code null}.
- * @param valueType the type of features to be evaluated by the given expression.
- * @return expected type resulting from expression evaluation, or {@code null} if unknown.
+ * @param expression the expression for which to get the result type, or {@code null}.
+ * @param valueType the type of features to be evaluated by the given expression.
+ * @param addTo where to add the type of properties evaluated by the given expression.
+ * @return builder of the added property, or {@code null} if this method can not add
a property.
* @throws IllegalArgumentException if this method can operate only on some feature types
* and the given type is not one of them.
*/
- public static PropertyType expectedType(final Expression parameter, final FeatureType
valueType) {
- if (parameter instanceof FeatureExpression) {
- return ((FeatureExpression) parameter).expectedType(valueType);
+ public static PropertyTypeBuilder expectedType(final Expression expression, final FeatureType
valueType, final FeatureTypeBuilder addTo) {
+ if (expression instanceof FeatureExpression) {
+ return ((FeatureExpression) expression).expectedType(valueType, addTo);
}
- if (parameter != null) {
+ PropertyType pt = null;
+ if (expression != null) {
// TODO: remove this hack if we can get more type-safe Expression.
- PropertyType pt = parameter.evaluate(valueType, PropertyType.class);
- if (pt != null) {
- return pt;
+ pt = expression.evaluate(valueType, PropertyType.class);
+ }
+ if (pt == null) {
+ pt = CollectionsExt.singletonOrNull(valueType.getProperties(true));
+ if (pt == null) {
+ return null;
}
}
- return CollectionsExt.singletonOrNull(valueType.getProperties(true));
+ return addTo.addProperty(pt);
}
}
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
index 40dd2e1..0ed326d 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
@@ -137,6 +137,20 @@ public abstract class Geometries<G> {
}
/**
+ * Returns an accessor to the library implementation for a geometry of the given type.
+ * If the given type is not recognized, then this method returns the default library.
+ *
+ * @param type the type to verify.
+ * @return a geometry implementation compatible with the given type.
+ */
+ public static Geometries<?> implementation(final Class<?> type) {
+ for (Geometries<?> g = implementation; g != null; g = g.fallback) {
+ if (g.rootClass.isAssignableFrom(type)) return g;
+ }
+ return implementation;
+ }
+
+ /**
* Returns {@code true} if the given type is one of the types known to Apache SIS.
*
* @param type the type to verify.
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Resources.java
b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Resources.java
index c15ee72..44d8258 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Resources.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Resources.java
@@ -251,6 +251,11 @@ public final class Resources extends IndexedResourceBundle {
public static final short NonLinearInDimensions_1 = 45;
/**
+ * Value provided by first expression is not a geometry.
+ */
+ public static final short NotAGeometryAtFirstExpression = 57;
+
+ /**
* Property “{0}” contains more than one value.
*/
public static final short NotASingleton_1 = 14;
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Resources.properties
b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Resources.properties
index 8904f41..b63161e 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Resources.properties
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Resources.properties
@@ -56,6 +56,7 @@ MismatchedValueClass_3 = An attribute for \u2018{1}\u2019 values
wher
NoCategoryForValue_1 = No category for value {0}.
NoNDimensionalSlice_3 = Can not infer a {0}-dimensional slice from the grid envelope.
Dimension {1} has {2,number} cells.
NonLinearInDimensions_1 = non-linear in {0} dimension{0,choice,1#|2#s}:
+NotAGeometryAtFirstExpression = Value provided by first expression is not a geometry.
NotASingleton_1 = Property \u201c{0}\u201d contains more than one value.
NotStrictlyOrderedDimensions = The specified dimensions are not in strictly ascending
order.
OptionalLibraryNotFound_2 = The {0} optional library is not available. Geometric
operations will ignore that library.\nCause is {1}.
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Resources_fr.properties
b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Resources_fr.properties
index 2d2d051..dbfee3f 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Resources_fr.properties
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Resources_fr.properties
@@ -61,6 +61,7 @@ MismatchedValueClass_3 = Un attribut pour des valeurs de type
\u2018{
NoCategoryForValue_1 = Aucune cat\u00e9gorie n\u2019est d\u00e9finie pour la
valeur {0}.
NoNDimensionalSlice_3 = Ne peut pas inf\u00e9rer une tranche \u00e0 {0} dimensions
\u00e0 partir de l\u2019enveloppe de la grille. La dimension {1} a {2,number} cellules.
NonLinearInDimensions_1 = non-lin\u00e9aire dans {0} dimension{0,choice,1#|2#s}\u2008:
+NotAGeometryAtFirstExpression = La valeur fournie par la premi\u00e8re expression n\u2019est
pas une g\u00e9om\u00e9trie.
NotASingleton_1 = La propri\u00e9t\u00e9 \u00ab\u202f{0}\u202f\u00bb contient
plus de une valeur.
NotStrictlyOrderedDimensions = Les dimensions sp\u00e9cifi\u00e9es ne sont pas en ordre
strictement croissant.
OptionalLibraryNotFound_2 = La biblioth\u00e8que optionnelle {0} n\u2019est pas disponible.
Les op\u00e9rations g\u00e9om\u00e9triques ignoreront cette biblioth\u00e8que.\nLa cause est
{1}.
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SimpleQuery.java
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SimpleQuery.java
index 3b675f7..8752f73 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SimpleQuery.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SimpleQuery.java
@@ -24,6 +24,7 @@ import java.util.Objects;
import org.opengis.util.GenericName;
import org.apache.sis.filter.InvalidExpressionException;
import org.apache.sis.feature.builder.FeatureTypeBuilder;
+import org.apache.sis.feature.builder.PropertyTypeBuilder;
import org.apache.sis.internal.feature.FeatureExpression;
import org.apache.sis.internal.util.UnmodifiableArrayList;
import org.apache.sis.internal.storage.Resources;
@@ -33,13 +34,9 @@ import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.Classes;
import org.apache.sis.util.collection.Containers;
import org.apache.sis.util.iso.Names;
-import org.apache.sis.util.resources.Errors;
// Branch-dependent imports
-import org.opengis.feature.AttributeType;
-import org.opengis.feature.FeatureAssociationRole;
import org.opengis.feature.FeatureType;
-import org.opengis.feature.PropertyType;
import org.opengis.filter.Filter;
import org.opengis.filter.expression.Expression;
import org.opengis.filter.sort.SortBy;
@@ -306,11 +303,11 @@ public class SimpleQuery extends Query {
}
/**
- * Returns the type of results computed by this column.
+ * Adds in the given builder the type of results computed by this column.
*
- * @param valueType the type of features to be evaluated by the expression in this
column.
* @param column index of this column. Used for error message only.
- * @return expected type resulting from expression evaluation (never null).
+ * @param valueType the type of features to be evaluated by the expression in this
column.
+ * @param addTo where to add the type of properties evaluated by expression
in this column.
* @throws IllegalArgumentException if this method can operate only on some feature
types
* and the given type is not one of them.
* @throws InvalidExpressionException if this method can not determine the result
type of the expression
@@ -318,23 +315,14 @@ public class SimpleQuery extends Query {
*
* @see SimpleQuery#expectedType(FeatureType)
*/
- final PropertyType expectedType(final FeatureType valueType, final int column) {
- PropertyType resultType = FeatureExpression.expectedType(expression, valueType);
+ final void expectedType(final int column, final FeatureType valueType, final FeatureTypeBuilder
addTo) {
+ final PropertyTypeBuilder resultType = FeatureExpression.expectedType(expression,
valueType, addTo);
if (resultType == null) {
throw new InvalidExpressionException(expression, column);
}
- /*
- * If a name has been explicitly given, rename the result type.
- * We allow renaming only for attributes and associations.
- */
if (alias != null && !alias.equals(resultType.getName())) {
- resultType = new FeatureTypeBuilder().addProperty(resultType).setName(alias).build();
- if (!(resultType instanceof AttributeType<?>) && !(resultType
instanceof FeatureAssociationRole)) {
- throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalPropertyValueClass_3,
- alias, AttributeType.class, Classes.getStandardType(Classes.getClass(resultType))));
- }
+ resultType.setName(alias);
}
- return resultType;
}
/**
@@ -422,7 +410,7 @@ public class SimpleQuery extends Query {
}
final FeatureTypeBuilder ftb = new FeatureTypeBuilder().setName(valueType.getName());
for (int i=0; i<columns.length; i++) {
- ftb.addProperty(columns[i].expectedType(valueType, i));
+ columns[i].expectedType(i, valueType, ftb);
}
return ftb.build();
}
|