use of org.bedework.caldav.util.filter.FilterBase in project bw-calendar-engine by Bedework.
the class SimpleFilterParser method resolveVpath.
/**
* A virtual path is the apparent path for a user looking at an explorer
* view of collections.
*
* <p>We might have,
* <pre>
* home-->Arts-->Theatre
* </pre>
*
* <p>In reality the Arts collection might be an alias to another alias which
* is an alias to a collection containing aliases including "Theatre".
*
* <p>So the real picture might be something like...
* <pre>
* home-->Arts (categories="ChemEng")
* |
* V
* Arts (categories="Approved")
* |
* V
* Arts-->Theatre (categories="Arts" AND categories="Theatre")
* |
* V
* MainCal
* </pre>
* where the vertical links are aliasing. The importance of this is that
* each alias might introduce another filtering term, the intent of which is
* to restrict the retrieval to a specific subset. The parenthesized terms
* represent example filters.
*
* <p>The desired filter is the ANDing of all the above.
*
* @param vpath a String virtual path
* @return FilterBase object or null for bad path
* @throws ParseFailed on error
*/
private FilterBase resolveVpath(final String vpath) throws ParseFailed {
/* We decompose the virtual path into it's elements and then try to
* build a sequence of collections that include the aliases and their
* targets until we reach the last element in the path.
*
* We'll assume the path is already normalized and that no "/" are allowed
* as parts of names.
*
* What we're doing here is resolving aliases to aliases and accumulating
* any filtering that might be in place as a sequence of ANDed terms. For
* example:
*
* /user/eng/Lectures has the filter cat=eng and is aliased to
* /public/aliases/Lectures which has the filter cat=lectures and is aliased to
* /public/cals/MainCal
*
* We want the filter (cat=eng) & (cat=Lectures) on MainCal.
*
* Below, we decompose the virtual path and we save the path to an actual
* folder or calendar collection.
*/
final Collection<BwCalendar> cols = callDecomposeVirtualPath(vpath);
if (cols == null) {
throw parseResult.fail("Bad virtual path: " + vpath);
}
FilterBase vfilter = null;
BwCalendar vpathTarget = null;
for (final BwCalendar col : cols) {
if (debug) {
debug(" vpath collection:" + col.getPath());
}
if (col.getFilterExpr() != null) {
if (subParser == null) {
subParser = callGetParser();
}
final ParseResult pr = subParser.parse(col.getFilterExpr(), false, col.getPath());
if (!pr.ok) {
throw parseResult.fromPr(pr);
}
if (pr.filter != null) {
vfilter = and(null, vfilter, pr.filter);
}
}
if (col.getCollectionInfo().onlyCalEntities || (col.getCalType() == BwCalendar.calTypeFolder)) {
// reached an end point
vpathTarget = col;
}
}
if (vpathTarget == null) {
throw parseResult.fail("Bad vpath - no calendar collection" + " vpath: " + vpath + " source: " + source);
}
final String name;
if (vpathTarget.getAliasOrigin() != null) {
name = vpathTarget.getAliasOrigin().getPath();
} else {
name = vpathTarget.getPath();
}
return and(name, vfilter, resolveColPath(vpathTarget.getPath(), false, false));
}
use of org.bedework.caldav.util.filter.FilterBase in project bw-calendar-engine by Bedework.
the class BwSysIntfImpl method getEvents.
@Override
public Collection<CalDAVEvent> getEvents(final CalDAVCollection col, final FilterBase filter, final List<String> retrieveList, final RetrievalMode recurRetrieval) throws WebdavException {
try {
/* Limit the results to just this collection by adding an ANDed filter */
final SimpleFilterParser sfp = getSvci().getFilterParser();
final String expr = "(colPath='" + SfpTokenizer.escapeQuotes(col.getPath()) + "')";
final ParseResult pr = sfp.parse(expr, true, null);
if (!pr.ok) {
throw new WebdavBadRequest("Failed to reference collection " + col.getPath() + ": message was " + pr.message);
}
final FilterBase f = FilterBase.addAndChild(filter, pr.filter);
final Collection<EventInfo> bwevs = // Collection
getSvci().getEventsHandler().getEvents(// Collection
null, f, // start
null, // end
null, RetrieveList.getRetrieveList(retrieveList), DeletedState.noDeleted, getRrm(recurRetrieval));
if (bwevs == null) {
return null;
}
final Collection<CalDAVEvent> evs = new ArrayList<>();
for (final EventInfo ei : bwevs) {
if (recurRetrieval != null) {
ei.getEvent().setForceUTC(recurRetrieval.getExpand() != null);
}
evs.add(new BwCalDAVEvent(this, ei));
}
return evs;
} catch (final CalFacadeAccessException cfae) {
throw new WebdavForbidden();
} catch (final CalFacadeException cfe) {
if (CalFacadeException.unknownProperty.equals(cfe.getMessage())) {
throw new WebdavBadRequest("Unknown property " + cfe.getExtra());
}
throw new WebdavException(cfe);
} catch (final WebdavException wde) {
throw wde;
} catch (final Throwable t) {
throw new WebdavException(t);
}
}
use of org.bedework.caldav.util.filter.FilterBase in project bw-calendar-engine by Bedework.
the class ESQueryFilter method addLimits.
/**
* This method adds extra limits to the search if they are necessary.
* If the search is already limited to one or more collections or
* specific href(s) then we don't need to add anything.
*
* <p>Otherwise we apply a default search context (if any). If the
* result is still not limited we limit to entities owned by the
* current principal</p>
*
* @param f current filter
* @param defaultFilterContext set if we have one
* @return augmented filter
* @throws CalFacadeException on error
*/
public FilterBuilder addLimits(final FilterBuilder f, final FilterBase defaultFilterContext, final DeletedState delState) throws CalFacadeException {
if (f instanceof MatchNone) {
return f;
}
final List<NamedFilterBuilder> nfbs = new ArrayList<>();
if (!queryLimited) {
if (defaultFilterContext != null) {
if (defaultFilterContext instanceof BwViewFilter) {
/* Treat this specially. Create a named query for each
child filter. The name will be the filter name which
itself is derived from the collection href.
*/
final FilterBase fb = ((BwViewFilter) defaultFilterContext).getFilter();
if ((fb != null) && (fb.getChildren() != null)) {
for (final FilterBase vfb : fb.getChildren()) {
nfbs.add(new NamedFilterBuilder(vfb.getName(), and(buildFilter(vfb), f, vfb.getName())));
}
}
} else {
final FilterBuilder limFb = buildFilter(defaultFilterContext);
nfbs.add(new NamedFilterBuilder(null, and(f, limFb, null)));
}
}
if (!queryLimited) {
nfbs.add(new NamedFilterBuilder(null, principalFilter(f)));
}
} else {
nfbs.add(new NamedFilterBuilder(null, f));
}
FilterBuilder recurFb = recurTerms();
FilterBuilder fb;
if (nfbs.size() == 1) {
fb = nfbs.get(0).fb;
if (recurFb != null) {
fb = and(fb, recurFb, null);
}
} else {
fb = null;
if (recurFb == null) {
recurFb = new MatchAllFilterBuilder();
}
for (final NamedFilterBuilder nfb : nfbs) {
fb = or(fb, and(nfb.fb, recurFb, nfb.name));
}
}
if (delState == includeDeleted) {
return fb;
}
return and(fb, addTerm(PropertyInfoIndex.DELETED, String.valueOf(delState == onlyDeleted)), null);
}
use of org.bedework.caldav.util.filter.FilterBase in project bw-calendar-engine by Bedework.
the class CoreEvents method getEvents.
@Override
public Collection<CoreEventInfo> getEvents(final Collection<BwCalendar> calendars, final FilterBase filter, final BwDateTime startDate, final BwDateTime endDate, final List<BwIcalPropertyInfoEntry> retrieveList, final DeletedState delState, RecurringRetrievalMode recurRetrieval, final boolean freeBusy) throws CalFacadeException {
/* Ensure dates are limited explicitly or implicitly */
recurRetrieval = defaultRecurringRetrieval(recurRetrieval, startDate, endDate);
if (debug) {
trace("getEvents for start=" + startDate + " end=" + endDate);
}
FilterBase fltr = filter;
if (!Util.isEmpty(calendars)) {
FilterBase colfltr = null;
for (final BwCalendar c : calendars) {
colfltr = FilterBase.addOrChild(colfltr, new BwCollectionFilter(null, c));
}
fltr = FilterBase.addAndChild(fltr, colfltr);
}
int desiredAccess = privRead;
if (freeBusy) {
// DORECUR - freebusy events must have enough info for expansion
desiredAccess = privReadFreeBusy;
}
final List<PropertyInfoIndex> properties = new ArrayList<>(2);
properties.add(PropertyInfoIndex.DTSTART);
properties.add(PropertyInfoIndex.UTC);
final List<SortTerm> sort = new ArrayList<>(1);
sort.add(new SortTerm(properties, true));
String start = null;
String end = null;
if (startDate != null) {
start = startDate.getDate();
}
if (endDate != null) {
end = endDate.getDate();
}
final SearchResult sr = // query
getIndexer(null).search(// query
null, false, fltr, sort, // defaultFilterContext
null, start, end, -1, delState, recurRetrieval);
final List<SearchResultEntry> sres = sr.getIndexer().getSearchResult(sr, 0, -1, desiredAccess);
final TreeSet<CoreEventInfo> ceis = new TreeSet<>();
for (final SearchResultEntry sre : sres) {
final Object o = sre.getEntity();
if (!(o instanceof EventInfo)) {
continue;
}
final EventInfo ei = (EventInfo) o;
final BwEvent ev = ei.getEvent();
restoreCategories(ev);
final CoreEventInfo cei = postGetEvent(ev, null, ei.getCurrentAccess());
if (cei == null) {
continue;
}
ceis.add(cei);
}
return buildVavail(ceis);
}
use of org.bedework.caldav.util.filter.FilterBase in project bw-calendar-engine by Bedework.
the class Filters method makeWhere.
/* Generate a where clause for a query which selects the events for the
* given filter.
*
* @param f Filter element.
*/
private void makeWhere(final FilterBase f) throws CalFacadeException {
if ((f instanceof AndFilter) || (f instanceof OrFilter)) {
boolean itsAnd = (f instanceof AndFilter);
qseg.append('(');
boolean first = true;
for (FilterBase flt : f.getChildren()) {
if (!first) {
if (itsAnd) {
qseg.append(" and ");
} else {
qseg.append(" or ");
}
}
makeWhere(flt);
first = false;
}
qseg.append(")");
}
if (f instanceof BwHrefFilter) {
// Special case this
qseg.append('(');
qseg.append(masterName);
qseg.append(".");
qseg.append("colPath");
qseg.append("=:");
parTerm();
qseg.append(" and ");
qseg.append(masterName);
qseg.append(".");
qseg.append("name");
qseg.append("=:");
parTerm();
qseg.append(')');
queryLimited = true;
} else if (f instanceof PropertyFilter) {
PropertyFilter pf = (PropertyFilter) f;
BwIcalPropertyInfoEntry pi = BwIcalPropertyInfo.getPinfo(pf.getPropertyIndex());
if (pi == null) {
throw new CalFacadeException("org.bedework.filters.unknownproperty", String.valueOf(pf.getPropertyIndex()));
}
String fieldName = pi.getDbFieldName();
boolean multi = pi.getMultiValued();
boolean param = pi.getParam();
if (param) {
BwIcalPropertyInfoEntry parentPi = BwIcalPropertyInfo.getPinfo(pf.getParentPropertyIndex());
fieldName = parentPi.getDbFieldName() + "." + fieldName;
}
if (multi) {
if (f instanceof PresenceFilter) {
PresenceFilter prf = (PresenceFilter) f;
// qseg.append("(size(");
qseg.append("((select count(*) from ");
qseg.append(masterName);
qseg.append(".");
qseg.append(fieldName);
if (pi.getPresenceField() != null) {
qseg.append(".");
qseg.append(pi.getPresenceField());
}
qseg.append(")");
if (prf.getTestPresent()) {
qseg.append(">0)");
} else {
qseg.append("=0)");
}
} else if (pf instanceof TimeRangeFilter) {
String fld = "joined_" + pi.getDbFieldName();
String subfld = "unknown";
if (pi.getPindex() == PropertyInfoIndex.VALARM) {
subfld = "triggerTime";
}
doTimeRange((TimeRangeFilter) pf, false, fld, subfld);
} else if (pf instanceof BwCategoryFilter) {
BwCategory cat = ((BwCategoryFilter) pf).getEntity();
if (cat.unsaved()) {
((BwCategoryFilter) pf).setEntity(cb.getCategory(cat.getUid()));
}
qseg.append("(:");
parTerm();
if (f.getNot()) {
qseg.append(" not");
}
qseg.append(" in elements(");
qseg.append(masterName);
qseg.append(".");
qseg.append(fieldName);
qseg.append("))");
} else if (pf instanceof BwObjectFilter) {
// String fld = "joined_" + pi.getField();
String subfld = "value";
// if (pi.getPindex() == PropertyInfoIndex.CATEGORIES) {
// subfld = "word.value";
// }
doObject(((BwObjectFilter) pf).getEntity(), masterName, fieldName, subfld, true);
} else {
qseg.append("(:");
parTerm();
if (f.getNot()) {
qseg.append(" not");
}
qseg.append(" in elements(");
qseg.append(masterName);
qseg.append(".");
qseg.append(fieldName);
qseg.append("))");
}
// not multi follow
} else if (f instanceof PresenceFilter) {
PresenceFilter prf = (PresenceFilter) f;
qseg.append('(');
qseg.append(masterName);
qseg.append(".");
qseg.append(fieldName);
if (prf.getTestPresent()) {
qseg.append(" is not null");
} else {
qseg.append(" is null");
}
qseg.append(")");
} else if (pf instanceof EntityTimeRangeFilter) {
doEntityTimeRange((EntityTimeRangeFilter) pf);
} else if (pf instanceof TimeRangeFilter) {
doTimeRange((TimeRangeFilter) pf, (pi.getFieldType().getName().equals(BwDateTime.class.getName())), masterName, fieldName);
} else if (pf instanceof BwObjectFilter) {
doObject(((BwObjectFilter) pf).getEntity(), masterName, fieldName, null, false);
} else {
/* We assume we can't handle this one as a query.
*/
throw new CalFacadeException("org.bedework.filters.unknownfilter", String.valueOf(f));
}
}
}
Aggregations