Skip to content

Commit

Permalink
Added properties and parameters defined in RFC7986
Browse files Browse the repository at this point in the history
  • Loading branch information
benfortuna committed Jan 3, 2019
1 parent 93fb02c commit ec15dda
Show file tree
Hide file tree
Showing 19 changed files with 899 additions and 21 deletions.
5 changes: 3 additions & 2 deletions build.gradle
Expand Up @@ -74,7 +74,8 @@ dependencies {
api "org.slf4j:slf4j-api:$slf4jVersion",
'commons-codec:commons-codec:1.10',
'org.apache.commons:commons-lang3:3.6',
'org.apache.commons:commons-collections4:4.1'
'org.apache.commons:commons-collections4:4.1',
'javax.mail:javax.mail-api:1.5.4'

implementation 'javax.cache:cache-api:1.0.0', optional
implementation "org.codehaus.groovy:groovy-all:$groovyVersion", optional
Expand All @@ -86,7 +87,7 @@ dependencies {
'org.spockframework:spock-core:1.1-groovy-2.4',
'org.ccil.cowan.tagsoup:tagsoup:1.2.1',
"org.slf4j:slf4j-log4j12:$slf4jVersion",
'org.ehcache:ehcache:3.4.0'
'org.ehcache:ehcache:3.4.0', 'com.sun.mail:javax.mail:1.5.4'
}

jacocoTestReport {
Expand Down
13 changes: 13 additions & 0 deletions src/main/groovy/net/fortuna/ical4j/model/ContentBuilder.groovy
Expand Up @@ -128,6 +128,13 @@ class ContentBuilder extends FactoryBuilderSupport {
registerFactory('url', new DefaultPropertyFactory(klass: Url))
registerFactory('version', new VersionFactory())
registerFactory('xproperty', new XPropertyFactory())

// RFC7986
registerFactory('color', new PropertyFactoryWrapper(Color, new Color.Factory()))
registerFactory('conference', new PropertyFactoryWrapper(Conference, new Conference.Factory()))
registerFactory('image', new PropertyFactoryWrapper(Image, new Image.Factory()))
registerFactory('refreshinterval', new PropertyFactoryWrapper(RefreshInterval, new RefreshInterval.Factory()))
registerFactory('source', new PropertyFactoryWrapper(Source, new Source.Factory()))
}

def registerParameters() {
Expand Down Expand Up @@ -155,6 +162,12 @@ class ContentBuilder extends FactoryBuilderSupport {
registerFactory('tzid_', new TzIdFactory())
registerFactory('value', new ValueFactory())
registerFactory('xparameter', new XParameterFactory())

// RFC7986
registerFactory('display', new ParameterFactoryWrapper(Display, new Display.Factory()))
registerFactory('email', new ParameterFactoryWrapper(Email, new Email.Factory()))
registerFactory('feature', new ParameterFactoryWrapper(Feature, new Feature.Factory()))
registerFactory('label', new ParameterFactoryWrapper(Label, new Label.Factory()))
}
}

@@ -0,0 +1,27 @@
package net.fortuna.ical4j.model.parameter

import net.fortuna.ical4j.model.ParameterFactory

class ParameterFactoryWrapper extends AbstractFactory {

Class parameterClass

ParameterFactory factory

ParameterFactoryWrapper(Class paramClass, ParameterFactory factory) {
this.parameterClass = paramClass
this.factory = factory
}

@Override
Object newInstance(FactoryBuilderSupport builder, Object name, Object value, Map attributes) throws InstantiationException, IllegalAccessException {
if (FactoryBuilderSupport.checkValueIsTypeNotString(value, name, parameterClass)) {
return value
}
return factory.createParameter(value)
}

boolean isLeaf() {
return true
}
}
@@ -0,0 +1,41 @@
package net.fortuna.ical4j.model.property

import net.fortuna.ical4j.model.Parameter
import net.fortuna.ical4j.model.ParameterList
import net.fortuna.ical4j.model.PropertyFactory

class PropertyFactoryWrapper extends AbstractFactory {

Class propertyClass

PropertyFactory factory

PropertyFactoryWrapper(Class propClass, PropertyFactory factory) {
this.propertyClass = propClass
this.factory = factory
}

@Override
Object newInstance(FactoryBuilderSupport builder, Object name, Object value, Map attributes) throws InstantiationException, IllegalAccessException {
if (FactoryBuilderSupport.checkValueIsTypeNotString(value, name, propertyClass)) {
return value
}
ParameterList parameters = attributes.remove('parameters')
if (parameters == null) {
parameters = new ParameterList()
}
String propValue = attributes.remove('value')
if (propValue != null) {
return factory.createProperty(parameters, propValue)
}
else {
return factory.createProperty(parameters, value)
}
}

void setChild(FactoryBuilderSupport build, Object parent, Object child) {
if (child instanceof Parameter) {
parent.parameters.add(child)
}
}
}
Expand Up @@ -3,6 +3,7 @@
import net.fortuna.ical4j.model.ParameterFactory;
import net.fortuna.ical4j.model.parameter.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;
Expand All @@ -19,6 +20,12 @@ public List<ParameterFactory> get() {
new SentBy.Factory(), new Type.Factory(), new TzId.Factory(),
new Value.Factory(), new Vvenue.Factory());

List<ParameterFactory> rfc7986 = Arrays.asList(new Display.Factory(), new Email.Factory(), new Feature.Factory(),
new Label.Factory());

List<ParameterFactory> factories = new ArrayList<>(rfc5545);
factories.addAll(rfc7986);

return rfc5545;
}
}
Expand Up @@ -3,6 +3,7 @@
import net.fortuna.ical4j.model.PropertyFactory;
import net.fortuna.ical4j.model.property.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;
Expand All @@ -28,6 +29,11 @@ public List<PropertyFactory> get() {
new TzOffsetTo.Factory(), new TzUrl.Factory(), new Uid.Factory(), new Url.Factory(),
new Version.Factory());

