Search in sources :

Example 61 with EventInfo

use of org.bedework.calfacade.svc.EventInfo in project bw-calendar-engine by Bedework.

the class BwSysIntfImpl method fromIcal.

@Override
public SysiIcalendar fromIcal(final CalDAVCollection col, final IcalendarType ical, final IcalResultType rtype) throws WebdavException {
    // Ensure open
    getSvci();
    boolean rollback = true;
    try {
        BwCalendar bwcol = null;
        if (col != null) {
            bwcol = unwrap(col.resolveAlias(true));
        }
        Icalendar ic = trans.fromIcal(bwcol, ical, // diff the contents
        true);
        if (rtype == IcalResultType.OneComponent) {
            if (ic.getComponents().size() != 1) {
                throw new WebdavBadRequest(CaldavTags.validCalendarObjectResource);
            }
            if (!(ic.getComponents().iterator().next() instanceof EventInfo)) {
                throw new WebdavBadRequest(CaldavTags.validCalendarObjectResource);
            }
        } else if (rtype == IcalResultType.TimeZone) {
            if (ic.getTimeZones().size() != 1) {
                throw new WebdavBadRequest("Expected one timezone");
            }
        }
        SysiIcalendar sic = new MySysiIcalendar(this, ic);
        rollback = false;
        return sic;
    } catch (WebdavException wde) {
        throw wde;
    } catch (IcalMalformedException ime) {
        throw new WebdavForbidden(CaldavTags.validCalendarData, ime.getMessage());
    } catch (Throwable t) {
        if (debug) {
            error(t);
        }
        // Assume bad data in some way
        throw new WebdavForbidden(CaldavTags.validCalendarObjectResource, t.getMessage());
    } finally {
        if (rollback) {
            try {
                getSvci().rollbackTransaction();
            } catch (Throwable t) {
            }
        }
    }
}
Also used : WebdavBadRequest(org.bedework.webdav.servlet.shared.WebdavBadRequest) EventInfo(org.bedework.calfacade.svc.EventInfo) Icalendar(org.bedework.icalendar.Icalendar) SysiIcalendar(org.bedework.caldav.server.SysiIcalendar) WebdavForbidden(org.bedework.webdav.servlet.shared.WebdavForbidden) WebdavException(org.bedework.webdav.servlet.shared.WebdavException) BwCalendar(org.bedework.calfacade.BwCalendar) SysiIcalendar(org.bedework.caldav.server.SysiIcalendar) IcalMalformedException(org.bedework.icalendar.IcalMalformedException)

Example 62 with EventInfo

use of org.bedework.calfacade.svc.EventInfo in project bw-calendar-engine by Bedework.

the class BwIndexEsImpl method reindex.

