/// <summary>
        /// Returns a code type references for the specified json schema.
        /// Generates the appropriate references.
        /// </summary>
        internal static CodeTypeReference GetCodeType(JsonSchema propertySchema,
                                                      SchemaImplementationDetails details,
                                                      INestedClassProvider internalClassProvider)
        {
            propertySchema.ThrowIfNull("propertySchema");
            internalClassProvider.ThrowIfNull("internalClassProvider");
            if (propertySchema.Type.HasValue == false)
            {
                throw new NotSupportedException("propertySchema has no Type. " + propertySchema);
            }

            switch (propertySchema.Type.Value)
            {
                case JsonSchemaType.String:
                    return new CodeTypeReference(typeof(string));
                case JsonSchemaType.Integer:
                    return new CodeTypeReference(typeof(long?));
                case JsonSchemaType.Boolean:
                    return new CodeTypeReference(typeof(bool?));
                case JsonSchemaType.Float:
                    return new CodeTypeReference(typeof(double?));
                case JsonSchemaType.Array:
                    return GetArrayTypeReference(propertySchema, details, internalClassProvider);
                case JsonSchemaType.Object:
                    return GetObjectTypeReference(propertySchema, details, internalClassProvider);
                case JsonSchemaType.Any:
                    return new CodeTypeReference(typeof(string));
                default:
                    logger.Warning(
                        "Found currently unsupported type {0} as part of {1}", propertySchema.Type.Value,
                        propertySchema);
                    return new CodeTypeReference(typeof(object));
            }
        }
Beispiel #2
0
        internal static void AddIsMethodResult(IDictionary <JsonSchema, SchemaImplementationDetails> details,
                                               IService service,
                                               IMethod method)
        {
            details.ThrowIfNull("details");
            service.ThrowIfNull("service");
            method.ThrowIfNull("method");

            string id = method.ResponseType;

            if (string.IsNullOrEmpty(id))
            {
                // Return if this method has no response type
                return;
            }

            // Check if this name is a valid schema
            if (!service.Schemas.ContainsKey(id))
            {
                return;
            }

            ISchema schema = service.Schemas[id];

            // If no implementation details have been added yet, create a new entry
            SchemaImplementationDetails implementationDetails = GetOrCreateDetails(details, schema.SchemaDetails);

            // Change the value
            implementationDetails.IsMethodResult = true;
        }
        internal static CodeTypeReference GetArrayTypeReference(JsonSchema propertySchema,
                                                                 SchemaImplementationDetails details,
                                                                 INestedClassProvider internalClassProvider)
        {
            propertySchema.ThrowIfNull("propertySchema");
            if (propertySchema.Type != JsonSchemaType.Array)
            {
                throw new ArgumentException("Must be of JsonSchemaType.Array", "propertySchema");
            }

            var arrayItems = propertySchema.Items;
            if (arrayItems != null && arrayItems.Count == 1)
            {
                CodeTypeReference itemType = arrayItems[0].Id.IsNotNullOrEmpty()
                    ? new CodeTypeReference(arrayItems[0].Id)
                    : GetCodeType(arrayItems[0], details, internalClassProvider);
                logger.Debug("type for array {0}", itemType.BaseType);
                return new CodeTypeReference(typeof(IList<>))
                {
                    TypeArguments = { itemType }
                };
            }

            logger.Warning("Found Array of unhandled type. {0}", propertySchema);
            return new CodeTypeReference(typeof(System.Collections.IList));
        }
