/**
  * Returns a cached onset for the specified date.
  *
  * @param date
  * @return a cached onset date or null if no cached onset is applicable for the specified date
  */
 private DateTime getCachedOnset(final Date date) {
   int index = Arrays.binarySearch(onsetsMillisec, date.getTime());
   if (index >= 0) {
     return onsetsDates[index];
   } else {
     int insertionIndex = -index - 1;
     return onsetsDates[insertionIndex - 1];
   }
 }
예제 #2
0
  /**
   * Build recurring properties from ical recurrence.
   *
   * @param r
   * @return RecurTyp filled in
   * @throws Throwable
   */
  public static RecurType doRecur(final Recur r) throws Throwable {
    RecurType rt = new RecurType();

    rt.setFreq(FreqRecurType.fromValue(r.getFrequency()));
    if (r.getCount() > 0) {
      rt.setCount(BigInteger.valueOf(r.getCount()));
    }

    Date until = r.getUntil();
    if (until != null) {
      UntilRecurType u = new UntilRecurType();
      XcalUtil.initUntilRecur(u, until.toString());
    }

    if (r.getInterval() > 0) {
      rt.setInterval(String.valueOf(r.getInterval()));
    }

    listFromNumberList(rt.getBysecond(), r.getSecondList());

    listFromNumberList(rt.getByminute(), r.getMinuteList());

    listFromNumberList(rt.getByhour(), r.getHourList());

    if (r.getDayList() != null) {
      List<String> l = rt.getByday();

      for (Object o : r.getDayList()) {
        l.add(((WeekDay) o).getDay());
      }
    }

    listFromNumberList(rt.getByyearday(), r.getYearDayList());

    intlistFromNumberList(rt.getBymonthday(), r.getMonthDayList());

    listFromNumberList(rt.getByweekno(), r.getWeekNoList());

    intlistFromNumberList(rt.getBymonth(), r.getMonthList());

    bigintlistFromNumberList(rt.getBysetpos(), r.getSetPosList());

    return rt;
  }
  @Override
  @SuppressWarnings("unchecked")
  public String encode(List<CalendarEvent> events) {

    if (events == null || events.isEmpty()) {
      throw new IllegalArgumentException("The calendar events must be defined to encode them");
    }
    Calendar calendarIcs = new Calendar();
    calendarIcs.getProperties().add(new ProdId("-//Silverpeas//iCal4j 1.1//FR"));
    calendarIcs.getProperties().add(Version.VERSION_2_0);
    calendarIcs.getProperties().add(CalScale.GREGORIAN);
    List<VEvent> iCalEvents = new ArrayList<VEvent>();
    ByteArrayOutputStream output = new ByteArrayOutputStream(10240);
    for (CalendarEvent event : events) {
      Date startDate = anICal4JDateCodec().encode(event.getStartDate());
      Date endDate = anICal4JDateCodec().encode(event.getEndDate());
      VEvent iCalEvent;
      if (event.isOnAllDay() && startDate.equals(endDate)) {
        iCalEvent = new VEvent(startDate, event.getTitle());
      } else {
        iCalEvent = new VEvent(startDate, endDate, event.getTitle());
      }

      // Generate UID
      iCalEvent.getProperties().add(generator.generateUid());

      // Add recurring data if any
      if (event.isRecurring()) {
        CalendarEventRecurrence eventRecurrence = event.getRecurrence();
        Recur recur = anICal4JRecurrenceCodec().encode(eventRecurrence);
        iCalEvent.getProperties().add(new RRule(recur));
        iCalEvent.getProperties().add(exceptionDatesFrom(eventRecurrence));
      }
      // Add Description
      iCalEvent.getProperties().add(new Description(event.getDescription()));
      // Add Classification
      iCalEvent.getProperties().add(new Clazz(event.getAccessLevel()));
      // Add Priority
      iCalEvent.getProperties().add(new Priority(event.getPriority()));

      // Add location if any
      if (!event.getLocation().isEmpty()) {
        iCalEvent.getProperties().add(new Location(event.getLocation()));
      }

      // Add event URL if any
      if (event.getUrl() != null) {
        try {
          iCalEvent.getProperties().add(new Url(event.getUrl().toURI()));
        } catch (URISyntaxException ex) {
          throw new EncodingException(ex.getMessage(), ex);
        }
      }

      // Add Categories
      TextList categoryList = new TextList(event.getCategories().asArray());
      if (!categoryList.isEmpty()) {
        iCalEvent.getProperties().add(new Categories(categoryList));
      }
      // Add attendees
      for (String attendee : event.getAttendees().asList()) {
        try {
          iCalEvent.getProperties().add(new Attendee(attendee));
        } catch (URISyntaxException ex) {
          throw new EncodingException("Malformed attendee URI: " + attendee, ex);
        }
      }

      iCalEvents.add(iCalEvent);
    }
    calendarIcs.getComponents().addAll(iCalEvents);
    CalendarOutputter outputter = new CalendarOutputter();
    try {
      outputter.output(calendarIcs, output);
      return output.toString(CharEncoding.UTF_8);
    } catch (Exception ex) {
      throw new EncodingException(
          "The encoding of the events in iCal formatted text has failed!", ex);
    } finally {
      IOUtils.closeQuietly(output);
    }
  }
 //    private Date calculateOnset(DateProperty dateProperty) {
 //        return calculateOnset(dateProperty.getValue());
 //    }
 //
 private DateTime calculateOnset(Date date) throws ParseException {
   return calculateOnset(date.toString());
 }
  /**
   * Returns the latest applicable onset of this observance for the specified date.
   *
   * @param date the latest date that an observance onset may occur
   * @return the latest applicable observance date or null if there is no applicable observance
   *     onset for the specified date
   */
  public final Date getLatestOnset(final Date date) {

    if (initialOnset == null) {
      try {
        initialOnset =
            applyOffsetFrom(calculateOnset(((DtStart) getProperty(Property.DTSTART)).getDate()));
      } catch (ParseException e) {
        Log log = LogFactory.getLog(Observance.class);
        log.error("Unexpected error calculating initial onset", e);
        // XXX: is this correct?
        return null;
      }
    }

    // observance not applicable if date is before the effective date of this observance..
    if (date.before(initialOnset)) {
      return null;
    }

    if ((onsetsMillisec != null) && (onsetLimit == null || date.before(onsetLimit))) {
      return getCachedOnset(date);
    }

    Date onset = initialOnset;
    Date initialOnsetUTC;
    // get first onset without adding TZFROM as this may lead to a day boundary
    // change which would be incompatible with BYDAY RRULES
    // we will have to add the offset to all cacheable onsets
    try {
      initialOnsetUTC = calculateOnset(((DtStart) getProperty(Property.DTSTART)).getDate());
    } catch (ParseException e) {
      Log log = LogFactory.getLog(Observance.class);
      log.error("Unexpected error calculating initial onset", e);
      // XXX: is this correct?
      return null;
    }
    // collect all onsets for the purposes of caching..
    final DateList cacheableOnsets = new DateList();
    cacheableOnsets.setUtc(true);
    cacheableOnsets.add(initialOnset);

    // check rdates for latest applicable onset..
    final PropertyList rdates = getProperties(Property.RDATE);
    for (final Iterator i = rdates.iterator(); i.hasNext(); ) {
      final RDate rdate = (RDate) i.next();
      for (final Iterator j = rdate.getDates().iterator(); j.hasNext(); ) {
        try {
          final DateTime rdateOnset = applyOffsetFrom(calculateOnset((Date) j.next()));
          if (!rdateOnset.after(date) && rdateOnset.after(onset)) {
            onset = rdateOnset;
          }
          /*
           * else if (rdateOnset.after(date) && rdateOnset.after(onset) && (nextOnset == null ||
           * rdateOnset.before(nextOnset))) { nextOnset = rdateOnset; }
           */
          cacheableOnsets.add(rdateOnset);
        } catch (ParseException e) {
          Log log = LogFactory.getLog(Observance.class);
          log.error("Unexpected error calculating onset", e);
        }
      }
    }

    // check recurrence rules for latest applicable onset..
    final PropertyList rrules = getProperties(Property.RRULE);
    for (final Iterator i = rrules.iterator(); i.hasNext(); ) {
      final RRule rrule = (RRule) i.next();
      // include future onsets to determine onset period..
      final Calendar cal = Dates.getCalendarInstance(date);
      cal.setTime(date);
      cal.add(Calendar.YEAR, 10);
      onsetLimit = Dates.getInstance(cal.getTime(), Value.DATE_TIME);
      final DateList recurrenceDates =
          rrule.getRecur().getDates(initialOnsetUTC, onsetLimit, Value.DATE_TIME);
      for (final Iterator j = recurrenceDates.iterator(); j.hasNext(); ) {
        final DateTime rruleOnset = applyOffsetFrom((DateTime) j.next());
        if (!rruleOnset.after(date) && rruleOnset.after(onset)) {
          onset = rruleOnset;
        }
        /*
         * else if (rruleOnset.after(date) && rruleOnset.after(onset) && (nextOnset == null ||
         * rruleOnset.before(nextOnset))) { nextOnset = rruleOnset; }
         */
        cacheableOnsets.add(rruleOnset);
      }
    }

    // cache onsets..
    Collections.sort(cacheableOnsets);
    DateTime cacheableOnset = null;
    this.onsetsMillisec = new long[cacheableOnsets.size()];
    this.onsetsDates = new DateTime[onsetsMillisec.length];

    for (int i = 0; i < onsetsMillisec.length; i++) {
      cacheableOnset = (DateTime) cacheableOnsets.get(i);
      onsetsMillisec[i] = cacheableOnset.getTime();
      onsetsDates[i] = cacheableOnset;
    }

    return onset;
  }