Skip to content

Commit

Permalink
Can generate storage schema from swagger
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan Schulte committed Apr 20, 2016
1 parent ce58306 commit a757cc4
Show file tree
Hide file tree
Showing 6 changed files with 396 additions and 100 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,21 +47,6 @@
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="xunit.abstractions">
<HintPath>..\..\..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="xunit.assert">
<HintPath>..\..\..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="xunit.core">
<HintPath>..\..\..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="xunit.execution.desktop">
<HintPath>..\..\..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll</HintPath>
</Reference>
<Reference Include="xunit.abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll</HintPath>
<Private>True</Private>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ResourceProperty.cs" />
<Compile Include="Schema.cs" />
<Compile Include="AzureResourceSchemaCodeGenerator.cs" />
<Compile Include="$(SolutionDir)\Tools\AssemblyVersionInfo.cs">
<Link>Properties\AssemblyVersionInfo.cs</Link>
Expand All @@ -47,7 +49,7 @@
</ItemGroup>
<ItemGroup>
<CodeAnalysisDictionary Include="$(SolutionDir)\Tools\CustomDictionary.xml">
<Link>CustomDictionary.xml</Link>
<Link>CustomDictionary.xml</Link>
</CodeAnalysisDictionary>
</ItemGroup>
<ItemGroup>
Expand Down Expand Up @@ -81,6 +83,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Resource.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
Expand All @@ -13,8 +14,6 @@ namespace Microsoft.Rest.Generator.AzureResourceSchema
{
public class AzureResourceSchemaCodeGenerator : CodeGenerator
{
private const string resourceMethodPrefix = "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/";

public AzureResourceSchemaCodeGenerator(Settings settings)
: base(settings)
{
Expand Down Expand Up @@ -55,102 +54,111 @@ public override void NormalizeClientModel(ServiceClient serviceClient)

public override async Task Generate(ServiceClient serviceClient)
{
StringWriter stringWriter = new StringWriter();
using (JsonTextWriter writer = new JsonTextWriter(stringWriter))
try
{
writer.Formatting = Formatting.Indented;
writer.Indentation = 2;
writer.IndentChar = ' ';

string resourceProvider = GetResourceProvider(serviceClient);
IEnumerable<string> resourceFullTypes = GetResourceFullTypes(serviceClient);

WriteObject(writer, () => {
WriteProperty(writer, "id", string.Format("http://schema.management.azure.com/schemas/{0}/{1}.json#", serviceClient.ApiVersion, resourceProvider));
WriteProperty(writer, "$schema", "http://json-schema.org/draft-04/schema#");
WriteProperty(writer, "title", resourceProvider);
WriteProperty(writer, "description", resourceProvider.Replace('.', ' ') + " Resource Types");
WriteProperty(writer, "resourceDefinitions", () => {
foreach (string resourceFullType in resourceFullTypes)
{
string resourceShortType = resourceFullType.Substring(resourceFullType.IndexOf('/') + 1);

WriteProperty(writer, resourceShortType, () => {
WriteProperty(writer, "type", "object");
WriteProperty(writer, "properties", () => {
WriteProperty(writer, "type", () => {
WriteProperty(writer, "enum", new string[] {
resourceFullType
});
});
WriteProperty(writer, "apiVersion", () => {
WriteProperty(writer, "enum", new string[] {
serviceClient.ApiVersion
});
});
WriteProperty(writer, "properties", () => {
WriteProperty(writer, "type", "object");
WriteProperty(writer, "properties", () => {
});
WriteProperty(writer, "required", new string[0]);
});
});
WriteProperty(writer, "required", new string[] {
"type",
"apiVersion",
"properties",
"location"
});
WriteProperty(writer, "description", resourceFullType);
});
}
});
});
}
StringWriter stringWriter = new StringWriter();
using (JsonTextWriter writer = new JsonTextWriter(stringWriter))
{
writer.Formatting = Formatting.Indented;
writer.Indentation = 2;
writer.IndentChar = ' ';

await Write(stringWriter.ToString(), SchemaPath);
}
Schema schema = Schema.Parse(serviceClient);

private static IEnumerable<Method> GetResourceMethods(ServiceClient serviceClient)
{
return GetResourceMethods(serviceClient.Methods);
}
WriteSchema(writer, schema);
}

private static IEnumerable<Method> GetResourceMethods(IEnumerable<Method> methods)
{
return methods.Where(m => m.Url.StartsWith(resourceMethodPrefix));
await Write(stringWriter.ToString(), SchemaPath);
}
catch (Exception)
{
Debugger.Break();
}
}

private static IEnumerable<string> GetResourceMethodUrisAfterPrefix(ServiceClient serviceClient)
private static void WriteSchema(JsonTextWriter writer, Schema schema)
{
IEnumerable<Method> resourceMethods = GetResourceMethods(serviceClient);
IEnumerable<string> resourceMethodUris = resourceMethods.Select(rm => rm.Url);
return resourceMethodUris.Select(rmu => rmu.Substring(resourceMethodPrefix.Length));
WriteObject(writer, () =>
{
WriteProperty(writer, "id", schema.Id);
WriteProperty(writer, "$schema", schema.SchemaUri);
WriteProperty(writer, "title", schema.Title);
WriteProperty(writer, "description", schema.Description);
WriteProperty(writer, "resourceDefinitions", () =>
{
foreach (Resource resource in schema.Resources)
{
WriteResource(writer, resource);
}
});
});
}

private static string GetResourceProvider(ServiceClient serviceClient)
private static void WriteResource(JsonTextWriter writer, Resource resource)
{
IEnumerable<string> resourceMethodUrisAfterPrefix = GetResourceMethodUrisAfterPrefix(serviceClient);
return resourceMethodUrisAfterPrefix.Select(rmuap => rmuap.Substring(0, rmuap.IndexOf('/'))).Distinct().Single();
WriteProperty(writer, resource.Name, () =>
{
WriteProperty(writer, "type", "object");
WriteProperty(writer, "properties", () =>
{
WriteProperty(writer, "type", () =>
{
WriteProperty(writer, "enum", new string[]
{
resource.Type
});
});

WriteProperty(writer, "apiVersion", () =>
{
WriteProperty(writer, "enum", resource.ApiVersions);
});

WriteProperty(writer, "properties", () =>
{
WriteObjectOrExpression(writer, () =>
{
WriteProperty(writer, "type", "object");
WriteProperty(writer, "properties", () =>
{
foreach (ResourceProperty property in resource.Properties)
{
WriteResourceProperty(writer, property);
}
});
WriteProperty(writer, "required", resource.RequiredPropertyNames);
});
});
});
WriteProperty(writer, "required", new string[]
{
"type",
"apiVersion",
"properties",
"location"
});
WriteProperty(writer, "description", resource.Description);
});
}

private static IEnumerable<string> GetResourceFullTypes(ServiceClient serviceClient)
private static void WriteResourceProperty(JsonTextWriter writer, ResourceProperty resourceProperty)
{
IEnumerable<string> resourceMethodUrisAfterPrefix = GetResourceMethodUrisAfterPrefix(serviceClient);
return resourceMethodUrisAfterPrefix.Select(rmuap =>
WriteProperty(writer, resourceProperty.Name, () =>
{
int forwardSlashAfterProvider = rmuap.IndexOf('/');
int forwardSlashAfterType = rmuap.IndexOf('/', forwardSlashAfterProvider + 1);
int startIndex = forwardSlashAfterProvider + 1;
if (forwardSlashAfterType == -1)
WriteObjectOrExpression(writer, () =>
{
return rmuap;
}
else
{
return rmuap.Substring(0, forwardSlashAfterType);
}
}).Distinct();
if (resourceProperty.Type != null)
{
WriteProperty(writer, "type", resourceProperty.Type);
}

if (resourceProperty.AllowedValues != null)
{
WriteProperty(writer, "allowedValues", resourceProperty.AllowedValues);
}
});
WriteProperty(writer, "description", resourceProperty.Description);
});
}

