All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.ical.values.RRule Maven / Gradle / Ivy

There is a newer version: 7.4.3.112-ga112
Show newest version
// Copyright (C) 2006 Google Inc.
//
// 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 com.google.ical.values;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * encapsulates an RFC 2445 RRULE or EXRULE.
 *
 * @author [email protected] (Mike Samuel)
 */
public class RRule extends AbstractIcalObject {

  private Frequency freq;
  private Weekday wkst;
  private DateValue until;
  private int count;
  private int interval;
  private List byDay = new ArrayList();
  private int[] byMonth = NO_INTS;  // in +/-[1-12]
  private int[] byMonthDay = NO_INTS;  // in +/-[1-31]
  private int[] byWeekNo = NO_INTS;  // in +/-[1-53]
  private int[] byYearDay = NO_INTS;  // in +/-[1-366]
  private int[] byHour = NO_INTS;  // in [0-23]
  private int[] byMinute = NO_INTS;  // in [0-59]
  private int[] bySecond = NO_INTS;  // in [0-60]
  private int[] bySetPos = NO_INTS;  // in +/-[1-366]

  private static final int[] NO_INTS = new int[0];

  public RRule() {
    this.freq = Frequency.DAILY;
    setName("RRULE");
  }

  public RRule(String icalString) throws ParseException {
    parse(VcalRewriter.rewriteRule(icalString), RRuleSchema.instance());
  }

  /**
   * formats as an *unfolded* RFC 2445 content line.
   */
  public String toIcal() {
    StringBuilder buf = new StringBuilder();
    buf.append(this.getName());
    if (hasExtParams()) {
      for (Map.Entry param : getExtParams().entrySet()) {
        String k = param.getKey(),
               v = param.getValue();
        if (ICAL_SPECIALS.matcher(v).find()) {
          v = "\"" + v + "\"";
        }
        buf.append(';').append(k).append('=').append(v);
      }
    }
    buf.append(":FREQ=").append(freq);
    if (null != wkst) {
      buf.append(";WKST=").append(wkst.toString());
    }
    if (null != this.until) {
      buf.append(";UNTIL=").append(until);
      if (until instanceof TimeValue) {
        buf.append('Z');
      }
    }
    if (count != 0) {
      buf.append(";COUNT=").append(count);
    }
    if (interval != 0) {
      buf.append(";INTERVAL=").append(interval);
    }
    if (0 != byYearDay.length) {
      buf.append(";BYYEARDAY=");
      writeIntList(byYearDay, buf);
    }
    if (0 != byMonth.length) {
      buf.append(";BYMONTH=");
      writeIntList(byMonth, buf);
    }
    if (0 != byMonthDay.length) {
      buf.append(";BYMONTHDAY=");
      writeIntList(byMonthDay, buf);
    }
    if (0 != byWeekNo.length) {
      buf.append(";BYWEEKNO=");
      writeIntList(byWeekNo, buf);
    }
    if (!byDay.isEmpty()) {
      buf.append(";BYDAY=");
      boolean first = true;
      for (WeekdayNum day : this.byDay) {
        if (!first) {
          buf.append(',');
        } else {
          first = false;
        }
        buf.append(day);
      }
    }
    if (0 != byHour.length) {
      buf.append(";BYHOUR=");
      writeIntList(byHour, buf);
    }
    if (0 != byMinute.length) {
      buf.append(";BYMINUTE=");
      writeIntList(byMinute, buf);
    }
    if (0 != bySecond.length) {
      buf.append(";BYSECOND=");
      writeIntList(bySecond, buf);
    }
    if (0 != bySetPos.length) {
      buf.append(";BYSETPOS=");
      writeIntList(bySetPos, buf);
    }
    return buf.toString();
  }

  private static void writeIntList(int[] nums, StringBuilder out) {
    for (int i = 0; i < nums.length; ++i) {
      if (0 != i) { out.append(','); }
      out.append(nums[i]);
    }
  }

