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 7d3d5c36483c43fbd191f5683b50fdb9ae61231a Author: Martin Desruisseaux <[email protected]> AuthorDate: Fri Sep 12 14:09:46 2025 +0200 Fix warnings emitted during the parsing of units of measurement in some netCDF files. contains also a dependency upgrade and fix in the metadata display in GUI. --- .../sis/openoffice/ReferencingFunctions.java | 4 +- .../org/apache/sis/openoffice/package-info.java | 2 +- .../apache/sis/storage/netcdf/MetadataReader.java | 1 + .../org/apache/sis/storage/netcdf/base/Axis.java | 2 +- .../apache/sis/storage/netcdf/base/AxisType.java | 32 ++++++----- .../apache/sis/storage/netcdf/base/FeatureSet.java | 2 +- .../storage/netcdf/base/VariableTransformer.java | 2 +- .../sis/storage/netcdf/classic/GridInfo.java | 2 +- .../sis/storage/netcdf/ucar/GridWrapper.java | 2 +- .../sis/storage/netcdf/ucar/VariableWrapper.java | 6 +- .../org/apache/sis/measure/UnitAliases.properties | 8 +-- .../main/org/apache/sis/measure/UnitFormat.java | 44 +++++++++------ .../apache/sis/measure/UnitNames_en_US.properties | 3 + .../org/apache/sis/util/resources/Vocabulary.java | 5 ++ .../sis/util/resources/Vocabulary.properties | 1 + .../sis/util/resources/Vocabulary_fr.properties | 1 + .../org/apache/sis/measure/UnitFormatTest.java | 66 +++++++++++++--------- netbeans-project/ivy.xml | 2 +- .../apache/sis/gui/metadata/MetadataSummary.java | 19 +++++-- .../sis/gui/metadata/RepresentationInfo.java | 15 +++-- settings.gradle.kts | 2 +- 21 files changed, 136 insertions(+), 85 deletions(-) diff --git a/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java b/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java index 21cfa71560..1cf4c66e88 100644 --- a/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java +++ b/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java @@ -55,9 +55,10 @@ import org.opengis.referencing.ObjectDomain; * * @author Richard Deplanque (IRD) * @author Martin Desruisseaux (IRD, Geomatys) - * @version 0.8 + * @version 1.5 * @since 0.8 */ +@SuppressWarnings("UseSpecificCatch") public class ReferencingFunctions extends CalcAddins implements XReferencing { /** * The name for the registration of this component. @@ -202,7 +203,6 @@ public class ReferencingFunctions extends CalcAddins implements XReferencing { */ @Override public String getScope(final String codeOrPath) { - final Object value; try { final IdentifiedObject object = getIdentifiedObject(codeOrPath, null); for (final ObjectDomain domain : object.getDomains()) { diff --git a/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/package-info.java b/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/package-info.java index 8e0786e80c..565f8a8566 100644 --- a/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/package-info.java +++ b/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/package-info.java @@ -25,7 +25,7 @@ * See {@code endorsed/src/org.apache.sis.openoffice/bundle/build-instruction.html} for more information.</p> * * @author Martin Desruisseaux (IRD, Geomatys) - * @version 0.8 + * @version 1.5 * @since 0.8 */ package org.apache.sis.openoffice; diff --git a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/MetadataReader.java b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/MetadataReader.java index 60b84000e1..46f308255b 100644 --- a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/MetadataReader.java +++ b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/MetadataReader.java @@ -691,6 +691,7 @@ split: while ((start = CharSequences.skipLeadingWhitespaces(value, start, lengt * @throws ArithmeticException if the size of an axis exceeds {@link Integer#MAX_VALUE}, or other overflow occurs. */ private void addSpatialRepresentationInfo(final Axis[] axes) throws IOException, DataStoreException { + newGridRepresentation(GridType.UNSPECIFIED); for (int i=0; i<axes.length; i++) { final Axis axis = axes[i]; /* diff --git a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Axis.java b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Axis.java index 5057c537b6..0b41178fa9 100644 --- a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Axis.java +++ b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Axis.java @@ -170,7 +170,7 @@ public final class Axis extends NamedElement { */ Axis(final Variable coordinates) { this.coordinates = coordinates; - abbreviation = AxisType.abbreviation(coordinates); + abbreviation = AxisType.abbreviation(coordinates, true); final AxisDirection dir = direction(coordinates.getUnitsString()); direction = (dir != null) ? dir : AxisDirections.fromAbbreviation(abbreviation); gridDimensionIndices = null; diff --git a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/AxisType.java b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/AxisType.java index fca5b97b5c..94e7a073e1 100644 --- a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/AxisType.java +++ b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/AxisType.java @@ -118,12 +118,13 @@ public enum AxisType { * Returns the axis type (identified by its abbreviation) for the given axis, or 0 if unknown. * The returned code is one of the controlled vocabulary documented in {@link Axis#abbreviation}. * - * @param axis axis for which to get an abbreviation. + * @param axis axis for which to get an abbreviation. + * @param useUnit whether this method is allowed to check the unit of measurement. * @return abbreviation for the given axis, or 0 if none. * * @see <a href="https://issues.apache.org/jira/browse/SIS-552">SIS-552</a> */ - public static char abbreviation(final Variable axis) { + public static char abbreviation(final Variable axis, final boolean useUnit) { /* * In Apache SIS implementation, the abbreviation determines the axis type. If a "_CoordinateAxisType" attribute * exists, il will have precedence over all other heuristic rules in this method because it is the most specific @@ -151,7 +152,7 @@ public enum AxisType { * already verified by Axis constructor. By checking the variable attributes first, we give a chance * to Axis constructor to report a warning if there is an inconsistency. */ - if (Units.isAngular(axis.getUnit())) { + if (useUnit && Units.isAngular(axis.getUnit())) { final AxisDirection direction = AxisDirections.absolute(Axis.direction(axis.getUnitsString())); if (direction == AxisDirection.EAST) { return 'λ'; @@ -166,16 +167,15 @@ public enum AxisType { abbreviation = abbreviation(axis.getName()); if (fallback == null) fallback = abbreviation; if (isNullOrAmbiguous(abbreviation)) { - final Unit<?> unit = axis.getUnit(); - if (Units.isTemporal(unit)) { - return 't'; - } else if (Units.isPressure(unit)) { - return 'z'; - } else if (fallback != null) { - return fallback; - } else { - return 0; + if (useUnit) { + final Unit<?> unit = axis.getUnit(); + if (Units.isTemporal(unit)) { + return 't'; + } else if (Units.isPressure(unit)) { + return 'z'; + } } + return (fallback != null) ? fallback : 0; } } } @@ -185,9 +185,13 @@ public enum AxisType { /** * Returns the enumeration value for the given variable, or {@code null} if none. + * + * @param axis axis for which to get an enumeration value. + * @param useUnit whether this method is allowed to check the unit of measurement. + * @return enumeration value for the given axis, or {@code null} if none. */ - static AxisType valueOf(final Variable axis) { - final char abbreviation = abbreviation(axis); + static AxisType valueOf(final Variable axis, final boolean useUnit) { + final char abbreviation = abbreviation(axis, useUnit); return (abbreviation != 0) ? VALUES.get(abbreviation) : null; } } diff --git a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/FeatureSet.java b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/FeatureSet.java index dd5789ef2a..4bd81d41ca 100644 --- a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/FeatureSet.java +++ b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/FeatureSet.java @@ -432,7 +432,7 @@ final class FeatureSet extends DiscreteSampling { * We handle separately the axes having coordinates provided by static and dynamic properties. * We will decide at the end of this loop which one of those two groups to use. */ - final AxisType axisType = AxisType.valueOf(data); + final AxisType axisType = AxisType.valueOf(data, true); if (axisType != null) { final Variable previous = (dynamic ? trajectory : coordinates).putIfAbsent(axisType, data); if (previous != null) { diff --git a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/VariableTransformer.java b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/VariableTransformer.java index a40600866b..8eff98382b 100644 --- a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/VariableTransformer.java +++ b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/VariableTransformer.java @@ -191,7 +191,7 @@ final class VariableTransformer { matchers = new Matcher[candidates.length]; } for (final UnitPattern candidate : candidates) { - if (!candidate.requireTimeAxis || AxisType.valueOf(variable) == AxisType.T) { + if (!candidate.requireTimeAxis || AxisType.valueOf(variable, false) == AxisType.T) { Matcher matcher = matchers[candidate.ordinal()]; if (matcher == null) { matcher = candidate.pattern.matcher(units); diff --git a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/GridInfo.java b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/GridInfo.java index 1596467eac..3f1b9d97f2 100644 --- a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/GridInfo.java +++ b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/GridInfo.java @@ -221,7 +221,7 @@ next: for (final String name : axisNames) { } } } - final char abbreviation = AxisType.abbreviation(axis); + final char abbreviation = AxisType.abbreviation(axis, true); axes[targetDim] = new Axis(abbreviation, axis.getAttributeAsString(CF.POSITIVE), indices, sizes, i, axis); } return axes; diff --git a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/GridWrapper.java b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/GridWrapper.java index e893ac60e0..d2fe64b757 100644 --- a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/GridWrapper.java +++ b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/GridWrapper.java @@ -280,7 +280,7 @@ next: for (final String name : axisNames) { case RadialDistance: abbreviation = 'r'; break; // Geocentric radius } if (abbreviation == 0) { - abbreviation = org.apache.sis.storage.netcdf.base.AxisType.abbreviation(wrapper); + abbreviation = org.apache.sis.storage.netcdf.base.AxisType.abbreviation(wrapper, true); } /* * Get the grid dimensions (part of the "domain" in UCAR terminology) used for computing diff --git a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/VariableWrapper.java b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/VariableWrapper.java index 24a5cb3753..7cc300f3dd 100644 --- a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/VariableWrapper.java +++ b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/VariableWrapper.java @@ -171,7 +171,7 @@ final class VariableWrapper extends org.apache.sis.storage.netcdf.base.Variable * "2 hours since 1970-01-01 00:00:00". If there is no such number, then the two methods * are equivalent. It is not clear that adding such number is the right thing to do. */ - final DateUnit temporal = new DateUnit(symbols); + final var temporal = new DateUnit(symbols); epoch = temporal.getDateOrigin().toInstant(); return Units.SECOND.multiply(temporal.getTimeUnit().getValueInSeconds()); } else { @@ -446,7 +446,7 @@ final class VariableWrapper extends org.apache.sis.storage.netcdf.base.Variable @Override protected NumberRange<?> getRangeFallback() { if (variable instanceof EnhanceScaleMissingUnsigned) { - final EnhanceScaleMissingUnsigned ev = (EnhanceScaleMissingUnsigned) variable; + final var ev = (EnhanceScaleMissingUnsigned) variable; if (ev.hasValidData()) { // Returns a MeasurementRange instance for signaling the caller that this is converted values. return MeasurementRange.create(ev.getValidMin(), true, ev.getValidMax(), true, getUnit()); @@ -618,7 +618,7 @@ final class VariableWrapper extends org.apache.sis.storage.netcdf.base.Variable throws IOException, DataStoreException { if (variable instanceof CoordinateAxis1D) { - final CoordinateAxis1D axis = (CoordinateAxis1D) variable; + final var axis = (CoordinateAxis1D) variable; if (axis.isRegular()) { final double start = axis.getStart(); final double increment = axis.getIncrement(); diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitAliases.properties b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitAliases.properties index 48fd3cf3ed..4fde176ec2 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitAliases.properties +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitAliases.properties @@ -1,8 +1,10 @@ # Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements; # and to You under the Apache License, Version 2.0. -# Contains only unit names not included in UnitNames.properties. -# "degrees", "metres" and "meters" are handled as special cases. +# Contains only unit names not included in the "UnitNames.properties" file. +# Some aliases are the plural forms of units declared in their singular form +# in "UnitNames.properties" file. Common units such as "degrees", "radians", +# "seconds", "metres" and "meters" are handled as special cases in Java code. arcsec=\u2033 days=d decibars=dbar @@ -30,8 +32,6 @@ millibar=hPa millibars=hPa minutes=min percentage=% -radians=rad -seconds=s weeks=wk # Common misspellings diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitFormat.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitFormat.java index 08c892c1de..1c200704b6 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitFormat.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitFormat.java @@ -17,7 +17,6 @@ package org.apache.sis.measure; import java.util.Map; -import java.util.List; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -555,15 +554,12 @@ public class UnitFormat extends Format implements javax.measure.format.UnitForma nameToUnit = map; } /* - * The `nameToUnit` map contains plural forms (declared in UnitAliases.properties), - * but we make a special case for "degrees", "metres" and "meters" because they - * appear in numerous places. + * The `nameToUnit` map contains plural forms (declared in "UnitAliases.properties" file), + * but we make a special case for common units such as "degrees", "radians", "seconds", + * "metres" and "meters" because they are repeated in units such as "kilometers". */ uom = uom.replace('_', ' ').toLowerCase(locale); - uom = CharSequences.replace(CharSequences.replace(CharSequences.replace(CharSequences.toASCII(uom), - "meters", "meter"), - "metres", "metre"), - DEGREES, "degree").toString(); + uom = removePlural(CharSequences.toASCII(uom)); /* * Returns the unit with application of the power if it is part of the name. * For example, this method interprets "meter2" as "meter" raised to power 2. @@ -589,16 +585,32 @@ appPow: if (unit == null) { /** * Copies all entries from the given "symbols to names" mapping to the given "names to units" mapping. * During this copy, keys are converted from symbols to names and values are converted from symbols to - * {@code Unit} instance. We use {@code Unit} values instead of their symbols because all {@code Unit} + * {@code Unit} instances. We use {@code Unit} values instead of their symbols because all {@code Unit} * instances are created at {@link Units} class initialization anyway (so we do not create new instance - * here), and it avoid to retain references to the {@link String} instances loaded by the resource bundle. + * here), and it avoids to retain references to the {@link String} instances loaded by the resource bundle. */ private static void copy(final Locale locale, final ResourceBundle symbolToName, final Map<String,Unit<?>> nameToUnit) { for (final String symbol : symbolToName.keySet()) { - nameToUnit.put(CharSequences.toASCII(symbolToName.getString(symbol).toLowerCase(locale)).toString().intern(), Units.get(symbol)); + String name = CharSequences.toASCII(symbolToName.getString(symbol).toLowerCase(locale)).toString().intern(); + nameToUnit.put(removePlural(name), Units.get(symbol)); } } + /** + * Returns the given string with common units such as "degrees", "radians", "seconds", "metres" and "meters" + * replaced by their singular forms. All these units may have a prefix, for example as in "kilometres". + * The result may not be grammatically correct English, but those strings will not be visible to users. + * This is similar to making a string in lower cases before comparison in order to be case-insensitive. + */ + private static String removePlural(CharSequence uom) { + uom = CharSequences.replace(uom, DEGREES, "degree"); + uom = CharSequences.replace(uom, "radians", "radian"); + uom = CharSequences.replace(uom, "seconds", "second"); + uom = CharSequences.replace(uom, "meters", "meter"); + uom = CharSequences.replace(uom, "metres", "metre"); + return uom.toString(); + } + /** * Formats the specified unit. * This method performs the first of the following actions that can be done. @@ -795,7 +807,7 @@ appPow: if (unit == null) { throws IOException { boolean isFirst = true; - final List<Map.Entry<?,? extends Number>> deferred = new ArrayList<>(components.size()); + final var deferred = new ArrayList<Map.Entry<?,? extends Number>>(components.size()); for (final Map.Entry<?,? extends Number> entry : components.entrySet()) { final Number power = entry.getValue(); final int n = (power instanceof Fraction) ? ((Fraction) power).numerator : power.intValue(); @@ -1071,7 +1083,7 @@ appPow: if (unit == null) { */ @Override public Unit<?> parse(final CharSequence symbols) throws MeasurementParseException { - final Position position = new Position(); + final var position = new Position(); Unit<?> unit = parse(symbols, position); final int length = symbols.length(); int unrecognized; @@ -1156,7 +1168,7 @@ appPow: if (unit == null) { * * The `start` variable is the index of the first character of the next unit term to parse. */ - final Operation operation = new Operation(symbols); // Enumeration value: NOOP, IMPLICIT, MULTIPLY, DIVIDE. + final var operation = new Operation(symbols); // Enumeration value: NOOP, IMPLICIT, MULTIPLY, DIVIDE. Unit<?> unit = null; boolean hasSpaces = false; int i = start; @@ -1240,7 +1252,7 @@ scan: for (int n; i < end; i += n) { */ case Style.OPEN: { final int pos = i + Character.charCount(c); - final ParsePosition sub = new ParsePosition(pos); + final var sub = new ParsePosition(pos); final Unit<?> term = parse(symbols, sub); i = CharSequences.skipLeadingWhitespaces(symbols, sub.getIndex(), end); if (i >= end || Character.codePointAt(symbols, i) != Style.CLOSE) { @@ -1581,7 +1593,7 @@ search: while ((i = CharSequences.skipTrailingWhitespaces(symbols, start, i) return Double.parseDouble(term); // No exponent symbol and no superscript found. } // Example: "10⁻⁴". Split in base and exponent. - final StringBuilder buffer = new StringBuilder(s); + final var buffer = new StringBuilder(s); do { buffer.appendCodePoint(Characters.toNormalScript(c)); if ((s -= Character.charCount(c)) <= 0) break; diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitNames_en_US.properties b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitNames_en_US.properties index 94d76daee2..187486ff27 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitNames_en_US.properties +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitNames_en_US.properties @@ -2,10 +2,13 @@ # and to You under the Apache License, Version 2.0. cm=centimeter km=kilometer +km\u2215h=kilometers per hour L=liter m=meter m\u00b2=square meter m\u00b3=cubic meter +m\u2215s=meters per second +m\u2215s\u00b2=meters per second squared mi=international mile mm=millimeter nm=nanometer diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java index 5cef3e30e1..e0f372470a 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java @@ -969,6 +969,11 @@ public class Vocabulary extends IndexedResourceBundle { */ public static final short OriginalColors = 272; + /** + * Other + */ + public static final short Other = 280; + /** * Other surface */ diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties index 14dc57b6fa..3ae9fe1411 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties @@ -198,6 +198,7 @@ Options = Options Origin = Origin OriginalColors = Original colors OriginInCellCenter = Origin in a cell center +Other = Other Others = Others OtherSurface = Other surface Page_1 = Page {0} diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties index 8294ba244a..c1a58d477a 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties @@ -205,6 +205,7 @@ Options = Options Origin = Origine OriginalColors = Couleurs originales OriginInCellCenter = Origine au centre d\u2019une cellule +Other = Autre Others = Autres OtherSurface = Autre surface Page_1 = Page {0} diff --git a/endorsed/src/org.apache.sis.util/test/org/apache/sis/measure/UnitFormatTest.java b/endorsed/src/org.apache.sis.util/test/org/apache/sis/measure/UnitFormatTest.java index 12b52b6283..4aa647a8ba 100644 --- a/endorsed/src/org.apache.sis.util/test/org/apache/sis/measure/UnitFormatTest.java +++ b/endorsed/src/org.apache.sis.util/test/org/apache/sis/measure/UnitFormatTest.java @@ -58,7 +58,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void verifyUnitConstants() { - final Set<String> declared = new HashSet<>(64); + final var declared = new HashSet<String>(64); for (final Field f : Units.class.getFields()) { if (Unit.class.isAssignableFrom(f.getType())) { declared.add(f.getName()); @@ -182,7 +182,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testLabel() { - final UnitFormat f = new UnitFormat(Locale.ENGLISH); + final var f = new UnitFormat(Locale.ENGLISH); f.label(Units.METRE, "mFoo"); f.label(Units.SECOND, "sFoo"); assertEquals("mFoo", f.format(Units.METRE)); @@ -212,7 +212,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testDuplicatedLabels() { - final UnitFormat f = new UnitFormat(Locale.ENGLISH); + final var f = new UnitFormat(Locale.ENGLISH); f.label(Units.DEGREE, "deg"); f.label(Units.DEGREE, "dd"); // For "decimal degrees" roundtrip(f, "dd", "dd"); @@ -223,7 +223,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testFormatUCUM() { - final UnitFormat f = new UnitFormat(Locale.UK); + final var f = new UnitFormat(Locale.UK); f.setStyle(UnitFormat.Style.UCUM); assertEquals("m", f.format(Units.METRE)); assertEquals("km", f.format(Units.KILOMETRE)); @@ -243,7 +243,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testFormatName() { - final UnitFormat f = new UnitFormat(Locale.UK); + final var f = new UnitFormat(Locale.UK); f.setStyle(UnitFormat.Style.NAME); assertEquals("metre", f.format(Units.METRE)); assertEquals("kilometre", f.format(Units.KILOMETRE)); @@ -282,7 +282,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testFormatScaled() { - final UnitFormat f = new UnitFormat(Locale.UK); + final var f = new UnitFormat(Locale.UK); f.setStyle(UnitFormat.Style.SYMBOL); assertEquals("Mm", f.format(Units.KILOMETRE .multiply(1000))); assertEquals("10⁵⋅m", f.format(Units.KILOMETRE .multiply( 100))); @@ -299,7 +299,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testFormatPower() { - final UnitFormat f = new UnitFormat(Locale.UK); + final var f = new UnitFormat(Locale.UK); f.setStyle(UnitFormat.Style.SYMBOL); assertEquals("m²", f.format(Units.METRE .pow(2))); assertEquals("cm²", f.format(Units.CENTIMETRE.pow(2))); @@ -311,7 +311,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testFormatRatio() { - final UnitFormat f = new UnitFormat(Locale.UK); + final var f = new UnitFormat(Locale.UK); f.setStyle(UnitFormat.Style.SYMBOL); assertEquals( "m∕h", f.format(Units.METRE.divide(Units.HOUR))); assertEquals("mm∕h", f.format(Units.MILLIMETRE.divide(Units.HOUR))); @@ -323,7 +323,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testFormatUnusual() { - final UnitFormat f = new UnitFormat(Locale.UK); + final var f = new UnitFormat(Locale.UK); final Unit<?> u1 = Units.SECOND.pow(-1).multiply(3); assertEquals("3∕s", f.format(u1)); assertEquals("3⋅m∕s", f.format(Units.METRE.multiply(u1))); @@ -338,7 +338,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testUnity() { - final UnitFormat f = new UnitFormat(Locale.UK); + final var f = new UnitFormat(Locale.UK); assertEquals( "1∕m²", f.format(Units.UNITY.divide(Units.SQUARE_METRE))); assertEquals("10⁻²∕m²", f.format(Units.UNITY.divide(100).divide(Units.SQUARE_METRE))); assertEquals("%∕m²", f.format(Units.PERCENT.divide(Units.SQUARE_METRE))); @@ -402,12 +402,22 @@ public final class UnitFormatTest extends TestCase { assertSame(Units.CUBIC_METRE, f.parse("mètre cube")); } + /** + * Tests parsing of names such "metres per second". + */ + @Test + public void testParseNameWithRatio() { + final var f = new UnitFormat(Locale.UK); + assertSame(Units.METRES_PER_SECOND, f.parse("metres per second")); + assertSame(Units.METRES_PER_SECOND, f.parse("metres per seconds")); // Mispelling sometime encoutered. + } + /** * Tests parsing of names raised to some power, for example {@code "meter2"}. */ @Test public void testParseNameRaisedToPower() { - final UnitFormat f = new UnitFormat(Locale.UK); + final var f = new UnitFormat(Locale.UK); assertSame(Units.SQUARE_METRE, f.parse("meter2")); assertSame(Units.HERTZ, f.parse("second-1")); } @@ -418,7 +428,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testParseEPSG() { - final UnitFormat f = new UnitFormat(Locale.UK); + final var f = new UnitFormat(Locale.UK); assertSame(Units.METRE, f.parse("EPSG:9001")); assertSame(Units.METRE, f.parse("urn:ogc:def:uom:EPSG::9001")); assertSame(Units.METRES_PER_SECOND, f.parse("urn:ogc:def:uom:EPSG::1026")); @@ -429,7 +439,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testParseURL() { - final UnitFormat f = new UnitFormat(Locale.UK); + final var f = new UnitFormat(Locale.UK); assertSame(Units.METRE, f.parse("http://www.opengis.net/def/uom/EPSG/0/9001")); assertSame(Units.DAY, f.parse("http://www.opengis.net/def/uom/UCUM/0/d")); } @@ -439,7 +449,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testParseSymbol() { - final UnitFormat f = new UnitFormat(Locale.UK); + final var f = new UnitFormat(Locale.UK); assertSame(Units.METRE, f.parse("m")); assertSame(Units.UNITY, f.parse("m⁰")); assertSame(Units.METRE, f.parse("m¹")); @@ -461,7 +471,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testParsePrefix() { - final UnitFormat f = new UnitFormat(Locale.UK); + final var f = new UnitFormat(Locale.UK); ConventionalUnitTest.verify(Units.JOULE, f.parse("kJ"), "kJ", 1E+3); ConventionalUnitTest.verify(Units.HERTZ, f.parse("MHz"), "MHz", 1E+6); ConventionalUnitTest.verify(Units.PASCAL, f.parse("daPa"), "daPa", 1E+1); @@ -494,7 +504,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testParseTerms() { - final UnitFormat f = new UnitFormat(Locale.UK); + final var f = new UnitFormat(Locale.UK); assertSame(Units.SQUARE_METRE, f.parse("m⋅m")); assertSame(Units.CUBIC_METRE, f.parse("m⋅m⋅m")); assertSame(Units.CUBIC_METRE, f.parse("m²⋅m")); @@ -510,7 +520,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testParseTermsSeparatedBySpace() { - final UnitFormat f = new UnitFormat(Locale.UK); + final var f = new UnitFormat(Locale.UK); assertSame(Units.METRES_PER_SECOND, f.parse("m s**-1")); assertEqualsIgnoreSymbol(Units.KILOGRAM.divide(Units.SQUARE_METRE), f.parse("kg m**-2")); @@ -525,7 +535,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testParseMultiplier() { - final UnitFormat f = new UnitFormat(Locale.UK); + final var f = new UnitFormat(Locale.UK); assertSame(Units.MILLIMETRE, f.parse("m/1000")); assertSame(Units.KILOMETRE, f.parse( "1000*m")); assertSame(Units.KILOMETRE, f.parse( "1000.0*m")); @@ -548,7 +558,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testParseKilogram() { - final UnitFormat f = new UnitFormat(Locale.UK); + final var f = new UnitFormat(Locale.UK); /* * Kilograms should be identified even if they appear in an expression. * Current implementation creates a symbol early when it detects such case. @@ -562,7 +572,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testParseInverseL() { - final UnitFormat f = new UnitFormat(Locale.UK); + final var f = new UnitFormat(Locale.UK); final Unit<?> u = f.parse("1/l"); assertEquals("1∕L", u.toString()); } @@ -574,7 +584,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testParseExponentiation() { - final UnitFormat f = new UnitFormat(Locale.UK); + final var f = new UnitFormat(Locale.UK); assertSame(Units.HERTZ, f.parse("s^-1")); assertSame(Units.HERTZ, f.parse("s**-1")); assertSame(Units.METRES_PER_SECOND, f.parse("m*s^-1")); @@ -586,7 +596,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testParseWithParenthesis() { - final UnitFormat f = new UnitFormat(Locale.UK); + final var f = new UnitFormat(Locale.UK); assertSame(Units.PASCAL, f.parse("kg∕(m⋅s²)")); assertSame(Units.PASCAL, f.parse("(kg)∕m∕s²")); assertSame(Units.VOLT, f.parse("kg⋅m²∕(s³⋅A)")); @@ -599,8 +609,8 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testParsePosition() { - final UnitFormat f = new UnitFormat(Locale.UK); - final ParsePosition pos = new ParsePosition(4); + final var f = new UnitFormat(Locale.UK); + final var pos = new ParsePosition(4); assertSame(Units.CENTIMETRE, f.parse("ABC cm foo", pos)); assertEquals( 6, pos.getIndex(), "ParsePosition.getIndex()"); assertEquals(-1, pos.getErrorIndex(), "ParsePosition.getErrorIndex()"); @@ -620,7 +630,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testClone() { - final UnitFormat f1 = new UnitFormat(Locale.FRANCE); + final var f1 = new UnitFormat(Locale.FRANCE); f1.label(Units.METRE, "myMeterLabel"); f1.label(Units.SECOND, "mySecondLabel"); final UnitFormat f2 = f1.clone(); @@ -643,7 +653,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void testParseAndFormat() { - final UnitFormat f = new UnitFormat(Locale.UK); + final var f = new UnitFormat(Locale.UK); roundtrip(f, "K.m2.kg-1.s-1", "K⋅m²∕(kg⋅s)"); roundtrip(f, "m.m6.m-3", "m⋅m⁶∕m³"); roundtrip(f, "Pa.s-1", "Pa∕s"); @@ -713,7 +723,7 @@ public final class UnitFormatTest extends TestCase { public void testParseAndFormatLabel() { final Unit<Length> yard = Units.METRE.multiply(0.9144); final Unit<?> yard2 = yard.pow(2); - final UnitFormat f = new UnitFormat(Locale.ENGLISH); + final var f = new UnitFormat(Locale.ENGLISH); f.label(yard, "yd"); roundtrip(f, "yd", "yd", yard); roundtrip(f, "yd**2", "yd²", yard2); @@ -733,7 +743,7 @@ public final class UnitFormatTest extends TestCase { */ @Test public void needForImprovements() { - final UnitFormat f = new UnitFormat(Locale.UK); + final var f = new UnitFormat(Locale.UK); roundtrip(f, "kg.kg-1.m.s-1", "m∕s"); roundtrip(f, "(m2.s.sr)-1", "1∕(m²⋅s)"); roundtrip(f, "m-2.s.rad-1", "s∕m²"); diff --git a/netbeans-project/ivy.xml b/netbeans-project/ivy.xml index 84d86ca69e..489f8cf876 100644 --- a/netbeans-project/ivy.xml +++ b/netbeans-project/ivy.xml @@ -23,7 +23,7 @@ <dependency org="joda-time" name="joda-time" rev="2.10.3"/> <dependency org="com.google.guava" name="guava" rev="30.1-jre"/> <dependency org="org.libreoffice" name="libreoffice" rev="24.8.4"/> - <dependency org="software.amazon.awssdk" name="s3" rev="2.31.68"/> + <dependency org="software.amazon.awssdk" name="s3" rev="2.33.4"/> <dependency org="org.antlr" name="antlr4-maven-plugin" rev="4.13.2"/> <dependency org="jakarta.servlet" name="jakarta.servlet-api" rev="6.1.0"/> <dependency org="org.osgi" name="osgi.core" rev="8.0.0"/> diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/MetadataSummary.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/MetadataSummary.java index b63d30c961..b2f5931f8e 100644 --- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/MetadataSummary.java +++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/MetadataSummary.java @@ -16,6 +16,7 @@ */ package org.apache.sis.gui.metadata; +import java.util.Locale; import java.util.Collection; import java.util.StringJoiner; import javafx.application.Platform; @@ -54,7 +55,7 @@ import org.opengis.util.ControlledVocabulary; * * @author Smaniotto Enzo (GSoC) * @author Martin Desruisseaux (Geomatys) - * @version 1.3 + * @version 1.5 * @since 1.1 */ @DefaultProperty("metadata") @@ -126,7 +127,7 @@ public class MetadataSummary extends Widget { @SuppressWarnings("this-escape") // `this` appears in a cyclic graph. public MetadataSummary() { vocabulary = Vocabulary.forLocale(null); - formats = new VerboseFormats(vocabulary.getLocale()); + formats = new VerboseFormats(getLocale()); information = new TitledPane[] { // If order is modified, revisit `getIdentificationInfo()`. new TitledPane(vocabulary.getString(Vocabulary.Keys.ResourceIdentification), new IdentificationInfo(this)), @@ -303,7 +304,7 @@ public class MetadataSummary extends Widget { private static void applyChange(final ObservableValue<? extends Metadata> property, final Metadata oldValue, final Metadata metadata) { - final MetadataSummary s = (MetadataSummary) ((SimpleObjectProperty<?>) property).getBean(); + final var s = (MetadataSummary) ((SimpleObjectProperty<?>) property).getBean(); s.getter = null; // In case this method is invoked before `Getter` completed. s.error = null; if (metadata != oldValue) { @@ -318,7 +319,7 @@ public class MetadataSummary extends Widget { */ int i = 0; for (TitledPane pane : s.information) { - final Section<?> info = (Section<?>) pane.getContent(); + final var info = (Section<?>) pane.getContent(); info.setInformation(metadata); final boolean isEmpty = info.isEmpty(); final boolean isPresent = (i < children.size()) && children.get(i) == pane; @@ -364,6 +365,14 @@ public class MetadataSummary extends Widget { * Returns the given international string as a non-empty localized string, or {@code null} if none. */ final String string(final InternationalString i18n) { - return (i18n != null) ? Strings.trimOrNull(i18n.toString(vocabulary.getLocale())) : null; + return (i18n != null) ? Strings.trimOrNull(i18n.toString(getLocale())) : null; + } + + /** + * Returns the locale used by this widget for controls and messages. + */ + @Override + public final Locale getLocale() { + return vocabulary.getLocale(); } } diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/RepresentationInfo.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/RepresentationInfo.java index 616df94d48..c286a36177 100644 --- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/RepresentationInfo.java +++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/RepresentationInfo.java @@ -77,7 +77,7 @@ final class RepresentationInfo extends Section<SpatialRepresentation> { if (info instanceof GridSpatialRepresentation) { build((GridSpatialRepresentation) info); } - addLine(Vocabulary.Keys.ReferenceSystem, IdentifiedObjects.getDisplayName(referenceSystem, owner.vocabulary.getLocale())); + addLine(Vocabulary.Keys.ReferenceSystem, IdentifiedObjects.getDisplayName(referenceSystem, owner.getLocale())); } /** @@ -89,19 +89,24 @@ final class RepresentationInfo extends Section<SpatialRepresentation> { */ private void build(final GridSpatialRepresentation info) { addLine(Vocabulary.Keys.NumberOfDimensions, owner.format(info.getNumberOfDimensions())); - final StringBuffer gridSize = new StringBuffer(20); - final StringBuffer resolution = new StringBuffer(20); + final var gridSize = new StringBuffer(20); + final var resolution = new StringBuffer(20); + boolean hasName = false; for (final Dimension dim : nonNull(info.getAxisDimensionProperties())) { - final String name = owner.string(Types.getCodeTitle(dim.getDimensionName())); + String name = owner.string(Types.getCodeTitle(dim.getDimensionName())); final Integer size = dim.getDimensionSize(); if (name != null || size != null) { if (gridSize.length() != 0) { gridSize.append(" × "); } owner.format(size, gridSize); + if (hasName && name == null) { + name = owner.vocabulary.getString(Vocabulary.Keys.Other); + } if (name != null) { if (size != null) gridSize.append(' '); - gridSize.append(name); + gridSize.append(name.toLowerCase(owner.getLocale())); + hasName = true; } } final Double r = dim.getResolution(); diff --git a/settings.gradle.kts b/settings.gradle.kts index 0c19c8e84b..c173374243 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -68,7 +68,7 @@ dependencyResolutionManagement { library("esri.geometry", "com.esri.geometry", "esri-geometry-api") .version {strictly("[2.0, 3.0["); prefer("2.2.4")} library("libreoffice", "org.libreoffice", "libreoffice") .version {strictly("[7.0, 8.0["); prefer("24.8.4")} library("ucar", "edu.ucar", "cdm-core") .version {strictly("[5.0, 6.0["); prefer("5.5.3")} - library("aws.s3", "software.amazon.awssdk", "s3") .version {strictly("[2.0, 3.0["); prefer("2.31.68")} + library("aws.s3", "software.amazon.awssdk", "s3") .version {strictly("[2.0, 3.0["); prefer("2.33.4")} } create("tests") { library("geoapi", "org.opengis", "geoapi-conformance") .version {strictly(geoapiVersion)}