Beispiel #4
0
        internal static void AddDetails(IDictionary <JsonSchema, SchemaImplementationDetails> dictionary,
                                        JsonSchema schema)
        {
            // Add details for this schema
            SchemaImplementationDetails details = GetOrCreateDetails(dictionary, schema);

            if (details.TraversedByGenerator)
            {
                // This scheme has already been fully generated
                return;
            }
            details.TraversedByGenerator = true;

            // Check for properties:
            if (schema.Properties != null)
            {
                foreach (KeyValuePair <string, JsonSchema> property in schema.Properties)
                {
                    ProposeNameIfNecessary(dictionary, property.Key + PropertyClassSuffix, property.Value);
                    AddDetails(dictionary, property.Value);
                }
            }

            // Generate a template name for subclasses.
            string proposedName = schema.Id.IsNotNullOrEmpty() ? schema.Id : details.ProposedName;

            // Check for items:
            if (schema.Items != null)
            {
                // Iterate through items and check if they require a name.
                foreach (JsonSchema item in schema.Items)
                {
                    // Set the name if necessary and possible.
                    if (!string.IsNullOrEmpty(proposedName))
                    {
                        ProposeNameIfNecessary(dictionary, proposedName, item);
                    }
                    AddDetails(dictionary, item);
                }
            }

            // Check additional properties:
            if (schema.AdditionalProperties != null)
            {
                ProposeNameIfNecessary(dictionary, proposedName + "Properties", schema.AdditionalProperties);
                AddDetails(dictionary, schema.AdditionalProperties);
            }
        }
Beispiel #5
0
            /// <summary>
            /// Gets a class name as a CodeTypeReference for the given schema of the form "IntenalClassN" where
            /// N is an integer. Given the same JsonSchema this will return the same classname.
            /// </summary>
            public CodeTypeReference GetClassName(JsonSchema definition, SchemaImplementationDetails details)
            {
                if (knownSubschemas.ContainsKey(definition))
                {
                    return(knownSubschemas[definition].Reference);
                }

                string name = null;

                // First, try to generate a name based upon the environment.
                if (typeDeclaration != null && details != null && !string.IsNullOrEmpty(details.ProposedName))
                {
                    string proposedName = details.ProposedName;
                    IEnumerable <string> forbiddenWords = GeneratorUtils.GetWordContextListFromClass(typeDeclaration);
                    forbiddenWords =
                        forbiddenWords.Concat(from KnownSubschema k in knownSubschemas.Values select k.ClassName);

                    string generatedName = GeneratorUtils.GetClassName(proposedName, forbiddenWords);
                    if (generatedName.IsNotNullOrEmpty())
                    {
                        // The generated name is valid -> take it.
                        name = generatedName;
                    }
                }

                // If this name collides with an existing type, generate a unique name.
                if (name == null)
                {
                    name = GetSchemaName(knownSubschemas.Count + 1);
                }

                // If the current class is not null, set the prefix to the class name as it will be required for
                // addressing this nested type.
                string prefix = "";

                if (typeDeclaration != null)
                {
                    prefix = typeDeclaration.Name + ".";
                }

                var newSubschema = new KnownSubschema();

                newSubschema.Reference = new CodeTypeReference(prefix + name);
                newSubschema.ClassName = name;
                knownSubschemas.Add(definition, newSubschema);
                return(newSubschema.Reference);
            }
