Class IcsMerger
A calendar object is not ours alone. Another client may have written overrides into the same object, with its own properties and its own VTIMEZONE, and a push that replaced the whole document would silently destroy them. So the object is read, the parts this event owns are replaced, and everything else is left exactly as it was found.
Two rules decide what "the parts this event owns" means, and both were learned the hard way. Pushing a master replaces the master — and also prunes any override whose instance the master's EXDATEs now exclude, because an override contradicting an EXDATE keeps a deleted occurrence visible on the client. Pushing an override replaces only the override for that instance.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final recordWhat an attempted answer rewrite found. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionexcludeOccurrence(String existing, Instant occurrence) Rewrites a calendar object so that it no longer produces one occurrence.Merges one component into the object a server holds.setAttendeeResponse(String existing, Collection<String> addresses, String partStat) Rewrites one attendee's participation status in the object a server holds, leaving every other byte of it alone.
-
Constructor Details
-
IcsMerger
public IcsMerger()
-
-
Method Details
-
merge
Merges one component into the object a server holds.- Parameters:
existing- the calendar object as fetched from the servercomponent- the object this engine just built, holding one VEVENToccurrence- whether the component amends one instance rather than being the master- Returns:
- the object to write back
- Throws:
IcsParseException- when either document is not readable iCalendar
-
setAttendeeResponse
public IcsMerger.AnswerRewrite setAttendeeResponse(String existing, Collection<String> addresses, String partStat) Rewrites one attendee's participation status in the object a server holds, leaving every other byte of it alone.The outward half of answering a meeting. An answer given in eXo — in the agenda screen, or through the tokenised link in the notification mail — only ever reached eXo's own database, so the copy on the user's calendar server went on displaying the answer it last carried. That is a wrong answer shown to its own author, and worse: the copy is also what the verification pass reads a client's answer back from, so a stale one is eventually adopted and the newer answer is silently lost.
A targeted rewrite rather than a fresh serialisation of the whole event: the object may carry overrides and properties another client wrote, and an answer is not consent to discard them. It is also what makes the write idempotent — an object that already says this comes back with no document to write, which is what stops an answer adopted from the copy from being pushed straight back at it.
Every VEVENT in the object is visited, master and overrides alike, because agenda propagates an answer to a series onto each of its exceptional occurrences: leaving the overrides on their old value would show the user one answer for the series and another for the instances of it they moved.
A set of addresses, not one. A copy does not name a person the same way everywhere: their own line carries the address their CalDAV account answers to, so that a client recognises the meeting as an invitation to its owner, while every other line — and every copy written before that rule existed — carries their eXo profile address. Being handed one address and told it is the one is how this silently matched nothing on a live rig: the caller offers every address that could name this person, and whichever the object actually holds is the one rewritten.
- Parameters:
existing- the calendar object as fetched from the serveraddresses- every address the copy might name this attendee bypartStat- the RFC 5545 token to set, already validated byIcsText.partStat(String)- Returns:
- whether the object names the attendee at all, and the document to write back when the answer moved
- Throws:
IcsParseException- when the document is not readable iCalendar
-
excludeOccurrence
Rewrites a calendar object so that it no longer produces one occurrence.Not a deletion of the object: RFC 4791 puts every component of a series in one object, so removing it would remove the whole series. The override carrying that instance is dropped, and the master gains an EXDATE for it — in the value type the master's own DTSTART uses, because RFC 5545 matches instances by identical value. An EXDATE written as a date-time against a date-valued series matches no instance at all, and the deleted occurrence simply reappears.
Answering null rather than an object means nothing is left: the caller deletes the object instead of writing back a VCALENDAR with no VEVENT in it, which some servers accept and then serve to clients that choke on it.
- Parameters:
existing- the calendar object as fetched from the serveroccurrence- the instance to exclude- Returns:
- the object to write back, or null when nothing remains of it
- Throws:
IcsParseException- when the document is not readable iCalendar
-