-
Notifications
You must be signed in to change notification settings - Fork 44
Nonstandard Components
iCalendar objects can contain non-standard components that are not part of the iCal specification. These are called "experimental" components.
The iCalendar object below contains an example of such a component. It is called "X-PARTY
" (note that the names of experimental components must begin with "X-
").
BEGIN:VCALENDAR
PRODID:-//Company//Application//EN
VERSION:2.0
BEGIN:X-PARTY
DTSTART:20130625T200000Z
DTEND:20130626T020000Z
X-DJ:Jonny D
END:X-PARTY
END:VCALENDAR
To get an experimental component, call the getExperimentalComponent(String)
method. This returns the first component with that name, in the form of a RawComponent
object. Since the DTSTART
and DTEND
properties are standard properties (part of the iCal spec), they can be retrieved by calling the getProperty(Class)
method. The experimental property X-DJ
can be retrieved by calling getExperimentalProperty(String)
.
ICalendar ical = ...
RawComponent party = ical.getExperimentalComponent("X-PARTY");
DateStart start = party.getProperty(DateStart.class);
DateEnd end = party.getProperty(DateEnd.class);
RawProperty dj = party.getExperimentalProperty("X-DJ");
If there is more than one instance of an experimental component, the getExperimentalComponents(String)
method can be called to retrieve all instances:
ICalendar ical = ...
List<RawComponent> parties = ical.getExperimentalComponents("X-PARTY");
To add an experimental component to an iCalendar object, call the addExperimentalComponent(String)
method. This method (1) creates a RawComponent
object, (2) adds it to the iCalendar object, and (3) returns the RawComponent
object. Returning the created object allows you to add properties and other sub-components to it.
ICalendar ical = new ICalendar();
RawComponent party = ical.addExperimentalComponent("X-PARTY");
java.util.Date start = ...
java.util.Date end = ...
party.addProperty(new DateStart(start));
party.addProperty(new DateEnd(end));
party.addExperimentalProperty("X-DJ", "Johnny D");
biweekly supports a plugin system that allows you to marshal and unmarshal experimental components into Java objects. It requires the creation of a component class and a scribe class. This system can also be used to override the scribes of the standard components, if need be.
The example below will create component and scribe classes for our "X-PARTY
" example.
The component class is a POJO that extends ICalComponent
.
public class Party extends ICalComponent {
public DateStart getDateStart() {
return getProperty(DateStart.class);
}
public void setDateStart(DateStart dateStart) {
setProperty(DateStart.class, dateStart);
}
public DateEnd getDateEnd() {
return getProperty(DateEnd.class);
}
public void setDateEnd(DateEnd dateEnd) {
setProperty(DateEnd.class, dateEnd);
}
public String getDj(){
RawProperty prop = getExperimentalProperty("X-DJ");
return (prop == null) ? null : prop.getValue();
}
public void setDj(String dj) {
setExperimentalProperty("X-DJ", dj);
}
@Override
protected void validate(List<ICalComponent> parentComponents, List<String> warnings) {
if (getDateStart() == null){
warnings.add("Start date required.");
}
}
}
The getter/setter methods were added to make it easier to get/set the properties that the component is expected to have (they are not required).
The validate()
method is also optional. It validates the contents of the object when ICalendar.validate()
is called. The first parameter, parentComponents
, contains the hierarchy of components to which the component belongs. For example, if the component is inside of a VEVENT
component, which is inside of an VCALENDAR
component, index 0 of the list would be an ICalendar
object and index 1 of the list would be a VEvent
object (the first element of the list will always be an ICalendar
object). The validation warnings are added to the warnings
list.
The scribe class is responsible for reading/writing the component to/from the actual data stream (such as an ".ics" file). It extends the ICalComponentScribe
class.
public class PartyScribe extends ICalComponentScribe<Party> {
public PartyScribe() {
super(Party.class, "X-PARTY");
}
@Override
public Party newInstance() {
return new Party();
}
}
The name of the component is passed into the parent constructor. The class must have a newInstance()
method, which creates a new instance of the component object.
Before an iCalendar data stream is parsed, the scribe class must be registered with the reader object. Then, once an ICalendar
object has been read, the instances of the component can be retrieved by calling the getComponent(Class)
method.
String icalStr =
"BEGIN:VCALENDAR\r\n" +
"PRODID:example.com\r\n" +
"VERSION:2.0\r\n" +
"BEGIN:X-PARTY\r\n" +
"DTSTART:20130625T200000Z\r\n" +
"DTEND:20130626T020000Z\r\n" +
"X-DJ:Jonny D\r\n" +
"END:X-PARTY\r\n" +
"END:VCALENDAR\r\n";
//using "Biweekly" class
ICalendar ical = Biweekly.parse(icalStr)
.register(new PartyScribe())
.first();
Party party = ical.getComponent(Party.class);
//using "ICalReader" class
ICalReader icalReader = new ICalReader(icalStr);
icalReader.registerScribe(new PartyScribe());
ICalendar ical = icalReader.readNext();
Party party = ical.getComponent(Party.class);
To add instances of the component class to the iCalendar object, call the addComponent()
method on the component that the experimental component belongs to. Then, register the scribe class with the writer object and perform the write operation.
ICalendar ical = new ICalendar();
Party party = new Party();
java.util.Date start = ...
java.util.Date end = ...
party.setDateStart(new DateStart(start));
party.setDateEnd(new DateEnd(end));
party.setDj("Johnny D");
ical.addComponent(party);
//using "Biweekly" class
String icalStr = Biweekly.write(ical)
.register(new PartyScribe())
.go();
//using "ICalWriter" class
StringWriter sw = new StringWriter();
ICalWriter icalWriter = new ICalWriter(sw);
icalWriter.registerScribe(new PartyScribe());
icalWriter.write(ical);
String icalStr = sw.toString();
biweekly is maintained by Michael Angstadt
Table of Contents
Getting started
Examples
FAQ
Javadocs
Downloads
1 An Overview of the iCalendar data format
2 Reading and Writing iCalendar data with biweekly
2.1 Plain-text (traditional)
2.2 XML-encoded (xCal)
2.3 JSON-encoded (jCal)
4 Working with Timezones
4.1 0.4.6 and earlier
4.2 0.5.0 and later
5 Dealing with Non-standard Data
5.1 Non-standard components
5.2 Non-standard properties
5.3 Non-standard parameters
6 Project Information
6.1 Dependencies
6.2 Supported Specifications
6.3 Changelog
7 Reference
7.1 iCalendar Component Reference
7.2 iCalendar Property Reference
7.3 Javadocs