return rfc5545;
List<PropertyFactory> rfc7986 = Arrays.asList(new Color.Factory(), new Conference.Factory(), new Image.Factory(),
new RefreshInterval.Factory(), new Source.Factory());

List<PropertyFactory> factories = new ArrayList<>(rfc5545);
factories.addAll(rfc7986);
return factories;
}
}
96 changes: 96 additions & 0 deletions src/main/java/net/fortuna/ical4j/model/parameter/Display.java
@@ -0,0 +1,96 @@
package net.fortuna.ical4j.model.parameter;

import net.fortuna.ical4j.model.Content;
import net.fortuna.ical4j.model.Parameter;
import net.fortuna.ical4j.model.ParameterFactory;
import org.apache.commons.lang3.StringUtils;

/**
* <pre>
* Parameter Name: DISPLAY
*
* Purpose: To specify different ways in which an image for a calendar
* or component can be displayed.
*
* Format Definition: This property parameter is defined by the
* following notation:
*
* displayparam = "DISPLAY" "=" displayval *("," displayval)
*
* displayval = ("BADGE" / ; image inline with the title of the
* ; event
* "GRAPHIC" / ; a full image replacement for the event
* ; itself
* "FULLSIZE / ; an image that is used to enhance the
* ; event
* "THUMBNAIL / ; a smaller variant of "FULLSIZE" to be
* ; used when space for the image is
* ; constrained
* x-name / ; Experimental type
* iana-token) ; Other IANA registered type
* ;
* ; Default is BADGE
*
* Description: This property parameter MAY be specified on "IMAGE"
* properties. In the absence of this parameter, the value "BADGE"
* MUST be used for the default behavior. The value determines how a
* client ought to present an image supplied in iCalendar data to the
* user.
*
* Values for this parameter are registered with IANA as per
* Section 8.3. New values can be added to this registry following
* the procedure outlined in Section 8.2.1 of [RFC5545].
*
* Servers and clients MUST handle x-name and iana-token values they
* don't recognize by not displaying any image at all.
*
* Example:
*
* IMAGE;VALUE=URI;DISPLAY=BADGE,THUMBNAIL,;FMTTYPE=image/png:http://exa
* mple.com/images/weather-cloudy.png
* </pre>
*/
public class Display extends Parameter {

private static final long serialVersionUID = 1L;

private static final String PARAMETER_NAME = "DISPLAY";

public enum Value {
BADGE, GRAPHIC, FULLSIZE, THUMBNAIL;
}

private final String[] values;

public Display(String value) {
super(PARAMETER_NAME, new Factory());
String[] valueStrings = value.split(",");
for (String valueString : valueStrings) {
try {
Value.valueOf(valueString);
} catch (IllegalArgumentException iae) {
if (!valueString.startsWith(Parameter.EXPERIMENTAL_PREFIX)) {
throw iae;
}
}
}
this.values = valueStrings;
}

@Override
public String getValue() {
return StringUtils.join(values, ",");
}

public static class Factory extends Content.Factory implements ParameterFactory {
private static final long serialVersionUID = 1L;

public Factory() {
super(PARAMETER_NAME);
}

public Parameter createParameter(final String value) {
return new Display(value);
}
}
}
81 changes: 81 additions & 0 deletions src/main/java/net/fortuna/ical4j/model/parameter/Email.java
@@ -0,0 +1,81 @@
package net.fortuna.ical4j.model.parameter;

