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
commit 31375b87a8568084e7610b4242df9b4cf8857d68 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Thu Dec 30 19:30:43 2021 +0100 Share common code in the way to format property values in the JavaFX application, and put a limit on the string length. --- .../sis/gui/coverage/ImagePropertyExplorer.java | 54 ++++---------- .../org/apache/sis/gui/metadata/MetadataTree.java | 21 +----- .../apache/sis/internal/gui/ExceptionReporter.java | 3 +- .../sis/internal/gui/PropertyValueFormatter.java | 85 ++++++++++++++++++++++ .../org/apache/sis/internal/gui/PropertyView.java | 17 +++-- .../apache/sis/metadata/TreeTableFormatTest.java | 2 +- .../org/apache/sis/metadata/TreeTableViewTest.java | 2 +- .../extent/DefaultGeographicBoundingBoxTest.java | 5 +- .../DefaultDataIdentificationTest.java | 2 +- .../apache/sis/internal/util/PropertyFormat.java | 37 ++++++++-- .../sis/util/collection/TreeTableFormat.java | 2 +- .../org/apache/sis/util/resources/Vocabulary.java | 10 +++ .../sis/util/resources/Vocabulary.properties | 2 + .../sis/util/resources/Vocabulary_fr.properties | 2 + 14 files changed, 165 insertions(+), 79 deletions(-) diff --git a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/ImagePropertyExplorer.java b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/ImagePropertyExplorer.java index 4de7c8b..83bdb43 100644 --- a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/ImagePropertyExplorer.java +++ b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/ImagePropertyExplorer.java @@ -16,7 +16,6 @@ */ package org.apache.sis.gui.coverage; -import java.util.Date; import java.util.Locale; import java.util.List; import java.util.Map; @@ -59,8 +58,8 @@ import org.apache.sis.util.resources.Vocabulary; import org.apache.sis.internal.gui.Styles; import org.apache.sis.internal.gui.PropertyView; import org.apache.sis.internal.gui.ImmutableObjectProperty; +import org.apache.sis.internal.gui.PropertyValueFormatter; import org.apache.sis.internal.gui.Resources; -import org.apache.sis.internal.util.PropertyFormat; /** @@ -639,7 +638,16 @@ public class ImagePropertyExplorer extends Widget { String text = null; Color fill = Styles.NORMAL_TEXT; if (image != null) { - text = getClassName(image.getClass()); + /* + * Gets a simple top-level class name for an image class. If the image is an enclosed class, + * searches for a parent class because enclosed class names are often not very informative. + * For example `ImageRenderer.Untitled` is a `BufferedImage` subclass. + */ + Class<?> type = image.getClass(); + while (type.getEnclosingClass() != null) { + type = type.getSuperclass(); + } + text = type.getSimpleName(); if (image instanceof PlanarImage) { final String check = ((PlanarImage) image).verify(); if (check != null) { @@ -656,19 +664,6 @@ public class ImagePropertyExplorer extends Widget { } /** - * Gets a simple top-level class name for an image class. If the given type is an enclosed class, - * searches for a parent class instead because enclosed class names are often not very informative. - * For example {@code ImageRenderer.Untitled} which is a {@code BufferedImage} subclass: - * the enclosing class name is not suitable in that example. - */ - private static String getClassName(Class<?> type) { - while (type.getEnclosingClass() != null) { - type = type.getSuperclass(); - } - return type.getSimpleName(); - } - - /** * Creates the renderer of cells in the table of image layout information. */ private static final class LayoutCell extends TableCell<LayoutRow,Number> { @@ -701,30 +696,7 @@ public class ImagePropertyExplorer extends Widget { /** * The formatter to use for producing a short string representation of a property value. */ - private final ValueFormat format; - - /** {@link PropertyCell#format} implementation. */ - private static final class ValueFormat extends PropertyFormat { - /** The locale to use for objects such as international strings. */ - private final Locale locale; - - /** Creates a new formatter which will write in the given buffer. */ - ValueFormat(final Locale locale, final StringBuilder buffer) { - super(buffer); - this.locale = locale; - } - - /** Returns the locale specified at construction time. */ - @Override public Locale getLocale() {return locale;} - - /** Invoked by {@link PropertyFormat} for values of unrecognized type. */ - @Override protected String toString(final Object value) { - if (value instanceof Number || value instanceof Date) { // See super-class javadoc. - return value.toString(); - } - return getClassName(value.getClass()) + "[…]"; - } - } + private final PropertyValueFormatter format; /** * Temporary buffer user when formatting property values. @@ -736,7 +708,7 @@ public class ImagePropertyExplorer extends Widget { */ PropertyCell(final Locale locale) { buffer = new StringBuilder(); - format = new ValueFormat(locale, buffer); + format = new PropertyValueFormatter(buffer, locale); } /** diff --git a/application/sis-javafx/src/main/java/org/apache/sis/gui/metadata/MetadataTree.java b/application/sis-javafx/src/main/java/org/apache/sis/gui/metadata/MetadataTree.java index 1b11850..0effac0 100644 --- a/application/sis-javafx/src/main/java/org/apache/sis/gui/metadata/MetadataTree.java +++ b/application/sis-javafx/src/main/java/org/apache/sis/gui/metadata/MetadataTree.java @@ -46,10 +46,10 @@ import javafx.scene.input.ClipboardContent; import org.opengis.util.InternationalString; import org.opengis.referencing.IdentifiedObject; import org.apache.sis.referencing.IdentifiedObjects; -import org.apache.sis.internal.util.PropertyFormat; import org.apache.sis.internal.system.Modules; import org.apache.sis.internal.gui.Resources; import org.apache.sis.internal.gui.PropertyView; +import org.apache.sis.internal.gui.PropertyValueFormatter; import org.apache.sis.internal.gui.ExceptionReporter; import org.apache.sis.util.collection.TreeTable; import org.apache.sis.util.collection.TableColumn; @@ -353,29 +353,14 @@ check: if (data != null) { * Formatter for metadata property value in a tree cell. This formatter handles in a special way * many object classes like {@link InternationalString}, <i>etc</i>. */ - private static final class Formatter extends PropertyFormat + private static final class Formatter extends PropertyValueFormatter implements Callback<CellDataFeatures<TreeTable.Node, Object>, ObservableValue<Object>> { /** - * The locale to use for texts. This is usually {@link Locale#getDefault()}. - * This value is given to {@link InternationalString#toString(Locale)} calls. - */ - private final Locale locale; - - /** * Creates a new formatter for the given locale. */ Formatter(final Locale locale) { - super(new StringBuilder()); - this.locale = locale; - } - - /** - * The locale to use for formatting textual content. - */ - @Override - public Locale getLocale() { - return locale; + super(new StringBuilder(), locale); } /** diff --git a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/ExceptionReporter.java b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/ExceptionReporter.java index 4aa0060..20bb02e 100644 --- a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/ExceptionReporter.java +++ b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/ExceptionReporter.java @@ -134,8 +134,7 @@ public final class ExceptionReporter extends Widget { */ public static String getStackTrace(final Throwable exception) { final StringWriter buffer = new StringWriter(); - final PrintWriter writer = new PrintWriter(buffer); - exception.printStackTrace(writer); + exception.printStackTrace(new PrintWriter(buffer)); return buffer.toString(); } diff --git a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/PropertyValueFormatter.java b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/PropertyValueFormatter.java new file mode 100644 index 0000000..c6adcd2 --- /dev/null +++ b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/PropertyValueFormatter.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sis.internal.gui; + +import java.util.Date; +import java.util.Locale; +import org.apache.sis.util.Classes; +import org.apache.sis.util.CharSequences; +import org.apache.sis.internal.util.PropertyFormat; + + +/** + * Creates string representation of property values of unknown type. + * Tabulations are replaced by spaces and line feeds are replaced by the Pilcrow character. + * + * @author Martin Desruisseaux (Geomatys) + * @version 1.2 + * @since 1.2 + * @module + */ +public class PropertyValueFormatter extends PropertyFormat { + /** + * The locale to use for objects. This is usually {@link Locale#getDefault()}. + * This value is given to {@link InternationalString#toString(Locale)} calls. + */ + protected final Locale locale; + + /** + * Creates a formatter for the specified locale. + * + * @param locale the locale to use for texts, numbers and dates. + * @param buffer where to format the objects. + */ + public PropertyValueFormatter(final Appendable buffer, final Locale locale) { + super(buffer); + this.locale = locale; + setLineSeparator(" ¶ "); + } + + /** + * The locale to use for formatting textual content. + */ + @Override + public final Locale getLocale() { + return locale; + } + + /** + * Invoked by {@link PropertyFormat} for formatting a value which has not been recognized as one of + * the types to be handled in a special way. In particular numbers and dates should be handled here. + */ + @Override + protected String toString(final Object value) { + if (value instanceof Number || value instanceof Date) { // See super-class javadoc. + return value.toString(); + } + return Classes.getShortClassName(value) + "(…)"; + } + + /** + * Invoked by {@link PropertyFormat} when the property value is any kind of {@link CharSequence}. + * This method applies an arbitrary limit for avoiding too long texts. + * + * @param text the text. + * @return the text potentially truncated if too long. + */ + @Override + protected String freeText(final String text) { + return CharSequences.shortSentence(super.freeText(text), 100).toString(); + } +} diff --git a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/PropertyView.java b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/PropertyView.java index c4df1ee..2a30407 100644 --- a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/PropertyView.java +++ b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/PropertyView.java @@ -21,8 +21,6 @@ import java.util.Objects; import java.util.Collection; import java.lang.reflect.Array; import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; import java.text.Format; import java.text.FieldPosition; import java.text.ParsePosition; @@ -44,6 +42,7 @@ import javafx.scene.layout.Background; import javafx.scene.layout.GridPane; import javafx.scene.layout.Pane; import javafx.scene.layout.Priority; +import org.opengis.referencing.IdentifiedObject; import org.apache.sis.io.CompoundFormat; import org.apache.sis.math.Statistics; import org.apache.sis.internal.util.Numerics; @@ -241,6 +240,8 @@ public final class PropertyView extends CompoundFormat<Object> implements Change content = null; } else if (newValue instanceof Throwable) { content = setText((Throwable) newValue); + } else if (newValue instanceof IdentifiedObject) { + content = setCRS((IdentifiedObject) newValue); } else if (newValue instanceof Collection<?>) { content = setList(((Collection<?>) newValue).toArray()); } else if (newValue.getClass().isArray()) { @@ -273,9 +274,7 @@ public final class PropertyView extends CompoundFormat<Object> implements Change * Sets the text to the stack trace of given exception. */ private Node setText(final Throwable ex) { - final StringWriter out = new StringWriter(); - ex.printStackTrace(new PrintWriter(out)); - return setText(out.toString()); + return setText(ExceptionReporter.getStackTrace(ex)); } /** @@ -296,6 +295,14 @@ public final class PropertyView extends CompoundFormat<Object> implements Change } /** + * Sets the viewer for a coordinate reference system. Shown as Well-Known Text (WKT) for now, + * but a future version may provide a more sophisticated viewer. + */ + private Node setCRS(final IdentifiedObject crs) { + return setText(crs.toString()); + } + + /** * Returns the pane containing {@link #imageView}. */ private Pane getImageCanvas() { diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeTableFormatTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeTableFormatTest.java index ec7068b..9d8c298 100644 --- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeTableFormatTest.java +++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeTableFormatTest.java @@ -97,7 +97,7 @@ public final strictfp class TreeTableFormatTest extends TestCase { " │ │ ├─East bound longitude…… 180°E\n" + " │ │ ├─South bound latitude…… 90°S\n" + " │ │ ├─North bound latitude…… 90°N\n" + - " │ │ └─Extent type code……………… true\n" + + " │ │ └─Extent type code……………… True\n" + " │ └─Organisation……………………………………………… Kōdansha\n" + " ├─Presentation form (1 of 2)…………………… Document digital\n" + " ├─Presentation form (2 of 2)…………………… Document hardcopy\n" + diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeTableViewTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeTableViewTest.java index 9decb78..ba323ea 100644 --- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeTableViewTest.java +++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeTableViewTest.java @@ -124,6 +124,6 @@ public final strictfp class TreeTableViewTest extends TestCase { " ├─East bound longitude…… 160°W…… Bounding box crosses the antimeridian.\n" + // See method javadoc. " ├─South bound latitude…… 30°S\n" + " ├─North bound latitude…… 40°N\n" + - " └─Extent type code……………… true\n", text); + " └─Extent type code……………… True\n", text); } } diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/extent/DefaultGeographicBoundingBoxTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/extent/DefaultGeographicBoundingBoxTest.java index 4b3d3d6..0dfa5d9 100644 --- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/extent/DefaultGeographicBoundingBoxTest.java +++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/extent/DefaultGeographicBoundingBoxTest.java @@ -33,7 +33,7 @@ import static org.apache.sis.test.Assert.*; * Tests {@link DefaultGeographicBoundingBox}. * * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.2 * @since 0.4 * @module */ @@ -444,6 +444,7 @@ public final strictfp class DefaultGeographicBoundingBoxTest extends TestCase { " ├─East bound longitude…… 50°E\n" + " ├─South bound latitude…… 20°S\n" + " ├─North bound latitude…… 45°N\n" + - " └─Extent type code……………… true\n", extent.toString()); + " └─Extent type code……………… True\n", + TestUtilities.formatMetadata(extent.asTreeTable())); } } diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/identification/DefaultDataIdentificationTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/identification/DefaultDataIdentificationTest.java index ed5ab1f..0e60c25 100644 --- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/identification/DefaultDataIdentificationTest.java +++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/identification/DefaultDataIdentificationTest.java @@ -142,7 +142,7 @@ public final strictfp class DefaultDataIdentificationTest extends TestCase { " │ ├─East bound longitude…… 180°E\n" + " │ ├─South bound latitude…… 90°S\n" + " │ ├─North bound latitude…… 90°N\n" + - " │ └─Extent type code……………… true\n" + + " │ └─Extent type code……………… True\n" + " ├─Descriptive keywords\n" + " │ ├─Keyword………………………………………………… EARTH SCIENCE > Oceans > Ocean Temperature > Sea Surface Temperature\n" + " │ ├─Type………………………………………………………… Theme\n" + diff --git a/core/sis-utility/src/main/java/org/apache/sis/internal/util/PropertyFormat.java b/core/sis-utility/src/main/java/org/apache/sis/internal/util/PropertyFormat.java index ae8272b..3fbcecf 100644 --- a/core/sis-utility/src/main/java/org/apache/sis/internal/util/PropertyFormat.java +++ b/core/sis-utility/src/main/java/org/apache/sis/internal/util/PropertyFormat.java @@ -45,12 +45,17 @@ import org.apache.sis.util.Localized; * Subclasses need to override {@link #getLocale()}, and should also override {@link #toString(Object)}. * * @author Martin Desruisseaux (Geomatys) - * @version 1.1 + * @version 1.2 * @since 1.1 * @module */ public abstract class PropertyFormat extends LineAppender implements Localized { /** + * The string to insert for missing values. + */ + private static final String MISSING = " "; + + /** * The format for the column in process of being written. This is a format to use for the column as a whole. * This field is updated for every new column to write. May be {@code null} if the format is unspecified. */ @@ -59,7 +64,7 @@ public abstract class PropertyFormat extends LineAppender implements Localized { /** * Creates a new instance which will write to the given appendable. * - * @param out where to format the tree. + * @param out where to format the objects. */ protected PropertyFormat(final Appendable out) { super(out); @@ -76,7 +81,7 @@ public abstract class PropertyFormat extends LineAppender implements Localized { } /** - * Appends a textual representation of the given value, with a check against nested collections. + * Appends a textual representation of the given value, with a check for nested collections. * * @param value the value to format (may be {@code null}). * @param recursive {@code true} if this method is invoking itself for writing collection values. @@ -84,7 +89,7 @@ public abstract class PropertyFormat extends LineAppender implements Localized { private void appendValue(final Object value, final boolean recursive) throws IOException { final CharSequence text; if (value == null) { - text = " "; // String for missing value. + text = MISSING; } else if (columnFormat != null) { if (columnFormat instanceof CompoundFormat<?>) { appendCompound((CompoundFormat<?>) columnFormat, value); @@ -92,11 +97,13 @@ public abstract class PropertyFormat extends LineAppender implements Localized { } text = columnFormat.format(value); } else if (value instanceof InternationalString) { - text = ((InternationalString) value).toString(getLocale()); + text = freeText(((InternationalString) value).toString(getLocale())); } else if (value instanceof CharSequence) { - text = value.toString(); + text = freeText(value.toString()); } else if (value instanceof ControlledVocabulary) { text = MetadataServices.getInstance().getCodeTitle((ControlledVocabulary) value, getLocale()); + } else if (value instanceof Boolean) { + text = Vocabulary.getResources(getLocale()).getString((Boolean) value ? Vocabulary.Keys.True : Vocabulary.Keys.False); } else if (value instanceof Enum<?>) { text = CharSequences.upperCaseToSentence(((Enum<?>) value).name()); } else if (value instanceof Type) { @@ -155,7 +162,23 @@ public abstract class PropertyFormat extends LineAppender implements Localized { * @return the formatted value. */ protected String toString(final Object value) { - return value.toString(); + return freeText(value.toString()); + } + + /** + * Invoked after formatting a text that could be anything. It current version, it includes all kinds of + * {@link CharSequence} including {@link InternationalString}, together with {@link Object#toString()} + * values computed by the default {@link #toString(Object)} implementation. + * + * The default {@code freeText(…)} implementation removes white space and control characters. + * Subclasses can override for example for making a text shorter. + * + * @param text the free text, or {@code null}. + * @return the text to append. + */ + protected String freeText(final String text) { + // Really want `trim()` because there is sometime control characters to remove. + return (text != null) ? text.trim() : MISSING; } /** diff --git a/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java b/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java index a6c6a4d..fbddfdb 100644 --- a/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java +++ b/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java @@ -703,7 +703,7 @@ public class TreeTableFormat extends TabularFormat<TreeTable> { */ @Override public Locale getLocale() { - return getDisplayLocale(); + return TreeTableFormat.this.getLocale(); } /** diff --git a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java index 79228c2..97b2e11 100644 --- a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java +++ b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java @@ -505,6 +505,11 @@ public final class Vocabulary extends IndexedResourceBundle { public static final short Extent = 81; /** + * False + */ + public static final short False = 264; + + /** * File */ public static final short File = 82; @@ -1240,6 +1245,11 @@ public final class Vocabulary extends IndexedResourceBundle { public static final short Transparent = 249; /** + * True + */ + public static final short True = 265; + + /** * Truncated Julian */ public static final short TruncatedJulian = 202; diff --git a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties index 12e78be..3737547 100644 --- a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties +++ b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties @@ -104,6 +104,7 @@ EntryCount_1 = {0} entr{0,choice,0#y|2#ies} Envelope = Envelope Errors = Errors Extent = Extent +False = False File = File FillValue = Fill value Filter = Filter @@ -252,6 +253,7 @@ TransformationAccuracy = Transformation accuracy Transparency = Transparency Transparent = Transparent TruncatedJulian = Truncated Julian +True = True Type = Type TypeOfResource = Type of resource Units = Units diff --git a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties index 14c5138..959ad86 100644 --- a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties +++ b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties @@ -111,6 +111,7 @@ EntryCount_1 = {0} entr\u00e9e{0,choice,0#|2#s} Envelope = Enveloppe Errors = Erreurs Extent = \u00c9tendue +False = Faux File = Fichier FillValue = Valeur de remplissage Filter = Filtre @@ -259,6 +260,7 @@ TransformationAccuracy = Pr\u00e9cision de la transformation Transparency = Transparence Transparent = Transparent TruncatedJulian = Julien tronqu\u00e9 +True = Vrai Type = Type TypeOfResource = Type de ressource Units = Unit\u00e9s