Search in sources :

Example 16 with BwEventAnnotation

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;
}
Also used : SearchHit(org.elasticsearch.search.SearchHit) EventInfo(org.bedework.calfacade.svc.EventInfo) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) BwEvent(org.bedework.calfacade.BwEvent) BwEventProxy(org.bedework.calfacade.BwEventProxy) TreeSet(java.util.TreeSet) SearchHits(org.elasticsearch.search.SearchHits) SortTerm(org.bedework.calfacade.filter.SortTerm) SearchRequestBuilder(org.elasticsearch.action.search.SearchRequestBuilder) SortOrder(org.elasticsearch.search.sort.SortOrder) FieldSortBuilder(org.elasticsearch.search.sort.FieldSortBuilder) Acl(org.bedework.access.Acl) CalFacadeException(org.bedework.calfacade.exc.CalFacadeException) SearchResponse(org.elasticsearch.action.search.SearchResponse) GetAliasesResponse(org.elasticsearch.action.admin.indices.alias.get.GetAliasesResponse) UpdateResponse(org.elasticsearch.action.update.UpdateResponse) BulkResponse(org.elasticsearch.action.bulk.BulkResponse) CreateIndexResponse(org.elasticsearch.action.admin.indices.create.CreateIndexResponse) Response(org.bedework.calfacade.responses.Response) IndicesAliasesResponse(org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse) GetEntityResponse(org.bedework.calfacade.responses.GetEntityResponse) IndicesStatusResponse(org.elasticsearch.action.admin.indices.status.IndicesStatusResponse) DeleteByQueryResponse(org.elasticsearch.action.deletebyquery.DeleteByQueryResponse) DeleteIndexResponse(org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse) IndexDeleteByQueryResponse(org.elasticsearch.action.deletebyquery.IndexDeleteByQueryResponse) ReindexResponse(org.bedework.calfacade.indexing.ReindexResponse) GetResponse(org.elasticsearch.action.get.GetResponse) SearchResponse(org.elasticsearch.action.search.SearchResponse) IndexStatsResponse(org.bedework.calfacade.indexing.IndexStatsResponse) IndexResponse(org.elasticsearch.action.index.IndexResponse) ClusterHealthResponse(org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse) BwEventAnnotation(org.bedework.calfacade.BwEventAnnotation) Collection(java.util.Collection) SearchResultEntry(org.bedework.calfacade.indexing.SearchResultEntry)

Example 17 with BwEventAnnotation

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;
}
Also used : SearchHit(org.elasticsearch.search.SearchHit) EventInfo(org.bedework.calfacade.svc.EventInfo) BwEventAnnotation(org.bedework.calfacade.BwEventAnnotation) FilteredQueryBuilder(org.elasticsearch.index.query.FilteredQueryBuilder) BwEvent(org.bedework.calfacade.BwEvent) TermsQueryBuilder(org.elasticsearch.index.query.TermsQueryBuilder) MatchQueryBuilder(org.elasticsearch.index.query.MatchQueryBuilder) QueryBuilder(org.elasticsearch.index.query.QueryBuilder) FilteredQueryBuilder(org.elasticsearch.index.query.FilteredQueryBuilder) TransportClient(org.elasticsearch.client.transport.TransportClient) Client(org.elasticsearch.client.Client) ClusterAdminClient(org.elasticsearch.client.ClusterAdminClient) IndicesAdminClient(org.elasticsearch.client.IndicesAdminClient) TimeValue(org.elasticsearch.common.unit.TimeValue) IndexStatsResponse(org.bedework.calfacade.indexing.IndexStatsResponse) SearchResponse(org.elasticsearch.action.search.SearchResponse)

Example 18 with BwEventAnnotation

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);
}
Also used : BwDateTime(org.bedework.calfacade.BwDateTime) CoreEventInfo(org.bedework.calcorei.CoreEventInfo) Period(net.fortuna.ical4j.model.Period) BwEvent(org.bedework.calfacade.BwEvent) BwRecurrenceInstance(org.bedework.calfacade.BwRecurrenceInstance) BwEventAnnotation(org.bedework.calfacade.BwEventAnnotation) TreeSet(java.util.TreeSet) CurrentAccess(org.bedework.access.Acl.CurrentAccess) RecurPeriods(org.bedework.icalendar.RecurUtil.RecurPeriods) HashSet(java.util.HashSet)

Example 19 with BwEventAnnotation

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);
}
Also used : BwDateTime(org.bedework.calfacade.BwDateTime) BwEventAnnotation(org.bedework.calfacade.BwEventAnnotation) CoreEventInfo(org.bedework.calcorei.CoreEventInfo) BwEvent(org.bedework.calfacade.BwEvent) BwEventProxy(org.bedework.calfacade.BwEventProxy)

Example 20 with BwEventAnnotation

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);
}
Also used : BwEventAnnotation(org.bedework.calfacade.BwEventAnnotation)

Aggregations

BwEventAnnotation (org.bedework.calfacade.BwEventAnnotation)27 BwEvent (org.bedework.calfacade.BwEvent)22 BwEventProxy (org.bedework.calfacade.BwEventProxy)19 EventInfo (org.bedework.calfacade.svc.EventInfo)15 CoreEventInfo (org.bedework.calcorei.CoreEventInfo)10 BwDateTime (org.bedework.calfacade.BwDateTime)8 CalFacadeException (org.bedework.calfacade.exc.CalFacadeException)7 BwRecurrenceInstance (org.bedework.calfacade.BwRecurrenceInstance)6 BwCalendar (org.bedework.calfacade.BwCalendar)5 Dur (net.fortuna.ical4j.model.Dur)4 ArrayList (java.util.ArrayList)3 TreeSet (java.util.TreeSet)3 DateTime (net.fortuna.ical4j.model.DateTime)3 SearchResponse (org.elasticsearch.action.search.SearchResponse)3 SearchHit (org.elasticsearch.search.SearchHit)3 Period (net.fortuna.ical4j.model.Period)2 TimeZone (net.fortuna.ical4j.model.TimeZone)2 DtStart (net.fortuna.ical4j.model.property.DtStart)2 CurrentAccess (org.bedework.access.Acl.CurrentAccess)2 HibSession (org.bedework.calcorei.HibSession)2