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 605344850159ef0b1ae3aa4633f1f664cc8110f8 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Fri Dec 2 14:20:35 2022 +0100 Replace `java.util.Date` (from Java 1) by `java.time.temporal.Temporal` (from Java 8) in two properties that were introduced by the ISO 19157 upgrade (JIRA issue SIS-394). This change should be done on all properties, but this commit starts with properties that did not existed before SIS 1.3 release for making the transition smother. https://github.com/opengeospatial/geoapi/issues/79 --- .../apache/sis/internal/jaxb/gco/GO_DateTime.java | 7 +- .../gco/{GO_DateTime.java => GO_Temporal.java} | 61 +++++---- .../internal/metadata/legacy/DateToTemporal.java | 87 +++++++++++++ .../internal/metadata/legacy/TemporalToDate.java | 94 ++++++++++++++ .../org/apache/sis/internal/xml/XmlUtilities.java | 143 ++++++++++++++++++++- .../org/apache/sis/internal/xml/package-info.java | 2 +- .../sis/metadata/iso/quality/AbstractElement.java | 27 ++-- .../sis/metadata/iso/quality/AbstractResult.java | 28 ++-- .../iso/quality/DefaultEvaluationMethod.java | 78 +++++------ .../sis/metadata/iso/quality/package-info.java | 1 + .../apache/sis/internal/xml/XmlUtilitiesTest.java | 67 +++++++++- .../metadata/iso/quality/AbstractElementTest.java | 96 +++----------- ...tTest.java => DefaultEvaluationMethodTest.java} | 24 ++-- .../apache/sis/test/suite/MetadataTestSuite.java | 1 + 14 files changed, 526 insertions(+), 190 deletions(-) diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gco/GO_DateTime.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gco/GO_DateTime.java index b31340c401..af53fa8b7c 100644 --- a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gco/GO_DateTime.java +++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gco/GO_DateTime.java @@ -56,8 +56,11 @@ import org.apache.sis.internal.xml.XmlUtilities; * * @since 0.3 * @module + * + * @todo This adapter may be deleted in favor of {@link GO_Temporal} after all usages + * of {@link Date} have been replaced by {@link java.time.temporal.Temporal}. */ -@XmlType(name = "Date_PropertyType") +@XmlType(name = "DateTime_PropertyType") public class GO_DateTime extends XmlAdapter<GO_DateTime, Date> { /** * The date and time value using the {@code code "DateTime"} name. @@ -111,7 +114,7 @@ public class GO_DateTime extends XmlAdapter<GO_DateTime, Date> { * Returns the current date, or {@code null} if none. If both fields are defined, * then {@link #dateTime} has precedence since it is assumed more accurate. */ - final Date getDate() { + private Date getDate() { return XmlUtilities.toDate(Context.current(), dateTime != null ? dateTime : date); } diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gco/GO_DateTime.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gco/GO_Temporal.java similarity index 76% copy from core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gco/GO_DateTime.java copy to core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gco/GO_Temporal.java index b31340c401..bf50053b6c 100644 --- a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gco/GO_DateTime.java +++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gco/GO_Temporal.java @@ -16,7 +16,8 @@ */ package org.apache.sis.internal.jaxb.gco; -import java.util.Date; +import java.time.temporal.Temporal; +import java.time.temporal.ChronoField; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlSchemaType; @@ -32,8 +33,8 @@ import org.apache.sis.internal.xml.XmlUtilities; /** * JAXB adapter wrapping the date value in a {@code <gco:Date>} or {@code <gco:DateTime>} element, * for ISO 19115-3 compliance. Only one of {@code Date} or {@code DateTime} field shall be non-null. - * At marshalling time, the choice is performed depending on whatever the given date contains - * hour, minute or seconds information different than zero. + * At marshalling time, the choice is performed depending on whatever the given date contains hour, + * minute or seconds fields. * * <h2>Difference between ISO 19139:2007 and ISO 19115-3:2016</h2> * The ISO {@code baseTypes.xsd} files define two kinds of date property: @@ -54,11 +55,11 @@ import org.apache.sis.internal.xml.XmlUtilities; * @see org.apache.sis.internal.jaxb.gml.DateAdapter * @see org.apache.sis.internal.jaxb.gml.UniversalTimeAdapter * - * @since 0.3 + * @since 1.3 * @module */ @XmlType(name = "Date_PropertyType") -public class GO_DateTime extends XmlAdapter<GO_DateTime, Date> { +public class GO_Temporal extends XmlAdapter<GO_Temporal, Temporal> { /** * The date and time value using the {@code code "DateTime"} name. * Only one of {@code date} and {@link #dateTime} shall be non-null. @@ -78,30 +79,28 @@ public class GO_DateTime extends XmlAdapter<GO_DateTime, Date> { /** * Empty constructor for JAXB. */ - public GO_DateTime() { + public GO_Temporal() { } /** - * Builds a wrapper for the given {@link Date}. + * Builds a wrapper for the given temporal object. * - * @param date the date to marshal. Cannot be {@code null}. + * @param time the date and time to marshal. Cannot be {@code null}. */ - private GO_DateTime(final Date date) { + private GO_Temporal(final Temporal time) { final Context context = Context.current(); try { - final XMLGregorianCalendar gc = XmlUtilities.toXML(context, date); + final XMLGregorianCalendar gc = XmlUtilities.toXML(context, time); + if (gc.getMillisecond() == 0) { + gc.setMillisecond(DatatypeConstants.FIELD_UNDEFINED); + } if (Context.isFlagSet(context, Context.LEGACY_METADATA)) { - if (XmlUtilities.trimTime(gc, false)) { - this.date = gc; - } else { - dateTime = gc; - } - } else { - if (gc.getMillisecond() == 0) { - gc.setMillisecond(DatatypeConstants.FIELD_UNDEFINED); + if (!time.isSupported(ChronoField.HOUR_OF_DAY)) { + date = gc; + return; } - dateTime = gc; } + dateTime = gc; } catch (DatatypeConfigurationException e) { Context.warningOccured(context, XmlAdapter.class, "marshal", e, true); } @@ -111,40 +110,40 @@ public class GO_DateTime extends XmlAdapter<GO_DateTime, Date> { * Returns the current date, or {@code null} if none. If both fields are defined, * then {@link #dateTime} has precedence since it is assumed more accurate. */ - final Date getDate() { - return XmlUtilities.toDate(Context.current(), dateTime != null ? dateTime : date); + private Temporal getDate() { + return XmlUtilities.toTemporal(Context.current(), dateTime != null ? dateTime : date); } /** - * Converts a date read from a XML stream to the object which will contain - * the value. JAXB calls automatically this method at unmarshalling time. + * Converts a date read from a XML stream to the object which will contain the value. + * JAXB calls automatically this method at unmarshalling time. * * @param value the adapter for this metadata value. - * @return a {@linkplain Date date} which represents the metadata value. + * @return a temporal object which represents the metadata value. */ @Override - public final Date unmarshal(final GO_DateTime value) { + public final Temporal unmarshal(final GO_Temporal value) { return (value != null) ? value.getDate() : null; } /** - * Converts the {@linkplain Date date} to the object to be marshalled in a XML - * file or stream. JAXB calls automatically this method at marshalling time. + * Converts the temporal object to the object to be marshalled in a XML file or stream. + * JAXB calls automatically this method at marshalling time. * The use of {@code <gco:Date>} or {@code <gco:DateTime>} is determined automatically. * * @param value the date value. * @return the adapter for this date. */ @Override - public GO_DateTime marshal(final Date value) { - return (value != null) ? new GO_DateTime(value) : null; + public GO_Temporal marshal(final Temporal value) { + return (value != null) ? new GO_Temporal(value) : null; } /** * Wraps the value only if marshalling ISO 19115-3 element. * Otherwise (i.e. if marshalling a legacy ISO 19139:2007 document), omit the element. */ - public static final class Since2014 extends GO_DateTime { + public static final class Since2014 extends GO_Temporal { /** Empty constructor used only by JAXB. */ public Since2014() { } @@ -154,7 +153,7 @@ public class GO_DateTime extends XmlAdapter<GO_DateTime, Date> { * * @return a non-null value only if marshalling ISO 19115-3 or newer. */ - @Override public GO_DateTime marshal(final Date value) { + @Override public GO_Temporal marshal(final Temporal value) { return FilterByVersion.CURRENT_METADATA.accept() ? super.marshal(value) : null; } } diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/legacy/DateToTemporal.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/legacy/DateToTemporal.java new file mode 100644 index 0000000000..5fe78a10e6 --- /dev/null +++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/legacy/DateToTemporal.java @@ -0,0 +1,87 @@ +/* + * 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.metadata.legacy; + +import java.time.temporal.Temporal; +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Date; +import java.util.Iterator; + + +/** + * A collection where conversion from {@link Date} to {@link Temporal} objects are performed on-the-fly. + * This is used for handling legacy metadata, before the move to {@link java.time}. + * This adapter may be deleted after deprecated metadata methods have been removed from Apache SIS. + * + * @author Martin Desruisseaux (Geomatys) + * @version 1.3 + * @since 1.3 + * @module + */ +public final class DateToTemporal extends AbstractCollection<Temporal> { + /** + * The collection of dates. + */ + private final Collection<? extends Date> source; + + /** + * Creates a new view over the given collection. + * + * @param source the collection of dates to wrap. + */ + public DateToTemporal(final Collection<? extends Date> source) { + this.source = source; + } + + /** + * Returns the number of dates in this collection. + * + * @return number of dates. + */ + @Override + public int size() { + return source.size(); + } + + /** + * Returns an iterator over the dates in this collection. + * + * @return an iterator over the dates. + */ + @Override + public Iterator<Temporal> iterator() { + final Iterator<? extends Date> dates = source.iterator(); + return new Iterator<Temporal>() { + /** Tests whether there is more dates to return. */ + @Override public boolean hasNext() { + return dates.hasNext(); + } + + /** Returns the next date, converted to a temporal object. */ + @Override public Temporal next() { + final Date t = dates.next(); + return (t != null) ? t.toInstant() : null; + } + + /** Remove the last date returned by the iterator. */ + @Override public void remove() { + dates.remove(); + } + }; + } +} diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/legacy/TemporalToDate.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/legacy/TemporalToDate.java new file mode 100644 index 0000000000..02e1fad93c --- /dev/null +++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/legacy/TemporalToDate.java @@ -0,0 +1,94 @@ +/* + * 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.metadata.legacy; + +import java.time.Instant; +import java.time.temporal.ChronoField; +import java.time.temporal.Temporal; +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Date; +import java.util.Iterator; + + +/** + * A collection where conversion from {@link Temporal} to {@link Date} objects are performed on-the-fly. + * This is used for handling legacy metadata, before the move to {@link java.time}. + * This adapter may be deleted after deprecated metadata methods have been removed from Apache SIS. + * + * @author Martin Desruisseaux (Geomatys) + * @version 1.3 + * @since 1.3 + * @module + */ +public final class TemporalToDate extends AbstractCollection<Date> { + /** + * The collection of dates. + */ + private final Collection<? extends Temporal> source; + + /** + * Creates a new view over the given collection. + * + * @param source the collection of dates to wrap. + */ + public TemporalToDate(final Collection<? extends Temporal> source) { + this.source = source; + } + + /** + * Returns the number of dates in this collection. + * + * @return number of dates. + */ + @Override + public int size() { + return source.size(); + } + + /** + * Returns an iterator over the dates in this collection. + * + * @return an iterator over the dates. + */ + @Override + public Iterator<Date> iterator() { + final Iterator<? extends Temporal> dates = source.iterator(); + return new Iterator<Date>() { + /** Tests whether there is more dates to return. */ + @Override public boolean hasNext() { + return dates.hasNext(); + } + + /** Returns the next temporal object, converted to a date. */ + @Override public Date next() { + final Temporal t = dates.next(); + if (t == null) return null; + if (t instanceof Instant) { + return Date.from((Instant) t); + } + // Following may throw `DateTimeException` if the temporal does not support the field. + return new Date(Math.multiplyExact(t.getLong(ChronoField.INSTANT_SECONDS), 1000)); + } + + /** Remove the last date returned by the iterator. */ + @Override public void remove() { + dates.remove(); + } + }; + } +} diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/xml/XmlUtilities.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/xml/XmlUtilities.java index 4ce01ccc94..76be5ca57f 100644 --- a/core/sis-metadata/src/main/java/org/apache/sis/internal/xml/XmlUtilities.java +++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/xml/XmlUtilities.java @@ -16,10 +16,25 @@ */ package org.apache.sis.internal.xml; +import java.math.BigDecimal; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.OffsetTime; +import java.time.YearMonth; +import java.time.Year; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.temporal.Temporal; +import java.time.temporal.ChronoField; import java.util.Date; import java.util.Locale; import java.util.TimeZone; import java.util.GregorianCalendar; +import java.util.function.ObjIntConsumer; import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.DatatypeConfigurationException; @@ -34,7 +49,7 @@ import static javax.xml.datatype.DatatypeConstants.FIELD_UNDEFINED; * Utilities methods related to XML. * * @author Martin Desruisseaux (Geomatys) - * @version 0.3 + * @version 1.3 * @since 0.3 * @module */ @@ -131,9 +146,78 @@ public final class XmlUtilities extends SystemListener { return false; } + /** + * Temporal fields that may be copied into {@link XMLGregorianCalendar}. + */ + private static final ChronoField[] FIELDS = { + /*[0]*/ ChronoField.YEAR, + /*[1]*/ ChronoField.MONTH_OF_YEAR, + /*[2]*/ ChronoField.DAY_OF_MONTH, + /*[3]*/ ChronoField.HOUR_OF_DAY, + /*[4]*/ ChronoField.MINUTE_OF_HOUR, + /*[5]*/ ChronoField.SECOND_OF_MINUTE, + /*[6]*/ ChronoField.MILLI_OF_SECOND, + /*[7]*/ ChronoField.OFFSET_SECONDS + }; + + /** + * Setter methods to invoke for setting the value of a temporal field on a {@link XMLGregorianCalendar}. + * Indices in this array must correspond to indices in the {@link #FIELDS} array. + */ + @SuppressWarnings({"rawtypes", "unchecked"}) // Generic array creation. + private static final ObjIntConsumer<XMLGregorianCalendar>[] SETTERS = new ObjIntConsumer[FIELDS.length]; + static { + SETTERS[0] = XMLGregorianCalendar::setYear; + SETTERS[1] = XMLGregorianCalendar::setMonth; + SETTERS[2] = XMLGregorianCalendar::setDay; + SETTERS[3] = XMLGregorianCalendar::setHour; + SETTERS[4] = XMLGregorianCalendar::setMinute; + SETTERS[5] = XMLGregorianCalendar::setSecond; + SETTERS[6] = XMLGregorianCalendar::setMillisecond; + SETTERS[7] = (calendar, seconds) -> calendar.setTimezone(seconds / 60); // Convert seconds to minutes. + } + + /** + * Converts the given temporal object to a XML Gregorian calendar. + * The returned calendar may have undefined fields (including undefined time zone) + * if the corresponding information was not provided in the given temporal object. + * + * <p>If the returned date has a time, then it usually has millisecond accuracy. + * Caller may want to clear the millisecond field if it is equal to zero.</p> + * + * @param context the current (un)marshalling context, or {@code null} if none. + * @param date the date to convert to a XML calendar, or {@code null}. + * @return the XML calendar, or {@code null} if {@code date} was null. + * @throws DatatypeConfigurationException if the factory cannot be created. + */ + public static XMLGregorianCalendar toXML(final Context context, final Temporal date) throws DatatypeConfigurationException { + if (date == null) { + return null; + } + final XMLGregorianCalendar xml = getDatatypeFactory().newXMLGregorianCalendar(); + if (date instanceof Instant) { + final TimeZone zone = (context != null) ? context.getTimeZone() : null; + final ZoneId zid = (zone != null) ? zone.toZoneId() : ZoneId.systemDefault(); + final ZonedDateTime t = ZonedDateTime.ofInstant((Instant) date, zid); + for (int i=0; i<FIELDS.length; i++) { + SETTERS[i].accept(xml, t.get(FIELDS[i])); + } + } else { + for (int i=0; i<FIELDS.length; i++) { + final ChronoField field = FIELDS[i]; + if (date.isSupported(field)) { + SETTERS[i].accept(xml, date.get(field)); + } + } + } + return xml; + } + /** * Converts the given date to a XML Gregorian calendar using the locale and timezone * from the current {@linkplain Context marshalling context}. + * The returned date has millisecond accuracy. + * Caller may want to clear the millisecond field if it is equal to zero. * * @param context the current (un)marshalling context, or {@code null} if none. * @param date the date to convert to a XML calendar, or {@code null}. @@ -175,6 +259,61 @@ public final class XmlUtilities extends SystemListener { return new GregorianCalendar(); } + /** + * Replaces undefined value by zero. Used for optional time fields. + */ + private static int zeroIfUndef(final int value) { + return (value != FIELD_UNDEFINED) ? value : 0; + } + + /** + * Converts the given XML Gregorian calendar to a temporal object. + * The temporal object may be {@link LocalDate}, {@link LocalTime}, + * {@link LocalDateTime}, {@link OffsetDateTime}, {@link Year} or {@link YearMonth} + * depending on which fields are defined in the given calendar. + * + * @param context the current (un)marshalling context, or {@code null} if none. + * @param xml the XML calendar to convert to a temporal object, or {@code null}. + * @return the temporal object, or {@code null} if {@code xml} is null or has too many undefined fields. + */ + public static Temporal toTemporal(final Context context, final XMLGregorianCalendar xml) { + if (xml == null) { + return null; + } + final int year = xml.getYear(); + final int month = xml.getMonth(); + final int day = xml.getDay(); + final int hour = xml.getHour(); + final int min = zeroIfUndef(xml.getMinute()); + final int sec = zeroIfUndef(xml.getSecond()); + final int nano; + final boolean hasYear = (year != FIELD_UNDEFINED); + final boolean hasYM = hasYear && (month != FIELD_UNDEFINED); + final boolean hasDate = hasYM && (day != FIELD_UNDEFINED); + if (hour == FIELD_UNDEFINED) { + return hasDate ? LocalDate.of(year, month, day) : + hasYM ? YearMonth.of(year, month) : + hasYear ? Year .of(year) : null; + } else { + final BigDecimal f = xml.getFractionalSecond(); + nano = (f != null) ? f.movePointRight(9).intValue() : 0; + } + final int offset = xml.getTimezone(); + if (offset == FIELD_UNDEFINED) { + if (hasDate) { + return LocalDateTime.of(year, month, day, hour, min, sec, nano); + } else { + return LocalTime.of(hour, min, sec, nano); + } + } + final ZoneOffset zone = ZoneOffset.ofTotalSeconds(offset * 60); + if (hasDate) { + return OffsetDateTime.of(year, month, day, hour, min, sec, nano, zone); + } else { + return OffsetTime.of(hour, min, sec, nano, zone); + } + } + /** * Converts the given XML Gregorian calendar to a date. * @@ -184,7 +323,7 @@ public final class XmlUtilities extends SystemListener { */ public static Date toDate(final Context context, final XMLGregorianCalendar xml) { if (xml != null) { - final GregorianCalendar calendar = xml.toGregorianCalendar(); + final GregorianCalendar calendar = xml.toGregorianCalendar(); if (context != null && xml.getTimezone() == FIELD_UNDEFINED) { final TimeZone timezone = context.getTimeZone(); if (timezone != null) { diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/xml/package-info.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/xml/package-info.java index 4017656bd7..fc62947465 100644 --- a/core/sis-metadata/src/main/java/org/apache/sis/internal/xml/package-info.java +++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/xml/package-info.java @@ -30,7 +30,7 @@ * @author Cédric Briançon (Geomatys) * @author Cullen Rombach (Image Matters) * @author Martin Desruisseaux (Geomatys) - * @version 1.1 + * @version 1.3 * @since 1.0 * @module */ diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractElement.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractElement.java index db46e76277..8a04d3dbb7 100644 --- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractElement.java +++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractElement.java @@ -21,6 +21,7 @@ import java.util.Collection; import java.util.Collections; import java.util.function.Function; import java.util.function.BiConsumer; +import java.time.temporal.Temporal; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @@ -43,6 +44,8 @@ import org.opengis.metadata.quality.Metaquality; import org.opengis.util.InternationalString; import org.apache.sis.internal.jaxb.FilterByVersion; import org.apache.sis.internal.jaxb.gco.InternationalStringAdapter; +import org.apache.sis.internal.metadata.legacy.DateToTemporal; +import org.apache.sis.internal.metadata.legacy.TemporalToDate; import org.apache.sis.internal.metadata.Dependencies; import org.apache.sis.internal.xml.LegacyNamespaces; @@ -547,20 +550,18 @@ public class AbstractElement extends ISOMetadata implements Element { @Dependencies("getEvaluationMethod") @XmlElement(name = "dateTime", namespace = LegacyNamespaces.GMD) public Collection<Date> getDates() { - if (!FilterByVersion.LEGACY_METADATA.accept()) { - return null; - } - EvaluationMethod m = getEvaluationMethod(); - if (m == null) { - if (state() == State.FINAL) { - return Collections.emptyList(); + if (FilterByVersion.LEGACY_METADATA.accept()) { + EvaluationMethod m = getEvaluationMethod(); + if (m == null) { + if (state() == State.FINAL) { + return Collections.emptyList(); + } + setEvaluationMethod(m = new DefaultEvaluationMethod()); } - setEvaluationMethod(m = new DefaultEvaluationMethod()); - } - if (m instanceof DefaultEvaluationMethod) { - return ((DefaultEvaluationMethod) m).getDates(); + Collection<? extends Temporal> dates = m.getDates(); + if (dates != null) return new TemporalToDate(dates); } - return Collections.unmodifiableCollection(m.getDates()); + return null; } /** @@ -574,7 +575,7 @@ public class AbstractElement extends ISOMetadata implements Element { @Deprecated public void setDates(final Collection<? extends Date> newValues) { if (!isNullOrEmpty(newValues)) { - setEvaluationMethodProperty(DefaultEvaluationMethod::setDates, newValues); + setEvaluationMethodProperty(DefaultEvaluationMethod::setDates, new DateToTemporal(newValues)); } } diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractResult.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractResult.java index d733b85ef2..ab6c9894e0 100644 --- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractResult.java +++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractResult.java @@ -16,7 +16,7 @@ */ package org.apache.sis.metadata.iso.quality; -import java.util.Date; +import java.time.temporal.Temporal; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.XmlSeeAlso; @@ -28,8 +28,7 @@ import org.opengis.metadata.quality.ConformanceResult; import org.opengis.metadata.quality.QuantitativeResult; import org.opengis.metadata.quality.DescriptiveResult; import org.apache.sis.internal.jaxb.metadata.MD_Scope; -import org.apache.sis.internal.jaxb.gco.GO_DateTime; -import org.apache.sis.internal.metadata.ImplementationHelper; +import org.apache.sis.internal.jaxb.gco.GO_Temporal; // Branch-dependent imports import org.opengis.metadata.maintenance.Scope; @@ -78,15 +77,15 @@ public class AbstractResult extends ISOMetadata implements Result { private Scope resultScope; /** - * Date when the result was generated, or {@link Long#MIN_VALUE} if none. + * Date when the result was generated, or {@code null} if none. */ - private long dateTime; + @SuppressWarnings("serial") + private Temporal dateTime; /** * Constructs an initially empty result. */ public AbstractResult() { - dateTime = Long.MIN_VALUE; } /** @@ -102,9 +101,7 @@ public class AbstractResult extends ISOMetadata implements Result { super(object); if (object != null) { resultScope = object.getResultScope(); - dateTime = ImplementationHelper.toMilliseconds(object.getDateTime()); - } else { - dateTime = Long.MIN_VALUE; + dateTime = object.getDateTime(); } } @@ -178,6 +175,9 @@ public class AbstractResult extends ISOMetadata implements Result { /** * Returns the date when the result was generated. + * This is typically a {@link java.time.LocalDate}, {@link java.time.LocalDateTime} + * or {@link java.time.ZonedDateTime} depending on whether the hour of the day and + * the time zone are provided. * * @return date of the result, or {@code null} if none. * @@ -185,9 +185,9 @@ public class AbstractResult extends ISOMetadata implements Result { */ @Override @XmlElement(name = "dateTime") - @XmlJavaTypeAdapter(GO_DateTime.Since2014.class) - public Date getDateTime() { - return ImplementationHelper.toDate(dateTime); + @XmlJavaTypeAdapter(GO_Temporal.Since2014.class) + public Temporal getDateTime() { + return dateTime; } /** @@ -197,7 +197,7 @@ public class AbstractResult extends ISOMetadata implements Result { * * @since 1.3 */ - public void setDateTime(final Date newValue) { - dateTime = ImplementationHelper.toMilliseconds(newValue); + public void setDateTime(final Temporal newValue) { + dateTime = newValue; } } diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultEvaluationMethod.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultEvaluationMethod.java index 51764ef798..d204673ae5 100644 --- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultEvaluationMethod.java +++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultEvaluationMethod.java @@ -16,11 +16,11 @@ */ package org.apache.sis.metadata.iso.quality; -import java.util.Date; import java.util.Iterator; import java.util.Collection; import java.util.AbstractList; import java.io.Serializable; +import java.time.temporal.Temporal; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @@ -34,6 +34,7 @@ import org.opengis.metadata.quality.AggregationDerivation; import org.apache.sis.internal.system.Semaphores; import org.apache.sis.util.collection.CheckedContainer; import org.apache.sis.util.resources.Errors; +import org.apache.sis.util.ArgumentChecks; import static org.apache.sis.util.collection.Containers.isNullOrEmpty; import static org.apache.sis.internal.metadata.ImplementationHelper.valueIfDefined; @@ -107,8 +108,8 @@ public class DefaultEvaluationMethod extends ISOMetadata implements EvaluationMe /** * The start and end times as a list of O, 1 or 2 elements. */ - private static final class Dates extends AbstractList<Date> - implements CheckedContainer<Date>, Cloneable, Serializable + private static final class Dates extends AbstractList<Temporal> + implements CheckedContainer<Temporal>, Cloneable, Serializable { /** * For cross-version compatibility. @@ -116,10 +117,11 @@ public class DefaultEvaluationMethod extends ISOMetadata implements EvaluationMe private static final long serialVersionUID = 1210175223467194009L; /** - * Start time ({@code date1}) and end time ({@code date2}) on which a data quality measure - * was applied. Value is {@link Long#MIN_VALUE} if this information is not available. + * Start time ({@code date1}) and end time ({@code date2}) on which a data quality measure was applied. + * Value is {@code null} if this information is not available. */ - private long date1, date2; + @SuppressWarnings("serial") + private Temporal date1, date2; /** * Creates a new list initialized with no dates. @@ -132,8 +134,8 @@ public class DefaultEvaluationMethod extends ISOMetadata implements EvaluationMe * Returns the type of elements in this list. */ @Override - public Class<Date> getElementType() { - return Date.class; + public Class<Temporal> getElementType() { + return Temporal.class; } /** @@ -141,8 +143,8 @@ public class DefaultEvaluationMethod extends ISOMetadata implements EvaluationMe */ @Override public void clear() { - date1 = Long.MIN_VALUE; - date2 = Long.MIN_VALUE; + date1 = null; + date2 = null; } /** @@ -150,8 +152,8 @@ public class DefaultEvaluationMethod extends ISOMetadata implements EvaluationMe */ @Override public int size() { - if (date2 != Long.MIN_VALUE) return 2; - if (date1 != Long.MIN_VALUE) return 1; + if (date2 != null) return 2; + if (date1 != null) return 1; return 0; } @@ -159,14 +161,17 @@ public class DefaultEvaluationMethod extends ISOMetadata implements EvaluationMe * Returns the value at the given index. */ @Override - @SuppressWarnings("fallthrough") - public Date get(final int index) { - long date = date1; + public Temporal get(final int index) { + Temporal date; switch (index) { - case 1: date = date2; // Fall through - case 0: if (date != Long.MIN_VALUE) return new Date(date); // else fallthrough. - default: throw new IndexOutOfBoundsException(Errors.format(Errors.Keys.IndexOutOfBounds_1, index)); + case 0: date = date1; break; + case 1: date = date2; break; + default: date = null; break; + } + if (date == null) { + throw new IndexOutOfBoundsException(Errors.format(Errors.Keys.IndexOutOfBounds_1, index)); } + return date; } /** @@ -174,9 +179,9 @@ public class DefaultEvaluationMethod extends ISOMetadata implements EvaluationMe * Null values are not allowed. */ @Override - public Date set(final int index, final Date value) { - final long date = value.getTime(); - final Date previous = get(index); + public Temporal set(final int index, final Temporal date) { + ArgumentChecks.ensureNonNull("date", date); + final Temporal previous = get(index); switch (index) { case 0: date1 = date; break; case 1: date2 = date; break; @@ -190,11 +195,11 @@ public class DefaultEvaluationMethod extends ISOMetadata implements EvaluationMe */ @Override @SuppressWarnings("fallthrough") - public Date remove(final int index) { - final Date previous = get(index); + public Temporal remove(final int index) { + final Temporal previous = get(index); switch (index) { - case 0: date1 = date2; // Fallthrough - case 1: date2 = Long.MIN_VALUE; break; + case 0: date1 = date2; // Fallthrough + case 1: date2 = null; break; } modCount++; return previous; @@ -205,9 +210,8 @@ public class DefaultEvaluationMethod extends ISOMetadata implements EvaluationMe * Null values are not allowed. */ @Override - public void add(final int index, final Date value) { - final long date = value.getTime(); - if (date2 == Long.MIN_VALUE) { + public void add(final int index, final Temporal date) { + if (date2 == null) { switch (index) { case 0: { date2 = date1; @@ -216,7 +220,7 @@ public class DefaultEvaluationMethod extends ISOMetadata implements EvaluationMe return; } case 1: { - if (date1 == Long.MIN_VALUE) break; // Exception will be thrown below. + if (date1 == null) break; // Exception will be thrown below. date2 = date; modCount++; return; @@ -231,16 +235,16 @@ public class DefaultEvaluationMethod extends ISOMetadata implements EvaluationMe */ @Override @SuppressWarnings("fallthrough") - public boolean addAll(final Collection<? extends Date> dates) { + public boolean addAll(final Collection<? extends Temporal> dates) { final int c = modCount; if (dates != null) { - final Iterator<? extends Date> it = dates.iterator(); - switch (size()) { // Fallthrough everywhere. + final Iterator<? extends Temporal> it = dates.iterator(); + switch (size()) { // Fallthrough everywhere. case 0: if (!it.hasNext()) break; - date1 = it.next().getTime(); + date1 = it.next(); modCount++; case 1: if (!it.hasNext()) break; - date2 = it.next().getTime(); + date2 = it.next(); modCount++; default: if (!it.hasNext()) break; throw new IllegalArgumentException(Errors.format( @@ -418,7 +422,7 @@ public class DefaultEvaluationMethod extends ISOMetadata implements EvaluationMe @Override @XmlElement(name = "dateTime") @SuppressWarnings("ReturnOfCollectionOrArrayField") - public Collection<Date> getDates() { + public Collection<Temporal> getDates() { if (Semaphores.query(Semaphores.NULL_COLLECTION)) { return isNullOrEmpty(dates) ? null : dates; } @@ -434,7 +438,7 @@ public class DefaultEvaluationMethod extends ISOMetadata implements EvaluationMe * * @param newValues the new dates, or {@code null}. */ - public void setDates(final Collection<? extends Date> newValues) { + public void setDates(final Collection<? extends Temporal> newValues) { if (newValues != dates) { // Mandatory check for avoiding the call to 'dates.clear()'. checkWritePermission(valueIfDefined(dates)); writeDates(newValues); @@ -444,7 +448,7 @@ public class DefaultEvaluationMethod extends ISOMetadata implements EvaluationMe /** * Implementation of {@link #setDates(Collection)}. */ - private void writeDates(final Collection<? extends Date> newValues) { + private void writeDates(final Collection<? extends Temporal> newValues) { if (isNullOrEmpty(newValues)) { dates = null; } else { diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/package-info.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/package-info.java index f5bf8095e8..12ec71efde 100644 --- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/package-info.java +++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/package-info.java @@ -70,6 +70,7 @@ @XmlJavaTypeAdapter(DQM_SourceReference.class), @XmlJavaTypeAdapter(DQM_ValueStructure.class), @XmlJavaTypeAdapter(GO_Boolean.class), + @XmlJavaTypeAdapter(GO_Temporal.class), @XmlJavaTypeAdapter(GO_DateTime.class), @XmlJavaTypeAdapter(GO_GenericName.class), @XmlJavaTypeAdapter(GO_Record.class), diff --git a/core/sis-metadata/src/test/java/org/apache/sis/internal/xml/XmlUtilitiesTest.java b/core/sis-metadata/src/test/java/org/apache/sis/internal/xml/XmlUtilitiesTest.java index b2217b9f52..8c90d2d4cf 100644 --- a/core/sis-metadata/src/test/java/org/apache/sis/internal/xml/XmlUtilitiesTest.java +++ b/core/sis-metadata/src/test/java/org/apache/sis/internal/xml/XmlUtilitiesTest.java @@ -16,10 +16,19 @@ */ package org.apache.sis.internal.xml; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.YearMonth; +import java.time.Year; +import java.time.temporal.Temporal; import java.util.Date; import java.util.Locale; import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.datatype.DatatypeConfigurationException; +import org.apache.sis.internal.jaxb.Context; import org.apache.sis.test.xml.TestCase; import org.junit.Test; @@ -31,24 +40,74 @@ import static javax.xml.datatype.DatatypeConstants.FIELD_UNDEFINED; * Test {@link XmlUtilities}. * * @author Martin Desruisseaux (Geomatys) - * @version 0.3 + * @version 1.3 * @since 0.3 * @module */ public final strictfp class XmlUtilitiesTest extends TestCase { /** - * Tests the {@link XmlUtilities#toXML} method. + * Tests the {@link XmlUtilities#toXML(Context, Date)} method. * This test arbitrarily uses the CET timezone. + * The reverse operation is also tested. * * @throws DatatypeConfigurationException if the XML factory cannot be created. */ @Test - public void testToXML() throws DatatypeConfigurationException { + public void testDateToXML() throws DatatypeConfigurationException { createContext(false, Locale.FRANCE, "CET"); - final XMLGregorianCalendar calendar = XmlUtilities.toXML(context, new Date(1230786000000L)); + final Date date = new Date(1230786000000L); + final XMLGregorianCalendar calendar = XmlUtilities.toXML(context, date); assertEquals("2009-01-01T06:00:00.000+01:00", calendar.toString()); + assertEquals(date, XmlUtilities.toDate(context, calendar)); calendar.setMillisecond(FIELD_UNDEFINED); assertEquals("2009-01-01T06:00:00+01:00", calendar.toString()); } + + /** + * Tests the {@link XmlUtilities#toXML(Context, Temporal)} method. + * This test arbitrarily uses the JST timezone. + * + * @throws DatatypeConfigurationException if the XML factory cannot be created. + */ + @Test + public void testTemporalToXML() throws DatatypeConfigurationException { + createContext(false, Locale.JAPAN, "JST"); + XMLGregorianCalendar calendar; + Temporal t; + + t = Instant.ofEpochMilli(1230786000000L); + calendar = XmlUtilities.toXML(context, t); + assertEquals("2009-01-01T14:00:00.000+09:00", calendar.toString()); + + t = OffsetDateTime.parse("2009-01-01T06:00:00+01:00"); + calendar = XmlUtilities.toXML(context, t); + assertEquals("2009-01-01T06:00:00.000+01:00", calendar.toString()); + assertEquals(t, XmlUtilities.toTemporal(context, calendar)); + + t = LocalDateTime.parse("2009-08-12T06:20:10"); + calendar = XmlUtilities.toXML(context, t); + assertEquals("2009-08-12T06:20:10.000", calendar.toString()); + assertEquals(t, XmlUtilities.toTemporal(context, calendar)); + + t = LocalTime.parse("06:10:45"); + calendar = XmlUtilities.toXML(context, t); + assertEquals("06:10:45.000", calendar.toString()); + assertEquals(t, XmlUtilities.toTemporal(context, calendar)); + + t = LocalDate.parse("2009-05-08"); + calendar = XmlUtilities.toXML(context, t); + assertEquals("2009-05-08", calendar.toString()); + assertEquals(t, XmlUtilities.toTemporal(context, calendar)); + + t = YearMonth.parse("2009-05"); + calendar = XmlUtilities.toXML(context, t); + assertEquals("2009-05", calendar.toString()); + assertEquals(t, XmlUtilities.toTemporal(context, calendar)); + + t = Year.parse("2012"); + calendar = XmlUtilities.toXML(context, t); + assertEquals("2012", calendar.toString()); + assertEquals(t, XmlUtilities.toTemporal(context, calendar)); + } } diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/quality/AbstractElementTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/quality/AbstractElementTest.java index 02392b2c2b..f06163f89c 100644 --- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/quality/AbstractElementTest.java +++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/quality/AbstractElementTest.java @@ -16,98 +16,44 @@ */ package org.apache.sis.metadata.iso.quality; +import java.time.Instant; import java.util.Date; -import java.util.List; +import java.util.Arrays; +import java.util.Iterator; +import java.util.Collection; import org.apache.sis.test.TestCase; import org.junit.Test; -import static org.apache.sis.test.Assert.*; +import static org.junit.Assert.*; /** * Tests {@link AbstractElement}. * * @author Martin Desruisseaux (Geomatys) - * @version 0.3 + * @version 1.3 * @since 0.3 * @module */ public final strictfp class AbstractElementTest extends TestCase { /** - * Tests the {@link AbstractElement#getDates()} list, which is backed by a custom implementation. + * Tests {@link Element#getDates()}. */ @Test - public void testDates() { - final Date now = new Date(); - final Date later = new Date(now.getTime() + 60000); - final List<Date> dates = (List<Date>) new AbstractElement().getDates(); - /* - * dates = [] - */ - assertTrue("isEmpty()", dates.isEmpty()); - assertCanNotGet(dates, 2); - assertCanNotGet(dates, 1); - assertCanNotGet(dates, 0); - /* - * dates = [now] - */ - assertCanNotAdd(dates, 2, now); - assertCanNotAdd(dates, 1, now); - dates.add(0, now); - assertEquals("size()", 1, dates.size()); - assertCanNotGet(dates, 2); - assertCanNotGet(dates, 1); - assertEquals(now, dates.get(0)); - /* - * dates = [now, later] - */ - assertCanNotAdd(dates, 2, later); - dates.add(1, later); - assertEquals("size()", 2, dates.size()); - assertCanNotGet(dates, 2); - assertEquals(later, dates.get(1)); - assertEquals(now, dates.get(0)); - /* - * dates = [later] - */ - assertEquals(now, dates.remove(0)); - assertEquals("size()", 1, dates.size()); - assertCanNotGet(dates, 2); - assertCanNotGet(dates, 1); - assertEquals(later, dates.get(0)); - /* - * dates = [now, later] - */ - dates.add(0, now); - assertEquals("size()", 2, dates.size()); - assertCanNotGet(dates, 2); - assertEquals(later, dates.get(1)); - assertEquals(now, dates.get(0)); + public void testGetDates() { + final Instant startTime = Instant.parse("2009-05-08T14:10:00Z"); + final Instant endTime = Instant.parse("2009-05-12T21:45:00Z"); + final DefaultEvaluationMethod method = new DefaultEvaluationMethod(); + method.setDates(Arrays.asList(startTime, endTime)); + final AbstractElement element = new AbstractElement(); + element.setEvaluationMethod(method); - assertSerializedEquals(dates); - } - - /** - * Asserts that we cannot get a date at the given index in the given list. - */ - private static void assertCanNotGet(final List<Date> dates, final int index) { - try { - dates.get(index); - fail("Should not be allowed to get an element at index " + index); - } catch (IndexOutOfBoundsException e) { - // This is the expected exception. - } - } - - /** - * Asserts that we cannot get add a date at the given index in the given list. - */ - private static void assertCanNotAdd(final List<Date> dates, final int index, final Date date) { - try { - dates.add(index, date); - fail("Should not be allowed to add an element at index " + index); - } catch (IndexOutOfBoundsException e) { - // This is the expected exception. - } + @SuppressWarnings("deprecation") + final Collection<? extends Date> dates = element.getDates(); + assertEquals(2, dates.size()); + final Iterator<? extends Date> it = dates.iterator(); + assertEquals(startTime, it.next().toInstant()); + assertEquals(endTime, it.next().toInstant()); + assertFalse (it.hasNext()); } } diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/quality/AbstractElementTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/quality/DefaultEvaluationMethodTest.java similarity index 80% copy from core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/quality/AbstractElementTest.java copy to core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/quality/DefaultEvaluationMethodTest.java index 02392b2c2b..f475257fb7 100644 --- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/quality/AbstractElementTest.java +++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/quality/DefaultEvaluationMethodTest.java @@ -16,8 +16,9 @@ */ package org.apache.sis.metadata.iso.quality; -import java.util.Date; import java.util.List; +import java.time.Instant; +import java.time.temporal.Temporal; import org.apache.sis.test.TestCase; import org.junit.Test; @@ -25,22 +26,23 @@ import static org.apache.sis.test.Assert.*; /** - * Tests {@link AbstractElement}. + * Tests {@link DefaultEvaluationMethod}. * * @author Martin Desruisseaux (Geomatys) - * @version 0.3 - * @since 0.3 + * @version 1.3 + * @since 1.3 * @module */ -public final strictfp class AbstractElementTest extends TestCase { +public final strictfp class DefaultEvaluationMethodTest extends TestCase { /** - * Tests the {@link AbstractElement#getDates()} list, which is backed by a custom implementation. + * Tests the {@link DefaultEvaluationMethod#getDates()} list, + * which is backed by a custom implementation. */ @Test public void testDates() { - final Date now = new Date(); - final Date later = new Date(now.getTime() + 60000); - final List<Date> dates = (List<Date>) new AbstractElement().getDates(); + final Instant now = Instant.now(); + final Instant later = Instant.ofEpochSecond(now.getEpochSecond()+ 60); + final List<Temporal> dates = (List<Temporal>) new DefaultEvaluationMethod().getDates(); /* * dates = [] */ @@ -90,7 +92,7 @@ public final strictfp class AbstractElementTest extends TestCase { /** * Asserts that we cannot get a date at the given index in the given list. */ - private static void assertCanNotGet(final List<Date> dates, final int index) { + private static void assertCanNotGet(final List<Temporal> dates, final int index) { try { dates.get(index); fail("Should not be allowed to get an element at index " + index); @@ -102,7 +104,7 @@ public final strictfp class AbstractElementTest extends TestCase { /** * Asserts that we cannot get add a date at the given index in the given list. */ - private static void assertCanNotAdd(final List<Date> dates, final int index, final Date date) { + private static void assertCanNotAdd(final List<Temporal> dates, final int index, final Temporal date) { try { dates.add(index, date); fail("Should not be allowed to add an element at index " + index); diff --git a/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java b/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java index 7a16422d54..f815db9985 100644 --- a/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java +++ b/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java @@ -119,6 +119,7 @@ import org.junit.BeforeClass; org.apache.sis.internal.jaxb.metadata.replace.QualityParameterTest.class, org.apache.sis.metadata.iso.identification.DefaultCoupledResourceTest.class, org.apache.sis.metadata.iso.identification.DefaultServiceIdentificationTest.class, + org.apache.sis.metadata.iso.quality.DefaultEvaluationMethodTest.class, org.apache.sis.metadata.iso.quality.AbstractElementTest.class, org.apache.sis.metadata.iso.quality.AbstractPositionalAccuracyTest.class, org.apache.sis.metadata.iso.quality.DefaultDomainConsistencyTest.class,