-
Notifications
You must be signed in to change notification settings - Fork 31
/
ResourceMetadata.cs
370 lines (324 loc) · 13.7 KB
/
ResourceMetadata.cs
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using SODA.Utilities;
namespace SODA
{
/// <summary>
/// A class that represents metadata about a <see cref="SODA.Resource{T}">Resource</see> in Socrata.
/// </summary>
[DataContract]
public class ResourceMetadata
{
/// <summary>
/// Gets the SodaClient object used for sending requests to this ResourceMetadata's Host.
/// </summary>
public SodaClient Client { get; internal set; }
/// <summary>
/// Gets the url to the Socrata Open Data Portal that hosts this ResourceMetadata.
/// </summary>
public string Host
{
get { return Client.Host; }
}
/// <summary>
/// Gets the Socrata identifier (4x4) for the Resource that this ResourceMetadata describes.
/// </summary>
[DataMember(Name="id")]
public string Identifier { get; internal set; }
/// <summary>
/// Gets or sets the name of the Resource that this ResourceMetadata describes.
/// </summary>
[DataMember(Name = "name")]
public string Name { get; set; }
/// <summary>
/// Gets or sets the category of the resource that this ResourceMetadata describes.
/// </summary>
/// <remarks>
/// The available categories are defined by the Socrata Host.
/// </remarks>
[DataMember(Name = "category")]
public string Category { get; set; }
/// <summary>
/// Gets or sets the description of the resource that this ResourceMetadata describes.
/// </summary>
[DataMember(Name = "description")]
public string Description { get; set; }
/// <summary>
/// Gets or sets the tags (topics) assigned to the resource that this ResourceMetadata describes.
/// </summary>
/// <remarks>
/// Tags (topics) are free-form text not necessarily pre-defined by the Socrata Host.
/// </remarks>
[DataMember(Name = "tags")]
public IEnumerable<string> Tags { get; set; }
/// <summary>
/// Gets or sets the name of the entity providing the data that this ResourceMetadata describes.
/// </summary>
[DataMember(Name = "attribution")]
public string Attribution { get; set; }
/// <summary>
/// Gets or sets the url for the entity providing the data that this ResourceMetadata describes.
/// </summary>
[DataMember(Name = "attributionLink")]
public string AttributionLink { get; set; }
/// <summary>
/// Gets the unix timestamp when the resource that this ResourceMetadata describes was created.
/// </summary>
[DataMember(Name = "createdAt")]
public double? CreationDateUnix { get; internal set; }
/// <summary>
/// Gets the local DateTime representation of <see cref="CreationDateUnix">CreationDateUnix</see>.
/// </summary>
public DateTime? CreationDate
{
get
{
if (CreationDateUnix.HasValue)
{
return DateTimeConverter.FromUnixTimestamp(CreationDateUnix.Value);
}
return default(DateTime?);
}
}
/// <summary>
/// Gets the unix timestamp when the resource that this ResourceMetadata describes was first published.
/// </summary>
[DataMember(Name = "publicationDate")]
public double? PublishedDateUnix { get; internal set; }
/// <summary>
/// Gets the local DateTime representation of <see cref="PublishedDateUnix">PublishedDateUnix</see>.
/// </summary>
public DateTime? PublishedDate
{
get
{
if (PublishedDateUnix.HasValue)
{
return DateTimeConverter.FromUnixTimestamp(PublishedDateUnix.Value);
}
return default(DateTime?);
}
}
/// <summary>
/// Gets the unix timestamp when the data in the resource that this ResourceMetadata describes was last updated.
/// </summary>
[DataMember(Name = "rowsUpdatedAt")]
public double? RowsLastUpdatedUnix { get; internal set; }
/// <summary>
/// Gets the local DateTime representation of <see cref="RowsLastUpdatedUnix">RowsLastUpdatedUnix</see>.
/// </summary>
public DateTime? RowsLastUpdated
{
get
{
if (RowsLastUpdatedUnix.HasValue)
{
return DateTimeConverter.FromUnixTimestamp(RowsLastUpdatedUnix.Value);
}
return default(DateTime?);
}
}
/// <summary>
/// Gets the unix timestamp when the schema of the resource that this ResourceMetadata describes was last modified.
/// </summary>
[DataMember(Name = "viewLastModified")]
public double? SchemaLastUpdatedUnix { get; internal set; }
/// <summary>
/// Gets the local DateTime representation of <see cref="SchemaLastUpdatedUnix">SchemaLastUpdatedUnix</see>
/// </summary>
public DateTime? SchemaLastUpdated
{
get
{
if (SchemaLastUpdatedUnix.HasValue)
{
return DateTimeConverter.FromUnixTimestamp(SchemaLastUpdatedUnix.Value);
}
return default(DateTime?);
}
}
/// <summary>
/// Gets the collection of <see cref="ResourceColumn">ResourceColumn</see> that describe the schema of this ResourceMetadata's resource.
/// </summary>
[DataMember(Name = "columns")]
public IEnumerable<ResourceColumn> Columns { get; internal set; }
/// <summary>
/// Gets the number of comments posted to the resource that this ResourceMetadata describes.
/// </summary>
[DataMember(Name = "numberOfComments")]
public long CommentsCount { get; private set; }
/// <summary>
/// Gets the number of times the resource that this ResourceMetadata describes has been downloaded.
/// </summary>
[DataMember(Name = "downloadCount")]
public long DownloadsCount { get; private set; }
/// <summary>
/// Gets the total number of ratings received by the resource that this ResourceMetadata describes.
/// </summary>
[DataMember(Name = "totalTimesRated")]
public long RatingsCount { get; private set; }
/// <summary>
/// Gets the average rating for the resource that this ResourceMetadata describes.
/// </summary>
[DataMember(Name = "averageRating")]
public decimal AverageRating { get; private set; }
/// <summary>
/// Gets the number of times the resource that this ResourceMetadata describes has been viewed.
/// </summary>
[DataMember(Name = "viewCount")]
public long ViewsCount { get; private set; }
/// <summary>
/// Gets the Socrata object type of the resource that this ResourceMetadata describes.
/// </summary>
/// <remarks>
/// E.g. table, map, calendar, chart
/// </remarks>
[DataMember(Name = "displayType")]
public string DisplayType { get; private set; }
/// <summary>
/// Gets the Socrata view type of the resource that this ResourceMetadata describes.
/// </summary>
[DataMember(Name = "viewType")]
public string ViewType { get; private set; }
/// <summary>
/// Gets the Socrata internal table id for the resource that this ResourceMetadata describes.
/// </summary>
[DataMember(Name = "tableId")]
public long TableId { get; private set; }
/// <summary>
/// Gets or sets a dynamic dictionary of additional metadata fields.
/// </summary>
/// <remarks>
/// If the Socrata Host has defined any custom metadata fields, these will be available in this dictionary
/// as a Dictionary<string, dynamic> under the "custom_fields" key.
/// </remarks>
[DataMember(Name = "metadata")]
public Dictionary<string, dynamic> Metadata { get; set; }
/// <summary>
/// Gets the internal Socrata id for the column that acts as the row identifier for the resource that this ResourceMetadata describes.
/// </summary>
public long? RowIdentifierFieldId
{
get
{
if (Metadata != null && Metadata.ContainsKey("rowIdentifier"))
{
long id;
if (long.TryParse(Metadata["rowIdentifier"].ToString(), out id))
{
return id;
}
}
return null;
}
}
/// <summary>
/// Gets the SODA-compatible field name of the column that acts as the row identifier for the resource that this ResourceMetadata describes.
/// </summary>
public string RowIdentifierField
{
get
{
if (RowIdentifierFieldId.HasValue)
{
if (Columns != null && Columns.Any())
{
var column = Columns.SingleOrDefault(c => c.Id.Equals(RowIdentifierFieldId.Value));
if (column != null)
{
return column.SodaFieldName;
}
}
}
else if (Metadata != null && Metadata.ContainsKey("rowIdentifier"))
{
return Metadata["rowIdentifier"];
}
return ":id";
}
}
/// <summary>
/// Gets or sets a dynamic dictionary describing the filtering and sorting applied to the resource that this ResourceMetadata describes.
/// </summary>
[DataMember(Name = "query")]
public Dictionary<string, dynamic> Query { get; set; }
/// <summary>
/// Gets or sets a dynamic dictionary of "private" metadata associated with this ResourceMetadata.
/// </summary>
/// <remarks>
/// <see cref="ContactEmail">ContactEmail</see> is derived from the private metadata.
/// </remarks>
[DataMember(Name = "privateMetadata")]
public Dictionary<string, dynamic> PrivateMetadata { get; set; }
/// <summary>
/// Gets the contact email assigned to the resource that this ResourceMetadata describes.
/// </summary>
public string ContactEmail
{
get
{
if (PrivateMetadata != null && PrivateMetadata.ContainsKey("contactEmail"))
{
return (string)PrivateMetadata["contactEmail"];
}
return null;
}
}
/// <summary>
/// Gets or sets a dynamic dictionary describing the filtering applied to the resource that this ResourceMetadata describes.
/// </summary>
/// <remarks>
/// This appears to only be available when the resource is a Socrata Filtered View.
/// In other words, Datasets, Maps, etc. do not have this metadata property.
/// </remarks>
[Obsolete("Socrata has discontinued support for this undocumented metadata field. It will no longer be requested or sent with SODA calls, and may be removed in a future release.")]
public Dictionary<string, dynamic> ViewFilters { get; set; }
/// <summary>
/// Updates this ResourceMetadata on the Socrata Host.
/// </summary>
/// <returns>A SodaResult, indicating success or failure.</returns>
public SodaResult Update()
{
var metadataUri = SodaUri.ForMetadata(Host, Identifier);
SodaResult result = new SodaResult();
try
{
//use PUT to replace all existing metadata with the new values
result = Client.write<ResourceMetadata, SodaResult>(metadataUri, "PUT", this);
//no exception thrown => success!
result.IsError = false;
result.Message = String.Format("Metadata for {0} updated successfully.", Identifier);
}
catch (Exception ex)
{
result.IsError = true;
result.Message = ex.Message;
result.Data = ex.StackTrace;
}
return result;
}
/// <summary>
/// Initialize a new ResourceMetadata object.
/// </summary>
/// <remarks>
/// The constructor is internal because ResourceMetadata should be obtained through a SodaClient or Resource object.
/// </remarks>
internal ResourceMetadata() { }
/// <summary>
/// Initialize a new ResourceMetadata object with the specified <see cref="SodaClient"/>.
/// </summary>
/// <param name="client">A <see cref="SodaClient"/> used to access this ResourceMetadata on a Socrata Host.</param>
/// <remarks>
/// The constructor is internal because ResourceMetadata should be obtained through a SodaClient or Resource object.
/// </remarks>
internal ResourceMetadata(SodaClient client)
{
if (client == null)
throw new ArgumentNullException("client", "Cannot initialize a ResourceMetadata with null SodaClient");
Client = client;
}
}
}