/* ********************************************************************
Licensed to Jasig under one or more contributor license
agreements. See the NOTICE file distributed with this work
for additional information regarding copyright ownership.
Jasig licenses this file to you under the Apache License,
Version 2.0 (the "License"); you may not use this file
except in compliance with the License. You may obtain a
copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.bedework.caldav.bwserver;
import org.bedework.access.AccessPrincipal;
import org.bedework.caldav.server.CalDAVEvent;
import org.bedework.caldav.server.Organizer;
import org.bedework.calfacade.BwAttendee;
import org.bedework.calfacade.BwEvent;
import org.bedework.calfacade.BwEventObj;
import org.bedework.calfacade.BwOrganizer;
import org.bedework.calfacade.BwXproperty;
import org.bedework.calfacade.svc.EventInfo;
import org.bedework.icalendar.IcalTranslator;
import org.bedework.util.calendar.ScheduleMethods;
import org.bedework.util.misc.Util;
import org.bedework.util.xml.XmlEmit;
import org.bedework.util.xml.tagdefs.AppleServerTags;
import org.bedework.util.xml.tagdefs.CaldavTags;
import org.bedework.util.xml.tagdefs.ICalTags;
import org.bedework.util.xml.tagdefs.WebdavTags;
import org.bedework.webdav.servlet.shared.WebdavException;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import javax.xml.namespace.QName;
/**
*
* @author douglm
*
*/
public class BwCalDAVEvent extends CalDAVEvent<BwCalDAVEvent> {
private BwSysIntfImpl intf;
private EventInfo evi;
private BwEvent ev;
/**
* @param intf
* @param evi
* @throws WebdavException
*/
BwCalDAVEvent(final BwSysIntfImpl intf, final EventInfo evi) throws WebdavException {
this.intf = intf;
this.evi = evi;
if (evi != null) {
ev = evi.getEvent();
}
}
/* ====================================================================
* Abstract method implementations
* ==================================================================== */
@Override
public boolean getCanShare() throws WebdavException {
return false;
}
@Override
public boolean getCanPublish() throws WebdavException {
return false;
}
@Override
public boolean isAlias() throws WebdavException {
return false;
}
@Override
public String getAliasUri() throws WebdavException {
return null;
}
@Override
public BwCalDAVEvent resolveAlias(final boolean resolveSubAlias) throws WebdavException {
return this;
}
@Override
public void setProperty(final QName name, final String val) throws WebdavException {
}
@Override
public String getProperty(final QName name) throws WebdavException {
return null;
}
@Override
public boolean getDeleted() throws WebdavException {
return getEv().getDeleted() || getEv().getTombstoned();
}
/* (non-Javadoc)
* @see org.bedework.caldav.server.CalDAVEvent#getScheduleTag()
*/
@Override
public String getScheduleTag() throws WebdavException {
return getEv().getStag();
}
/* (non-Javadoc)
* @see org.bedework.caldav.server.CalDAVEvent#getPrevScheduleTag()
*/
@Override
public String getPrevScheduleTag() throws WebdavException {
return getEvinfo().getPrevStag();
}
@Override
public boolean getOrganizerSchedulingObject() throws WebdavException {
return getEv().getOrganizerSchedulingObject();
}
@Override
public boolean getAttendeeSchedulingObject() throws WebdavException {
return getEv().getAttendeeSchedulingObject();
}
/* (non-Javadoc)
* @see org.bedework.caldav.server.CalDAVEvent#getSummary()
*/
@Override
public String getSummary() throws WebdavException {
return getEv().getSummary();
}
/* (non-Javadoc)
* @see org.bedework.caldav.server.CalDAVEvent#getNewEvent()
*/
@Override
public boolean isNew() throws WebdavException {
return getEvinfo().getNewEvent();
}
/* (non-Javadoc)
* @see org.bedework.caldav.server.CalDAVEvent#getEntityType()
*/
@Override
public int getEntityType() throws WebdavException {
return getEv().getEntityType();
}
/* (non-Javadoc)
* @see org.bedework.caldav.server.CalDAVEvent#setOrganizer(org.bedework.caldav.server.Organizer)
*/
@Override
public void setOrganizer(final Organizer val) throws WebdavException {
BwOrganizer org = new BwOrganizer();
org.setCn(val.getCn());
org.setDir(val.getDir());
org.setLanguage(val.getLanguage());
org.setSentBy(val.getSentBy());
org.setOrganizerUri(val.getOrganizerUri());
getEv().setOrganizer(org);
}
@Override
public Organizer getOrganizer() throws WebdavException {
BwOrganizer bworg = getEv().getOrganizer();
Organizer org = new Organizer(bworg.getCn(),
bworg.getDir(),
bworg.getLanguage(),
bworg.getSentBy(),
bworg.getOrganizerUri());
return org;
}
@Override
public void setOriginator(final String val) throws WebdavException {
getEv().setOriginator(val);
}
@Override
public void setRecipients(final Set<String> val) throws WebdavException {
if (getEv().getRecipients() == null) {
getEv().setRecipients(val);
} else {
Util.adjustCollection(val, getEv().getRecipients());
}
}
@Override
public Set<String> getRecipients() throws WebdavException {
return getEv().getRecipients();
}
@Override
public void addRecipient(final String val) throws WebdavException {
getEv().addRecipient(val);
}
@Override
public Set<String> getAttendeeUris() throws WebdavException {
Set<String> uris = new TreeSet<>();
for (BwAttendee att: getEv().getAttendees()) {
uris.add(att.getAttendeeUri());
}
return uris;
}
@Override
public void setScheduleMethod(final int val) throws WebdavException {
getEv().setScheduleMethod(val);
}
@Override
public int getScheduleMethod() throws WebdavException {
return getEv().getScheduleMethod();
}
/* (non-Javadoc)
* @see org.bedework.caldav.server.CalDAVEvent#getUid()
*/
@Override
public String getUid() throws WebdavException {
return getEv().getUid();
}
@Override
public boolean generatePropertyValue(final QName tag,
final XmlEmit xml) throws WebdavException {
try {
BwEvent ev = getEv();
/*
if (tag.equals(CaldavTags.scheduleState)) {
xml.openTag(tag);
if (ev.getScheduleState() == BwEvent.scheduleStateNotProcessed) {
xml.emptyTag(CaldavTags.notProcessed);
} else {
xml.emptyTag(CaldavTags.processed);
}
xml.closeTag(tag);
return true;
}
*/
if (tag.equals(CaldavTags.scheduleTag)) {
if (!ev.getOrganizerSchedulingObject() &&
!ev.getAttendeeSchedulingObject()) {
return false;
}
xml.property(tag, ev.getStag());
return true;
}
if (tag.equals(CaldavTags.originator)) {
if (ev.getOriginator() != null) {
xml.openTag(tag);
xml.property(WebdavTags.href, ev.getOriginator());
xml.closeTag(tag);
}
return true;
}
if (tag.equals(CaldavTags.recipient)) {
Collection<String> r = ev.getRecipients();
if ((r == null) || (r.isEmpty())) {
return true;
}
xml.openTag(tag);
for (String recip: r) {
xml.property(WebdavTags.href, recip);
}
xml.closeTag(tag);
return true;
}
if (tag.equals(AppleServerTags.scheduleChanges)) {
List<BwXproperty> xps = ev.getXproperties(BwXproperty.bedeworkChanges);
if (Util.isEmpty(xps)) {
return true;
}
BwXproperty xp = xps.get(0);
String[] vals = xp.getValue().split(";");
xml.openTag(tag);
xml.property(AppleServerTags.dtstamp, vals[0]);
xml.openTag(AppleServerTags.action);
QName actionTag;
if ("CANCEL".equals(vals[1])) {
actionTag = AppleServerTags.cancel;
} else if ("CREATE".equals(vals[1])) {
actionTag = AppleServerTags.create;
} else if ("REPLY".equals(vals[1])) {
actionTag = AppleServerTags.reply;
} else { // "UPDATE"
actionTag = AppleServerTags.update;
}
xml.openTag(actionTag);
int i = 2;
while (i < vals.length) {
/* Next is master or rid */
xml.openTag(AppleServerTags.recurrence);
String val = vals[i];
if ("MASTER".equals(val)) {
xml.emptyTag(AppleServerTags.master);
i++;
}
if (val.startsWith("RID=")) {
xml.openTagNoNewline(AppleServerTags.recurrenceid);
xml.value(val);
xml.closeTag(AppleServerTags.recurrenceid);
i++;
}
if ((i < vals.length) && "CHANGES".equals(vals[i])) {
i++;
xml.openTag(AppleServerTags.changes);
while (i < vals.length) {
val = vals[i];
if ("MASTER".equals(val) ||
"CHANGES".equals(val) ||
val.startsWith("RID=")) {
break;
}
xml.startTag(AppleServerTags.changedProperty);
xml.attribute("name", val);
xml.endEmptyTag();
i++;
}
xml.closeTag(AppleServerTags.changes);
}
xml.closeTag(AppleServerTags.recurrence);
}
xml.closeTag(actionTag);
xml.closeTag(AppleServerTags.action);
xml.closeTag(tag);
return true;
}
/* =============== ICalTags follow ================= */
if (tag.equals(ICalTags.action)) {
// PROPTODO
return true;
}
if (tag.equals(ICalTags.attach)) {
// PROPTODO
return true;
}
if (tag.equals(ICalTags.attendee)) {
// PROPTODO
return true;
}
if (tag.equals(ICalTags.categories)) {
// PROPTODO
return true;
}
if (tag.equals(ICalTags._class)) {
// PROPTODO
return true;
}
if (tag.equals(ICalTags.comment)) {
// PROPTODO
return true;
}
if (tag.equals(ICalTags.completed)) {
// PROPTODO
return true;
}
if (tag.equals(ICalTags.contact)) {
// PROPTODO
return true;
}
if (tag.equals(ICalTags.created)) {
xml.property(tag, ev.getCreated());
return true;
}
if (tag.equals(ICalTags.description)) {
if (ev.getDescription() != null) {
xml.property(tag, ev.getDescription());
}
return true;
}
if (tag.equals(ICalTags.dtend)) {
xml.property(tag, ev.getDtend().getDate());
return true;
}
if (tag.equals(ICalTags.dtstamp)) {
xml.property(tag, ev.getDtstamp());
return true;
}
if (tag.equals(ICalTags.dtstart)) {
xml.property(tag, ev.getDtstart().getDate());
return true;
}
/* TODO
if (tag.equals(ICalTags.due)) {
pv.val = ev.
return pv;
}
*/
if (tag.equals(ICalTags.duration)) {
xml.property(tag, ev.getDuration());
return true;
}
if (tag.equals(ICalTags.exdate)) {
// PROPTODO
return true;
}
if (tag.equals(ICalTags.exrule)) {
// PROPTODO
return true;
}
if (tag.equals(ICalTags.freebusy)) {
// PROPTODO
return true;
}
if (tag.equals(ICalTags.geo)) {
// PROPTODO
return true;
}
/*
if (tag.equals(ICalTags.hasRecurrence)) {
pv.val = ev
return pv;
}
if (tag.equals(ICalTags.hasAlarm)) {
pv.val = ev
return pv;
}
if (tag.equals(ICalTags.hasAttachment)) {
pv.val = ev
return pv;
}*/
if (tag.equals(ICalTags.lastModified)) {
// PROPTODO
return true;
}
if (tag.equals(ICalTags.lastModified)) {
xml.property(tag, ev.getLastmod());
return true;
}
if (tag.equals(ICalTags.location)) {
// PROPTODO
return true;
}
if (tag.equals(ICalTags.organizer)) {
// PROPTODO
return true;
}
if (tag.equals(ICalTags.organizer)) {
if (ev.getOrganizer() != null) {
xml.property(tag, ev.getOrganizer().getOrganizerUri());
}
return true;
}
if (tag.equals(ICalTags.percentComplete)) {
// PROPTODO
return true;
}
if (tag.equals(ICalTags.priority)) {
Integer val = ev.getPriority();
if ((val != null) && (val != 0)) {
xml.property(tag, String.valueOf(val));
}
return true;
}
if (tag.equals(ICalTags.rdate)) {
// PROPTODO
return true;
}
if (tag.equals(ICalTags.recurrenceId)) {
// PROPTODO
return true;
}
if (tag.equals(ICalTags.recurrenceId)) {
if (ev.getRecurrenceId() != null) {
xml.property(tag, ev.getRecurrenceId());
}
return true;
}
if (tag.equals(ICalTags.relatedTo)) {
// PROPTODO
return true;
}
if (tag.equals(ICalTags.repeat)) {
// PROPTODO
return true;
}
if (tag.equals(ICalTags.resources)) {
// PROPTODO
return true;
}
if (tag.equals(ICalTags.requestStatus)) {
// PROPTODO
/*
if (ev.getRequestStatus() != null) {
xml.property(tag, ev.getRequestStatus().strVal());
}
*/
return true;
}
if (tag.equals(ICalTags.rrule)) {
// PROPTODO
return true;
}
if (tag.equals(ICalTags.sequence)) {
xml.property(tag, String.valueOf(ev.getSequence()));
return true;
}
if (tag.equals(ICalTags.status)) {
xml.property(tag, ev.getStatus());
return true;
}
if (tag.equals(ICalTags.summary)) {
xml.property(tag, ev.getSummary());
return true;
}
if (tag.equals(ICalTags.transp)) {
xml.property(tag, ev.getPeruserTransparency(intf.getPrincipal().getPrincipalRef()));
return true;
}
if (tag.equals(ICalTags.trigger)) {
// PROPTODO
return true;
}
if (tag.equals(ICalTags.uid)) {
xml.property(tag, ev.getUid());
return true;
}
if (tag.equals(ICalTags.url)) {
if (ev.getLink() != null) {
xml.property(tag, ev.getLink());
}
return true;
}
if (tag.equals(ICalTags.version)) {
// PROPTODO
return true;
}
return false;
} catch (WebdavException wde) {
throw wde;
} catch (Throwable t) {
throw new WebdavException(t);
}
}
@Override
public String toIcalString(final int methodType,
final String contentType) throws WebdavException {
try {
if (contentType.equals("text/calendar")) {
return IcalTranslator.toIcalString(methodType, getEv());
}
if (contentType.equals("application/calendar+json")) {
return intf.toJcal(this,
methodType != ScheduleMethods.methodTypeNone, null);
}
throw new WebdavException("Unhandled content type" + contentType);
} catch (Throwable t) {
throw new WebdavException(t);
}
}
/* ====================================================================
* Overrides
* ==================================================================== */
@Override
public void setName(final String val) throws WebdavException {
getEv().setName(val);
}
@Override
public String getName() throws WebdavException {
return getEv().getName();
}
@Override
public void setDisplayName(final String val) throws WebdavException {
// No display name
}
@Override
public String getDisplayName() throws WebdavException {
return getEv().getSummary();
}
@Override
public void setPath(final String val) throws WebdavException {
// Not actually saved
}
@Override
public String getPath() throws WebdavException {
return getEv().getColPath() + "/" + getEv().getName();
}
@Override
public void setParentPath(final String val) throws WebdavException {
getEv().setColPath(val);
}
@Override
public String getParentPath() throws WebdavException {
return getEv().getColPath();
}
@Override
public void setOwner(final AccessPrincipal val) throws WebdavException {
getEv().setOwnerHref(val.getPrincipalRef());
}
@Override
public AccessPrincipal getOwner() throws WebdavException {
return intf.getPrincipal(getEv().getOwnerHref());
}
@Override
public void setCreated(final String val) throws WebdavException {
getEv().setCreated(val);
}
@Override
public String getCreated() throws WebdavException {
return getEv().getCreated();
}
@Override
public void setLastmod(final String val) throws WebdavException {
getEv().setLastmod(val);
}
@Override
public String getLastmod() throws WebdavException {
return getEv().getLastmod();
}
@Override
public String getEtag() throws WebdavException {
return "\"" + getEv().getCtoken() + "\"";
// return "\"" + getEv().getLastmod() + "-" +
// "0" + // < Should be a sequence - needs to be in event and saved
// "\"";
}
@Override
public String getPreviousEtag() throws WebdavException {
return "\"" + getEvinfo().getPrevCtoken() + "\"";
}
@Override
public void setDescription(final String val) throws WebdavException {
getEv().setDescription(val);
}
@Override
public String getDescription() throws WebdavException {
return getEv().getDescription();
}
/* ====================================================================
* Object methods
* ==================================================================== */
@Override
public String toString() {
StringBuilder sb = new StringBuilder("BwCalDAVEvent{");
try {
sb.append(getEv().toString());
} catch (Throwable t) {
sb.append(t);
}
sb.append("}");
return sb.toString();
}
/* ====================================================================
* Private methods
* ==================================================================== */
EventInfo getEvinfo() throws WebdavException {
if (evi == null) {
evi = new EventInfo(new BwEventObj());
ev = evi.getEvent();
}
return evi;
}
BwEvent getEv() throws WebdavException {
getEvinfo();
return ev;
}
}