This is an automated email from the ASF dual-hosted git repository. asf-gitbox-commits pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
commit 0d5e5d119de637d4e635ef656ed244f2ac007d8b Author: Martin Desruisseaux <[email protected]> AuthorDate: Mon May 18 14:50:54 2026 +0200 Fix an anomaly in the display of the tree of GeoHEIF boxes. --- .../org/apache/sis/metadata/TreeTableView.java | 2 +- .../sis/util/internal/shared/TreeTableForGUI.java | 2 +- .../org/apache/sis/storage/isobmff/Extension.java | 2 +- .../apache/sis/storage/isobmff}/NodeSummary.java | 8 +- .../org/apache/sis/storage/isobmff/TreeNode.java | 112 ++++++++++----------- .../isobmff/geo/TiledImageConfiguration.java | 6 +- 6 files changed, 64 insertions(+), 68 deletions(-) diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/TreeTableView.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/TreeTableView.java index 56fbb43c45..c01f9cea09 100644 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/TreeTableView.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/TreeTableView.java @@ -126,7 +126,7 @@ final class TreeTableView implements TreeTableForGUI, Serializable { } /** - * Returns whether the given value produces by the given node is a title. + * Returns whether the given value produced by the given node is a title. */ @Override public boolean isNodeTitle(final Node node, final Object value) { diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/shared/TreeTableForGUI.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/shared/TreeTableForGUI.java index 9a7f40eb96..25e748ce33 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/shared/TreeTableForGUI.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/shared/TreeTableForGUI.java @@ -26,7 +26,7 @@ import org.apache.sis.util.collection.TreeTable; */ public interface TreeTableForGUI extends TreeTable { /** - * Returns whether the given value produces by the given node is a title. + * Returns whether the given value produced by the given node is a title. * Title are a short description of the node, typically copied from one of the children. * For example for the code of a {@code Citation} object, this is the {@code title} property. * diff --git a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/isobmff/Extension.java b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/isobmff/Extension.java index 0bedee9003..caf43a0418 100644 --- a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/isobmff/Extension.java +++ b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/isobmff/Extension.java @@ -74,6 +74,6 @@ public abstract class Extension extends Box { @Override protected void prependTreeNodes(final TreeBuilder tree, final TreeTable.Node target) { super.prependTreeNodes(tree, target); - tree.addNode(target, "extendedType", extendedType()); + tree.addNode(target, "extended type", extendedType()); } } diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/metadata/NodeSummary.java b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/isobmff/NodeSummary.java similarity index 90% rename from endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/metadata/NodeSummary.java rename to incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/isobmff/NodeSummary.java index 7634c498ad..d8276d245c 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/metadata/NodeSummary.java +++ b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/isobmff/NodeSummary.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.sis.storage.metadata; +package org.apache.sis.storage.isobmff; import org.apache.sis.util.SimpleInternationalString; @@ -28,7 +28,7 @@ import org.apache.sis.util.SimpleInternationalString; * * @see org.apache.sis.metadata.TitleProperty */ -public final class NodeSummary extends SimpleInternationalString { +final class NodeSummary extends SimpleInternationalString { /** * Serial number for inter-operability with different versions. */ @@ -39,7 +39,7 @@ public final class NodeSummary extends SimpleInternationalString { * * @param text the string for all locales. */ - private NodeSummary(final String text) { + NodeSummary(final String text) { super(text); } @@ -49,7 +49,7 @@ public final class NodeSummary extends SimpleInternationalString { * @param text the text to wrap, or {@code null}. * @return the wrapped text, or {@code null} if the given text was null. */ - public static NodeSummary of(final CharSequence text) { + static NodeSummary of(final CharSequence text) { if (text == null || text instanceof NodeSummary) { return (NodeSummary) text; } else { diff --git a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/isobmff/TreeNode.java b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/isobmff/TreeNode.java index 510c2125ba..0bd7b6134e 100644 --- a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/isobmff/TreeNode.java +++ b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/isobmff/TreeNode.java @@ -45,7 +45,6 @@ import org.apache.sis.util.internal.shared.PropertyFormat; import org.apache.sis.util.internal.shared.TreeTableForGUI; import org.apache.sis.storage.isobmff.base.ItemInfoEntry; import org.apache.sis.storage.geoheif.GeoHeifStore; -import org.apache.sis.storage.metadata.NodeSummary; /** @@ -113,21 +112,7 @@ public abstract class TreeNode { */ IDENTIFIER { @Override String format(final TreeBuilder tree, final Number value) { - return Long.toUnsignedString(switch (value) { - case Byte i -> Byte .toUnsignedLong(i); - case Short i -> Short .toUnsignedLong(i); - case Integer i -> Integer.toUnsignedLong(i); - default -> value.longValue(); - }); - } - - @Override CharSequence summary(final TreeBuilder tree, final Number value, final String text) { - final String name = tree.getItemName(value); - if (name != null) { - // Do not wrap in `NodeSummary` because we want to keep that name always visible. - return name; - } - return super.summary(tree, value, text); + return formatUnsigned(value); } }, @@ -162,18 +147,6 @@ public abstract class TreeNode { return tree.integerFormat.format(value); } - /** - * Returns the text to show as the summary of a node when the node is collapsed. - * - * @param tree builder of the tree to format. - * @param value the integer value which has been formatted. - * @param text the {@link #format(TreeBuilder, Number)} result. - * @return text to show as a summary of a collapsed node. - */ - CharSequence summary(final TreeBuilder tree, final Number value, final String text) { - return NodeSummary.of(text); - } - /** * Returns the value of the given annotation, or {@code null} if none. * @@ -206,6 +179,21 @@ public abstract class TreeNode { }, StandardCharsets.ISO_8859_1).trim(); } + /** + * Returns the string representation of the given number interpreted as an unsigned integer. + * + * @param value the value to format as an unsigned integer. + * @return the formatted value. + */ + static String formatUnsigned(final Number value) { + return Long.toUnsignedString(switch (value) { + case Byte i -> Byte .toUnsignedLong(i); + case Short i -> Short .toUnsignedLong(i); + case Integer i -> Integer.toUnsignedLong(i); + default -> value.longValue(); + }); + } + /** * Creates a new box or item. */ @@ -286,7 +274,7 @@ public abstract class TreeNode { } /** - * Returns whether the given value produces by the given node is a title. + * Returns whether the given value produced by the given node is a title. */ @Override public boolean isNodeTitle(final TreeTable.Node node, final Object value) { @@ -453,9 +441,7 @@ public abstract class TreeNode { if (value instanceof TreeNode[]) { for (final TreeNode child : (TreeNode[]) value) { if (child != null) { - final TreeTable.Node node = target.newChild(); - node.setValue(TableColumn.NAME, child.typeName()); - appendProperties(child, node); + appendProperties(child, addNode(target, child.typeName(), child, null)); } } } else if (value.getClass().isArray()) { @@ -465,7 +451,13 @@ public abstract class TreeNode { * the names of the identified items. */ final Type type = Type.of(field.getAnnotation(Interpretation.class)); - final TreeTable.Node addTo = (type == Type.IDENTIFIER) ? addNode(target, field, value) : null; + final TreeTable.Node addTo; + if (type == Type.IDENTIFIER) { + addTo = addNode(target, camelCaseToWords(field), value, null); + // No `VALUE_AS_TEXT` because this is an array that we will develop below. + } else { + addTo = null; + } final var values = new String[Array.getLength(value)]; for (int i=0; i < values.length; i++) { final Object element = Array.get(value, i); @@ -473,7 +465,7 @@ public abstract class TreeNode { if (type != null) { final var n = (Number) element; if (addTo != null) { - addNode(addTo, Type.UNSIGNED.format(this, n), n, getItemName(n)); + addNode(addTo, formatUnsigned(n), n, getItemName(n)); } else { values[i] = type.format(this, n); } @@ -483,16 +475,16 @@ public abstract class TreeNode { } } if (addTo == null) { - addNode(target, field.getName(), value, String.join(", ", values)); + addNode(target, camelCaseToWords(field), value, String.join(", ", values)); } } else { /* - * Case of a single element. + * Case where the property is a single element (not an array). * Identifier codes will be converted to their four-character code (4CC) representations. * The fields to convert to 4CC are identified by the `@Interpretation` annotation. */ if (value instanceof TreeNode addTo) { - appendProperties(addTo, addNode(target, field, value)); + appendProperties(addTo, addNode(target, camelCaseToWords(field), addTo, null)); } else { final Interpretation itpr = field.getAnnotation(Interpretation.class); final Type type = Type.of(itpr); @@ -503,10 +495,20 @@ public abstract class TreeNode { text = formatUsingStringBuilder(value); } if (text != null) { - addNode(target, field.getName(), value, text); + addNode(target, camelCaseToWords(field), value, text); } + /* + * If the field is annotated with `Interpretation(…, summary=true)`, + * take the field value is a summary of the whole node. + */ if (summary == null && withSummary && itpr != null && itpr.summary()) { - summary = (type != null) ? type.summary(this, (Number) value, text) : text; + if (type == Type.IDENTIFIER) { + String name = getItemName((Number) value); + if (name != null) summary = name; + // Do not wrap in `NodeSummary` because we want that name always visible. + } else if (text != null) { + summary = new NodeSummary(text); + } } } } @@ -529,11 +531,11 @@ public abstract class TreeNode { } /** - * Convenience method for adding a child node. + * Convenience method for adding a child node if the given value is non-null. * - * @param target where to add the node. - * @param name the programmatic (camel-case) name of the node. - * @param value value of the node, or {@code null} if none. + * @param target where to add the node. + * @param name name of the node or property to add. + * @param value value of the node, or {@code null} for skipping the node. */ public final void addNode(final TreeTable.Node target, final String name, final Object value) { if (value != null) { @@ -545,33 +547,27 @@ public abstract class TreeNode { * Convenience method for adding a child node. * * @param target where to add the node. - * @param name the programmatic (camel-case) name of the node. - * @param value value of the node. Should not be null. - * @param valueAsText string representation of the value. + * @param name name of the node or property to add. + * @param value value of the node, or {@code null} for a node without value. + * @param valueAsText string representation of the value, or {@code null} if none. * @return the node which has been added. */ public static TreeTable.Node addNode(final TreeTable.Node target, String name, Object value, String valueAsText) { final TreeTable.Node child = target.newChild(); - child.setValue(TableColumn.NAME, CharSequences.camelCaseToWords(name, true).toString()); + child.setValue(TableColumn.NAME, name); child.setValue(TableColumn.VALUE, value); child.setValue(TableColumn.VALUE_AS_TEXT, valueAsText); return child; } /** - * Adds a node for a field. The {@code NAME} and {@code VALUE} columns are set to values - * derived from the given arguments. The {@code VALUE_AS_TEXT} column is left {@code null}. + * Returns the name of the given field with camel-case converted to a sentence of words. * - * @param target where to add the node. - * @param field field of the property to represent as a node. - * @param value value of the property to represent as a node. - * @return the node which has been added. + * @param field the field for which to get the name. + * @return field name as a sequence of words. */ - private static TreeTable.Node addNode(final TreeTable.Node target, final Field field, final Object value) { - final TreeTable.Node child = target.newChild(); - child.setValue(TableColumn.NAME, CharSequences.camelCaseToWords(field.getName(), false).toString()); - child.setValue(TableColumn.VALUE, value); - return child; + private static String camelCaseToWords(final Field field) { + return CharSequences.camelCaseToWords(field.getName(), false).toString(); } } diff --git a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/isobmff/geo/TiledImageConfiguration.java b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/isobmff/geo/TiledImageConfiguration.java index d12d1284c5..94b9bb993f 100644 --- a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/isobmff/geo/TiledImageConfiguration.java +++ b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/isobmff/geo/TiledImageConfiguration.java @@ -157,8 +157,8 @@ public final class TiledImageConfiguration extends FullBox { */ @Override protected void appendFlagDescriptions(final TreeBuilder tree, final TreeTable.Node target) { - tree.addNode(target, "offsetFieldLength", offsetFieldLength()); - tree.addNode(target, "sizeFieldLength", sizeFieldLength()); - tree.addNode(target, "sequential", sequential()); + tree.addNode(target, "offset field length", offsetFieldLength()); + tree.addNode(target, "size field length", sizeFieldLength()); + tree.addNode(target, "sequential", sequential()); } }