  /** an approximate number of days between occurences. */
  public int approximateIntervalInDays() {
    int freqLengthDays;
    int nPerPeriod = 0;
    switch (this.freq) {
      case DAILY:
        freqLengthDays = 1;
        break;
      case WEEKLY:
        freqLengthDays = 7;
        if (!this.byDay.isEmpty()) {
          nPerPeriod = this.byDay.size();
        }
        break;
      case MONTHLY:
        freqLengthDays = 30;
        if (!this.byDay.isEmpty()) {
          for (WeekdayNum day : byDay) {
            // if it's every weekday in the month, assume four of that weekday,
            // otherwise there is one of that week-in-month,weekday pair
            nPerPeriod += 0 != day.num ? 1 : 4;
          }
        } else {
          nPerPeriod = this.byMonthDay.length;
        }
        break;
      case YEARLY:
        freqLengthDays = 365;

        int monthCount = 12;
        if (0 != this.byMonth.length) {
          monthCount = this.byMonth.length;
        }

        if (!this.byDay.isEmpty()) {
          for (WeekdayNum day : byDay) {
            // if it's every weekend in the months in the year,
            // assume 4 of that weekday per month,
            // otherwise there is one of that week-in-month,weekday pair per
            // month
            nPerPeriod += (0 != day.num ? 1 : 4) * monthCount;
          }
        } else if (0 != this.byMonthDay.length) {
          nPerPeriod += monthCount * this.byMonthDay.length;
        } else {
          nPerPeriod += this.byYearDay.length;
        }
        break;
      default: freqLengthDays = 0;
    }
    if (0 == nPerPeriod) { nPerPeriod = 1; }

    return ((freqLengthDays / nPerPeriod) * this.interval);
  }

  /** the frequency of repetition */
  public Frequency getFreq() { return this.freq; }
  public void setFreq(Frequency freq) {
    this.freq = freq;
  }
  /** day of the week the week starts on */
  public Weekday getWkSt() { return this.wkst; }
  public void setWkSt(Weekday wkst) {
    this.wkst = wkst;
  }
  public DateValue getUntil() { return this.until; }
  public void setUntil(DateValue until) {
    this.until = until;
  }
  public int getCount() { return this.count; }
  public void setCount(int count) {
    this.count = count;
  }
  public int getInterval() { return this.interval; }
  public void setInterval(int interval) {
    this.interval = interval;
  }
  public List getByDay() { return this.byDay; }
  public void setByDay(List byDay) {
    this.byDay = new ArrayList(byDay);
  }
  public int[] getByMonth() { return this.byMonth; }
  public void setByMonth(int[] byMonth) {
    this.byMonth = byMonth.clone();
  }
  public int[] getByMonthDay() { return this.byMonthDay; }
  public void setByMonthDay(int[] byMonthDay) {
    this.byMonthDay = byMonthDay.clone();
  }
  public int[] getByWeekNo() { return this.byWeekNo; }
  public void setByWeekNo(int[] byWeekNo) {
    this.byWeekNo = byWeekNo.clone();
  }
  public int[] getByYearDay() { return this.byYearDay; }
  public void setByYearDay(int[] byYearDay) {
    this.byYearDay = byYearDay.clone();
  }
  public int[] getBySetPos() { return this.bySetPos; }
  public void setBySetPos(int[] bySetPos) {
    this.bySetPos = bySetPos.clone();
  }
  public int[] getByHour() { return this.byHour; }
  public void setByHour(int[] byHour) {
    this.byHour = byHour.clone();
  }
  public int[] getByMinute() { return this.byMinute; }
  public void setByMinute(int[] byMinute) {
    this.byMinute = byMinute.clone();
  }
  public int[] getBySecond() { return this.bySecond; }
  public void setBySecond(int[] bySecond) {
    this.bySecond = bySecond.clone();
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy