Search in sources :

Example 1 with Priority

use of net.fortuna.ical4j.model.property.Priority in project bw-calendar-engine by Bedework.

the class VEventUtil method toIcalComponent.

/**
 * Make an Icalendar component from a BwEvent object. This may produce a
 * VEvent, VTodo, VJournal or VPoll.
 *
 * @param ei the event
 * @param isOverride - true if event object is an override
 * @param tzreg - timezone registry
 * @param currentPrincipal - href for current authenticated user
 * @return Component
 * @throws CalFacadeException
 */
public static Component toIcalComponent(final EventInfo ei, final boolean isOverride, final TimeZoneRegistry tzreg, final String currentPrincipal) throws CalFacadeException {
    if ((ei == null) || (ei.getEvent() == null)) {
        return null;
    }
    final BwEvent val = ei.getEvent();
    boolean isInstance = false;
    try {
        Component xcomp = null;
        Calendar cal = null;
        final List<BwXproperty> xcompProps = val.getXproperties(BwXproperty.bedeworkIcal);
        if (!Util.isEmpty(xcompProps)) {
            final BwXproperty xcompProp = xcompProps.get(0);
            final String xcompPropVal = xcompProp.getValue();
            if (xcompPropVal != null) {
                final StringBuilder sb = new StringBuilder();
                final Icalendar ic = new Icalendar();
                try {
                    sb.append("BEGIN:VCALENDAR\n");
                    sb.append(Version.VERSION_2_0.toString());
                    sb.append("\n");
                    sb.append(xcompPropVal);
                    if (!xcompPropVal.endsWith("\n")) {
                        sb.append("\n");
                    }
                    sb.append("END:VCALENDAR\n");
                    CalendarBuilder bldr = new CalendarBuilder(new CalendarParserImpl(), ic);
                    UnfoldingReader ufrdr = new UnfoldingReader(new StringReader(sb.toString()), true);
                    cal = bldr.build(ufrdr);
                } catch (Throwable t) {
                    error(t);
                    error("Trying to parse:\n" + xcompPropVal);
                }
            }
        }
        Component comp;
        PropertyList pl = new PropertyList();
        boolean freeBusy = false;
        boolean vavail = false;
        boolean todo = false;
        boolean vpoll = false;
        int entityType = val.getEntityType();
        if (entityType == IcalDefs.entityTypeEvent) {
            comp = new VEvent(pl);
        } else if (entityType == IcalDefs.entityTypeTodo) {
            comp = new VToDo(pl);
            todo = true;
        } else if (entityType == IcalDefs.entityTypeJournal) {
            comp = new VJournal(pl);
        } else if (entityType == IcalDefs.entityTypeFreeAndBusy) {
            comp = new VFreeBusy(pl);
            freeBusy = true;
        } else if (entityType == IcalDefs.entityTypeVavailability) {
            comp = new VAvailability(pl);
            vavail = true;
        } else if (entityType == IcalDefs.entityTypeAvailable) {
            comp = new Available(pl);
        } else if (entityType == IcalDefs.entityTypeVpoll) {
            comp = new VPoll(pl);
            vpoll = true;
        } else {
            throw new CalFacadeException("org.bedework.invalid.entity.type", String.valueOf(entityType));
        }
        if (cal != null) {
            xcomp = cal.getComponent(comp.getName());
        }
        Property prop;
        /* ------------------- RecurrenceID --------------------
       * Done early so we know if this is an instance.
       */
        String strval = val.getRecurrenceId();
        if ((strval != null) && (strval.length() > 0)) {
            isInstance = true;
            pl.add(new RecurrenceId(makeZonedDt(val, strval)));
        }
        /* ------------------- Alarms -------------------- */
        VAlarmUtil.processEventAlarm(val, comp, currentPrincipal);
        /* ------------------- Attachments -------------------- */
        if (val.getNumAttachments() > 0) {
            for (BwAttachment att : val.getAttachments()) {
                pl.add(setAttachment(att));
            }
        }
        /* ------------------- Attendees -------------------- */
        if (!vpoll && (val.getNumAttendees() > 0)) {
            for (BwAttendee att : val.getAttendees()) {
                prop = setAttendee(att);
                mergeXparams(prop, xcomp);
                pl.add(prop);
            }
        }
        if (val.getNumCategories() > 0) {
            // LANG - filter on language - group language in one cat list?
            for (BwCategory cat : val.getCategories()) {
                prop = new Categories();
                TextList cl = ((Categories) prop).getCategories();
                cl.add(cat.getWord().getValue());
                pl.add(langProp(prop, cat.getWord()));
            }
        }
        /* ------------------- Class -------------------- */
        final String pval = val.getClassification();
        if (pval != null) {
            pl.add(new Clazz(pval));
        }
        if (val.getNumComments() > 0) {
            for (final BwString str : val.getComments()) {
                pl.add(langProp(new Comment(str.getValue()), str));
            }
        }
        if ((todo || vpoll) && (val.getCompleted() != null)) {
            prop = new Completed(new DateTime(val.getCompleted()));
            pl.add(prop);
        }
        if (val.getNumContacts() > 0) {
            for (final BwContact c : val.getContacts()) {
                // LANG
                prop = new Contact(c.getCn().getValue());
                final String l = c.getLink();
                if (l != null) {
                    prop.getParameters().add(new AltRep(l));
                }
                pl.add(langProp(uidProp(prop, c.getUid()), c.getCn()));
            }
        }
        if (val.getCost() != null) {
            IcalUtil.addXproperty(pl, BwXproperty.bedeworkCost, null, val.getCost());
        }
        /* ------------------- Created -------------------- */
        prop = new Created(val.getCreated());
        // if (pars.includeDateTimeProperty) {
        // prop.getParameters().add(Value.DATE_TIME);
        // }
        pl.add(prop);
        if (val.getDeleted()) {
            IcalUtil.addXproperty(pl, BwXproperty.bedeworkDeleted, null, String.valueOf(val.getDeleted()));
        }
        /* ------------------- Description -------------------- */
        BwStringBase bwstr = val.findDescription(null);
        if (bwstr != null) {
            pl.add(langProp(new Description(bwstr.getValue()), bwstr));
        }
        if (val.getEndType() == StartEndComponent.endTypeDate) {
            if (todo) {
                Due due = val.getDtend().makeDue(tzreg);
                if (freeBusy | val.getForceUTC()) {
                    due.setUtc(true);
                }
                pl.add(due);
            } else {
                DtEnd dtend = val.getDtend().makeDtEnd(tzreg);
                if (freeBusy | val.getForceUTC()) {
                    dtend.setUtc(true);
                }
                pl.add(dtend);
            }
        } else if (val.getEndType() == StartEndComponent.endTypeDuration) {
            addProperty(comp, new Duration(new Dur(val.getDuration())));
        }
        /* ------------------- DtStamp -------------------- */
        prop = new DtStamp(new DateTime(val.getDtstamp()));
        // if (pars.includeDateTimeProperty) {
        // prop.getParameters().add(Value.DATE_TIME);
        // }
        pl.add(prop);
        if (!val.getNoStart()) {
            DtStart dtstart = val.getDtstart().makeDtStart(tzreg);
            if (freeBusy | val.getForceUTC()) {
                dtstart.setUtc(true);
            }
            pl.add(dtstart);
        }
        if (freeBusy) {
            Collection<BwFreeBusyComponent> fbps = val.getFreeBusyPeriods();
            if (fbps != null) {
                for (BwFreeBusyComponent fbc : fbps) {
                    FreeBusy fb = new FreeBusy();
                    int type = fbc.getType();
                    if (type == BwFreeBusyComponent.typeBusy) {
                        addParameter(fb, FbType.BUSY);
                    } else if (type == BwFreeBusyComponent.typeFree) {
                        addParameter(fb, FbType.FREE);
                    } else if (type == BwFreeBusyComponent.typeBusyUnavailable) {
                        addParameter(fb, FbType.BUSY_UNAVAILABLE);
                    } else if (type == BwFreeBusyComponent.typeBusyTentative) {
                        addParameter(fb, FbType.BUSY_TENTATIVE);
                    } else {
                        throw new CalFacadeException("Bad free-busy type " + type);
                    }
                    PeriodList pdl = fb.getPeriods();
                    for (Period p : fbc.getPeriods()) {
                        // XXX inverse.ca plugin cannot handle durations.
                        Period np = new Period(p.getStart(), p.getEnd());
                        pdl.add(np);
                    }
                    pl.add(fb);
                }
            }
        }
        if (!vpoll) {
            BwGeo bwgeo = val.getGeo();
            if (bwgeo != null) {
                Geo geo = new Geo(bwgeo.getLatitude(), bwgeo.getLongitude());
                pl.add(geo);
            }
        }
        /* ------------------- LastModified -------------------- */
        prop = new LastModified(new DateTime(val.getLastmod()));
        // if (pars.includeDateTimeProperty) {
        // prop.getParameters().add(Value.DATE_TIME);
        // }
        pl.add(prop);
        if (!vpoll) {
            final BwLocation loc = val.getLocation();
            if (loc != null) {
                prop = new Location(loc.getCombinedValues());
                pl.add(langProp(uidProp(prop, loc.getUid()), loc.getAddress()));
                IcalUtil.addXproperty(pl, BwXproperty.xBedeworkLocationAddr, null, loc.getAddressField());
                IcalUtil.addXproperty(pl, BwXproperty.xBedeworkLocationRoom, null, loc.getRoomField());
                IcalUtil.addXproperty(pl, BwXproperty.xBedeworkLocationAccessible, null, String.valueOf(loc.getAccessible()));
                IcalUtil.addXproperty(pl, BwXproperty.xBedeworkLocationSfield1, null, loc.getSubField1());
                IcalUtil.addXproperty(pl, BwXproperty.xBedeworkLocationSfield2, null, loc.getSubField2());
                IcalUtil.addXproperty(pl, BwXproperty.xBedeworkLocationGeo, null, loc.getGeouri());
                IcalUtil.addXproperty(pl, BwXproperty.xBedeworkLocationStreet, null, loc.getStreet());
                IcalUtil.addXproperty(pl, BwXproperty.xBedeworkLocationCity, null, loc.getCity());
                IcalUtil.addXproperty(pl, BwXproperty.xBedeworkLocationState, null, loc.getState());
                IcalUtil.addXproperty(pl, BwXproperty.xBedeworkLocationZip, null, loc.getZip());
                IcalUtil.addXproperty(pl, BwXproperty.xBedeworkLocationLink, null, loc.getLink());
            }
        }
        /* ------------------- Organizer -------------------- */
        BwOrganizer org = val.getOrganizer();
        if (org != null) {
            prop = setOrganizer(org);
            mergeXparams(prop, xcomp);
            pl.add(prop);
        }
        if (todo) {
            Integer pc = val.getPercentComplete();
            if (pc != null) {
                pl.add(new PercentComplete(pc.intValue()));
            }
        }
        /* ------------------- Priority -------------------- */
        Integer prio = val.getPriority();
        if (prio != null) {
            pl.add(new Priority(prio.intValue()));
        }
        /* ------------------- RDate -below------------------- */
        /* ------------------- RelatedTo -------------------- */
        /* We encode related to (maybe) as triples - reltype, value-type, value */
        String[] info = null;
        BwRelatedTo relto = val.getRelatedTo();
        if (relto != null) {
            info = new String[3];
            info[0] = relto.getRelType();
            // default
            info[1] = "";
            info[2] = relto.getValue();
        } else {
            String relx = val.getXproperty(BwXproperty.bedeworkRelatedTo);
            if (relx != null) {
                info = Util.decodeArray(relx);
            }
        }
        if (info != null) {
            int i = 0;
            while (i < info.length) {
                RelatedTo irelto;
                String reltype = info[i];
                String valtype = info[i + 1];
                String relval = info[i + 2];
                ParameterList rtpl = null;
                if (reltype.length() > 0) {
                    rtpl = new ParameterList();
                    rtpl.add(new RelType(reltype));
                }
                if (valtype.length() > 0) {
                    if (rtpl == null) {
                        rtpl = new ParameterList();
                    }
                    rtpl.add(new Value(valtype));
                }
                if (rtpl != null) {
                    irelto = new RelatedTo(rtpl, relval);
                } else {
                    irelto = new RelatedTo(relval);
                }
                pl.add(irelto);
                i += 3;
            }
        }
        if (val.getNumResources() > 0) {
            /* This event has a resource */
            prop = new Resources();
            TextList rl = ((Resources) prop).getResources();
            for (BwString str : val.getResources()) {
                // LANG
                rl.add(str.getValue());
            }
            pl.add(prop);
        }
        if (val.getSequence() > 0) {
            pl.add(new Sequence(val.getSequence()));
        }
        /* ------------------- Status -------------------- */
        String status = val.getStatus();
        if ((status != null) && !status.equals(BwEvent.statusMasterSuppressed)) {
            pl.add(new Status(status));
        }
        /* ------------------- Summary -------------------- */
        bwstr = val.findSummary(null);
        if (bwstr != null) {
            pl.add(langProp(new Summary(bwstr.getValue()), bwstr));
        }
        if (!todo && !vpoll) {
            strval = val.getPeruserTransparency(currentPrincipal);
            if ((strval != null) && (strval.length() > 0)) {
                pl.add(new Transp(strval));
            }
        }
        /* ------------------- Uid -------------------- */
        pl.add(new Uid(val.getUid()));
        /* ------------------- Url -------------------- */
        strval = val.getLink();
        if (strval != null) {
            // Possibly drop this if we do it on input and check all data
            strval = strval.trim();
        }
        if ((strval != null) && (strval.length() > 0)) {
            URI uri = Util.validURI(strval);
            if (uri != null) {
                pl.add(new Url(uri));
            }
        }
        if (val.getNumXproperties() > 0) {
            try {
                IcalUtil.xpropertiesToIcal(pl, val.getXproperties());
            } catch (Throwable t) {
                // XXX For the moment swallow these.
                error(t);
            }
        }
        if (!vpoll && !isInstance && !isOverride && val.testRecurring()) {
            doRecurring(val, pl);
        }
        if (vavail) {
            if (ei.getNumContainedItems() > 0) {
                final VAvailability va = (VAvailability) comp;
                for (final EventInfo aei : ei.getContainedItems()) {
                    va.getAvailable().add((Available) toIcalComponent(aei, false, tzreg, currentPrincipal));
                }
            }
            /* ----------- Vavailability - busyType ----------------- */
            String s = val.getBusyTypeString();
            if (s != null) {
                pl.add(new BusyType(s));
            }
        }
        if (vpoll) {
            final Integer ival = val.getPollWinner();
            if (ival != null) {
                pl.add(new PollWinner(ival));
            }
            strval = val.getPollAcceptResponse();
            if ((strval != null) && (strval.length() > 0)) {
                pl.add(new AcceptResponse(strval));
            }
            strval = val.getPollMode();
            if ((strval != null) && (strval.length() > 0)) {
                pl.add(new PollMode(strval));
            }
            strval = val.getPollProperties();
            if ((strval != null) && (strval.length() > 0)) {
                pl.add(new PollProperties(strval));
            }
            final Map<String, VVoter> vvoters = parseVpollVvoters(val);
            for (final VVoter vv : vvoters.values()) {
                ((VPoll) comp).getVoters().add(vv);
            }
            final Map<Integer, Component> comps = parseVpollCandidates(val);
            for (final Component candidate : comps.values()) {
                ((VPoll) comp).getCandidates().add(candidate);
            }
        }
        return comp;
    } catch (final CalFacadeException cfe) {
        throw cfe;
    } catch (final Throwable t) {
        throw new CalFacadeException(t);
    }
}
Also used : FreeBusy(net.fortuna.ical4j.model.property.FreeBusy) VFreeBusy(net.fortuna.ical4j.model.component.VFreeBusy) BwRelatedTo(org.bedework.calfacade.BwRelatedTo) EventInfo(org.bedework.calfacade.svc.EventInfo) BwCategory(org.bedework.calfacade.BwCategory) BwString(org.bedework.calfacade.BwString) VAvailability(net.fortuna.ical4j.model.component.VAvailability) DateTime(net.fortuna.ical4j.model.DateTime) BwDateTime(org.bedework.calfacade.BwDateTime) TextList(net.fortuna.ical4j.model.TextList) LastModified(net.fortuna.ical4j.model.property.LastModified) DtStamp(net.fortuna.ical4j.model.property.DtStamp) AcceptResponse(net.fortuna.ical4j.model.property.AcceptResponse) Available(net.fortuna.ical4j.model.component.Available) BwAttachment(org.bedework.calfacade.BwAttachment) RelatedTo(net.fortuna.ical4j.model.property.RelatedTo) BwRelatedTo(org.bedework.calfacade.BwRelatedTo) VEvent(net.fortuna.ical4j.model.component.VEvent) Status(net.fortuna.ical4j.model.property.Status) BwFreeBusyComponent(org.bedework.calfacade.BwFreeBusyComponent) BwLocation(org.bedework.calfacade.BwLocation) VVoter(net.fortuna.ical4j.model.component.VVoter) Transp(net.fortuna.ical4j.model.property.Transp) Categories(net.fortuna.ical4j.model.property.Categories) Priority(net.fortuna.ical4j.model.property.Priority) BusyType(net.fortuna.ical4j.model.property.BusyType) PeriodList(net.fortuna.ical4j.model.PeriodList) Period(net.fortuna.ical4j.model.Period) Duration(net.fortuna.ical4j.model.property.Duration) BwString(org.bedework.calfacade.BwString) BwContact(org.bedework.calfacade.BwContact) Sequence(net.fortuna.ical4j.model.property.Sequence) Geo(net.fortuna.ical4j.model.property.Geo) BwGeo(org.bedework.calfacade.BwGeo) Uid(net.fortuna.ical4j.model.property.Uid) PollMode(net.fortuna.ical4j.model.property.PollMode) BwXproperty(org.bedework.calfacade.BwXproperty) Value(net.fortuna.ical4j.model.parameter.Value) ParameterList(net.fortuna.ical4j.model.ParameterList) RecurrenceId(net.fortuna.ical4j.model.property.RecurrenceId) Resources(net.fortuna.ical4j.model.property.Resources) BwAttendee(org.bedework.calfacade.BwAttendee) VToDo(net.fortuna.ical4j.model.component.VToDo) CalendarParserImpl(net.fortuna.ical4j.data.CalendarParserImpl) VJournal(net.fortuna.ical4j.model.component.VJournal) Description(net.fortuna.ical4j.model.property.Description) BwGeo(org.bedework.calfacade.BwGeo) AltRep(net.fortuna.ical4j.model.parameter.AltRep) BwEvent(org.bedework.calfacade.BwEvent) URI(java.net.URI) Url(net.fortuna.ical4j.model.property.Url) PollWinner(net.fortuna.ical4j.model.property.PollWinner) Created(net.fortuna.ical4j.model.property.Created) VPoll(net.fortuna.ical4j.model.component.VPoll) Due(net.fortuna.ical4j.model.property.Due) StringReader(java.io.StringReader) PollProperties(net.fortuna.ical4j.model.property.PollProperties) Clazz(net.fortuna.ical4j.model.property.Clazz) StartEndComponent(org.bedework.calfacade.base.StartEndComponent) Component(net.fortuna.ical4j.model.Component) BwFreeBusyComponent(org.bedework.calfacade.BwFreeBusyComponent) DateListProperty(net.fortuna.ical4j.model.property.DateListProperty) Property(net.fortuna.ical4j.model.Property) BwOrganizer(org.bedework.calfacade.BwOrganizer) Dur(net.fortuna.ical4j.model.Dur) Comment(net.fortuna.ical4j.model.property.Comment) RelType(net.fortuna.ical4j.model.parameter.RelType) VFreeBusy(net.fortuna.ical4j.model.component.VFreeBusy) Calendar(net.fortuna.ical4j.model.Calendar) UnfoldingReader(net.fortuna.ical4j.data.UnfoldingReader) CalFacadeException(org.bedework.calfacade.exc.CalFacadeException) Contact(net.fortuna.ical4j.model.property.Contact) BwContact(org.bedework.calfacade.BwContact) PropertyList(net.fortuna.ical4j.model.PropertyList) DtStart(net.fortuna.ical4j.model.property.DtStart) BwStringBase(org.bedework.calfacade.base.BwStringBase) PercentComplete(net.fortuna.ical4j.model.property.PercentComplete) Completed(net.fortuna.ical4j.model.property.Completed) Summary(net.fortuna.ical4j.model.property.Summary) DtEnd(net.fortuna.ical4j.model.property.DtEnd) BwLocation(org.bedework.calfacade.BwLocation) Location(net.fortuna.ical4j.model.property.Location)

