src/net/fortuna/ical4j/util/Calendars.java

Tue, 10 Feb 2015 18:12:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 10 Feb 2015 18:12:00 +0100
changeset 0
fb9019fb1bf7
permissions
-rw-r--r--

Import initial revisions of existing project AndroidCaldavSyncAdapater,
forked from upstream repository at 27e8a0f8495c92e0780d450bdf0c7cec77a03a55.

     1 /**
     2  * Copyright (c) 2012, Ben Fortuna
     3  * All rights reserved.
     4  *
     5  * Redistribution and use in source and binary forms, with or without
     6  * modification, are permitted provided that the following conditions
     7  * are met:
     8  *
     9  *  o Redistributions of source code must retain the above copyright
    10  * notice, this list of conditions and the following disclaimer.
    11  *
    12  *  o Redistributions in binary form must reproduce the above copyright
    13  * notice, this list of conditions and the following disclaimer in the
    14  * documentation and/or other materials provided with the distribution.
    15  *
    16  *  o Neither the name of Ben Fortuna nor the names of any other contributors
    17  * may be used to endorse or promote products derived from this software
    18  * without specific prior written permission.
    19  *
    20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31  */
    32 package net.fortuna.ical4j.util;
    34 import java.io.FileInputStream;
    35 import java.io.IOException;
    36 import java.net.URL;
    37 import java.nio.charset.Charset;
    38 import java.util.HashMap;
    39 import java.util.Iterator;
    40 import java.util.Map;
    42 import net.fortuna.ical4j.data.CalendarBuilder;
    43 import net.fortuna.ical4j.data.ParserException;
    44 import net.fortuna.ical4j.model.Calendar;
    45 import net.fortuna.ical4j.model.Component;
    46 import net.fortuna.ical4j.model.ComponentList;
    47 import net.fortuna.ical4j.model.ConstraintViolationException;
    48 import net.fortuna.ical4j.model.IndexedComponentList;
    49 import net.fortuna.ical4j.model.Parameter;
    50 import net.fortuna.ical4j.model.Property;
    51 import net.fortuna.ical4j.model.component.VTimeZone;
    52 import net.fortuna.ical4j.model.parameter.TzId;
    53 import net.fortuna.ical4j.model.property.Method;
    54 import net.fortuna.ical4j.model.property.Uid;
    56 /**
    57  * $Id$
    58  *
    59  * Created on 10/11/2006
    60  *
    61  * Utility method for working with {@link Calendar}s.
    62  * @author Ben Fortuna
    63  */
    64 public final class Calendars {
    66     /**
    67      * Constructor made private to enforce static nature.
    68      */
    69     private Calendars() {
    70     }
    72     /**
    73      * Loads a calendar from the specified file.
    74      * @param filename the name of the file from which to load calendar data
    75      * @return returns a new calendar instance initialised from the specified file
    76      * @throws IOException occurs when there is an error reading the specified file
    77      * @throws ParserException occurs when the data in the specified file is invalid
    78      */
    79     public static Calendar load(final String filename) throws IOException, ParserException {
    80         final FileInputStream fin = new FileInputStream(filename);
    81         final CalendarBuilder builder = new CalendarBuilder();
    82         return builder.build(fin);
    83     }
    85     /**
    86      * Loads a calendar from the specified URL.
    87      * @param url the URL from which to load calendar data
    88      * @return returns a new calendar instance initialised from the specified URL
    89      * @throws IOException occurs when there is an error reading from the specified URL
    90      * @throws ParserException occurs when the data in the specified URL is invalid
    91      */
    92     public static Calendar load(final URL url) throws IOException, ParserException {
    93         final CalendarBuilder builder = new CalendarBuilder();
    94         return builder.build(url.openStream());
    95     }
    97     /**
    98      * Merge all properties and components from two specified calendars into one instance.
    99      * Note that the merge process is not very sophisticated, and may result in invalid calendar
   100      * data (e.g. multiple properties of a type that should only be specified once).
   101      * @param c1 the first calendar to merge
   102      * @param c2 the second calendar to merge
   103      * @return a Calendar instance containing all properties and components from both of the specified calendars
   104      */
   105     public static Calendar merge(final Calendar c1, final Calendar c2) {
   106         final Calendar result = new Calendar();
   107         result.getProperties().addAll(c1.getProperties());
   108         for (final Iterator i = c2.getProperties().iterator(); i.hasNext();) {
   109             final Property p = (Property) i.next();
   110             if (!result.getProperties().contains(p)) {
   111                 result.getProperties().add(p);
   112             }
   113         }
   114         result.getComponents().addAll(c1.getComponents());
   115         for (final Iterator i = c2.getComponents().iterator(); i.hasNext();) {
   116             final Component c = (Component) i.next();
   117             if (!result.getComponents().contains(c)) {
   118                 result.getComponents().add(c);
   119             }
   120         }
   121         return result;
   122     }
   124     /**
   125      * Wraps a component in a calendar.
   126      * @param component the component to wrap with a calendar
   127      * @return a calendar containing the specified component
   128      */
   129     public static Calendar wrap(final Component component) {
   130         final ComponentList components = new ComponentList();
   131         components.add(component);
   132         return new Calendar(components);
   133     }
   135     /**
   136      * Splits a calendar object into distinct calendar objects for unique
   137      * identifers (UID).
   138      * @param calendar a calendar instance
   139      * @return an array of calendar objects
   140      */
   141     public static Calendar[] split(final Calendar calendar) {
   142         // if calendar contains one component or less, or is composed entirely of timezone
   143         // definitions, return the original calendar unmodified..
   144         if (calendar.getComponents().size() <= 1
   145                 || calendar.getComponents(Component.VTIMEZONE).size() == calendar.getComponents().size()) {
   146             return new Calendar[] {calendar};
   147         }
   149         final IndexedComponentList timezones = new IndexedComponentList(calendar.getComponents(Component.VTIMEZONE),
   150                 Property.TZID);
   152         final Map calendars = new HashMap();
   153         for (final Iterator i = calendar.getComponents().iterator(); i.hasNext();) {
   154             final Component c = (Component) i.next();
   155             if (c instanceof VTimeZone) {
   156                 continue;
   157             }
   159             final Uid uid = (Uid) c.getProperty(Property.UID);
   161             Calendar uidCal = (Calendar) calendars.get(uid);
   162             if (uidCal == null) {
   163                 uidCal = new Calendar(calendar.getProperties(), new ComponentList());
   164                 // remove METHOD property for split calendars..
   165                 for (final Iterator mp = uidCal.getProperties(Property.METHOD).iterator(); mp.hasNext();) {
   166                     uidCal.getProperties().remove(mp.next());
   167                 }
   168                 calendars.put(uid, uidCal);
   169             }
   171             for (final Iterator j = c.getProperties().iterator(); j.hasNext();) {
   172                 final Property p = (Property) j.next();
   173                 final TzId tzid = (TzId) p.getParameter(Parameter.TZID);
   174                 if (tzid != null) {
   175                     final VTimeZone timezone = (VTimeZone) timezones.getComponent(tzid.getValue());
   176                     if (!uidCal.getComponents().contains(timezone)) {
   177                         uidCal.getComponents().add(timezone);
   178                     }
   179                 }
   180             }
   181             uidCal.getComponents().add(c);
   182         }
   183         return (Calendar[]) calendars.values().toArray(new Calendar[calendars.values().size()]);
   184     }
   186     /**
   187      * Returns a unique identifier as specified by components in the provided calendar.
   188      * @param calendar a calendar instance
   189      * @return the UID property
   190      * @throws ConstraintViolationException if zero or more than one unique identifer is found in the specified calendar
   191      */
   192     public static Uid getUid(final Calendar calendar) throws ConstraintViolationException {
   193         Uid uid = null;
   194         for (final Iterator i = calendar.getComponents().iterator(); i.hasNext();) {
   195             final Component c = (Component) i.next();
   196             for (final Iterator j = c.getProperties(Property.UID).iterator(); j.hasNext();) {
   197                 final Uid foundUid = (Uid) j.next();
   198                 if (uid != null && !uid.equals(foundUid)) {
   199                     throw new ConstraintViolationException("More than one UID found in calendar");
   200                 }
   201                 uid = foundUid;
   202             }
   203         }
   204         if (uid == null) {
   205             throw new ConstraintViolationException("Calendar must specify a single unique identifier (UID)");
   206         }
   207         return uid;
   208     }
   210     /**
   211      * Returns an appropriate MIME Content-Type for the specified calendar object.
   212      * @param calendar a calendar instance
   213      * @param charset an optional encoding
   214      * @return a content type string
   215      */
   216     public static String getContentType(Calendar calendar, Charset charset) {
   217         final StringBuffer b = new StringBuffer("text/calendar");
   219         final Method method = (Method) calendar.getProperty(Property.METHOD);
   220         if (method != null) {
   221             b.append("; method=");
   222             b.append(method.getValue());
   223         }
   225         if (charset != null) {
   226             b.append("; charset=");
   227             b.append(charset);
   228         }
   229         return b.toString();
   230     }
   231 }

mercurial