Enum Class ServerQuirk

java.lang.Object
java.lang.Enum<ServerQuirk>
org.exoplatform.caldav.model.ServerQuirk
All Implemented Interfaces:
Serializable, Comparable<ServerQuirk>, Constable

public enum ServerQuirk extends Enum<ServerQuirk>
The behaviours a CalDAV server can be excused for, named in code.

Why the list is code and not data. Each entry decides what "unchanged" means for the servers it is ticked on, so adding one is a decision about the mirror's guarantees rather than a configuration value. Written here, it is reviewed like any other change to the comparison; typed into a text field it would not be. That is also why the administrator never types a property name: the drawer offers what the sweep has actually seen, and each offer carries the sentence written here beside it.

Nothing is blocked by the list being incomplete. A divergence no entry matches is still offered, described generically by the property name the sweep saw. A deployment meeting a server nobody here has seen can excuse its quirk on the day it meets it; the entry that gives that quirk a sentence follows later.

The patterns are the unit of storage. Ticking an entry writes exactly the patterns below into the server's list, so what was ticked can be read back from the row and the excusal covers the whole family the sentence names — every X-MOZ- marker, not only the one this deployment happened to see first. A pattern ending in * matches by prefix; anything else is an exact, case-insensitive property name. That is the same matcher the comparison uses against the stored list, so what the drawer says is excused and what the sweep excuses cannot drift apart.

Two kinds of entry, and the difference is declared. Most entries only change what eXo notices; one changes what eXo writes into a copy on somebody's calendar. ServerQuirkEffect carries that, it decides which stored list a tick is written into, and the drawer renders it — a payload-changing box that looks identical to a tolerance one is the kind of thing that reads fine today and surprises somebody in a year.

