org.obm.sync.calendar.CalendarItemsParser.java Source code

Java tutorial

Introduction

Here is the source code for org.obm.sync.calendar.CalendarItemsParser.java

Source

/* ***** BEGIN LICENSE BLOCK *****
 * 
 * Copyright (C) 2011-2014  Linagora
 *
 * This program is free software: you can redistribute it and/or 
 * modify it under the terms of the GNU Affero General Public License as 
 * published by the Free Software Foundation, either version 3 of the 
 * License, or (at your option) any later version, provided you comply 
 * with the Additional Terms applicable for OBM connector by Linagora 
 * pursuant to Section 7 of the GNU Affero General Public License, 
 * subsections (b), (c), and (e), pursuant to which you must notably (i) retain 
 * the Message sent thanks to OBM, Free Communication by Linagora? 
 * signature notice appended to any and all outbound messages 
 * (notably e-mail and meeting requests), (ii) retain all hypertext links between 
 * OBM and obm.org, as well as between Linagora and linagora.com, and (iii) refrain 
 * from infringing Linagora intellectual property rights over its trademarks 
 * and commercial brands. Other Additional Terms apply, 
 * see <http://www.linagora.com/licenses/> for more details. 
 *
 * This program is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
 * for more details. 
 *
 * You should have received a copy of the GNU Affero General Public License 
 * and its applicable Additional Terms for OBM along with this program. If not, 
 * see <http://www.gnu.org/licenses/> for the GNU Affero General Public License version 3 
 * and <http://www.linagora.com/licenses/> for the Additional Terms applicable to 
 * OBM connectors. 
 * 
 * ***** END LICENSE BLOCK ***** */
package org.obm.sync.calendar;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.obm.push.utils.DOMUtils;
import org.obm.push.utils.DateUtils;
import org.obm.sync.base.Category;
import org.obm.sync.items.AbstractItemsParser;
import org.obm.sync.items.EventChanges;
import org.obm.sync.utils.DateHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

public class CalendarItemsParser extends AbstractItemsParser {

    protected Logger logger = LoggerFactory.getLogger(getClass());

    private static final EventPrivacy DEFAULT_PRIVACY_VALUE = EventPrivacy.PUBLIC;
    private static final int DEFAULT_PRIORITY_VALUE = 0;
    private static final int DEFAULT_DURATION_VALUE = 0;

    public EventChanges parseChanges(Document doc) {
        Element root = doc.getDocumentElement();
        Date lastSync = DateHelper.asDate(root.getAttribute("lastSync"));
        Element removed = DOMUtils.getUniqueElement(root, "removed");
        Element updated = DOMUtils.getUniqueElement(root, "updated");

        NodeList rmed = removed.getElementsByTagName("event");
        Set<DeletedEvent> removedIds = Sets.newHashSetWithExpectedSize(rmed.getLength() + 1);
        for (int i = 0; i < rmed.getLength(); i++) {
            Element e = (Element) rmed.item(i);
            removedIds.add(DeletedEvent.builder().eventObmId(Integer.valueOf(e.getAttribute("id")))
                    .eventExtId(e.getAttribute("extId")).build());
        }

        NodeList upd = updated.getElementsByTagName("event");
        List<Event> updatedEvents = new ArrayList<Event>(upd.getLength() + 1);
        for (int i = 0; i < upd.getLength(); i++) {
            Element e = (Element) upd.item(i);
            Event ev = parseEvent(e);
            updatedEvents.add(ev);
        }

        return EventChanges.builder().lastSync(lastSync).deletes(removedIds).updates(updatedEvents).build();
    }

