Post-release version bump
[platform/upstream/folks.git] / folks / role-details.vala
1 /*
2  * Copyright (C) 2011 Collabora Ltd.
3  * Copyright (C) 2011 Philip Withnall
4  *
5  * This library is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation, either version 2.1 of the License, or
8  * (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this library.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  * Authors:
19  *       Raul Gutierrez Segales <raul.gutierrez.segales@collabora.co.uk>
20  *       Travis Reitter <travis.reitter@collabora.co.uk>
21  *       Philip Withnall <philip@tecnocode.co.uk>
22  */
23
24 using Gee;
25 using GLib;
26
27 /**
28  * This interface represents the role a {@link Persona} and {@link Individual}
29  * have in a given Organisation.
30  *
31  * @since 0.4.0
32  */
33 public class Folks.Role : Object
34 {
35   private string _organisation_name;
36   /**
37    * The name of the organisation in which the role is held.
38    */
39   public string organisation_name
40     {
41       get { return this._organisation_name; }
42       set { this._organisation_name = (value != null ? value : ""); }
43     }
44
45   private string _title;
46   /**
47    * The title of the position held.
48    *
49    * For example: “Director, Ministry of Silly Walks”
50    */
51   public string title
52     {
53       get { return this._title; }
54       set { this._title = (value != null ? value : ""); }
55     }
56
57   private string _role;
58   /**
59    * The role of the position.
60    *
61    * For example: “Programmer”
62    *
63    * @since 0.6.0
64    */
65   public string role
66     {
67       get { return this._role; }
68       set { this._role = (value != null ? value : ""); }
69     }
70
71   private string _uid;
72   /**
73    * The UID that distinguishes this role.
74    */
75   [Deprecated (since = "0.6.5", replacement = "AbstractFieldDetails.id")]
76   public string uid
77     {
78       get { return _uid; }
79       set { _uid = (value != null ? value : ""); }
80     }
81
82   /**
83    * Default constructor.
84    *
85    * @param title title of the position
86    * @param organisation_name organisation where the role is hold
87    * @param uid a Unique ID associated to this Role
88    * @return a new Role
89    *
90    * @since 0.4.0
91    */
92   public Role (string? title = null,
93       string? organisation_name = null, string? uid = null)
94     {
95       Object (uid:                  uid,
96               title:                title,
97               organisation_name:    organisation_name);
98     }
99
100   /**
101    * Whether none of the components is set.
102    *
103    * @return `true` if all the components are the empty string, `false`
104    * otherwise.
105    *
106    * @since 0.6.7
107    */
108   public bool is_empty ()
109     {
110       return this.organisation_name == "" &&
111              this.title == "" &&
112              this.role == "";
113     }
114
115   /**
116    * Compare if two roles are equal. Roles are equal if their titles and
117    * organisation names are equal.
118    *
119    * @param a a role to compare
120    * @param b another role to compare
121    * @return `true` if the roles are equal, `false` otherwise
122    */
123   public static bool equal (Role a, Role b)
124     {
125       return (a.title == b.title) &&
126           (a.role == b.role) &&
127           (a.organisation_name == b.organisation_name);
128     }
129
130   /**
131    * Hash function for the class. Suitable for use as a hash table key.
132    *
133    * @param r a role to hash
134    * @return hash value for the role instance
135    */
136   public static uint hash (Role r)
137     {
138       return r.organisation_name.hash () ^ r.title.hash () ^ r.role.hash ();
139     }
140
141   /**
142    * Formatted version of this role.
143    *
144    * @since 0.4.0
145    */
146   public string to_string ()
147     {
148       var str = _("Title: %s, Organisation: %s, Role: %s");
149       return str.printf (this.title, this.organisation_name, this.role);
150     }
151 }
152
153 /**
154  * Object representing details of a contact in an organisation which can have
155  * some parameters associated with it.
156  *
157  * See {@link Folks.AbstractFieldDetails}.
158  *
159  * @since 0.6.0
160  */
161 public class Folks.RoleFieldDetails : AbstractFieldDetails<Role>
162 {
163   private string _id;
164   /**
165    * {@inheritDoc}
166    */
167   public override string id
168     {
169       get { return this._id; }
170       set
171         {
172           this._id = (value != null ? value : "");
173
174           /* Keep the Role.uid sync'd from our id */
175           if (this._id != this.value.uid)
176             this.value.uid = this._id;
177         }
178     }
179
180   /**
181    * Create a new RoleFieldDetails.
182    *
183    * @param value the non-empty {@link Role} of the field
184    * @param parameters initial parameters. See
185    * {@link AbstractFieldDetails.parameters}. A `null` value is equivalent to an
186    * empty map of parameters.
187    *
188    * @return a new RoleFieldDetails
189    *
190    * @since 0.6.0
191    */
192   public RoleFieldDetails (Role value,
193       MultiMap<string, string>? parameters = null)
194     {
195       if (value.is_empty ())
196         {
197           warning ("Empty role passed to RoleFieldDetails.");
198         }
199
200       /* We keep id and value.uid synchronised in both directions. */
201       Object (value: value,
202               parameters: parameters,
203               id: value.uid);
204     }
205
206   construct
207     {
208       /* Keep the Role.uid sync'd to our id */
209       this.value.notify["uid"].connect ((s, p) =>
210         {
211           if (this.id != this.value.uid)
212             this.id = this.value.uid;
213         });
214     }
215
216   /**
217    * {@inheritDoc}
218    *
219    * @since 0.6.0 
220    */
221   public override bool equal (AbstractFieldDetails<Role> that)
222     {
223       var _that_fd = that as RoleFieldDetails;
224       if (_that_fd == null)
225         return false;
226       RoleFieldDetails that_fd = (!) _that_fd;
227
228       if (!base.parameters_equal (that))
229         return false;
230
231       return Role.equal (this.value, that_fd.value);
232     }
233
234   /**
235    * {@inheritDoc}
236    *
237    * @since 0.6.0
238    */
239   public override uint hash ()
240     {
241       return str_hash (this.value.to_string ());
242     }
243 }
244
245 /**
246  * This interfaces represents the list of roles a {@link Persona} and
247  * {@link Individual} might have.
248  *
249  * @since 0.4.0
250  */
251 public interface Folks.RoleDetails : Object
252 {
253   /**
254    * The roles of the contact.
255    *
256    * @since 0.6.0
257    */
258   public abstract Set<RoleFieldDetails> roles { get; set; }
259
260   /**
261    * Change the contact's roles.
262    *
263    * It's preferred to call this rather than setting {@link RoleDetails.roles}
264    * directly, as this method gives error notification and will only return once
265    * the roles have been written to the relevant backing store (or the
266    * operation's failed).
267    *
268    * @param roles the set of roles
269    * @throws PropertyError if setting the roles failed
270    * @since 0.6.2
271    */
272   public virtual async void change_roles (Set<RoleFieldDetails> roles)
273       throws PropertyError
274     {
275       /* Default implementation. */
276       throw new PropertyError.NOT_WRITEABLE (
277           _("Roles are not writeable on this contact."));
278     }
279 }