private void reindex(final ReindexResponse resp, final String indexName, final String docType) {
    // Only retrieve masters - we'll query for the overrides
    final QueryBuilder qb = getFilters(RecurringRetrievalMode.entityOnly).getAllForReindex(docType);
    // 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;
    }
    checkUidsMap();
    // Start with default index as source
    targetIndex = Util.buildPath(false, idxpars.getUserIndexName());
    final BulkProcessor bulkProcessor = BulkProcessor.builder(cl, new BulkListener()).setBulkActions(batchSize).setConcurrentRequests(3).setFlushInterval(tv).build();
    SearchResponse scrollResp = cl.prepareSearch(targetIndex).setSearchType(SearchType.SCAN).setScroll(tv).setQuery(qb).setSize(batchSize).execute().actionGet();
    // Switch to new index
    targetIndex = indexName;
    // Scroll until no hits are returned
    while (true) {
        for (final SearchHit hit : scrollResp.getHits().getHits()) {
            final String dtype = hit.getType();
            resp.incProcessed();
            if ((resp.getProcessed() % 250) == 0) {
                info("processed " + docType + ": " + resp.getProcessed());
            }
            if (dtype.equals(docTypeUpdateTracker)) {
                continue;
            }
            resp.getStats().inc(docToType.getOrDefault(dtype, unreachableEntities));
            final ReindexResponse.Failure hitResp = new ReindexResponse.Failure();
            final Object entity = makeEntity(hitResp, hit, null);
            if (entity == null) {
                warn("Unable to build entity " + hit.sourceAsString());
                resp.incTotalFailed();
                if (resp.getTotalFailed() < 50) {
                    resp.addFailure(hitResp);
                }
                continue;
            }
            if (entity instanceof BwShareableDbentity) {
                final BwShareableDbentity ent = (BwShareableDbentity) entity;
                try {
                    principal = BwPrincipal.makePrincipal(ent.getOwnerHref());
                } catch (final CalFacadeException cfe) {
                    errorReturn(resp, cfe);
                    return;
                }
            }
            if (entity instanceof EventInfo) {
                // This might be a single event or a recurring event.
                final EventInfo ei = (EventInfo) entity;
                final BwEvent ev = ei.getEvent();
                if (ev.getRecurring()) {
                    resp.incRecurring();
                }
                if (!reindexEvent(hitResp, indexName, hit, ei, bulkProcessor)) {
                    warn("Unable to iondex event " + hit.sourceAsString());
                    resp.incTotalFailed();
                    if (resp.getTotalFailed() < 50) {
                        resp.addFailure(hitResp);
                    }
                }
            } else {
                final EsDocInfo doc = makeDoc(resp, entity);
                if (doc == null) {
                    if (resp.getStatus() != ok) {
                        resp.addFailure(hitResp);
                    }
                    continue;
                }
                final IndexRequest request = new IndexRequest(indexName, hit.type(), doc.getId());
                request.source(doc.getSource());
                bulkProcessor.add(request);
                if (entity instanceof BwEventProperty) {
                    if (!cacheEvprop(hitResp, (BwEventProperty) entity)) {
                        resp.addFailure(hitResp);
                    }
                }
            }
        }
        scrollResp = cl.prepareSearchScroll(scrollResp.getScrollId()).setScroll(tv).execute().actionGet();
        // Break condition: No hits are returned
        if (scrollResp.getHits().getHits().length == 0) {
            break;
        }
    }
    try {
        bulkProcessor.awaitClose(10, TimeUnit.MINUTES);
    } catch (final InterruptedException e) {
        errorReturn(resp, "Final bulk close was interrupted. Records may be missing", failed);
    }
    if (uidsSet > 0) {
        info("Uids set: " + uidsSet);
        info("uidOverridesSet: " + uidOverridesSet);
    }
    uidsMap = null;
    uidsOverideMap = null;
}
Also used : SearchHit(org.elasticsearch.search.SearchHit) EventInfo(org.bedework.calfacade.svc.EventInfo) BwEvent(org.bedework.calfacade.BwEvent) BwEventProperty(org.bedework.calfacade.BwEventProperty) TermsQueryBuilder(org.elasticsearch.index.query.TermsQueryBuilder) MatchQueryBuilder(org.elasticsearch.index.query.MatchQueryBuilder) QueryBuilder(org.elasticsearch.index.query.QueryBuilder) FilteredQueryBuilder(org.elasticsearch.index.query.FilteredQueryBuilder) IndexRequest(org.elasticsearch.action.index.IndexRequest) CreateIndexRequest(org.elasticsearch.action.admin.indices.create.CreateIndexRequest) CalFacadeException(org.bedework.calfacade.exc.CalFacadeException) SearchResponse(org.elasticsearch.action.search.SearchResponse) ReindexResponse(org.bedework.calfacade.indexing.ReindexResponse) BwShareableDbentity(org.bedework.calfacade.base.BwShareableDbentity) BulkProcessor(org.elasticsearch.action.bulk.BulkProcessor) EsDocInfo(org.bedework.util.elasticsearch.EsDocInfo) 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)

Example 63 with EventInfo

use of org.bedework.calfacade.svc.EventInfo in project bw-calendar-engine by Bedework.

the class BwIndexEsImpl method indexEvent.

