⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 segmentedtimeline.java

📁 大家打开看看啊, 很有用的东西
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
     *
     * @param domainValue domain value to teat as a baseTimeline exception
     */
    public void addBaseTimelineException(long domainValue) {

        Segment baseSegment = baseTimeline.getSegment(domainValue);
        if (baseSegment.inIncludeSegments()) {

            // cycle through all the segments contained in the BaseTimeline exception segment
            Segment segment = getSegment(baseSegment.getSegmentStart());
            while (segment.getSegmentStart() <= baseSegment.getSegmentEnd()) {
                if (segment.inIncludeSegments()) {

                    // find all consecutive included segments
                    long fromDomainValue = segment.getSegmentStart();
                    long toDomainValue;
                    do {
                        toDomainValue = segment.getSegmentEnd();
                        segment.inc();
                    }
                    while (segment.inIncludeSegments());

                    // add the interval as an exception
                    addException(fromDomainValue, toDomainValue);

                }
                else {
                    // this is not one of our included segment, skip it
                    segment.inc();
                }
            }
        }
    }

    /**
     * Adds a segment relative to the baseTimeline as an exception. An exception segment is 
     * defined as a segment to exclude from what would otherwise be considered a valid segment 
     * of the timeline.
     * An exception segment can not be contained inside an already excluded segment.
     * If so, no action will occure (the proposed exception segment will be discarted).
     * <p>
     * The segment is identified by a domainValue into any part of the segment.
     * Therefore the segmentStart <= domainValue <= segmentEnd.
     *
     * @param date date domain value to teat as a baseTimeline exception
     */
    public void addBaseTimelineException(Date date) {
        addBaseTimelineException(getTime(date));
    }

    /**
     * Adds all excluded segments from the BaseTimeline as exceptions to our timeline. This allows
     * us to combine two timelines for more complex calculations.
     *
     * @param fromBaseDomainValue Start of the range where exclusions will be extracted.
     * @param toBaseDomainValue End of the range to process.
     */
    public void addBaseTimelineExclusions(long fromBaseDomainValue, long toBaseDomainValue) {

        // find first excluded base segment starting fromDomainValue
        Segment baseSegment = baseTimeline.getSegment(fromBaseDomainValue);
        while (baseSegment.getSegmentStart() <= toBaseDomainValue 
               && !baseSegment.inExcludeSegments()) {
                   
            baseSegment.inc();
            
        }

        // cycle over all the base segments groups in the range
        while (baseSegment.getSegmentStart() <= toBaseDomainValue) {

            long baseExclusionRangeEnd = baseSegment.getSegmentStart() 
                 + baseTimeline.getSegmentsExcluded() * baseTimeline.getSegmentSize() - 1;

            // cycle through all the segments contained in the base exclusion area
            Segment segment = getSegment(baseSegment.getSegmentStart());
            while (segment.getSegmentStart() <= baseExclusionRangeEnd) {
                if (segment.inIncludeSegments()) {

                    // find all consecutive included segments
                    long fromDomainValue = segment.getSegmentStart();
                    long toDomainValue;
                    do {
                        toDomainValue = segment.getSegmentEnd();
                        segment.inc();
                    }
                    while (segment.inIncludeSegments());

                    // add the interval as an exception
                    addException(new BaseTimelineSegmentRange(fromDomainValue, toDomainValue));
                }
                else {
                    // this is not one of our included segment, skip it
                    segment.inc();
                }
            }

            // go to next base segment group
            baseSegment.inc(baseTimeline.getSegmentsGroup());
        }
    }

    /**
     * Returns the number of exception segments wholy contained in the
     * (fromDomainValue, toDomainValue) interval.
     *
     * @param fromDomainValue Beginning of the interval
     * @param toDomainValue End of interval
     * @return Number of exception segments contained in the interval.
     */
    public long getExceptionSegmentCount(long fromDomainValue, long toDomainValue) {
        if (toDomainValue < fromDomainValue) {
            return (0);
        }

        int n = 0;
        for (Iterator iter = exceptionSegments.iterator(); iter.hasNext();) {
            Segment segment = (Segment) iter.next();
            Segment intersection = segment.intersect(fromDomainValue, toDomainValue);
            if (intersection != null) {
                n += intersection.getSegmentCount();
            }
        }

        return (n);
    }

    /**
     * Returns a segment that contains a domainValue. If the domainValue is not contained
     * in the timeline (because it is not contained in the baseTimeline),
     * a Segment that contains <code>index + segmentSize*m</code> will be returned for the
     * smallest <code>m</code> possible.

     * @param domainValue index into the segment
     * @return a Segment that contains index, or the next possible Segment.
     */
    public Segment getSegment(long domainValue) {
        return (new Segment(domainValue));
    }

    /**
     * Returns a segment that contains a date. For accurate calculations,
     * the calendar should use TIME_ZONE for its calculation (or any other similar time zone).
     *
     * If the date is not contained in the timeline (because it is not contained in the 
     * baseTimeline), a Segment that contains <code>date + segmentSize*m</code> will be returned 
     * for the smallest <code>m</code> possible.
     *
     * @param date date into the segment
     * @return a Segment that contains date, or the next possible Segment.
     */
    public Segment getSegment(Date date) {
        return (getSegment(getTime(date)));
    }

    /**
     * Convenient method to test equality in two object taking into account nulls.
     * @param o first object to compare
     * @param p second object to compare
     * @return true if both objects are equal or both null, false otherwise.
     */
    private boolean equals(Object o, Object p) {
        return (o == p || ((o != null) && o.equals(p)));
    }

    /**
     * Returns true if we are equal to the parameter
     * @param o Object to verify with us
     * @return true or false
     */
    public boolean equals(Object o) {
        if (o instanceof SegmentedTimeline) {
            SegmentedTimeline other = (SegmentedTimeline) o;
            return (segmentSize == other.getSegmentSize() 
                    && segmentsIncluded == other.getSegmentsIncluded() 
                    && segmentsExcluded == other.getSegmentsExcluded() 
                    && startTime == other.getStartTime() 
                    && equals(exceptionSegments, other.getExceptionSegments()));
        } 
        else {
            return (false);
        }
    }

    /**
     * Preforms a binary serach in the exceptionSegments sorted array. This array can contain
     * Segments or SegmentRange objects.
     *
     * @param  segment the key to be searched for.
     * 
     * @return index of the search segment, if it is contained in the list;
     *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The
     *         <i>insertion point</i> is defined as the point at which the
     *         segment would be inserted into the list: the index of the first
     *         element greater than the key, or <tt>list.size()</tt>, if all
     *         elements in the list are less than the specified segment.  Note
     *         that this guarantees that the return value will be &gt;= 0 if
     *         and only if the key is found.
     */
    private int binarySearchExceptionSegments(Segment segment) {
        int low = 0;
        int high = exceptionSegments.size() - 1;

        while (low <= high) {
            int mid = (low + high) / 2;
            Segment midSegment = (Segment) exceptionSegments.get(mid);

            // first test for equality (contains or contained)
            if (segment.contains(midSegment) || midSegment.contains(segment)) {
                return (mid);
            }

            if (midSegment.before(segment)) {
                low = mid + 1;
            } 
            else if (midSegment.after(segment)) {
                high = mid - 1;
            } 
            else {
                throw new IllegalStateException("Invalid condition.");
            }
        }
        return -(low + 1);  // key not found
    }

    /**
     * Special method that handles conversion between the Default Time Zone and a UTC time zone
     * with no DST. This is needed so all days have the same size. This method is the prefered
     * way of converting a Data into milliseconds for usage in this class.
     *
     * @param date Date to convert to long.
     * 
     * @return The milliseconds.
     */
    public long getTime(Date date) {
        workingCalendar.setTime(date);
        workingCalendarNoDST.set(workingCalendar.get(Calendar.YEAR),
                                 workingCalendar.get(Calendar.MONTH),
                                 workingCalendar.get(Calendar.DATE),
                                 workingCalendar.get(Calendar.HOUR_OF_DAY),
                                 workingCalendar.get(Calendar.MINUTE),
                                 workingCalendar.get(Calendar.SECOND));
        workingCalendarNoDST.set(Calendar.MILLISECOND, workingCalendar.get(Calendar.MILLISECOND));
        return (workingCalendarNoDST.getTime().getTime());
    }

    /** 
     * Converts a millisecond value into a {@link Date} object.
     * 
     * @param value  the millisecond value.
     * 
     * @return The date.
     */
    public Date getDate(long value) {
        workingCalendarNoDST.setTime(new Date(value));
        return (workingCalendarNoDST.getTime());
    }

    /**
     * Internal class to represent a valid Segment valid for this timeline. A segment
     * is valid on a timeline if it is part of its incluced, excluded or exception
     * segments.
     * <p>
     * Each segment will know its segment number, segmentStart, segmentEnd and
     * index inside the segment.
     */
    public class Segment implements Comparable, Cloneable, Serializable {

        /** The segment number. */
        protected long segmentNumber;
        
        /** The segment start. */
        protected long segmentStart;
        
        /** The segment end. */
        protected long segmentEnd;
        
        /** The index. */
        protected long index;

        /**
         * Protected constructor only used by sub-classes.
         */
        protected Segment() {
        }

        /**
         * Creates a segment based on an index inside the segment
         * 
         * @param index index inside the segment
         */
        protected Segment(long index) {
            this.segmentNumber = getSegmentNumber(index);
            this.segmentStart = startTime + segmentNumber * segmentSize;
            this.segmentEnd = segmentStart + segmentSize - 1;
            this.index = index;
        }

        /**
         * Returns the segment number of an index.
         * 
         * @param index index inside the segment
         * 
         * @return The segment number.
         */
        public long getSegmentNumber(long index) {
            return ((index - startTime) / segmentSize);
        }

        /**
         * Returns the segment number of this segment. Segments start at 0.
         * 
         * @return The segment number.
         */
        public long getSegmentNumber() {
            return (segmentNumber);
        }

        /**
         * Returns always one (the number of segments contained in this segment).
         * 
         * @return The segment count (always 1 for this class).
         */
        public long getSegmentCount() {
            return (1);
        }

        /**
         * Gets the start of this segment in ms.
         * 
         * @return The segment start.
         */
        public long getSegmentStart() {
            return (segmentStart);
        }

        /**
         * Gets the end of this segment in ms.
         * 
         * @return The segment end.
         */
        public long getSegmentEnd() {
            return (segmentEnd);
        }

        /**
         * Gets the index in this segment. Index will always be between the segmentStart
         * and segmentEnd.
         * 
         * @return The index.
         */
        public long getIndex() {
            return (index);
        }

        /**
         * Gets a Date that represents the index of this segment.
         * 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -