[Bedework-commit] calendarapi r1387 -
releases/bedework-3.6/icalendar/src/org/bedework/icalendar
svnadmin at bedework.org
svnadmin at bedework.org
Thu Sep 9 10:12:12 EDT 2010
Author: douglm
Date: 2010-09-09 10:12:11 -0400 (Thu, 09 Sep 2010)
New Revision: 1387
Added:
releases/bedework-3.6/icalendar/src/org/bedework/icalendar/XmlCalendarBuilder.java
Modified:
releases/bedework-3.6/icalendar/src/org/bedework/icalendar/IcalTranslator.java
Log:
Implement parsing of xml icalendar objects
Modified: releases/bedework-3.6/icalendar/src/org/bedework/icalendar/IcalTranslator.java
===================================================================
--- releases/bedework-3.6/icalendar/src/org/bedework/icalendar/IcalTranslator.java 2010-09-09 14:12:10 UTC (rev 1386)
+++ releases/bedework-3.6/icalendar/src/org/bedework/icalendar/IcalTranslator.java 2010-09-09 14:12:11 UTC (rev 1387)
@@ -318,17 +318,42 @@
* @return Icalendar
* @throws CalFacadeException
*/
- public Icalendar fromIcal(final BwCalendar col, final Reader rdr) throws CalFacadeException {
+ public Icalendar fromIcal(final BwCalendar col,
+ final Reader rdr) throws CalFacadeException {
+ return fromIcal(col, rdr, null);
+ }
+
+ /** Convert the Icalendar reader to a Collection of Calendar objects
+ *
+ * @param col collection the entities will live in - possibly null
+ * @param rdr
+ * @param contentType
+ * @return Icalendar
+ * @throws CalFacadeException
+ */
+ public Icalendar fromIcal(final BwCalendar col,
+ final Reader rdr,
+ final String contentType) throws CalFacadeException {
try {
Icalendar ic = new Icalendar();
setSystemProperties();
- CalendarBuilder bldr = new CalendarBuilder(new CalendarParserImpl(), ic);
- UnfoldingReader ufrdr = new UnfoldingReader(rdr, true);
+ Calendar cal;
- Calendar cal = bldr.build(ufrdr);
+ if ((contentType != null) &&
+ contentType.equals("application/calendar+xml")) {
+ XmlCalendarBuilder bldr = new XmlCalendarBuilder(ic);
+ cal = bldr.build(rdr);
+ } else {
+ CalendarBuilder bldr = new CalendarBuilder(new CalendarParserImpl(), ic);
+
+ UnfoldingReader ufrdr = new UnfoldingReader(rdr, true);
+
+ cal = bldr.build(ufrdr);
+ }
+
ic.setComponents(new ArrayList<Object>());
if (cal == null) {
Added: releases/bedework-3.6/icalendar/src/org/bedework/icalendar/XmlCalendarBuilder.java
===================================================================
--- releases/bedework-3.6/icalendar/src/org/bedework/icalendar/XmlCalendarBuilder.java (rev 0)
+++ releases/bedework-3.6/icalendar/src/org/bedework/icalendar/XmlCalendarBuilder.java 2010-09-09 14:12:11 UTC (rev 1387)
@@ -0,0 +1,723 @@
+/**
+ * Copyright (c) 2010, 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 org.bedework.icalendar;
+
+import edu.rpi.sss.util.xml.XmlUtil;
+import edu.rpi.sss.util.xml.tagdefs.XcalTags;
+
+import net.fortuna.ical4j.data.ContentHandler;
+import net.fortuna.ical4j.data.ParserException;
+import net.fortuna.ical4j.model.Calendar;
+import net.fortuna.ical4j.model.CalendarException;
+import net.fortuna.ical4j.model.Component;
+import net.fortuna.ical4j.model.ComponentFactory;
+import net.fortuna.ical4j.model.Escapable;
+import net.fortuna.ical4j.model.Parameter;
+import net.fortuna.ical4j.model.ParameterFactory;
+import net.fortuna.ical4j.model.ParameterFactoryImpl;
+import net.fortuna.ical4j.model.ParameterFactoryRegistry;
+import net.fortuna.ical4j.model.ParameterList;
+import net.fortuna.ical4j.model.Property;
+import net.fortuna.ical4j.model.PropertyFactory;
+import net.fortuna.ical4j.model.PropertyFactoryRegistry;
+import net.fortuna.ical4j.model.TimeZone;
+import net.fortuna.ical4j.model.TimeZoneRegistry;
+import net.fortuna.ical4j.model.component.VAvailability;
+import net.fortuna.ical4j.model.component.VEvent;
+import net.fortuna.ical4j.model.component.VTimeZone;
+import net.fortuna.ical4j.model.component.VToDo;
+import net.fortuna.ical4j.model.parameter.TzId;
+import net.fortuna.ical4j.model.property.DateListProperty;
+import net.fortuna.ical4j.model.property.DateProperty;
+import net.fortuna.ical4j.util.CompatibilityHints;
+import net.fortuna.ical4j.util.Constants;
+import net.fortuna.ical4j.util.Strings;
+
+import org.apache.log4j.Logger;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URISyntaxException;
+import java.nio.charset.Charset;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+/**
+ * Parses and builds an iCalendar model from an xml input stream.
+ * Note that this class is not thread-safe.
+ *
+ * @version 1.0
+ * @author Mike Douglass
+ *
+ * Created: Sept 8, 2010
+ *
+ */
+public class XmlCalendarBuilder {
+ private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
+
+ private Logger log = Logger.getLogger(XmlCalendarBuilder.class);
+
+ private final TimeZoneRegistry tzRegistry;
+
+ private static class BuildState {
+ ContentHandler handler;
+
+ /**
+ * The calendar instance(s) created by the builder.
+ */
+ List<Calendar> calendars = new ArrayList<Calendar>();
+
+ /**
+ * The current calendar instance being created by the builder.
+ */
+ Calendar calendar;
+
+ /**
+ * The current component instance created by the builder.
+ */
+ Component component;
+
+ /**
+ * The current sub-component instance created by the builder.
+ */
+ Component subComponent;
+
+ /**
+ * The current property instance created by the builder.
+ */
+ Property property;
+
+ List<Property> datesMissingTimezones = new ArrayList<Property>();
+
+ }
+
+ /**
+ * @param tzRegistry a custom timezone registry
+ */
+ public XmlCalendarBuilder(final TimeZoneRegistry tzRegistry) {
+ this.tzRegistry = tzRegistry;
+ }
+
+ /**
+ * Builds an iCalendar model from the specified input stream.
+ * @param in an input stream to read calendar data from
+ * @return a calendar parsed from the specified input stream
+ * @throws IOException where an error occurs reading data from the specified stream
+ * @throws ParserException where an error occurs parsing data from the stream
+ */
+ public Calendar build(final InputStream in) throws IOException,
+ ParserException {
+ return build(new InputStreamReader(in, DEFAULT_CHARSET));
+ }
+
+ /**
+ * Build an iCalendar model by parsing data from the specified reader.
+ *
+ * @param in an unfolding reader to read data from
+ * @return a calendar parsed from the specified reader
+ * @throws IOException where an error occurs reading data from the specified reader
+ * @throws ParserException where an error occurs parsing data from the reader
+ */
+ public Calendar build(final Reader in) throws IOException,
+ ParserException {
+ BuildState bs = new BuildState();
+
+ bs.handler = new ContentHandlerImpl(bs);
+
+ try {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+
+ DocumentBuilder builder = factory.newDocumentBuilder();
+
+ Document doc = builder.parse(new InputSource(in));
+
+ process(doc, bs);
+ } catch (SAXException e) {
+ throw new ParserException(e.getMessage(), 0, e);
+ } catch (Throwable t) {
+ throw new ParserException(t.getMessage(), 0, t);
+ }
+
+ if ((bs.datesMissingTimezones.size() > 0) && (tzRegistry != null)) {
+ resolveTimezones(bs);
+ }
+
+ return bs.calendars.iterator().next();
+ }
+
+ private void process(final Document doc,
+ final BuildState bs) throws ParserException {
+ // start = element icalendar { vcalendar+ }
+
+ Element root = doc.getDocumentElement();
+
+ if (!XmlUtil.nodeMatches(root, XcalTags.icalendar)) {
+ // error
+ throw new ParserException("Expected " + XcalTags.icalendar +
+ " found " + root, 0);
+ }
+
+ for (Element el: getChildren(root)) {
+ // Expect vcalendar
+
+ if (!XmlUtil.nodeMatches(el, XcalTags.vcalendar)) {
+ // error
+ throw new ParserException("Expected " + XcalTags.vcalendar +
+ " found " + el, 0);
+ }
+
+ bs.calendar = null;
+ processVcalendar(el, bs);
+
+ if (bs.calendar != null) {
+ bs.calendars.add(bs.calendar);
+ }
+ }
+ }
+
+ private void processVcalendar(final Element el,
+ final BuildState bs) throws ParserException {
+ bs.handler.startCalendar();
+
+ try {
+ Collection<Element> els = XmlUtil.getElements(el);
+ /*
+ vcalendar = element vcalendar {
+ type-calprops,
+ type-component
+ }
+ */
+ Iterator<Element> elit = els.iterator();
+
+ Element vcel = null;
+
+ if (elit.hasNext()) {
+ vcel = elit.next();
+ }
+
+ /*
+ type-calprops = element properties {
+ property-prodid &
+ property-version &
+ property-calscale? &
+ property-method?
+ }
+ */
+ if (XmlUtil.nodeMatches(vcel, XcalTags.properties)) {
+ processProperties(vcel, bs);
+
+ if (elit.hasNext()) {
+ vcel = elit.next();
+ } else {
+ vcel = null;
+ }
+ }
+
+ if (XmlUtil.nodeMatches(vcel, XcalTags.components)) {
+ processCalcomps(vcel, bs);
+
+ if (elit.hasNext()) {
+ vcel = elit.next();
+ } else {
+ vcel = null;
+ }
+ }
+
+ if (vcel != null) {
+ throw new ParserException("Unexpected element: found " + vcel, 0);
+ }
+ } catch (SAXException e) {
+ throw new ParserException(e.getMessage(), 0, e);
+ }
+ }
+
+ private void processProperties(final Element el,
+ final BuildState bs) throws ParserException {
+ try {
+ for (Element e: XmlUtil.getElements(el)) {
+ processProperty(e, bs);
+ }
+ } catch (SAXException e) {
+ throw new ParserException(e.getMessage(), 0, e);
+ }
+ }
+
+ private void processCalcomps(final Element el,
+ final BuildState bs) throws ParserException {
+ /*
+ type-component = element components {
+ (
+ component-vevent |
+ component-vtodo |
+ component-vjournal |
+ component-vfreebusy |
+ component-vtimezone
+ )*
+ }
+ */
+ try {
+ for (Element e: XmlUtil.getElements(el)) {
+ processComponent(e, bs);
+ }
+ } catch (SAXException e) {
+ throw new ParserException(e.getMessage(), 0, e);
+ }
+ }
+
+ private void processComponent(final Element el,
+ final BuildState bs) throws ParserException {
+ try {
+ bs.handler.startComponent(el.getLocalName().toUpperCase());
+
+ for (Element e: XmlUtil.getElements(el)) {
+ if (XmlUtil.nodeMatches(e, XcalTags.properties)) {
+ processProperties(e, bs);
+ } else if (XmlUtil.nodeMatches(e, XcalTags.components)) {
+ for (Element ce: XmlUtil.getElements(e)) {
+ processComponent(ce, bs);
+ }
+ } else {
+ throw new ParserException("Unexpected element: found " + e, 0);
+ }
+ }
+
+ bs.handler.endComponent(el.getLocalName().toUpperCase());
+ } catch (SAXException e) {
+ throw new ParserException(e.getMessage(), 0, e);
+ }
+ }
+
+ private void processProperty(final Element el,
+ final BuildState bs) throws ParserException {
+ try {
+ bs.handler.startProperty(el.getLocalName());
+
+ for (Element e: XmlUtil.getElements(el)) {
+ if (XmlUtil.nodeMatches(e, XcalTags.parameters)) {
+ for (Element par: XmlUtil.getElements(e)) {
+ bs.handler.parameter(par.getLocalName(),
+ XmlUtil.getElementContent(par));
+ }
+ }
+
+ if (!processValue(e, bs)) {
+ throw new ParserException("Bad property " + el, 0);
+ }
+ }
+
+ bs.handler.endProperty(el.getLocalName());
+ } catch (SAXException e) {
+ throw new ParserException(e.getMessage(), 0, e);
+ } catch (URISyntaxException e) {
+ throw new ParserException(e.getMessage(), 0, e);
+ }
+ }
+
+ private boolean processValue(final Element el,
+ final BuildState bs) throws ParserException {
+ try {
+ if (XmlUtil.nodeMatches(el, XcalTags.recur)) {
+ /*
+ value-recur = element recur {
+ type-freq,
+ (type-until | type-count)?,
+ element interval { text }?,
+ element bysecond { text }*,
+ element byminute { text }*,
+ element byhour { text }*,
+ type-byday*,
+ type-bymonthday*,
+ type-byyearday*,
+ type-byweekno*,
+ element bymonth { text }*,
+ type-bysetpos*,
+ element wkst { type-weekday }?
+ }
+
+ */
+ StringBuilder sb = new StringBuilder();
+
+ String delim = "";
+
+ for (Element re: XmlUtil.getElements(el)) {
+ sb.append(delim);
+ delim = ";";
+ sb.append(re.getLocalName().toUpperCase());
+ sb.append("=");
+ sb.append(XmlUtil.getElementContent(re));
+ }
+
+ bs.handler.propertyValue(sb.toString());
+
+ return true;
+ }
+
+ if (XmlUtil.nodeMatches(el, XcalTags.binary) ||
+ XmlUtil.nodeMatches(el, XcalTags._boolean) ||
+ XmlUtil.nodeMatches(el, XcalTags.calAddress) ||
+ XmlUtil.nodeMatches(el, XcalTags.date) ||
+ XmlUtil.nodeMatches(el, XcalTags.dateTime) ||
+ XmlUtil.nodeMatches(el, XcalTags.duration) ||
+ XmlUtil.nodeMatches(el, XcalTags._float) ||
+ XmlUtil.nodeMatches(el, XcalTags.integer) ||
+ XmlUtil.nodeMatches(el, XcalTags.period) ||
+ XmlUtil.nodeMatches(el, XcalTags.text) ||
+ XmlUtil.nodeMatches(el, XcalTags.time) ||
+ XmlUtil.nodeMatches(el, XcalTags.uri) ||
+ XmlUtil.nodeMatches(el, XcalTags.utcOffset)) {
+ bs.handler.propertyValue(XmlUtil.getElementContent(el));
+ return true;
+ }
+
+ return false;
+ } catch (SAXException e) {
+ throw new ParserException(e.getMessage(), 0, e);
+ } catch (URISyntaxException e) {
+ throw new ParserException(e.getMessage(), 0, e);
+ } catch (ParseException e) {
+ throw new ParserException(e.getMessage(), 0, e);
+ } catch (IOException e) {
+ throw new ParserException(e.getMessage(), 0, e);
+ }
+ }
+
+ private class ContentHandlerImpl implements ContentHandler {
+ private BuildState bs;
+
+ private final ComponentFactory componentFactory;
+
+ private final PropertyFactory propertyFactory;
+
+ private final ParameterFactory parameterFactory;
+
+ public ContentHandlerImpl(final BuildState bs) {
+ this.bs = bs;
+ componentFactory = ComponentFactory.getInstance();
+ propertyFactory = new PropertyFactoryRegistry();
+ parameterFactory = new ParameterFactoryRegistry();
+ }
+
+ public void endCalendar() {
+ // do nothing..
+ }
+
+ public void endComponent(final String name) {
+ assertComponent(bs.component);
+
+ if (bs.subComponent != null) {
+ if (bs.component instanceof VTimeZone) {
+ ((VTimeZone) bs.component).getObservances().add(bs.subComponent);
+ }
+ else if (bs.component instanceof VEvent) {
+ ((VEvent) bs.component).getAlarms().add(bs.subComponent);
+ }
+ else if (bs.component instanceof VToDo) {
+ ((VToDo) bs.component).getAlarms().add(bs.subComponent);
+ }
+ else if (bs.component instanceof VAvailability) {
+ ((VAvailability) bs.component).getAvailable().add(bs.subComponent);
+ }
+ bs.subComponent = null;
+ }
+ else {
+ bs.calendar.getComponents().add(bs.component);
+ if ((bs.component instanceof VTimeZone) && (tzRegistry != null)) {
+ // register the timezone for use with iCalendar objects..
+ tzRegistry.register(new TimeZone((VTimeZone) bs.component));
+ }
+ bs.component = null;
+ }
+ }
+
+ public void endProperty(final String name) {
+ assertProperty(bs.property);
+
+ // replace with a constant instance if applicable..
+ bs.property = Constants.forProperty(bs.property);
+ if (bs.component != null) {
+ if (bs.subComponent != null) {
+ bs.subComponent.getProperties().add(bs.property);
+ }
+ else {
+ bs.component.getProperties().add(bs.property);
+ }
+ }
+ else if (bs.calendar != null) {
+ bs.calendar.getProperties().add(bs.property);
+ }
+
+ bs.property = null;
+ }
+
+ public void parameter(final String name, final String value) throws URISyntaxException {
+ assertProperty(bs.property);
+
+ // parameter names are case-insensitive, but convert to upper case to simplify further processing
+ final Parameter param = parameterFactory.createParameter(name.toUpperCase(), value);
+ bs.property.getParameters().add(param);
+ if ((param instanceof TzId) && (tzRegistry != null)) {
+ final TimeZone timezone = tzRegistry.getTimeZone(param.getValue());
+ if (timezone != null) {
+ updateTimeZone(bs.property, timezone);
+
+ /* Bedework - for the moment switch ids if they differ */
+
+ if (!timezone.getID().equals(param.getValue())) {
+ /* Fetched timezone has a different id */
+
+ ParameterList pl = bs.property.getParameters();
+
+ pl.replace(ParameterFactoryImpl.getInstance().
+ createParameter(Parameter.TZID, timezone.getID()));
+ }
+ } else {
+ // VTIMEZONE may be defined later, so so keep
+ // track of dates until all components have been
+ // parsed, and then try again later
+ bs.datesMissingTimezones.add(bs.property);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void propertyValue(final String value) throws URISyntaxException,
+ ParseException, IOException {
+
+ assertProperty(bs.property);
+
+ if (bs.property instanceof Escapable) {
+ bs.property.setValue(Strings.unescape(value));
+ }
+ else {
+ bs.property.setValue(value);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void startCalendar() {
+ bs.calendar = new Calendar();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void startComponent(final String name) {
+ if (bs.component != null) {
+ bs.subComponent = componentFactory.createComponent(name);
+ }
+ else {
+ bs.component = componentFactory.createComponent(name);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void startProperty(final String name) {
+ // property names are case-insensitive, but convert to upper case to simplify further processing
+ bs.property = propertyFactory.createProperty(name.toUpperCase());
+ }
+ }
+
+ private void assertComponent(final Component component) {
+ if (component == null) {
+ throw new CalendarException("Expected component not initialised");
+ }
+ }
+
+ private void assertProperty(final Property property) {
+ if (property == null) {
+ throw new CalendarException("Expected property not initialised");
+ }
+ }
+
+ /**
+ * Returns the timezone registry used in the construction of calendars.
+ * @return a timezone registry
+ */
+ public final TimeZoneRegistry getRegistry() {
+ return tzRegistry;
+ }
+
+ private void updateTimeZone(final Property property, final TimeZone timezone) {
+ try {
+ ((DateProperty) property).setTimeZone(timezone);
+ }
+ catch (ClassCastException e) {
+ try {
+ ((DateListProperty) property).setTimeZone(timezone);
+ }
+ catch (ClassCastException e2) {
+ if (CompatibilityHints.isHintEnabled(CompatibilityHints.KEY_RELAXED_PARSING)) {
+ log.warn("Error setting timezone [" + timezone.getID()
+ + "] on property [" + property.getName()
+ + "]", e);
+ }
+ else {
+ throw e2;
+ }
+ }
+ }
+ }
+
+ private void resolveTimezones(final BuildState bs) throws IOException {
+
+ // Go through each property and try to resolve the TZID.
+ for (final Property property: bs.datesMissingTimezones) {
+ final Parameter tzParam = property.getParameter(Parameter.TZID);
+
+ // tzParam might be null:
+ if (tzParam == null) {
+ continue;
+ }
+
+ //lookup timezone
+ final TimeZone timezone = tzRegistry.getTimeZone(tzParam.getValue());
+
+ // If timezone found, then update date property
+ if (timezone != null) {
+ // Get the String representation of date(s) as
+ // we will need this after changing the timezone
+ final String strDate = property.getValue();
+
+ // Change the timezone
+ if(property instanceof DateProperty) {
+ ((DateProperty) property).setTimeZone(timezone);
+ }
+ else if(property instanceof DateListProperty) {
+ ((DateListProperty) property).setTimeZone(timezone);
+ }
+
+ // Reset value
+ try {
+ property.setValue(strDate);
+ } catch (ParseException e) {
+ // shouldn't happen as its already been parsed
+ throw new CalendarException(e);
+ } catch (URISyntaxException e) {
+ // shouldn't happen as its already been parsed
+ throw new CalendarException(e);
+ }
+ }
+ }
+ }
+
+ /* ====================================================================
+ * XmlUtil wrappers
+ * ==================================================================== */
+
+ boolean icalElement(final Element el) {
+ if (el == null) {
+ return false;
+ }
+
+ String ns = el.getNamespaceURI();
+
+ if ((ns == null) || !ns.equals(XcalTags.namespace)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ boolean icalElement(final Element el, final String name) {
+ if (!icalElement(el)) {
+ return false;
+ }
+
+ String ln = el.getLocalName();
+
+ if (ln == null) {
+ return false;
+ }
+
+ return ln.equals(name);
+ }
+
+ protected Collection<Element> getChildren(final Node nd) throws ParserException {
+ try {
+ return XmlUtil.getElements(nd);
+ } catch (Throwable t) {
+ throw new ParserException(t.getMessage(), 0);
+ }
+ }
+
+ protected Element[] getChildrenArray(final Node nd) throws ParserException {
+ try {
+ return XmlUtil.getElementsArray(nd);
+ } catch (Throwable t) {
+ throw new ParserException(t.getMessage(), 0);
+ }
+ }
+
+ protected Element getOnlyChild(final Node nd) throws ParserException {
+ try {
+ return XmlUtil.getOnlyElement(nd);
+ } catch (Throwable t) {
+ throw new ParserException(t.getMessage(), 0);
+ }
+ }
+
+ protected String getElementContent(final Element el) throws ParserException {
+ try {
+ return XmlUtil.getElementContent(el);
+ } catch (Throwable t) {
+ throw new ParserException(t.getMessage(), 0);
+ }
+ }
+
+ protected boolean isEmpty(final Element el) throws ParserException {
+ try {
+ return XmlUtil.isEmpty(el);
+ } catch (Throwable t) {
+ throw new ParserException(t.getMessage(), 0);
+ }
+ }
+}
More information about the Bedework-commit
mailing list