private IndexResponse indexEvent(final EventInfo ei) throws CalFacadeException {
    try {
        /* If it's not recurring or a stand-alone instance index it */
        final BwEvent ev = ei.getEvent();
        if (!ev.testRecurring() && (ev.getRecurrenceId() == null)) {
            return indexEvent(ei, ItemKind.master, ev.getDtstart(), ev.getDtend(), // ev.getRecurrenceId(),
            null, null);
        }
        if (ev.getRecurrenceId() != null) {
            error("Not implemented - index of single override");
            return null;
        }
        /* Delete all instances of this event: we'll do a delete by query
       * We need to find all with the same path and uid.
       */
        /* TODO - do a query for all recurrence ids and delete the ones
          we don't want.
       */
        deleteEvent(ei);
        /* Create a list of all instance date/times before overrides. */
        final int maxYears;
        final int maxInstances;
        final DateLimits dl = new DateLimits();
        if (ev.getPublick()) {
            maxYears = unauthpars.getMaxYears();
            maxInstances = unauthpars.getMaxInstances();
        } else {
            maxYears = authpars.getMaxYears();
            maxInstances = authpars.getMaxInstances();
        }
        final RecurPeriods rp = RecurUtil.getPeriods(ev, maxYears, maxInstances);
        if (rp.instances.isEmpty()) {
            // No instances for an alleged recurring event.
            return null;
        // throw new CalFacadeException(CalFacadeException.noRecurrenceInstances);
        }
        final String stzid = ev.getDtstart().getTzid();
        int instanceCt = maxInstances;
        final boolean dateOnly = ev.getDtstart().getDateType();
        /* First build a table of overrides so we can skip these later
       */
        final Map<String, String> overrides = new HashMap<>();
        /*
      if (!Util.isEmpty(ei.getOverrideProxies())) {
        for (BwEvent ov: ei.getOverrideProxies()) {
          overrides.put(ov.getRecurrenceId(), ov.getRecurrenceId());
        }
      }
      */
        final IndexResponse iresp;
        if (!Util.isEmpty(ei.getOverrides())) {
            for (final EventInfo oei : ei.getOverrides()) {
                final BwEvent ov = oei.getEvent();
                overrides.put(ov.getRecurrenceId(), ov.getRecurrenceId());
                final String start;
                if (ov.getDtstart().getDateType()) {
                    start = ov.getRecurrenceId().substring(0, 8);
                } else {
                    start = ov.getRecurrenceId();
                }
                final BwDateTime rstart = BwDateTime.makeBwDateTime(ov.getDtstart().getDateType(), start, stzid);
                final BwDateTime rend = rstart.addDuration(BwDuration.makeDuration(ov.getDuration()));
                /*iresp = */
                indexEvent(oei, ItemKind.override, rstart, rend, ov.getRecurrenceId(), dl);
                instanceCt--;
            }
        }
        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.get(rstart.getDate()) != null) {
                // Overrides indexed 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);
            /*iresp = */
            indexEvent(ei, entity, rstart, rend, recurrenceId, dl);
            instanceCt--;
            if (instanceCt == 0) {
                // That's all you're getting from me
                break;
            }
        }
        // </editor-fold>
        // <editor-fold desc="Emit the master event with a date range covering the entire period.">
        final BwDateTime start = BwDateTime.makeBwDateTime(dateOnly, dl.minStart, stzid);
        final BwDateTime end = BwDateTime.makeBwDateTime(dateOnly, dl.maxEnd, stzid);
        iresp = indexEvent(ei, ItemKind.master, start, end, null, null);
        return iresp;
    } catch (final CalFacadeException cfe) {
        throw cfe;
    } catch (final Throwable t) {
        throw new CalFacadeException(t);
    }
}
Also used : EventInfo(org.bedework.calfacade.svc.EventInfo) BwDateTime(org.bedework.calfacade.BwDateTime) HashMap(java.util.HashMap) Period(net.fortuna.ical4j.model.Period) BwEvent(org.bedework.calfacade.BwEvent) CalFacadeException(org.bedework.calfacade.exc.CalFacadeException) CreateIndexResponse(org.elasticsearch.action.admin.indices.create.CreateIndexResponse) DeleteIndexResponse(org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse) IndexResponse(org.elasticsearch.action.index.IndexResponse) RecurPeriods(org.bedework.icalendar.RecurUtil.RecurPeriods)

