Class CaldavCopyPolicy

java.lang.Object
org.exoplatform.caldav.service.CaldavCopyPolicy

@Service public class CaldavCopyPolicy extends Object
Which eXo events a calendar copy may stand for, said once.

Why this is a class and not two conditions

There are two questions, and they are not the same one: whether an event may acquire a copy it does not have, and whether an event may keep one it already has. They had drifted apart before this class existed — the seeding pass required CONFIRMED and refused a date poll, while the push core asked nothing at all and wrote whatever it was handed, so the author's own browser pushed a copy of the very poll the fan-out had refused everyone else. One rule stated in one place, read by every path, is the only shape in which that cannot happen again.

What a date poll is, and why no copy of one is written

eXo spells a date poll TENTATIVE and stores it as one event whose start and end are the envelope of every option proposed — AgendaEventServiceImpl.checkAndComputeDateOptions sets the start to the earliest option's start and the end to the latest option's end, then marks the event TENTATIVE. So a poll offering Tuesday morning or Friday afternoon is stored as an event running from Tuesday morning to Friday afternoon, and a copy of it is a four-day block on the calendar of everybody invited to vote. That block is not a meeting anybody is going to; it describes nothing that will happen, and it makes its owner look busy for four days. There is no fix for that inside the copy: the option list is what carries the meaning and iCalendar has nowhere to put it. So the copy is not written at all (EXO-89863).

The idea this supersedes was to push the poll's envelope marked TRANSP:TRANSPARENT, so at least it would not book the time. It was shipped as far as the design and then dropped, for the reason above: a four-day entry that does not book time is still a four-day entry describing a meeting that is not happening, and being free-time makes it no more truthful. The availability machinery it was built on stayed and is now used for what it is actually for — an event its owner marked free (EXO-89870).

Cancelled is not the same case

A CANCELLED event keeps its copy, deliberately. The copy is the only place an attendee is still told the meeting is off — eXo hides a cancelled event from its own screens — and a client shows a cancelled entry struck through where it shows a removed one not at all, which is also what a broken synchronisation looks like. So the copy of a cancelled meeting is a tombstone that has to exist, and only TENTATIVE is refused here.

  • Constructor Details

    • CaldavCopyPolicy

      public CaldavCopyPolicy()
  • Method Details

    • mayHoldCopy

      public boolean mayHoldCopy(org.exoplatform.agenda.model.Event event)
      Whether a calendar copy of this event may exist at all.

      The suppression rule, and the one every write path is guarded by. False means more than "do not write": it means a copy that already exists is retired, because an event can become a poll — adding a second date option to a confirmed meeting through updateEvent sets it back to TENTATIVE, and that is reachable from the REST API. Refusing new writes alone would leave the copy written before the change standing for ever.

      A null event answers true, and that is not an oversight. This predicate says "a date poll may hold no copy", not "an event nobody could read may hold none". An event that comes back null is a state each caller already answers for itself and answers differently — the push refuses it as a failure, the verification pass repairs or drops the row — and folding it in here would turn a momentary read failure into a retirement, deleting the copies of every meeting of a user whose agenda blinked.

      Parameters:
      event - the eXo event, as agenda holds it now; null when it could not be read, which this does not answer for
      Returns:
      false only for a date poll
    • maySeedCopy

      public boolean maySeedCopy(org.exoplatform.agenda.model.Event event)
      Whether a calendar copy of this event may be written where none exists.

      Stricter than mayHoldCopy(Event) by exactly one case, and the two live side by side so that the difference is visible rather than inferred: a CANCELLED event keeps the copy it has and is never given a new one. Seeding a tombstone for a meeting somebody's calendar never held would announce a cancellation to a person who was never told the meeting existed.

      Everything this allows, mayHoldCopy(Event) allows too. That implication is what makes the pair safe to read as one rule, and it is pinned by a test rather than left as a sentence.

      Parameters:
      event - the eXo event, as agenda holds it now; null when it could not be read, and a copy is never seeded for an event nobody can read
      Returns:
      true only for a confirmed meeting