aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Data.WindowsInstaller/ColumnDefinition.cs
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2017-12-07 14:19:05 -0800
committerRob Mensching <rob@firegiant.com>2017-12-07 14:19:05 -0800
commit49f1209035aac1fcfad5dbbe25f7b2306d3be86c (patch)
tree6ce5921493eb751b6d89c3faf0ebdf64110cbb65 /src/WixToolset.Data.WindowsInstaller/ColumnDefinition.cs
parentb1e662bd480241ea914f0f3d6bd174d9ffd03f5f (diff)
downloadwix-49f1209035aac1fcfad5dbbe25f7b2306d3be86c.tar.gz
wix-49f1209035aac1fcfad5dbbe25f7b2306d3be86c.tar.bz2
wix-49f1209035aac1fcfad5dbbe25f7b2306d3be86c.zip
Support MSI backends creating custom tables and remove WixToolset.Data.WindowsInstaller
Diffstat (limited to 'src/WixToolset.Data.WindowsInstaller/ColumnDefinition.cs')
-rw-r--r--src/WixToolset.Data.WindowsInstaller/ColumnDefinition.cs1033
1 files changed, 0 insertions, 1033 deletions
diff --git a/src/WixToolset.Data.WindowsInstaller/ColumnDefinition.cs b/src/WixToolset.Data.WindowsInstaller/ColumnDefinition.cs
deleted file mode 100644
index 056be1e9..00000000
--- a/src/WixToolset.Data.WindowsInstaller/ColumnDefinition.cs
+++ /dev/null
@@ -1,1033 +0,0 @@
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
3namespace WixToolset.Data
4{
5 using System;
6 using System.Globalization;
7 using System.Xml;
8
9 /// <summary>
10 /// Defines MSI column types.
11 /// </summary>
12 public enum ColumnType
13 {
14 /// <summary>Unknown column type, default and invalid.</summary>
15 Unknown,
16
17 /// <summary>Column is a string.</summary>
18 String,
19
20 /// <summary>Column is a localizable string.</summary>
21 Localized,
22
23 /// <summary>Column is a number.</summary>
24 Number,
25
26 /// <summary>Column is a binary stream.</summary>
27 Object,
28
29 /// <summary>Column is a string that is preserved in transforms (like Object).</summary>
30 Preserved,
31 }
32
33 /// <summary>
34 /// Specifies if the column should be modularized.
35 /// </summary>
36 public enum ColumnModularizeType
37 {
38 /// <summary>Column should not be modularized.</summary>
39 None,
40
41 /// <summary>Column should be modularized.</summary>
42 Column,
43
44 /// <summary>When the column is an primary or foreign key to the Icon table it should be modularized special.</summary>
45 Icon,
46
47 /// <summary>When the column is a companion file it should be modularized.</summary>
48 CompanionFile,
49
50 /// <summary>Column is a condition and should be modularized.</summary>
51 Condition,
52
53 /// <summary>Special modularization type for the ControlEvent table's Argument column.</summary>
54 ControlEventArgument,
55
56 /// <summary>Special modularization type for the Control table's Text column.</summary>
57 ControlText,
58
59 /// <summary>Any Properties in the column should be modularized.</summary>
60 Property,
61
62 /// <summary>Semi-colon list of keys, all of which need to be modularized.</summary>
63 SemicolonDelimited,
64 }
65
66 /// <summary>
67 /// Column validation category type
68 /// </summary>
69 public enum ColumnCategory
70 {
71 /// <summary>Unknown category, default and invalid.</summary>
72 Unknown,
73
74 /// <summary>Text category.</summary>
75 Text,
76
77 /// <summary>UpperCase category.</summary>
78 UpperCase,
79
80 /// <summary>LowerCase category.</summary>
81 LowerCase,
82
83 /// <summary>Integer category.</summary>
84 Integer,
85
86 /// <summary>DoubleInteger category.</summary>
87 DoubleInteger,
88
89 /// <summary>TimeDate category.</summary>
90 TimeDate,
91
92 /// <summary>Identifier category.</summary>
93 Identifier,
94
95 /// <summary>Property category.</summary>
96 Property,
97
98 /// <summary>Filename category.</summary>
99 Filename,
100
101 /// <summary>WildCardFilename category.</summary>
102 WildCardFilename,
103
104 /// <summary>Path category.</summary>
105 Path,
106
107 /// <summary>Paths category.</summary>
108 Paths,
109
110 /// <summary>AnyPath category.</summary>
111 AnyPath,
112
113 /// <summary>DefaultDir category.</summary>
114 DefaultDir,
115
116 /// <summary>RegPath category.</summary>
117 RegPath,
118
119 /// <summary>Formatted category.</summary>
120 Formatted,
121
122 /// <summary>Template category.</summary>
123 Template,
124
125 /// <summary>Condition category.</summary>
126 Condition,
127
128 /// <summary>Guid category.</summary>
129 Guid,
130
131 /// <summary>Version category.</summary>
132 Version,
133
134 /// <summary>Language category.</summary>
135 Language,
136
137 /// <summary>Binary category.</summary>
138 Binary,
139
140 /// <summary>CustomSource category.</summary>
141 CustomSource,
142
143 /// <summary>Cabinet category.</summary>
144 Cabinet,
145
146 /// <summary>Shortcut category.</summary>
147 Shortcut,
148
149 /// <summary>Formatted SDDL category.</summary>
150 FormattedSDDLText,
151 }
152
153 /// <summary>
154 /// Definition of a table's column.
155 /// </summary>
156 public sealed class ColumnDefinition : IComparable<ColumnDefinition>
157 {
158 private string name;
159 private ColumnType type;
160 private int length;
161 private bool primaryKey;
162 private bool nullable;
163 private ColumnModularizeType modularize;
164 private bool localizable;
165 private bool added;
166
167 private bool minValueSet;
168 private long minValue;
169 private bool maxValueSet;
170 private long maxValue;
171 private string keyTable;
172 private bool keyColumnSet;
173 private int keyColumn;
174 private ColumnCategory category;
175 private string possibilities;
176 private string description;
177 private bool escapeIdtCharacters;
178 private bool useCData;
179
180 /// <summary>
181 /// Creates a new column definition.
182 /// </summary>
183 /// <param name="name">Name of column.</param>
184 /// <param name="type">Type of column</param>
185 /// <param name="length">Length of column.</param>
186 /// <param name="primaryKey">If column is primary key.</param>
187 /// <param name="nullable">If column is nullable.</param>
188 /// <param name="modularizeType">Type of modularization for column</param>
189 /// <param name="localizable">If the column is localizable.</param>
190 /// <param name="minValueSet">If the minimum of the value was set.</param>
191 /// <param name="minValue">Minimum value for the column.</param>
192 /// <param name="maxValueSet">If the maximum value was set.</param>
193 /// <param name="maxValue">Maximum value for the colum.</param>
194 /// <param name="keyTable">Optional name of table for foreign key.</param>
195 /// <param name="keyColumnSet">If the key column was set.</param>
196 /// <param name="keyColumn">Optional name of column for foreign key.</param>
197 /// <param name="category">Validation category for column.</param>
198 /// <param name="possibilities">Set of possible values for column.</param>
199 /// <param name="description">Description of column in vaidation table.</param>
200 /// <param name="escapeIdtCharacters">If characters should be escaped in IDT.</param>
201 /// <param name="useCData">If whitespace should be preserved in a CDATA node.</param>
202 public ColumnDefinition(string name, ColumnType type, int length, bool primaryKey, bool nullable, ColumnModularizeType modularizeType, bool localizable, bool minValueSet, long minValue, bool maxValueSet, long maxValue, string keyTable, bool keyColumnSet, int keyColumn, ColumnCategory category, string possibilities, string description, bool escapeIdtCharacters, bool useCData)
203 {
204 this.name = name;
205 this.type = type;
206 this.length = length;
207 this.primaryKey = primaryKey;
208 this.nullable = nullable;
209 this.modularize = modularizeType;
210 this.localizable = localizable;
211 this.minValueSet = minValueSet;
212 this.minValue = minValue;
213 this.maxValueSet = maxValueSet;
214 this.maxValue = maxValue;
215 this.keyTable = keyTable;
216 this.keyColumnSet = keyColumnSet;
217 this.keyColumn = keyColumn;
218 this.category = category;
219 this.possibilities = possibilities;
220 this.description = description;
221 this.escapeIdtCharacters = escapeIdtCharacters;
222 this.useCData = useCData;
223 }
224
225 /// <summary>
226 /// Gets whether this column was added via a transform.
227 /// </summary>
228 /// <value>Whether this column was added via a transform.</value>
229 public bool Added
230 {
231 get { return this.added; }
232 set { this.added = value; }
233 }
234
235 /// <summary>
236 /// Gets the name of the column.
237 /// </summary>
238 /// <value>Name of column.</value>
239 public string Name
240 {
241 get { return this.name; }
242 }
243
244 /// <summary>
245 /// Gets the type of the column.
246 /// </summary>
247 /// <value>Type of column.</value>
248 public ColumnType Type
249 {
250 get { return this.type; }
251 }
252
253 /// <summary>
254 /// Gets the length of the column.
255 /// </summary>
256 /// <value>Length of column.</value>
257 public int Length
258 {
259 get { return this.length; }
260 }
261
262 /// <summary>
263 /// Gets if the column is a primary key.
264 /// </summary>
265 /// <value>true if column is primary key.</value>
266 public bool PrimaryKey
267 {
268 get { return this.primaryKey; }
269 }
270
271 /// <summary>
272 /// Gets if the column is nullable.
273 /// </summary>
274 /// <value>true if column is nullable.</value>
275 public bool Nullable
276 {
277 get { return this.nullable; }
278 }
279
280 /// <summary>
281 /// Gets the type of modularization for this column.
282 /// </summary>
283 /// <value>Column's modularization type.</value>
284 public ColumnModularizeType ModularizeType
285 {
286 get { return this.modularize; }
287 }
288
289 /// <summary>
290 /// Gets if the column is localizable. Can be because the type is localizable, or because the column
291 /// was explicitly set to be so.
292 /// </summary>
293 /// <value>true if column is localizable.</value>
294 public bool IsLocalizable
295 {
296 get { return this.localizable || ColumnType.Localized == this.Type; }
297 }
298
299 /// <summary>
300 /// Gets if the minimum value of the column is set.
301 /// </summary>
302 /// <value>true if minimum value is set.</value>
303 public bool IsMinValueSet
304 {
305 get { return this.minValueSet; }
306 }
307
308 /// <summary>
309 /// Gets the minimum value for the column, only valid if IsMinValueSet returns true.
310 /// </summary>
311 /// <value>Minimum value for the column.</value>
312 public long MinValue
313 {
314 get { return this.minValue; }
315 }
316
317 /// <summary>
318 /// Gets if the maximum value of the column is set.
319 /// </summary>
320 /// <value>true if maximum value is set.</value>
321 public bool IsMaxValueSet
322 {
323 get { return this.maxValueSet; }
324 }
325
326 /// <summary>
327 /// Gets the maximum value for the column, only valid if IsMinValueSet returns true.
328 /// </summary>
329 /// <value>Maximum value for the column.</value>
330 public long MaxValue
331 {
332 get { return this.maxValue; }
333 }
334
335 /// <summary>
336 /// Gets the table that has the foreign key for this column
337 /// </summary>
338 /// <value>Foreign key table name.</value>
339 public string KeyTable
340 {
341 get { return this.keyTable; }
342 }
343
344 /// <summary>
345 /// Gets if the key column is set.
346 /// </summary>
347 /// <value>True if the key column is set.</value>
348 public bool IsKeyColumnSet
349 {
350 get { return this.keyColumnSet; }
351 }
352
353 /// <summary>
354 /// Gets the foreign key column that this column refers to.
355 /// </summary>
356 /// <value>Foreign key column.</value>
357 public int KeyColumn
358 {
359 get { return this.keyColumn; }
360 }
361
362 /// <summary>
363 /// Gets the validation category for this column.
364 /// </summary>
365 /// <value>Validation category.</value>
366 public ColumnCategory Category
367 {
368 get { return this.category; }
369 }
370
371 /// <summary>
372 /// Gets the set of possibilities for this column.
373 /// </summary>
374 /// <value>Set of possibilities for this column.</value>
375 public string Possibilities
376 {
377 get { return this.possibilities; }
378 }
379
380 /// <summary>
381 /// Gets the description for this column.
382 /// </summary>
383 /// <value>Description of column.</value>
384 public string Description
385 {
386 get { return this.description; }
387 }
388
389 /// <summary>
390 /// Gets if characters should be escaped to fit into IDT.
391 /// </summary>
392 /// <value>true if data should be escaped when adding to IDT.</value>
393 public bool EscapeIdtCharacters
394 {
395 get { return this.escapeIdtCharacters; }
396 }
397
398 /// <summary>
399 /// Gets if whitespace should be preserved in a CDATA node.
400 /// </summary>
401 /// <value>true if whitespace should be preserved in a CDATA node.</value>
402 public bool UseCData
403 {
404 get { return this.useCData; }
405 }
406
407 /// <summary>
408 /// Gets the type of the column in IDT format.
409 /// </summary>
410 /// <value>IDT format for column type.</value>
411 public string IdtType
412 {
413 get
414 {
415 char typeCharacter;
416 switch (this.type)
417 {
418 case ColumnType.Number:
419 typeCharacter = this.nullable ? 'I' : 'i';
420 break;
421 case ColumnType.Preserved:
422 case ColumnType.String:
423 typeCharacter = this.nullable ? 'S' : 's';
424 break;
425 case ColumnType.Localized:
426 typeCharacter = this.nullable ? 'L' : 'l';
427 break;
428 case ColumnType.Object:
429 typeCharacter = this.nullable ? 'V' : 'v';
430 break;
431 default:
432 throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixDataStrings.EXP_UnknownColumnType, this.type));
433 }
434
435 return String.Concat(typeCharacter, this.length);
436 }
437 }
438
439 /// <summary>
440 /// Parses a column definition in a table definition.
441 /// </summary>
442 /// <param name="reader">Reader to get data from.</param>
443 /// <returns>The ColumnDefintion represented by the Xml.</returns>
444 internal static ColumnDefinition Read(XmlReader reader)
445 {
446 if (!reader.LocalName.Equals("columnDefinition"))
447 {
448 throw new XmlException();
449 }
450
451 bool added = false;
452 ColumnCategory category = ColumnCategory.Unknown;
453 string description = null;
454 bool empty = reader.IsEmptyElement;
455 bool escapeIdtCharacters = false;
456 int keyColumn = -1;
457 bool keyColumnSet = false;
458 string keyTable = null;
459 int length = -1;
460 bool localizable = false;
461 long maxValue = 0;
462 bool maxValueSet = false;
463 long minValue = 0;
464 bool minValueSet = false;
465 ColumnModularizeType modularize = ColumnModularizeType.None;
466 string name = null;
467 bool nullable = false;
468 string possibilities = null;
469 bool primaryKey = false;
470 ColumnType type = ColumnType.Unknown;
471 bool useCData = false;
472
473 // parse the attributes
474 while (reader.MoveToNextAttribute())
475 {
476 switch (reader.LocalName)
477 {
478 case "added":
479 added = reader.Value.Equals("yes");
480 break;
481 case "category":
482 switch (reader.Value)
483 {
484 case "anyPath":
485 category = ColumnCategory.AnyPath;
486 break;
487 case "binary":
488 category = ColumnCategory.Binary;
489 break;
490 case "cabinet":
491 category = ColumnCategory.Cabinet;
492 break;
493 case "condition":
494 category = ColumnCategory.Condition;
495 break;
496 case "customSource":
497 category = ColumnCategory.CustomSource;
498 break;
499 case "defaultDir":
500 category = ColumnCategory.DefaultDir;
501 break;
502 case "doubleInteger":
503 category = ColumnCategory.DoubleInteger;
504 break;
505 case "filename":
506 category = ColumnCategory.Filename;
507 break;
508 case "formatted":
509 category = ColumnCategory.Formatted;
510 break;
511 case "formattedSddl":
512 category = ColumnCategory.FormattedSDDLText;
513 break;
514 case "guid":
515 category = ColumnCategory.Guid;
516 break;
517 case "identifier":
518 category = ColumnCategory.Identifier;
519 break;
520 case "integer":
521 category = ColumnCategory.Integer;
522 break;
523 case "language":
524 category = ColumnCategory.Language;
525 break;
526 case "lowerCase":
527 category = ColumnCategory.LowerCase;
528 break;
529 case "path":
530 category = ColumnCategory.Path;
531 break;
532 case "paths":
533 category = ColumnCategory.Paths;
534 break;
535 case "property":
536 category = ColumnCategory.Property;
537 break;
538 case "regPath":
539 category = ColumnCategory.RegPath;
540 break;
541 case "shortcut":
542 category = ColumnCategory.Shortcut;
543 break;
544 case "template":
545 category = ColumnCategory.Template;
546 break;
547 case "text":
548 category = ColumnCategory.Text;
549 break;
550 case "timeDate":
551 category = ColumnCategory.TimeDate;
552 break;
553 case "upperCase":
554 category = ColumnCategory.UpperCase;
555 break;
556 case "version":
557 category = ColumnCategory.Version;
558 break;
559 case "wildCardFilename":
560 category = ColumnCategory.WildCardFilename;
561 break;
562 default:
563 throw new InvalidOperationException();
564 }
565 break;
566 case "description":
567 description = reader.Value;
568 break;
569 case "escapeIdtCharacters":
570 escapeIdtCharacters = reader.Value.Equals("yes");
571 break;
572 case "keyColumn":
573 keyColumnSet = true;
574 keyColumn = Convert.ToInt32(reader.Value, 10);
575 break;
576 case "keyTable":
577 keyTable = reader.Value;
578 break;
579 case "length":
580 length = Convert.ToInt32(reader.Value, 10);
581 break;
582 case "localizable":
583 localizable = reader.Value.Equals("yes");
584 break;
585 case "maxValue":
586 maxValueSet = true;
587 maxValue = Convert.ToInt32(reader.Value, 10);
588 break;
589 case "minValue":
590 minValueSet = true;
591 minValue = Convert.ToInt32(reader.Value, 10);
592 break;
593 case "modularize":
594 switch (reader.Value)
595 {
596 case "column":
597 modularize = ColumnModularizeType.Column;
598 break;
599 case "companionFile":
600 modularize = ColumnModularizeType.CompanionFile;
601 break;
602 case "condition":
603 modularize = ColumnModularizeType.Condition;
604 break;
605 case "controlEventArgument":
606 modularize = ColumnModularizeType.ControlEventArgument;
607 break;
608 case "controlText":
609 modularize = ColumnModularizeType.ControlText;
610 break;
611 case "icon":
612 modularize = ColumnModularizeType.Icon;
613 break;
614 case "none":
615 modularize = ColumnModularizeType.None;
616 break;
617 case "property":
618 modularize = ColumnModularizeType.Property;
619 break;
620 case "semicolonDelimited":
621 modularize = ColumnModularizeType.SemicolonDelimited;
622 break;
623 default:
624 throw new XmlException();
625 }
626 break;
627 case "name":
628 switch (reader.Value)
629 {
630 case "CREATE":
631 case "DELETE":
632 case "DROP":
633 case "INSERT":
634 throw new XmlException();
635 default:
636 name = reader.Value;
637 break;
638 }
639 break;
640 case "nullable":
641 nullable = reader.Value.Equals("yes");
642 break;
643 case "primaryKey":
644 primaryKey = reader.Value.Equals("yes");
645 break;
646 case "set":
647 possibilities = reader.Value;
648 break;
649 case "type":
650 switch (reader.Value)
651 {
652 case "localized":
653 type = ColumnType.Localized;
654 break;
655 case "number":
656 type = ColumnType.Number;
657 break;
658 case "object":
659 type = ColumnType.Object;
660 break;
661 case "string":
662 type = ColumnType.String;
663 break;
664 case "preserved":
665 type = ColumnType.Preserved;
666 break;
667 default:
668 throw new XmlException();
669 }
670 break;
671 case "useCData":
672 useCData = reader.Value.Equals("yes");
673 break;
674 }
675 }
676
677 // parse the child elements (there should be none)
678 if (!empty)
679 {
680 bool done = false;
681
682 while (!done && reader.Read())
683 {
684 switch (reader.NodeType)
685 {
686 case XmlNodeType.Element:
687 throw new XmlException();
688 case XmlNodeType.EndElement:
689 done = true;
690 break;
691 }
692 }
693
694 if (!done)
695 {
696 throw new XmlException();
697 }
698 }
699
700 ColumnDefinition columnDefinition = new ColumnDefinition(name, type, length, primaryKey, nullable, modularize, localizable, minValueSet, minValue, maxValueSet, maxValue, keyTable, keyColumnSet, keyColumn, category, possibilities, description, escapeIdtCharacters, useCData);
701 columnDefinition.Added = added;
702
703 return columnDefinition;
704 }
705
706 /// <summary>
707 /// Persists a ColumnDefinition in an XML format.
708 /// </summary>
709 /// <param name="writer">XmlWriter where the Output should persist itself as XML.</param>
710 internal void Write(XmlWriter writer)
711 {
712 writer.WriteStartElement("columnDefinition", TableDefinitionCollection.XmlNamespaceUri);
713
714 writer.WriteAttributeString("name", this.name);
715
716 switch (this.type)
717 {
718 case ColumnType.Localized:
719 writer.WriteAttributeString("type", "localized");
720 break;
721 case ColumnType.Number:
722 writer.WriteAttributeString("type", "number");
723 break;
724 case ColumnType.Object:
725 writer.WriteAttributeString("type", "object");
726 break;
727 case ColumnType.String:
728 writer.WriteAttributeString("type", "string");
729 break;
730 case ColumnType.Preserved:
731 writer.WriteAttributeString("type", "preserved");
732 break;
733 }
734
735 writer.WriteAttributeString("length", this.length.ToString(CultureInfo.InvariantCulture.NumberFormat));
736
737 if (this.primaryKey)
738 {
739 writer.WriteAttributeString("primaryKey", "yes");
740 }
741
742 if (this.nullable)
743 {
744 writer.WriteAttributeString("nullable", "yes");
745 }
746
747 if (this.localizable)
748 {
749 writer.WriteAttributeString("localizable", "yes");
750 }
751
752 if (this.added)
753 {
754 writer.WriteAttributeString("added", "yes");
755 }
756
757 switch (this.modularize)
758 {
759 case ColumnModularizeType.Column:
760 writer.WriteAttributeString("modularize", "column");
761 break;
762 case ColumnModularizeType.CompanionFile:
763 writer.WriteAttributeString("modularize", "companionFile");
764 break;
765 case ColumnModularizeType.Condition:
766 writer.WriteAttributeString("modularize", "condition");
767 break;
768 case ColumnModularizeType.ControlEventArgument:
769 writer.WriteAttributeString("modularize", "controlEventArgument");
770 break;
771 case ColumnModularizeType.ControlText:
772 writer.WriteAttributeString("modularize", "controlText");
773 break;
774 case ColumnModularizeType.Icon:
775 writer.WriteAttributeString("modularize", "icon");
776 break;
777 case ColumnModularizeType.None:
778 // this is the default value
779 break;
780 case ColumnModularizeType.Property:
781 writer.WriteAttributeString("modularize", "property");
782 break;
783 case ColumnModularizeType.SemicolonDelimited:
784 writer.WriteAttributeString("modularize", "semicolonDelimited");
785 break;
786 }
787
788 if (this.minValueSet)
789 {
790 writer.WriteAttributeString("minValue", this.minValue.ToString(CultureInfo.InvariantCulture.NumberFormat));
791 }
792
793 if (this.maxValueSet)
794 {
795 writer.WriteAttributeString("maxValue", this.maxValue.ToString(CultureInfo.InvariantCulture.NumberFormat));
796 }
797
798 if (!String.IsNullOrEmpty(this.keyTable))
799 {
800 writer.WriteAttributeString("keyTable", this.keyTable);
801 }
802
803 if (this.keyColumnSet)
804 {
805 writer.WriteAttributeString("keyColumn", this.keyColumn.ToString(CultureInfo.InvariantCulture.NumberFormat));
806 }
807
808 switch (this.category)
809 {
810 case ColumnCategory.AnyPath:
811 writer.WriteAttributeString("category", "anyPath");
812 break;
813 case ColumnCategory.Binary:
814 writer.WriteAttributeString("category", "binary");
815 break;
816 case ColumnCategory.Cabinet:
817 writer.WriteAttributeString("category", "cabinet");
818 break;
819 case ColumnCategory.Condition:
820 writer.WriteAttributeString("category", "condition");
821 break;
822 case ColumnCategory.CustomSource:
823 writer.WriteAttributeString("category", "customSource");
824 break;
825 case ColumnCategory.DefaultDir:
826 writer.WriteAttributeString("category", "defaultDir");
827 break;
828 case ColumnCategory.DoubleInteger:
829 writer.WriteAttributeString("category", "doubleInteger");
830 break;
831 case ColumnCategory.Filename:
832 writer.WriteAttributeString("category", "filename");
833 break;
834 case ColumnCategory.Formatted:
835 writer.WriteAttributeString("category", "formatted");
836 break;
837 case ColumnCategory.FormattedSDDLText:
838 writer.WriteAttributeString("category", "formattedSddl");
839 break;
840 case ColumnCategory.Guid:
841 writer.WriteAttributeString("category", "guid");
842 break;
843 case ColumnCategory.Identifier:
844 writer.WriteAttributeString("category", "identifier");
845 break;
846 case ColumnCategory.Integer:
847 writer.WriteAttributeString("category", "integer");
848 break;
849 case ColumnCategory.Language:
850 writer.WriteAttributeString("category", "language");
851 break;
852 case ColumnCategory.LowerCase:
853 writer.WriteAttributeString("category", "lowerCase");
854 break;
855 case ColumnCategory.Path:
856 writer.WriteAttributeString("category", "path");
857 break;
858 case ColumnCategory.Paths:
859 writer.WriteAttributeString("category", "paths");
860 break;
861 case ColumnCategory.Property:
862 writer.WriteAttributeString("category", "property");
863 break;
864 case ColumnCategory.RegPath:
865 writer.WriteAttributeString("category", "regPath");
866 break;
867 case ColumnCategory.Shortcut:
868 writer.WriteAttributeString("category", "shortcut");
869 break;
870 case ColumnCategory.Template:
871 writer.WriteAttributeString("category", "template");
872 break;
873 case ColumnCategory.Text:
874 writer.WriteAttributeString("category", "text");
875 break;
876 case ColumnCategory.TimeDate:
877 writer.WriteAttributeString("category", "timeDate");
878 break;
879 case ColumnCategory.UpperCase:
880 writer.WriteAttributeString("category", "upperCase");
881 break;
882 case ColumnCategory.Version:
883 writer.WriteAttributeString("category", "version");
884 break;
885 case ColumnCategory.WildCardFilename:
886 writer.WriteAttributeString("category", "wildCardFilename");
887 break;
888 }
889
890 if (!String.IsNullOrEmpty(this.possibilities))
891 {
892 writer.WriteAttributeString("set", this.possibilities);
893 }
894
895 if (!String.IsNullOrEmpty(this.description))
896 {
897 writer.WriteAttributeString("description", this.description);
898 }
899
900 if (this.escapeIdtCharacters)
901 {
902 writer.WriteAttributeString("escapeIdtCharacters", "yes");
903 }
904
905 if (this.useCData)
906 {
907 writer.WriteAttributeString("useCData", "yes");
908 }
909
910 writer.WriteEndElement();
911 }
912
913 /// <summary>
914 /// Validate a value for this column.
915 /// </summary>
916 /// <param name="value">The value to validate.</param>
917 /// <returns>Validated value.</returns>
918 internal object ValidateValue(object value)
919 {
920 if (null == value)
921 {
922 if (!this.nullable)
923 {
924 throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Cannot set column '{0}' with a null value because this is a required field.", this.name));
925 }
926 }
927 else // check numerical values against their specified minimum and maximum values.
928 {
929 if (ColumnType.Number == this.type && !this.IsLocalizable)
930 {
931 // For now all enums in the tables can be represented by integers. This if statement would need to
932 // be enhanced if that ever changes.
933 if (value is int || value.GetType().IsEnum)
934 {
935 int intValue = (int)value;
936
937 // validate the value against the minimum allowed value
938 if (this.minValueSet && this.minValue > intValue)
939 {
940 throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Cannot set column '{0}' with value {1} because it is less than the minimum allowed value for this column, {2}.", this.name, intValue, this.minValue));
941 }
942
943 // validate the value against the maximum allowed value
944 if (this.maxValueSet && this.maxValue < intValue)
945 {
946 throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Cannot set column '{0}' with value {1} because it is greater than the maximum allowed value for this column, {2}.", this.name, intValue, this.maxValue));
947 }
948
949 return intValue;
950 }
951 else if (value is long)
952 {
953 long longValue = (long)value;
954
955 // validate the value against the minimum allowed value
956 if (this.minValueSet && this.minValue > longValue)
957 {
958 throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Cannot set column '{0}' with value {1} because it is less than the minimum allowed value for this column, {2}.", this.name, longValue, this.minValue));
959 }
960
961 // validate the value against the maximum allowed value
962 if (this.maxValueSet && this.maxValue < longValue)
963 {
964 throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Cannot set column '{0}' with value {1} because it is greater than the maximum allowed value for this column, {2}.", this.name, longValue, this.maxValue));
965 }
966
967 return longValue;
968 }
969 else
970 {
971 throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Cannot set number column '{0}' with a value of type '{1}'.", this.name, value.GetType().ToString()));
972 }
973 }
974 else
975 {
976 if (!(value is string))
977 {
978 //throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Cannot set string column '{0}' with a value of type '{1}'.", this.name, value.GetType().ToString()));
979 return value.ToString();
980 }
981 }
982 }
983
984 return value;
985 }
986
987 /// <summary>
988 /// Compare this column definition to another column definition.
989 /// </summary>
990 /// <remarks>
991 /// Only Windows Installer traits are compared, allowing for updates to WiX-specific table definitions.
992 /// </remarks>
993 /// <param name="other">The <see cref="ColumnDefinition"/> to compare with this one.</param>
994 /// <returns>0 if the columns' core propeties are the same; otherwise, non-0.</returns>
995 public int CompareTo(ColumnDefinition other)
996 {
997 // by definition, this object is greater than null
998 if (null == other)
999 {
1000 return 1;
1001 }
1002
1003 // compare column names
1004 int ret = String.Compare(this.Name, other.Name, StringComparison.Ordinal);
1005
1006 // compare column types
1007 if (0 == ret)
1008 {
1009 ret = this.Type == other.Type ? 0 : -1;
1010
1011 // compare column lengths
1012 if (0 == ret)
1013 {
1014 ret = this.Length == other.Length ? 0 : -1;
1015
1016 // compare whether both are primary keys
1017 if (0 == ret)
1018 {
1019 ret = this.PrimaryKey == other.PrimaryKey ? 0 : -1;
1020
1021 // compare nullability
1022 if (0 == ret)
1023 {
1024 ret = this.Nullable == other.Nullable ? 0 : -1;
1025 }
1026 }
1027 }
1028 }
1029
1030 return ret;
1031 }
1032 }
1033}