/// <summary> /// Loads a user's schema file /// </summary> internal static TemplateSchema Load(IObjectReader objectReader) { var context = new TemplateContext { CancellationToken = CancellationToken.None, Errors = new TemplateValidationErrors(maxErrors: 10, maxMessageLength: 500), Memory = new TemplateMemory( maxDepth: 50, maxEvents: 1000000, // 1 million maxBytes: 1024 * 1024), // 1 mb TraceWriter = new EmptyTraceWriter(), }; var value = TemplateReader.Read(context, TemplateConstants.TemplateSchema, objectReader, null, Schema, out _); if (context.Errors.Count > 0) { throw new TemplateValidationException(context.Errors); } var mapping = value.AssertMapping(TemplateConstants.TemplateSchema); var schema = new TemplateSchema(mapping); schema.Validate(); return(schema); }
private static IEnumerable <KeyValuePair <String, PropertyValue> > GetMergedProperties( TemplateSchema schema, MappingDefinition mapping) { foreach (var property in mapping.Properties) { yield return(property); } if (!String.IsNullOrEmpty(mapping.Inherits)) { var inherited = schema.GetDefinition(mapping.Inherits) as MappingDefinition; if (!String.IsNullOrEmpty(inherited.Inherits)) { throw new NotSupportedException("Multiple levels of inheritance is not supported"); } foreach (var property in inherited.Properties) { if (!mapping.Properties.ContainsKey(property.Key)) { yield return(property); } } } }
internal override void Validate( TemplateSchema schema, String name) { if (!String.IsNullOrEmpty(Constant) && RequireNonEmpty) { throw new ArgumentException($"Properties '{TemplateConstants.Constant}' and '{TemplateConstants.RequireNonEmpty}' cannot both be set"); } }
internal override void Validate( TemplateSchema schema, String name) { if (String.IsNullOrEmpty(ItemType)) { throw new ArgumentException($"'{name}' does not define '{TemplateConstants.ItemType}'"); } // Lookup item type schema.GetDefinition(ItemType); }
internal override void Validate( TemplateSchema schema, String name) { }
internal abstract void Validate( TemplateSchema schema, String name);
internal override void Validate( TemplateSchema schema, String name) { // Lookup loose key type if (!String.IsNullOrEmpty(LooseKeyType)) { schema.GetDefinition(LooseKeyType); // Lookup loose value type if (!String.IsNullOrEmpty(LooseValueType)) { schema.GetDefinition(LooseValueType); } else { throw new ArgumentException($"Property '{TemplateConstants.LooseKeyType}' is defined but '{TemplateConstants.LooseValueType}' is not defined on '{name}'"); } } // Otherwise validate loose value type not be defined else if (!String.IsNullOrEmpty(LooseValueType)) { throw new ArgumentException($"Property '{TemplateConstants.LooseValueType}' is defined but '{TemplateConstants.LooseKeyType}' is not defined"); } // Lookup each property foreach (var property in Properties) { if (String.IsNullOrEmpty(property.Value.Type)) { throw new ArgumentException($"Type not specified for the '{property.Key}' property on the '{name}' type"); } schema.GetDefinition(property.Value.Type); } if (!String.IsNullOrEmpty(Inherits)) { var inherited = schema.GetDefinition(Inherits); if (inherited.Context.Length > 0) { throw new NotSupportedException($"Property '{TemplateConstants.Context}' is not supported on inhertied definitions"); } if (inherited.DefinitionType != DefinitionType.Mapping) { throw new NotSupportedException($"Expected structure of inherited definition to match. Actual '{inherited.DefinitionType}'"); } var inheritedMapping = inherited as MappingDefinition; if (!String.IsNullOrEmpty(inheritedMapping.Inherits)) { throw new NotSupportedException($"Property '{TemplateConstants.Inherits}' is not supported on inherited definition"); } if (!String.IsNullOrEmpty(inheritedMapping.LooseKeyType)) { throw new NotSupportedException($"Property '{TemplateConstants.LooseKeyType}' is not supported on inherited definition"); } if (!String.IsNullOrEmpty(inheritedMapping.LooseValueType)) { throw new NotSupportedException($"Property '{TemplateConstants.LooseValueType}' is not supported on inherited definition"); } } }
internal override void Validate( TemplateSchema schema, String name) { if (OneOf.Count == 0) { throw new ArgumentException($"'{name}' does not contain any references"); } var foundLooseKeyType = false; var mappingDefinitions = default(List <MappingDefinition>); var sequenceDefinition = default(SequenceDefinition); var nullDefinition = default(NullDefinition); var booleanDefinition = default(BooleanDefinition); var numberDefinition = default(NumberDefinition); var stringDefinitions = default(List <StringDefinition>); foreach (var nestedType in OneOf) { var nestedDefinition = schema.GetDefinition(nestedType); if (nestedDefinition.ReaderContext.Length > 0) { throw new ArgumentException($"'{name}' is a one-of definition and references another definition that defines context. This is currently not supported."); } if (nestedDefinition is MappingDefinition mappingDefinition) { if (mappingDefinitions == null) { mappingDefinitions = new List <MappingDefinition>(); } mappingDefinitions.Add(mappingDefinition); if (!String.IsNullOrEmpty(mappingDefinition.LooseKeyType)) { foundLooseKeyType = true; } } else if (nestedDefinition is SequenceDefinition s) { // Multiple sequence definitions not allowed if (sequenceDefinition != null) { throw new ArgumentException($"'{name}' refers to more than one '{TemplateConstants.Sequence}'"); } sequenceDefinition = s; } else if (nestedDefinition is NullDefinition n) { // Multiple sequence definitions not allowed if (nullDefinition != null) { throw new ArgumentException($"'{name}' refers to more than one '{TemplateConstants.Null}'"); } nullDefinition = n; } else if (nestedDefinition is BooleanDefinition b) { // Multiple boolean definitions not allowed if (booleanDefinition != null) { throw new ArgumentException($"'{name}' refers to more than one '{TemplateConstants.Boolean}'"); } booleanDefinition = b; } else if (nestedDefinition is NumberDefinition num) { // Multiple number definitions not allowed if (numberDefinition != null) { throw new ArgumentException($"'{name}' refers to more than one '{TemplateConstants.Number}'"); } numberDefinition = num; } else if (nestedDefinition is StringDefinition stringDefinition) { // First string definition if (stringDefinitions == null) { stringDefinitions = new List <StringDefinition>(); } // Multiple string definitions, all must be 'Constant' else if ((stringDefinitions.Count == 1 && String.IsNullOrEmpty(stringDefinitions[0].Constant)) || String.IsNullOrEmpty(stringDefinition.Constant)) { throw new ArgumentException($"'{name}' refers to more than one '{TemplateConstants.Scalar}', but some do not set '{TemplateConstants.Constant}'"); } stringDefinitions.Add(stringDefinition); } else { throw new ArgumentException($"'{name}' refers to a '{nestedDefinition.DefinitionType}' definition"); } } if (mappingDefinitions?.Count > 1) { if (foundLooseKeyType) { throw new ArgumentException($"'{name}' refers to two mappings that both set '{TemplateConstants.LooseKeyType}'"); } var seenProperties = new Dictionary <String, PropertyValue>(StringComparer.Ordinal); foreach (var mappingDefinition in mappingDefinitions) { foreach (var newProperty in GetMergedProperties(schema, mappingDefinition)) { // Already seen if (seenProperties.TryGetValue(newProperty.Key, out PropertyValue existingProperty)) { // Types match if (String.Equals(existingProperty.Type, newProperty.Value.Type, StringComparison.Ordinal)) { continue; } // Collision throw new ArgumentException($"'{name}' contains two mappings with the same property, but each refers to a different type. All matching properties must refer to the same type."); } // New else { seenProperties.Add(newProperty.Key, newProperty.Value); } } } } }