Java tutorial
/** * Copyright 2011 Caleb Richardson * * 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.outerspacecat.icalendar; import java.io.IOException; import java.io.Serializable; import java.util.ArrayDeque; import java.util.Deque; import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.ThreadSafe; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableMultimap; /** * A representation of an iCalendar object defined by <a * href="http://tools.ietf.org/html/rfc5545">RFC 5545</a>. This class does not * enforce the amount of times a property or component is required or allowed to * appear. * * @author Caleb Richardson */ @Immutable @ThreadSafe public final class VCalendar implements Serializable { private final static long serialVersionUID = 1L; private final ImmutableMultimap<String, Property> properties; private final ImmutableMultimap<String, Component> components; /** * Creates a new calendar. * * @param properties the calendar properties. Must be non {@code null}, all * elements must be non {@code null}, may be empty. * @param components the calendar components. Must be non {@code null}, all * elements must be non {@code null}, may be empty. */ public VCalendar(final Iterable<Property> properties, final Iterable<Component> components) { Preconditions.checkNotNull(properties, "properties required"); Preconditions.checkNotNull(components, "components required"); ImmutableMultimap.Builder<String, Property> propBuilder = new ImmutableMultimap.Builder<String, Property>(); for (Property prop : properties) { Preconditions.checkNotNull(prop, "properties must each be non null"); propBuilder.put(prop.getName().getName(), prop); } this.properties = propBuilder.build(); ImmutableMultimap.Builder<String, Component> compBuilder = new ImmutableMultimap.Builder<String, Component>(); for (Component comp : components) { Preconditions.checkNotNull(comp, "components must each be non null"); compBuilder.put(comp.getName(), comp); } this.components = compBuilder.build(); } /** * Returns the properties of this calendar. * * @return the properties of this calendar. Never {@code null}, contains zero * or more entries. */ public ImmutableMultimap<String, Property> getProperties() { return properties; } /** * Returns the components of this calendar. * * @return the components of this calendar. Never {@code null}, contains zero * or more entries. */ public ImmutableMultimap<String, Component> getComponents() { return components; } /** * Returns a single {@link Property} with the specified name, or {@code null} * if no such property exists. This method provides an easy way to ignore * extra properties. Which property is returned is non-deterministic, however * the same property will be returned each time this method is called. * * @param name the name of the property to retrieve. Must be non {@code null}. * @return a single {@link Property} with the specified name, or {@code null} * if no such property exists. */ public Property getFirstProperty(final String name) { Preconditions.checkNotNull(name, "name required"); ImmutableCollection<Property> props = getProperties().get(name.toUpperCase()); return props.isEmpty() ? null : props.iterator().next(); } /** * Returns a single {@link Property} with the specified name, or throws a * {@link CalendarParseException} if a property with the specified name does * not occur exactly once. * * @param name the name of the property to retrieve. Must be non {@code null}. * @return a single {@link Property} with the specified name. Never * {@code null}. * @throws CalendarParseException if a property with the specified name does * not occur exactly once. */ public Property getSingleProperty(final String name) throws CalendarParseException { Preconditions.checkNotNull(name, "name required"); ImmutableCollection<Property> props = getProperties().get(name.toUpperCase()); if (props.isEmpty()) throw new CalendarParseException("no properties for name: " + name); if (props.size() > 1) throw new CalendarParseException("more than one property for name: " + name); return props.iterator().next(); } /** * Converts this object to iCalendar and writes it to {@code sink}. * * @param sink the character sink to write the generated iCalendar to. Must be * non {@code null}. * @throws IOException if an error occurs while writing to {@code sink} */ public void toICalendar(final Appendable sink) throws IOException { Preconditions.checkNotNull(sink, "sink required"); sink.append("BEGIN:VCALENDAR\r\n"); for (Property p : getProperties().values()) sink.append(p.toICalendar()).append("\r\n"); for (Component c : getComponents().values()) c.toICalendar(sink); sink.append("END:VCALENDAR\r\n"); } /** * A builder for creating instances of {@link VCalendar}. */ final static class Builder { private final Deque<Property> properties = new ArrayDeque<Property>(); private final Deque<Component> components = new ArrayDeque<Component>(); /** * Adds a property to the calendar. * * @param prop the property to add. Must be non {@code null}. * @return this builder. Never {@code null}. */ public Builder addProperty(final Property prop) { Preconditions.checkNotNull(prop, "prop required"); properties.add(prop); return this; } /** * Adds a component to the calendar. * * @param comp the component to add. Must be non {@code null}. * @return this builder. Never {@code null}. */ public Builder addComponent(final Component comp) { Preconditions.checkNotNull(comp, "comp required"); components.add(comp); return this; } /** * Builds the calendar. * * @return a new calendar. Never {@code null}. */ public VCalendar build() { return new VCalendar(properties, components); } } }