The URL duplication is deliberately absent. BlueMind appends every URI in a description a second time; eXo recognises and normalises that for every server (EXO-89756). It is a correctness fix, not a preference, and an entry here would only offer a way to switch working code off.

  • Enum Constant Details

    • DROPS_CONFERENCE

      public static final ServerQuirk DROPS_CONFERENCE
      The server does not keep video-conference links. BlueMind stores no CONFERENCE at all: eXo writes the link on every push and the copy comes back without it, which kept five copies of a live account in a permanent repair loop.
    • ADDS_COMPATIBILITY_MARKERS

      public static final ServerQuirk ADDS_COMPATIBILITY_MARKERS
      The server stamps the compatibility markers Outlook and Thunderbird read — hidden fields that say nothing about the meeting. eXo writes none of them, so they arrive as unrecognised properties on every copy.
    • ADDS_FORMATTED_DESCRIPTION

      public static final ServerQuirk ADDS_FORMATTED_DESCRIPTION
      The server adds a rich-text duplicate of the invitation text. It is a second rendering of the same words, not a second statement about the meeting, and eXo goes on comparing the plain one.
    • REWRITES_DESCRIPTION

      public static final ServerQuirk REWRITES_DESCRIPTION
      The server rewrites the invitation text itself.

      The blunt one, and it must stay blunt. Excusing it stops the text of every copy on that server being compared at all — including the tokenised answer links the description carries since EXO-89753, which EXO-89752 bounded in time precisely so that a rewritten one would be noticed. Ticked, nobody notices a rewritten answer link again on that server. It is the one entry whose direction is ServerQuirkDirection.REWRITTEN, which is what makes the comparison tolerate a substituted value and not only an absence, and it is the reason that tolerance is opt-in per entry rather than granted to every excused property.

    • OMITS_SOLO_ORGANIZER

      public static final ServerQuirk OMITS_SOLO_ORGANIZER
      The server drops the organizer from an event with no other participants.

      BlueMind stores neither ORGANIZER nor ATTENDEE on a copy of an event whose only participant is its creator. eXo writes an organizer, reads back a copy with none, judges it altered and rewrites it — on every sweep, for ever (EXO-89775).

      Superseded by EXO-89805, and kept deliberately. eXo no longer names an organizer on such an event on any server: soloness is a property of the event, and AgendaEventIcsMapper.organizerOf now reads it the way rsvpLinks always did, so the two halves of one copy can no longer contradict each other. This entry therefore describes something the sweep can never observe again — eXo writes no organizer there, so none can be seen dropped — and ticking it asks for exactly what already happens. It stays for two reasons and no third: a deployment whose stored observations still remember the behaviour must read a sentence rather than a bare token, and SOLO_ORGANIZER must go on naming the case in IcsStatement so an organizer missing from a solo copy is never offered as a bare ORGANIZER excusal — which would blind the comparison on real meetings too. Retiring the entry means retiring the omittedProperties list, its column and its drawer with it, which is a separate decision and not this one.

      The one entry that changes what eXo writes rather than what it tolerates. Ticking it stops eXo naming an organizer on those copies for this server; the copy and the render then say the same thing, so there is nothing left to excuse and no tolerance entry beside it. That is why its pattern, SOLO_ORGANIZER, is deliberately not a property name eXo writes: it can never be read as an excusal by the comparison, whose lists are restricted to the properties IcsWriter emits.

      Why it was per server, and why that was the wrong axis. The golden corpus holds organizer-only events that a real server stored with their organizer, and EXO-89768 and EXO-89775 both read that as proof the behaviour was one server's. It proves what a server keeps, which is not the same question as what eXo should write; and the registration that finally showed the cost had never been declared at all, so no per-server lever could have reached it.

  • Field Details

    • SOLO_ORGANIZER

      public static final String SOLO_ORGANIZER
      The token standing for "the organizer of an event with no other participants".

      Deliberately not ORGANIZER. It names a case and not a property, so it can never be mistaken for one: the comparison's excusal lists only ever accept a property IcsWriter emits, which means no setting of this can make a missing organizer on an ordinary meeting stop being reported. An organizer disappearing from a copy on a server that normally keeps it is a real change and stays one.

      See Also:
  • Method Details

    • values

      public static ServerQuirk[] values()
      Returns an array containing the constants of this enum class, in the order they are declared.
      Returns:
      an array containing the constants of this enum class, in the order they are declared
    • valueOf

      public static ServerQuirk valueOf(String name)
      Returns the enum constant of this class with the specified name. The string must match exactly an identifier used to declare an enum constant in this class. (Extraneous whitespace characters are not permitted.)
      Parameters:
      name - the name of the enum constant to be returned.
      Returns:
      the enum constant with the specified name
      Throws:
      IllegalArgumentException - if this enum class has no constant with the specified name
      NullPointerException - if the argument is null
    • getEffect

      public ServerQuirkEffect getEffect()
      Returns:
      whether ticking this entry changes what eXo notices or what eXo writes into copies on the server
    • getSupersedes

      public String getSupersedes()
      Returns:
      the property whose own stored record this entry replaces, or null when it replaces none
    • superseding

      public static Optional<String> superseding(String property)
      The property whose stored record is replaced once a behaviour is observed.

      Asked of what a pass actually saw, so nothing is forgotten on the strength of the catalogue alone: a record only goes when the case that replaces it is being observed on that very server.

      Parameters:
      property - the property or case name a pass reported
      Returns:
      the property whose record it replaces, or empty when it replaces none
    • getId

      public String getId()
      Returns:
      the stable identifier the browser resolves this entry's wording by
    • getDirection

      public ServerQuirkDirection getDirection()
      Returns:
      which way the divergence this entry describes points
    • getPatterns

      public List<String> getPatterns()
      Returns:
      the property-name patterns ticking this entry writes into the server's list
    • describing

      public static Optional<ServerQuirk> describing(String property, ServerQuirkDirection direction)
      The catalogue entry describing a divergence, when one does.
      Parameters:
      property - the property name the sweep saw diverge
      direction - which way that divergence pointed
      Returns:
      the entry, or empty when nothing in the catalogue describes it
    • rewriteExcusable

      public static boolean rewriteExcusable(String property)
      Whether excusing a property's absence on a server also excuses the server substituting its own value for it.

      True only for an entry that declares ServerQuirkDirection.REWRITTEN — one deliberate entry today. Every other excused property, and every property no entry names, keeps the narrow meaning the operator lever has always had: a statement eXo makes and the copy does not carry. So a client that rewrites a conference link is still caught on a server excused for dropping one, which is what the entry's own wording promises.

      Parameters:
      property - the property name
      Returns:
      true when a rewritten value of it is excused along with its absence
    • listMatches

      public static boolean listMatches(String patterns, String property)
      Whether a stored list of patterns asks eXo to leave something out of the copies it writes to a server.
      Parameters:
      patterns - the server's stored omission list, may be null or blank
      property - the case or property name to test
      Returns:
      true when one of the patterns names it
    • patternMatches

      public static boolean patternMatches(String pattern, String property)
      Whether a stored pattern names a property.

      The one matcher, used by the catalogue, by the drawer's ticking and by the comparison's excusal, so a family written as X-MOZ-* means the same thing everywhere it is read.

      Parameters:
      pattern - an exact property name, or a prefix followed by *
      property - the property name to test
      Returns:
      true when the pattern names the property