import net.fortuna.ical4j.model.Content;
import net.fortuna.ical4j.model.Parameter;
import net.fortuna.ical4j.model.ParameterFactory;

import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;

/**
* From specification:
*
* <pre>
* Parameter Name: EMAIL
*
* Purpose: To specify an email address that is used to identify or
* contact an organizer or attendee.
*
* Format Definition: This property parameter is defined by the
* following notation:
*
* emailparam = "EMAIL" "=" param-value
*
* Description: This property parameter MAY be specified on "ORGANIZER"
* or "ATTENDEE" properties. This property can be used in situations
* where the calendar user address value of "ORGANIZER" and
* "ATTENDEE" properties is not likely to be an identifier that
* recipients of scheduling messages could use to match the calendar
* user with, for example, an address book entry. The value of this
* property is an email address that can easily be matched by
* recipients. Recipients can also use this value as an alternative
* means of contacting the calendar user via email. If a recipient's
* calendar user agent allows the recipient to save contact
* information based on the "ORGANIZER" or "ATTENDEE" properties,
* those calendar user agents SHOULD use any "EMAIL" property
* parameter value for the email address of the contact over any
* mailto: calendar user address specified as the value of the
* property. Calendar user agents SHOULD NOT include an "EMAIL"
* property parameter when its value matches the calendar user
* address specified as the value of the property.
*
* Example:
*
* ATTENDEE;CN=Cyrus Daboo;EMAIL=cyrus@example.com:mailto:opaque-toke
* n-1234@example.com
* </pre>
*/
public class Email extends Parameter {

private static final long serialVersionUID = 1L;

private static final String PARAMETER_NAME = "EMAIL";

private final InternetAddress address;

public Email(String address) throws AddressException {
super(PARAMETER_NAME, new Factory());
this.address = InternetAddress.parse(address)[0];
}

@Override
public String getValue() {
return address.getAddress();
}

public static class Factory extends Content.Factory implements ParameterFactory {
private static final long serialVersionUID = 1L;

public Factory() {
super(PARAMETER_NAME);
}

public Parameter createParameter(final String value) {
try {
return new Email(value);
} catch (AddressException e) {
throw new IllegalArgumentException(e);
}
}
}
}

0 comments on commit ec15dda

Please sign in to comment.