19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.pim; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Config; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.LinkedHashMap; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.LinkedList; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Set; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Parses RFC 2445 iCalendar objects. 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class ICalendar { 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "Sync"; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO: keep track of VEVENT, VTODO, VJOURNAL, VFREEBUSY, VTIMEZONE, VALARM 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // components, by type field or by subclass? subclass would allow us to 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // enforce grammars. 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Exception thrown when an iCalendar object has invalid syntax. 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static class FormatException extends Exception { 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public FormatException() { 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(); 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public FormatException(String msg) { 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(msg); 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public FormatException(String msg, Throwable cause) { 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(msg, cause); 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A component within an iCalendar (VEVENT, VTODO, VJOURNAL, VFEEBUSY, 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * VTIMEZONE, VALARM). 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static class Component { 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // components 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String BEGIN = "BEGIN"; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String END = "END"; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String NEWLINE = "\n"; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final String VCALENDAR = "VCALENDAR"; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final String VEVENT = "VEVENT"; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final String VTODO = "VTODO"; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final String VJOURNAL = "VJOURNAL"; 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final String VFREEBUSY = "VFREEBUSY"; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final String VTIMEZONE = "VTIMEZONE"; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final String VALARM = "VALARM"; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final String mName; 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Component mParent; // see if we can get rid of this 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private LinkedList<Component> mChildren = null; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final LinkedHashMap<String, ArrayList<Property>> mPropsMap = 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new LinkedHashMap<String, ArrayList<Property>>(); 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates a new component with the provided name. 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param name The name of the component. 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Component(String name, Component parent) { 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mName = name; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mParent = parent; 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the name of the component. 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The name of the component. 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String getName() { 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mName; 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the parent of this component. 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The parent of this component. 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Component getParent() { 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mParent; 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Helper that lazily gets/creates the list of children. 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The list of children. 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected LinkedList<Component> getOrCreateChildren() { 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mChildren == null) { 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildren = new LinkedList<Component>(); 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mChildren; 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Adds a child component to this component. 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param child The child component. 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void addChild(Component child) { 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getOrCreateChildren().add(child); 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns a list of the Component children of this component. May be 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * null, if there are no children. 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A list of the children. 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public List<Component> getComponents() { 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mChildren; 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Adds a Property to this component. 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param prop 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void addProperty(Property prop) { 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String name= prop.getName(); 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Property> props = mPropsMap.get(name); 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (props == null) { 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project props = new ArrayList<Property>(); 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPropsMap.put(name, props); 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project props.add(prop); 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns a set of the property names within this component. 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A set of property names within this component. 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Set<String> getPropertyNames() { 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mPropsMap.keySet(); 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns a list of properties with the specified name. Returns null 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * if there are no such properties. 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param name The name of the property that should be returned. 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A list of properties with the requested name. 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public List<Property> getProperties(String name) { 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mPropsMap.get(name); 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the first property with the specified name. Returns null 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * if there is no such property. 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param name The name of the property that should be returned. 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The first property with the specified name. 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Property getFirstProperty(String name) { 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project List<Property> props = mPropsMap.get(name); 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (props == null || props.size() == 0) { 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return props.get(0); 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String toString() { 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb = new StringBuilder(); 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project toString(sb); 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(NEWLINE); 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sb.toString(); 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Helper method that appends this component to a StringBuilder. The 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * caller is responsible for appending a newline at the end of the 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * component. 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void toString(StringBuilder sb) { 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(BEGIN); 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(":"); 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(mName); 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(NEWLINE); 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // append the properties 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String propertyName : getPropertyNames()) { 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (Property property : getProperties(propertyName)) { 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project property.toString(sb); 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(NEWLINE); 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // append the sub-components 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mChildren != null) { 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (Component component : mChildren) { 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project component.toString(sb); 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(NEWLINE); 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(END); 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(":"); 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(mName); 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A property within an iCalendar component (e.g., DTSTART, DTEND, etc., 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * within a VEVENT). 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static class Property { 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // properties 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO: do we want to list these here? the complete list is long. 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final String DTSTART = "DTSTART"; 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final String DTEND = "DTEND"; 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final String DURATION = "DURATION"; 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final String RRULE = "RRULE"; 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final String RDATE = "RDATE"; 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final String EXRULE = "EXRULE"; 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final String EXDATE = "EXDATE"; 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ... need to add more. 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final String mName; 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private LinkedHashMap<String, ArrayList<Parameter>> mParamsMap = 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new LinkedHashMap<String, ArrayList<Parameter>>(); 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String mValue; // TODO: make this final? 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates a new property with the provided name. 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param name The name of the property. 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Property(String name) { 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mName = name; 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates a new property with the provided name and value. 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param name The name of the property. 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value The value of the property. 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Property(String name, String value) { 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mName = name; 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mValue = value; 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the name of the property. 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The name of the property. 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String getName() { 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mName; 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the value of this property. 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The value of this property. 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String getValue() { 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mValue; 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the value of this property. 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value The desired value for this property. 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setValue(String value) { 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mValue = value; 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Adds a {@link Parameter} to this property. 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param param The parameter that should be added. 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void addParameter(Parameter param) { 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Parameter> params = mParamsMap.get(param.name); 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (params == null) { 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project params = new ArrayList<Parameter>(); 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mParamsMap.put(param.name, params); 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project params.add(param); 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the set of parameter names for this property. 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The set of parameter names for this property. 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Set<String> getParameterNames() { 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mParamsMap.keySet(); 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the list of parameters with the specified name. May return 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * null if there are no such parameters. 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param name The name of the parameters that should be returned. 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The list of parameters with the specified name. 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public List<Parameter> getParameters(String name) { 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mParamsMap.get(name); 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the first parameter with the specified name. May return 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * nll if there is no such parameter. 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param name The name of the parameter that should be returned. 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The first parameter with the specified name. 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Parameter getFirstParameter(String name) { 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Parameter> params = mParamsMap.get(name); 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (params == null || params.size() == 0) { 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return params.get(0); 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String toString() { 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb = new StringBuilder(); 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project toString(sb); 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sb.toString(); 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Helper method that appends this property to a StringBuilder. The 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * caller is responsible for appending a newline after this property. 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void toString(StringBuilder sb) { 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(mName); 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Set<String> parameterNames = getParameterNames(); 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String parameterName : parameterNames) { 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (Parameter param : getParameters(parameterName)) { 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(";"); 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project param.toString(sb); 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(":"); 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(mValue); 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A parameter defined for an iCalendar property. 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO: make this a proper class rather than a struct? 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static class Parameter { 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String name; 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String value; 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates a new empty parameter. 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Parameter() { 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates a new parameter with the specified name and value. 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param name The name of the parameter. 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value The value of the parameter. 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Parameter(String name, String value) { 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.name = name; 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.value = value; 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String toString() { 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb = new StringBuilder(); 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project toString(sb); 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sb.toString(); 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Helper method that appends this parameter to a StringBuilder. 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void toString(StringBuilder sb) { 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(name); 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("="); 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(value); 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final class ParserState { 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // public int lineNumber = 0; 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String line; // TODO: just point to original text 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int index; 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // use factory method 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ICalendar() { 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO: get rid of this -- handle all of the parsing in one pass through 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the text. 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static String normalizeText(String text) { 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // it's supposed to be \r\n, but not everyone does that 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text = text.replaceAll("\r\n", "\n"); 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text = text.replaceAll("\r", "\n"); 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we deal with line folding, by replacing all "\n " strings 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // with nothing. The RFC specifies "\r\n " to be folded, but 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we handle "\n " and "\r " too because we can get those. 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text = text.replaceAll("\n ", ""); 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return text; 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Parses text into an iCalendar component. Parses into the provided 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * component, if not null, or parses into a new component. In the latter 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * case, expects a BEGIN as the first line. Returns the provided or newly 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * created top-level component. 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO: use an index into the text, so we can make this a recursive 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // function? 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static Component parseComponentImpl(Component component, 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String text) 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws FormatException { 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Component current = component; 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ParserState state = new ParserState(); 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state.index = 0; 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // split into lines 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] lines = text.split("\n"); 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // each line is of the format: 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // name *(";" param) ":" value 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String line : lines) { 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project current = parseLine(line, state, current); 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // if the provided component was null, we will return the root 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // NOTE: in this case, if the first line is not a BEGIN, a 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // FormatException will get thrown. 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (component == null) { 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project component = current; 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (FormatException fe) { 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Config.LOGV) { 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(TAG, "Cannot parse " + line, fe); 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // for now, we ignore the parse error. Google Calendar seems 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // to be emitting some misformatted iCalendar objects. 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return component; 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Parses a line into the provided component. Creates a new component if 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the line is a BEGIN, adding the newly created component to the provided 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * parent. Returns whatever component is the current one (to which new 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * properties will be added) in the parse. 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static Component parseLine(String line, ParserState state, 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Component component) 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws FormatException { 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state.line = line; 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = state.line.length(); 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // grab the name 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = 0; 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (state.index = 0; state.index < len; ++state.index) { 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c = line.charAt(state.index); 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c == ';' || c == ':') { 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String name = line.substring(0, state.index); 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (component == null) { 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!Component.BEGIN.equals(name)) { 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new FormatException("Expected BEGIN"); 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Property property; 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Component.BEGIN.equals(name)) { 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // start a new component 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String componentName = extractValue(state); 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Component child = new Component(componentName, component); 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (component != null) { 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project component.addChild(child); 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return child; 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (Component.END.equals(name)) { 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // finish the current component 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String componentName = extractValue(state); 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (component == null || 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project !componentName.equals(component.getName())) { 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new FormatException("Unexpected END " + componentName); 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return component.getParent(); 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project property = new Property(name); 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c == ';') { 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Parameter parameter = null; 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while ((parameter = extractParameter(state)) != null) { 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project property.addParameter(parameter); 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String value = extractValue(state); 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project property.setValue(value); 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project component.addProperty(property); 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return component; 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Extracts the value ":..." on the current line. The first character must 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be a ':'. 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static String extractValue(ParserState state) 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws FormatException { 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String line = state.line; 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state.index >= line.length() || line.charAt(state.index) != ':') { 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new FormatException("Expected ':' before end of line in " 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + line); 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String value = line.substring(state.index + 1); 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state.index = line.length() - 1; 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return value; 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Extracts the next parameter from the line, if any. If there are no more 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * parameters, returns null. 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static Parameter extractParameter(ParserState state) 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws FormatException { 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String text = state.line; 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = text.length(); 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Parameter parameter = null; 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int startIndex = -1; 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int equalIndex = -1; 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (state.index < len) { 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = text.charAt(state.index); 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c == ':') { 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (parameter != null) { 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (equalIndex == -1) { 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new FormatException("Expected '=' within " 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + "parameter in " + text); 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project parameter.value = text.substring(equalIndex + 1, 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state.index); 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return parameter; // may be null 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (c == ';') { 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (parameter != null) { 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (equalIndex == -1) { 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new FormatException("Expected '=' within " 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + "parameter in " + text); 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project parameter.value = text.substring(equalIndex + 1, 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state.index); 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return parameter; 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project parameter = new Parameter(); 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project startIndex = state.index; 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (c == '=') { 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project equalIndex = state.index; 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((parameter == null) || (startIndex == -1)) { 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new FormatException("Expected ';' before '=' in " 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + text); 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project parameter.name = text.substring(startIndex + 1, equalIndex); 58106912bddc6b9db4fd01ed689ca4a8e16b0790244Alon Albert } else if (c == '"') { 58206912bddc6b9db4fd01ed689ca4a8e16b0790244Alon Albert if (parameter == null) { 58306912bddc6b9db4fd01ed689ca4a8e16b0790244Alon Albert throw new FormatException("Expected parameter before '\"' in " + text); 58406912bddc6b9db4fd01ed689ca4a8e16b0790244Alon Albert } 58506912bddc6b9db4fd01ed689ca4a8e16b0790244Alon Albert if (equalIndex == -1) { 58606912bddc6b9db4fd01ed689ca4a8e16b0790244Alon Albert throw new FormatException("Expected '=' within parameter in " + text); 58706912bddc6b9db4fd01ed689ca4a8e16b0790244Alon Albert } 58806912bddc6b9db4fd01ed689ca4a8e16b0790244Alon Albert if (state.index > equalIndex + 1) { 58906912bddc6b9db4fd01ed689ca4a8e16b0790244Alon Albert throw new FormatException("Parameter value cannot contain a '\"' in " + text); 59006912bddc6b9db4fd01ed689ca4a8e16b0790244Alon Albert } 59106912bddc6b9db4fd01ed689ca4a8e16b0790244Alon Albert final int endQuote = text.indexOf('"', state.index + 1); 59206912bddc6b9db4fd01ed689ca4a8e16b0790244Alon Albert if (endQuote < 0) { 59306912bddc6b9db4fd01ed689ca4a8e16b0790244Alon Albert throw new FormatException("Expected closing '\"' in " + text); 59406912bddc6b9db4fd01ed689ca4a8e16b0790244Alon Albert } 59506912bddc6b9db4fd01ed689ca4a8e16b0790244Alon Albert parameter.value = text.substring(state.index + 1, endQuote); 59606912bddc6b9db4fd01ed689ca4a8e16b0790244Alon Albert state.index = endQuote + 1; 59706912bddc6b9db4fd01ed689ca4a8e16b0790244Alon Albert return parameter; 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ++state.index; 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new FormatException("Expected ':' before end of line in " + text); 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Parses the provided text into an iCalendar object. The top-level 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * component must be of type VCALENDAR. 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param text The text to be parsed. 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The top-level VCALENDAR component. 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws FormatException Thrown if the text could not be parsed into an 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * iCalendar VCALENDAR object. 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static Component parseCalendar(String text) throws FormatException { 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Component calendar = parseComponent(null, text); 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (calendar == null || !Component.VCALENDAR.equals(calendar.getName())) { 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new FormatException("Expected " + Component.VCALENDAR); 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return calendar; 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Parses the provided text into an iCalendar event. The top-level 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * component must be of type VEVENT. 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param text The text to be parsed. 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The top-level VEVENT component. 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws FormatException Thrown if the text could not be parsed into an 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * iCalendar VEVENT. 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static Component parseEvent(String text) throws FormatException { 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Component event = parseComponent(null, text); 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (event == null || !Component.VEVENT.equals(event.getName())) { 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new FormatException("Expected " + Component.VEVENT); 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return event; 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Parses the provided text into an iCalendar component. 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param text The text to be parsed. 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The top-level component. 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws FormatException Thrown if the text could not be parsed into an 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * iCalendar component. 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static Component parseComponent(String text) throws FormatException { 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return parseComponent(null, text); 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Parses the provided text, adding to the provided component. 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param component The component to which the parsed iCalendar data should 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be added. 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param text The text to be parsed. 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The top-level component. 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws FormatException Thrown if the text could not be parsed as an 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * iCalendar object. 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static Component parseComponent(Component component, String text) 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws FormatException { 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text = normalizeText(text); 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return parseComponentImpl(component, text); 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 662