private static void WriteObject(JsonTextWriter writer, Action writeObjectContents)
Expand All @@ -162,19 +170,45 @@ private static void WriteObject(JsonTextWriter writer, Action writeObjectContent
writer.WriteEndObject();
}

private static void WriteExpressionReference(JsonTextWriter writer)
{
WriteObject(writer, () =>
{
WriteProperty(writer, "$ref", "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#/definitions/expression");
});
}

private static void WriteObjectOrExpression(JsonTextWriter writer, Action writeObjectContents)
{
writer.WritePropertyName("oneOf");
writer.WriteStartArray();

WriteObject(writer, writeObjectContents);

WriteExpressionReference(writer);

writer.WriteEndArray();
}

private static void WriteProperty(JsonTextWriter writer, string propertyName, string propertyValue)
{
writer.WritePropertyName(propertyName);
writer.WriteValue(propertyValue);
}

private static void WriteProperty(JsonTextWriter writer, string propertyName, int propertyValue)
{
writer.WritePropertyName(propertyName);
writer.WriteValue(propertyValue);
}

private static void WriteProperty(JsonTextWriter writer, string propertyName, Action writeObjectContents)
{
writer.WritePropertyName(propertyName);
WriteObject(writer, writeObjectContents);
}

private static void WriteProperty(JsonTextWriter writer, string propertyName, string[] writeArrayContents)
private static void WriteProperty(JsonTextWriter writer, string propertyName, IEnumerable<string> writeArrayContents)
{
writer.WritePropertyName(propertyName);
writer.WriteStartArray();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System.Collections.Generic;
using System.Linq;

namespace Microsoft.Rest.Generator.AzureResourceSchema
{
public class Resource
{
private readonly string name;
private readonly string type;
private readonly string[] apiVersions;
private readonly IEnumerable<ResourceProperty> properties;
private readonly string description;

public Resource(string name, string type, string[] apiVersions, IEnumerable<ResourceProperty> properties, string description)
{
this.name = name;
this.type = type;
this.apiVersions = apiVersions;
this.properties = properties;
this.description = description;
}

public string Name
{
get { return name; }
}

public string Type
{
get { return type; }
}

public string[] ApiVersions
{
get { return apiVersions; }
}

public IEnumerable<ResourceProperty> Properties
{
get { return properties; }
}

public string[] RequiredPropertyNames
{
get { return Properties.Where(property => property.IsRequired).Select(property => property.Name).ToArray(); }
}

public string Description
{
get { return description; }
}
}
}
Loading

0 comments on commit a757cc4

Please sign in to comment.