Interface AgendaAvailabilityService


public interface AgendaAvailabilityService
Free/busy over the platform's own calendars, under the platform's own calendar ACL.

Every method takes the asking user's identity, and every method enforces it. Availability is calendar content: knowing when someone is busy is knowing that they have a meeting, and over a long enough window it maps their working life. The rule applied here is not a new one — it is Utils.canAccessCalendar, the same check AgendaEventService.getEvents(org.exoplatform.agenda.model.EventFilter, java.time.ZoneId, long) applies to a calendar owner. For a personal calendar that check resolves to "its owner, and no one else", so in practice a user may currently ask about their own availability only.

That is deliberately the narrow reading. Whether, and to whom, a user should be able to expose their free/busy is a product decision that has not been taken; until it is, this service enforces the guard that already exists rather than inventing a sharing policy of its own. When such a policy arrives it belongs here, in this one place, so that every surface built on this service — REST, MCP, the UI — moves together and none of them can drift.

  • Method Details

    • getAvailability

      List<UserAvailability> getAvailability(List<Long> targetIdentityIds, ZonedDateTime start, ZonedDateTime end, long userIdentityId) throws IllegalAccessException
      Computes the busy and free blocks of each given user over a window.
      Parameters:
      targetIdentityIds - technical identifiers of the users whose availability is asked for
      start - window start, inclusive
      end - window end, exclusive
      userIdentityId - technical identifier of the user asking
      Returns:
      one UserAvailability per requested user, in the order asked
      Throws:
      IllegalAccessException - when the asking user is not allowed to read the availability of any one of the requested users
      IllegalArgumentException - when the window or the user list is missing or empty, or when the window ends before it starts
    • suggestMeetingTime

      List<TimeBlock> suggestMeetingTime(List<Long> attendeeIdentityIds, Duration duration, ZonedDateTime windowStart, ZonedDateTime windowEnd, boolean morningsOnly, boolean afternoonsOnly, int limit, long userIdentityId) throws IllegalAccessException
      Proposes the slots of the given length, inside the given window, over which every one of the given attendees is free.

      The proposal is only worth as much as the calendars behind it, so this method refuses rather than guesses: if the asking user cannot read one attendee's availability, no slot is proposed at all. Silently proposing slots computed from a subset of the attendees would return a confident answer that is not backed by the data.

      Parameters:
      attendeeIdentityIds - technical identifiers of the users who must all be free
      duration - the length a slot must have
      windowStart - earliest acceptable start
      windowEnd - latest acceptable end
      morningsOnly - restrict candidate starts to before noon
      afternoonsOnly - restrict candidate starts to noon and after
      limit - maximum number of slots to propose
      userIdentityId - technical identifier of the user asking
      Returns:
      the candidate slots, earliest first, at most limit of them
      Throws:
      IllegalAccessException - when the asking user is not allowed to read the availability of any one of the attendees
      IllegalArgumentException - when the attendee list, the duration or the window is missing or invalid
    • getConflicts

      AvailabilityConflicts getConflicts(List<Long> attendeeIdentityIds, ZonedDateTime start, ZonedDateTime end, long userIdentityId)
      Reports which of the given attendees clash with a proposed window.

      Unlike getAvailability(java.util.List<java.lang.Long>, java.time.ZonedDateTime, java.time.ZonedDateTime, long) this method does not refuse: it is an enrichment of an operation the user is already allowed to perform — creating or updating an event — and failing it would deny a legitimate write over information the user never asked for. It reports on the attendees it may read and names the ones it may not, so the answer is partial but never misleading. See AvailabilityConflicts.

      Parameters:
      attendeeIdentityIds - technical identifiers of the event's attendees; non-user identities are ignored
      start - proposed window start
      end - proposed window end
      userIdentityId - technical identifier of the user asking
      Returns:
      the clash report, never null
    • rankDateOptionsByAvailability

      List<EventDateOption> rankDateOptionsByAvailability(List<EventDateOption> dateOptions, List<Long> attendeeIdentityIds, long userIdentityId)
      Orders date-poll options so that the ones suiting the most attendees come first.

      Only the attendees the asking user may read are counted; an attendee whose availability is not readable counts for no option, so they shift no option relative to another. Like getConflicts(java.util.List<java.lang.Long>, java.time.ZonedDateTime, java.time.ZonedDateTime, long) this degrades rather than refusing — an unreadable attendee costs ordering quality, not the poll.

      Parameters:
      dateOptions - the options to order
      attendeeIdentityIds - technical identifiers of the event's attendees
      userIdentityId - technical identifier of the user asking
      Returns:
      the options, most-available first, keeping the original order between equally available ones