Example 2 with Priority

use of net.fortuna.ical4j.model.property.Priority in project zm-mailbox by Zimbra.

the class DefaultTnefToICalendar method convert.

/* (non-Javadoc)
     * @see com.zimbra.cs.util.tnef.TnefToICalendar#convert(java.io.InputStream, net.fortuna.ical4j.data.ContentHandler)
     */
public boolean convert(MimeMessage mimeMsg, InputStream tnefInput, ContentHandler icalOutput) throws ServiceException {
    boolean conversionSuccessful = false;
    recurDef = null;
    TNEFInputStream tnefStream = null;
    SchedulingViewOfTnef schedView = null;
    Integer sequenceNum = 0;
    icalType = ICALENDAR_TYPE.VEVENT;
    try {
        tnefStream = new TNEFInputStream(tnefInput);
        schedView = new SchedulingViewOfTnef(tnefStream);
        String msgClass = schedView.getMessageClass();
        if (msgClass == null) {
            sLog.debug("Unable to determine Class of TNEF - cannot generate ICALENDER equivalent");
            // throw TNEFtoIcalendarServiceException.NON_CALENDARING_CLASS(msgClass);
            return false;
        }
        icalType = schedView.getIcalType();
        method = null;
        PartStat partstat = null;
        boolean replyWanted = schedView.getResponseRequested();
        Boolean isCounterProposal = schedView.isCounterProposal();
        if (msgClass != null) {
            // just in case.
            if (msgClass.startsWith("IPM.Microsoft Schedule.MtgReq")) {
                method = Method.REQUEST;
                partstat = PartStat.NEEDS_ACTION;
            } else if (msgClass.startsWith("IPM.Microsoft Schedule.MtgRespP")) {
                method = Method.REPLY;
                partstat = PartStat.ACCEPTED;
                replyWanted = false;
            } else if (msgClass.startsWith("IPM.Microsoft Schedule.MtgRespN")) {
                method = Method.REPLY;
                partstat = PartStat.DECLINED;
                replyWanted = false;
            } else if (msgClass.startsWith("IPM.Microsoft Schedule.MtgRespA")) {
                if ((isCounterProposal != null) && isCounterProposal) {
                    method = Method.COUNTER;
                } else {
                    method = Method.REPLY;
                }
                partstat = PartStat.TENTATIVE;
                replyWanted = false;
            } else if (msgClass.startsWith("IPM.Microsoft Schedule.MtgCncl")) {
                method = Method.CANCEL;
                replyWanted = false;
            } else if (msgClass.startsWith("IPM.TaskRequest.Accept")) {
                method = Method.REPLY;
                partstat = PartStat.ACCEPTED;
                replyWanted = false;
            } else if (msgClass.startsWith("IPM.TaskRequest.Decline")) {
                method = Method.REPLY;
                partstat = PartStat.DECLINED;
                replyWanted = false;
            } else if (msgClass.startsWith("IPM.TaskRequest.Update")) {
                method = Method.REPLY;
                // May be overridden?
                partstat = PartStat.IN_PROCESS;
                replyWanted = false;
            } else if (msgClass.startsWith("IPM.TaskRequest")) {
                method = Method.REQUEST;
                partstat = PartStat.NEEDS_ACTION;
                replyWanted = true;
            }
        }
        if (method == null) {
            sLog.debug("Unable to map class %s to ICALENDER", msgClass);
            return false;
        // throw TNEFtoIcalendarServiceException.NON_CALENDARING_CLASS(msgClass);
        }
        if (icalType == ICALENDAR_TYPE.VTODO) {
            List<?> attaches = (List<?>) schedView.getAttachments();
            if (attaches == null) {
                sLog.debug("Unable to map class %s to ICALENDER - no attachments", msgClass);
                return false;
            }
            schedView = null;
            for (Object obj : attaches) {
                if (obj instanceof Attachment) {
                    Attachment currAttach = (Attachment) obj;
                    MAPIProps attachMPs = currAttach.getMAPIProps();
                    if (attachMPs != null) {
                        MAPIProp attachData = attachMPs.getProp(MAPIProp.PR_ATTACH_DATA_OBJ);
                        if (attachData != null) {
                            Object theVal = attachData.getValue();
                            if ((theVal != null) && (theVal instanceof TNEFInputStream)) {
                                TNEFInputStream tnefSubStream = (TNEFInputStream) theVal;
                                schedView = new SchedulingViewOfTnef(tnefSubStream);
                                break;
                            }
                        }
                    }
                }
            }
            if (schedView == null) {
                sLog.debug("Unable to map class %s to ICALENDER - no properties found for sub-msg", msgClass);
                return false;
            }
        }
        uid = schedView.getIcalUID();
        sequenceNum = schedView.getSequenceNumber();
        boolean reminderSet = schedView.getReminderSet();
        String location = schedView.getLocation();
        Boolean isAllDayEvent = schedView.isAllDayEvent();
        Integer importance = schedView.getMapiImportance();
        Clazz icalClass = schedView.getIcalClass();
        Integer ownerApptId = schedView.getOwnerAppointmentId();
        EnumSet<MeetingTypeFlag> meetingTypeFlags = schedView.getMeetingTypeFlags();
        BusyStatus busyStatus = schedView.getBusyStatus();
        BusyStatus intendedBusyStatus = schedView.getIntendedBusyStatus();
        // For some ICAL properties like TRANSP and STATUS, intendedBusyStatus
        // seems closer to what is intended than straight busyStatus
        BusyStatus bestBusyStatus = intendedBusyStatus;
        if (bestBusyStatus == null) {
            bestBusyStatus = busyStatus;
        }
        // An algorithm is used to choose the values for these
        // TimeZoneDefinitions  - they don't necessarily map to single
        // MAPI properties
        TimeZoneDefinition startTimeTZinfo = schedView.getStartDateTimezoneInfo();
        TimeZoneDefinition endTimeTZinfo = schedView.getEndDateTimezoneInfo();
        TimeZoneDefinition recurrenceTZinfo = schedView.getRecurrenceTimezoneInfo();
        recurDef = schedView.getRecurrenceDefinition(recurrenceTZinfo);
        DateTime icalStartDate = schedView.getStartTime();
        DateTime icalEndDate = schedView.getEndTime();
        DateTime icalDueDate = schedView.getDueDate();
        DateTime icalDateTaskCompleted = schedView.getDateTaskCompleted();
        DateTime icalCreateDate = MapiPropertyId.PidTagCreationTime.getDateTimeAsUTC(schedView);
        DateTime icalLastModDate = MapiPropertyId.PidTagLastModificationTime.getDateTimeAsUTC(schedView);
        DateTime recurrenceIdDateTime = schedView.getRecurrenceIdTime();
        DateTime attendeeCriticalChange = schedView.getAttendeeCriticalChange();
        DateTime ownerCriticalChange = schedView.getOwnerCriticalChange();
        int percentComplete = schedView.getPercentComplete();
        TaskStatus taskStatus = schedView.getTaskStatus();
        TaskMode taskMode = schedView.getTaskMode();
        String mileage = schedView.getMileage();
        String billingInfo = schedView.getBillingInfo();
        String companies = schedView.getCompanies();
        Integer actualEffort = schedView.getActualEffort();
        Integer estimatedEffort = schedView.getEstimatedEffort();
        List<String> categories = schedView.getCategories();
        String descriptionText = null;
        String summary = null;
        if (mimeMsg != null) {
            summary = mimeMsg.getSubject();
            PlainTextFinder finder = new PlainTextFinder();
            finder.accept(mimeMsg);
            descriptionText = finder.getPlainText();
        }
        // RTF might be useful as a basis for X-ALT-DESC if we can find a reliable
        // conversion to HTML
        // String rtfText = schedView.getRTF();
        icalOutput.startCalendar();
        // Results in a 2nd PRODID in iCalendar
        // IcalUtil.addProperty(icalOutput, Property.PRODID,
        // "Zimbra-TNEF-iCalendar-Converter");
        IcalUtil.addProperty(icalOutput, method);
        if (recurDef != null) {
            String MsCalScale = recurDef.xMicrosoftCalscale();
            if ((MsCalScale == null) || (MsCalScale.equals(""))) {
                IcalUtil.addProperty(icalOutput, CalScale.GREGORIAN);
            } else {
                IcalUtil.addProperty(icalOutput, "X-MICROSOFT-CALSCALE", MsCalScale);
            }
        } else {
            IcalUtil.addProperty(icalOutput, CalScale.GREGORIAN);
        }
        String startTZname = null;
        String endTZname = null;
        String recurTZname = null;
        if (startTimeTZinfo != null) {
            startTZname = startTimeTZinfo.getTimezoneName();
            startTimeTZinfo.addVtimezone(icalOutput);
        }
        if (endTimeTZinfo != null) {
            endTZname = endTimeTZinfo.getTimezoneName();
            if ((startTZname == null) || (!endTZname.equals(startTZname))) {
                endTimeTZinfo.addVtimezone(icalOutput);
            }
        }
        if (recurrenceTZinfo != null) {
            recurTZname = recurrenceTZinfo.getTimezoneName();
            boolean addName = true;
            if ((startTZname != null) && (recurTZname.equals(startTZname))) {
                addName = false;
            }
            if ((endTZname != null) && (recurTZname.equals(endTZname))) {
                addName = false;
            }
            if (addName) {
                recurrenceTZinfo.addVtimezone(icalOutput);
            }
        }
        if (uid == null) {
            sLog.debug("Unable to map class %s to ICALENDER - no suitable value found for UID", msgClass);
            return false;
        }
        icalOutput.startComponent(icalType.toString());
        IcalUtil.addProperty(icalOutput, Property.UID, uid);
        if ((attendeeCriticalChange != null) && (method.equals(Method.REPLY) || method.equals(Method.COUNTER))) {
            dtstamp = new DtStamp(attendeeCriticalChange);
        } else if (ownerCriticalChange != null) {
            dtstamp = new DtStamp(ownerCriticalChange);
        } else {
            DateTime stampTime = new DateTime("20000101T000000Z");
            dtstamp = new DtStamp(stampTime);
        }
        IcalUtil.addProperty(icalOutput, dtstamp);
        IcalUtil.addProperty(icalOutput, Property.CREATED, icalCreateDate, false);
        IcalUtil.addProperty(icalOutput, Property.LAST_MODIFIED, icalLastModDate, false);
        IcalUtil.addProperty(icalOutput, Property.SEQUENCE, sequenceNum, false);
        if ((summary == null) || (summary.length() == 0)) {
            // TNEF_to_iCalendar.pdf Spec requires SUMMARY for certain method types
            if (this.icalType == ICALENDAR_TYPE.VTODO) {
                if (method.equals(Method.REQUEST)) {
                    summary = new String("Task Request");
                } else if (method.equals(Method.REPLY)) {
                    summary = new String("Task Response");
                } else {
                    summary = new String("Task");
                }
            } else {
                if (method.equals(Method.REPLY)) {
                    summary = new String("Response");
                } else if (method.equals(Method.CANCEL)) {
                    summary = new String("Canceled");
                } else if (method.equals(Method.COUNTER)) {
                    summary = new String("Counter Proposal");
                }
            }
        }
        IcalUtil.addProperty(icalOutput, Property.SUMMARY, summary, false);
        IcalUtil.addProperty(icalOutput, Property.LOCATION, location, false);
        IcalUtil.addProperty(icalOutput, Property.DESCRIPTION, descriptionText, false);
        if (method.equals(Method.COUNTER)) {
            IcalUtil.addPropertyFromUtcTimeAndZone(icalOutput, Property.DTSTART, schedView.getProposedStartTime(), startTimeTZinfo, isAllDayEvent);
            IcalUtil.addPropertyFromUtcTimeAndZone(icalOutput, Property.DTEND, schedView.getProposedEndTime(), endTimeTZinfo, isAllDayEvent);
            IcalUtil.addPropertyFromUtcTimeAndZone(icalOutput, "X-MS-OLK-ORIGINALSTART", icalStartDate, startTimeTZinfo, isAllDayEvent);
            IcalUtil.addPropertyFromUtcTimeAndZone(icalOutput, "X-MS-OLK-ORIGINALEND", icalEndDate, endTimeTZinfo, isAllDayEvent);
        } else {
            if (this.icalType == ICALENDAR_TYPE.VTODO) {
                IcalUtil.addFloatingDateProperty(icalOutput, Property.DTSTART, icalStartDate);
                IcalUtil.addFloatingDateProperty(icalOutput, Property.DUE, icalDueDate);
                Status icalStatus = null;
                if (method.equals(Method.CANCEL)) {
                    icalStatus = Status.VTODO_CANCELLED;
                } else if (taskStatus != null) {
                    if (taskStatus.equals(TaskStatus.COMPLETE)) {
                        icalStatus = Status.VTODO_COMPLETED;
                    } else if (taskStatus.equals(TaskStatus.IN_PROGRESS)) {
                        icalStatus = Status.VTODO_IN_PROCESS;
                    }
                }
                IcalUtil.addProperty(icalOutput, icalStatus);
                if (percentComplete != 0) {
                    IcalUtil.addProperty(icalOutput, Property.PERCENT_COMPLETE, percentComplete, false);
                }
                // COMPLETED must be a UTC DATE-TIME according to rfc5545
                IcalUtil.addPropertyFromUtcTimeAndZone(icalOutput, Property.COMPLETED, icalDateTaskCompleted, null, false);
            } else {
                IcalUtil.addPropertyFromUtcTimeAndZone(icalOutput, Property.DTSTART, icalStartDate, startTimeTZinfo, isAllDayEvent);
                IcalUtil.addPropertyFromUtcTimeAndZone(icalOutput, Property.DTEND, icalEndDate, endTimeTZinfo, isAllDayEvent);
            }
        }
        // just the original start date.
        if (recurrenceIdDateTime != null) {
            IcalUtil.addPropertyFromUtcTimeAndZone(icalOutput, Property.RECURRENCE_ID, recurrenceIdDateTime, startTimeTZinfo, isAllDayEvent);
        } else {
            // Outlook messages related to a specific instance still include info on
            // the full recurrence but we don't want to include that.
            addRecurrenceRelatedProps(icalOutput, recurDef, startTimeTZinfo, isAllDayEvent);
        }
        // VTODO REQUEST must have priority according to http://tools.ietf.org/html/rfc5546
        // No harm in always setting it
        Priority priority = Priority.MEDIUM;
        if (importance != null) {
            if (importance == 2) {
                priority = Priority.HIGH;
            } else if (importance == 1) {
                priority = Priority.MEDIUM;
            } else if (importance == 0) {
                priority = Priority.LOW;
            }
        }
        IcalUtil.addProperty(icalOutput, priority);
        IcalUtil.addProperty(icalOutput, icalClass);
        addStatusProperty(icalOutput, bestBusyStatus, meetingTypeFlags);
        addTranspProperty(icalOutput, bestBusyStatus);
        addAttendees(icalOutput, mimeMsg, partstat, replyWanted);
        // Not done as Zimbra doesn't currently support "RESOURCES".
        if (categories != null) {
            CategoryList cl = new CategoryList();
            for (String category : categories) {
                cl.add(category);
            }
            if (cl.size() > 0) {
                Categories myCategories = new Categories(cl);
                IcalUtil.addProperty(icalOutput, myCategories);
            }
        }
        if (taskStatus != null) {
            if (taskStatus.equals(TaskStatus.DEFERRED) || taskStatus.equals(TaskStatus.WAITING_ON_OTHER)) {
                IcalUtil.addProperty(icalOutput, "X-ZIMBRA-TASK-STATUS", taskStatus, false);
            }
        }
        if ((taskMode != null) && (!taskMode.equals(TaskMode.TASK_REQUEST))) {
            IcalUtil.addProperty(icalOutput, "X-ZIMBRA-TASK-MODE", taskMode, false);
        }
        IcalUtil.addProperty(icalOutput, "X-ZIMBRA-MILEAGE", mileage, false);
        IcalUtil.addProperty(icalOutput, "X-ZIMBRA-BILLING-INFO", billingInfo, false);
        IcalUtil.addProperty(icalOutput, "X-ZIMBRA-COMPANIES", companies, false);
        IcalUtil.addProperty(icalOutput, "X-ZIMBRA-ACTUAL-WORK-MINS", actualEffort, false);
        IcalUtil.addProperty(icalOutput, "X-ZIMBRA-TOTAL-WORK-MINS", estimatedEffort, false);
        if (this.icalType == ICALENDAR_TYPE.VEVENT) {
            IcalUtil.addProperty(icalOutput, "X-MICROSOFT-CDO-ALLDAYEVENT", isAllDayEvent ? "TRUE" : "FALSE");
            IcalUtil.addProperty(icalOutput, "X-MICROSOFT-CDO-BUSYSTATUS", busyStatus, false);
            if (method.equals(Method.REQUEST)) {
                IcalUtil.addProperty(icalOutput, "X-MICROSOFT-CDO-INTENDEDSTATUS", intendedBusyStatus, false);
            }
            IcalUtil.addProperty(icalOutput, "X-MICROSOFT-CDO-OWNERAPPTID", ownerApptId, false);
            IcalUtil.addProperty(icalOutput, "X-MICROSOFT-CDO-REPLYTIME", schedView.getAppointmentReplyTime(), false);
            IcalUtil.addProperty(icalOutput, "X-MICROSOFT-CDO-OWNER-CRITICAL-CHANGE", ownerCriticalChange, false);
            Boolean disallowCounter = schedView.isDisallowCounter();
            if (disallowCounter != null) {
                IcalUtil.addProperty(icalOutput, "X-MICROSOFT-CDO-DISALLOW-COUNTER", disallowCounter ? "TRUE" : "FALSE");
            }
        }
        if (reminderSet) {
            addAlarmComponent(icalOutput, schedView.getReminderDelta());
        }
        icalOutput.endComponent(icalType.toString());
        if (recurrenceIdDateTime == null) {
            // If this message primarily relates to a specific instance,
            // exception information is superfluous
            addExceptions(icalOutput, recurDef, recurrenceTZinfo, sequenceNum, ownerApptId, summary, location, isAllDayEvent);
        }
        icalOutput.endCalendar();
        conversionSuccessful = true;
        sLog.info("Calendaring TNEF message mapped to ICALENDAR with UID=%s", uid);
    } catch (ParserException e) {
        sLog.debug("Unexpected ParserException thrown", e);
    } catch (URISyntaxException e) {
        sLog.debug("Unexpected URISyntaxException thrown", e);
    } catch (ParseException e) {
        sLog.debug("Unexpected ParseException thrown", e);
    } catch (MessagingException e) {
        sLog.debug("Unexpected MessagingException thrown", e);
    } catch (NegativeArraySizeException e) {
        sLog.debug("Problem decoding TNEF for ICALENDAR", e);
    } catch (IOException e) {
        sLog.debug("Unexpected IOException thrown", e);
    } catch (UnsupportedTnefCalendaringMsgException e) {
        sLog.debug("Unable to map this message to ICALENDAR", e);
    } catch (TNEFtoIcalendarServiceException e) {
        sLog.debug("Problem encountered mapping this message to ICALENDAR", e);
    } finally {
        try {
            if (tnefStream != null) {
                tnefStream.close();
            }
        } catch (IOException ioe) {
            sLog.debug("Problem encountered closing TNEF stream", ioe);
        }
    }
    return conversionSuccessful;
}
Also used : MAPIProps(net.freeutils.tnef.MAPIProps) TimeZoneDefinition(com.zimbra.cs.util.tnef.mapi.TimeZoneDefinition) Attachment(net.freeutils.tnef.Attachment) BusyStatus(com.zimbra.cs.util.tnef.mapi.BusyStatus) URISyntaxException(java.net.URISyntaxException) TaskMode(com.zimbra.cs.util.tnef.mapi.TaskMode) MAPIProp(net.freeutils.tnef.MAPIProp) DateTime(net.fortuna.ical4j.model.DateTime) DtStamp(net.fortuna.ical4j.model.property.DtStamp) MeetingTypeFlag(com.zimbra.cs.util.tnef.mapi.MeetingTypeFlag) List(java.util.List) ParameterList(net.fortuna.ical4j.model.ParameterList) CategoryList(net.fortuna.ical4j.model.CategoryList) Clazz(net.fortuna.ical4j.model.property.Clazz) UnsupportedTnefCalendaringMsgException(com.zimbra.cs.util.tnef.TNEFtoIcalendarServiceException.UnsupportedTnefCalendaringMsgException) Status(net.fortuna.ical4j.model.property.Status) TaskStatus(com.zimbra.cs.util.tnef.mapi.TaskStatus) BusyStatus(com.zimbra.cs.util.tnef.mapi.BusyStatus) ParserException(net.fortuna.ical4j.data.ParserException) Categories(net.fortuna.ical4j.model.property.Categories) MessagingException(javax.mail.MessagingException) Priority(net.fortuna.ical4j.model.property.Priority) PartStat(net.fortuna.ical4j.model.parameter.PartStat) IOException(java.io.IOException) TNEFInputStream(net.freeutils.tnef.TNEFInputStream) TaskStatus(com.zimbra.cs.util.tnef.mapi.TaskStatus) CategoryList(net.fortuna.ical4j.model.CategoryList) ParseException(java.text.ParseException)

Aggregations

DateTime (net.fortuna.ical4j.model.DateTime)2 ParameterList (net.fortuna.ical4j.model.ParameterList)2 Categories (net.fortuna.ical4j.model.property.Categories)2 Clazz (net.fortuna.ical4j.model.property.Clazz)2 DtStamp (net.fortuna.ical4j.model.property.DtStamp)2 Priority (net.fortuna.ical4j.model.property.Priority)2 Status (net.fortuna.ical4j.model.property.Status)2 UnsupportedTnefCalendaringMsgException (com.zimbra.cs.util.tnef.TNEFtoIcalendarServiceException.UnsupportedTnefCalendaringMsgException)1 BusyStatus (com.zimbra.cs.util.tnef.mapi.BusyStatus)1 MeetingTypeFlag (com.zimbra.cs.util.tnef.mapi.MeetingTypeFlag)1 TaskMode (com.zimbra.cs.util.tnef.mapi.TaskMode)1 TaskStatus (com.zimbra.cs.util.tnef.mapi.TaskStatus)1 TimeZoneDefinition (com.zimbra.cs.util.tnef.mapi.TimeZoneDefinition)1 IOException (java.io.IOException)1 StringReader (java.io.StringReader)1 URI (java.net.URI)1 URISyntaxException (java.net.URISyntaxException)1 ParseException (java.text.ParseException)1 List (java.util.List)1 MessagingException (javax.mail.MessagingException)1