Skip to content

Commit

Permalink
#24 Add WikibaseUri atomic class.
Browse files Browse the repository at this point in the history
  • Loading branch information
CXuesong committed Oct 2, 2017
1 parent 0aaf269 commit 94ea9b2
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 5 deletions.
4 changes: 2 additions & 2 deletions WikiClientLibrary/Wikibase/PropertyType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public static class PropertyTypes
var after = (int) e["after"];
var precision = (WikibaseTimePrecision) (int) e["precision"];
var calendar = (string) e["calendarmodel"];
return new WikibaseTime(time, before, after, timeZone, precision, calendar);
return new WikibaseTime(time, before, after, timeZone, precision, WikibaseUri.Get(calendar));
}, v =>
{
var obj = new JObject
Expand All @@ -82,7 +82,7 @@ public static class PropertyTypes
{"before", v.Before},
{"after", v.After},
{"precision", (int) v.Precision},
{"calendarmodel", v.CalendarModel}
{"calendarmodel", v.CalendarModel.Uri}
};
return obj;
});
Expand Down
7 changes: 4 additions & 3 deletions WikiClientLibrary/Wikibase/WikibaseTime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public struct WikibaseTime : IEquatable<WikibaseTime>

public WikibaseTime(int year, int month, int day, int hour, int minute, int second,
int before, int after, int timeZone,
WikibaseTimePrecision precision, string calendarModel)
WikibaseTimePrecision precision, WikibaseUri calendarModel)
{
Year = year;
Month = month;
Expand All @@ -33,7 +33,8 @@ public WikibaseTime(int year, int month, int day, int hour, int minute, int seco
private static readonly Regex ISO8601Matcher =
new Regex(@"^\s*(?<Y>[\+-]?\d{1,9})-(?<M>\d\d?)-(?<D>\d\d?)T(?<H>\d\d?)-(?<m>\d\d?)-(?<S>\d\d?)(?<K>Z|[\+-]\d\d?:\d\d?)?\s*$");

public WikibaseTime(string dateTime, int before, int after, int timeZone, WikibaseTimePrecision precision, string calendarModel)
public WikibaseTime(string dateTime, int before, int after, int timeZone,
WikibaseTimePrecision precision, WikibaseUri calendarModel)
{
if (dateTime == null) throw new ArgumentNullException(nameof(dateTime));
var dateTimeMatch = ISO8601Matcher.Match(dateTime);
Expand Down Expand Up @@ -102,7 +103,7 @@ public WikibaseTime(string dateTime, int before, int after, int timeZone, Wikiba
/// <summary>
/// URI identifying the calendar model.
/// </summary>
public string CalendarModel { get; }
public WikibaseUri CalendarModel { get; }

public string ToIso8601UtcString()
{
Expand Down
111 changes: 111 additions & 0 deletions WikiClientLibrary/Wikibase/WikibaseUri.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Text;
using Newtonsoft.Json;

namespace WikiClientLibrary.Wikibase
{
/// <summary>
/// An atomic instance of URI used in Wikibase.
/// </summary>
[JsonObject(ItemConverterType = typeof(WikibaseUriJsonConverter))]
public sealed class WikibaseUri : IEquatable<WikibaseUri>
{

private static readonly ConcurrentDictionary<string, WeakReference<WikibaseUri>> cacheDict =
new ConcurrentDictionary<string, WeakReference<WikibaseUri>>();

public static WikibaseUri Get(string uri)
{
if (uri == null) throw new ArgumentNullException(nameof(uri));
WikibaseUri inst = null;
// Fast route
if (cacheDict.TryGetValue(uri, out var r) && r.TryGetTarget(out inst))
return inst;
// Slow route
cacheDict.AddOrUpdate(uri,
u => new WeakReference<WikibaseUri>(inst = new WikibaseUri(u)),
(u, r0) =>
{
if (!r0.TryGetTarget(out inst))
{
inst = new WikibaseUri(u);
return new WeakReference<WikibaseUri>(inst);
}
return r0;
});
return inst;
}

private WikibaseUri(string uri)
{
Uri = uri ?? throw new ArgumentNullException(nameof(uri));
}

public string Uri { get; }

/// <inheritdoc />
public override string ToString() => Uri;

/// <inheritdoc />
public bool Equals(WikibaseUri other)
{
Debug.Assert(ReferenceEquals(this, other) == (this.Uri == other.Uri));
return ReferenceEquals(this, other);
}

/// <inheritdoc />
public override bool Equals(object obj)
{
#if DEBUG
if (obj is WikibaseUri other)
Debug.Assert(ReferenceEquals(this, other) == (this.Uri == other.Uri));
#endif
return ReferenceEquals(this, obj);
}

/// <inheritdoc />
public override int GetHashCode()
{
return Uri.GetHashCode();
}

public static bool operator ==(WikibaseUri left, WikibaseUri right)
{
return Equals(left, right);
}

public static bool operator !=(WikibaseUri left, WikibaseUri right)
{
return !Equals(left, right);
}
}

internal class WikibaseUriJsonConverter : JsonConverter
{
/// <inheritdoc />
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var obj = (WikibaseUri) value;
writer.WriteValue(obj.Uri);
}

/// <inheritdoc />
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType != JsonToken.String) throw new JsonException("Expect string value.");
var uri = (string) reader.Value;
return WikibaseUri.Get(uri);
}

/// <inheritdoc />
public override bool CanConvert(Type objectType)
{
return objectType == typeof(WikibaseUri);
}
}

}

0 comments on commit 94ea9b2

Please sign in to comment.