diff -r 000000000000 -r fb9019fb1bf7 src/net/fortuna/ical4j/model/Property.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/net/fortuna/ical4j/model/Property.java Tue Feb 10 18:12:00 2015 +0100 @@ -0,0 +1,537 @@ +/** + * Copyright (c) 2012, Ben Fortuna + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * o Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * o Neither the name of Ben Fortuna nor the names of any other contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.fortuna.ical4j.model; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.text.ParseException; +import net.fortuna.ical4j.model.parameter.Value; +import net.fortuna.ical4j.model.property.XProperty; + +import net.fortuna.ical4j.util.Strings; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +/** + * Defines an iCalendar property. Subclasses of this class provide additional validation and typed values for specific + * iCalendar properties. + * + * Note that subclasses must provide a reference to the factory used to create the + * property to support property cloning (copy). If no factory is specified an + * {@link UnsupportedOperationException} will be thrown by the {@link #copy()} method. + * + * @author Ben Fortuna + * + * $Id$ [Apr 5, 2004] + */ +public abstract class Property extends Content { + + private static final long serialVersionUID = 7048785558435608687L; + + // iCalendar properties.. + + /** + * Product identifier property name. + */ + public static final String PRODID = "PRODID"; + + /** + * iCalendar version property name. + */ + public static final String VERSION = "VERSION"; + + /** + * Calendar scale property name. + */ + public static final String CALSCALE = "CALSCALE"; + + /** + * iTIP method property name. + */ + public static final String METHOD = "METHOD"; + + // Component properties.. + + /** + * Busy type property name. + */ + public static final String BUSYTYPE = "BUSYTYPE"; + + /** + * Classifier property name. + */ + public static final String CLASS = "CLASS"; + + /** + * Creation date property name. + */ + public static final String CREATED = "CREATED"; + + /** + * Description property name. + */ + public static final String DESCRIPTION = "DESCRIPTION"; + + /** + * Start date property name. + */ + public static final String DTSTART = "DTSTART"; + + /** + * Geographic location property name. + */ + public static final String GEO = "GEO"; + + /** + * Last modified date property name. + */ + public static final String LAST_MODIFIED = "LAST-MODIFIED"; + + /** + * Location property name. + */ + public static final String LOCATION = "LOCATION"; + + /** + * Organiser property name. + */ + public static final String ORGANIZER = "ORGANIZER"; + + /** + * Percentage complete property name. + */ + public static final String PERCENT_COMPLETE = "PERCENT-COMPLETE"; + + /** + * Prority property name. + */ + public static final String PRIORITY = "PRIORITY"; + + /** + * Date-stamp property name. + */ + public static final String DTSTAMP = "DTSTAMP"; + + /** + * Sequence property name. + */ + public static final String SEQUENCE = "SEQUENCE"; + + /** + * Status property name. + */ + public static final String STATUS = "STATUS"; + + /** + * Summary property name. + */ + public static final String SUMMARY = "SUMMARY"; + + /** + * Transparency property name. + */ + public static final String TRANSP = "TRANSP"; + + /** + * Unique identifier property name. + */ + public static final String UID = "UID"; + + /** + * Uniform resource locator property name. + */ + public static final String URL = "URL"; + + /** + * Recurrence identifier property name. + */ + public static final String RECURRENCE_ID = "RECURRENCE-ID"; + + /** + * Completed date property name. + */ + public static final String COMPLETED = "COMPLETED"; + + /** + * Due date property name. + */ + public static final String DUE = "DUE"; + + /** + * Free/busy property name. + */ + public static final String FREEBUSY = "FREEBUSY"; + + /** + * Timezone identifier property name. + */ + public static final String TZID = "TZID"; + + /** + * Timezone name property name. + */ + public static final String TZNAME = "TZNAME"; + + /** + * Prior timezone offset property name. + */ + public static final String TZOFFSETFROM = "TZOFFSETFROM"; + + /** + * New timezone offset property name. + */ + public static final String TZOFFSETTO = "TZOFFSETTO"; + + /** + * URL for timezone definition property name. + */ + public static final String TZURL = "TZURL"; + + /** + * Alarm action property name. + */ + public static final String ACTION = "ACTION"; + + /** + * Repeat rule property name. + */ + public static final String REPEAT = "REPEAT"; + + /** + * Alarm trigger property name. + */ + public static final String TRIGGER = "TRIGGER"; + + /** + * Request status property name. + */ + public static final String REQUEST_STATUS = "REQUEST-STATUS"; + + /** + * End date property name. + */ + public static final String DTEND = "DTEND"; + + /** + * Duration property name. + */ + public static final String DURATION = "DURATION"; + + /** + * Attachment property name. + */ + public static final String ATTACH = "ATTACH"; + + /** + * Attendee property name. + */ + public static final String ATTENDEE = "ATTENDEE"; + + /** + * Categories property name. + */ + public static final String CATEGORIES = "CATEGORIES"; + + /** + * Comment property name. + */ + public static final String COMMENT = "COMMENT"; + + /** + * Contact property name. + */ + public static final String CONTACT = "CONTACT"; + + /** + * Exclusion date property name. + */ + public static final String EXDATE = "EXDATE"; + + /** + * Exclusion rule property name. + */ + public static final String EXRULE = "EXRULE"; + + /** + * Relationship property name. + */ + public static final String RELATED_TO = "RELATED-TO"; + + /** + * Resources property name. + */ + public static final String RESOURCES = "RESOURCES"; + + /** + * Recurrence date property name. + */ + public static final String RDATE = "RDATE"; + + /** + * Recurrence rule property name. + */ + public static final String RRULE = "RRULE"; + + /** + * Prefix for non-standard properties. + */ + public static final String EXPERIMENTAL_PREFIX = "X-"; + + /** + * VVENUE country property name. + */ + public static final String COUNTRY = "COUNTRY"; + + /** + * VVENUE extended address property name. + */ + public static final String EXTENDED_ADDRESS = "EXTENDED-ADDRESS"; + + /** + * VVENUE locality property name. + */ + public static final String LOCALITY = "LOCALITY"; + + /** + * VVENUE location type property name. + */ + public static final String LOCATION_TYPE = "LOCATION-TYPE"; + + /** + * VVENUE name property name. + */ + public static final String NAME = "NAME"; + + /** + * VVENUE postal code property name. + */ + public static final String POSTALCODE = "POSTAL-CODE"; + + /** + * VVENUE region property name. + */ + public static final String REGION = "REGION"; + + /** + * VVENUE street address property name. + */ + public static final String STREET_ADDRESS = "STREET-ADDRESS"; + + /** + * VVENUE telephone property name. + */ + public static final String TEL = "TEL"; + + private String name; + + private ParameterList parameters; + + private final PropertyFactory factory; + + /** + * Constructor. + * @param aName property name + * @param factory the factory used to create the property instance + */ + protected Property(final String aName, PropertyFactory factory) { + this(aName, new ParameterList(), factory); + } + + /** + * Constructor made protected to enforce the use of PropertyFactory for property instantiation. + * @param aName property name + * @param aList a list of parameters + */ +// protected Property(final String aName, final ParameterList aList) { +// this(aName, aList, PropertyFactoryImpl.getInstance()); +// } + + /** + * @param aName a property identifier + * @param aList a list of initial parameters + * @param factory the factory used to create the property instance + */ + protected Property(final String aName, final ParameterList aList, PropertyFactory factory) { + this.name = aName; + this.parameters = aList; + this.factory = factory; + } + + /** + * Creates a deep copy of the specified property. That is, the name, parameter list, and value are duplicated from + * the specified property. This constructor should only be called from sub-classes to ensure type integrity is + * maintained. + * @param property a property to copy + * @throws URISyntaxException where the specified property contains an invalid URI value + * @throws ParseException where the specified property has invalid data + * @throws IOException where an error occurs reading data from the specified property + * @deprecated Use {@link #copy()} instead + */ + protected Property(final Property property) throws IOException, + URISyntaxException, ParseException { + this(property.getName(), new ParameterList(property.getParameters(), false), + property.factory); + setValue(property.getValue()); + } + + /** + * {@inheritDoc} + */ + public final String toString() { + final StringBuffer buffer = new StringBuffer(); + buffer.append(getName()); + if (getParameters() != null) { + buffer.append(getParameters()); + } + buffer.append(':'); + boolean needsEscape = false; + if (this instanceof XProperty) { + Value valParam = (Value)getParameter(Parameter.VALUE); + if (valParam == null || valParam.equals(Value.TEXT)) { + needsEscape = true; + } + } else if (this instanceof Escapable) { + needsEscape = true; + } + if (needsEscape) { + buffer.append(Strings.escape(Strings.valueOf(getValue()))); + } + else { + buffer.append(Strings.valueOf(getValue())); + } + buffer.append(Strings.LINE_SEPARATOR); + + return buffer.toString(); + } + + /** + * Indicates whether this property is a calendar property. + * @return boolean + */ + public boolean isCalendarProperty() { + + return PRODID.equalsIgnoreCase(getName()) + || VERSION.equalsIgnoreCase(getName()) + || CALSCALE.equalsIgnoreCase(getName()) + || METHOD.equalsIgnoreCase(getName()); + } + + /** + * @return Returns the name. + */ + public final String getName() { + return name; + } + + /** + * @return Returns the parameters. + */ + public final ParameterList getParameters() { + return parameters; + } + + /** + * Convenience method for retrieving a list of named parameters. + * @param name name of parameters to retrieve + * @return a parameter list containing only parameters with the specified name + */ + public final ParameterList getParameters(final String name) { + return getParameters().getParameters(name); + } + + /** + * Convenience method for retrieving a single parameter. + * @param name name of the parameter to retrieve + * @return the first parameter from the parameter list with the specified name + */ + public final Parameter getParameter(final String name) { + return getParameters().getParameter(name); + } + + /** + * Sets the current value of the property. + * @param aValue a string representation of the property value + * @throws IOException possibly thrown by setting the value of certain properties + * @throws URISyntaxException possibly thrown by setting the value of certain properties + * @throws ParseException possibly thrown by setting the value of certain properties + */ + public abstract void setValue(String aValue) throws IOException, + URISyntaxException, ParseException; + + /** + * Perform validation on a property. + * @throws ValidationException where the property is not in a valid state + */ + public abstract void validate() throws ValidationException; + + /** + * {@inheritDoc} + */ + public final boolean equals(final Object arg0) { + if (arg0 instanceof Property) { + final Property p = (Property) arg0; + if (getName().equals(p.getName())) { + return new EqualsBuilder().append(getValue(), p.getValue()) + .append(getParameters(), p.getParameters()).isEquals(); + } else { + return false; + } + } + return super.equals(arg0); + } + + /** + * {@inheritDoc} + */ + public int hashCode() { + // as property name is case-insensitive generate hash for uppercase.. + return new HashCodeBuilder().append(getName().toUpperCase()).append( + getValue()).append(getParameters()).toHashCode(); + } + + /** + * Create a (deep) copy of this property. + * @return the copy of the property + * @throws IOException where an error occurs reading property data + * @throws URISyntaxException where the property contains an invalid URI value + * @throws ParseException where the property contains an invalid date value + */ + public Property copy() throws IOException, URISyntaxException, ParseException { + if (factory == null) { + throw new UnsupportedOperationException("No factory specified"); + } + // Deep copy parameter list.. + final ParameterList params = new ParameterList(getParameters(), false); + return factory.createProperty(getName(), params, getValue()); + } +}