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 2017/09/09 00:12:08 UTC
svn commit: r1807850 - in /sis/branches/JDK8/core/sis-feature/src:
main/java/org/apache/sis/feature/ main/java/org/apache/sis/internal/feature/
test/java/org/apache/sis/feature/
Author: desruisseaux
Date: Sat Sep 9 00:12:08 2017
New Revision: 1807850
URL: http://svn.apache.org/viewvc?rev=1807850&view=rev
Log:
Fix attribute characteristic formatting (was missing the actual values).
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/ESRI.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/JTS.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Java2D.java
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureFormatTest.java
Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java?rev=1807850&r1=1807849&r2=1807850&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java [UTF-8] Sat Sep 9 00:12:08 2017
@@ -43,6 +43,7 @@ import org.apache.sis.util.logging.Loggi
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.resources.Vocabulary;
import org.apache.sis.internal.util.CollectionsExt;
+import org.apache.sis.internal.feature.Geometries;
import org.apache.sis.internal.system.Modules;
import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.math.MathFunctions;
@@ -98,6 +99,11 @@ public class FeatureFormat extends Tabul
private static final long serialVersionUID = -5792086817264884947L;
/**
+ * The separator to use in comma-separated lists.
+ */
+ private static final String SEPARATOR = ", ";
+
+ /**
* An instance created when first needed and potentially shared.
*/
private static final AtomicReference<FeatureFormat> INSTANCE = new AtomicReference<>();
@@ -350,7 +356,7 @@ public class FeatureFormat extends Tabul
String separator = " ⇾ "; // UML symbol for inheritance.
for (final FeatureType parent : featureType.getSuperTypes()) {
toAppendTo.append(separator).append(toString(parent.getName()));
- separator = ", ";
+ separator = SEPARATOR;
}
}
toAppendTo.append(getLineSeparator());
@@ -463,19 +469,37 @@ public class FeatureFormat extends Tabul
if (!isFirstColumn) nextColumn(table);
isFirstColumn = false;
switch (column) {
+ /*
+ * Human-readable name of the property. May contains any characters (spaces, ideographs, etc).
+ * In many cases, this information is not provided and the whole column is skipped.
+ */
case DESIGNATION: {
final InternationalString d = propertyType.getDesignation();
if (d != null) table.append(d.toString(displayLocale));
break;
}
+ /*
+ * Machine-readable name of the property (identifier). This information is mandatory.
+ * This name is usually shorter than the designation and should contain only valid
+ * Unicode identifier characters (e.g. no spaces).
+ */
case NAME: {
table.append(toString(propertyType.getName()));
break;
}
+ /*
+ * The base class or interface for all values in properties of the same type.
+ * This is typically String, Number, Integer, Geometry or URL.
+ */
case TYPE: {
table.append(valueType);
break;
}
+ /*
+ * Minimum and maximum number of occurrences allowed for this property.
+ * If we are formatting a Feature instead than a FeatureType, then the
+ * actual number of values is also formatted. Example: 42 ∈ [0 … ∞]
+ */
case CARDINALITY: {
table.setCellAlignment(TableAppender.ALIGN_RIGHT);
if (cardinality >= 0) {
@@ -501,6 +525,12 @@ public class FeatureFormat extends Tabul
}
break;
}
+ /*
+ * If formatting a FeatureType, the default value. If formatting a Feature, the actual value.
+ * A java.text.Format instance dedicated to the value class is used if possible. In addition
+ * to types for which a java.text.Format may be available, we also have to check for other
+ * special cases. If there is more than one value, they are formatted as a coma-separated list.
+ */
case VALUE: {
table.setCellAlignment(TableAppender.ALIGN_LEFT);
final Format format = getFormat(valueClass); // Null if valueClass is null.
@@ -555,28 +585,62 @@ public class FeatureFormat extends Tabul
length = formatValue(value, table.append(separator), length);
buffer.setLength(0);
if (length < 0) break; // Value is too long, abandon remaining iterations.
- separator = ", ";
- length += 2;
+ separator = SEPARATOR;
+ length += SEPARATOR.length();
}
}
break;
}
+ /*
+ * Characteristics are optional information attached to some values. For example if a property
+ * value is a temperature measurement, a characteritic of that value may be the unit of measure.
+ * Characteristics are handled as "attributes of attributes".
+ */
case CHARACTERISTICS: {
if (propertyType instanceof AttributeType<?>) {
+ int length = 0;
String separator = "";
- for (final AttributeType<?> attribute : ((AttributeType<?>) propertyType).characteristics().values()) {
- table.append(separator).append(toString(attribute.getName()));
- Object c = attribute.getDefaultValue();
+format: for (final AttributeType<?> ct : ((AttributeType<?>) propertyType).characteristics().values()) {
+ /*
+ * Format the characteristic name. We will append the value(s) later.
+ * We keep trace of the text length in order to stop formatting if the
+ * text become too long.
+ */
+ final GenericName cn = ct.getName();
+ final String cs = toString(cn);
+ table.append(separator).append(cs);
+ length += separator.length() + cs.length();
+ Collection<?> cv = CollectionsExt.singletonOrEmpty(ct.getDefaultValue());
if (feature != null) {
- final Property p = feature.getProperty(propertyType.getName().toString());
- if (p instanceof Attribute<?>) { // Should always be true, but we are paranoiac.
- c = ((Attribute<?>) p).characteristics().get(attribute.getName().toString());
+ /*
+ * Usually, the property 'cp' below is null because all features use the same
+ * characteristic value (for example the same unit of measurement), which is
+ * given by the default value 'cv'. Nevertheless we have to check if current
+ * feature overrides this characteristic.
+ */
+ final Property cp = feature.getProperty(propertyType.getName().toString());
+ if (cp instanceof Attribute<?>) { // Should always be true, but we are paranoiac.
+ Attribute<?> ca = ((Attribute<?>) cp).characteristics().get(cn.toString());
+ if (ca != null) cv = ca.getValues();
}
}
- if (c != null) {
- formatValue(c, table.append(" = "), 0);
+ /*
+ * Now format the value, separated from the name with " = ". Example: unit = m/s
+ * If the value accepts multi-occurrences, we will format the value between {…}.
+ * We use {…} because we may have more than one characteristic in the same cell,
+ * so we need a way to distinguish multi-values from multi-characteristics.
+ */
+ final boolean multi = ct.getMaximumOccurs() > 1;
+ String sep = multi ? " = {" : " = ";
+ for (Object c : cv) {
+ length = formatValue(c, table.append(sep), length += sep.length());
+ if (length < 0) break format; // Value is too long, abandon remaining iterations.
+ sep = SEPARATOR;
+ }
+ separator = SEPARATOR;
+ if (multi && sep == SEPARATOR) {
+ table.append('}');
}
- separator = ", ";
}
}
break;
@@ -635,7 +699,7 @@ public class FeatureFormat extends Tabul
* the length exceed the maximal length (in which case the caller should break iteration).
*/
private int formatValue(final Object value, final TableAppender table, final int length) {
- final String text;
+ String text;
if (value instanceof InternationalString) {
text = ((InternationalString) value).toString(displayLocale);
} else if (value instanceof GenericName) {
@@ -644,7 +708,7 @@ public class FeatureFormat extends Tabul
text = toString(((IdentifiedType) value).getName());
} else if (value instanceof IdentifiedObject) {
text = IdentifiedObjects.getIdentifierOrName((IdentifiedObject) value);
- } else {
+ } else if ((text = Geometries.toString(value)) == null) {
text = value.toString();
}
final int remaining = MAXIMAL_VALUE_LENGTH - length;
Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/ESRI.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/ESRI.java?rev=1807850&r1=1807849&r2=1807850&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/ESRI.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/ESRI.java [UTF-8] Sat Sep 9 00:12:08 2017
@@ -26,6 +26,7 @@ import com.esri.core.geometry.Point;
import org.apache.sis.geometry.GeneralEnvelope;
import org.apache.sis.setup.GeometryLibrary;
import org.apache.sis.math.Vector;
+import org.apache.sis.util.Classes;
/**
@@ -48,6 +49,14 @@ final class ESRI extends Geometries<Geom
}
/**
+ * If the given object is a JTS geometry, returns a short string representation the class name.
+ */
+ @Override
+ final String tryGetLabel(Object geometry) {
+ return (geometry instanceof Geometry) ? Classes.getShortClassName(geometry) : null;
+ }
+
+ /**
* If the given object is an ESRI geometry and its envelope is non-empty, returns
* that envelope as an Apache SIS implementation. Otherwise returns {@code null}.
*
Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java?rev=1807850&r1=1807849&r2=1807850&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java [UTF-8] Sat Sep 9 00:12:08 2017
@@ -178,7 +178,7 @@ public abstract class Geometries<G> {
abstract GeneralEnvelope tryGetEnvelope(Object geometry);
/**
- * If the given object is one of the recognized type and its envelope is non-empty,
+ * If the given object is one of the recognized types and its envelope is non-empty,
* returns that envelope as an Apache SIS implementation. Otherwise returns {@code null}.
*
* @param geometry the geometry from which to get the envelope, or {@code null}.
@@ -192,6 +192,35 @@ public abstract class Geometries<G> {
}
return null;
}
+
+ /**
+ * If the given geometry is the type supported by this {@code Geometries} instance,
+ * returns a short string representation the class name. Otherwise returns {@code null}.
+ */
+ abstract String tryGetLabel(Object geometry);
+
+ /**
+ * If the given object is one of the recognized types, returns a short string representation
+ * (typically the class name and the bounds). Otherwise returns {@code null}.
+ *
+ * @param geometry the geometry from which to get a string representation, or {@code null}.
+ * @return a short string representation of the given geometry, or {@code null} if the given
+ * object is not a recognized geometry.
+ */
+ public static String toString(final Object geometry) {
+ for (Geometries<?> g = implementation; g != null; g = g.fallback) {
+ String s = g.tryGetLabel(geometry);
+ if (s != null) {
+ GeneralEnvelope env = g.tryGetEnvelope(geometry);
+ if (env != null) {
+ final String bbox = env.toString();
+ s += bbox.substring(bbox.indexOf('('));
+ }
+ return s;
+ }
+ }
+ return null;
+ }
/**
* Creates a two-dimensional point from the given coordinate. If the CRS is geographic, then the
Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/JTS.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/JTS.java?rev=1807850&r1=1807849&r2=1807850&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/JTS.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/JTS.java [UTF-8] Sat Sep 9 00:12:08 2017
@@ -21,6 +21,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import org.apache.sis.geometry.GeneralEnvelope;
import org.apache.sis.math.Vector;
+import org.apache.sis.util.Classes;
/**
@@ -62,6 +63,14 @@ final class JTS extends Geometries<Objec
}
/**
+ * If the given object is a JTS geometry, returns a short string representation the class name.
+ */
+ @Override
+ final String tryGetLabel(Object geometry) {
+ return (rootClass.isInstance(geometry)) ? Classes.getShortClassName(geometry) : null;
+ }
+
+ /**
* If the given object is a JTS geometry and its envelope is non-empty, returns
* that envelope as an Apache SIS implementation. Otherwise returns {@code null}.
*
Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Java2D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Java2D.java?rev=1807850&r1=1807849&r2=1807850&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Java2D.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Java2D.java [UTF-8] Sat Sep 9 00:12:08 2017
@@ -26,6 +26,7 @@ import org.apache.sis.geometry.GeneralEn
import org.apache.sis.setup.GeometryLibrary;
import org.apache.sis.internal.referencing.j2d.ShapeUtilities;
import org.apache.sis.math.Vector;
+import org.apache.sis.util.Classes;
/**
@@ -48,6 +49,21 @@ final class Java2D extends Geometries<Sh
}
/**
+ * If the given geometry is a Java2D geometry, returns a short string representation the class name,
+ * ignoring the primitive type specialization. For example if the class is {@code Rectangle2D.Float},
+ * then this method returns {@code "Rectangle2D"}.
+ */
+ @Override
+ final String tryGetLabel(Object geometry) {
+ if (geometry instanceof Shape) {
+ Class<?> c = geometry.getClass();
+ Class<?> e = c.getEnclosingClass();
+ return Classes.getShortName(e != null ? e : c);
+ }
+ return null;
+ }
+
+ /**
* If the given object is a Java2D geometry and its envelope is non-empty, returns
* that envelope as an Apache SIS implementation. Otherwise returns {@code null}.
*
Modified: sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureFormatTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureFormatTest.java?rev=1807850&r1=1807849&r2=1807850&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureFormatTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureFormatTest.java [UTF-8] Sat Sep 9 00:12:08 2017
@@ -157,16 +157,16 @@ public final strictfp class FeatureForma
final FeatureFormat format = create();
final String text = format.format(feature);
assertMultilinesEquals("World metropolis\n" +
- "┌──────────────┬─────────────────────┬─────────────┬──────────────┬─────────────────┐\n" +
- "│ Name │ Type │ Cardinality │ Value │ Characteristics │\n" +
- "├──────────────┼─────────────────────┼─────────────┼──────────────┼─────────────────┤\n" +
- "│ city │ String │ 1 ∈ [1 … 1] │ Tokyo │ │\n" +
- "│ population │ Integer │ 1 ∈ [1 … 1] │ 13,185,502 │ │\n" +
- "│ region │ InternationalString │ 0 ∉ [1 … 1] │ │ │\n" +
- "│ isGlobal │ Boolean │ 0 ∉ [1 … 1] │ │ │\n" +
- "│ universities │ String │ 2 ∈ [0 … ∞] │ Waseda, Keio │ │\n" +
- "│ temperature │ Float │ 1 ∈ [1 … 1] │ NaN │ accuracy, units │\n" +
- "└──────────────┴─────────────────────┴─────────────┴──────────────┴─────────────────┘\n", text);
+ "┌──────────────┬─────────────────────┬─────────────┬──────────────┬────────────────────────────┐\n" +
+ "│ Name │ Type │ Cardinality │ Value │ Characteristics │\n" +
+ "├──────────────┼─────────────────────┼─────────────┼──────────────┼────────────────────────────┤\n" +
+ "│ city │ String │ 1 ∈ [1 … 1] │ Tokyo │ │\n" +
+ "│ population │ Integer │ 1 ∈ [1 … 1] │ 13,185,502 │ │\n" +
+ "│ region │ InternationalString │ 0 ∉ [1 … 1] │ │ │\n" +
+ "│ isGlobal │ Boolean │ 0 ∉ [1 … 1] │ │ │\n" +
+ "│ universities │ String │ 2 ∈ [0 … ∞] │ Waseda, Keio │ │\n" +
+ "│ temperature │ Float │ 1 ∈ [1 … 1] │ NaN │ accuracy = 0.1, units = °C │\n" +
+ "└──────────────┴─────────────────────┴─────────────┴──────────────┴────────────────────────────┘\n", text);
}
/**