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); }
internal IList <CodeMemberField> GenerateAllFields(string name, JsonSchema schema, IDictionary <JsonSchema, SchemaImplementationDetails> implDetails, INestedClassProvider internalClassProvider) { schema.ThrowIfNull("schema"); name.ThrowIfNull("name"); implDetails.ThrowIfNull("details"); internalClassProvider.ThrowIfNull("internalClassProvider"); var fields = new List <CodeMemberField>(); if (schema.Properties.IsNullOrEmpty()) { logger.Debug("No Properties found for " + name); return(fields); } int index = 0; foreach (var propertyPair in schema.Properties) { SchemaImplementationDetails details = implDetails[propertyPair.Value]; fields.Add( GenerateField( propertyPair.Key, propertyPair.Value, details, index, internalClassProvider, schema.Properties.Keys.Without(propertyPair.Key))); index++; } return(fields); }
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))); }
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(2, declaration.Members.Count); // 1 property with a field. // 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(1, declaration.Members.Count); }
/// <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 void DecorateInternalClass(CodeTypeDeclaration typeDeclaration, string name, JsonSchema schema, IDictionary <JsonSchema, SchemaImplementationDetails> implDetails, INestedClassProvider internalClassProvider) { typeDeclaration.ThrowIfNull("typeDeclatation"); schema.ThrowIfNull("schema"); implDetails.ThrowIfNull("details"); internalClassProvider.ThrowIfNull("internalClassProvider"); SchemaImplementationDetails details = implDetails[schema]; typeDeclaration.Members.AddRange( GenerateAllProperties(name, schema, implDetails, internalClassProvider, typeDeclaration.Name) .ToArray()); }
public void GetClassNameWithDetailsCollisionsTest() { 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 schema2 = new JsonSchema(); var details = new SchemaImplementationDetails() { ProposedName = "TestClass" }; Assert.AreEqual("Top.TestClass", gen.GetClassName(schema1, details).BaseType); Assert.AreNotEqual("Top.TestClass", gen.GetClassName(schema2, details).BaseType); }
public void DecorateClass(CodeTypeDeclaration typeDeclaration, ISchema schema, IDictionary <JsonSchema, SchemaImplementationDetails> implDetails, INestedClassProvider internalClassProvider) { typeDeclaration.ThrowIfNull("typeDeclaration"); schema.ThrowIfNull("schema"); implDetails.ThrowIfNull("implDetails"); SchemaImplementationDetails details = implDetails[schema.SchemaDetails]; // If this method is refered as a result directly, add an inheritance to IResponse and implement // the interface if (details.IsMethodResult) { logger.Debug("Applying decorator to schema " + schema.Name); typeDeclaration.BaseTypes.Add(GetIResponseBaseType()); typeDeclaration.Members.AddRange(CreateETagProperty(typeDeclaration)); } }
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); }
/// <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))); } }
internal IList <CodeMemberProperty> GenerateAllProperties(string name, JsonSchema schema, IDictionary <JsonSchema, SchemaImplementationDetails> implDetails, INestedClassProvider internalClassProvider, params string[] usedWordsInContext) { schema.ThrowIfNull("schema"); name.ThrowIfNullOrEmpty("name"); logger.Debug("Adding properties for {0}", name); var fields = new List <CodeMemberProperty>(); if (schema.Properties.IsNullOrEmpty()) { logger.Debug("No properties found for schema " + name); return(fields); } IEnumerable <string> allUsedWordsInContext = usedWordsInContext.Concat(schema.Properties.Keys); int index = 0; foreach (var propertyPair in schema.Properties) { SchemaImplementationDetails details = implDetails[propertyPair.Value]; CodeMemberProperty property = GenerateProperty( propertyPair.Key, propertyPair.Value, details, index++, internalClassProvider, allUsedWordsInContext.Except(new[] { propertyPair.Key })); foreach (var decorator in propertyDecorators) { decorator.DecorateProperty(property, propertyPair); } fields.Add(property); } return(fields); }
public void DecorateClass(CodeTypeDeclaration typeDeclaration, ISchema schema, IDictionary <JsonSchema, SchemaImplementationDetails> implDetails, INestedClassProvider internalClassProvider) { typeDeclaration.ThrowIfNull("typeDeclaration"); schema.ThrowIfNull("schema"); implDetails.ThrowIfNull("implDetails"); internalClassProvider.ThrowIfNull("internalClassProvider"); JsonSchema details = schema.SchemaDetails; details.ThrowIfNull("schemaDetails"); // Check if this decorator can be applied to the schema); if (details.Type != JsonSchemaType.Array) { return; } if (details.Items == null || details.Items.Count != 1) { logger.Warning("Found array scheme of unhandled type. {0}", details); return; // not supported } // Generate or find the nested type JsonSchema itemScheme = details.Items[0]; SchemaImplementationDetails implDetail = implDetails[itemScheme]; implDetail.ProposedName = "Entry"; // Change the name to a custom one. CodeTypeReference item = SchemaDecoratorUtil.GetCodeType(itemScheme, implDetail, internalClassProvider); // Insert the base type before any interface declaration typeDeclaration.BaseTypes.Insert(0, new CodeTypeReference(typeof(List <>)) { TypeArguments = { item } }); }
internal void ImplementAdditionalProperties(CodeTypeDeclaration type, JsonSchema schema, IDictionary <JsonSchema, SchemaImplementationDetails> implDetails, INestedClassProvider internalClassProvider) { // Validate the input parameters. type.ThrowIfNull("type"); schema.ThrowIfNull("schema"); implDetails.ThrowIfNull("implDetails"); internalClassProvider.ThrowIfNull("internalClassProvider"); // Check if this decorator applies to the specified json schema. if (schema.AdditionalProperties == null) { return; } // Note/ToDo: Currently we only support AdditionalProperties for schemas // specifiying no normal properties, as these won't be used // by the newtonsoft json library if a dictionary is specified. if (schema.Properties != null && schema.Properties.Count > 0) { type.Comments.Add(new CodeCommentStatement("TODO: Add support for additionalProperties on schemas")); type.Comments.Add(new CodeCommentStatement(" which have normal properties defined.")); return; } // Generate the underlying type. SchemaImplementationDetails details = implDetails[schema]; CodeTypeReference underlyingTypeRef = SchemaDecoratorUtil.GetCodeType( schema.AdditionalProperties, details, internalClassProvider); // Add the base type reference. CodeTypeReference dictionaryRef = new CodeTypeReference(typeof(Dictionary <,>)); dictionaryRef.TypeArguments.Add(typeof(string)); dictionaryRef.TypeArguments.Add(underlyingTypeRef); type.BaseTypes.Add(dictionaryRef); }
public CodeTypeReference GetClassName(JsonSchema definition, SchemaImplementationDetails details) { return(new CodeTypeReference(typeof(object))); }