/* * Copyright 2011-2013 the original author or authors. * * 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 kr.debop4j.timeperiod; import com.google.common.collect.Lists; import kr.debop4j.core.Guard; import kr.debop4j.timeperiod.tools.TimeSpec; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.joda.time.DateTime; import org.joda.time.Duration; import java.util.*; /** * {@link DateTime}을 요소로 정렬한 컬렉션입니다. * * @author 배성혁 sunghyouk.bae@gmail.com * @since 13. 5. 19. 오전 12:22 */ @Slf4j public class DateTimeSet extends TreeSet<DateTime> implements IDateTimeSet { private static final long serialVersionUID = -1067490053852738541L; @Getter(lazy = true) private static final Comparator<? super DateTime> defaultComparator = new Comparator<DateTime>() { @Override public int compare(DateTime o1, DateTime o2) { return o1.compareTo(o2); } }; /** * Instantiates a new Date time set. */ public DateTimeSet() { } /** * Instantiates a new Date time set. * * @param c the c */ public DateTimeSet(Iterable<? extends DateTime> c) { super(Lists.newArrayList(c)); } /** * Instantiates a new Date time set. * * @param comparator the comparator */ public DateTimeSet(Comparator<? super DateTime> comparator) { super(comparator); } /** * Instantiates a new Date time set. * * @param s the s */ public DateTimeSet(SortedSet<DateTime> s) { super(s); } @Override public DateTime getMin() { return isEmpty() ? null : first(); } @Override public DateTime getMax() { return isEmpty() ? null : last(); } @Override public Duration getDuration() { if (isEmpty()) return null; DateTime min = getMin(); DateTime max = getMax(); return (min != null && max != null) ? new Duration(min, max) : null; } @Override public boolean isMoment() { Duration duration = getDuration(); return (duration != null) && (duration.compareTo(Duration.ZERO) == 0); } @Override public boolean isAnytime() { return getMin() != null && getMin().equals(TimeSpec.MinPeriodTime) && getMax() != null && getMax().equals(TimeSpec.MaxPeriodTime); } @Override public boolean add(DateTime moment) { log.trace("새로운 요소를 추가합니다. moment=[{}]", moment); return !contains(moment) && super.add(moment); } @Override public void addAll(Iterable<DateTime> moments) { super.addAll(Lists.newArrayList(moments)); } /** * 지정된 구간의 {@link Duration}을 계산합니다. * * @param startIndex 시작 인덱스 (0부터 시작) * @param count count (갯수) */ @Override public List<Duration> getDurations(int startIndex, int count) { Guard.shouldBePositiveOrZeroNumber(startIndex, "startIndex"); Guard.shouldBePositiveNumber(count, "count"); Guard.shouldBe(startIndex < count, "startIndex 는 Count보다 작아야 합니다. startIndex=[%d], count=[%d]", startIndex, count); log.trace("duration을 구합니다... startIndex=[{}], count=[{}]", startIndex, count); int endIndex = Math.min(startIndex + count, size() - 1); List<Duration> durations = Lists.newArrayList(); Iterator<DateTime> iter = iterator(); DateTime prevItem = null; while (iter.hasNext()) { DateTime currItem = iter.next(); if (prevItem == null) { prevItem = currItem; } else { durations.add(new Duration(prevItem, currItem)); } } return durations; } /** * 지정된 시각(moment) 바로 전의 시각을 찾습니다. 없으면 null을 반환합니다. * * @param moment 기준 시각 * @return 기준 시각 바로 전의 시각, 없으면 null */ @Override public DateTime findPrevious(DateTime moment) { log.trace("지정된 시각[{}] 바로 전의 시각을 찾습니다. 없으면 null을 반환합니다.", moment); if (isEmpty()) return null; Iterator<DateTime> iter = descendingIterator(); while (iter.hasNext()) { DateTime item = iter.next(); if (item.compareTo(moment) < 0) return item; } return null; } /** * 지정된 시각(moment) 바로 후의 시각을 찾습니다. 없으면 null을 반환합니다. * * @param moment 기준 시각 * @return moment 이후의 시각, 없으면 null 반환 */ @Override public DateTime findNext(DateTime moment) { log.trace("지정된 시각[{}] 바루 후의 시각을 찾습니다. 없으면 null을 반환합니다.", moment); if (isEmpty()) return null; Iterator<DateTime> iter = iterator(); while (iter.hasNext()) { DateTime item = iter.next(); if (item.compareTo(moment) > 0) return item; } return null; } }