• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* //device/apps/Calendar/MonthView.java
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 package com.android.providers.calendar;
19 
20 import android.pim.DateException;
21 import android.text.format.DateUtils;
22 import android.util.Log;
23 
24 import java.util.ArrayList;
25 import java.util.Calendar;
26 import java.util.GregorianCalendar;
27 import java.util.TimeZone;
28 import java.util.regex.Pattern;
29 
30 public class VCal
31 {
32     public static final Pattern LINE = Pattern.compile(
33             "([^:;]+)([^:]*):(.*)");
34 
35     public ArrayList<Property> properties = new ArrayList<Property>();
36     public String dtstart;
37     public String tzid;
38     public String duration;
39     public String rrule;
40     public boolean allDay;
41 
dump()42     public void dump()
43     {
44         System.out.println("-----------------------");
45         dump(properties, "");
46         System.out.println("dtstart='" + this.dtstart + "'");
47         System.out.println("tzid='" + this.tzid + "'");
48         System.out.println("duration='" + this.duration + "'");
49         System.out.println("rrule='" + this.rrule + "'");
50         System.out.println("-----------------------");
51     }
52 
dump(ArrayList<Property> props, String prefix)53     public static void dump(ArrayList<Property> props, String prefix)
54     {
55         int count = props.size();
56         for (int i=0; i<count; i++) {
57             Property prop = props.get(i);
58             System.out.println(prefix + prop.name);
59             if (prop instanceof Begin) {
60                 Begin b = (Begin)prop;
61                 dump(b.properties, prefix + "  ");
62             }
63         }
64    }
65 
66     public static class Parameter
67     {
68         public String name;
69         public String value;
70     }
71 
72     public static class Property
73     {
74         public String name;
75         public Parameter[] parameters;
76         public String value;
77         public String[] values;
78     }
79 
80     public static class Begin extends Property
81     {
82         public Begin parent;
83         public ArrayList<Property> properties = new ArrayList<Property>();
84     }
85 
86 
make(String name)87     public static Property make(String name)
88     {
89         Property p;
90         if (name.equals("BEGIN")) {
91             p = new Begin();
92         }
93         else {
94             p = new Property();
95         }
96         p.name = name;
97         return p;
98     }
99 
parse(String str)100     public static VCal parse(String str)
101     {
102         VCal vc = new VCal();
103 
104         int i, j, start;
105         int N, M;
106 
107         // first we deal with line folding, by replacing all "\r\n " strings
108         // with nothing
109         str = str.replaceAll("\r\n ", "");
110 
111         // it's supposed to be \r\n, but not everyone does that
112         str = str.replaceAll("\r\n", "\n");
113         str = str.replaceAll("\r", "\n");
114 
115         ArrayList<Parameter> params = new ArrayList<Parameter>();
116         ArrayList<Property> props = vc.properties;
117 
118         // then we split into lines
119         String[] lines = str.split("\n");
120 
121         Begin begin = null;
122         //System.out.println("lines.length=" + lines);
123         N = lines.length;
124         for (j=0; j<N; j++) {
125             //System.out.println("===[" + lines[j] + "]===");
126             String line = lines[j];
127             int len = line.length();
128             if (len > 0) {
129                 i = 0;
130                 char c;
131                 do {
132                     c = line.charAt(i);
133                     i++;
134                 } while (c != ';' && c != ':');
135 
136                 String n = line.substring(0, i-1);
137                 Property prop = make(n);
138                 props.add(prop);
139                 if (n.equals("BEGIN")) {
140                     Begin b = (Begin)prop;
141                     b.parent = begin;
142                     begin = b;
143                     props = begin.properties;
144                 }
145                 else if (n.equals("END")) {
146                     begin = begin.parent;
147                     if (begin != null) {
148                         props = begin.properties;
149                     } else {
150                         props = vc.properties;
151                     }
152                 }
153 
154                 //System.out.println("name=[" + prop.name + "]");
155                 params.clear();
156                 while (c == ';') {
157                     Parameter param = new Parameter();
158                     start = i;
159                     i++;
160                     // param name
161                     do {
162                         c = line.charAt(i);
163                         i++;
164                     } while (c != '=');
165                     param.name = line.substring(start, i-1);
166                     //System.out.println(" param.name=[" + param.name + "]");
167                     start = i;
168                     if (line.charAt(start) == '"') {
169                         i++;
170                         start++;
171                         do {
172                             c = line.charAt(i);
173                             i++;
174                         } while (c != '"');
175                         param.value = line.substring(start, i-1);
176                         c = line.charAt(i);
177                         i++;
178                         //System.out.println(" param.valueA=[" + param.value
179                         //                              + "]");
180                     } else {
181                         do {
182                             c = line.charAt(i);
183                             i++;
184                         } while (c != ';' && c != ':');
185                         param.value = line.substring(start, i-1);
186                         //System.out.println(" param.valueB=["
187                         //                              + param.value + "]");
188                     }
189                     params.add(param);
190                 }
191                 Object[] array = params.toArray();
192                 prop.parameters = new Parameter[array.length];
193                 System.arraycopy(array, 0, prop.parameters, 0, array.length);
194                 if (c != ':') {
195                     throw new RuntimeException("error finding ':' c=" + c);
196                 }
197                 prop.value = line.substring(i);
198                 prop.values = line.split(",");
199             }
200         }
201 
202         N = vc.properties.size();
203         Calendar calStart = null;
204         for (i=0; i<N; i++) {
205             Property prop = vc.properties.get(i);
206             String n = prop.name;
207             if (n.equals("DTSTART")) {
208                 try {
209                     calStart = parseDateTime(prop, vc);
210                     vc.dtstart = prop.value;
211                 } catch (DateException de) {
212                     Log.w("CalendarProvider", "Unable to parse DTSTART=" + n, de);
213                     return null;
214                 }
215             } else if (n.equals("DTEND")) {
216                 // TODO: store the dtend, compute when expanding instances?
217                 // will we ever need to deal with seeing the DTEND before the
218                 // DTSTART?
219                 try {
220                     if (calStart == null) {
221                         vc.duration = "+P0S";
222                     } else {
223                         Calendar calEnd =
224                                 parseDateTime(prop, vc);
225                         long durationMillis =
226                                 calEnd.getTimeInMillis() -
227                                         calStart.getTimeInMillis();
228                         long durationSeconds = (durationMillis / 1000);
229                         vc.duration = "+P" + durationSeconds + "S";
230                     }
231                 } catch (DateException de) {
232                     Log.w("CalendarProvider", "Unable to parse DTEND=" + n, de);
233                     return null;
234                 }
235             } else if (n.equals("DURATION")) {
236                 vc.duration = prop.value;
237             } else if (n.equals("RRULE")) {
238                 vc.rrule = prop.value;
239             }
240         }
241         return vc;
242     }
243 
parseDateTime(Property prop, VCal vc)244     private static Calendar parseDateTime(Property prop, VCal vc) throws DateException {
245         int M;
246         int j;
247         String dt = prop.value;
248         M = prop.parameters.length;
249         for (j=0; j<M; j++) {
250             Parameter param = prop.parameters[j];
251             if (param.name.equals("TZID")) {
252                 vc.tzid = param.value;
253             }
254         }
255 
256         TimeZone tz = TimeZone.getTimeZone(vc.tzid);
257         if (tz == null) {
258             tz = TimeZone.getTimeZone("UTC");
259         }
260         GregorianCalendar somewhere = new GregorianCalendar(tz);
261         DateUtils.parseDateTime(dt, somewhere);
262         if (dt.length() == 8) {
263             // this seems to work.
264             vc.allDay = true;
265         }
266         return somewhere;
267         /*GregorianCalendar zulu = new GregorianCalendar(
268                                        TimeZone.getTimeZone("GMT"));
269         zulu.setTimeInMillis(somewhere.getTimeInMillis());
270         return zulu;*/
271         // System.out.println("DTSTART=" + dtstart
272         //         + " somewhere=" + somewhere
273         //         + " vc.dtstart=" + vc.dtstart);
274     }
275 }
276