    public Event parseEvent(Element e) {
        Event ev = new Event();
        String id = e.getAttribute("id");
        if (!Strings.isNullOrEmpty(id)) {
            ev.setUid(new EventObmId(id));
        }
        ev.setInternalEvent(e.hasAttribute("isInternal") ? !"false".equals(e.getAttribute("isInternal")) : true);
        ev.setAllday(e.hasAttribute("allDay") ? "true".equals(e.getAttribute("allDay")) : false);
        ev.setType(EventType.valueOf(e.getAttribute("type")));
        // The sequence is not repeated for an event exception
        if (e.hasAttribute("sequence")) {
            ev.setSequence(Integer.valueOf(e.getAttribute("sequence")));
        }
        ev.setExtId(new EventExtId(s(e, "extId")));
        ev.setRecurrenceId(d(e, "recurrenceId"));

        String opacity = DOMUtils.getElementTextInChildren(e, "opacity");
        ev.setOpacity(EventOpacity.getValueOf(opacity));
        ev.setTitle(s(e, "title"));
        String owner = s(e, "owner");
        ev.setOwner(owner);
        ev.setOwnerEmail(s(e, "ownerEmail"));
        ev.setOwnerDisplayName(owner);
        String tz = s(e, "tz");
        if (!DateUtils.isValidTimeZoneIdentifier(tz)) {
            tz = "Europe/Paris";
        }
        ev.setTimezoneName(tz);
        ev.setDescription(s(e, "description"));
        ev.setStartDate(d(e, "date"));
        ev.setPrivacy(getPrivacy(e));
        ev.setAnonymized(getAnonymized(e));
        ev.setPriority(i(e, "priority", DEFAULT_PRIORITY_VALUE));
        ev.setDuration(i(e, "duration", DEFAULT_DURATION_VALUE));
        ev.setCategory(s(e, "category"));
        ev.setLocation(s(e, "location"));
        ev.setAlert(getAlert(e));
        ev.setTimeUpdate(d(e, "timeupdate"));
        ev.setTimeCreate(d(e, "timecreate"));

        parseAttendees(ev, e);

        Element rec = DOMUtils.getUniqueElementInChildren(e, "recurrence");
        if (rec != null) {
            parseRecurrence(ev, rec);
        }

        Element eventsExp = DOMUtils.getUniqueElement(e, "eventExceptions");
        if (eventsExp != null) {
            NodeList elems = eventsExp.getElementsByTagName("eventException");
            for (int i = 0; i < elems.getLength(); i++) {
                Event eexcept = parseEventException(ev, (Element) elems.item(i));
                ev.getRecurrence().addEventException(eexcept);
            }
        }
        return ev;
    }

    private boolean getAnonymized(Element e) {
        return e.hasAttribute("anonymized") ? "true".equals(e.getAttribute("anonymized")) : false;
    }

    private EventPrivacy getPrivacy(Element e) {
        Integer privacy = i(e, "privacy");
        if (privacy != null) {
            return EventPrivacy.valueOf(privacy);
        }
        return DEFAULT_PRIVACY_VALUE;
    }

    private Integer getAlert(Element e) {
        Integer alert = i(e, "alert");
        if (alert == null || alert < 0) {
            return null;
        }
        return alert;
    }

    private Event parseEventException(Event eventReference, Element item) {
        Event eexcept = parseEvent(item);
        eexcept.setSequence(eventReference.getSequence());
        eexcept.setExtId(eventReference.getExtId());
        return eexcept;
    }

    private void parseAttendees(Event ev, Element e) {
        Element ats = DOMUtils.getUniqueElementInChildren(e, "attendees");
        ev.setAttendees(getAttendees(ats));
    }

    private List<Attendee> getAttendees(Element ats) {
        String[][] atVals = DOMUtils.getAttributes(ats, "attendee",
                new String[] { "displayName", "email", "state", "required", "percent", "isOrganizer" });
        List<Attendee> la = new ArrayList<Attendee>(atVals.length);
        for (String[] attendee : atVals) {
            Attendee at = UnidentifiedAttendee.builder().displayName(attendee[0]).email(attendee[1])
                    .participation(Participation.getValueOf(attendee[2]))
                    .participationRole(ParticipationRole.valueOf(attendee[3])).build();

            if (!Strings.isNullOrEmpty(attendee[4])) {
                at.setPercent(Integer.parseInt(attendee[4]));
            } else {
                at.setPercent(100);
            }

            at.setOrganizer(Boolean.parseBoolean(attendee[5]));

            la.add(at);
        }
        return la;

    }

    @VisibleForTesting
    void parseRecurrence(Event ev, Element rec) {
        String kind = rec.getAttribute("kind");
        EventRecurrence er = new EventRecurrence();
        er.setKind(RecurrenceKind.lookup(kind));
        if (er.getKind() != RecurrenceKind.none) {
            if (rec.hasAttribute("end")) {
                er.setEnd(DateHelper.asDate(rec.getAttribute("end")));
            }
            er.setFrequence(Integer.parseInt(rec.getAttribute("freq")));
            RecurrenceDays recurrenceDays = new RecurrenceDaysParser().parse(rec.getAttribute("days"));
            er.setDays(recurrenceDays);
            if (!er.getDays().isEmpty()) {
                er.setKind(RecurrenceKind.weekly);
                if (er.getFrequence() == 0) {
                    er.setFrequence(1);
                }
            }
            String[] exDates = DOMUtils.getTexts(rec, "exception");
            for (int i = 0; i < exDates.length; i++) {
                er.addException(DateHelper.asDate(exDates[i]));

            }
        }
        ev.setRecurrence(er);
    }

