org.n52.shetland.ogc.gml.time.TimePeriod.java Source code

Java tutorial

Introduction

Here is the source code for org.n52.shetland.ogc.gml.time.TimePeriod.java

Source

/*
 * Copyright 2015-2018 52North Initiative for Geospatial Open Source
 * Software GmbH
 *
 * 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.n52.shetland.ogc.gml.time;

import java.text.ParseException;
import java.util.Collection;
import java.util.Date;
import java.util.Optional;

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.Interval;
import org.joda.time.Period;
import org.joda.time.format.ISOPeriodFormat;

import org.n52.shetland.util.CollectionHelper;

/**
 * Class represents a GML conform timePeriod element.
 *
 * @since 1.0.0
 */
public class TimePeriod extends Time {
    /**
     * serial number
     */
    private static final long serialVersionUID = -1784577421975774171L;

    /** start Date of timePeriod */
    private DateTime start;

    /** indeterminate position of startPosition */
    private IndeterminateValue startIndet;

    /** end Date of timePeriod */
    private DateTime end;

    /** indeterminate position of endPosition */
    private IndeterminateValue endIndet;

    /** duration value ISO8601 format */
    private Period duration;

    /** interval value ISO8601 format */
    private String interval;

    /**
     * default constructor
     *
     */
    public TimePeriod() {
    }

    /**
     * Creates a new {@code TimePeriod} from an {@code Interval}.
     *
     * @param interval the interval
     */
    public TimePeriod(Interval interval) {
        this(interval.getStart(), interval.getEnd());
    }

    /**
     * constructor with start and end date as parameters
     *
     * @param start
     *            start date of the time period
     * @param end
     *            end date of the time period
     */
    public TimePeriod(DateTime start, DateTime end) {
        this.start = start;
        this.end = end;
    }

    /**
     * constructor
     *
     * @param start
     *            start date of the time period
     * @param end
     *            end date of the time period
     * @param id
     *            GML id
     */
    public TimePeriod(DateTime start, DateTime end, String id) {
        super(id);
        this.start = start;
        this.end = end;
    }

    /**
     * constructor
     *
     * @param start
     *            start date of the time period
     * @param startIndet
     *            indeterminate time position of start
     * @param end
     *            end date of the time period
     * @param endIndet
     *            indeterminate time value of end position
     */
    public TimePeriod(DateTime start, IndeterminateValue startIndet, DateTime end, IndeterminateValue endIndet) {
        this.start = start;
        this.startIndet = startIndet;
        this.end = end;
        this.endIndet = endIndet;
    }

    /**
     * standard constructor
     *
     * @param start
     *            timeString of start position in ISO8601 format
     * @param startIndet
     *            indeterminate time position of start
     * @param end
     *            timeString of end position in ISO8601 format
     * @param endIndet
     *            indeterminate time value of end position
     * @param duration
     *            duration in ISO8601 format
     * @param id
     *            the optional GML id
     * @throws ParseException
     *             if parsing the time strings of start or end into
     *             java.util.Date failed
     */
    public TimePeriod(DateTime start, IndeterminateValue startIndet, DateTime end, IndeterminateValue endIndet,
            String duration, String id) throws ParseException {
        super(id);
        this.start = start;
        this.startIndet = startIndet;
        this.end = end;
        this.endIndet = endIndet;
        this.duration = ISOPeriodFormat.standard().parsePeriod(duration);
    }

    /**
     * Constructor using {@link TimeInstant}s
     *
     * @param startTime
     *            Start TimeInstant
     * @param endTime
     *            End TimeInstant
     */
    public TimePeriod(TimeInstant startTime, TimeInstant endTime) {
        if (startTime != null) {
            this.start = startTime.getValue();
            this.startIndet = startTime.getIndeterminateValue();
        }
        if (endTime != null) {
            this.end = endTime.getValue();
            this.endIndet = endTime.getIndeterminateValue();
        }
    }

