use of org.bedework.calfacade.BwEventAnnotation in project bw-calendar-engine by Bedework.
the class BwIndexEsImpl method getSearchResult.
@Override
public List<SearchResultEntry> getSearchResult(final SearchResult sres, final int offset, final int num, final int desiredAccess) throws CalFacadeException {
if (debug) {
debug("offset: " + offset + ", num: " + num);
}
final EsSearchResult res = (EsSearchResult) sres;
res.pageStart = offset;
final SearchRequestBuilder srb = getClient().prepareSearch(searchIndexes);
if (res.curQuery != null) {
srb.setQuery(res.curQuery);
}
srb.setSearchType(SearchType.QUERY_THEN_FETCH).setPostFilter(res.curFilter).setFrom(res.pageStart);
final int size;
if (num < 0) {
size = (int) sres.getFound();
} else {
size = num;
}
// TODO - need a configurable absolute max size for fetches
srb.setSize(size);
final List<SearchResultEntry> entities = new ArrayList<>(size);
if (!Util.isEmpty(res.curSort)) {
SortOrder so;
for (final SortTerm st : res.curSort) {
if (st.isAscending()) {
so = SortOrder.ASC;
} else {
so = SortOrder.DESC;
}
srb.addSort(new FieldSortBuilder(ESQueryFilter.makePropertyRef(st.getProperties())).order(so));
}
}
if (res.requiresSecondaryFetch) {
// Limit to href then fetch those
srb.addField(ESQueryFilter.hrefJname);
}
final SearchResponse resp = srb.execute().actionGet();
if (resp.status() != RestStatus.OK) {
if (debug) {
debug("Search returned status " + resp.status());
}
}
final SearchHits hitsResp = resp.getHits();
if ((hitsResp.getHits() == null) || (hitsResp.getHits().length == 0)) {
return entities;
}
// Break condition: No hits are returned
if (hitsResp.hits().length == 0) {
return entities;
}
final List<SearchHit> hits;
if (res.requiresSecondaryFetch) {
hits = multiFetch(hitsResp, res.recurRetrieval);
if (hits == null) {
return entities;
}
} else {
hits = Arrays.asList(hitsResp.getHits());
}
final Map<String, Collection<BwEventAnnotation>> overrides = new HashMap<>();
final Collection<EventInfo> masters = new TreeSet<>();
EntityBuilder.checkFlushCache(currentChangeToken());
/* If we are retrieving events with a time range query and we are asking for the
* master + overrides then we need to check that the master really has an
* instance in the given time range */
final boolean checkTimeRange = (res.recurRetrieval.mode == Rmode.overrides) && ((res.latestStart != null) || (res.earliestEnd != null));
final Set<String> excluded = new TreeSet<>();
for (final SearchHit hit : hits) {
res.pageStart++;
final String dtype = hit.getType();
if (dtype == null) {
throw new CalFacadeException("org.bedework.index.noitemtype");
}
final String kval = hit.getId();
if (kval == null) {
throw new CalFacadeException("org.bedework.index.noitemkey");
}
final EntityBuilder eb = getEntityBuilder(hit.sourceAsMap());
Object entity = null;
switch(dtype) {
case docTypeCollection:
entity = eb.makeCollection();
break;
case docTypeCategory:
entity = eb.makeCat();
break;
case docTypeContact:
entity = eb.makeContact();
break;
case docTypeLocation:
entity = eb.makeLocation();
break;
case docTypeEvent:
case docTypePoll:
entity = eb.makeEvent(kval, res.recurRetrieval.mode == Rmode.expanded);
final EventInfo ei = (EventInfo) entity;
final BwEvent ev = ei.getEvent();
final Response evrestResp = new Response();
restoreEvProps(evrestResp, ei);
if (evrestResp.getStatus() != ok) {
warn("Failed restore of ev props: " + evrestResp);
}
final Acl.CurrentAccess ca = res.accessCheck.checkAccess(ev, desiredAccess, true);
if ((ca == null) || !ca.getAccessAllowed()) {
continue;
}
ei.setCurrentAccess(ca);
if (ev instanceof BwEventAnnotation) {
if (excluded.contains(ev.getUid())) {
continue;
}
// Treat as override
final Collection<BwEventAnnotation> ov = overrides.computeIfAbsent(ev.getHref(), k -> new TreeSet<>());
ov.add((BwEventAnnotation) ev);
continue;
}
if (checkTimeRange && dtype.equals(docTypeEvent) && ev.getRecurring()) {
if (Util.isEmpty(RecurUtil.getPeriods(ev, 99, 1, res.latestStart, res.earliestEnd).instances)) {
excluded.add(ev.getUid());
continue;
}
}
masters.add(ei);
break;
}
entities.add(new SearchResultEntry(entity, dtype, hit.getScore()));
}
for (final EventInfo ei : masters) {
final BwEvent ev = ei.getEvent();
if (ev.getRecurring()) {
final Collection<BwEventAnnotation> ov = overrides.get(ev.getHref());
if (ov != null) {
for (final BwEventAnnotation ann : ov) {
final BwEvent proxy = new BwEventProxy(ann);
ann.setTarget(ev);
ann.setMaster(ev);
final EventInfo oei = new EventInfo(proxy);
ei.addOverride(oei);
}
}
}
}
return entities;
}
use of org.bedework.calfacade.BwEventAnnotation in project bw-calendar-engine by Bedework.
the class BwIndexEsImpl method getIndexStats.
@Override
public IndexStatsResponse getIndexStats(final String indexName) {
final IndexStatsResponse resp = new IndexStatsResponse(indexName);
if (indexName == null) {
return errorReturn(resp, "indexName must be provided");
}
final QueryBuilder qb = new FilteredQueryBuilder(null, FilterBuilders.matchAllFilter());
// 1 minute
final int timeoutMillis = 60000;
final TimeValue tv = new TimeValue(timeoutMillis);
final int batchSize = 100;
final Client cl = getClient(resp);
if (cl == null) {
return resp;
}
SearchResponse scrollResp = cl.prepareSearch(indexName).setSearchType(SearchType.SCAN).setScroll(tv).setQuery(qb).setSize(batchSize).execute().actionGet();
// Scroll until no hits are returned
while (true) {
for (final SearchHit hit : scrollResp.getHits().getHits()) {
resp.incProcessed();
final String dtype = hit.getType();
if (dtype.equals(docTypeEvent)) {
final EventInfo entity = (EventInfo) makeEntity(resp, hit, null);
if (entity == null) {
errorReturn(resp, "Unable to make doc for " + hit.sourceAsString());
continue;
}
final BwEvent ev = entity.getEvent();
if (ev instanceof BwEventAnnotation) {
final BwEventAnnotation ann = (BwEventAnnotation) ev;
if (ann.testOverride()) {
resp.incOverrides();
}
}
if (ev.getRecurring()) {
resp.incRecurring();
}
if (ev.getRecurrenceId() == null) {
resp.incMasters();
} else {
resp.incInstances();
}
} else {
resp.getStats().inc(docToType.getOrDefault(dtype, unreachableEntities));
}
}
scrollResp = cl.prepareSearchScroll(scrollResp.getScrollId()).setScroll(tv).execute().actionGet();
// Break condition: No hits are returned
if (scrollResp.getHits().getHits().length == 0) {
break;
}
}
return resp;
}
use of org.bedework.calfacade.BwEventAnnotation in project bw-calendar-engine by Bedework.
the class CoreEvents method doRecurrence.
/* Retrieves the overides for a recurring event and if required,
* retrieves the instances.
*
* The overrides we retrieve are optionally limited by date.
*
* The CalDAV spec requires that we retrieve all overrides which fall within
* the given date range AND all instances in that date range including
* overriden instances that WOULD have fallen in that range had they not been
* overriden.
*
* Thus we need to search both overrides and instances - unless no date range
* is given in which case all overrides will appear along with the instances.
*
* If the calendars parameter is non-null, as it usually will be for a call
* from getEvents, we limit the result to instances that appear within that
* set of calendars. This handles the case of an overriden instance moved to a
* different calendar, for example the trash.
*/
@SuppressWarnings("unchecked")
private void doRecurrence(final CoreEventInfo cei, final RecurringRetrievalMode recurRetrieval) throws CalFacadeException {
final BwEvent master = cei.getEvent();
final Set<String> overrides = new HashSet<>();
final CurrentAccess ca = cei.getCurrentAccess();
// Always fetch all overrides
final Collection<BwEventAnnotation> ovs = dao.eventQuery(BwEventAnnotation.class, null, null, null, master, // overrides
true, // recurRetrieval);
null);
if (ovs != null) {
for (final BwEventAnnotation override : ovs) {
final CoreEventInfo ocei = makeOverrideProxy(override, ca);
cei.addOverride(ocei);
overrides.add(ocei.getEvent().getRecurrenceId());
}
}
if ((recurRetrieval == null) || (recurRetrieval.mode != Rmode.expanded)) {
return;
}
/* Create a list of all instance date/times before overrides. */
final int maxYears;
final int maxInstances;
maxYears = getAuthprops().getMaxYears();
maxInstances = getAuthprops().getMaxInstances();
final RecurPeriods rp = RecurUtil.getPeriods(master, maxYears, maxInstances);
if (rp.instances.isEmpty()) {
// No instances for an alleged recurring event.
return;
// throw new CalFacadeException(CalFacadeException.noRecurrenceInstances);
}
final String stzid = master.getDtstart().getTzid();
final boolean dateOnly = master.getDtstart().getDateType();
/* Emit all instances that aren't overridden. */
final TreeSet<CoreEventInfo> ceis = new TreeSet<>();
for (final Period p : rp.instances) {
String dtval = p.getStart().toString();
if (dateOnly) {
dtval = dtval.substring(0, 8);
}
final BwDateTime rstart = BwDateTime.makeBwDateTime(dateOnly, dtval, stzid);
if (overrides.contains(rstart.getDate())) {
// Overrides built separately - skip this instance.
continue;
}
final String recurrenceId = rstart.getDate();
dtval = p.getEnd().toString();
if (dateOnly) {
dtval = dtval.substring(0, 8);
}
final BwDateTime rend = BwDateTime.makeBwDateTime(dateOnly, dtval, stzid);
final BwRecurrenceInstance inst = new BwRecurrenceInstance(rstart, rend, recurrenceId, master, null);
final CoreEventInfo instcei = makeInstanceProxy(inst, ca);
if (instcei != null) {
// if (debug) {
// debugMsg("Ev: " + proxy);
// }
ceis.add(instcei);
}
}
cei.setInstances(ceis);
}
use of org.bedework.calfacade.BwEventAnnotation in project bw-calendar-engine by Bedework.
the class CoreEvents method makeInstanceProxy.
/**
* The master has been checked for access and we now build and
* return an event proxy for an instance which has no override.
*
* @param inst the instance
* @param ca Checked access from master
* @return CoreEventInfo
* @throws CalFacadeException on error
*/
private CoreEventInfo makeInstanceProxy(final BwRecurrenceInstance inst, final CurrentAccess ca) throws CalFacadeException {
final BwEvent mstr = inst.getMaster();
/*
if (recurRetrieval.mode == Rmode.masterOnly) {
// Master only and we've just seen it for the first time
// Note we will not do this for freebusy. We need all recurrences.
/* XXX I think this was wrong. Why make an override?
* /
// make a fake one pointing at the owners override
override = new BwEventAnnotation();
override.setTarget(mstr);
override.setMaster(mstr);
BwDateTime start = mstr.getDtstart();
BwDateTime end = mstr.getDtend();
override.setDtstart(start);
override.setDtend(end);
override.setDuration(BwDateTime.makeDuration(start, end).toString());
override.setCreatorHref(mstr.getCreatorHref());
override.setOwnerHref(getUser().getPrincipalRef());
return new CoreEventInfo(new BwEventProxy(override), ca);
}
*/
/* success so now we build a proxy with the event and any override.
*/
final BwEventAnnotation override = new BwEventAnnotation();
override.setTarget(mstr);
override.setMaster(mstr);
final BwDateTime start = inst.getDtstart();
final BwDateTime end = inst.getDtend();
override.setRecurrenceId(inst.getRecurrenceId());
override.setDtstart(start);
override.setDtend(end);
override.setDuration(BwDateTime.makeDuration(start, end).toString());
override.setCreatorHref(mstr.getCreatorHref());
override.setOwnerHref(mstr.getOwnerHref());
override.setOverride(true);
override.setName(mstr.getName());
override.setUid(mstr.getUid());
/* At this point we have an event with possible overrides. If this is free
* busy we need to replace it all with a skeleton event holding only date/time
* information.
*
* We can't do this before I think because we need to allow the user to
* override the transparency on a particular instance,
*/
final BwEvent proxy = new BwEventProxy(override);
return new CoreEventInfo(proxy, ca);
}
use of org.bedework.calfacade.BwEventAnnotation in project bw-calendar-engine by Bedework.
the class CoreEvents method addOverride.
/* XXX This needs more work, OK until we allow modification of annotations - which
* could happen anyway through caldav or by synch.
*
* If the master changes then either we change the referencing annotations or
* we let the user know it's changed. At the moment we have no notification
* mechanism.
* /
private void updateRefs(BwEvent val) throws CalFacadeException {
HibSession sess = getSess();
Iterator it = getAnnotations(val).iterator();
while (it.hasNext()) {
BwEventAnnotation ann = (BwEventAnnotation)it.next();
boolean changed = false;
if (!val.getDtstart().equals(ann.getDtstart())) {
ann.setDtstart(val.getDtstart());
changed = true;
}
if (!val.getDtend().equals(ann.getDtend())) {
ann.setDtend(val.getDtend());
changed = true;
}
if (!val.getDuration().equals(ann.getDuration())) {
ann.setDuration(val.getDuration());
changed = true;
}
if (val.getEndType() != ann.getEndType()) {
ann.setEndType(val.getEndType());
changed = true;
}
if (changed) {
sess.update(ann);
}
}
}
*/
/* Called when adding an event with overrides
*/
private void addOverride(final BwEventProxy proxy, final BwRecurrenceInstance inst) throws CalFacadeException {
final BwEventAnnotation override = proxy.getRef();
if (override.getOwnerHref() == null) {
override.setOwnerHref(inst.getMaster().getOwnerHref());
}
override.setMaster(inst.getMaster());
override.setTarget(inst.getMaster());
override.setOverride(true);
override.setTombstoned(false);
dao.saveOrUpdate(override);
inst.setOverride(override);
}
Aggregations