Skip to content

Commit

Permalink
Move JSON Schema Generation to separate .csproj; Add shell script (#…
Browse files Browse the repository at this point in the history
…463)

* Move JSON Schema Generation to separate `.csproj`; Add shell script

previously the JSON schemas in `json-schema-files` were generated by a unittest. That's not as intuitive as it could be.
disclaimer: i generated most of the code with chatti:
https://chatgpt.com/share/36c015f9-468a-43b5-b614-690e0b672d57

* remove bom

* remove more boms
  • Loading branch information
hf-kklein authored Aug 1, 2024
1 parent 229a9a4 commit 0637132
Show file tree
Hide file tree
Showing 39 changed files with 31,062 additions and 562 deletions.
6 changes: 6 additions & 0 deletions BO4E-dotnet.sln
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestBO4E.Reporting", "TestB
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestBO4E.Extensions", "TestBO4E.Extensions\TestBO4E.Extensions.csproj", "{BDA5224F-3C83-44F7-B96F-B873247E3245}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SchemaGenerator", "SchemaGenerator\SchemaGenerator.csproj", "{A178CA52-4DF3-4A12-8B84-FFF1EB3152F7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -48,6 +50,10 @@ Global
{BDA5224F-3C83-44F7-B96F-B873247E3245}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BDA5224F-3C83-44F7-B96F-B873247E3245}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BDA5224F-3C83-44F7-B96F-B873247E3245}.Release|Any CPU.Build.0 = Release|Any CPU
{A178CA52-4DF3-4A12-8B84-FFF1EB3152F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A178CA52-4DF3-4A12-8B84-FFF1EB3152F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A178CA52-4DF3-4A12-8B84-FFF1EB3152F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A178CA52-4DF3-4A12-8B84-FFF1EB3152F7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
13 changes: 2 additions & 11 deletions BO4ETestProject/TestJsonSchemaGeneration.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using BO4E.BO;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
Expand Down Expand Up @@ -48,20 +46,13 @@ public void TestJSchemaFileGenerationBo(int offset)
var relevantBusinessObjectTypes = typeof(BusinessObject).Assembly.GetTypes()
.Where(t => t.IsSubclassOf(typeof(BusinessObject)));
relevantBusinessObjectTypes.Count().Should().BeLessThan(LastDataRowOffset + MaxSchemasPerHour); // if this fails, add another data row to this test method
try
try // generate plain json schemas
{
foreach (var type in relevantBusinessObjectTypes.Skip(offset).Take(MaxSchemasPerHour))
{
var schema = BusinessObject.GetJsonSchema(type);
Assert.IsNotNull(schema);
var path = $"../../../../json-schema-files/{type}.json"; // not elegant but ok ;)
if (!File.Exists(path))
{
var stream = File.Create(path);
stream.Close();
}
var utf8WithoutByteOrderMark = new UTF8Encoding(false);
File.WriteAllText(path, schema.ToString(SchemaVersion.Draft7), utf8WithoutByteOrderMark);
// writing the schemas has moved to the SchemaGenerator project/generate-json-schemas.sh
}
}
catch (JSchemaException jse)
Expand Down
95 changes: 95 additions & 0 deletions SchemaGenerator/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using System.Text;
using Newtonsoft.Json.Schema;
using BO4E.BO;

Console.WriteLine("Starting schema generation process...");

int offset;
string outputDirectory;

// Validate arguments
if (args.Length < 2)
{
Console.Error.WriteLine("Error: You must provide both an offset and an output directory.");
Console.Error.WriteLine("Usage: dotnet run -- <offset> <outputDirectory>");
Environment.Exit(1); // Exit with a specific error code for missing arguments
}

if (!int.TryParse(args[0], out offset))
{
Console.Error.WriteLine($"Error: Invalid argument '{args[0]}'. Please provide a valid integer offset.");
Environment.Exit(2); // Exit with a specific error code for invalid offset
}

// Get the output directory from the arguments
outputDirectory = args[1];

Console.WriteLine($"Offset provided: {offset}");
Console.WriteLine($"Output directory: {outputDirectory}");

// Generate schemas
try
{
JsonSchemaGenerator.GenerateSchemas(offset, outputDirectory);
Console.WriteLine("Schema generation completed successfully.");
}
catch (Exception ex)
{
Console.Error.WriteLine($"An unexpected error occurred: {ex.Message}");
Environment.Exit(4); // Exit with a specific error code for unexpected errors
}

Environment.Exit(0); // Success

/// <summary>
/// Generates plain JSON schemas from business object model classes.
/// </summary>
public class JsonSchemaGenerator
{
private const int LastDataRowOffset = 50;
private const int MaxSchemasPerHour = 10;

public static void GenerateSchemas(int offset, string outputDirectory)
{
var relevantBusinessObjectTypes = typeof(BusinessObject).Assembly
.GetTypes()
.Where(t => t.IsSubclassOf(typeof(BusinessObject)));

if (relevantBusinessObjectTypes.Count() > LastDataRowOffset + MaxSchemasPerHour)
{
throw new InvalidOperationException("Too many BusinessObject types. Increase the LastDataRowOffset or adjust the MaxSchemasPerHour.");
}

try
{
// Ensure the output directory exists
if (!Directory.Exists(outputDirectory))
{
Directory.CreateDirectory(outputDirectory);
}

foreach (var type in relevantBusinessObjectTypes.Skip(offset).Take(MaxSchemasPerHour))
{
var schema = BusinessObject.GetJsonSchema(type);
var path = Path.Combine(outputDirectory, $"{type.Name}.json");

Console.WriteLine($"Generating schema for {type.Name} at {path}.");

if (!File.Exists(path))
{
using (File.Create(path))
{
}
}

var utf8WithoutByteOrderMark = new UTF8Encoding(false);
File.WriteAllText(path, schema.ToString(SchemaVersion.Draft7), utf8WithoutByteOrderMark);
}
}
catch (JSchemaException jse)
{
Console.Error.WriteLine($"Schema generation failed with error: {jse.Message}");
Environment.Exit(3); // Exit with a specific error code for schema generation failure
}
}
}
14 changes: 14 additions & 0 deletions SchemaGenerator/SchemaGenerator.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\BO4E\BO4E.csproj" />
</ItemGroup>

</Project>
23 changes: 23 additions & 0 deletions SchemaGenerator/generate-json-schemas.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Cross-platform script to run the .NET console application with different offsets and an optional output directory
# Invoke it like this: powershell.exe C:/github/BO4E-dotnet2/SchemaGenerator/generate-json-schemas.sh

# Define the offsets
offsets=(10 20 30 40 50)

# Define the default output directory
default_output_directory="../json-schema-files" # json-schema-files in repo root

# Check if an output directory argument is provided
if [ $# -eq 1 ]; then
output_directory=$1
else
output_directory=$default_output_directory
fi

# Loop through the offsets and call the .NET application
for offset in "${offsets[@]}"
do
echo "Running schema generation with offset: $offset in directory: $output_directory"
# Run the .NET application
dotnet run -- $offset $output_directory
done
Loading

0 comments on commit 0637132

Please sign in to comment.