/**
* Copyright (C) 2008 - 2014 52°North Initiative for Geospatial Open Source
* Software GmbH
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* If the program is linked with libraries which are licensed under one of
* the following licenses, the combination of the program with the linked
* library is not considered a "derivative work" of the program:
*
* - Apache License, version 2.0
* - Apache Software License, version 1.0
* - GNU Lesser General Public License, version 3
* - Mozilla Public License, versions 1.0, 1.1 and 2.0
* - Common Development and Distribution License (CDDL), version 1.0
*
* Therefore the distribution of the program linked with libraries licensed
* under the aforementioned licenses, is permitted by the copyright holders
* if the distribution is compliant with both the GNU General Public
* icense version 2 and the aforementioned licenses.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*/
package org.n52.ses.eml.v002.filter.temporal;
import javax.xml.namespace.QName;
import net.opengis.fes.x20.BinaryTemporalOpType;
import net.opengis.fes.x20.TemporalOpsType;
import org.apache.muse.util.xml.XmlUtils;
import org.apache.xmlbeans.XmlObject;
import org.joda.time.DateTime;
import org.joda.time.Interval;
import org.n52.ses.api.exception.FESParseException;
import org.n52.ses.eml.v002.filter.IFilterElement;
import org.w3c.dom.Node;
/**
*
* @author Thomas Everding
*
*/
public abstract class ATemporalFilter implements IFilterElement {
/**
* Factory to build new comparison filters.
*/
public static final TemporalFilterFactory FACTORY = new TemporalFilterFactory();
private static final String FES_NAMESPACE = "http://www.opengis.net/fes/2.0";
private static final String GML_NAMESPACE = "http://www.opengis.net/gml/3.2";
/**
* qualified name of FES ValueReference
*/
protected static final QName VALUE_REFERENCE_QNAME = new QName(FES_NAMESPACE, "ValueReference");
/**
* qualified name of GML identifier
*/
protected static final QName GML_IDENTIFIER = new QName(GML_NAMESPACE, "identifier");
/**
* qualified name of GML validTime
*/
protected static final QName GML_VALID_TIME = new QName(GML_NAMESPACE, "validTime");
/**
* qualified name of GML TimePeriod
*/
protected static final QName GML_TIME_PERIOD = new QName(GML_NAMESPACE, "TimePeriod");
/**
* qualified name of GML TimeInstant
*/
protected static final QName GML_TIME_INSTANT = new QName(GML_NAMESPACE, "TimeInstant");
/**
* qualified name of GML timePosition
*/
protected static final QName GML_TIME_POSITION = new QName(GML_NAMESPACE, "timePosition");
/**
* qualified name of GML beginPosition
*/
protected static final QName GML_BEGIN_POSITION = new QName(GML_NAMESPACE, "beginPosition");
/**
* qualified name of GML endPosition
*/
protected static final QName GML_END_POSITION = new QName(GML_NAMESPACE, "endPosition");
/**
* xbeans {@link TemporalOpsType}
*/
protected TemporalOpsType temporalOp;
/**
*
* Constructor
*
* @param temporalOp
* XML representation of a temporal filter
*/
public ATemporalFilter(TemporalOpsType temporalOp) {
this.temporalOp = temporalOp;
}
/**
* Parses the gml:validTime from a BinaryTemporalOpType
*
* @param binaryOp
* {@link BinaryTemporalOpType}
* @return jodatime {@link Interval}
*/
protected Interval parseGMLTimePeriodFromBinaryTemporalOp(BinaryTemporalOpType binaryOp) {
XmlObject period = binaryOp.selectChildren(GML_TIME_PERIOD)[0];
String beginPos = "";
XmlObject hasIndeterminate = period.selectChildren(GML_BEGIN_POSITION)[0].selectAttribute(new QName("", "indeterminatePosition"));
if (hasIndeterminate == null) {
beginPos = stripText(period.selectChildren(GML_BEGIN_POSITION));
}
else {
beginPos = stripText(hasIndeterminate);
}
String endPos = "";
hasIndeterminate = period.selectChildren(GML_END_POSITION)[0].selectAttribute(new QName("", "indeterminatePosition"));
if (hasIndeterminate == null) {
endPos = stripText(period.selectChildren(GML_END_POSITION));
}
else {
endPos = stripText(hasIndeterminate);
}
/*
* construct time in millis. for "unknown" set the MAX_VALUE
*/
long beginPosMs, endPosMs = 0L;
if (beginPos.equals("unknown")) {
beginPosMs = Long.MAX_VALUE;
}
else {
beginPosMs = new DateTime(beginPos).getMillis();
}
if (endPos.equals("unknown")) {
endPosMs = Long.MAX_VALUE;
}
else {
endPosMs = new DateTime(endPos).getMillis();
}
return new Interval(beginPosMs, endPosMs);
}
/**
* @param valRef
* xbeans value reference
* @return jodatime {@link Interval}
* @throws FESParseException
* if unexpected error occurs
*/
protected Interval getTimeFromValueReference(XmlObject valRef) throws FESParseException {
String valRefString = XmlUtils.toString(valRef.getDomNode().getFirstChild()).trim();
if (valRefString.endsWith("validTime")) {
return parseValidTime();
}
throw new FESParseException("Only gml:validTime supported at the current developement state");
}
private Interval parseValidTime() {
XmlObject[] valRef = this.temporalOp.selectChildren(VALUE_REFERENCE_QNAME);
if (valRef.length == 2) {
// another valRef, referenced time
// TODO how to parse the time with a ValueReference?
}
else {
XmlObject[] period = this.temporalOp.selectChildren(GML_TIME_PERIOD);
if (period != null && period.length > 0) {
String beginPos = "";
XmlObject hasIndeterminate = period[0].selectChildren(GML_BEGIN_POSITION)[0].selectAttribute(new QName("", "indeterminatePosition"));
if (hasIndeterminate == null) {
beginPos = stripText(period[0].selectChildren(GML_BEGIN_POSITION));
}
else {
beginPos = stripText(hasIndeterminate);
}
String endPos = "";
hasIndeterminate = period[0].selectChildren(GML_END_POSITION)[0].selectAttribute(new QName("", "indeterminatePosition"));
if (hasIndeterminate == null) {
endPos = stripText(period[0].selectChildren(GML_END_POSITION));
}
else {
endPos = stripText(hasIndeterminate);
}
/*
* construct time in millis. for "unknown" set the MAX_VALUE
*/
long beginPosMs, endPosMs = 0L;
if (beginPos.equals("unknown")) {
beginPosMs = Long.MAX_VALUE;
}
else {
beginPosMs = new DateTime(beginPos).getMillis();
}
if (endPos.equals("unknown")) {
endPosMs = Long.MAX_VALUE;
}
else {
endPosMs = new DateTime(endPos).getMillis();
}
return new Interval(beginPosMs, endPosMs);
}
XmlObject[] instant = this.temporalOp.selectChildren(GML_TIME_INSTANT);
if (instant != null && instant.length > 0) {
String timepos = stripText(instant[0].selectChildren(GML_TIME_POSITION));
long beginPosMs = new DateTime(timepos).getMillis();
return new Interval(beginPosMs, beginPosMs);
}
}
return null;
}
/**
* Strips out the text of an xml-element and returns as a String.
*/
private String stripText(XmlObject[] elems) {
if (elems != null && elems.length > 0) {
return stripText(elems[0]);
}
return null;
}
private String stripText(XmlObject elem) {
if (elem != null) {
Node child = elem.getDomNode().getFirstChild();
if (child != null) {
return XmlUtils.toString(child).trim();
}
}
return null;
}
}