/*
* Constellation - An open source and standard compliant SDI
* http://www.constellation-sdi.org
*
* Copyright 2014 Geomatys.
*
* Licensed 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.constellation.metadata.io.generic;
// J2SE dependencies
import org.apache.sis.metadata.iso.citation.DefaultCitationDate;
import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
import org.apache.sis.util.iso.SimpleInternationalString;
import org.apache.sis.util.logging.Logging;
import org.constellation.generic.Values;
import org.geotoolkit.ows.xml.v100.BoundingBoxType;
import org.opengis.metadata.citation.CitationDate;
import org.opengis.metadata.citation.DateType;
import org.opengis.metadata.extent.GeographicExtent;
import org.opengis.util.InternationalString;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
// Constellation dependencies
// Geotoolkit dependencies
// GeoAPI dependencies
/**
* A set of static utility methods generally used in sub-implementations of the Generic reader.
* It allows to create more easily geotk ISO object.
*
* @author Guilhem Legal (Geomatys)
*/
public final class GenericMetadataUtilities {
/**
* Forbidden constructor.
*/
private GenericMetadataUtilities() {}
/**
* A List of date formatter.
*/
private static final List<DateFormat> DATE_FORMATS = new ArrayList<DateFormat>();
static {
DATE_FORMATS.add(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
DATE_FORMATS.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"));
DATE_FORMATS.add(new SimpleDateFormat("yyyy-MM-dd"));
DATE_FORMATS.add(new SimpleDateFormat("yyyy"));
}
/**
* A debugging logger
*/
private static final Logger LOGGER = Logging.getLogger("org.constellation.metadata.io.generic");
/**
* Avoid the IllegalArgumentException when the variable value is null.
*
*/
public static InternationalString getInternationalStringVariable(final String value) {
if (value != null){
return new SimpleInternationalString(value);
}
return null;
}
/**
* Parse the specified date and return a CitationDate with the dateType code REVISION.
*
* @param date The date to parse.
*
* @return A CitationDate of type revision.
*/
public static CitationDate createRevisionDate(final String date) {
return createCitationDate(date, DateType.REVISION);
}
/**
* Parse the specified date and return a CitationDate with the dateType code PUBLICATION.
*
* @param date The date to parse.
*
* @return A CitationDate of type revision.
*/
public static CitationDate createPublicationDate(final String date) {
return createCitationDate(date, DateType.PUBLICATION);
}
/**
* Parse the specified date and return a CitationDate with the dateType code CREATION.
*
* @param date The date to parse.
*
* @return A CitationDate of type revision.
*/
public static CitationDate createCreationDate(final String date) {
return createCitationDate(date, DateType.CREATION);
}
/**
* Parse the specified date and return a CitationDate with the specified dateType.
*
* @param date The date to parse.
*
* @return A CitationDate of type revision.
*/
public static CitationDate createCitationDate(final String date, final DateType type) {
final DefaultCitationDate ciDate = new DefaultCitationDate();
ciDate.setDateType(type);
final Date d = parseDate(date);
if (d != null) {
ciDate.setDate(d);
} else {
LOGGER.log(Level.FINER, "citation date null: {0}", date);
}
return ciDate;
}
/**
* Parse a date from a String
* @param date The date to parse.
*/
public static Date parseDate(final String date) {
if (date == null || date.isEmpty()) {return null;}
int i = 0;
while (i < DATE_FORMATS.size()) {
final DateFormat dateFormat = DATE_FORMATS.get(i);
try {
Date d;
synchronized (dateFormat) {
d = dateFormat.parse(date);
}
return d;
} catch (ParseException ex) {
i++;
}
}
LOGGER.log(Level.WARNING, "unable to parse the date: [{0}]", date);
return null;
}
/**
* Extract A list of w-e-s-n coordinates from the values object,
* and return it a many array of 4 double.
*
* @param westVar The name of the west coordinates variable.
* @param eastVar The name of the east coordinates variable.
* @param southVar The name of the south coordinates variable.
* @param northVar The name of the north coordinates variable.
* @param values A set of variables and their corresponding values.
*
* @return
*/
private static List<Double[]> getCoordinateList(final String westVar, final String eastVar,
final String southVar, final String northVar, final Values values) {
final List<Double[]> result = new ArrayList<Double[]>();
final List<String> w = values.getVariables(westVar);
final List<String> e = values.getVariables(eastVar);
final List<String> s = values.getVariables(southVar);
final List<String> n = values.getVariables(northVar);
if (w == null || e == null || s == null || n == null) {
LOGGER.warning("One or more extent/BBOX coordinates are null");
return result;
}
if (!(w.size() == e.size() && e.size() == s.size() && s.size() == n.size())) {
LOGGER.warning("There is not the same number of geographic extent/BBOX coordinates");
return result;
}
final int size = w.size();
for (int i = 0; i < size; i++) {
double west = 0; double east = 0; double south = 0; double north = 0;
String westValue = null; String eastValue = null;
String southValue = null; String northValue = null;
try {
westValue = w.get(i);
if (westValue != null) {
if (westValue.indexOf(',') != -1) {
westValue = westValue.substring(0, westValue.indexOf(','));
}
west = Double.parseDouble(westValue);
}
eastValue = e.get(i);
if (eastValue != null) {
if (eastValue.indexOf(',') != -1) {
eastValue = eastValue.substring(0, eastValue.indexOf(','));
}
east = Double.parseDouble(eastValue);
}
southValue = s.get(i);
if (southValue != null) {
if (southValue.indexOf(',') != -1) {
southValue = southValue.substring(0, southValue.indexOf(','));
}
south = Double.parseDouble(southValue);
}
northValue = n.get(i);
if (northValue != null) {
north = Double.parseDouble(northValue);
}
// for point BBOX we replace the westValue equals to 0 by the eastValue (respectively for north/south)
if (east == 0) {
east = west;
}
if (north == 0) {
north = south;
}
final Double[] coordinate = new Double[4];
coordinate[0] = west;
coordinate[1] = east;
coordinate[2] = south;
coordinate[3] = north;
result.add(coordinate);
} catch (NumberFormatException ex) {
LOGGER.warning("Number format exception while parsing boundingBox:\ncurrent box: " +
westValue + ',' + eastValue + ',' + southValue + ',' + northValue);
}
}
return result;
}
/**
* Extract one or more geographic extent from the values object. (ISO 19139 object)
*
* @param westVar The name of the west coordinates variable.
* @param eastVar The name of the east coordinates variable.
* @param southVar The name of the south coordinates variable.
* @param northVar The name of the north coordinates variable.
* @param values A set of variables and their corresponding values.
*
* @return A list of geographic extent.
*/
public static List<GeographicExtent> createGeographicExtent(final String westVar, final String eastVar,
final String southVar, final String northVar, final Values values) {
final List<GeographicExtent> result = new ArrayList<GeographicExtent>();
final List<Double[]> coordinates = getCoordinateList(westVar, eastVar, southVar, northVar, values);
final int size = coordinates.size();
for (int i = 0; i < size; i++) {
final Double[] coordinate = coordinates.get(i);
final GeographicExtent geo = new DefaultGeographicBoundingBox(coordinate[0], coordinate[1], coordinate[2], coordinate[3]);
result.add(geo);
}
return result;
}
/**
* Extract one or more bounding box from the values object. (Dublin-core object)
*
* @param westVar The name of the west coordinates variable.
* @param eastVar The name of the east coordinates variable.
* @param southVar The name of the south coordinates variable.
* @param northVar The name of the north coordinates variable.
* @param values A set of variables and their corresponding values.
*
* @return A list of BoundingBox.
*/
public static List<BoundingBoxType> createBoundingBoxes(final String westVar, final String eastVar,
final String southVar, final String northVar, final Values values) {
final List<BoundingBoxType> result = new ArrayList<BoundingBoxType>();
final List<Double[]> coordinates = getCoordinateList(westVar, eastVar, southVar, northVar, values);
final int size = coordinates.size();
for (int i = 0; i < size; i++) {
final Double[] coordinate = coordinates.get(i);
//TODO CRS
final BoundingBoxType bbox = new BoundingBoxType("EPSG:4326", coordinate[0], coordinate[2], coordinate[1], coordinate[3]);
result.add(bbox);
}
return result;
}
}