Beispiel #6
0
        internal static void ProposeNameIfNecessary(IDictionary <JsonSchema, SchemaImplementationDetails> dictionary,
                                                    string name,
                                                    JsonSchema schema)
        {
            schema.ThrowIfNull("schema");
            name.ThrowIfNull("name");
            dictionary.ThrowIfNull("name");

            if (schema.Id.IsNotNullOrEmpty())
            {
                // Already has a name -> return.
                return;
            }

            SchemaImplementationDetails details = GetOrCreateDetails(dictionary, schema);

            if (string.IsNullOrEmpty(details.ProposedName))
            {
                details.ProposedName = name;
            }
        }
        public void DecorateClassTest()
        {
            // Init required vars.
            var decorator = new ResponseInterfaceDecorator();
            var declaration = new CodeTypeDeclaration();
            var schema = new MockSchema { SchemaDetails = new JsonSchema() };
            var internalClassProvider = new ObjectInternalClassProvider();
            var implDetails = new Dictionary<JsonSchema, SchemaImplementationDetails>();
            implDetails.Add(schema.SchemaDetails, new SchemaImplementationDetails());

            // Test edge cases.
            Assert.Throws(
                typeof(ArgumentNullException),
                () => decorator.DecorateClass(null, schema, implDetails, internalClassProvider));
            Assert.Throws(
                typeof(ArgumentNullException),
                () => decorator.DecorateClass(declaration, null, implDetails, internalClassProvider));
            Assert.Throws(
                typeof(ArgumentNullException),
                () => decorator.DecorateClass(declaration, schema, null, internalClassProvider));

            decorator.DecorateClass(declaration, schema, implDetails, internalClassProvider);
            Assert.AreEqual(0, declaration.BaseTypes.Count);
            Assert.AreEqual(0, declaration.Members.Count);

            // Test simple functionality.
            var details = new SchemaImplementationDetails { IsMethodResult = true };
            implDetails = new Dictionary<JsonSchema, SchemaImplementationDetails>
                                  { { schema.SchemaDetails, details } };

            decorator.DecorateClass(declaration, schema, implDetails, internalClassProvider);

            Assert.AreEqual(1, declaration.BaseTypes.Count);
            Assert.AreEqual(4, declaration.Members.Count); // 2 properties with a field each

            // Test with already existing e-tag field.
            declaration = new CodeTypeDeclaration();
            declaration.Members.Add(new CodeMemberProperty() { Name = "ETag" });
            decorator.DecorateClass(declaration, schema, implDetails, internalClassProvider);

            Assert.AreEqual(1, declaration.BaseTypes.Count);
            Assert.AreEqual(3, declaration.Members.Count); // one property with a field, and the previously added one.
        }
        /// <summary>
        /// Resolves/generates an object type reference for a schema.
        /// </summary>
        internal static CodeTypeReference GetObjectTypeReference(JsonSchema propertySchema,
                                                                 SchemaImplementationDetails details,
                                                                 INestedClassProvider internalClassProvider)
        {
            propertySchema.ThrowIfNull("propertySchema");
            if (propertySchema.Type != JsonSchemaType.Object)
            {
                throw new ArgumentException("Must be of JsonSchemaType.Array", "propertySchema");
            }
            if (propertySchema.Id.IsNotNullOrEmpty())
            {
                logger.Debug("Found Object with id using type {0}", propertySchema.Id);
                return new CodeTypeReference(propertySchema.Id);
            }

            return internalClassProvider.GetClassName(propertySchema, details);
        }
 public CodeTypeReference GetClassName(JsonSchema definition, SchemaImplementationDetails details)
 {
     return new CodeTypeReference(typeof(object));
 }
        public void GenerateFieldTest()
        {
            var schema = new JsonSchema();
            var decorator = new StandardPropertyFieldDecorator();
            var implDetails = new SchemaImplementationDetails();

            schema.Type = JsonSchemaType.String;
            CodeMemberField generatedField = decorator.GenerateField(
                "normalName", schema, implDetails, 1, internalClassProvider, Enumerable.Empty<string>());

            Assert.NotNull(generatedField);
            Assert.AreEqual(typeof(string).FullName, generatedField.Type.BaseType);
            Assert.AreEqual("_normalName", generatedField.Name);
            Assert.AreEqual(MemberAttributes.Private, generatedField.Attributes);

            schema.Type = JsonSchemaType.Boolean;
            generatedField = decorator.GenerateField(
                "public", schema, implDetails, 2, internalClassProvider, Enumerable.Empty<string>());

            Assert.NotNull(generatedField);
            Assert.AreEqual(typeof(Nullable<>).FullName, generatedField.Type.BaseType);
            Assert.AreEqual(typeof(bool).FullName, generatedField.Type.TypeArguments[0].BaseType);
            Assert.AreEqual("_public", generatedField.Name);
            Assert.AreEqual(MemberAttributes.Private, generatedField.Attributes);

            generatedField = decorator.GenerateField(
                "UPPERCASE", schema, implDetails, 2, internalClassProvider, Enumerable.Empty<string>());

            Assert.NotNull(generatedField);
            Assert.AreEqual("_UPPERCASE", generatedField.Name);
        }
        internal CodeMemberProperty GenerateProperty(string name,
                                                     JsonSchema propertySchema,
                                                     SchemaImplementationDetails details,
                                                     int index,
                                                     INestedClassProvider internalClassProvider,
                                                     IEnumerable<string> disallowedNames)
        {
            name.ThrowIfNullOrEmpty("name");
            propertySchema.ThrowIfNull("propertySchema");

            var ret = new CodeMemberProperty();
            ret.Name = SchemaDecoratorUtil.GetPropertyName(name, disallowedNames);
            ret.Type = SchemaDecoratorUtil.GetCodeType(propertySchema, details, internalClassProvider);
            ret.Attributes = MemberAttributes.Public;

            ret.HasGet = true;
            var fieldReference = new CodeFieldReferenceExpression(
                new CodeThisReferenceExpression(), SchemaDecoratorUtil.GetFieldName(name, disallowedNames));
            ret.GetStatements.Add(new CodeMethodReturnStatement(fieldReference));

            ret.HasSet = true;
            var parameterReference = new CodeVariableReferenceExpression("value");
            ret.SetStatements.Add(new CodeAssignStatement(fieldReference, parameterReference));

            return ret;
        }
            public void GetClassNameWithDetailsTest()
            {
                var empty = new List<ISchemaDecorator>(0);
                var decl = new CodeTypeDeclaration() { Name = "Top" };
                var gen = new SchemaGenerator.NestedClassGenerator(decl, empty, "1_");

                var schema1 = new JsonSchema();
                var details = new SchemaImplementationDetails() { ProposedName = "TestClass" };
                Assert.AreEqual("Top.TestClass", gen.GetClassName(schema1, details).BaseType);
                Assert.AreEqual("Top.TestClass", gen.GetClassName(schema1, null).BaseType);
                Assert.AreEqual("Top.NestedClass1_2", gen.GetClassName(new JsonSchema(), null).BaseType);
            }
        internal CodeMemberField GenerateField(string name,
                                               JsonSchema propertySchema,
                                               SchemaImplementationDetails details,
                                               int index,
                                               INestedClassProvider internalClassProvider,
                                               IEnumerable<string> otherFieldNames)
        {
            name.ThrowIfNullOrEmpty("name");
            propertySchema.ThrowIfNull("propertySchema");
            internalClassProvider.ThrowIfNull("internalClassProvider");
            details.ThrowIfNull("details");

            var ret = new CodeMemberField(
                SchemaDecoratorUtil.GetCodeType(propertySchema, details, internalClassProvider),
                SchemaDecoratorUtil.GetFieldName(name, otherFieldNames));
            ret.Attributes = MemberAttributes.Private;

            return ret;
        }