Example 64 with EventInfo

use of org.bedework.calfacade.svc.EventInfo 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 65 with EventInfo

use of org.bedework.calfacade.svc.EventInfo in project bw-calendar-engine by Bedework.

the class BwIndexEsImpl method fetchEvent.

@Override
public GetEntityResponse<EventInfo> fetchEvent(final String href) throws CalFacadeException {
    final GetEntityResponse<EventInfo> resp = new GetEntityResponse<>();
    final String recurrenceId;
    final String hrefNorid;
    // Check validity
    final int pos = href.lastIndexOf("/");
    if (pos < 0) {
        throw new RuntimeException("Bad href: " + href);
    }
    final int fragPos = href.lastIndexOf("#");
    if (fragPos < pos) {
        hrefNorid = href;
        recurrenceId = null;
    } else {
        hrefNorid = href.substring(0, fragPos);
        recurrenceId = href.substring(fragPos + 1);
    }
    final FilterBuilder fltr = getFilters(null).singleEventFilter(href, recurrenceId);
    final SearchHit hit = fetchEntity(docTypeEvent, fltr);
    if (hit == null) {
        return notFound(resp);
    }
    final EntityBuilder eb = getEntityBuilder(hit.sourceAsMap());
    final EventInfo ei = eb.makeEvent(hit.getId(), false);
    if (ei == null) {
        return notFound(resp);
    }
    final BwEvent ev = ei.getEvent();
    final Acl.CurrentAccess ca = accessCheck.checkAccess(ev, privRead, true);
    if ((ca == null) || !ca.getAccessAllowed()) {
        return notFound(resp);
    }
    ei.setCurrentAccess(ca);
    if (ev.getRecurrenceId() != null) {
        // Single instance
        resp.setEntity(ei);
        return resp;
    }
    addOverrides(resp, idxpars.getUserIndexName(), ei);
    return resp;
}
Also used : EventInfo(org.bedework.calfacade.svc.EventInfo) SearchHit(org.elasticsearch.search.SearchHit) TermFilterBuilder(org.elasticsearch.index.query.TermFilterBuilder) FilterBuilder(org.elasticsearch.index.query.FilterBuilder) BwEvent(org.bedework.calfacade.BwEvent) Acl(org.bedework.access.Acl) GetEntityResponse(org.bedework.calfacade.responses.GetEntityResponse)

Aggregations

EventInfo (org.bedework.calfacade.svc.EventInfo)111 BwEvent (org.bedework.calfacade.BwEvent)80 CalFacadeException (org.bedework.calfacade.exc.CalFacadeException)37 BwCalendar (org.bedework.calfacade.BwCalendar)27 BwEventProxy (org.bedework.calfacade.BwEventProxy)24 BwAttendee (org.bedework.calfacade.BwAttendee)19 ArrayList (java.util.ArrayList)16 CoreEventInfo (org.bedework.calcorei.CoreEventInfo)15 BwEventAnnotation (org.bedework.calfacade.BwEventAnnotation)15 BwString (org.bedework.calfacade.BwString)11 BwDateTime (org.bedework.calfacade.BwDateTime)10 BwEventObj (org.bedework.calfacade.BwEventObj)10 TreeSet (java.util.TreeSet)9 BwXproperty (org.bedework.calfacade.BwXproperty)9 BwPrincipal (org.bedework.calfacade.BwPrincipal)7 CalFacadeAccessException (org.bedework.calfacade.exc.CalFacadeAccessException)7 WebdavException (org.bedework.webdav.servlet.shared.WebdavException)7 Calendar (net.fortuna.ical4j.model.Calendar)6 Period (net.fortuna.ical4j.model.Period)6 BwOrganizer (org.bedework.calfacade.BwOrganizer)6