1 /*
2 * e-source-resource.c
3 *
4 * This library is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18 /**
19 * SECTION: e-source-resource
20 * @include: libedataserver/libedataserver.h
21 * @short_description: #ESource extension for a remote resource
22 *
23 * The #ESourceResource extension holds the server-assigned identity of a
24 * remote calendar, address book, or whatever else an #ESource can represent.
25 *
26 * This extension is typically used by an #ECollectionBackend to note a
27 * server-assigned resource identity in an #ESource. Then in a later session,
28 * after querying the server for available resources, a resource identity can
29 * be paired with the same #ESource #ESource:uid from the previous session,
30 * allowing locally cached data from the previous session to be reused.
31 *
32 * Access the extension as follows:
33 *
34 * |[
35 * #include <libedataserver/libedataserver.h>
36 *
37 * ESourceResource *extension;
38 *
39 * extension = e_source_get_extension (source, E_SOURCE_EXTENSION_RESOURCE);
40 * ]|
41 **/
42
43 #include "e-source-resource.h"
44
45 #include <libedataserver/e-data-server-util.h>
46
47 struct _ESourceResourcePrivate {
48 gchar *identity;
49 };
50
51 enum {
52 PROP_0,
53 PROP_IDENTITY
54 };
55
G_DEFINE_TYPE_WITH_PRIVATE(ESourceResource,e_source_resource,E_TYPE_SOURCE_EXTENSION)56 G_DEFINE_TYPE_WITH_PRIVATE (
57 ESourceResource,
58 e_source_resource,
59 E_TYPE_SOURCE_EXTENSION)
60
61 static void
62 source_resource_set_property (GObject *object,
63 guint property_id,
64 const GValue *value,
65 GParamSpec *pspec)
66 {
67 switch (property_id) {
68 case PROP_IDENTITY:
69 e_source_resource_set_identity (
70 E_SOURCE_RESOURCE (object),
71 g_value_get_string (value));
72 return;
73 }
74
75 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
76 }
77
78 static void
source_resource_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)79 source_resource_get_property (GObject *object,
80 guint property_id,
81 GValue *value,
82 GParamSpec *pspec)
83 {
84 switch (property_id) {
85 case PROP_IDENTITY:
86 g_value_take_string (
87 value,
88 e_source_resource_dup_identity (
89 E_SOURCE_RESOURCE (object)));
90 return;
91 }
92
93 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
94 }
95
96 static void
source_resource_finalize(GObject * object)97 source_resource_finalize (GObject *object)
98 {
99 ESourceResourcePrivate *priv;
100
101 priv = E_SOURCE_RESOURCE (object)->priv;
102
103 g_free (priv->identity);
104
105 /* Chain up to parent's finalize() method. */
106 G_OBJECT_CLASS (e_source_resource_parent_class)->finalize (object);
107 }
108
109 static void
e_source_resource_class_init(ESourceResourceClass * class)110 e_source_resource_class_init (ESourceResourceClass *class)
111 {
112 GObjectClass *object_class;
113 ESourceExtensionClass *extension_class;
114
115 object_class = G_OBJECT_CLASS (class);
116 object_class->set_property = source_resource_set_property;
117 object_class->get_property = source_resource_get_property;
118 object_class->finalize = source_resource_finalize;
119
120 extension_class = E_SOURCE_EXTENSION_CLASS (class);
121 extension_class->name = E_SOURCE_EXTENSION_RESOURCE;
122
123 g_object_class_install_property (
124 object_class,
125 PROP_IDENTITY,
126 g_param_spec_string (
127 "identity",
128 "Identity",
129 "Resource identity",
130 NULL,
131 G_PARAM_READWRITE |
132 G_PARAM_CONSTRUCT |
133 G_PARAM_EXPLICIT_NOTIFY |
134 G_PARAM_STATIC_STRINGS |
135 E_SOURCE_PARAM_SETTING));
136 }
137
138 static void
e_source_resource_init(ESourceResource * extension)139 e_source_resource_init (ESourceResource *extension)
140 {
141 extension->priv = e_source_resource_get_instance_private (extension);
142 }
143
144 /**
145 * e_source_resource_get_identity:
146 * @extension: an #ESourceResource
147 *
148 * Returns the server-assigned identity of the remote resource associated
149 * with the #ESource to which @extension belongs.
150 *
151 * Returns: (nullable): the identity of a remote resource
152 *
153 * Since: 3.6
154 **/
155 const gchar *
e_source_resource_get_identity(ESourceResource * extension)156 e_source_resource_get_identity (ESourceResource *extension)
157 {
158 g_return_val_if_fail (E_IS_SOURCE_RESOURCE (extension), NULL);
159
160 return extension->priv->identity;
161 }
162
163 /**
164 * e_source_resource_dup_identity:
165 * @extension: an #ESourceResource
166 *
167 * Thread-safe variation of e_source_resource_get_identity().
168 * Use this function when accessing @extension from multiple threads.
169 *
170 * The returned string should be freed with g_free() when no longer needed.
171 *
172 * Returns: (nullable): a newly-allocated copy of #ESourceResource:identity
173 *
174 * Since: 3.6
175 **/
176 gchar *
e_source_resource_dup_identity(ESourceResource * extension)177 e_source_resource_dup_identity (ESourceResource *extension)
178 {
179 const gchar *protected;
180 gchar *duplicate;
181
182 g_return_val_if_fail (E_IS_SOURCE_RESOURCE (extension), NULL);
183
184 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
185
186 protected = e_source_resource_get_identity (extension);
187 duplicate = g_strdup (protected);
188
189 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
190
191 return duplicate;
192 }
193
194 /**
195 * e_source_resource_set_identity:
196 * @extension: an #ESourceResource
197 * @identity: (nullable): the identity of a remote resource
198 *
199 * Sets the server-assigned identity of the remote resource associated with
200 * the #ESource to which @extension belongs.
201 *
202 * The internal copy of @identity is automatically stripped of leading and
203 * trailing whitespace. If the resulting string is empty, %NULL is set
204 * instead.
205 *
206 * Since: 3.6
207 **/
208 void
e_source_resource_set_identity(ESourceResource * extension,const gchar * identity)209 e_source_resource_set_identity (ESourceResource *extension,
210 const gchar *identity)
211 {
212 g_return_if_fail (E_IS_SOURCE_RESOURCE (extension));
213
214 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
215
216 if (e_util_strcmp0 (extension->priv->identity, identity) == 0) {
217 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
218 return;
219 }
220
221 g_free (extension->priv->identity);
222 extension->priv->identity = e_util_strdup_strip (identity);
223
224 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
225
226 g_object_notify (G_OBJECT (extension), "identity");
227 }
228
229