284 lines
8.2 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEngine;
namespace UniGLTF.JsonSchema
{
/// <summary>
/// 型が確定する前にパースして値を集める
/// </summary>
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<KeyValuePair<string, JsonSchemaSource>> 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<KeyValuePair<string, JsonSchemaSource>>();
}
if (m_properties.Any(x => x.Key == name))
{
throw new ArgumentException($"{name}: is already exist");
}
m_properties.Add(new KeyValuePair<string, JsonSchemaSource>(name, prop));
}
public IEnumerable<KeyValuePair<string, JsonSchemaSource>> 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<string, int>[] enumValues;
public string[] enumStringValues;
#endregion
public IEnumerable<JsonSchemaSource> 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<JsonSchemaSource> 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();
}
}
}