/// <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);
        }
Esempio n. 2
0
        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);
                    }
                }
            }
        }
Esempio n. 3
0
 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");
     }
 }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
 internal override void Validate(
     TemplateSchema schema,
     String name)
 {
 }
 internal abstract void Validate(
     TemplateSchema schema,
     String name);
Esempio n. 7
0
        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");
                }
            }
        }
Esempio n. 8
0
        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);
                        }
                    }
                }
            }
        }