public static void AddChanges(this ICollection <DocumentsChanges> docChanges, KeyValuePair <string, RavenJToken> kvp, RavenJToken token, string fieldName) { var changes = new DocumentsChanges { FieldNewType = kvp.Value.Type.ToString(), FieldOldType = token.Type.ToString(), FieldNewValue = kvp.Value.ToString(), FieldOldValue = token.ToString(), Change = DocumentsChanges.ChangeType.FieldChanged, FieldName = fieldName }; docChanges.Add(changes); }
internal virtual void AddForCloning(string key, RavenJToken token) { // kept virtual (as opposed to abstract) to waive the new for implementing this in RavenJValue }
internal static U Convert <U>(this RavenJToken token, bool cast) { if (cast) { // HACK return((U)(object)token); } if (token == null || token.Type == JTokenType.Null) { return(default(U)); } var value = token as RavenJValue; if (value == null) { throw new InvalidCastException("Cannot cast {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, token.GetType(), typeof(U))); } if (value.Value is U) { return((U)value.Value); } Type targetType = typeof(U); if (targetType.IsGenericType() && targetType.GetGenericTypeDefinition() == typeof(Nullable <>)) { if (value.Value == null) { return(default(U)); } targetType = Nullable.GetUnderlyingType(targetType); } if (targetType == typeof(Guid)) { if (value.Value == null) { return(default(U)); } return((U)(object)new Guid(value.Value.ToString())); } if (targetType == typeof(string)) { if (value.Value == null) { return(default(U)); } return((U)(object)value.Value.ToString()); } if (targetType == typeof(DateTime)) { var s = value.Value as string; if (s != null) { DateTime dateTime; if (DateTime.TryParseExact(s, Default.DateTimeFormatsToRead, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out dateTime)) { return((U)(object)dateTime); } dateTime = RavenJsonTextReader.ParseDateMicrosoft(s); return((U)(object)dateTime); } if (value.Value is DateTimeOffset) { return((U)(object)((DateTimeOffset)value.Value).UtcDateTime); } } if (targetType == typeof(DateTimeOffset)) { var s = value.Value as string; if (s != null) { DateTimeOffset dateTimeOffset; if (DateTimeOffset.TryParseExact(s, Default.DateTimeFormatsToRead, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out dateTimeOffset)) { return((U)(object)dateTimeOffset); } return(default(U)); } if (value.Value is DateTime) { return((U)(object)(new DateTimeOffset((DateTime)value.Value))); } } if (targetType == typeof(byte[]) && value.Value is string) { return((U)(object)System.Convert.FromBase64String((string)value.Value)); } if (value.Value == null && typeof(U).IsValueType) { throw new InvalidOperationException("value.Value == null and conversion target type is not nullable"); } try { return((U)System.Convert.ChangeType(value.Value, targetType, CultureInfo.InvariantCulture)); } catch (Exception e) { if (value.Value != null) { throw new InvalidOperationException(string.Format("Unable to find suitable conversion for {0} since it is not predefined and does not implement IConvertible. ", value.Value.GetType()), e); } throw new InvalidOperationException(string.Format("Unable to find suitable conversion for {0} since it is not predefined ", value), e); } }
public static int GetDeepHashCode(RavenJToken t) { return(t == null ? 0 : t.GetDeepHashCode()); }
internal virtual bool DeepEquals(RavenJToken other) { if (other == null) { return(false); } if (Type != other.Type) { return(false); } var otherStack = new Stack <RavenJToken>(); var thisStack = new Stack <RavenJToken>(); thisStack.Push(this); otherStack.Push(other); while (otherStack.Count > 0) { var curOtherReader = otherStack.Pop(); var curThisReader = thisStack.Pop(); if (curOtherReader == null && curThisReader == null) { continue; // shouldn't happen, but we got an error report from a user about this } if (curOtherReader == null || curThisReader == null) { return(false); } if (curThisReader.Type == curOtherReader.Type) { switch (curOtherReader.Type) { case JTokenType.Array: var selfArray = (RavenJArray)curThisReader; var otherArray = (RavenJArray)curOtherReader; if (selfArray.Length != otherArray.Length) { return(false); } for (int i = 0; i < selfArray.Length; i++) { thisStack.Push(selfArray[i]); otherStack.Push(otherArray[i]); } break; case JTokenType.Object: var selfObj = (RavenJObject)curThisReader; var otherObj = (RavenJObject)curOtherReader; if (selfObj.Count != otherObj.Count) { return(false); } foreach (var kvp in selfObj.Properties) { RavenJToken token; if (otherObj.TryGetValue(kvp.Key, out token) == false) { return(false); } if (kvp.Value == null) { if (token != null && token.Type != JTokenType.Null) { return(false); } continue; } switch (kvp.Value.Type) { case JTokenType.Array: case JTokenType.Object: otherStack.Push(token); thisStack.Push(kvp.Value); break; case JTokenType.Bytes: var bytes = kvp.Value.Value <byte[]>(); byte[] tokenBytes = token.Type == JTokenType.String ? Convert.FromBase64String(token.Value <string>()) : token.Value <byte[]>(); if (tokenBytes == null) { return(false); } if (bytes.Length != tokenBytes.Length) { return(false); } if (tokenBytes.Where((t, i) => t != bytes[i]).Any()) { return(false); } break; default: if (!kvp.Value.DeepEquals(token)) { return(false); } break; } } break; default: if (!curOtherReader.DeepEquals(curThisReader)) { return(false); } break; } } else { switch (curThisReader.Type) { case JTokenType.Guid: if (curOtherReader.Type != JTokenType.String) { return(false); } if (curThisReader.Value <string>() != curOtherReader.Value <string>()) { return(false); } break; default: return(false); } } } return(true); }
internal abstract bool DeepEquals(RavenJToken node);
/// <summary> /// Compares the values of two tokens, including the values of all descendant tokens. /// </summary> /// <param name="t1">The first <see cref="RavenJToken"/> to compare.</param> /// <param name="t2">The second <see cref="RavenJToken"/> to compare.</param> /// <returns>true if the tokens are equal; otherwise false.</returns> public static bool DeepEquals(RavenJToken t1, RavenJToken t2) { return(t1 == t2 || (t1 != null && t2 != null && t1.DeepEquals(t2))); }
internal virtual bool DeepEquals(RavenJToken other) { return(DeepEquals(other, (List <DocumentsChanges>)null)); }
internal virtual bool DeepEquals(RavenJToken other, List <DocumentsChanges> docChanges) { if (other == null) { return(false); } if (Type != other.Type) { return(false); } var curType = JTokenType.None; var fieldName = string.Empty; var otherStack = new Stack <RavenJToken>(); var thisStack = new Stack <RavenJToken>(); var fieldNameStack = new Stack <string>(); var isEqual = true; thisStack.Push(this); otherStack.Push(other); while (otherStack.Count > 0) { var curOtherReader = otherStack.Pop(); var curThisReader = thisStack.Pop(); string fieldArrName = string.Empty; if (fieldNameStack.Count > 0) { fieldArrName = fieldNameStack.Pop(); fieldName = fieldArrName; } if (curOtherReader == null && curThisReader == null) { continue; // shouldn't happen, but we got an error report from a user about this } if (curOtherReader == null || curThisReader == null) { return(false); } if (curThisReader.Type == curOtherReader.Type) { switch (curOtherReader.Type) { case JTokenType.Array: var selfArray = (RavenJArray)curThisReader; var otherArray = (RavenJArray)curOtherReader; curType = JTokenType.Array; if (selfArray.Length != otherArray.Length) { if (docChanges == null) { return(false); } isEqual = docChanges.CompareRavenJArrayData(selfArray, otherArray, fieldArrName); } else { for (var i = 0; i < selfArray.Length; i++) { thisStack.Push(selfArray[i]); otherStack.Push(otherArray[i]); fieldNameStack.Push(fieldName); } } break; case JTokenType.Object: var selfObj = (RavenJObject)curThisReader; var otherObj = (RavenJObject)curOtherReader; if (selfObj.Count != otherObj.Count) { curType = JTokenType.Object; if (docChanges == null) { return(false); } isEqual = docChanges.CompareDifferentLengthRavenJObjectData(otherObj, selfObj, fieldName); } else { var prevType = curType; curType = JTokenType.Object; var origFieldName = fieldName; foreach (var kvp in selfObj.Properties) { if (prevType == JTokenType.Object) { fieldName = origFieldName + "." + kvp.Key; } else { fieldName = kvp.Key; } RavenJToken token; if (otherObj.TryGetValue(kvp.Key, out token) == false) { if (docChanges == null) { return(false); } docChanges.AddChanges(DocumentsChanges.ChangeType.RemovedField); isEqual = false; } if (kvp.Value == null) { if (token != null && token.Type != JTokenType.Null) { if (docChanges == null) { return(false); } docChanges.AddChanges(DocumentsChanges.ChangeType.NewField); isEqual = false; } continue; } switch (kvp.Value.Type) { case JTokenType.Array: case JTokenType.Object: otherStack.Push(token); thisStack.Push(kvp.Value); fieldNameStack.Push(fieldName); break; case JTokenType.Bytes: var bytes = kvp.Value.Value <byte[]>(); var tokenBytes = token.Type == JTokenType.String ? Convert.FromBase64String(token.Value <string>()) : token.Value <byte[]>(); if (tokenBytes == null) { return(false); } if (bytes.Length != tokenBytes.Length) { return(false); } if (tokenBytes.Where((t, i) => t != bytes[i]).Any()) { return(false); } break; default: if (!kvp.Value.DeepEquals(token)) { if (docChanges == null) { return(false); } docChanges.AddChanges(kvp, token, fieldName); isEqual = false; } break; } } } break; default: curType = curThisReader.Type; if (!curOtherReader.DeepEquals(curThisReader)) { if (docChanges == null) { return(false); } docChanges.AddChanges(curThisReader, curOtherReader, fieldName); isEqual = false; } break; } } else { curType = curThisReader.Type; switch (curThisReader.Type) { case JTokenType.Guid: if (curOtherReader.Type != JTokenType.String) { return(false); } if (curThisReader.Value <string>() != curOtherReader.Value <string>()) { return(false); } break; default: return(false); } } } return(isEqual); }
/// <summary> /// Initializes a new instance of the <see cref="RavenJTokenReader"/> class. /// </summary> /// <param name="token">The token to read from.</param> public RavenJTokenReader(RavenJToken token) { _root = token; }
/// <summary> /// Compares the values of two tokens, including the values of all descendant tokens. /// </summary> /// <param name="t1">The first <see cref="RavenJToken" /> to compare.</param> /// <param name="t2">The second <see cref="RavenJToken" /> to compare.</param> /// <param name="difference"> changes description</param> /// <returns>true if the tokens are equal; otherwise false.</returns> public static bool DeepEquals(RavenJToken t1, RavenJToken t2, List <DocumentsChanges> difference) { return(t1 == t2 || (t1 != null && t2 != null && t1.DeepEquals(t2, difference))); }
public static U Value <U>(this RavenJToken value) { return(value.Convert <U>()); }
internal static U Convert <U>(this RavenJToken token, bool cast) { if (cast) { // HACK return((U)(object)token); } if (token == null) { return(default(U)); } var value = token as RavenJValue; if (value == null) { throw new InvalidCastException("Cannot cast {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, token.GetType(), typeof(U))); } if (value.Value is U) { return((U)value.Value); } Type targetType = typeof(U); if (targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Nullable <>)) { if (value.Value == null) { return(default(U)); } targetType = Nullable.GetUnderlyingType(targetType); } if (targetType == typeof(Guid)) { if (value.Value == null) { return(default(U)); } return((U)(object)new Guid(value.Value.ToString())); } if (targetType == typeof(string)) { if (value.Value == null) { return(default(U)); } return((U)(object)value.Value.ToString()); } if (targetType == typeof(DateTime) && value.Value is string) { DateTime dateTime; if (DateTime.TryParseExact((string)value.Value, Default.DateTimeFormatsToRead, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out dateTime)) { return((U)(object)dateTime); } dateTime = RavenJsonTextReader.ParseDateMicrosoft((string)value.Value); return((U)(object)dateTime); } return((U)System.Convert.ChangeType(value.Value, targetType, CultureInfo.InvariantCulture)); }
internal virtual bool DeepEquals(RavenJToken other) { if (other == null) { return(false); } if (Type != other.Type) { return(false); } var otherStack = new Stack <RavenJToken>(); var thisStack = new Stack <RavenJToken>(); thisStack.Push(this); otherStack.Push(other); while (otherStack.Count > 0) { var curOtherReader = otherStack.Pop(); var curThisReader = thisStack.Pop(); if (curThisReader.Type != curOtherReader.Type) { return(false); } if (curOtherReader.Type == JTokenType.Array) { var selfArray = (RavenJArray)curThisReader; var otherArray = (RavenJArray)curOtherReader; if (selfArray.Length != otherArray.Length) { return(false); } for (int i = 0; i < selfArray.Length; i++) { thisStack.Push(selfArray[i]); otherStack.Push(otherArray[i]); } } else if (curOtherReader.Type == JTokenType.Object) { var selfObj = (RavenJObject)curThisReader; var otherObj = (RavenJObject)curOtherReader; if (selfObj.Count != otherObj.Count) { return(false); } foreach (var kvp in selfObj.Properties) { RavenJToken token; if (otherObj.TryGetValue(kvp.Key, out token) == false) { return(false); } otherStack.Push(token); thisStack.Push(kvp.Value); } } else // value { if (!curOtherReader.DeepEquals(curThisReader)) { return(false); } } } return(true); }
public static void AddChanges(this ICollection <DocumentsChanges> docChanges, RavenJToken curThisReader, RavenJToken curOtherReader, string fieldName) { var changes = new DocumentsChanges { FieldNewType = curThisReader.Type.ToString(), FieldOldType = curOtherReader.Type.ToString(), FieldNewValue = curThisReader.ToString(), FieldOldValue = curOtherReader.ToString(), Change = DocumentsChanges.ChangeType.FieldChanged, FieldName = fieldName }; docChanges.Add(changes); }
internal override bool DeepEquals(RavenJToken node) { var other = node as RavenJValue; return(other != null && ValuesEquals(this, other)); }
internal RavenJToken Evaluate(RavenJToken root, bool errorWhenNoMatch) { var current = root; foreach (object part in Parts) { var propertyName = part as string; if (propertyName != null) { var o = current as RavenJObject; if (o != null) { current = o[propertyName]; if (current == null && errorWhenNoMatch) { throw new Exception("Property '{0}' does not exist on RavenJObject.".FormatWith(CultureInfo.InvariantCulture, propertyName)); } } else { var array = current as RavenJArray; if (array != null) { switch (propertyName) { case "Count": case "count": case "Length": case "length": current = array.Length; break; default: if (errorWhenNoMatch) { throw new Exception("Property '{0}' not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, propertyName, current.GetType().Name)); } break; } continue; } if (errorWhenNoMatch) { throw new Exception("Property '{0}' not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, propertyName, current.GetType().Name)); } return(null); } } else { var index = (int)part; var a = current as RavenJArray; if (a != null) { if (a.Length <= index) { if (errorWhenNoMatch) { throw new IndexOutOfRangeException("Index {0} outside the bounds of RavenJArray.".FormatWith(CultureInfo.InvariantCulture, index)); } return(null); } current = a[index]; } else { if (errorWhenNoMatch) { throw new Exception("Index {0} not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, index, current.GetType().Name)); } return(null); } } } return(current); }
internal RavenJToken Evaluate(RavenJToken root, bool errorWhenNoMatch, bool createSnapshots = false) { var current = root; foreach (object part in Parts) { var propertyName = part as string; if (propertyName != null) { var o = current as RavenJObject; if (o != null) { if (createSnapshots) { switch (propertyName) { case "$Values": current = new RavenJArray(o.Values()); break; case "$Keys": current = new RavenJArray(o.Keys); break; default: var newProp = o[propertyName]; if (newProp != null) { newProp.EnsureCannotBeChangeAndEnableSnapshotting(); newProp = newProp.CreateSnapshot(); current = o[propertyName] = newProp; } else { current = null; } break; } } else { switch (propertyName) { case "$Values": current = new RavenJArray(o.Values()); break; case "$Keys": current = new RavenJArray(o.Keys); break; default: current = o[propertyName]; break; } } if (current == null && errorWhenNoMatch) { throw new Exception("Property '{0}' does not exist on RavenJObject.".FormatWith(CultureInfo.InvariantCulture, propertyName)); } } else { var array = current as RavenJArray; if (array != null) { switch (propertyName) { case "Count": case "count": case "Length": case "length": current = array.Length; break; default: if (errorWhenNoMatch) { throw new Exception("Property '{0}' not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, propertyName, current.GetType().Name)); } break; } continue; } if (errorWhenNoMatch) { throw new Exception("Property '{0}' not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, propertyName, current.GetType().Name)); } return(null); } } else { var index = (int)part; var a = current as RavenJArray; if (a != null) { if (a.Length <= index) { if (errorWhenNoMatch) { throw new IndexOutOfRangeException("Index {0} outside the bounds of RavenJArray.".FormatWith(CultureInfo.InvariantCulture, index)); } return(null); } current = a[index]; } else { if (errorWhenNoMatch) { throw new Exception("Index {0} not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, index, current.GetType().Name)); } return(null); } } } return(current); }