    public Collection<CalendarInfo> parseInfos(Document doc) {
        NodeList infosList = doc.getElementsByTagName("info");
        List<CalendarInfo> infos = Lists.newArrayList();
        for (int i = 0; i < infosList.getLength(); i++) {
            infos.add(parseInfo((Element) infosList.item(i)));
        }
        return infos;
    }

    private CalendarInfo parseInfo(Element item) {
        CalendarInfo ci = new CalendarInfo();
        ci.setFirstname(s(item, "first"));
        ci.setLastname(s(item, "last"));
        ci.setMail(s(item, "mail"));
        ci.setUid(s(item, "uid"));
        ci.setRead("true".equals(s(item, "read")));
        ci.setWrite("true".equals(s(item, "write")));
        return ci;
    }

    public Collection<ResourceInfo> parseResourceInfo(Document doc) {
        NodeList resourceInfoList = doc.getElementsByTagName("resourceInfo");
        List<ResourceInfo> resourceInfo = Lists.newArrayList();
        for (int i = 0; i < resourceInfoList.getLength(); i++) {
            resourceInfo.add(parseResourceInfo((Element) resourceInfoList.item(i)));
        }
        return resourceInfo;
    }

    public ResourceInfo parseResourceInfo(Element item) {
        return ResourceInfo.builder().id(i(item, "id")).name(s(item, "name")).mail(s(item, "mail"))
                .description(Strings.emptyToNull(s(item, "description"))).read("true".equals(s(item, "read")))
                .write("true".equals(s(item, "write"))).domainName(s(item, "domain")).build();
    }

    public List<Category> parseCategories(Element documentElement) {
        NodeList nl = documentElement.getElementsByTagName("cat");
        ArrayList<Category> ret = new ArrayList<Category>(nl.getLength());
        for (int i = 0; i < nl.getLength(); i++) {
            Element cat = (Element) nl.item(i);
            Category c = new Category();
            c.setId(Integer.parseInt(cat.getAttribute("id")));
            c.setLabel(cat.getAttribute("label"));
            ret.add(c);
        }
        return ret;
    }

    public List<Event> parseListEvents(Element documentElement) {
        List<Event> ret = new LinkedList<Event>();
        NodeList nl = documentElement.getElementsByTagName("event");
        for (int i = 0; i < nl.getLength(); i++) {
            Element e = (Element) nl.item(i);
            ret.add(parseEvent(e));
        }
        return ret;
    }

    public EventParticipationState parseEventParticipationState(Element e) {
        EventParticipationState eps = new EventParticipationState();
        eps.setUid(e.getAttribute("id"));
        eps.setTitle(s(e, "title"));
        eps.setParticipation(Participation.getValueOf(s(e, "state")));
        eps.setAlert(getAlert(e));
        eps.setDate(d(e, "date"));
        return eps;
    }

    public FreeBusyRequest parseFreeBusyRequest(Element e) {
        FreeBusyRequest fb = new FreeBusyRequest();
        fb.setUid(s(e, "uid"));
        fb.setOwner(s(e, "owner"));
        fb.setStart(d(e, "start"));
        fb.setEnd(d(e, "end"));
        Element ats = DOMUtils.getUniqueElementInChildren(e, "attendees");
        List<Attendee> atts = getAttendees(ats);
        for (Attendee att : atts) {
            fb.addAttendee(att);
        }
        return fb;
    }

    public FreeBusy parseFreeBusy(Element e) {
        FreeBusy fb = new FreeBusy();

        fb.setUid(s(e, "uid"));
        fb.setOwner(s(e, "owner"));
        fb.setStart(d(e, "start"));
        fb.setEnd(d(e, "end"));

        List<Attendee> atts = getAttendees(e);
        if (atts.size() > 0) {
            fb.setAtt(atts.get(0));
        }

        NodeList nlines = e.getElementsByTagName("freebusyinterval");
        for (int j = 0; j < nlines.getLength(); j++) {
            FreeBusyInterval fbl = new FreeBusyInterval();
            Element lineE = (Element) nlines.item(j);
            fbl.setAllDay(b(lineE, "allDay"));
            fbl.setStart(d(lineE, "start"));
            fbl.setDuration(i(lineE, "duration", DEFAULT_DURATION_VALUE));
            fb.addFreeBusyInterval(fbl);
        }
        return fb;
    }

    public List<FreeBusy> parseListFreeBusy(Element e) {
        List<FreeBusy> ret = new LinkedList<FreeBusy>();
        NodeList freebusys = e.getChildNodes();
        for (int i = 0; i < freebusys.getLength(); i++) {
            Element fbe = (Element) freebusys.item(i);
            FreeBusy fb = parseFreeBusy(fbe);
            ret.add(fb);
        }
        return ret;
    }
}