Beispiel #14
0
            /// <summary>
            /// Gets a class name as a CodeTypeReference for the given schema of the form "IntenalClassN" where 
            /// N is an integer. Given the same JsonSchema this will return the same classname.
            /// </summary>
            public CodeTypeReference GetClassName(JsonSchema definition, SchemaImplementationDetails details)
            {
                if (knownSubschemas.ContainsKey(definition))
                {
                    return knownSubschemas[definition].Reference;
                }

                string name = null;
                
                // First, try to generate a name based upon the environment.
                if (typeDeclaration != null && details != null && !string.IsNullOrEmpty(details.ProposedName))
                {
                    string proposedName = details.ProposedName;
                    IEnumerable<string> forbiddenWords = GeneratorUtils.GetWordContextListFromClass(typeDeclaration);
                    forbiddenWords =
                        forbiddenWords.Concat(from KnownSubschema k in knownSubschemas.Values select k.ClassName);

                    string generatedName = GeneratorUtils.GetClassName(proposedName, forbiddenWords);
                    if (generatedName.IsNotNullOrEmpty())
                    {
                        // The generated name is valid -> take it.
                        name = generatedName;
                    }
                }

                // If this name collides with an existing type, generate a unique name.
                if (name == null)
                {
                    name = GetSchemaName(knownSubschemas.Count+1);
                }

                // If the current class is not null, set the prefix to the class name as it will be required for
                // addressing this nested type.
                string prefix = "";
                if (typeDeclaration != null)
                {
                    prefix = typeDeclaration.Name + ".";
                }

                var newSubschema = new KnownSubschema();
                newSubschema.Reference = new CodeTypeReference(prefix + name);
                newSubschema.ClassName = name;
                knownSubschemas.Add(definition, newSubschema);
                return newSubschema.Reference;
            }