using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using UnityEngine; namespace UniGLTF.JsonSchema { /// /// 型が確定する前にパースして値を集める /// public class JsonSchemaSource { public FileInfo FilePath; public string JsonPath; public static (string, string) SplitParent(string jsonPath) { var splitted = jsonPath.Split('.'); return (String.Join(".", splitted.Take(splitted.Length - 1)), splitted[splitted.Length - 1]); } public void AddJsonPath(string jsonPath, JsonSchemaSource source) { var (parent, child) = SplitParent(jsonPath); var parentSchema = this.Get(parent); var materialExtensions = parentSchema; source.JsonPath = jsonPath; materialExtensions.AddProperty(child, source); } public JsonSchemaSource Get(string jsonPath) { if (JsonPath == jsonPath) { return this; } if (jsonPath.StartsWith(JsonPath)) { foreach (var child in Children()) { var found = child.Get(jsonPath); if (found != null) { return found; } } } return null; } public JsonSchemaType type; public string title; public string description; public string gltfDetail; public JsonSchemaSource baseSchema; #region Number public double? minimum; public bool exclusiveMinimum; public double? maximum; public double? multipleOf; #endregion #region String public string pattern; #endregion #region Object List> m_properties; public JsonSchemaSource GetProperty(string name, bool remove = false) { if (m_properties is null) { return null; } for (int i = 0; i < m_properties.Count; ++i) { if (m_properties[i].Key == name) { var found = m_properties[i].Value; if (remove) { m_properties.RemoveAt(i); } return found; } } return null; } public void AddProperty(string name, JsonSchemaSource prop) { if (name is null) { throw new ArgumentNullException(); } if (prop.type == JsonSchemaType.Unknown) { if (name == "extensions" || name == "extras") { // return; prop.type = JsonSchemaType.Object; } else { throw new NotImplementedException(); } } if (m_properties is null) { m_properties = new List>(); } if (m_properties.Any(x => x.Key == name)) { throw new ArgumentException($"{name}: is already exist"); } m_properties.Add(new KeyValuePair(name, prop)); } public IEnumerable> EnumerateProperties() { if (m_properties != null) { foreach (var kv in m_properties) { yield return kv; } } } public string[] required; #endregion #region Dictionary public JsonSchemaSource additionalProperties; public int? minProperties; #endregion #region Array public JsonSchemaSource items; public int? minItems; public int? maxItems; public bool? uniqueItems; #endregion #region Enum public KeyValuePair[] enumValues; public string[] enumStringValues; #endregion public IEnumerable Children() { if (m_properties != null) { foreach (var kv in m_properties) { yield return kv.Value; } } else if (additionalProperties != null) { yield return additionalProperties; } else if (items != null) { if (type != JsonSchemaType.Array) { throw new NotImplementedException(); } yield return items; } } public IEnumerable Traverse() { yield return this; if (m_properties != null) { foreach (var kv in m_properties) { foreach (var x in kv.Value.Traverse()) { yield return x; } } } else if (additionalProperties != null) { foreach (var x in additionalProperties.Traverse()) { yield return x; } } else if (items != null) { foreach (var x in items.Traverse()) { yield return x; } } } public Schemas.JsonSchemaBase Create(bool useUpperCamelName, string rootName = default) { // if (baseSchema != null) // { // baseSchema.MergeTo(this); // } if (baseSchema != null) { if (type == JsonSchemaType.Unknown) { type = baseSchema.type; } } switch (type) { case JsonSchemaType.Object: if (this.JsonPath.EndsWith(".extensions") || this.JsonPath.EndsWith(".extras")) { return new Schemas.ExtensionJsonSchema(this); } if ((m_properties != null && m_properties.Any()) || additionalProperties is null) { var obj = new Schemas.ObjectJsonSchema(this, useUpperCamelName); if (!string.IsNullOrEmpty(rootName)) { obj.Title = rootName; } return obj; } else { return new Schemas.DictionaryJsonSchema(this, useUpperCamelName); } case JsonSchemaType.Array: return new Schemas.ArrayJsonSchema(this, useUpperCamelName); case JsonSchemaType.Boolean: return new Schemas.BoolJsonSchema(this); case JsonSchemaType.String: return new Schemas.StringJsonSchema(this); case JsonSchemaType.Number: return new Schemas.NumberJsonSchema(this); case JsonSchemaType.Integer: return new Schemas.IntegerJsonSchema(this); case JsonSchemaType.Enum: return new Schemas.EnumJsonSchema(this); case JsonSchemaType.EnumString: return new Schemas.EnumStringJsonSchema(this); default: return null; } } public void Dump(StringBuilder sb, string indent = "") { sb.AppendLine($"{JsonPath}: {type}"); foreach (var x in Children()) { x.Dump(sb, indent + " "); } } public string Dump() { var sb = new StringBuilder(); Dump(sb); return sb.ToString(); } } }