public static bool FindSchema(Action <JSchema> setSchema, JSchema schema, Uri rootSchemaId, Uri reference, JSchemaReader schemaReader, ref JSchemaDiscovery discovery) { // todo, better way to get parts from Uri string[] parts = reference.ToString().Split('/'); bool resolvedSchema; if (parts.Length > 0 && (parts[0] == "#" || parts[0] == rootSchemaId + "#")) { schemaReader._schemaStack.Push(schema); parts = parts.Skip(1).ToArray(); object current = schema; foreach (string part in parts) { string unescapedPart = UnescapeReference(part); if (current is JSchema) { JSchema s = current as JSchema; schemaReader._schemaStack.Push(s); switch (unescapedPart) { case Constants.PropertyNames.Properties: current = s._properties; break; case Constants.PropertyNames.Items: current = s._items; break; case Constants.PropertyNames.AdditionalProperties: current = s.AdditionalProperties; break; case Constants.PropertyNames.AdditionalItems: current = s.AdditionalItems; break; case Constants.PropertyNames.Not: current = s.Not; break; case Constants.PropertyNames.OneOf: current = s._oneOf; break; case Constants.PropertyNames.AllOf: current = s._allOf; break; case Constants.PropertyNames.AnyOf: current = s._anyOf; break; case Constants.PropertyNames.Enum: current = s._enum; break; case Constants.PropertyNames.PatternProperties: current = s._patternProperties; break; case Constants.PropertyNames.Dependencies: current = s._dependencies; break; default: JToken t; s.ExtensionData.TryGetValue(unescapedPart, out t); current = t; break; } } else if (current is JToken) { JToken resolvedToken; JToken t = (JToken)current; if (t is JObject) { resolvedToken = t[unescapedPart]; } else if (t is JArray || t is JConstructor) { int index; if (int.TryParse(unescapedPart, NumberStyles.None, CultureInfo.InvariantCulture, out index)) { if (index > t.Count() || index < 0) { resolvedToken = null; } else { resolvedToken = t[index]; } } else { resolvedToken = null; } } else { resolvedToken = null; } if (resolvedToken != null) { JSchemaAnnotation annotation = resolvedToken.Annotation <JSchemaAnnotation>(); if (annotation != null) { current = annotation.Schema; } else { current = resolvedToken; } } else { current = null; } } else if (current is IDictionary) { IDictionary d = (IDictionary)current; current = d[unescapedPart]; } else if (current is IList) { IList l = (IList)current; int index; if (int.TryParse(unescapedPart, NumberStyles.None, CultureInfo.InvariantCulture, out index)) { if (index > l.Count || index < 0) { current = null; } else { current = l[index]; } } else { current = null; } } else { break; } } if (current is JToken) { JToken t = (JToken)current; JSchemaAnnotation annotation = t.Annotation <JSchemaAnnotation>(); if (annotation != null) { setSchema(annotation.Schema); resolvedSchema = true; } else { JSchema inlineSchema = schemaReader.ReadInlineSchema(setSchema, t); string path = reference.OriginalString; if (path.StartsWith("#/", StringComparison.Ordinal)) { path = path.Substring(2, path.Length - 2); } discovery.Discover(inlineSchema, rootSchemaId, path); resolvedSchema = true; } } else { JSchema s = current as JSchema; if (s != null) { setSchema(s); resolvedSchema = true; // schema is a reference schema and needs to be resolved if (s.Reference != null) { schemaReader.AddDeferedSchema(setSchema, s); } } else { resolvedSchema = false; } } schemaReader._schemaStack.Clear(); } else { discovery.Discover(schema, null); Uri resolvedReference = ResolveSchemaId(rootSchemaId, reference); // default Uri comparison ignores fragments // use firstordefault to handle duplicates KnownSchema knownSchema = discovery.KnownSchemas.FirstOrDefault(s => s.Id.OriginalString.TrimEnd('#') == resolvedReference.OriginalString.TrimEnd('#')); if (knownSchema != null) { resolvedSchema = true; setSchema(knownSchema.Schema); } else { int hashIndex = resolvedReference.OriginalString.IndexOf('#'); if (hashIndex != -1) { Uri path = new Uri(resolvedReference.OriginalString.Substring(0, hashIndex), UriKind.RelativeOrAbsolute); Uri fragment = new Uri(resolvedReference.OriginalString.Substring(hashIndex), UriKind.RelativeOrAbsolute); // default Uri comparison ignores fragments // there could be duplicated ids. use FirstOrDefault to get first schema with an id knownSchema = discovery.KnownSchemas.FirstOrDefault(s => s.Id.OriginalString.TrimEnd('#') == path.OriginalString); if (knownSchema != null) { // don't attempt to find a schema in the same schema again // avoids stackoverflow if (knownSchema.Schema != schema || !UriComparer.Instance.Equals(rootSchemaId, path) || !UriComparer.Instance.Equals(reference, fragment)) { resolvedSchema = FindSchema(setSchema, knownSchema.Schema, path, fragment, schemaReader, ref discovery); } else { resolvedSchema = false; } } else { resolvedSchema = false; } } else { resolvedSchema = false; } } } return(resolvedSchema); }
public static bool FindSchema(Action<JSchema> setSchema, JSchema schema, Uri rootSchemaId, Uri reference, JSchemaReader schemaReader) { // todo, better way to get parts from Uri string[] parts = reference.ToString().Split('/'); bool resolvedSchema; if (parts.Length > 0 && (parts[0] == "#" || parts[0] == rootSchemaId + "#")) { schemaReader._schemaStack.Push(schema); parts = parts.Skip(1).ToArray(); object current = schema; foreach (string part in parts) { string unescapedPart = UnescapeReference(part); if (current is JSchema) { JSchema s = current as JSchema; schemaReader._schemaStack.Push(s); switch (unescapedPart) { case Constants.PropertyNames.Properties: current = s._properties; break; case Constants.PropertyNames.Items: current = s._items; break; case Constants.PropertyNames.AdditionalProperties: current = s.AdditionalProperties; break; case Constants.PropertyNames.AdditionalItems: current = s.AdditionalItems; break; case Constants.PropertyNames.Not: current = s.Not; break; case Constants.PropertyNames.OneOf: current = s._oneOf; break; case Constants.PropertyNames.AllOf: current = s._allOf; break; case Constants.PropertyNames.AnyOf: current = s._anyOf; break; case Constants.PropertyNames.Enum: current = s._enum; break; case Constants.PropertyNames.PatternProperties: current = s._patternProperties; break; case Constants.PropertyNames.Dependencies: current = s._dependencies; break; default: JToken t; s.ExtensionData.TryGetValue(unescapedPart, out t); current = t; break; } } else if (current is JToken) { JToken resolvedToken; JToken t = (JToken)current; if (t is JObject) { resolvedToken = t[unescapedPart]; } else if (t is JArray || t is JConstructor) { int index; if (int.TryParse(unescapedPart, NumberStyles.None, CultureInfo.InvariantCulture, out index)) { if (index > t.Count() || index < 0) resolvedToken = null; else resolvedToken = t[index]; } else { resolvedToken = null; } } else { resolvedToken = null; } if (resolvedToken != null) { JSchemaAnnotation annotation = resolvedToken.Annotation<JSchemaAnnotation>(); if (annotation != null) current = annotation.Schema; else current = resolvedToken; } else { current = null; } } else if (current is IDictionary) { IDictionary d = (IDictionary)current; current = d[unescapedPart]; } else if (current is IList) { IList l = (IList)current; int index; if (int.TryParse(unescapedPart, NumberStyles.None, CultureInfo.InvariantCulture, out index)) { if (index > l.Count || index < 0) current = null; else current = l[index]; } else { current = null; } } else { break; } } if (current is JToken) { JToken t = (JToken)current; JSchemaAnnotation annotation = t.Annotation<JSchemaAnnotation>(); if (annotation != null) { setSchema(annotation.Schema); resolvedSchema = true; } else { schemaReader.ReadInlineSchema(setSchema, t); resolvedSchema = true; } } else { JSchema s = current as JSchema; if (s != null) { setSchema(s); resolvedSchema = true; // schema is a reference schema and needs to be resolved if (s.Reference != null) schemaReader.AddDeferedSchema(setSchema, s); } else { resolvedSchema = false; } } schemaReader._schemaStack.Clear(); } else { JSchemaDiscovery discovery = new JSchemaDiscovery(); discovery.Discover(schema, null); Uri resolvedReference = ResolveSchemaId(rootSchemaId, reference); // default Uri comparison ignores fragments KnownSchema knownSchema = discovery.KnownSchemas.SingleOrDefault(s => s.Id.OriginalString.TrimEnd('#') == resolvedReference.OriginalString.TrimEnd('#')); if (knownSchema != null) { resolvedSchema = true; setSchema(knownSchema.Schema); } else { int hashIndex = resolvedReference.OriginalString.IndexOf('#'); if (hashIndex != -1) { Uri path = new Uri(resolvedReference.OriginalString.Substring(0, hashIndex), UriKind.RelativeOrAbsolute); Uri fragment = new Uri(resolvedReference.OriginalString.Substring(hashIndex), UriKind.RelativeOrAbsolute); // default Uri comparison ignores fragments knownSchema = discovery.KnownSchemas.SingleOrDefault(s => s.Id.OriginalString.TrimEnd('#') == path.OriginalString); if (knownSchema != null) { // don't attempt to find a schema in the same schema again // avoids stackoverflow if (knownSchema.Schema != schema || !UriComparer.Instance.Equals(rootSchemaId, path) || !UriComparer.Instance.Equals(reference, fragment)) { resolvedSchema = FindSchema(setSchema, knownSchema.Schema, path, fragment, schemaReader); } else { resolvedSchema = false; } } else { resolvedSchema = false; } } else { resolvedSchema = false; } } } return resolvedSchema; }
public static bool FindSchema(Action <JSchema> setSchema, JSchema schema, Uri rootSchemaId, Uri reference, JSchemaReader schemaReader) { // todo, better way to get parts from Uri string[] parts = reference.ToString().Split('/'); bool resolvedSchema; if (parts.Length > 0 && (parts[0] == "#" || parts[0] == rootSchemaId + "#")) { schemaReader._schemaStack.Push(schema); parts = parts.Skip(1).ToArray(); object current = schema; foreach (string part in parts) { string unescapedPart = UnescapeReference(part); if (current is JSchema) { JSchema s = current as JSchema; schemaReader._schemaStack.Push(s); switch (unescapedPart) { case Constants.PropertyNames.Properties: current = s._properties; break; case Constants.PropertyNames.Items: current = s._items; break; case Constants.PropertyNames.AdditionalProperties: current = s.AdditionalProperties; break; case Constants.PropertyNames.AdditionalItems: current = s.AdditionalItems; break; case Constants.PropertyNames.Not: current = s.Not; break; case Constants.PropertyNames.OneOf: current = s._oneOf; break; case Constants.PropertyNames.AllOf: current = s._allOf; break; case Constants.PropertyNames.AnyOf: current = s._anyOf; break; case Constants.PropertyNames.Enum: current = s._enum; break; case Constants.PropertyNames.PatternProperties: current = s._patternProperties; break; default: JToken t; s.ExtensionData.TryGetValue(unescapedPart, out t); current = t; break; } } else if (current is JToken) { JToken resolvedToken; JToken t = (JToken)current; if (t is JObject) { resolvedToken = t[unescapedPart]; } else if (t is JArray || t is JConstructor) { int index; if (int.TryParse(unescapedPart, NumberStyles.None, CultureInfo.InvariantCulture, out index)) { if (index > t.Count() || index < 0) { resolvedToken = null; } else { resolvedToken = t[index]; } } else { resolvedToken = null; } } else { resolvedToken = null; } if (resolvedToken != null) { JSchemaAnnotation annotation = resolvedToken.Annotation <JSchemaAnnotation>(); if (annotation != null) { current = annotation.Schema; } else { current = resolvedToken; } } else { current = null; } } else if (current is IDictionary) { IDictionary d = (IDictionary)current; current = d[unescapedPart]; } else if (current is IList) { IList l = (IList)current; int index; if (int.TryParse(unescapedPart, NumberStyles.None, CultureInfo.InvariantCulture, out index)) { if (index > l.Count || index < 0) { current = null; } else { current = l[index]; } } else { current = null; } } else { break; } } if (current is JToken) { JToken t = (JToken)current; JSchemaAnnotation annotation = t.Annotation <JSchemaAnnotation>(); if (annotation != null) { setSchema(annotation.Schema); resolvedSchema = true; } else { schemaReader.ReadInlineSchema(setSchema, t); resolvedSchema = true; } } else { var s = current as JSchema; if (s != null) { setSchema(s); resolvedSchema = true; } else { resolvedSchema = false; } } schemaReader._schemaStack.Clear(); } else { JSchemaDiscovery discovery = new JSchemaDiscovery(); discovery.Discover(schema, null); Uri resolvedReference = ResolveSchemaId(rootSchemaId, reference); // default Uri comparison ignores fragments KnownSchema knownSchema = discovery.KnownSchemas.SingleOrDefault(s => s.Id.OriginalString.TrimEnd('#') == resolvedReference.OriginalString.TrimEnd('#')); if (knownSchema != null) { resolvedSchema = true; setSchema(knownSchema.Schema); } else { int hashIndex = resolvedReference.OriginalString.IndexOf('#'); if (hashIndex != -1) { Uri path = new Uri(resolvedReference.OriginalString.Substring(0, hashIndex), UriKind.RelativeOrAbsolute); Uri fragment = new Uri(resolvedReference.OriginalString.Substring(hashIndex), UriKind.RelativeOrAbsolute); // default Uri comparison ignores fragments knownSchema = discovery.KnownSchemas.SingleOrDefault(s => s.Id.OriginalString.TrimEnd('#') == path.OriginalString); if (knownSchema != null) { resolvedSchema = FindSchema(setSchema, knownSchema.Schema, path, fragment, schemaReader); } else { resolvedSchema = false; } } else { resolvedSchema = false; } } } return(resolvedSchema); }
public static bool FindSchema(Action <JSchema> setSchema, JSchema schema, Uri rootSchemaId, Uri reference, JSchemaReader schemaReader, ref JSchemaDiscovery discovery) { // todo, better way to get parts from Uri string[] parts = reference.ToString().Split('/'); bool resolvedSchema; if (parts.Length > 0 && (parts[0] == "#" || parts[0] == rootSchemaId + "#")) { schemaReader._schemaStack.Add(schema); JSchema parent = schema; object current = schema; for (int i = 1; i != parts.Length; ++i) { string unescapedPart = UnescapeReference(parts[i]); JSchema s = current as JSchema; if (s != null) { schemaReader._schemaStack.Add(s); parent = s; current = GetCurrentFromSchema(s, unescapedPart); } else if (current is JToken) { current = GetCurrentFromToken((JToken)current, unescapedPart); } else if (current is IDictionary <string, JSchema> ) { IDictionary <string, JSchema> d = (IDictionary <string, JSchema>)current; JSchema temp; d.TryGetValue(unescapedPart, out temp); current = temp; } else if (current is IList <JSchema> ) { IList <JSchema> l = (IList <JSchema>)current; int index; // if the schema collection is items then implicitly get first item if there is no position validation if (ReferenceEquals(parent._items, l) && !parent.ItemsPositionValidation) { if (l.Count > 0) { current = GetCurrentFromSchema(l[0], unescapedPart); } else { current = null; } } else if (int.TryParse(unescapedPart, NumberStyles.None, CultureInfo.InvariantCulture, out index)) { if (index > l.Count || index < 0) { current = null; } else { current = l[index]; } } else { current = null; } } else { break; } } JToken t = current as JToken; if (t != null) { JSchemaAnnotation annotation = t.Annotation <JSchemaAnnotation>(); if (annotation != null) { setSchema(annotation.Schema); resolvedSchema = true; } else { JSchema inlineSchema = schemaReader.ReadInlineSchema(setSchema, t); string path = reference.OriginalString; if (path.StartsWith("#/", StringComparison.Ordinal)) { path = path.Substring(2, path.Length - 2); } discovery.Discover(inlineSchema, rootSchemaId, path); resolvedSchema = true; } } else { JSchema s = current as JSchema; if (s != null) { setSchema(s); resolvedSchema = true; // schema is a reference schema and needs to be resolved if (s.Reference != null) { schemaReader.AddDeferedSchema(null, setSchema, s); } } else { resolvedSchema = false; } } schemaReader._schemaStack.Clear(); } else { discovery.Discover(schema, null); Uri resolvedReference = ResolveSchemaId(rootSchemaId, reference); // use firstordefault to handle duplicates KnownSchema knownSchema = discovery.KnownSchemas.FirstOrDefault(s => UriComparer.Instance.Equals(s.Id, resolvedReference)); if (knownSchema != null) { resolvedSchema = true; setSchema(knownSchema.Schema); } else { int hashIndex = resolvedReference.OriginalString.IndexOf('#'); if (hashIndex != -1) { Uri path = new Uri(resolvedReference.OriginalString.Substring(0, hashIndex), UriKind.RelativeOrAbsolute); Uri fragment = new Uri(resolvedReference.OriginalString.Substring(hashIndex), UriKind.RelativeOrAbsolute); // there could be duplicated ids. use FirstOrDefault to get first schema with an id knownSchema = discovery.KnownSchemas.FirstOrDefault(s => UriComparer.Instance.Equals(s.Id, path)); if (knownSchema != null) { // don't attempt to find a schema in the same schema again // avoids stackoverflow if (knownSchema.Schema != schema || !UriComparer.Instance.Equals(rootSchemaId, path) || !UriComparer.Instance.Equals(reference, fragment)) { resolvedSchema = FindSchema(setSchema, knownSchema.Schema, path, fragment, schemaReader, ref discovery); } else { resolvedSchema = false; } } else { resolvedSchema = false; } } else { // special case // look in the root schema's definitions for a definition with the same property name and id as reference JToken definitions; if (schema.ExtensionData.TryGetValue(Constants.PropertyNames.Definitions, out definitions)) { JObject definitionsObject = definitions as JObject; if (definitionsObject != null) { JProperty matchingProperty = definitionsObject.Properties().FirstOrDefault(p => TryCompare(p.Name, resolvedReference)); JObject o = matchingProperty?.Value as JObject; if (o != null && TryCompare((string)o["id"], resolvedReference)) { JSchema inlineSchema = schemaReader.ReadInlineSchema(setSchema, o); discovery.Discover(inlineSchema, rootSchemaId, Constants.PropertyNames.Definitions + "/" + resolvedReference.OriginalString); resolvedSchema = true; } else { resolvedSchema = false; } } else { resolvedSchema = false; } } else { resolvedSchema = false; } } } } return(resolvedSchema); }