anti-linkable.vala 5.34 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
 * Copyright (C) 2011, 2012 Philip Withnall
 *
 * This library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors:
 *       Philip Withnall <philip@tecnocode.co.uk>
 */

using Gee;
using GLib;

/**
 * Interface for {@link Persona} subclasses from backends which support storage
 * of, anti-linking data.
 *
 * Anti-links are stored as a set of {@link Persona.uid}s with each
 * {@link Persona} (A), specifying that A must not be linked into an
 * {@link Individual} with any of the personas in its anti-links set.
 *
 * @since UNRELEASED
 */
public interface Folks.AntiLinkable : Folks.Persona
{
  /**
   * UIDs of anti-linked {@link Persona}s.
   *
   * The {@link Persona}s identified by their UIDs in this set are guaranteed to
   * not be linked to this {@link Persona}, even if their linkable properties
   * match.
   *
   * No UIDs may be `null`. Well-formed but non-existent UIDs (i.e. UIDs which
   * can be successfully parsed, but which don't currently correspond to a
   * {@link Persona} instance) are permitted, as personas may appear and
   * disappear over time.
   *
   * It is expected, but not guaranteed, that anti-links made between personas
   * will be reciprocal. That is, if persona A lists persona B's UID in its
   * {@link AntiLinkable.anti_links} set, persona B will typically also list
   * persona A in its anti-links set.
   *
   * @since UNRELEASED
   */
  public abstract Set<string> anti_links { get; set; }

  /**
   * Change the {@link Persona}'s set of anti-links.
   *
   * It's preferred to call this rather than setting
   * {@link AntiLinkable.anti_links} directly, as this method gives error
   * notification and will only return once the anti-links have been written
   * to the relevant backing store (or the operation's failed).
   *
   * It should be noted that {@link IndividualAggregator.link_personas} and
   * {@link IndividualAggregator.unlink_individual} will modify the anti-links
   * sets of the personas they touch, in order to remove and add anti-links,
   * respectively. It is expected that these {@link IndividualAggregator}
   * methods will be used to modify anti-links indirectly, rather than calling
   * {@link AntiLinkable.change_anti_links} directly.
   *
   * @param anti_links the new set of anti-links from this persona
   * @throws PropertyError if setting the anti-links failed
   * @since UNRELEASED
   */
  public virtual async void change_anti_links (Set<string> anti_links)
      throws PropertyError
    {
      /* Default implementation. */
      throw new PropertyError.NOT_WRITEABLE (
          _("Anti-links are not writeable on this contact."));
    }

  /**
   * Check for an anti-link with another persona.
   *
   * This will return `true` if `other_persona`'s UID is listed in this
   * persona's anti-links set. Note that this check is not symmetric.
   *
   * @param other_persona the persona to check is anti-linked
   * @return `true` if an anti-link exists, `false` otherwise
   * @since UNRELEASED
   */
  public bool has_anti_link_with_persona (Persona other_persona)
    {
      return (other_persona.uid in this.anti_links);
    }

  /**
   * Add anti-links to other personas.
   *
   * The UIDs of all personas in `other_personas` will be added to this
   * persona's anti-links set and the changes propagated to backends.
   *
   * Any attempt to anti-link a persona with itself is not an error, but is
   * ignored.
   *
   * @param other_personas the personas to anti-link to this one
   * @throws PropertyError if setting the anti-links failed
   * @since UNRELEASED
   */
  public async void add_anti_links (Set<Persona> other_personas)
      throws PropertyError
    {
      var new_anti_links = new HashSet<string> ();
      new_anti_links.add_all (this.anti_links);

      foreach (var p in other_personas)
        {
          /* Don't anti-link ourselves. */
          if (p == this)
            {
              continue;
            }

          new_anti_links.add (p.uid);
        }

      yield this.change_anti_links (new_anti_links);
    }

  /**
   * Remove anti-links to other personas.
   *
   * The UIDs of all personas in `other_personas` will be removed from this
   * persona's anti-links set and the changes propagated to backends.
   *
   * @param other_personas the personas to remove anti-links from this one
   * @throws PropertyError if setting the anti-links failed
   * @since UNRELEASED
   */
  public async void remove_anti_links (Set<Persona> other_personas)
      throws PropertyError
    {
      var new_anti_links = new HashSet<string> ();
      new_anti_links.add_all (this.anti_links);

      foreach (var p in other_personas)
        {
          new_anti_links.remove (p.uid);
        }

      yield this.change_anti_links (new_anti_links);
    }
}

/* vim: filetype=vala textwidth=80 tabstop=2 expandtab: */