forked from angularsen/UnitsNet
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathQuantityJsonFilesParser.cs
More file actions
128 lines (116 loc) · 5.66 KB
/
QuantityJsonFilesParser.cs
File metadata and controls
128 lines (116 loc) · 5.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Licensed under MIT No Attribution, see LICENSE file at the root.
// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using CodeGen.Exceptions;
using CodeGen.Helpers;
using CodeGen.JsonTypes;
using Newtonsoft.Json;
namespace CodeGen.Generators
{
/// <summary>
/// Parses JSON files that define quantities and their units.
/// This will later be used to generate source code and can be reused for different targets such as .NET framework,
/// .NET Core, .NET nanoFramework and even other programming languages.
/// </summary>
internal static class QuantityJsonFilesParser
{
private static readonly JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings
{
// Don't override the C# default assigned values if no value is set in JSON
NullValueHandling = NullValueHandling.Ignore
};
/// <summary>
/// Parses JSON files that define quantities and their units.
/// </summary>
/// <param name="rootDir">Repository root directory, where you cloned the repo to such as "c:\dev\UnitsNet".</param>
/// <returns>The parsed quantities and their units.</returns>
public static Quantity[] ParseQuantities(string rootDir)
{
var jsonDir = Path.Combine(rootDir, "Common/UnitDefinitions");
var jsonFileNames = Directory.GetFiles(jsonDir, "*.json");
return jsonFileNames
.OrderBy(fn => fn, StringComparer.InvariantCultureIgnoreCase)
.Select(ParseQuantityFile)
.ToArray();
}
private static Quantity ParseQuantityFile(string jsonFileName)
{
try
{
var quantity = JsonConvert.DeserializeObject<Quantity>(File.ReadAllText(jsonFileName), JsonSerializerSettings)
?? throw new UnitsNetCodeGenException($"Unable to parse quantity from JSON file: {jsonFileName}");
AddPrefixUnits(quantity);
OrderUnitsByName(quantity);
return quantity;
}
catch (Exception e)
{
throw new Exception($"Error parsing quantity JSON file: {jsonFileName}", e);
}
}
private static void OrderUnitsByName(Quantity quantity)
{
quantity.Units = quantity.Units.OrderBy(u => u.SingularName, StringComparer.OrdinalIgnoreCase).ToArray();
}
private static void AddPrefixUnits(Quantity quantity)
{
var unitsToAdd = new List<Unit>();
foreach (Unit unit in quantity.Units)
foreach (Prefix prefix in unit.Prefixes)
{
try
{
var prefixInfo = PrefixInfo.Entries[prefix];
unitsToAdd.Add(new Unit
{
SingularName = $"{prefix}{unit.SingularName.ToCamelCase()}", // "Kilo" + "NewtonPerMeter" => "KilonewtonPerMeter"
PluralName = $"{prefix}{unit.PluralName.ToCamelCase()}", // "Kilo" + "NewtonsPerMeter" => "KilonewtonsPerMeter"
BaseUnits = null, // Can we determine this somehow?
FromBaseToUnitFunc = $"({unit.FromBaseToUnitFunc}) / {prefixInfo.Factor}",
FromUnitToBaseFunc = $"({unit.FromUnitToBaseFunc}) * {prefixInfo.Factor}",
Localization = GetLocalizationForPrefixUnit(unit.Localization, prefixInfo),
ObsoleteText = unit.ObsoleteText,
SkipConversionGeneration = unit.SkipConversionGeneration,
AllowAbbreviationLookup = unit.AllowAbbreviationLookup
} );
}
catch (Exception e)
{
throw new Exception($"Error parsing prefix {prefix} for unit {quantity.Name}.{unit.SingularName}.", e);
}
}
quantity.Units = quantity.Units.Concat(unitsToAdd).ToArray();
}
/// <summary>
/// Create unit abbreviations for a prefix unit, given a unit and the prefix.
/// The unit abbreviations are either prefixed with the SI prefix or an explicitly configured abbreviation via
/// <see cref="Localization.AbbreviationsForPrefixes" />.
/// </summary>
private static Localization[] GetLocalizationForPrefixUnit(IEnumerable<Localization> localizations, PrefixInfo prefixInfo)
{
return localizations.Select(loc =>
{
if (loc.TryGetAbbreviationsForPrefix(prefixInfo.Prefix, out string[]? unitAbbreviationsForPrefix))
{
return new Localization
{
Culture = loc.Culture,
Abbreviations = unitAbbreviationsForPrefix
};
}
// No prefix unit abbreviations are specified, so fall back to prepending the default SI prefix to each unit abbreviation:
// kilo ("k") + meter ("m") => kilometer ("km")
var prefix = prefixInfo.GetPrefixForCultureOrSiPrefix(loc.Culture);
unitAbbreviationsForPrefix = loc.Abbreviations.Select(unitAbbreviation => $"{prefix}{unitAbbreviation}").ToArray();
return new Localization
{
Culture = loc.Culture,
Abbreviations = unitAbbreviationsForPrefix
};
}).ToArray();
}
}
}