use of org.apache.sis.metadata.iso.extent.DefaultTemporalExtent in project sis by apache.
the class AbstractReferenceSystemTest method testWKT.
/**
* Tests WKT formatting with a name that contains the quote character and optional information.
* We test that the closing quote character is doubled and the optional information properly formatted.
*/
@Test
@DependsOnMethod("testCreateFromMap")
public void testWKT() {
final Map<String, Object> properties = new HashMap<>(8);
assertNull(properties.put(NAME_KEY, "My “object”."));
assertNull(properties.put(SCOPE_KEY, "Large scale topographic mapping and cadastre."));
assertNull(properties.put(REMARKS_KEY, "注です。"));
assertNull(properties.put(IDENTIFIERS_KEY, new ImmutableIdentifier(Citations.EPSG, "EPSG", "4326", "8.2", null)));
assertNull(properties.put(DOMAIN_OF_VALIDITY_KEY, new DefaultExtent("Netherlands offshore.", new DefaultGeographicBoundingBox(2.54, 6.40, 51.43, 55.77), new DefaultVerticalExtent(10, 1000, VerticalCRSMock.DEPTH), // TODO: needs sis-temporal module for testing that one.
new DefaultTemporalExtent())));
final AbstractReferenceSystem object = new AbstractReferenceSystem(properties);
assertTrue(object.toString(Convention.WKT1).startsWith("ReferenceSystem[\"My “object”.\", AUTHORITY[\"EPSG\", \"4326\"]]"));
assertWktEquals(Convention.WKT1, "ReferenceSystem[“My \"object\".”, AUTHORITY[“EPSG”, “4326”]]", object);
assertWktEquals(Convention.WKT2, // Quotes replaced
"ReferenceSystem[“My \"object\".”,\n" + " SCOPE[“Large scale topographic mapping and cadastre.”],\n" + " AREA[“Netherlands offshore.”],\n" + " BBOX[51.43, 2.54, 55.77, 6.40],\n" + " VERTICALEXTENT[-1000, -10, LENGTHUNIT[“metre”, 1]],\n" + " ID[“EPSG”, 4326, “8.2”, URI[“urn:ogc:def:referenceSystem:EPSG:8.2:4326”]],\n" + " REMARK[“注です。”]]", object);
assertWktEquals(Convention.WKT2_SIMPLIFIED, "ReferenceSystem[“My \"object\".”,\n" + " Scope[“Large scale topographic mapping and cadastre.”],\n" + " Area[“Netherlands offshore.”],\n" + " BBox[51.43, 2.54, 55.77, 6.40],\n" + " VerticalExtent[-1000, -10],\n" + " Id[“EPSG”, 4326, “8.2”, URI[“urn:ogc:def:referenceSystem:EPSG:8.2:4326”]],\n" + " Remark[“注です。”]]", object);
assertWktEquals(Convention.INTERNAL, // Quote doubled
"ReferenceSystem[“My “object””.”,\n" + " Scope[“Large scale topographic mapping and cadastre.”],\n" + " Area[“Netherlands offshore.”],\n" + " BBox[51.43, 2.54, 55.77, 6.40],\n" + " VerticalExtent[-1000, -10],\n" + " Id[“EPSG”, 4326, “8.2”],\n" + " Remark[“注です。”]]", object);
}
use of org.apache.sis.metadata.iso.extent.DefaultTemporalExtent in project sis by apache.
the class MetadataBuilder method addTemporalExtent.
/**
* Adds a temporal extent covered by the data.
* Storage location is:
*
* <ul>
* <li>{@code metadata/identificationInfo/extent/temporalElement}</li>
* </ul>
*
* @param startTime when the data begins, or {@code null} if unbounded.
* @param endTime when the data ends, or {@code null} if unbounded.
* @throws UnsupportedOperationException if the temporal module is not on the classpath.
*
* @see #addAcquisitionTime(Date)
*/
public final void addTemporalExtent(final Date startTime, final Date endTime) {
if (startTime != null || endTime != null) {
final DefaultTemporalExtent t = new DefaultTemporalExtent();
t.setBounds(startTime, endTime);
addIfNotPresent(extent().getTemporalElements(), t);
}
}
use of org.apache.sis.metadata.iso.extent.DefaultTemporalExtent in project sis by apache.
the class ServicesForMetadata method addElements.
/**
* Initializes a horizontal, vertical and temporal extent with the values inferred from the given envelope.
*
* @param envelope the source envelope.
* @param target the target extent where to store envelope information.
* @throws TransformException if a coordinate transformation was required and failed.
*/
@Override
public void addElements(final Envelope envelope, final DefaultExtent target) throws TransformException {
final CoordinateReferenceSystem crs = envelope.getCoordinateReferenceSystem();
final SingleCRS horizontalCRS = CRS.getHorizontalComponent(crs);
final VerticalCRS verticalCRS = CRS.getVerticalComponent(crs, true);
final TemporalCRS temporalCRS = CRS.getTemporalComponent(crs);
if (horizontalCRS == null && verticalCRS == null && temporalCRS == null) {
throw new TransformException(dimensionNotFound(Resources.Keys.MissingSpatioTemporalDimension_1, crs));
}
if (horizontalCRS != null) {
final DefaultGeographicBoundingBox extent = new DefaultGeographicBoundingBox();
extent.setInclusion(Boolean.TRUE);
setBounds(envelope, extent);
target.getGeographicElements().add(extent);
}
if (verticalCRS != null) {
final DefaultVerticalExtent extent = new DefaultVerticalExtent();
setVerticalExtent(envelope, extent, crs, verticalCRS);
target.getVerticalElements().add(extent);
}
if (temporalCRS != null) {
final DefaultTemporalExtent extent = new DefaultTemporalExtent();
setTemporalExtent(envelope, extent, crs, temporalCRS);
target.getTemporalElements().add(extent);
}
}
use of org.apache.sis.metadata.iso.extent.DefaultTemporalExtent in project sis by apache.
the class GeodeticObjectParser method parseMetadataAndClose.
/**
* Parses an <strong>optional</strong> metadata elements and close.
* This include elements like {@code "SCOPE"}, {@code "ID"} (WKT 2) or {@code "AUTHORITY"} (WKT 1).
* This WKT 1 element has the following pattern:
*
* {@preformat wkt
* AUTHORITY["<name>", "<code>"]
* }
*
* <div class="section">Fallback</div>
* The name is a mandatory property, but some invalid WKT with an empty string exist. In such case,
* we will use the name of the enclosed datum. Indeed, it is not uncommon to have the same name for
* a geographic CRS and its geodetic datum.
*
* @param parent the parent element.
* @param name the name of the parent object being parsed.
* @param fallback the fallback to use if {@code name} is empty.
* @return a properties map with the parent name and the optional authority code.
* @throws ParseException if an element can not be parsed.
*/
@SuppressWarnings("ReturnOfCollectionOrArrayField")
private Map<String, Object> parseMetadataAndClose(final Element parent, final String name, final IdentifiedObject fallback) throws ParseException {
properties.clear();
properties.put(IdentifiedObject.NAME_KEY, (name.isEmpty() && fallback != null) ? fallback.getName() : name);
Element element;
while ((element = parent.pullElement(OPTIONAL, ID_KEYWORDS)) != null) {
final String codeSpace = element.pullString("codeSpace");
// Accepts Integer as well as String.
final String code = element.pullObject("code").toString();
// Accepts Number as well as String.
final Object version = element.pullOptional(Object.class);
final Element citation = element.pullElement(OPTIONAL, WKTKeywords.Citation);
final String authority;
if (citation != null) {
authority = citation.pullString("authority");
citation.close(ignoredElements);
} else {
authority = codeSpace;
}
final Element uri = element.pullElement(OPTIONAL, WKTKeywords.URI);
if (uri != null) {
// TODO: not yet stored, since often redundant with other informations.
uri.pullString("URI");
uri.close(ignoredElements);
}
element.close(ignoredElements);
/*
* Note: we could be tempted to assign the authority to the name as well, like below:
*
* if (name instanceof String) {
* name = new NamedIdentifier(authority, (String) name);
* }
* properties.put(IdentifiedObject.NAME_KEY, name);
*
* However experience shows that it is often wrong in practice, because peoples often
* declare EPSG codes but still use WKT names much shorter than the EPSG names
* (for example "WGS84" for the datum instead than "World Geodetic System 1984"),
* so the name in WKT is often not compliant with the name actually defined by the authority.
*/
final ImmutableIdentifier id = new ImmutableIdentifier(Citations.fromName(authority), codeSpace, code, (version != null) ? version.toString() : null, null);
final Object previous = properties.put(IdentifiedObject.IDENTIFIERS_KEY, id);
if (previous != null) {
Identifier[] identifiers;
if (previous instanceof Identifier) {
identifiers = new Identifier[] { (Identifier) previous, id };
} else {
identifiers = (Identifier[]) previous;
final int n = identifiers.length;
identifiers = Arrays.copyOf(identifiers, n + 1);
identifiers[n] = id;
}
properties.put(IdentifiedObject.IDENTIFIERS_KEY, identifiers);
// REMINDER: values associated to IDENTIFIERS_KEY shall be recognized by 'toIdentifier(Object)'.
}
}
/*
* Other metadata (SCOPE, AREA, etc.). ISO 19162 said that at most one of each type shall be present,
* but our parser accepts an arbitrary amount of some kinds of metadata. They can be recognized by the
* 'while' loop.
*
* Most WKT do not contain any of those metadata, so we perform an 'isEmpty()' check as an optimization
* for those common cases.
*/
if (!parent.isEmpty()) {
/*
* Example: SCOPE["Large scale topographic mapping and cadastre."]
*/
element = parent.pullElement(OPTIONAL, WKTKeywords.Scope);
if (element != null) {
// Other types like Datum use the same key.
properties.put(ReferenceSystem.SCOPE_KEY, element.pullString("scope"));
element.close(ignoredElements);
}
/*
* Example: AREA["Netherlands offshore."]
*/
DefaultExtent extent = null;
while ((element = parent.pullElement(OPTIONAL, WKTKeywords.Area)) != null) {
final String area = element.pullString("area");
element.close(ignoredElements);
if (extent == null) {
extent = new DefaultExtent(area, null, null, null);
} else {
extent.getGeographicElements().add(new DefaultGeographicDescription(area));
}
}
/*
* Example: BBOX[51.43, 2.54, 55.77, 6.40]
*/
while ((element = parent.pullElement(OPTIONAL, WKTKeywords.BBox)) != null) {
final double southBoundLatitude = element.pullDouble("southBoundLatitude");
final double westBoundLongitude = element.pullDouble("westBoundLongitude");
final double northBoundLatitude = element.pullDouble("northBoundLatitude");
final double eastBoundLongitude = element.pullDouble("eastBoundLongitude");
element.close(ignoredElements);
if (extent == null)
extent = new DefaultExtent();
extent.getGeographicElements().add(new DefaultGeographicBoundingBox(westBoundLongitude, eastBoundLongitude, southBoundLatitude, northBoundLatitude));
}
/*
* Example: VERTICALEXTENT[-1000, 0, LENGTHUNIT[“metre”, 1]]
*
* Units are optional, default to metres (no "contextual units" here).
*/
while ((element = parent.pullElement(OPTIONAL, WKTKeywords.VerticalExtent)) != null) {
final double minimum = element.pullDouble("minimum");
final double maximum = element.pullDouble("maximum");
Unit<Length> unit = parseScaledUnit(element, WKTKeywords.LengthUnit, Units.METRE);
element.close(ignoredElements);
if (unit == null)
unit = Units.METRE;
if (extent == null)
extent = new DefaultExtent();
verticalElements = new VerticalInfo(verticalElements, extent, minimum, maximum, unit).resolve(verticalCRS);
}
/*
* Example: TIMEEXTENT[2013-01-01, 2013-12-31]
*
* TODO: syntax like TIMEEXTENT[“Jurassic”, “Quaternary”] is not yet supported.
* See https://issues.apache.org/jira/browse/SIS-163
*
* This operation requires the the sis-temporal module. If not available,
* we will report a warning and leave the temporal extent missing.
*/
while ((element = parent.pullElement(OPTIONAL, WKTKeywords.TimeExtent)) != null) {
if (element.peekValue() instanceof String) {
element.pullString("startTime");
element.pullString("endTime");
element.close(ignoredElements);
warning(parent, element, Errors.formatInternational(Errors.Keys.UnsupportedType_1, "TimeExtent[String,String]"), null);
} else {
final Date startTime = element.pullDate("startTime");
final Date endTime = element.pullDate("endTime");
element.close(ignoredElements);
try {
final DefaultTemporalExtent t = new DefaultTemporalExtent();
t.setBounds(startTime, endTime);
if (extent == null)
extent = new DefaultExtent();
extent.getTemporalElements().add(t);
} catch (UnsupportedOperationException e) {
warning(parent, element, null, e);
}
}
}
if (extent != null) {
properties.put(ReferenceSystem.DOMAIN_OF_VALIDITY_KEY, extent);
}
/*
* Example: REMARK["Замечание на русском языке"]
*/
element = parent.pullElement(OPTIONAL, WKTKeywords.Remark);
if (element != null) {
properties.put(IdentifiedObject.REMARKS_KEY, element.pullString("remarks"));
element.close(ignoredElements);
}
}
parent.close(ignoredElements);
return properties;
}
use of org.apache.sis.metadata.iso.extent.DefaultTemporalExtent in project sis by apache.
the class ServicesForMetadataTest method testTemporalIntersection.
/**
* Tests {@link DefaultTemporalExtent#intersect(TemporalExtent)}.
*
* @throws TransformException if the transformation failed.
*
* @since 0.8
*/
@Test
@Ignore("This operation requires the sis-temporal module.")
public void testTemporalIntersection() throws TransformException {
final DefaultTemporalExtent e1 = new DefaultTemporalExtent();
final DefaultTemporalExtent e2 = new DefaultTemporalExtent();
final Date t1 = TestUtilities.date("2016-12-05 19:45:20");
final Date t2 = TestUtilities.date("2017-02-18 02:12:50");
final Date t3 = TestUtilities.date("2017-11-30 23:50:00");
final Date t4 = TestUtilities.date("2018-05-20 12:30:45");
e1.setBounds(t1, t3);
e2.setBounds(t2, t4);
e1.intersect(e2);
assertEquals("startTime", t2, e1.getStartTime());
assertEquals("endTime", t3, e1.getEndTime());
}
Aggregations