This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/sis.git
commit df88006c6b6adf3a37777a07b80d362c6e6c2cdb Merge: 7ea6427 171730a Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Fri Jan 7 21:19:57 2022 +0100 Merge branch 'geoapi-3.1' .../apache/sis/internal/jaxb/gml/TM_Primitive.java | 4 +- .../sis/internal/jaxb/gts/TM_PeriodDuration.java | 18 +- .../metadata/iso/extent/DefaultTemporalExtent.java | 5 - .../apache/sis/internal/jaxb/gml/DummyInstant.java | 54 ---- .../sis/internal/jaxb/gml/TimePeriodTest.java | 28 ++- .../sis/metadata/PropertyConsistencyCheck.java | 6 +- .../sis/metadata/iso/extent/DefaultExtentTest.java | 2 +- .../main/java/org/apache/sis/io/wkt/Formatter.java | 2 +- .../apache/sis/io/wkt/GeodeticObjectParser.java | 15 +- .../referencing/ServicesForMetadataTest.java | 2 - .../apache/sis/test/integration/MetadataTest.java | 24 +- .../sis/test/integration/MetadataVerticalTest.java | 1 - .../org/apache/sis/test/integration/Metadata.xml | 4 +- .../sis/internal/temporal/DefaultInstant.java | 60 +++++ .../sis/internal/temporal/DefaultPeriod.java | 72 ++++++ .../internal/temporal/DefaultPeriodDuration.java | 86 +++++++ .../internal/temporal/DefaultTemporalFactory.java | 59 +++++ .../apache/sis/internal/temporal/package-info.java | 29 +-- .../sis/internal/util/TemporalUtilities.java | 15 +- .../sis/util/collection/TreeTableFormat.java | 2 +- .../apache/sis/util/logging/MonolineFormatter.java | 2 +- .../src/test/java/org/apache/sis/test/Assert.java | 2 +- ide-project/NetBeans/nbproject/project.properties | 2 +- pom.xml | 2 +- .../apache/sis/storage/landsat/MetadataReader.java | 7 +- .../sis/storage/landsat/MetadataReaderTest.java | 2 +- storage/sis-geotiff/pom.xml | 5 + .../apache/sis/storage/geotiff/GeoTiffStore.java | 8 +- .../sis/storage/geotiff/GeoTiffStoreProvider.java | 22 +- .../sis/storage/geotiff/ImageFileDirectory.java | 12 +- .../org/apache/sis/storage/geotiff/Reader.java | 9 +- .../apache/sis/storage/geotiff/XMLMetadata.java | 192 +++++++++++++- .../sis/storage/geotiff/XMLMetadataTest.java | 159 ++++++++++++ .../apache/sis/test/suite/GeoTiffTestSuite.java | 3 +- .../apache/sis/internal/netcdf/GridMapping.java | 5 +- .../apache/sis/storage/netcdf/MetadataReader.java | 6 +- .../sis/storage/netcdf/NetcdfStoreProvider.java | 5 +- .../sis/storage/netcdf/MetadataReaderTest.java | 4 +- .../sis/internal/storage/MetadataBuilder.java | 186 +++++++------- .../org/apache/sis/internal/storage/Resources.java | 10 + .../sis/internal/storage/Resources.properties | 2 + .../sis/internal/storage/Resources_fr.properties | 2 + .../org/apache/sis/internal/storage/csv/Store.java | 23 +- .../sis/internal/storage/csv/TimeEncoding.java | 4 +- .../sis/internal/storage/csv/package-info.java | 8 +- .../sis/internal/storage/folder/StoreProvider.java | 1 + .../sis/internal/storage/io/ChannelData.java | 38 ++- .../internal/storage/io/InputStreamAdapter.java | 78 ++++-- .../apache/sis/internal/storage/io/Markable.java | 24 +- .../internal/storage/io/OutputStreamAdapter.java | 17 +- .../internal/storage/io/RewindableLineReader.java | 110 ++++++++- .../org/apache/sis/internal/storage/wkt/Store.java | 8 +- .../sis/internal/storage/xml/AbstractProvider.java | 24 +- .../org/apache/sis/storage/DataStoreProvider.java | 244 +++++++++++++++--- .../org/apache/sis/storage/ProbeInputStream.java | 88 +++++++ .../java/org/apache/sis/storage/ProbeReader.java | 90 +++++++ .../org/apache/sis/storage/StorageConnector.java | 106 ++++++-- .../internal/storage/io/ChannelDataOutputTest.java | 4 +- .../storage/io/ChannelImageOutputStreamTest.java | 4 +- .../apache/sis/storage/DataStoreProviderTest.java | 275 +++++++++++++++++++++ .../apache/sis/storage/StorageConnectorTest.java | 202 ++++++++++----- .../apache/sis/test/suite/StorageTestSuite.java | 4 +- .../internal/storage/xml/stream/StaxDataStore.java | 20 +- 63 files changed, 1969 insertions(+), 538 deletions(-) diff --cc core/sis-metadata/src/test/java/org/apache/sis/internal/jaxb/gml/TimePeriodTest.java index 9fb6888,6174f22..65eef90 --- a/core/sis-metadata/src/test/java/org/apache/sis/internal/jaxb/gml/TimePeriodTest.java +++ b/core/sis-metadata/src/test/java/org/apache/sis/internal/jaxb/gml/TimePeriodTest.java @@@ -37,6 -38,8 +38,8 @@@ import static org.apache.sis.test.Metad import static org.apache.sis.test.TestUtilities.date; import static org.apache.sis.test.TestUtilities.format; -import org.opengis.temporal.Instant; ++import org.apache.sis.internal.geoapi.temporal.Instant; + /** * Tests the {@link TimePeriod} class. The XML fragments used in this test cases are derived from diff --cc core/sis-referencing/src/test/java/org/apache/sis/test/integration/MetadataTest.java index 0e4a21c,e0035b3..c96c83d --- a/core/sis-referencing/src/test/java/org/apache/sis/test/integration/MetadataTest.java +++ b/core/sis-referencing/src/test/java/org/apache/sis/test/integration/MetadataTest.java @@@ -121,33 -118,6 +120,18 @@@ public final strictfp class MetadataTes } /** - * Sets the temporal extent. The current implementation does nothing, because {@code sis-metadata} does not have - * any dependency to {@code sis-temporal}. However a future version or an other module may implement this method. - * - * @param extent the extent to set. - * @param startTime the start time in the {@code "yyyy-MM-dd"} format. - * @param endTime the end time in the {@code "yyyy-MM-dd"} format. - */ - protected void setTemporalBounds(final DefaultTemporalExtent extent, final String startTime, final String endTime) { - /* - * Note: if this MetadataTest class is made final and this method removed, - * then testUnmarshalling() can be simplified. - */ - } - - /** + * Creates a telephone number of the given type. + * + * @param type Either {@code "VOICE"}, {@code "FACSIMILE"} or {@code "SMS"}. + */ + private static DefaultTelephone telephone(final String number, final String type) { + final DefaultTelephone tel = new DefaultTelephone(); + tel.setNumber(number); + tel.setNumberType(UnsupportedCodeList.valueOf(type)); + return tel; + } + + /** * Programmatically creates the metadata to marshal, or to compare against the unmarshalled metadata. * * @return the hard-coded representation of {@value #XML_FILE} content. @@@ -421,9 -391,8 +405,9 @@@ "<gmx:Anchor xlink:href=\"SDN:L231:3:CDI\">Pseudo Common Data Index record</gmx:Anchor>"); replace(xml, "<gcol:CharacterString>4326</gcol:CharacterString>", "<gmx:Anchor xlink:href=\"SDN:L101:2:4326\">4326</gmx:Anchor>"); + replace(xml, "License", "Licence"); /* - * The <gmd:EX_TemporalExtent> block can not be marshalled yet, since it requires the sis-temporal module. + * The <gmd:EX_TemporalExtent> block can not be marshalled es expected yet (need a "sis-temporal" module). * We need to instruct the XML comparator to ignore this block during the comparison. We also ignore for * now the "gml:id" attribute since SIS generates different values than the ones in our test XML file, * and those values may change in future SIS version. diff --cc core/sis-utility/src/main/java/org/apache/sis/internal/temporal/DefaultInstant.java index 0000000,b312280..4555787 mode 000000,100644..100644 --- a/core/sis-utility/src/main/java/org/apache/sis/internal/temporal/DefaultInstant.java +++ b/core/sis-utility/src/main/java/org/apache/sis/internal/temporal/DefaultInstant.java @@@ -1,0 -1,66 +1,60 @@@ + /* + * 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.temporal; + + import java.util.Date; -import org.opengis.temporal.Instant; -import org.opengis.temporal.TemporalPosition; ++import org.apache.sis.internal.geoapi.temporal.Instant; + + + /** + * Default implementation of GeoAPI instant. This is a temporary class; + * GeoAPI temporal interfaces are expected to change a lot in a future revision. + * + * @author Martin Desruisseaux (Geomatys) + * @version 1.2 + * @since 1.2 + * @module + */ -final class DefaultInstant extends Primitive implements Instant { ++final class DefaultInstant implements Instant { + /** The date in milliseconds since epoch. */ + private final long millis; + + /** Creates a new instant for the given date. */ + DefaultInstant(final Date time) { + millis = time.getTime(); + } + + /** Returns the date used for describing temporal position. */ + @Override public Date getDate() { + return new Date(millis); + } + - /** Association to a temporal reference system. */ - @Override public TemporalPosition getTemporalPosition() { - throw DefaultTemporalFactory.unsupported(); - } - + /** String representation in ISO format. */ + @Override public String toString() { + return java.time.Instant.ofEpochMilli(millis).toString(); + } + + /** Hash code value of the time position. */ + @Override public int hashCode() { + return Long.hashCode(millis) ^ 57; + } + + /** Compares with given object for equality. */ + @Override public boolean equals(final Object obj) { + return (obj instanceof DefaultInstant) && ((DefaultInstant) obj).millis == millis; + } + } diff --cc core/sis-utility/src/main/java/org/apache/sis/internal/temporal/DefaultPeriod.java index 0000000,353d644..5682efb mode 000000,100644..100644 --- a/core/sis-utility/src/main/java/org/apache/sis/internal/temporal/DefaultPeriod.java +++ b/core/sis-utility/src/main/java/org/apache/sis/internal/temporal/DefaultPeriod.java @@@ -1,0 -1,72 +1,72 @@@ + /* + * 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.temporal; + + import java.util.Objects; -import org.opengis.temporal.Instant; -import org.opengis.temporal.Period; ++import org.apache.sis.internal.geoapi.temporal.Instant; ++import org.apache.sis.internal.geoapi.temporal.Period; + + + /** + * Default implementation of GeoAPI period. This is a temporary class; + * GeoAPI temporal interfaces are expected to change a lot in a future revision. + * + * @author Martin Desruisseaux (Geomatys) + * @version 1.2 + * @since 1.2 + * @module + */ -final class DefaultPeriod extends Primitive implements Period { ++final class DefaultPeriod implements Period { + /** Bounds making this period. */ + private final Instant beginning, ending; + + /** Creates a new period with the given bounds. */ + DefaultPeriod(final Instant beginning, final Instant ending) { + this.beginning = beginning; + this.ending = ending; + } + + /** The beginning instant at which this period starts. */ + @Override public Instant getBeginning() { + return beginning; + } + + /** The ending instant at which this period ends. */ + @Override public Instant getEnding() { + return ending; + } + + /** String representation. */ + @Override public String toString() { + return "[" + beginning + " … " + ending + ']'; + } + + /** Hash code value of the time position. */ + @Override public int hashCode() { + return Objects.hash(beginning, ending); + } + + /** Compares with given object for equality. */ + @Override public boolean equals(final Object obj) { + if (obj instanceof DefaultPeriod) { + DefaultPeriod other = (DefaultPeriod) obj; + return Objects.equals(other.beginning, beginning) && + Objects.equals(other.ending, ending); + } + return false; + } + } diff --cc core/sis-utility/src/main/java/org/apache/sis/internal/temporal/DefaultPeriodDuration.java index 0000000,052a12c..b6620b8 mode 000000,100644..100644 --- a/core/sis-utility/src/main/java/org/apache/sis/internal/temporal/DefaultPeriodDuration.java +++ b/core/sis-utility/src/main/java/org/apache/sis/internal/temporal/DefaultPeriodDuration.java @@@ -1,0 -1,88 +1,86 @@@ + /* + * 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.temporal; + + import java.util.Objects; -import org.opengis.temporal.PeriodDuration; ++import org.apache.sis.internal.geoapi.temporal.PeriodDuration; + import org.opengis.util.InternationalString; + + + /** + * Default implementation of GeoAPI period duration. This is a temporary class; + * GeoAPI temporal interfaces are expected to change a lot in a future revision. + * + * @author Martin Desruisseaux (Geomatys) + * @version 1.2 + * @since 1.2 + * @module + */ + final class DefaultPeriodDuration implements PeriodDuration { + /** Components of this period duration. */ + private final InternationalString years, months, week, days, hours, minutes, seconds; + + /** + * Creates a new duration. + */ + DefaultPeriodDuration( + final InternationalString years, final InternationalString months, + final InternationalString week, final InternationalString days, + final InternationalString hours, final InternationalString minutes, final InternationalString seconds) + { + this.years = years; + this.months = months; + this.week = week; + this.days = days; + this.hours = hours; + this.minutes = minutes; + this.seconds = seconds; + } + + - @Override public InternationalString getDesignator() {return null;} + @Override public InternationalString getYears() {return years;} + @Override public InternationalString getMonths() {return months;} + @Override public InternationalString getDays() {return days;} - @Override public InternationalString getTimeIndicator() {return null;} + @Override public InternationalString getHours() {return hours;} + @Override public InternationalString getMinutes() {return minutes;} + @Override public InternationalString getSeconds() {return seconds;} + + /** String representation. */ + @Override public String toString() { + return "PeriodDuration[" + years + '-' + months + '-' + days + ' ' + hours + ':' + minutes + ':' + seconds + ']'; + } + + /** Hash code value of the time position. */ + @Override public int hashCode() { + return Objects.hash(years, months, week, days, hours, minutes, seconds); + } + + /** Compares with given object for equality. */ + @Override public boolean equals(final Object obj) { + if (obj instanceof DefaultPeriodDuration) { + DefaultPeriodDuration other = (DefaultPeriodDuration) obj; + return Objects.equals(other.years, years) && + Objects.equals(other.months, months) && + Objects.equals(other.week, week) && + Objects.equals(other.days, days) && + Objects.equals(other.hours, hours) && + Objects.equals(other.minutes, minutes) && + Objects.equals(other.seconds, seconds); + } + return false; + } + } diff --cc core/sis-utility/src/main/java/org/apache/sis/internal/temporal/DefaultTemporalFactory.java index 0000000,d040aea..184c20c mode 000000,100644..100644 --- a/core/sis-utility/src/main/java/org/apache/sis/internal/temporal/DefaultTemporalFactory.java +++ b/core/sis-utility/src/main/java/org/apache/sis/internal/temporal/DefaultTemporalFactory.java @@@ -1,0 -1,150 +1,59 @@@ + /* + * 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.temporal; + + import java.util.Date; -import java.util.Collection; -import javax.measure.Unit; -import javax.measure.quantity.Time; -import org.opengis.temporal.*; -import org.opengis.metadata.Identifier; -import org.opengis.metadata.extent.Extent; + import org.opengis.util.InternationalString; -import org.apache.sis.util.resources.Errors; ++import org.apache.sis.internal.geoapi.temporal.*; + + + /** + * Default implementation of temporal object factory. This is a temporary class; + * GeoAPI temporal interfaces are expected to change a lot in a future revision. + * + * @author Martin Desruisseaux (Geomatys) + * @version 1.2 + * @since 1.2 + * @module + */ + public final class DefaultTemporalFactory implements TemporalFactory { + /** The unique instance of this factory. */ + public static final TemporalFactory INSTANCE = new DefaultTemporalFactory(); + + /** Creates the singleton instance. */ + private DefaultTemporalFactory() { + } + + /** Creates an {@link Instant} for the given date. */ + @Override public Instant createInstant(Date date) { + return new DefaultInstant(date); + } + + /** Creates a period for the two given instants. */ + @Override public Period createPeriod(Instant begin, Instant end) { + return new DefaultPeriod(begin, end); + } + + /** Creates a period duration. */ + @Override public PeriodDuration createPeriodDuration( + InternationalString years, InternationalString months, + InternationalString week, InternationalString days, + InternationalString hours, InternationalString minutes, InternationalString seconds) + { + return new DefaultPeriodDuration(years, months, week, days, hours, minutes, seconds); + } - - /** Returns the exception to be thrown by all unsupported methods. */ - static UnsupportedOperationException unsupported() { - return new UnsupportedOperationException(Errors.format(Errors.Keys.MissingRequiredModule_1, "sis-temporal")); - } - - /** Unsupported. */ - @Override public Calendar createCalendar(Identifier name, Extent domainOfValidity) { - throw unsupported(); - } - - /** Unsupported. */ - @Override public Calendar createCalendar(Identifier name, Extent domainOfValidity, Collection<CalendarEra> referenceFrame, Clock timeBasis) { - throw unsupported(); - } - - /** Unsupported. */ - @Override public CalendarDate createCalendarDate(TemporalReferenceSystem frame, IndeterminateValue indeterminatePosition, InternationalString calendarEraName, int[] calendarDate) { - throw unsupported(); - } - - /** Unsupported. */ - @Override public CalendarEra createCalendarEra(InternationalString name, InternationalString referenceEvent, CalendarDate referenceDate, JulianDate julianReference, Period epochOfUse) { - throw unsupported(); - } - - /** Unsupported. */ - @Override public Clock createClock(Identifier name, Extent domainOfValidity, InternationalString referenceEvent, ClockTime referenceTime, ClockTime utcReference) { - throw unsupported(); - } - - /** Unsupported. */ - @Override public ClockTime createClockTime(TemporalReferenceSystem frame, IndeterminateValue indeterminatePosition, Number[] clockTime) { - throw unsupported(); - } - - /** Unsupported. */ - @Override public DateAndTime createDateAndTime(TemporalReferenceSystem frame, IndeterminateValue indeterminatePosition, InternationalString calendarEraName, int[] calendarDate, Number[] clockTime) { - throw unsupported(); - } - - /** Unsupported. */ - @Override public IntervalLength createIntervalLenght(Unit unit, int radix, int factor, int value) { - throw unsupported(); - } - - /** Unsupported. */ - @Override public JulianDate createJulianDate(TemporalReferenceSystem frame, IndeterminateValue indeterminatePosition, Number coordinateValue) { - throw unsupported(); - } - - /** Unsupported. */ - @Override public OrdinalEra createOrdinalEra(InternationalString name, Date beginning, Date end, Collection<OrdinalEra> member) { - throw unsupported(); - } - - /** Unsupported. */ - @Override public OrdinalPosition createOrdinalPosition(TemporalReferenceSystem frame, IndeterminateValue indeterminatePosition, OrdinalEra ordinalPosition) { - throw unsupported(); - } - - /** Unsupported. */ - @Override public OrdinalReferenceSystem createOrdinalReferenceSystem(Identifier name, Extent domainOfValidity, Collection<OrdinalEra> ordinalEraSequence) { - throw unsupported(); - } - - /** Unsupported. */ - @Override public TemporalCoordinate createTemporalCoordinate(TemporalReferenceSystem frame, IndeterminateValue indeterminatePosition, Number coordinateValue) { - throw unsupported(); - } - - /** Unsupported. */ - @Override public TemporalCoordinateSystem createTemporalCoordinateSystem(Identifier name, Extent domainOfValidity, Date origin, Unit<Time> interval) { - throw unsupported(); - } - - /** Unsupported. */ - @Override public TemporalPosition createTemporalPosition(TemporalReferenceSystem frame, IndeterminateValue indeterminatePosition) { - throw unsupported(); - } - - /** Unsupported. */ - @Override public TemporalReferenceSystem createTemporalReferenceSystem(Identifier name, Extent domainOfValidity) { - throw unsupported(); - } + } diff --cc core/sis-utility/src/main/java/org/apache/sis/internal/util/TemporalUtilities.java index 6228eb0,d3cdfb1..8b80a21 --- a/core/sis-utility/src/main/java/org/apache/sis/internal/util/TemporalUtilities.java +++ b/core/sis-utility/src/main/java/org/apache/sis/internal/util/TemporalUtilities.java @@@ -17,13 -17,13 +17,13 @@@ package org.apache.sis.internal.util; import java.util.Date; -import org.opengis.temporal.Instant; -import org.opengis.temporal.Period; -import org.opengis.temporal.TemporalFactory; +import org.apache.sis.internal.geoapi.temporal.Instant; +import org.apache.sis.internal.geoapi.temporal.Period; +import org.apache.sis.internal.geoapi.temporal.TemporalFactory; import org.opengis.temporal.TemporalPrimitive; import org.apache.sis.util.Static; - import org.apache.sis.util.resources.Errors; import org.apache.sis.internal.system.DefaultFactories; + import org.apache.sis.internal.temporal.DefaultTemporalFactory; /** diff --cc storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/MetadataReaderTest.java index be4d9dc,339ae0d..ef811b9 --- a/storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/MetadataReaderTest.java +++ b/storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/MetadataReaderTest.java @@@ -102,9 -105,9 +103,10 @@@ public final strictfp class MetadataRea final ContentVerifier verifier = new ContentVerifier(); verifier.addPropertyToIgnore(Metadata.class, "metadataStandard"); verifier.addPropertyToIgnore(Metadata.class, "referenceSystemInfo"); + verifier.addPropertyToIgnore(Metadata.class, "alternateTitle"); + verifier.addPropertyToIgnore(TemporalExtent.class, "extent"); verifier.addMetadataToVerify(actual); - verifier.addExpectedValues( + verifier.assertMetadataEquals( // Hard-coded "identificationInfo[0].resourceFormat[0].formatSpecificationCitation.alternateTitle[0]", "NetCDF", "identificationInfo[0].resourceFormat[0].formatSpecificationCitation.title", "NetCDF Classic and 64-bit Offset Format", diff --cc storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java index c592e67,21ef318..dd7c60e --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java @@@ -77,59 -57,20 +57,19 @@@ import org.opengis.referencing.crs.Vert import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.operation.TransformException; import org.apache.sis.internal.util.CollectionsExt; -import org.apache.sis.internal.simple.SimpleDuration; import org.apache.sis.geometry.AbstractEnvelope; - import org.apache.sis.metadata.iso.DefaultMetadata; - import org.apache.sis.metadata.iso.DefaultIdentifier; - import org.apache.sis.metadata.iso.DefaultMetadataScope; - import org.apache.sis.metadata.iso.extent.DefaultExtent; - import org.apache.sis.metadata.iso.extent.DefaultVerticalExtent; - import org.apache.sis.metadata.iso.extent.DefaultTemporalExtent; - import org.apache.sis.metadata.iso.extent.DefaultBoundingPolygon; - import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox; - import org.apache.sis.metadata.iso.extent.DefaultGeographicDescription; - import org.apache.sis.metadata.iso.spatial.DefaultGridSpatialRepresentation; - import org.apache.sis.metadata.iso.spatial.DefaultDimension; - import org.apache.sis.metadata.iso.spatial.DefaultGeorectified; - import org.apache.sis.metadata.iso.spatial.DefaultGeoreferenceable; - import org.apache.sis.metadata.iso.spatial.DefaultGCPCollection; - import org.apache.sis.metadata.iso.spatial.DefaultGCP; - import org.apache.sis.metadata.iso.content.DefaultAttributeGroup; - import org.apache.sis.metadata.iso.content.DefaultSampleDimension; - import org.apache.sis.metadata.iso.content.DefaultBand; - import org.apache.sis.metadata.iso.content.DefaultCoverageDescription; - import org.apache.sis.metadata.iso.content.DefaultFeatureCatalogueDescription; - import org.apache.sis.metadata.iso.content.DefaultRangeElementDescription; - import org.apache.sis.metadata.iso.content.DefaultImageDescription; - import org.apache.sis.metadata.iso.content.DefaultFeatureTypeInfo; - import org.apache.sis.metadata.iso.citation.Citations; - import org.apache.sis.metadata.iso.citation.AbstractParty; - import org.apache.sis.metadata.iso.citation.DefaultSeries; - import org.apache.sis.metadata.iso.citation.DefaultCitation; - import org.apache.sis.metadata.iso.citation.DefaultCitationDate; - import org.apache.sis.metadata.iso.citation.DefaultResponsibility; - import org.apache.sis.metadata.iso.citation.DefaultIndividual; - import org.apache.sis.metadata.iso.citation.DefaultOrganisation; - import org.apache.sis.metadata.iso.citation.DefaultOnlineResource; - import org.apache.sis.metadata.iso.constraint.DefaultLegalConstraints; - import org.apache.sis.metadata.iso.identification.AbstractIdentification; - import org.apache.sis.metadata.iso.identification.DefaultKeywords; - import org.apache.sis.metadata.iso.identification.DefaultResolution; - import org.apache.sis.metadata.iso.identification.DefaultDataIdentification; - import org.apache.sis.metadata.iso.distribution.DefaultFormat; - import org.apache.sis.metadata.iso.distribution.DefaultDistributor; - import org.apache.sis.metadata.iso.distribution.DefaultDistribution; - import org.apache.sis.metadata.iso.acquisition.DefaultAcquisitionInformation; - import org.apache.sis.metadata.iso.acquisition.DefaultEvent; - import org.apache.sis.metadata.iso.acquisition.DefaultInstrument; - import org.apache.sis.metadata.iso.acquisition.DefaultOperation; - import org.apache.sis.metadata.iso.acquisition.DefaultPlatform; - import org.apache.sis.metadata.iso.acquisition.DefaultRequirement; - import org.apache.sis.metadata.iso.lineage.DefaultLineage; - import org.apache.sis.metadata.iso.lineage.DefaultProcessStep; - import org.apache.sis.metadata.iso.lineage.DefaultProcessing; - import org.apache.sis.metadata.iso.lineage.DefaultSource; - import org.apache.sis.metadata.iso.maintenance.DefaultScope; - import org.apache.sis.metadata.iso.maintenance.DefaultScopeDescription; + import org.apache.sis.metadata.ModifiableMetadata; + import org.apache.sis.metadata.iso.*; + import org.apache.sis.metadata.iso.acquisition.*; + import org.apache.sis.metadata.iso.citation.*; + import org.apache.sis.metadata.iso.constraint.*; + import org.apache.sis.metadata.iso.content.*; + import org.apache.sis.metadata.iso.distribution.*; + import org.apache.sis.metadata.iso.extent.*; + import org.apache.sis.metadata.iso.identification.*; + import org.apache.sis.metadata.iso.lineage.*; + import org.apache.sis.metadata.iso.maintenance.*; + import org.apache.sis.metadata.iso.spatial.*; import org.apache.sis.metadata.sql.MetadataStoreException; import org.apache.sis.metadata.sql.MetadataSource; import org.apache.sis.coverage.grid.GridGeometry; @@@ -148,12 -90,8 +89,7 @@@ import org.apache.sis.measure.Units import static org.apache.sis.internal.util.StandardDateFormat.MILLISECONDS_PER_DAY; // Branch-dependent imports - import org.opengis.metadata.citation.ResponsibleParty; - import org.opengis.metadata.identification.CharacterSet; - import org.opengis.metadata.identification.DataIdentification; - import org.opengis.metadata.acquisition.AcquisitionInformation; - import org.apache.sis.metadata.iso.citation.DefaultResponsibleParty; -import org.opengis.temporal.Duration; -import org.opengis.feature.FeatureType; +import org.apache.sis.feature.DefaultFeatureType; /** @@@ -3231,6 -3205,52 +3192,49 @@@ parse: for (int i = 0; i < length; } /** + * Merge the given metadata into the metadata created by this builder. + * The given source should be an instance of {@link Metadata}, + * but some types of metadata components are accepted as well. + * + * @param source the source metadata to merge. Will never be modified. + * @param locale the locale to use for error message in exceptions, or {@code null} for the default locale. + * @return {@code true} if the given source has been merged, + * or {@code false} if its type is not managed by this builder. + * @throws RuntimeException if the merge failed (may be {@link IllegalArgumentException}, + * {@link ClassCastException}, {@link org.apache.sis.metadata.InvalidMetadataException}…) + * + * @see Merger + */ + public boolean mergeMetadata(final Object source, final Locale locale) { + final ModifiableMetadata target; + if (source instanceof Metadata) target = metadata(); + else if (source instanceof DataIdentification) target = identification(); + else if (source instanceof Citation) target = citation(); + else if (source instanceof Series) target = series(); - else if (source instanceof Responsibility) target = responsibility(); - else if (source instanceof Party) target = party(); ++ else if (source instanceof DefaultResponsibleParty) target = responsibility(); ++ else if (source instanceof AbstractParty) target = party(); + else if (source instanceof LegalConstraints) target = constraints(); + else if (source instanceof Extent) target = extent(); + else if (source instanceof AcquisitionInformation) target = acquisition(); + else if (source instanceof Platform) target = platform(); + else if (source instanceof FeatureCatalogueDescription) target = featureDescription(); + else if (source instanceof CoverageDescription) target = coverageDescription(); - else if (source instanceof AttributeGroup) target = attributeGroup(); ++ else if (source instanceof DefaultAttributeGroup) target = attributeGroup(); + else if (source instanceof SampleDimension) target = sampleDimension(); + else if (source instanceof GridSpatialRepresentation) target = gridRepresentation(); + else if (source instanceof GCPCollection) target = groundControlPoints(); + else if (source instanceof Distribution) target = distribution(); + else if (source instanceof Format) target = format(); + else if (source instanceof Lineage) target = lineage(); + else if (source instanceof ProcessStep) target = processStep(); + else if (source instanceof Processing) target = processing(); + else return false; + final Merger merger = new Merger(locale); + merger.copy(source, target); + return true; + } + + /** * Returns the metadata (optionally as an unmodifiable object), or {@code null} if none. * If {@code freeze} is {@code true}, then the returned metadata instance can not be modified. *