Skip to content

Commit

Permalink
Merge pull request #104 from Kentico/feature/refactoring-models
Browse files Browse the repository at this point in the history
Made compatible with the Delivery SDK v14
  • Loading branch information
petrsvihlik authored Aug 21, 2020
2 parents 068887e + b5ac947 commit 52adbc3
Show file tree
Hide file tree
Showing 28 changed files with 280 additions and 193 deletions.
6 changes: 6 additions & 0 deletions kontent-generators-net.sln
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kentico.Kontent.ModelGenera
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kentico.Kontent.ModelGenerator.Tests", "test\Kentico.Kontent.ModelGenerator.Tests\Kentico.Kontent.ModelGenerator.Tests.csproj", "{9D6A9E5B-EB41-472A-90B2-DF7E5EB43397}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kentico.Kontent.ModelGenerator.Core", "src\Kentico.Kontent.ModelGenerator.Core\Kentico.Kontent.ModelGenerator.Core.csproj", "{66C29DDB-8ED8-4D45-B8E8-003488E145E4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -27,6 +29,10 @@ Global
{9D6A9E5B-EB41-472A-90B2-DF7E5EB43397}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9D6A9E5B-EB41-472A-90B2-DF7E5EB43397}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9D6A9E5B-EB41-472A-90B2-DF7E5EB43397}.Release|Any CPU.Build.0 = Release|Any CPU
{66C29DDB-8ED8-4D45-B8E8-003488E145E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{66C29DDB-8ED8-4D45-B8E8-003488E145E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{66C29DDB-8ED8-4D45-B8E8-003488E145E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{66C29DDB-8ED8-4D45-B8E8-003488E145E4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using Microsoft.CodeAnalysis;
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Formatting;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Kentico.Kontent.ModelGenerator
namespace Kentico.Kontent.ModelGenerator.Core
{
public class BaseClassCodeGenerator
{
Expand All @@ -21,13 +21,7 @@ public class BaseClassCodeGenerator
/// <summary>
/// The calculated Extender Classname
/// </summary>
public string ExtenderClassName
{
get
{
return $"{_className}Extender";
}
}
public string ExtenderClassName => $"{_className}Extender";

public BaseClassCodeGenerator(string className, string @namespace = ClassCodeGenerator.DEFAULT_NAMESPACE)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Formatting;
using Newtonsoft.Json.Serialization;

namespace Kentico.Kontent.ModelGenerator
namespace Kentico.Kontent.ModelGenerator.Core
{
public class ClassCodeGenerator
{
Expand Down Expand Up @@ -34,23 +35,23 @@ public string GenerateCode(bool cmApi = false)
{
var cmApiUsings = new[]
{
SyntaxFactory.UsingDirective(SyntaxFactory.IdentifierName("Newtonsoft.Json")),
SyntaxFactory.UsingDirective(SyntaxFactory.IdentifierName("Kentico.Kontent.Management.Models.Items")),
SyntaxFactory.UsingDirective(SyntaxFactory.IdentifierName("Kentico.Kontent.Management.Models.Assets"))
SyntaxFactory.UsingDirective(SyntaxFactory.IdentifierName($"{nameof(Newtonsoft)}.{nameof(Newtonsoft.Json)}")),
SyntaxFactory.UsingDirective(SyntaxFactory.IdentifierName(typeof(Management.Models.Items.ContentItemModel).Namespace!)),
SyntaxFactory.UsingDirective(SyntaxFactory.IdentifierName(typeof(Management.Models.Assets.AssetModel).Namespace!))
};

var deliveryUsings = new[]
{
SyntaxFactory.UsingDirective(SyntaxFactory.IdentifierName("Kentico.Kontent.Delivery.Abstractions"))
SyntaxFactory.UsingDirective(SyntaxFactory.IdentifierName(typeof(Delivery.Abstractions.IApiResponse).Namespace!))
};

var usings = new[]
{
SyntaxFactory.UsingDirective(SyntaxFactory.IdentifierName("System")),
SyntaxFactory.UsingDirective(SyntaxFactory.IdentifierName("System.Collections.Generic")),
SyntaxFactory.UsingDirective(SyntaxFactory.IdentifierName(nameof(System))),
SyntaxFactory.UsingDirective(SyntaxFactory.IdentifierName(typeof(System.Collections.Generic.IEnumerable<>).Namespace!)),
}.Concat(cmApi ? cmApiUsings : deliveryUsings).ToArray();

var properties = ClassDefinition.Properties.OrderBy(p => p.Identifier).Select((element) =>
MemberDeclarationSyntax[] properties = ClassDefinition.Properties.OrderBy(p => p.Identifier).Select((element) =>
{
var property = SyntaxFactory
.PropertyDeclaration(SyntaxFactory.ParseTypeName(element.TypeName), element.Identifier)
Expand All @@ -61,13 +62,13 @@ public string GenerateCode(bool cmApi = false)
SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
);

if (cmApi)
{
property = property.AddAttributeLists(
SyntaxFactory.AttributeList(
SyntaxFactory.SingletonSeparatedList(
SyntaxFactory.Attribute(SyntaxFactory.IdentifierName("JsonProperty"))
SyntaxFactory.Attribute(SyntaxFactory.IdentifierName(nameof(JsonProperty)))
.WithArgumentList(
SyntaxFactory.AttributeArgumentList(
SyntaxFactory.SingletonSeparatedList(
Expand All @@ -81,7 +82,7 @@ public string GenerateCode(bool cmApi = false)
}
).ToArray();

var propertyCodenameConstants = ClassDefinition.PropertyCodenameConstants.OrderBy(p => p.Codename).Select(element =>
MemberDeclarationSyntax[] propertyCodenameConstants = ClassDefinition.PropertyCodenameConstants.OrderBy(p => p.Codename).Select(element =>
SyntaxFactory.FieldDeclaration(
SyntaxFactory.VariableDeclaration(
SyntaxFactory.ParseTypeName("string"),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
using Kentico.Kontent.Delivery.Abstractions;
using System;
using System;
using System.Collections.Generic;
using Kentico.Kontent.Delivery.Abstractions;

namespace Kentico.Kontent.ModelGenerator
namespace Kentico.Kontent.ModelGenerator.Core
{
public class ClassDefinition
{
public List<Property> Properties { get; } = new List<Property>();

public List<ContentElement> PropertyCodenameConstants { get; } = new List<ContentElement>();
public List<IContentElement> PropertyCodenameConstants { get; } = new List<IContentElement>();

public string ClassName => TextHelpers.GetValidPascalCaseIdentifierName(Codename);

Expand All @@ -29,7 +29,7 @@ public void AddProperty(Property property)
Properties.Add(property);
}

public void AddPropertyCodenameConstant(ContentElement element)
public void AddPropertyCodenameConstant(IContentElement element)
{
if (PropertyCodenameConstantIsAlreadyPresent(element))
{
Expand All @@ -41,15 +41,15 @@ public void AddPropertyCodenameConstant(ContentElement element)

public void AddSystemProperty()
{
AddProperty(new Property("system", "ContentItemSystemAttributes"));
AddProperty(new Property("system", nameof(IContentItemSystemAttributes)));
}

private bool PropertyIsAlreadyPresent(Property property)
{
return Properties.Exists(e => e.Identifier == property.Identifier);
}

private bool PropertyCodenameConstantIsAlreadyPresent(ContentElement element)
private bool PropertyCodenameConstantIsAlreadyPresent(IContentElement element)
{
return PropertyCodenameConstants.Exists(e => e.Codename == element.Codename);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,29 @@
using Kentico.Kontent.Delivery.Abstractions;
using Microsoft.Extensions.Options;
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Kentico.Kontent.Delivery.Abstractions;
using Kentico.Kontent.ModelGenerator.Core.Configuration;
using Microsoft.Extensions.Options;

namespace Kentico.Kontent.ModelGenerator
namespace Kentico.Kontent.ModelGenerator.Core
{
public class CodeGenerator
{
internal readonly CodeGeneratorOptions _options;

private readonly CodeGeneratorOptions _options;
private readonly IDeliveryClient _client;
private readonly IOutputProvider _outputProvider;

public CodeGenerator(IOptions<CodeGeneratorOptions> options, IDeliveryClient deliveryClient)
public CodeGenerator(IOptions<CodeGeneratorOptions> options, IDeliveryClient deliveryClient, IOutputProvider outputProvider)
{
_options = options.Value;
_client = deliveryClient;

// Setting OutputDir default value here instead of in the <see cref="Parse"/> method as it would overwrite the JSON value.
if (string.IsNullOrEmpty(_options.OutputDir))
{
_options.OutputDir = "./";
}
_outputProvider = outputProvider;

if (_options.GeneratePartials && string.IsNullOrEmpty(_options.FileNameSuffix))
{
_options.FileNameSuffix = "Generated";
}

// Resolve relative path to full path
_options.OutputDir = Path.GetFullPath(_options.OutputDir);
}

public async Task<int> RunAsync()
Expand All @@ -52,16 +44,13 @@ public async Task<int> RunAsync()

internal async Task GenerateContentTypeModels(bool structuredModel = false)
{
// Make sure the output dir exists
Directory.CreateDirectory(_options.OutputDir);

var classCodeGenerators = await GetClassCodeGenerators(structuredModel);

if (classCodeGenerators.Count() > 0)
if (classCodeGenerators.Any())
{
foreach (var codeGenerator in classCodeGenerators)
{
SaveToFile(codeGenerator.GenerateCode(_options.ContentManagementApi), codeGenerator.ClassFilename, codeGenerator.OverwriteExisting);
_outputProvider.Output(codeGenerator.GenerateCode(_options.ContentManagementApi), codeGenerator.ClassFilename, codeGenerator.OverwriteExisting);
}

Console.WriteLine($"{classCodeGenerators.Count()} content type models were successfully created.");
Expand All @@ -74,12 +63,10 @@ internal async Task GenerateContentTypeModels(bool structuredModel = false)

internal async Task GenerateTypeProvider()
{
// Make sure the output dir exists
Directory.CreateDirectory(_options.OutputDir);

var classCodeGenerators = await GetClassCodeGenerators();

if (classCodeGenerators.Count() > 0)
if (classCodeGenerators.Any())
{
var typeProviderCodeGenerator = new TypeProviderCodeGenerator(_options.Namespace);

Expand All @@ -91,7 +78,7 @@ internal async Task GenerateTypeProvider()
var typeProviderCode = typeProviderCodeGenerator.GenerateCode();
if (!string.IsNullOrEmpty(typeProviderCode))
{
SaveToFile(typeProviderCode, TypeProviderCodeGenerator.CLASS_NAME);
_outputProvider.Output(typeProviderCode, TypeProviderCodeGenerator.CLASS_NAME, true);
Console.WriteLine($"{TypeProviderCodeGenerator.CLASS_NAME} class was successfully created.");
}
}
Expand All @@ -101,31 +88,9 @@ internal async Task GenerateTypeProvider()
}
}

private void SaveToFile(string content, string fileName, bool overwriteExisting = true)
{
string outputPath = Path.Combine(_options.OutputDir, $"{fileName}.cs");
bool fileExists = File.Exists(outputPath);
if (!fileExists || overwriteExisting)
{
File.WriteAllText(outputPath, content);
}
}

private async Task<IEnumerable<ClassCodeGenerator>> GetClassCodeGenerators(bool structuredModel = false)
internal async Task<IEnumerable<ClassCodeGenerator>> GetClassCodeGenerators(bool structuredModel = false)
{
IEnumerable<ContentType> contentTypes = null;
try
{
contentTypes = (await _client.GetTypesAsync()).Types;
}
catch (AggregateException aex)
{
if ((aex.InnerExceptions.Count == 1) && aex.InnerException is DeliveryException)
{
// Return friendlier message
Console.WriteLine(aex.InnerException.Message);
}
}
IEnumerable<IContentType> contentTypes = (await _client.GetTypesAsync()).Types;
var codeGenerators = new List<ClassCodeGenerator>();
if (contentTypes != null)
{
Expand All @@ -148,7 +113,7 @@ private async Task<IEnumerable<ClassCodeGenerator>> GetClassCodeGenerators(bool
return codeGenerators;
}

private ClassCodeGenerator GetClassCodeGenerator(ContentType contentType, bool structuredModel)
internal ClassCodeGenerator GetClassCodeGenerator(IContentType contentType, bool structuredModel)
{
var classDefinition = new ClassDefinition(contentType.System.Codename);

Expand Down Expand Up @@ -197,22 +162,19 @@ private ClassCodeGenerator GetClassCodeGenerator(ContentType contentType, bool s
return new ClassCodeGenerator(classDefinition, classFilename, _options.Namespace);
}

private ClassCodeGenerator GetCustomClassCodeGenerator(ContentType contentType)
internal ClassCodeGenerator GetCustomClassCodeGenerator(IContentType contentType)
{
var classDefinition = new ClassDefinition(contentType.System.Codename);
string classFilename = $"{classDefinition.ClassName}";

return new ClassCodeGenerator(classDefinition, classFilename, _options.Namespace, true);
}

public async Task GenerateBaseClass()
internal async Task GenerateBaseClass()
{
// Make sure the output dir exists
Directory.CreateDirectory(_options.OutputDir);

IEnumerable<ClassCodeGenerator> classCodeGenerators = await GetClassCodeGenerators();

if (classCodeGenerators.Count() > 0)
if (classCodeGenerators.Any())
{
var baseClassCodeGenerator = new BaseClassCodeGenerator(_options.BaseClass, _options.Namespace);

Expand All @@ -224,14 +186,14 @@ public async Task GenerateBaseClass()
var baseClassCode = baseClassCodeGenerator.GenerateBaseClassCode();
if (!string.IsNullOrEmpty(baseClassCode))
{
SaveToFile(baseClassCode, _options.BaseClass);
_outputProvider.Output(baseClassCode, _options.BaseClass, false);
Console.WriteLine($"{_options.BaseClass} class was successfully created.");
}

var baseClassExtenderCode = baseClassCodeGenerator.GenereateExtenderCode();
if (!string.IsNullOrEmpty(baseClassExtenderCode))
{
SaveToFile(baseClassExtenderCode, baseClassCodeGenerator.ExtenderClassName);
_outputProvider.Output(baseClassExtenderCode, baseClassCodeGenerator.ExtenderClassName, true);
Console.WriteLine($"{baseClassCodeGenerator.ExtenderClassName} class was successfully created.");
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Kentico.Kontent.Delivery;
using Kentico.Kontent.Delivery.Abstractions;

namespace Kentico.Kontent.ModelGenerator
namespace Kentico.Kontent.ModelGenerator.Core.Configuration
{
public class CodeGeneratorOptions
{
Expand Down
10 changes: 10 additions & 0 deletions src/Kentico.Kontent.ModelGenerator.Core/IOutputProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.Collections.Generic;
using System.Text;

namespace Kentico.Kontent.ModelGenerator.Core
{
public interface IOutputProvider
{
void Output(string content, string fileName, bool overwriteExisting);
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
using System;

namespace Kentico.Kontent.ModelGenerator
namespace Kentico.Kontent.ModelGenerator.Core
{
public class InvalidIdentifierException : Exception
{
public InvalidIdentifierException()
{
}

public InvalidIdentifierException(string message) : base(message)
{
}
Expand Down
Loading

0 comments on commit 52adbc3

Please sign in to comment.