| /* //device/apps/Calendar/MonthView.java
|
| **
|
| ** Copyright 2006, The Android Open Source Project |
| **
|
| ** 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.android.providers.calendar;
|
|
|
| import android.pim.DateException;
|
| import android.text.format.DateUtils;
|
| import android.util.Log;
|
|
|
| import java.util.ArrayList;
|
| import java.util.Calendar;
|
| import java.util.GregorianCalendar;
|
| import java.util.TimeZone;
|
| import java.util.regex.Pattern;
|
|
|
| public class VCal
|
| {
|
| public static final Pattern LINE = Pattern.compile(
|
| "([^:;]+)([^:]*):(.*)");
|
|
|
| public ArrayList<Property> properties = new ArrayList<Property>();
|
| public String dtstart;
|
| public String tzid;
|
| public String duration;
|
| public String rrule;
|
| public boolean allDay;
|
|
|
| public void dump()
|
| {
|
| System.out.println("-----------------------");
|
| dump(properties, "");
|
| System.out.println("dtstart='" + this.dtstart + "'");
|
| System.out.println("tzid='" + this.tzid + "'");
|
| System.out.println("duration='" + this.duration + "'");
|
| System.out.println("rrule='" + this.rrule + "'");
|
| System.out.println("-----------------------");
|
| }
|
|
|
| public static void dump(ArrayList<Property> props, String prefix)
|
| {
|
| int count = props.size();
|
| for (int i=0; i<count; i++) {
|
| Property prop = props.get(i);
|
| System.out.println(prefix + prop.name);
|
| if (prop instanceof Begin) {
|
| Begin b = (Begin)prop;
|
| dump(b.properties, prefix + " ");
|
| }
|
| }
|
| }
|
|
|
| public static class Parameter
|
| {
|
| public String name;
|
| public String value;
|
| }
|
|
|
| public static class Property
|
| {
|
| public String name;
|
| public Parameter[] parameters;
|
| public String value;
|
| public String[] values;
|
| }
|
|
|
| public static class Begin extends Property
|
| {
|
| public Begin parent;
|
| public ArrayList<Property> properties = new ArrayList<Property>();
|
| }
|
|
|
|
|
| public static Property make(String name)
|
| {
|
| Property p;
|
| if (name.equals("BEGIN")) {
|
| p = new Begin();
|
| }
|
| else {
|
| p = new Property();
|
| }
|
| p.name = name;
|
| return p;
|
| }
|
|
|
| public static VCal parse(String str)
|
| {
|
| VCal vc = new VCal();
|
|
|
| int i, j, start;
|
| int N, M;
|
|
|
| // first we deal with line folding, by replacing all "\r\n " strings
|
| // with nothing
|
| str = str.replaceAll("\r\n ", "");
|
|
|
| // it's supposed to be \r\n, but not everyone does that
|
| str = str.replaceAll("\r\n", "\n");
|
| str = str.replaceAll("\r", "\n");
|
|
|
| ArrayList<Parameter> params = new ArrayList<Parameter>();
|
| ArrayList<Property> props = vc.properties;
|
|
|
| // then we split into lines
|
| String[] lines = str.split("\n");
|
|
|
| Begin begin = null;
|
| //System.out.println("lines.length=" + lines);
|
| N = lines.length;
|
| for (j=0; j<N; j++) {
|
| //System.out.println("===[" + lines[j] + "]===");
|
| String line = lines[j];
|
| int len = line.length();
|
| if (len > 0) {
|
| i = 0;
|
| char c;
|
| do {
|
| c = line.charAt(i);
|
| i++;
|
| } while (c != ';' && c != ':');
|
|
|
| String n = line.substring(0, i-1);
|
| Property prop = make(n);
|
| props.add(prop);
|
| if (n.equals("BEGIN")) {
|
| Begin b = (Begin)prop;
|
| b.parent = begin;
|
| begin = b;
|
| props = begin.properties;
|
| }
|
| else if (n.equals("END")) {
|
| begin = begin.parent;
|
| if (begin != null) {
|
| props = begin.properties;
|
| } else {
|
| props = vc.properties;
|
| }
|
| }
|
|
|
| //System.out.println("name=[" + prop.name + "]");
|
| params.clear();
|
| while (c == ';') {
|
| Parameter param = new Parameter();
|
| start = i;
|
| i++;
|
| // param name
|
| do {
|
| c = line.charAt(i);
|
| i++;
|
| } while (c != '=');
|
| param.name = line.substring(start, i-1);
|
| //System.out.println(" param.name=[" + param.name + "]");
|
| start = i;
|
| if (line.charAt(start) == '"') {
|
| i++;
|
| start++;
|
| do {
|
| c = line.charAt(i);
|
| i++;
|
| } while (c != '"');
|
| param.value = line.substring(start, i-1);
|
| c = line.charAt(i);
|
| i++;
|
| //System.out.println(" param.valueA=[" + param.value
|
| // + "]");
|
| } else {
|
| do {
|
| c = line.charAt(i);
|
| i++;
|
| } while (c != ';' && c != ':');
|
| param.value = line.substring(start, i-1);
|
| //System.out.println(" param.valueB=["
|
| // + param.value + "]");
|
| }
|
| params.add(param);
|
| }
|
| Object[] array = params.toArray();
|
| prop.parameters = new Parameter[array.length];
|
| System.arraycopy(array, 0, prop.parameters, 0, array.length);
|
| if (c != ':') {
|
| throw new RuntimeException("error finding ':' c=" + c);
|
| }
|
| prop.value = line.substring(i);
|
| prop.values = line.split(",");
|
| }
|
| }
|
|
|
| N = vc.properties.size();
|
| Calendar calStart = null;
|
| for (i=0; i<N; i++) {
|
| Property prop = vc.properties.get(i);
|
| String n = prop.name;
|
| if (n.equals("DTSTART")) {
|
| try {
|
| calStart = parseDateTime(prop, vc);
|
| vc.dtstart = prop.value;
|
| } catch (DateException de) {
|
| Log.w("CalendarProvider", "Unable to parse DTSTART=" + n, de);
|
| return null;
|
| }
|
| } else if (n.equals("DTEND")) {
|
| // TODO: store the dtend, compute when expanding instances?
|
| // will we ever need to deal with seeing the DTEND before the
|
| // DTSTART?
|
| try {
|
| if (calStart == null) {
|
| vc.duration = "+P0S";
|
| } else {
|
| Calendar calEnd =
|
| parseDateTime(prop, vc);
|
| long durationMillis =
|
| calEnd.getTimeInMillis() -
|
| calStart.getTimeInMillis();
|
| long durationSeconds = (durationMillis / 1000);
|
| vc.duration = "+P" + durationSeconds + "S";
|
| }
|
| } catch (DateException de) {
|
| Log.w("CalendarProvider", "Unable to parse DTEND=" + n, de);
|
| return null;
|
| }
|
| } else if (n.equals("DURATION")) {
|
| vc.duration = prop.value;
|
| } else if (n.equals("RRULE")) {
|
| vc.rrule = prop.value;
|
| }
|
| }
|
| return vc;
|
| }
|
|
|
| private static Calendar parseDateTime(Property prop, VCal vc) throws DateException {
|
| int M;
|
| int j;
|
| String dt = prop.value;
|
| M = prop.parameters.length;
|
| for (j=0; j<M; j++) {
|
| Parameter param = prop.parameters[j];
|
| if (param.name.equals("TZID")) {
|
| vc.tzid = param.value;
|
| }
|
| }
|
|
|
| TimeZone tz = TimeZone.getTimeZone(vc.tzid);
|
| if (tz == null) {
|
| tz = TimeZone.getTimeZone("UTC");
|
| }
|
| GregorianCalendar somewhere = new GregorianCalendar(tz);
|
| DateUtils.parseDateTime(dt, somewhere);
|
| if (dt.length() == 8) {
|
| // this seems to work.
|
| vc.allDay = true;
|
| }
|
| return somewhere;
|
| /*GregorianCalendar zulu = new GregorianCalendar(
|
| TimeZone.getTimeZone("GMT"));
|
| zulu.setTimeInMillis(somewhere.getTimeInMillis());
|
| return zulu;*/
|
| // System.out.println("DTSTART=" + dtstart
|
| // + " somewhere=" + somewhere
|
| // + " vc.dtstart=" + vc.dtstart);
|
| }
|
| }
|