    /**
     * Constructor using Java {@link Date}s, setting unknown indeterminate
     * values if null
     *
     * @param start
     *            start Date
     * @param end
     *            end Date
     */
    public TimePeriod(Date start, Date end) {
        if (start != null) {
            this.start = new DateTime(start, DateTimeZone.UTC);
        } else {
            this.startIndet = IndeterminateValue.UNKNOWN;
        }
        if (end != null) {
            this.end = new DateTime(end, DateTimeZone.UTC);
        } else {
            this.endIndet = IndeterminateValue.UNKNOWN;
        }
    }

    /**
     * Constructor using Java {@link Object}s, setting unknown indeterminate
     * values if null
     *
     * @param start
     *            start {@link Object}
     * @param end
     *            end {@link Object}
     */
    public TimePeriod(Object start, Object end) {
        if (start != null) {
            this.start = new DateTime(start, DateTimeZone.UTC);
        } else {
            this.startIndet = IndeterminateValue.UNKNOWN;
        }
        if (end != null) {
            this.end = new DateTime(end, DateTimeZone.UTC);
        } else {
            this.endIndet = IndeterminateValue.UNKNOWN;
        }
    }

    /**
     * Get duration
     *
     * @return Returns the duration.
     */
    public Period getDuration() {
        return duration;
    }

    /**
     * Set duration
     *
     * @param duration
     *            The duration to set.
     */
    public void setDuration(Period duration) {
        this.duration = duration;
    }

    /**
     * Get start time
     *
     * @return Returns the start.
     */
    public DateTime getStart() {
        return start;
    }

    /**
     * Set start time
     *
     * @param start
     *            The start to set.
     */
    public void setStart(DateTime start) {
        this.start = start;
    }

    /**
     * Get start time, resolving indeterminate value if start is null
     *
     * @return Returns the resolved start time.
     */
    public DateTime resolveStart() {
        return resolveDateTime(start, startIndet);
    }

    /**
     * Get end time
     *
     * @return Returns the end.
     */
    public DateTime getEnd() {
        return end;
    }

    /**
     * Set end time
     *
     * @param end
     *            The end to set.
     */
    public void setEnd(DateTime end) {
        this.end = end;
    }

    /**
     * Get end time, resolving indeterminate value if start is null
     *
     * @return Returns the resolved end time.
     */
    public DateTime resolveEnd() {
        return resolveDateTime(end, endIndet);
    }

    /**
     * Get start indet time
     *
     * @return Returns the startIndet.
     */
    public IndeterminateValue getStartIndet() {
        return startIndet;
    }

    /**
     * Set start indet time
     *
     * @param startIndet
     *            The startIndet to set.
     */
    public void setStartIndet(IndeterminateValue startIndet) {
        this.startIndet = startIndet;
    }

    /**
     * Get end indet time
     *
     * @return Returns the endIndet.
     */
    public IndeterminateValue getEndIndet() {
        return endIndet;
    }

    /**
     * Set end indet time
     *
     * @param endIndet
     *            The endIndet to set.
     */
    public void setEndIndet(IndeterminateValue endIndet) {
        this.endIndet = endIndet;
    }

    /**
     * Get interval
     *
     * @return Interval string
     */
    public String getInterval() {
        return this.interval;
    }

    /**
     * Set interval
     *
     * @param interval
     *            the interval
     */
    public void setInterval(String interval) {
        this.interval = interval;
    }

    /**
     * Get TimePosition for start.
     *
     * @return Start TimePosition object
     */
    public TimePosition getStartTimePosition() {
        if (isSetStartIndeterminateValue()) {
            return new TimePosition(getStartIndet());
        } else {
            return new TimePosition(getStart(), getTimeFormat());
        }
    }

    /**
     * Get TimePosition for end.
     *
     * @return End TimePosition object
     */
    public TimePosition getEndTimePosition() {
        if (isSetEndIndeterminateValue()) {
            return new TimePosition(getEndIndet());
        } else {
            return new TimePosition(getEnd(), getTimeFormat());
        }
    }

    /**
     * Extend TimePeriod to contain provided collection of {@link Time}s
     *
     * @param times
     *            the times to contain
     */
    public void extendToContain(Collection<Time> times) {
        if (CollectionHelper.isNotEmpty(times)) {
            times.forEach(this::extendToContain);
        }
    }

    /**
     * Extend TimePeriod to contain provided {@link Time}
     *
     * @param time
     *            To contain {@link Time}
     */
    public void extendToContain(Time time) {
        if (time instanceof TimeInstant) {
            extendToContain((TimeInstant) time);
        } else if (time instanceof TimePeriod) {
            extendToContain((TimePeriod) time);
        } else {
            String errorMsg = String.format("Received Time type \"%s\" unknown.",
                    Optional.ofNullable(time).map(Object::getClass).map(Class::getName).orElse("null"));
            throw new IllegalArgumentException(errorMsg);
        }
    }

    /**
     * Extend TimePeriod to contain another {@link TimePeriod}
     *
     * @param period
     *            To contain {@link TimePeriod}
     */
    public void extendToContain(TimePeriod period) {
        extendToContain(period.getStart());
        extendToContain(period.getEnd());
        checkTimeFormat(period.getTimeFormat());
    }

    /**
     * Extend TimePeriod to contain {@link TimeInstant}
     *
     * @param instant
     *            To contain {@link TimeInstant}
     */
    public void extendToContain(TimeInstant instant) {
        if (instant != null) {
            extendToContain(instant.getValue());
            checkTimeFormat(instant.getTimeFormat());
        }
    }

    /**
     * Extend TimePeriod to contain DateTime. Used by other extendToContain
     * methods.
     *
     * @param time
     *            the time to contain
     */
    public void extendToContain(DateTime time) {
        if (time != null) {
            if (!isSetStart() || time.isBefore(getStart())) {
                setStart(time);
            }
            if (!isSetEnd() || time.isAfter(getEnd())) {
                setEnd(time);
            }
        }
    }

    /**
     * Is this TimePeriod contained by another TimePeriod? Equal start/end times
     * are considered to be containing, as are equal indeterminate times.
     *
     * @param otherTimePeriod
     *            Potentially containing TimePeriod
     * @return Whether the argument TimePeriod contains this one
     */
    public boolean isWithin(TimePeriod otherTimePeriod) {
        if (otherTimePeriod == null) {
            throw new NullPointerException("otherTimePeriod cannot be null");
        }
        boolean startWithin = false;
        boolean endWithin = false;
        if (start != null && otherTimePeriod.getStart() != null) {
            startWithin = start.isEqual(otherTimePeriod.getStart()) || start.isAfter(otherTimePeriod.getStart());
        } else if (start == null && otherTimePeriod.getStart() == null && startIndet != null
                && otherTimePeriod.getStartIndet() != null && startIndet.equals(otherTimePeriod.getStartIndet())) {
            startWithin = true;
        }
        if (end != null && otherTimePeriod.getEnd() != null) {
            endWithin = end.isEqual(otherTimePeriod.getEnd()) || end.isBefore(otherTimePeriod.getEnd());
        } else if (end == null && otherTimePeriod.getEnd() == null && endIndet != null
                && otherTimePeriod.getEndIndet() != null && endIndet.equals(otherTimePeriod.getEndIndet())) {
            endWithin = true;
        }
        return startWithin && endWithin;
    }

    /**
     * Checks this timeFormat with passed
     *
     * @param timeFormat
     *            TimeFormat to check with local
     */
    private void checkTimeFormat(TimeFormat timeFormat) {
        if (this.getTimeFormat().equals(TimeFormat.NOT_SET)) {
            this.setTimeFormat(timeFormat);
        } else {
            if (!this.getTimeFormat().equals(timeFormat) && TimeFormat.SUPPORTED_FORMATS.contains(timeFormat)) {
                this.setTimeFormat(timeFormat);
            }
        }
    }

    @Override
    public String toString() {
        StringBuilder result = new StringBuilder("Time period: ");
        if (isSetStart()) {
            result.append(getStart().toString()).append(", ");
        }
        result.append(getStartIndet()).append(", ");
        if (isSetEnd()) {
            result.append(getEnd().toString()).append(", ");
        }
        result.append(getEndIndet());
        return result.toString();
    }

    @Override
    public int compareTo(Time o) {
        if (o instanceof TimeInstant) {
            TimeInstant ti = (TimeInstant) o;
            if (getEnd().isBefore(ti.getValue())) {
                return -1;
            } else if (getStart().isAfter(ti.getValue())) {
                return 1;
            }
        } else if (o instanceof TimePeriod) {
            TimePeriod tp = (TimePeriod) o;
            if (getStart().isBefore(tp.getStart())) {
                return -1;
            } else if (getEnd().isAfter(tp.getEnd())) {
                return 1;
            }
        }
        return 0;
    }

    /**
     * @return <tt>true</tt>, if start and end are NOT set
     * @see #isSetStart()
     * @see #isSetEnd()
     */
    @Override
    public boolean isEmpty() {
        return !isSetEnd() && !isSetStart();
    }

    /**
     * @return <tt>true</tt>, if start is set
     * @see #isEmpty()
     * @see #isSetEnd()
     */
    public boolean isSetStart() {
        return getStart() != null;
    }

    /**
     * @return <tt>true</tt>, if start IndeterminateValue is set
     */
    public boolean isSetStartIndeterminateValue() {
        return getStartIndet() != null;
    }

    /**
     * @return <tt>true</tt>, if end IndeterminateValue is set
     */
    public boolean isSetEndIndeterminateValue() {
        return getEndIndet() != null;
    }

    /**
     * @return <tt>true</tt>, if end is set
     * @see #isSetStart()
     * @see #isEmpty()
     */
    public boolean isSetEnd() {
        return getEnd() != null;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((getDuration() != null) ? getDuration().hashCode() : 0);
        result = prime * result + ((getEnd() != null) ? getEnd().hashCode() : 0);
        result = prime * result + ((getEndIndet() != null) ? getEndIndet().hashCode() : 0);
        result = prime * result + ((getInterval() != null) ? getInterval().hashCode() : 0);
        result = prime * result + ((getStart() != null) ? getStart().hashCode() : 0);
        result = prime * result + ((getStartIndet() != null) ? getStartIndet().hashCode() : 0);
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof TimePeriod)) {
            return false;
        }
        TimePeriod other = (TimePeriod) obj;
        if (getDuration() == null) {
            if (other.getDuration() != null) {
                return false;
            }
        } else if (!getDuration().equals(other.getDuration())) {
            return false;
        }
        if (getEnd() == null) {
            if (other.getEnd() != null) {
                return false;
            }
        } else if (!getEnd().equals(other.getEnd())) {
            return false;
        }
        if (getEndIndet() == null) {
            if (other.getEndIndet() != null) {
                return false;
            }
        } else if (!getEndIndet().equals(other.getEndIndet())) {
            return false;
        }
        if (getInterval() == null) {
            if (other.getInterval() != null) {
                return false;
            }
        } else if (!getInterval().equals(other.getInterval())) {
            return false;
        }
        if (getStart() == null) {
            if (other.getStart() != null) {
                return false;
            }
        } else if (!getStart().equals(other.getStart())) {
            return false;
        }
        if (getStartIndet() == null) {
            if (other.getStartIndet() != null) {
                return false;
            }
        } else if (!getStartIndet().equals(other.getStartIndet())) {
            return false;
        }
        return true;
    }
}