You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2016/04/15 23:12:14 UTC
svn commit: r1739369 - in /sis/branches/JDK8/core/sis-feature/src:
main/java/org/apache/sis/feature/AbstractAttribute.java
main/java/org/apache/sis/feature/StringJoinOperation.java
test/java/org/apache/sis/feature/StringJoinOperationTest.java
Author: desruisseaux
Date: Fri Apr 15 21:12:14 2016
New Revision: 1739369
URL: http://svn.apache.org/viewvc?rev=1739369&view=rev
Log:
Add test, bug fixes and formatting.
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAttribute.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/StringJoinOperation.java
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/StringJoinOperationTest.java
Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAttribute.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAttribute.java?rev=1739369&r1=1739368&r2=1739369&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAttribute.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAttribute.java [UTF-8] Fri Apr 15 21:12:14 2016
@@ -103,7 +103,7 @@ public abstract class AbstractAttribute<
/**
* Creates a new attribute of the given type.
*
- * @param type Information about the attribute (base Java class, domain of values, <i>etc.</i>).
+ * @param type information about the attribute (base Java class, domain of values, <i>etc.</i>).
*
* @see #create(AttributeType)
*/
@@ -115,9 +115,9 @@ public abstract class AbstractAttribute<
* Creates a new attribute of the given type initialized to the
* {@linkplain DefaultAttributeType#getDefaultValue() default value}.
*
- * @param <V> The type of attribute values.
- * @param type Information about the attribute (base Java class, domain of values, <i>etc.</i>).
- * @return The new attribute.
+ * @param <V> the type of attribute values.
+ * @param type information about the attribute (base Java class, domain of values, <i>etc.</i>).
+ * @return the new attribute.
*
* @see DefaultAttributeType#newInstance()
*/
@@ -132,9 +132,9 @@ public abstract class AbstractAttribute<
* Creates a new attribute of the given type initialized to the given value.
* Note that a {@code null} value may not be the same as the default value.
*
- * @param <V> The type of attribute values.
- * @param type Information about the attribute (base Java class, domain of values, <i>etc.</i>).
- * @param value The initial value (may be {@code null}).
+ * @param <V> the type of attribute values.
+ * @param type information about the attribute (base Java class, domain of values, <i>etc.</i>).
+ * @param value the initial value (may be {@code null}).
* @return The new attribute.
*/
static <V> AbstractAttribute<V> create(final AttributeType<V> type, final Object value) {
@@ -147,8 +147,8 @@ public abstract class AbstractAttribute<
/**
* Invoked on serialization for saving the {@link #characteristics} field.
*
- * @param out The output stream where to serialize this attribute.
- * @throws IOException If an I/O error occurred while writing.
+ * @param out the output stream where to serialize this attribute.
+ * @throws IOException if an I/O error occurred while writing.
*/
private void writeObject(final ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
@@ -164,9 +164,9 @@ public abstract class AbstractAttribute<
/**
* Invoked on deserialization for restoring the {@link #characteristics} field.
*
- * @param in The input stream from which to deserialize an attribute.
- * @throws IOException If an I/O error occurred while reading or if the stream contains invalid data.
- * @throws ClassNotFoundException If the class serialized on the stream is not on the classpath.
+ * @param in the input stream from which to deserialize an attribute.
+ * @throws IOException if an I/O error occurred while reading or if the stream contains invalid data.
+ * @throws ClassNotFoundException if the class serialized on the stream is not on the classpath.
*/
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
@@ -185,7 +185,7 @@ public abstract class AbstractAttribute<
* Returns the name of this attribute as defined by its {@linkplain #getType() type}.
* This convenience method delegates to {@link AttributeType#getName()}.
*
- * @return The attribute name specified by its type.
+ * @return the attribute name specified by its type.
*/
@Override
public GenericName getName() {
@@ -195,7 +195,7 @@ public abstract class AbstractAttribute<
/**
* Returns information about the attribute (base Java class, domain of values, <i>etc.</i>).
*
- * @return Information about the attribute.
+ * @return information about the attribute.
*/
@Override
public AttributeType<V> getType() {
@@ -207,7 +207,7 @@ public abstract class AbstractAttribute<
* the common case where the {@linkplain DefaultAttributeType#getMaximumOccurs() maximum number}
* of attribute values is restricted to 1 or 0.
*
- * @return The attribute value (may be {@code null}).
+ * @return the attribute value (may be {@code null}).
* @throws MultiValuedPropertyException if this attribute contains more than one value.
*
* @see AbstractFeature#getPropertyValue(String)
@@ -223,7 +223,7 @@ public abstract class AbstractAttribute<
* <p>The default implementation returns a collection which will delegate its work to
* {@link #getValue()} and {@link #setValue(Object)}.</p>
*
- * @return The attribute values in a <cite>live</cite> collection.
+ * @return the attribute values in a <cite>live</cite> collection.
*/
@Override
public Collection<V> getValues() {
@@ -239,12 +239,14 @@ public abstract class AbstractAttribute<
* and also because some rules may be temporarily broken while constructing a feature.
* A more exhaustive verification can be performed by invoking the {@link #quality()} method.
*
- * @param value The new value, or {@code null} for removing all values from this attribute.
+ * @param value the new value, or {@code null} for removing all values from this attribute.
+ * @throws InvalidPropertyValueException if this method verifies argument validity and the given value
+ * does not met the attribute constraints.
*
* @see AbstractFeature#setPropertyValue(String, Object)
*/
@Override
- public abstract void setValue(final V value);
+ public abstract void setValue(final V value) throws InvalidPropertyValueException;
/**
* Sets the attribute values. All previous values are replaced by the given collection.
@@ -252,7 +254,7 @@ public abstract class AbstractAttribute<
* <p>The default implementation ensures that the given collection contains at most one element,
* then delegates to {@link #setValue(Object)}.</p>
*
- * @param values The new values.
+ * @param values the new values.
* @throws InvalidPropertyValueException if the given collection contains too many elements.
*/
@Override
@@ -331,7 +333,7 @@ public abstract class AbstractAttribute<
* }</li>
* </ol>
*
- * @return Other attribute types that describes this attribute type, or an empty map if none.
+ * @return other attribute types that describes this attribute type, or an empty map if none.
*
* @see DefaultAttributeType#characteristics()
*/
@@ -341,7 +343,7 @@ public abstract class AbstractAttribute<
if (characteristics == null) {
characteristics = newCharacteristicsMap();
}
- return characteristics; // Intentionally modifiable
+ return characteristics; // Intentionally modifiable
}
/**
@@ -436,7 +438,7 @@ public abstract class AbstractAttribute<
* }
* </div>
*
- * @return Reports on all constraint violations found.
+ * @return reports on all constraint violations found.
*
* @see AbstractFeature#quality()
*/
@@ -456,7 +458,7 @@ public abstract class AbstractAttribute<
* └─ characteristics: units=°C, accuracy=0.1
* }
*
- * @return A string representation of this attribute for debugging purpose.
+ * @return a string representation of this attribute for debugging purpose.
*/
@Debug
@Override
@@ -481,7 +483,7 @@ public abstract class AbstractAttribute<
* are <strong>not</strong> cloned.
* However subclasses may choose to do otherwise.
*
- * @return A clone of this attribute.
+ * @return a clone of this attribute.
* @throws CloneNotSupportedException if this attribute, the {@linkplain #getValue() value}
* or one of its {@linkplain #characteristics() characteristics} can not be cloned.
*/
Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/StringJoinOperation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/StringJoinOperation.java?rev=1739369&r1=1739368&r2=1739369&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/StringJoinOperation.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/StringJoinOperation.java [UTF-8] Fri Apr 15 21:12:14 2016
@@ -305,10 +305,10 @@ final class StringJoinOperation extends
* parsed, then this method does not store any property value ("all or nothing" behavior).
*
* @param value the concatenated string.
- * @throws UnconvertibleObjectException if one of the attribute values can not be parsed to the expected type.
+ * @throws InvalidPropertyValueException if one of the attribute values can not be parsed to the expected type.
*/
@Override
- public void setValue(final String value) throws UnconvertibleObjectException {
+ public void setValue(final String value) throws InvalidPropertyValueException {
final int endAt = value.length() - suffix.length();
final boolean prefixMatches = value.startsWith(prefix);
if (!prefixMatches || !value.endsWith(suffix)) {
@@ -316,7 +316,7 @@ final class StringJoinOperation extends
getName(),
prefixMatches ? 1 : 0, // For "{1,choice,0#begin|1#end}" in message format.
prefixMatches ? suffix : prefix,
- prefixMatches ? CharSequences.token(value, 0) : value.substring(Math.max(0, endAt))));
+ prefixMatches ? value.substring(Math.max(0, endAt)) : CharSequences.token(value, 0)));
}
/*
* We do not use the regex split for avoiding possible reserved regex characters,
@@ -358,7 +358,7 @@ final class StringJoinOperation extends
element = new StringBuilder(element.length() - 1)
.append(element, 0, i).append(element, i+1, element.length()).toString();
if (i < element.length()) {
- if (element.indexOf(i) == ESCAPE) {
+ if (element.charAt(i) == ESCAPE) {
i++;
} else {
assert element.regionMatches(i, delimiter, 0, delimiter.length()) : element;
@@ -371,8 +371,11 @@ final class StringJoinOperation extends
* If we have more values than expected, continue the parsing but without storing the values.
* The intend is to get the correct count of values for error reporting.
*/
- if (!element.isEmpty() && count < values.length) {
+ if (!element.isEmpty() && count < values.length) try {
values[count] = converters[count].apply(element);
+ } catch (UnconvertibleObjectException e) {
+ throw new InvalidPropertyValueException(Errors.format(
+ Errors.Keys.CanNotAssign_2, attributeNames[count], element), e);
}
count++;
upper += delimiter.length();
Modified: sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/StringJoinOperationTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/StringJoinOperationTest.java?rev=1739369&r1=1739368&r2=1739369&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/StringJoinOperationTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/StringJoinOperationTest.java [UTF-8] Fri Apr 15 21:12:14 2016
@@ -27,12 +27,14 @@ import static org.junit.Assert.*;
// Branch-dependent imports
import org.opengis.feature.PropertyType;
+import org.opengis.feature.InvalidPropertyValueException;
/**
* Tests {@link StringJoinOperation}.
*
* @author Johann Sorel (Geomatys)
+ * @author Martin Desruisseaux (Geomatys)
* @since 0.7
* @version 0.7
* @module
@@ -52,12 +54,16 @@ public final strictfp class StringJoinOp
* <li>{@code summary} as string join of {@code name} and {@code age} attributes.</li>
* </ul>
*
+ * The operation uses {@code "<<:"} and {@code ":>>"} as prefix and suffix respectively
+ * avoid avoiding confusion if a code spelled the variable name (e.g. {@code prefix})
+ * instead of using it.
+ *
* @return The feature for a person.
*/
private static DefaultFeatureType person() {
final PropertyType nameType = new DefaultAttributeType<>(name("name"), String.class, 1, 1, null);
final PropertyType ageType = new DefaultAttributeType<>(name("age"), Integer.class, 1, 1, null);
- final PropertyType cmpType = FeatureOperations.compound(name("concat"), "/", "prefix:", ":suffix", nameType, ageType);
+ final PropertyType cmpType = FeatureOperations.compound(name("concat"), "/", "<<:", ":>>", nameType, ageType);
return new DefaultFeatureType(name("person"), false, null, nameType, ageType, cmpType);
}
@@ -70,6 +76,7 @@ public final strictfp class StringJoinOp
/**
* Tests {@code StringJoinOperation.Result.getValue()} on sparse and dense features.
+ * This test does not use the {@code '\'} escape character.
*/
@Test
public void testGetValue() {
@@ -82,17 +89,18 @@ public final strictfp class StringJoinOp
* Executes the {@link #testGetValue()} on the given feature, which is either sparse or dense.
*/
private static void testGetValue(final AbstractFeature feature) {
- assertEquals("prefix:/:suffix", feature.getPropertyValue("concat"));
+ assertEquals("<<:/:>>", feature.getPropertyValue("concat"));
feature.setPropertyValue("name", "marc");
- assertEquals("prefix:marc/:suffix", feature.getPropertyValue("concat"));
+ assertEquals("<<:marc/:>>", feature.getPropertyValue("concat"));
feature.setPropertyValue("age", 21);
- assertEquals("prefix:marc/21:suffix", feature.getPropertyValue("concat"));
+ assertEquals("<<:marc/21:>>", feature.getPropertyValue("concat"));
}
/**
* Tests {@code StringJoinOperation.Result.setValue(String)} on sparse and dense features.
+ * This test does not use the {@code '\'} escape character.
*/
@Test
@DependsOnMethod("testGetValue")
@@ -106,9 +114,65 @@ public final strictfp class StringJoinOp
* Executes the {@link #testSetValue()} on the given feature, which is either sparse or dense.
*/
private static void testSetValue(final AbstractFeature feature) {
- feature.setPropertyValue("concat", "prefix:emile/37:suffix");
+ feature.setPropertyValue("concat", "<<:emile/37:>>");
assertEquals("name", "emile", feature.getPropertyValue("name"));
assertEquals("age", 37, feature.getPropertyValue("age"));
- assertEquals("concat", "prefix:emile/37:suffix", feature.getPropertyValue("concat"));
+ assertEquals("concat", "<<:emile/37:>>", feature.getPropertyValue("concat"));
+ }
+
+ /**
+ * Tests {@code getValue()} and {@code setValue(String)} with values that contains the {@code '\'}
+ * escape character.
+ */
+ @Test
+ @DependsOnMethod({"testGetValue", "testSetValue"})
+ public void testEscapeCharacter() {
+ final DenseFeature feature = new DenseFeature(person());
+ feature.setPropertyValue("name", "marc/emile\\julie");
+ feature.setPropertyValue("age", 30);
+ assertEquals("<<:marc\\/emile\\\\julie/30:>>", feature.getPropertyValue("concat"));
+
+ feature.setPropertyValue("concat", "<<:emile\\\\julie\\/marc/:>>");
+ assertEquals("name", "emile\\julie/marc", feature.getPropertyValue("name"));
+ assertNull ("age", feature.getPropertyValue("age"));
+ }
+
+ /**
+ * Verifies that proper exceptions are thrown in case of illegal argument.
+ */
+ @Test
+ public void testIllegalArgument() {
+ final DenseFeature feature = new DenseFeature(person());
+ try {
+ feature.setPropertyValue("concat", "((:marc/21:>>");
+ fail("Should fail because of mismatched prefix.");
+ } catch (InvalidPropertyValueException e) {
+ String message = e.getMessage();
+ assertTrue(message, message.contains("<<:"));
+ assertTrue(message, message.contains("(("));
+ }
+ try {
+ feature.setPropertyValue("concat", "<<:marc/21:))");
+ fail("Should fail because of mismatched suffix.");
+ } catch (InvalidPropertyValueException e) {
+ String message = e.getMessage();
+ assertTrue(message, message.contains(":>>"));
+ assertTrue(message, message.contains("))"));
+ }
+ try {
+ feature.setPropertyValue("concat", "<<:marc/21/julie:>>");
+ fail("Should fail because of too many components.");
+ } catch (InvalidPropertyValueException e) {
+ String message = e.getMessage();
+ assertTrue(message, message.contains("<<:marc/21/julie:>>"));
+ }
+ try {
+ feature.setPropertyValue("concat", "<<:marc/julie:>>");
+ fail("Should fail because of unparsable number.");
+ } catch (InvalidPropertyValueException e) {
+ String message = e.getMessage();
+ assertTrue(message, message.contains("julie"));
+ assertTrue(message, message.contains("age"));
+ }
}
}