Class CopySettingsFingerprint

java.lang.Object
org.exoplatform.caldav.utils.CopySettingsFingerprint

public final class CopySettingsFingerprint extends Object
Which changes to a server registration have to reach the copies eXo has already written, and which do not (EXO-89759).

The problem. The mirror converges towards what eXo would render now only when something moves the remote ETag. Change a setting that alters what eXo writes into a copy and nothing moves: every copy already on the server keeps whatever it was given, indefinitely. The remedy is a stamp on the registration and a matching one on each mirror pair, and this class is the one place that decides when the first of them moves.

The rule, and it is a rule rather than a list. A registration's settings are copy-affecting by default. A field is excused only when it belongs to one of four categories that describe the row rather than the copies:

  • identity — which row this is (id, providerName);
  • address — where the server lives (serverUrl). Repointing a registration does not change what eXo would render; it changes which server the account talks to, and the copies on the old one are not this mechanism's business;
  • availability — whether users may connect at all (active). A deactivated connector has nothing to write;
  • presentation — how the row is shown in a list (name, description, icon, and the three image fields). None of it ever reaches a calendar object.
Everything else — what eXo writes into a copy, and what eXo is prepared to accept as still being its own writing — moves the stamp. So the answer-links switch of EXO-89757 moves it, and so will the per-server excusal lists, without either of them naming itself here.

Why by default, and why reflection. Enumerating today's copy-affecting fields would mean the next setting silently does not propagate, and that failure is invisible: nothing breaks, the copies simply never catch up, which is the exact bug this task exists to remove. Reading the model's own fields and excusing four named categories inverts it — a setting added later is covered the moment it is declared, and excusing one is a deliberate, reviewable edit to EXCUSED with a reason.

The asymmetry is on purpose. Over-including costs one comparison round per mirror, which fetches and compares and — finding nothing different — writes nothing at all. Under-including costs copies that never converge and nobody able to see why. So when a new field is ambiguous, leaving it in is the cheap mistake.

Never trusted from a caller. The stamp is recomputed on the write path from the row about to be overwritten, so a JSON body carrying one — stale, invented, or copied from another registration — can neither set every mirror in the deployment re-comparing nor stop one that should.

  • Method Summary

    Modifier and Type
    Method
    Description
    static String
    of(org.exoplatform.caldav.model.CaldavServer server)
    Everything about a registration that governs the copies, as one comparable string.
    static Date
    stampFor(org.exoplatform.caldav.model.CaldavServer stored, org.exoplatform.caldav.model.CaldavServer incoming, Date changedAt)
    The stamp an update should carry: the one the stored row already holds when nothing copy-affecting changed, and the moment of the change when something did.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Method Details

    • stampFor

      public static Date stampFor(org.exoplatform.caldav.model.CaldavServer stored, org.exoplatform.caldav.model.CaldavServer incoming, Date changedAt)
      The stamp an update should carry: the one the stored row already holds when nothing copy-affecting changed, and the moment of the change when something did.

      Carrying the stored value forward is as important as moving it. A write that left the stamp null — an activation toggle, a rename — would tell every mirror that there is nothing to apply, and quietly cancel a change an administrator made a minute earlier that no sweep has reached yet.

      Parameters:
      stored - the registration as it stands now, or null when it could not be read — in which case nothing can be compared and the stamp is left where the incoming row has it
      incoming - the registration as the caller wants it
      changedAt - the moment to stamp when something copy-affecting changed
      Returns:
      the stamp to persist, possibly null
    • of

      public static String of(org.exoplatform.caldav.model.CaldavServer server)
      Everything about a registration that governs the copies, as one comparable string.

      Fields are read in declaration order, which is stable for a class and is the order the model itself documents its appending discipline in; each is rendered as name=value so that two fields swapping values cannot produce the same fingerprint. Nothing here is persisted or shown — it exists only to be compared with another one taken the same way.

      Parameters:
      server - the registration to fingerprint
      Returns:
      the comparable state, never null