/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library 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 Lesser General Public License for more * details. */ package com.liferay.calendar.internal.recurrence; import com.google.ical.iter.RecurrenceIterator; import com.google.ical.iter.RecurrenceIteratorFactory; import com.google.ical.values.DateValue; import com.google.ical.values.DateValueImpl; import com.liferay.calendar.recurrence.Recurrence; import com.liferay.calendar.recurrence.RecurrenceSerializer; import java.text.ParseException; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import org.osgi.service.component.annotations.Component; /** * @author Adam Brandizzi */ @Component(service = RecurrenceSplitter.class) public class RecurrenceSplitterImpl implements RecurrenceSplitter { @Override public RecurrenceSplit split( Recurrence recurrence, Calendar startTimeJCalendar, Calendar splitTimeJCalendar) { Recurrence firstRecurrence = recurrence.clone(); Recurrence secondRecurrence = recurrence.clone(); try { if (recurrence.getCount() != 0) { _setCount( recurrence, firstRecurrence, secondRecurrence, startTimeJCalendar, splitTimeJCalendar); } else { _setUntilJCalendar( recurrence, firstRecurrence, startTimeJCalendar, splitTimeJCalendar); } _copyExceptionJCalendars( firstRecurrence, secondRecurrence, recurrence.getExceptionJCalendars(), splitTimeJCalendar); } catch (SplitTimeOutsideRecurrenceException store) { firstRecurrence = recurrence.clone(); secondRecurrence = null; } return new RecurrenceSplitImpl(firstRecurrence, secondRecurrence); } private void _copyExceptionJCalendars( Recurrence firstRecurrence, Recurrence secondRecurrence, List<Calendar> exceptionJCalendars, Calendar splitTimeJCalendar) { firstRecurrence.setExceptionJCalendars(new ArrayList<Calendar>()); secondRecurrence.setExceptionJCalendars(new ArrayList<Calendar>()); for (Calendar exceptionJCalendar : exceptionJCalendars) { if (exceptionJCalendar.before(splitTimeJCalendar)) { firstRecurrence.addExceptionJCalendar(exceptionJCalendar); } else { secondRecurrence.addExceptionJCalendar(exceptionJCalendar); } } } private RecurrenceIterator _getRecurrenceIterator( Recurrence recurrence, DateValue startTimeDateValue) { try { return RecurrenceIteratorFactory.createRecurrenceIterator( RecurrenceSerializer.serialize(recurrence), startTimeDateValue, recurrence.getTimeZone()); } catch (ParseException pe) { throw new IllegalStateException(pe); } } private void _setCount( Recurrence recurrence, Recurrence firstRecurrence, Recurrence secondRecurrence, Calendar startTimeJCalendar, Calendar splitTimeJCalendar) throws SplitTimeOutsideRecurrenceException { DateValue startTimeDateValue = _toDateValue(startTimeJCalendar); DateValue splitTimeDateValue = _toDateValue(splitTimeJCalendar); RecurrenceIterator recurrenceIterator = _getRecurrenceIterator( recurrence, startTimeDateValue); DateValue dateValue = recurrenceIterator.next(); int count = 0; while (recurrenceIterator.hasNext()) { if (dateValue.compareTo(splitTimeDateValue) >= 0) { break; } count++; dateValue = recurrenceIterator.next(); } _validateCount(splitTimeDateValue, dateValue); firstRecurrence.setCount(count); secondRecurrence.setCount(recurrence.getCount() - count); } private void _setUntilJCalendar( Recurrence recurrence, Recurrence firstRecurrence, Calendar startTimeJCalendar, Calendar splitTimeJCalendar) throws SplitTimeOutsideRecurrenceException { Calendar untilJCalendar = (Calendar)splitTimeJCalendar.clone(); untilJCalendar.add(Calendar.DATE, -1); _validateUntilJCalendar( untilJCalendar, recurrence.getUntilJCalendar(), startTimeJCalendar); firstRecurrence.setUntilJCalendar(untilJCalendar); } private DateValue _toDateValue(Calendar jCalendar) { return new DateValueImpl( jCalendar.get(Calendar.YEAR), jCalendar.get(Calendar.MONTH) + 1, jCalendar.get(Calendar.DAY_OF_MONTH)); } private void _validateCount( DateValue splitTimeDateValue, DateValue dateValue) throws SplitTimeOutsideRecurrenceException { if (dateValue.compareTo(splitTimeDateValue) < 0) { throw new SplitTimeOutsideRecurrenceException( "There is no instance after split time"); } } private void _validateUntilJCalendar( Calendar newUntilJCalendar, Calendar oldUntilJCalendar, Calendar startTimeJCalendar) throws SplitTimeOutsideRecurrenceException { if (newUntilJCalendar.after(oldUntilJCalendar)) { throw new SplitTimeOutsideRecurrenceException( "Split date comes after the limit date of the recurrence"); } else if (newUntilJCalendar.before(startTimeJCalendar)) { throw new SplitTimeOutsideRecurrenceException( "Split date comes before the start date of the recurrence"); } } private static class SplitTimeOutsideRecurrenceException extends Exception { public SplitTimeOutsideRecurrenceException(String message) { super(message); } } }