/*
* Copyright 2012 McEvoy Software Ltd.
*
*/
package io.milton.http.caldav;
import io.milton.http.DateUtils;
import io.milton.http.DateUtils.DateParseException;
import io.milton.http.HttpManager;
import io.milton.common.Utils;
import io.milton.http.exceptions.BadRequestException;
import io.milton.http.exceptions.NotAuthorizedException;
import io.milton.http.report.QualifiedReport;
import io.milton.http.webdav.PropFindPropertyBuilder;
import io.milton.http.webdav.PropFindResponse;
import io.milton.http.webdav.PropFindXmlGenerator;
import io.milton.http.webdav.PropertiesRequest;
import io.milton.http.webdav.WebDavProtocol;
import io.milton.resource.CalendarResource;
import io.milton.resource.ICalResource;
import io.milton.http.report.ReportUtils;
import io.milton.resource.Resource;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import javax.xml.namespace.QName;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author brad
*/
public class CalendarQueryReport implements QualifiedReport {
private static final Logger log = LoggerFactory.getLogger(CalendarQueryReport.class);
private final PropFindPropertyBuilder propertyBuilder;
private final PropFindXmlGenerator xmlGenerator;
private final CalendarSearchService calendarSearchService;
private final Namespace NS_DAV = Namespace.getNamespace(WebDavProtocol.NS_DAV.getPrefix(), WebDavProtocol.NS_DAV.getName());
private final Namespace NS_CAL = Namespace.getNamespace("C", CalDavProtocol.CALDAV_NS);
public CalendarQueryReport(PropFindPropertyBuilder propertyBuilder, PropFindXmlGenerator xmlGenerator, CalendarSearchService calendarSearchService) {
this.propertyBuilder = propertyBuilder;
this.xmlGenerator = xmlGenerator;
this.calendarSearchService = calendarSearchService;
}
@Override
public String getName() {
return "calendar-query";
}
@Override
public QName getQualifiedName()
{
return new QName(NS_CAL.getURI(), getName());
}
@Override
public String process(String host, String path, Resource resource, Document doc) throws BadRequestException, NotAuthorizedException {
log.debug("process");
// The requested properties
Set<QName> props = ReportUtils.getProps(doc, NS_DAV);
PropertiesRequest parseResult = PropertiesRequest.toProperties(props);
// Generate the response
List<PropFindResponse> respProps = new ArrayList<PropFindResponse>();
if (resource instanceof CalendarResource) {
CalendarResource calendar = (CalendarResource) resource;
List<ICalResource> foundResources = findCalendarResources(calendar, doc);
if (foundResources != null) {
log.trace("foundResources: " + foundResources.size());
} else {
log.trace("foundResources: null");
}
String parentHref = HttpManager.request().getAbsolutePath();
parentHref = Utils.suffixSlash(parentHref);
for (ICalResource cr : foundResources) {
String href = parentHref + cr.getName();
//List<PropFindResponse> resps = propertyBuilder.buildProperties(calendar, 0, parseResult, href);
List<PropFindResponse> resps = new ArrayList<PropFindResponse>();
propertyBuilder.processResource(resps, cr, parseResult, href, 0, 0, href);
respProps.addAll(resps);
}
} else {
throw new BadRequestException(resource, "Resource is not a " + CalendarResource.class.getCanonicalName() + " is a: " + resource.getClass());
}
String xml = xmlGenerator.generate(respProps);
return xml;
}
private List<ICalResource> findCalendarResources(CalendarResource calendar, Document doc) throws NotAuthorizedException, BadRequestException {
Date start;
Date end;
AbstractMap.SimpleImmutableEntry<String, String> propFilter = null;
Element elFilterRoot = doc.getRootElement().getChild("filter", NS_CAL);
if (elFilterRoot == null) {
start = null;
end = null;
} else {
Element elPropFilter = ReportUtils.findRecursively(elFilterRoot, "prop-filter");
if (elPropFilter != null) {
Element elTextMatch = ReportUtils.find( elPropFilter, "text-match", this.NS_CAL );
String filterAttr = ((Attribute)elPropFilter.getAttributes().get(0) ).getValue();
propFilter = new AbstractMap.SimpleImmutableEntry<String, String>(filterAttr, elTextMatch.getText());
}
Element elTimeRange = ReportUtils.find(elFilterRoot, "time-range", NS_CAL);
if (elTimeRange == null) {
start = null;
end = null;
} else {
String sStart = elTimeRange.getAttributeValue("start");
String sFinish = elTimeRange.getAttributeValue("end");
if (sStart != null && sStart.length() > 0) {
try {
start = DateUtils.parseIcalDateTime(sStart);
} catch (DateParseException ex) {
log.error("Couldnt parse start date in calendar-query: " + sStart);
start = null;
}
} else {
start = null;
}
if (sFinish != null && sFinish.length() > 0) {
try {
end = DateUtils.parseIcalDateTime(sFinish);
} catch (DateParseException ex) {
log.error("Couldnt parse end date in calendar-query: " + sFinish);
end = null;
}
} else {
end = null;
}
}
}
log.info("Search calendar resources. Start=" + start + " End:" + end);
return calendarSearchService.findCalendarResources(calendar, start, end, propFilter);
}
}