diff options
| author | Rob Mensching <rob@firegiant.com> | 2017-12-02 00:44:45 -0800 |
|---|---|---|
| committer | Rob Mensching <rob@firegiant.com> | 2017-12-02 00:44:45 -0800 |
| commit | 53e877183abe0dbbb623c39380101bc369e9f265 (patch) | |
| tree | 2b1a35e142d76013ba28d0a50e894ff477ee247a /src | |
| parent | 414bf166e07703056ad186fa8ec23a4119dd9993 (diff) | |
| download | wix-53e877183abe0dbbb623c39380101bc369e9f265.tar.gz wix-53e877183abe0dbbb623c39380101bc369e9f265.tar.bz2 wix-53e877183abe0dbbb623c39380101bc369e9f265.zip | |
Support tuples from extensions and make SourcePath a path instead of string
Diffstat (limited to 'src')
| -rw-r--r-- | src/Directory.Build.props | 4 | ||||
| -rw-r--r-- | src/WixToolset.Data/DictionaryExtensions.cs | 14 | ||||
| -rw-r--r-- | src/WixToolset.Data/ITupleDefinitionCreator.cs | 2 | ||||
| -rw-r--r-- | src/WixToolset.Data/Intermediate.cs | 170 | ||||
| -rw-r--r-- | src/WixToolset.Data/IntermediateFieldExtensions.cs | 72 | ||||
| -rw-r--r-- | src/WixToolset.Data/IntermediateFieldValueExtensions.cs | 76 | ||||
| -rw-r--r-- | src/WixToolset.Data/IntermediateSection.cs | 3 | ||||
| -rw-r--r-- | src/WixToolset.Data/IntermediateTuple.cs | 14 | ||||
| -rw-r--r-- | src/WixToolset.Data/IntermediateTupleDefinition.cs | 50 | ||||
| -rw-r--r-- | src/WixToolset.Data/IntermediateTupleExtensions.cs | 2 | ||||
| -rw-r--r-- | src/WixToolset.Data/SimpleTupleDefinitionCreator.cs | 17 | ||||
| -rw-r--r-- | src/WixToolset.Data/Tuples/WixFileTuple.cs | 4 |
12 files changed, 352 insertions, 76 deletions
diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 25cb6d36..7cd6767f 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props | |||
| @@ -5,11 +5,13 @@ | |||
| 5 | <PropertyGroup> | 5 | <PropertyGroup> |
| 6 | <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | 6 | <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
| 7 | <BaseIntermediateOutputPath>$(MSBuildThisFileDirectory)..\build\obj\$(MSBuildProjectName)\</BaseIntermediateOutputPath> | 7 | <BaseIntermediateOutputPath>$(MSBuildThisFileDirectory)..\build\obj\$(MSBuildProjectName)\</BaseIntermediateOutputPath> |
| 8 | <OutputPath>$(MSBuildThisFileDirectory)..\build\$(Configuration)\</OutputPath> | 8 | <BaseOutputPath>$(MSBuildThisFileDirectory)..\build\$(Configuration)\</BaseOutputPath> |
| 9 | <OutputPath>$(BaseOutputPath)</OutputPath> | ||
| 9 | 10 | ||
| 10 | <Authors>WiX Toolset Team</Authors> | 11 | <Authors>WiX Toolset Team</Authors> |
| 11 | <Company>WiX Toolset</Company> | 12 | <Company>WiX Toolset</Company> |
| 12 | <Copyright>Copyright (c) .NET Foundation and contributors. All rights reserved.</Copyright> | 13 | <Copyright>Copyright (c) .NET Foundation and contributors. All rights reserved.</Copyright> |
| 14 | <Product>WiX Toolset</Product> | ||
| 13 | </PropertyGroup> | 15 | </PropertyGroup> |
| 14 | 16 | ||
| 15 | <PropertyGroup> | 17 | <PropertyGroup> |
diff --git a/src/WixToolset.Data/DictionaryExtensions.cs b/src/WixToolset.Data/DictionaryExtensions.cs new file mode 100644 index 00000000..cb6647ff --- /dev/null +++ b/src/WixToolset.Data/DictionaryExtensions.cs | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Data | ||
| 4 | { | ||
| 5 | using System.Collections.Generic; | ||
| 6 | |||
| 7 | internal static class DictionaryExtensions | ||
| 8 | { | ||
| 9 | public static V GetValueOrDefault<K, V>(this IDictionary<K, V> dictionary, K key, V defaultValue = default(V)) | ||
| 10 | { | ||
| 11 | return dictionary.TryGetValue(key, out var value) ? value : defaultValue; | ||
| 12 | } | ||
| 13 | } | ||
| 14 | } | ||
diff --git a/src/WixToolset.Data/ITupleDefinitionCreator.cs b/src/WixToolset.Data/ITupleDefinitionCreator.cs index 63477314..7d818be1 100644 --- a/src/WixToolset.Data/ITupleDefinitionCreator.cs +++ b/src/WixToolset.Data/ITupleDefinitionCreator.cs | |||
| @@ -4,6 +4,8 @@ namespace WixToolset.Data | |||
| 4 | { | 4 | { |
| 5 | public interface ITupleDefinitionCreator | 5 | public interface ITupleDefinitionCreator |
| 6 | { | 6 | { |
| 7 | void AddCustomTupleDefinition(IntermediateTupleDefinition definition); | ||
| 8 | |||
| 7 | bool TryGetTupleDefinitionByName(string name, out IntermediateTupleDefinition tupleDefinition); | 9 | bool TryGetTupleDefinitionByName(string name, out IntermediateTupleDefinition tupleDefinition); |
| 8 | } | 10 | } |
| 9 | } | 11 | } |
diff --git a/src/WixToolset.Data/Intermediate.cs b/src/WixToolset.Data/Intermediate.cs index b03492ce..4d4e17cc 100644 --- a/src/WixToolset.Data/Intermediate.cs +++ b/src/WixToolset.Data/Intermediate.cs | |||
| @@ -4,6 +4,7 @@ namespace WixToolset.Data | |||
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
| 7 | using System.Linq; | ||
| 7 | using System.IO; | 8 | using System.IO; |
| 8 | using SimpleJson; | 9 | using SimpleJson; |
| 9 | 10 | ||
| @@ -96,8 +97,23 @@ namespace WixToolset.Data | |||
| 96 | /// <returns>Returns the loaded intermediate.</returns> | 97 | /// <returns>Returns the loaded intermediate.</returns> |
| 97 | public static Intermediate Load(string path, bool suppressVersionCheck = false) | 98 | public static Intermediate Load(string path, bool suppressVersionCheck = false) |
| 98 | { | 99 | { |
| 100 | using (var stream = File.OpenRead(path)) | ||
| 101 | { | ||
| 102 | var creator = new SimpleTupleDefinitionCreator(); | ||
| 103 | return Intermediate.Load(stream, path, creator, suppressVersionCheck); | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | /// <summary> | ||
| 108 | /// Loads an intermediate from a stream. | ||
| 109 | /// </summary> | ||
| 110 | /// <param name="stream">Stream to intermediate file.</param> | ||
| 111 | /// <param name="suppressVersionCheck">Suppress checking for wix.dll version mismatches.</param> | ||
| 112 | /// <returns>Returns the loaded intermediate.</returns> | ||
| 113 | public static Intermediate Load(Stream stream, bool suppressVersionCheck = false) | ||
| 114 | { | ||
| 99 | var creator = new SimpleTupleDefinitionCreator(); | 115 | var creator = new SimpleTupleDefinitionCreator(); |
| 100 | return Intermediate.Load(path, creator, suppressVersionCheck); | 116 | return Intermediate.Load(stream, creator, suppressVersionCheck); |
| 101 | } | 117 | } |
| 102 | 118 | ||
| 103 | /// <summary> | 119 | /// <summary> |
| @@ -109,51 +125,22 @@ namespace WixToolset.Data | |||
| 109 | /// <returns>Returns the loaded intermediate.</returns> | 125 | /// <returns>Returns the loaded intermediate.</returns> |
| 110 | public static Intermediate Load(string path, ITupleDefinitionCreator creator, bool suppressVersionCheck = false) | 126 | public static Intermediate Load(string path, ITupleDefinitionCreator creator, bool suppressVersionCheck = false) |
| 111 | { | 127 | { |
| 112 | JsonObject jsonObject; | 128 | using (var stream = File.OpenRead(path)) |
| 113 | |||
| 114 | using (FileStream stream = File.OpenRead(path)) | ||
| 115 | using (FileStructure fs = FileStructure.Read(stream)) | ||
| 116 | { | ||
| 117 | if (FileFormat.WixIR != fs.FileFormat) | ||
| 118 | { | ||
| 119 | throw new WixUnexpectedFileFormatException(path, FileFormat.WixIR, fs.FileFormat); | ||
| 120 | } | ||
| 121 | |||
| 122 | var json = fs.GetData(); | ||
| 123 | jsonObject = SimpleJson.DeserializeObject(json) as JsonObject; | ||
| 124 | } | ||
| 125 | |||
| 126 | if (!suppressVersionCheck) | ||
| 127 | { | 129 | { |
| 128 | var versionJson = jsonObject.GetValueOrDefault<string>("version"); | 130 | return Intermediate.Load(stream, path, creator, suppressVersionCheck); |
| 129 | |||
| 130 | if (!Version.TryParse(versionJson, out var version) || !Intermediate.CurrentVersion.Equals(version)) | ||
| 131 | { | ||
| 132 | throw new WixException(WixDataErrors.VersionMismatch(SourceLineNumber.CreateFromUri(path), "intermediate", versionJson, Intermediate.CurrentVersion.ToString())); | ||
| 133 | } | ||
| 134 | } | 131 | } |
| 132 | } | ||
| 135 | 133 | ||
| 136 | var id = jsonObject.GetValueOrDefault<string>("id"); | 134 | /// <summary> |
| 137 | 135 | /// Loads an intermediate from a path on disk. | |
| 138 | var sections = new List<IntermediateSection>(); | 136 | /// </summary> |
| 139 | 137 | /// <param name="stream">Stream to intermediate file.</param> | |
| 140 | var sectionsJson = jsonObject.GetValueOrDefault<JsonArray>("sections"); | 138 | /// <param name="creator">ITupleDefinitionCreator to use when reconstituting the intermediate.</param> |
| 141 | foreach (JsonObject sectionJson in sectionsJson) | 139 | /// <param name="suppressVersionCheck">Suppress checking for wix.dll version mismatches.</param> |
| 142 | { | 140 | /// <returns>Returns the loaded intermediate.</returns> |
| 143 | var section = IntermediateSection.Deserialize(creator, sectionJson); | 141 | public static Intermediate Load(Stream stream, ITupleDefinitionCreator creator, bool suppressVersionCheck = false) |
| 144 | sections.Add(section); | 142 | { |
| 145 | } | 143 | return Load(stream, "<unknown>", creator, suppressVersionCheck); |
| 146 | |||
| 147 | var localizations = new Dictionary<string, Localization>(StringComparer.OrdinalIgnoreCase); | ||
| 148 | |||
| 149 | //var localizationsJson = jsonObject.GetValueOrDefault<JsonArray>("localizations") ?? new JsonArray(); | ||
| 150 | //foreach (JsonObject localizationJson in localizationsJson) | ||
| 151 | //{ | ||
| 152 | // var localization = Localization.Deserialize(localizationJson); | ||
| 153 | // localizations.Add(localization.Culture, localization); | ||
| 154 | //} | ||
| 155 | |||
| 156 | return new Intermediate(id, sections, localizations, null); | ||
| 157 | } | 144 | } |
| 158 | 145 | ||
| 159 | /// <summary> | 146 | /// <summary> |
| @@ -183,6 +170,21 @@ namespace WixToolset.Data | |||
| 183 | 170 | ||
| 184 | jsonObject.Add("sections", sectionsJson); | 171 | jsonObject.Add("sections", sectionsJson); |
| 185 | 172 | ||
| 173 | var customDefinitions = GetCustomDefinitionsInSections(); | ||
| 174 | |||
| 175 | if (customDefinitions.Count > 0) | ||
| 176 | { | ||
| 177 | var customDefinitionsJson = new JsonArray(customDefinitions.Count); | ||
| 178 | |||
| 179 | foreach (var kvp in customDefinitions.OrderBy(d => d.Key)) | ||
| 180 | { | ||
| 181 | var customDefinitionJson = kvp.Value.Serialize(); | ||
| 182 | customDefinitionsJson.Add(customDefinitionJson); | ||
| 183 | } | ||
| 184 | |||
| 185 | jsonObject.Add("definitions", customDefinitionsJson); | ||
| 186 | } | ||
| 187 | |||
| 186 | //if (this.Localizations.Any()) | 188 | //if (this.Localizations.Any()) |
| 187 | //{ | 189 | //{ |
| 188 | // var localizationsJson = new JsonArray(); | 190 | // var localizationsJson = new JsonArray(); |
| @@ -200,6 +202,73 @@ namespace WixToolset.Data | |||
| 200 | } | 202 | } |
| 201 | } | 203 | } |
| 202 | 204 | ||
| 205 | /// <summary> | ||
| 206 | /// Loads an intermediate from a path on disk. | ||
| 207 | /// </summary> | ||
| 208 | /// <param name="stream">Stream to intermediate file.</param> | ||
| 209 | /// <param name="path">Path name of intermediate file.</param> | ||
| 210 | /// <param name="creator">ITupleDefinitionCreator to use when reconstituting the intermediate.</param> | ||
| 211 | /// <param name="suppressVersionCheck">Suppress checking for wix.dll version mismatches.</param> | ||
| 212 | /// <returns>Returns the loaded intermediate.</returns> | ||
| 213 | internal static Intermediate Load(Stream stream, string path, ITupleDefinitionCreator creator, bool suppressVersionCheck = false) | ||
| 214 | { | ||
| 215 | JsonObject jsonObject; | ||
| 216 | |||
| 217 | using (var fs = FileStructure.Read(stream)) | ||
| 218 | { | ||
| 219 | if (FileFormat.WixIR != fs.FileFormat) | ||
| 220 | { | ||
| 221 | throw new WixUnexpectedFileFormatException(path, FileFormat.WixIR, fs.FileFormat); | ||
| 222 | } | ||
| 223 | |||
| 224 | var json = fs.GetData(); | ||
| 225 | jsonObject = SimpleJson.DeserializeObject(json) as JsonObject; | ||
| 226 | } | ||
| 227 | |||
| 228 | if (!suppressVersionCheck) | ||
| 229 | { | ||
| 230 | var versionJson = jsonObject.GetValueOrDefault<string>("version"); | ||
| 231 | |||
| 232 | if (!Version.TryParse(versionJson, out var version) || !Intermediate.CurrentVersion.Equals(version)) | ||
| 233 | { | ||
| 234 | throw new WixException(WixDataErrors.VersionMismatch(SourceLineNumber.CreateFromUri(path), "intermediate", versionJson, Intermediate.CurrentVersion.ToString())); | ||
| 235 | } | ||
| 236 | } | ||
| 237 | |||
| 238 | var definitionsJson = jsonObject.GetValueOrDefault<JsonArray>("definitions"); | ||
| 239 | |||
| 240 | if (definitionsJson != null) | ||
| 241 | { | ||
| 242 | foreach (JsonObject definitionJson in definitionsJson) | ||
| 243 | { | ||
| 244 | var definition = IntermediateTupleDefinition.Deserialize(definitionJson); | ||
| 245 | creator.AddCustomTupleDefinition(definition); | ||
| 246 | } | ||
| 247 | } | ||
| 248 | |||
| 249 | var id = jsonObject.GetValueOrDefault<string>("id"); | ||
| 250 | |||
| 251 | var sections = new List<IntermediateSection>(); | ||
| 252 | |||
| 253 | var sectionsJson = jsonObject.GetValueOrDefault<JsonArray>("sections"); | ||
| 254 | foreach (JsonObject sectionJson in sectionsJson) | ||
| 255 | { | ||
| 256 | var section = IntermediateSection.Deserialize(creator, sectionJson); | ||
| 257 | sections.Add(section); | ||
| 258 | } | ||
| 259 | |||
| 260 | var localizations = new Dictionary<string, Localization>(StringComparer.OrdinalIgnoreCase); | ||
| 261 | |||
| 262 | //var localizationsJson = jsonObject.GetValueOrDefault<JsonArray>("localizations") ?? new JsonArray(); | ||
| 263 | //foreach (JsonObject localizationJson in localizationsJson) | ||
| 264 | //{ | ||
| 265 | // var localization = Localization.Deserialize(localizationJson); | ||
| 266 | // localizations.Add(localization.Culture, localization); | ||
| 267 | //} | ||
| 268 | |||
| 269 | return new Intermediate(id, sections, localizations, null); | ||
| 270 | } | ||
| 271 | |||
| 203 | #if false | 272 | #if false |
| 204 | /// <summary> | 273 | /// <summary> |
| 205 | /// Loads an intermediate from a path on disk. | 274 | /// Loads an intermediate from a path on disk. |
| @@ -344,5 +413,20 @@ namespace WixToolset.Data | |||
| 344 | writer.WriteEndElement(); | 413 | writer.WriteEndElement(); |
| 345 | } | 414 | } |
| 346 | #endif | 415 | #endif |
| 416 | |||
| 417 | private Dictionary<string, IntermediateTupleDefinition> GetCustomDefinitionsInSections() | ||
| 418 | { | ||
| 419 | var customDefinitions = new Dictionary<string, IntermediateTupleDefinition>(); | ||
| 420 | |||
| 421 | foreach (var tuple in this.Sections.SelectMany(s => s.Tuples).Where(t => t.Definition.Type == TupleDefinitionType.MustBeFromAnExtension)) | ||
| 422 | { | ||
| 423 | if (!customDefinitions.ContainsKey(tuple.Definition.Name)) | ||
| 424 | { | ||
| 425 | customDefinitions.Add(tuple.Definition.Name, tuple.Definition); | ||
| 426 | } | ||
| 427 | } | ||
| 428 | |||
| 429 | return customDefinitions; | ||
| 430 | } | ||
| 347 | } | 431 | } |
| 348 | } | 432 | } |
diff --git a/src/WixToolset.Data/IntermediateFieldExtensions.cs b/src/WixToolset.Data/IntermediateFieldExtensions.cs index c551b455..be225452 100644 --- a/src/WixToolset.Data/IntermediateFieldExtensions.cs +++ b/src/WixToolset.Data/IntermediateFieldExtensions.cs | |||
| @@ -11,6 +11,8 @@ namespace WixToolset.Data | |||
| 11 | 11 | ||
| 12 | public static IntermediateField Set(this IntermediateField field, object value) | 12 | public static IntermediateField Set(this IntermediateField field, object value) |
| 13 | { | 13 | { |
| 14 | var data = value; | ||
| 15 | |||
| 14 | if (field == null) | 16 | if (field == null) |
| 15 | { | 17 | { |
| 16 | throw new ArgumentNullException(nameof(field)); | 18 | throw new ArgumentNullException(nameof(field)); |
| @@ -21,30 +23,72 @@ namespace WixToolset.Data | |||
| 21 | } | 23 | } |
| 22 | else if (field.Type == IntermediateFieldType.Bool && !(value is bool)) | 24 | else if (field.Type == IntermediateFieldType.Bool && !(value is bool)) |
| 23 | { | 25 | { |
| 24 | throw new ArgumentException(nameof(value)); | 26 | if (value is int) |
| 27 | { | ||
| 28 | data = ((int)value) != 0; | ||
| 29 | } | ||
| 30 | else if (value is string str) | ||
| 31 | { | ||
| 32 | if (str.Equals("yes", StringComparison.OrdinalIgnoreCase) || str.Equals("true", StringComparison.OrdinalIgnoreCase)) | ||
| 33 | { | ||
| 34 | data = true; | ||
| 35 | } | ||
| 36 | else if (str.Equals("no", StringComparison.OrdinalIgnoreCase) || str.Equals("false", StringComparison.OrdinalIgnoreCase)) | ||
| 37 | { | ||
| 38 | data = false; | ||
| 39 | } | ||
| 40 | else | ||
| 41 | { | ||
| 42 | throw new ArgumentException(nameof(value)); | ||
| 43 | } | ||
| 44 | } | ||
| 45 | else | ||
| 46 | { | ||
| 47 | throw new ArgumentException(nameof(value)); | ||
| 48 | } | ||
| 25 | } | 49 | } |
| 26 | else if (field.Type == IntermediateFieldType.Number && !(value is int)) | 50 | else if (field.Type == IntermediateFieldType.Number && !(value is int)) |
| 27 | { | 51 | { |
| 28 | throw new ArgumentException(nameof(value)); | 52 | if (value is string str && Int32.TryParse(str, out var number)) |
| 53 | { | ||
| 54 | data = number; | ||
| 55 | } | ||
| 56 | else | ||
| 57 | { | ||
| 58 | throw new ArgumentException(nameof(value)); | ||
| 59 | } | ||
| 29 | } | 60 | } |
| 30 | else if (field.Type == IntermediateFieldType.String && !(value is string)) | 61 | else if (field.Type == IntermediateFieldType.String && !(value is string)) |
| 31 | { | 62 | { |
| 32 | throw new ArgumentException(nameof(value)); | 63 | if (value is int) |
| 33 | } | 64 | { |
| 34 | else if (field.Type == IntermediateFieldType.Path && !(value is IntermediateFieldPathValue || value is string)) | 65 | data = value.ToString(); |
| 35 | { | 66 | } |
| 36 | throw new ArgumentException(nameof(value)); | 67 | else if (value is bool b) |
| 37 | } | 68 | { |
| 38 | 69 | data = b ? "true" : "false"; | |
| 39 | if (field.Type == IntermediateFieldType.Path && value != null && value is string) | 70 | } |
| 40 | { | 71 | else |
| 41 | value = new IntermediateFieldPathValue { Path = (string)value }; | 72 | { |
| 73 | throw new ArgumentException(nameof(value)); | ||
| 74 | } | ||
| 75 | } | ||
| 76 | else if (field.Type == IntermediateFieldType.Path && !(value is IntermediateFieldPathValue)) | ||
| 77 | { | ||
| 78 | if (value is string str) | ||
| 79 | { | ||
| 80 | data = new IntermediateFieldPathValue { Path = str }; | ||
| 81 | } | ||
| 82 | else | ||
| 83 | { | ||
| 84 | throw new ArgumentException(nameof(value)); | ||
| 85 | } | ||
| 42 | } | 86 | } |
| 43 | 87 | ||
| 44 | field.Value = new IntermediateFieldValue | 88 | field.Value = new IntermediateFieldValue |
| 45 | { | 89 | { |
| 46 | Context = valueContext, | 90 | Context = valueContext, |
| 47 | Data = value, | 91 | Data = data, |
| 48 | PreviousValue = field.Value | 92 | PreviousValue = field.Value |
| 49 | }; | 93 | }; |
| 50 | 94 | ||
| @@ -103,7 +147,7 @@ namespace WixToolset.Data | |||
| 103 | return field.Value.AsNumber() != 0; | 147 | return field.Value.AsNumber() != 0; |
| 104 | 148 | ||
| 105 | case IntermediateFieldType.String: | 149 | case IntermediateFieldType.String: |
| 106 | return !System.String.IsNullOrEmpty(field.Value.AsString()); | 150 | return !String.IsNullOrEmpty(field.Value.AsString()); |
| 107 | 151 | ||
| 108 | default: | 152 | default: |
| 109 | throw new InvalidCastException($"Cannot convert field {field.Name} with type {field.Type} to boolean"); | 153 | throw new InvalidCastException($"Cannot convert field {field.Name} with type {field.Type} to boolean"); |
diff --git a/src/WixToolset.Data/IntermediateFieldValueExtensions.cs b/src/WixToolset.Data/IntermediateFieldValueExtensions.cs index bc106d4b..9a4237d8 100644 --- a/src/WixToolset.Data/IntermediateFieldValueExtensions.cs +++ b/src/WixToolset.Data/IntermediateFieldValueExtensions.cs | |||
| @@ -2,26 +2,71 @@ | |||
| 2 | 2 | ||
| 3 | namespace WixToolset.Data | 3 | namespace WixToolset.Data |
| 4 | { | 4 | { |
| 5 | using System; | ||
| 6 | |||
| 5 | public static class IntermediateFieldValueExtensions | 7 | public static class IntermediateFieldValueExtensions |
| 6 | { | 8 | { |
| 7 | public static bool AsBool(this IntermediateFieldValue value) | 9 | public static bool AsBool(this IntermediateFieldValue value) |
| 8 | { | 10 | { |
| 9 | return value?.Data == null ? false : (bool)value.Data; | 11 | var result = value.AsNullableBool(); |
| 12 | return result.HasValue && result.Value; | ||
| 10 | } | 13 | } |
| 11 | 14 | ||
| 12 | public static bool? AsNullableBool(this IntermediateFieldValue value) | 15 | public static bool? AsNullableBool(this IntermediateFieldValue value) |
| 13 | { | 16 | { |
| 14 | return (bool?)value?.Data; | 17 | if (value?.Data == null) |
| 18 | { | ||
| 19 | return null; | ||
| 20 | } | ||
| 21 | else if (value.Data is bool b) | ||
| 22 | { | ||
| 23 | return b; | ||
| 24 | } | ||
| 25 | else if (value.Data is int n) | ||
| 26 | { | ||
| 27 | return n != 0; | ||
| 28 | } | ||
| 29 | else if (value.Data is string s) | ||
| 30 | { | ||
| 31 | if (s.Equals("yes", StringComparison.OrdinalIgnoreCase) || s.Equals("true", StringComparison.OrdinalIgnoreCase)) | ||
| 32 | { | ||
| 33 | return true; | ||
| 34 | } | ||
| 35 | else if (s.Equals("no", StringComparison.OrdinalIgnoreCase) || s.Equals("false", StringComparison.OrdinalIgnoreCase)) | ||
| 36 | { | ||
| 37 | return false; | ||
| 38 | } | ||
| 39 | } | ||
| 40 | |||
| 41 | return (bool)value.Data; | ||
| 15 | } | 42 | } |
| 16 | 43 | ||
| 17 | public static int AsNumber(this IntermediateFieldValue value) | 44 | public static int AsNumber(this IntermediateFieldValue value) |
| 18 | { | 45 | { |
| 19 | return value?.Data == null ? 0 : (int)value.Data; | 46 | var result = value.AsNullableNumber(); |
| 47 | return result ?? 0; | ||
| 20 | } | 48 | } |
| 21 | 49 | ||
| 22 | public static int? AsNullableNumber(this IntermediateFieldValue value) | 50 | public static int? AsNullableNumber(this IntermediateFieldValue value) |
| 23 | { | 51 | { |
| 24 | return (int?)value?.Data; | 52 | if (value?.Data == null) |
| 53 | { | ||
| 54 | return null; | ||
| 55 | } | ||
| 56 | else if (value.Data is int n) | ||
| 57 | { | ||
| 58 | return n; | ||
| 59 | } | ||
| 60 | else if (value.Data is bool b) | ||
| 61 | { | ||
| 62 | return b ? 1 : 0; | ||
| 63 | } | ||
| 64 | else if (value.Data is string s) | ||
| 65 | { | ||
| 66 | return Convert.ToInt32(s); | ||
| 67 | } | ||
| 68 | |||
| 69 | return (int)value.Data; | ||
| 25 | } | 70 | } |
| 26 | 71 | ||
| 27 | public static IntermediateFieldPathValue AsPath(this IntermediateFieldValue value) | 72 | public static IntermediateFieldPathValue AsPath(this IntermediateFieldValue value) |
| @@ -31,7 +76,28 @@ namespace WixToolset.Data | |||
| 31 | 76 | ||
| 32 | public static string AsString(this IntermediateFieldValue value) | 77 | public static string AsString(this IntermediateFieldValue value) |
| 33 | { | 78 | { |
| 34 | return (string)value?.Data; | 79 | if (value?.Data == null) |
| 80 | { | ||
| 81 | return null; | ||
| 82 | } | ||
| 83 | else if (value.Data is string s) | ||
| 84 | { | ||
| 85 | return s; | ||
| 86 | } | ||
| 87 | else if (value.Data is int n) | ||
| 88 | { | ||
| 89 | return n.ToString(); | ||
| 90 | } | ||
| 91 | else if (value.Data is bool b) | ||
| 92 | { | ||
| 93 | return b ? "true" : "false"; | ||
| 94 | } | ||
| 95 | else if (value.Data is IntermediateFieldPathValue p) | ||
| 96 | { | ||
| 97 | return p.Path; | ||
| 98 | } | ||
| 99 | |||
| 100 | return (string)value.Data; | ||
| 35 | } | 101 | } |
| 36 | } | 102 | } |
| 37 | } | 103 | } |
diff --git a/src/WixToolset.Data/IntermediateSection.cs b/src/WixToolset.Data/IntermediateSection.cs index 2b1f7375..5d17eb31 100644 --- a/src/WixToolset.Data/IntermediateSection.cs +++ b/src/WixToolset.Data/IntermediateSection.cs | |||
| @@ -66,7 +66,6 @@ namespace WixToolset.Data | |||
| 66 | var codepage = jsonObject.GetValueOrDefault("codepage", 0); | 66 | var codepage = jsonObject.GetValueOrDefault("codepage", 0); |
| 67 | var id = jsonObject.GetValueOrDefault<string>("id"); | 67 | var id = jsonObject.GetValueOrDefault<string>("id"); |
| 68 | var type = jsonObject.GetEnumOrDefault("type", SectionType.Unknown); | 68 | var type = jsonObject.GetEnumOrDefault("type", SectionType.Unknown); |
| 69 | var tuplesJson = jsonObject.GetValueOrDefault<JsonArray>("tuples"); | ||
| 70 | 69 | ||
| 71 | if (null == id && (SectionType.Unknown != type && SectionType.Fragment != type)) | 70 | if (null == id && (SectionType.Unknown != type && SectionType.Fragment != type)) |
| 72 | { | 71 | { |
| @@ -80,6 +79,8 @@ namespace WixToolset.Data | |||
| 80 | 79 | ||
| 81 | var section = new IntermediateSection(id, type, codepage); | 80 | var section = new IntermediateSection(id, type, codepage); |
| 82 | 81 | ||
| 82 | var tuplesJson = jsonObject.GetValueOrDefault<JsonArray>("tuples"); | ||
| 83 | |||
| 83 | foreach (JsonObject tupleJson in tuplesJson) | 84 | foreach (JsonObject tupleJson in tuplesJson) |
| 84 | { | 85 | { |
| 85 | var tuple = IntermediateTuple.Deserialize(creator, tupleJson); | 86 | var tuple = IntermediateTuple.Deserialize(creator, tupleJson); |
diff --git a/src/WixToolset.Data/IntermediateTuple.cs b/src/WixToolset.Data/IntermediateTuple.cs index 0f1e5965..cda133b5 100644 --- a/src/WixToolset.Data/IntermediateTuple.cs +++ b/src/WixToolset.Data/IntermediateTuple.cs | |||
| @@ -6,9 +6,9 @@ namespace WixToolset.Data | |||
| 6 | 6 | ||
| 7 | public class IntermediateTuple | 7 | public class IntermediateTuple |
| 8 | { | 8 | { |
| 9 | //public IntermediateTuple(IntermediateTupleDefinition definition) : this(definition, null, null) | 9 | public IntermediateTuple(IntermediateTupleDefinition definition) : this(definition, null, null) |
| 10 | //{ | 10 | { |
| 11 | //} | 11 | } |
| 12 | 12 | ||
| 13 | public IntermediateTuple(IntermediateTupleDefinition definition, SourceLineNumber sourceLineNumber, Identifier id = null) | 13 | public IntermediateTuple(IntermediateTupleDefinition definition, SourceLineNumber sourceLineNumber, Identifier id = null) |
| 14 | { | 14 | { |
| @@ -35,11 +35,11 @@ namespace WixToolset.Data | |||
| 35 | var sourceLineNumbersJson = jsonObject.GetValueOrDefault<JsonObject>("ln"); | 35 | var sourceLineNumbersJson = jsonObject.GetValueOrDefault<JsonObject>("ln"); |
| 36 | var fieldsJson = jsonObject.GetValueOrDefault<JsonArray>("fields"); | 36 | var fieldsJson = jsonObject.GetValueOrDefault<JsonArray>("fields"); |
| 37 | 37 | ||
| 38 | creator.TryGetTupleDefinitionByName(definitionName, out var definition); // TODO: this isn't sufficient. | 38 | var id = (idJson == null) ? null : Identifier.Deserialize(idJson); |
| 39 | var tuple = definition.CreateTuple(); | 39 | var sourceLineNumbers = (sourceLineNumbersJson == null) ? null : SourceLineNumber.Deserialize(sourceLineNumbersJson); |
| 40 | 40 | ||
| 41 | tuple.Id = (idJson == null) ? null : Identifier.Deserialize(idJson); | 41 | creator.TryGetTupleDefinitionByName(definitionName, out var definition); // TODO: this isn't sufficient. |
| 42 | tuple.SourceLineNumbers = (sourceLineNumbersJson == null) ? null : SourceLineNumber.Deserialize(sourceLineNumbersJson); | 42 | var tuple = definition.CreateTuple(sourceLineNumbers, id); |
| 43 | 43 | ||
| 44 | for (var i = 0; i < fieldsJson.Count; ++i) | 44 | for (var i = 0; i < fieldsJson.Count; ++i) |
| 45 | { | 45 | { |
diff --git a/src/WixToolset.Data/IntermediateTupleDefinition.cs b/src/WixToolset.Data/IntermediateTupleDefinition.cs index 5658cfe9..eb4ab12e 100644 --- a/src/WixToolset.Data/IntermediateTupleDefinition.cs +++ b/src/WixToolset.Data/IntermediateTupleDefinition.cs | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | namespace WixToolset.Data | 3 | namespace WixToolset.Data |
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using SimpleJson; | ||
| 6 | 7 | ||
| 7 | public class IntermediateTupleDefinition | 8 | public class IntermediateTupleDefinition |
| 8 | { | 9 | { |
| @@ -23,7 +24,7 @@ namespace WixToolset.Data | |||
| 23 | this.FieldDefinitions = fieldDefinitions; | 24 | this.FieldDefinitions = fieldDefinitions; |
| 24 | this.StrongTupleType = strongTupleType ?? typeof(IntermediateTuple); | 25 | this.StrongTupleType = strongTupleType ?? typeof(IntermediateTuple); |
| 25 | #if DEBUG | 26 | #if DEBUG |
| 26 | if (!this.StrongTupleType.IsSubclassOf(typeof(IntermediateTuple))) throw new ArgumentException(nameof(strongTupleType)); | 27 | if (this.StrongTupleType != typeof(IntermediateTuple) && !this.StrongTupleType.IsSubclassOf(typeof(IntermediateTuple))) throw new ArgumentException(nameof(strongTupleType)); |
| 27 | #endif | 28 | #endif |
| 28 | } | 29 | } |
| 29 | 30 | ||
| @@ -43,5 +44,52 @@ namespace WixToolset.Data | |||
| 43 | 44 | ||
| 44 | return result; | 45 | return result; |
| 45 | } | 46 | } |
| 47 | |||
| 48 | internal static IntermediateTupleDefinition Deserialize(JsonObject jsonObject) | ||
| 49 | { | ||
| 50 | var name = jsonObject.GetValueOrDefault<string>("name"); | ||
| 51 | var definitionsJson = jsonObject.GetValueOrDefault<JsonArray>("fields"); | ||
| 52 | |||
| 53 | var fieldDefinitions = new IntermediateFieldDefinition[definitionsJson.Count]; | ||
| 54 | |||
| 55 | for (var i = 0; i < definitionsJson.Count; ++i) | ||
| 56 | { | ||
| 57 | var definitionJson = (JsonObject)definitionsJson[i]; | ||
| 58 | var fieldName = definitionJson.GetValueOrDefault<string>("name"); | ||
| 59 | var fieldType = definitionJson.GetEnumOrDefault("type", IntermediateFieldType.String); | ||
| 60 | fieldDefinitions[i] = new IntermediateFieldDefinition(fieldName, fieldType); | ||
| 61 | } | ||
| 62 | |||
| 63 | return new IntermediateTupleDefinition(name, fieldDefinitions, null); | ||
| 64 | } | ||
| 65 | |||
| 66 | internal JsonObject Serialize() | ||
| 67 | { | ||
| 68 | var jsonObject = new JsonObject | ||
| 69 | { | ||
| 70 | { "name", this.Name } | ||
| 71 | }; | ||
| 72 | |||
| 73 | var fieldsJson = new JsonArray(this.FieldDefinitions.Length); | ||
| 74 | |||
| 75 | foreach (var fieldDefinition in this.FieldDefinitions) | ||
| 76 | { | ||
| 77 | var fieldJson = new JsonObject | ||
| 78 | { | ||
| 79 | { "name", fieldDefinition.Name }, | ||
| 80 | }; | ||
| 81 | |||
| 82 | if (fieldDefinition.Type != IntermediateFieldType.String) | ||
| 83 | { | ||
| 84 | fieldJson.Add("type", fieldDefinition.Type.ToString().ToLowerInvariant()); | ||
| 85 | } | ||
| 86 | |||
| 87 | fieldsJson.Add(fieldJson); | ||
| 88 | } | ||
| 89 | |||
| 90 | jsonObject.Add("fields", fieldsJson); | ||
| 91 | |||
| 92 | return jsonObject; | ||
| 93 | } | ||
| 46 | } | 94 | } |
| 47 | } | 95 | } |
diff --git a/src/WixToolset.Data/IntermediateTupleExtensions.cs b/src/WixToolset.Data/IntermediateTupleExtensions.cs index 9865c06a..615c21f9 100644 --- a/src/WixToolset.Data/IntermediateTupleExtensions.cs +++ b/src/WixToolset.Data/IntermediateTupleExtensions.cs | |||
| @@ -8,7 +8,7 @@ namespace WixToolset.Data | |||
| 8 | { | 8 | { |
| 9 | var definition = tuple.Definition.FieldDefinitions[index]; | 9 | var definition = tuple.Definition.FieldDefinitions[index]; |
| 10 | 10 | ||
| 11 | var field = tuple.Fields[index].Set(definition, value); ; | 11 | var field = tuple.Fields[index].Set(definition, value); |
| 12 | 12 | ||
| 13 | return tuple.Fields[index] = field; | 13 | return tuple.Fields[index] = field; |
| 14 | } | 14 | } |
diff --git a/src/WixToolset.Data/SimpleTupleDefinitionCreator.cs b/src/WixToolset.Data/SimpleTupleDefinitionCreator.cs index b9d0b620..6a86639a 100644 --- a/src/WixToolset.Data/SimpleTupleDefinitionCreator.cs +++ b/src/WixToolset.Data/SimpleTupleDefinitionCreator.cs | |||
| @@ -2,12 +2,27 @@ | |||
| 2 | 2 | ||
| 3 | namespace WixToolset.Data | 3 | namespace WixToolset.Data |
| 4 | { | 4 | { |
| 5 | using System.Collections.Generic; | ||
| 6 | |||
| 5 | internal class SimpleTupleDefinitionCreator : ITupleDefinitionCreator | 7 | internal class SimpleTupleDefinitionCreator : ITupleDefinitionCreator |
| 6 | { | 8 | { |
| 9 | private Dictionary<string, IntermediateTupleDefinition> CustomDefinitionByName { get; } = new Dictionary<string, IntermediateTupleDefinition>(); | ||
| 10 | |||
| 11 | public void AddCustomTupleDefinition(IntermediateTupleDefinition definition) | ||
| 12 | { | ||
| 13 | this.CustomDefinitionByName.Add(definition.Name, definition); | ||
| 14 | } | ||
| 15 | |||
| 7 | public bool TryGetTupleDefinitionByName(string name, out IntermediateTupleDefinition tupleDefinition) | 16 | public bool TryGetTupleDefinitionByName(string name, out IntermediateTupleDefinition tupleDefinition) |
| 8 | { | 17 | { |
| 9 | tupleDefinition = TupleDefinitions.ByName(name); | 18 | tupleDefinition = TupleDefinitions.ByName(name); |
| 19 | |||
| 20 | if (tupleDefinition == null) | ||
| 21 | { | ||
| 22 | tupleDefinition = this.CustomDefinitionByName.GetValueOrDefault(name); | ||
| 23 | } | ||
| 24 | |||
| 10 | return tupleDefinition != null; | 25 | return tupleDefinition != null; |
| 11 | } | 26 | } |
| 12 | } | 27 | } |
| 13 | } \ No newline at end of file | 28 | } |
diff --git a/src/WixToolset.Data/Tuples/WixFileTuple.cs b/src/WixToolset.Data/Tuples/WixFileTuple.cs index 88dc4c82..3581e2e6 100644 --- a/src/WixToolset.Data/Tuples/WixFileTuple.cs +++ b/src/WixToolset.Data/Tuples/WixFileTuple.cs | |||
| @@ -131,9 +131,9 @@ namespace WixToolset.Data.Tuples | |||
| 131 | set => this.Set((int)WixFileTupleFields.DiskId, value); | 131 | set => this.Set((int)WixFileTupleFields.DiskId, value); |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | public string Source | 134 | public IntermediateFieldPathValue Source |
| 135 | { | 135 | { |
| 136 | get => this.Fields[(int)WixFileTupleFields.Source].AsPath()?.Path; | 136 | get => this.Fields[(int)WixFileTupleFields.Source].AsPath(); |
| 137 | set => this.Set((int)WixFileTupleFields.Source, value); | 137 | set => this.Set((int)WixFileTupleFields.Source, value); |
| 138 | } | 138 | } |
| 139 | 139 | ||
