diff options
Diffstat (limited to '')
-rw-r--r-- | src/dtf/WixToolset.Dtf.WindowsInstaller.Package/InstallPath.cs | 1073 |
1 files changed, 1073 insertions, 0 deletions
diff --git a/src/dtf/WixToolset.Dtf.WindowsInstaller.Package/InstallPath.cs b/src/dtf/WixToolset.Dtf.WindowsInstaller.Package/InstallPath.cs new file mode 100644 index 00000000..e3ba81b5 --- /dev/null +++ b/src/dtf/WixToolset.Dtf.WindowsInstaller.Package/InstallPath.cs | |||
@@ -0,0 +1,1073 @@ | |||
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.Dtf.WindowsInstaller.Package | ||
4 | { | ||
5 | using System; | ||
6 | using System.IO; | ||
7 | using System.Collections; | ||
8 | using System.Collections.Generic; | ||
9 | using System.Globalization; | ||
10 | |||
11 | /// <summary> | ||
12 | /// Represents the installation path of a file or directory from an installer product database. | ||
13 | /// </summary> | ||
14 | public class InstallPath | ||
15 | { | ||
16 | /// <summary> | ||
17 | /// Creates a new InstallPath, specifying a filename. | ||
18 | /// </summary> | ||
19 | /// <param name="name">The name of the file or directory. Not a full path.</param> | ||
20 | public InstallPath(string name) : this(name, false) { } | ||
21 | |||
22 | /// <summary> | ||
23 | /// Creates a new InstallPath, parsing out either the short or long filename. | ||
24 | /// </summary> | ||
25 | /// <param name="name">The name of the file or directory, in short|long syntax for a filename | ||
26 | /// or targetshort|targetlong:sourceshort|sourcelong syntax for a directory.</param> | ||
27 | /// <param name="useShortNames">true to parse the short part of the combined filename; false to parse the long part</param> | ||
28 | public InstallPath(string name, bool useShortNames) | ||
29 | { | ||
30 | if(name == null) | ||
31 | { | ||
32 | throw new ArgumentNullException(); | ||
33 | } | ||
34 | this.parentPath = null; | ||
35 | ParseName(name, useShortNames); | ||
36 | } | ||
37 | |||
38 | private void ParseName(string name, bool useShortNames) | ||
39 | { | ||
40 | string[] parse = name.Split(new char[] { ':' }, 3); | ||
41 | if(parse.Length == 3) | ||
42 | { | ||
43 | // Syntax was targetshort:sourceshort|targetlong:sourcelong. | ||
44 | // Chnage it to targetshort|targetlong:sourceshort|sourcelong. | ||
45 | parse = name.Split(new char[] { ':', '|' }, 4); | ||
46 | if(parse.Length == 4) | ||
47 | parse = new string[] { parse[0] + '|' + parse[2], parse[1] + '|' + parse[3] }; | ||
48 | else | ||
49 | parse = new string[] { parse[0] + '|' + parse[1], parse[1] + '|' + parse[2] }; | ||
50 | } | ||
51 | string targetName = parse[0]; | ||
52 | string sourceName = (parse.Length == 2 ? parse[1] : parse[0]); | ||
53 | parse = targetName.Split(new char[] { '|' }, 2); | ||
54 | if(parse.Length == 2) targetName = (useShortNames ? parse[0] : parse[1]); | ||
55 | parse = sourceName.Split(new char[] { '|' }, 2); | ||
56 | if(parse.Length == 2) sourceName = (useShortNames ? parse[0] : parse[1]); | ||
57 | |||
58 | this.SourceName = sourceName; | ||
59 | this.TargetName = targetName; | ||
60 | } | ||
61 | |||
62 | /// <summary> | ||
63 | /// Gets the path of the parent directory. | ||
64 | /// </summary> | ||
65 | public InstallPath ParentPath | ||
66 | { | ||
67 | get | ||
68 | { | ||
69 | return parentPath; | ||
70 | } | ||
71 | } | ||
72 | internal void SetParentPath(InstallPath value) | ||
73 | { | ||
74 | parentPath = value; | ||
75 | ResetSourcePath(); | ||
76 | ResetTargetPath(); | ||
77 | } | ||
78 | private InstallPath parentPath; | ||
79 | |||
80 | /// <summary> | ||
81 | /// Gets the set of child paths if this InstallPath object represents a a directory. | ||
82 | /// </summary> | ||
83 | public InstallPathCollection ChildPaths | ||
84 | { | ||
85 | get | ||
86 | { | ||
87 | if(childPaths == null) | ||
88 | { | ||
89 | childPaths = new InstallPathCollection(this); | ||
90 | } | ||
91 | return childPaths; | ||
92 | } | ||
93 | } | ||
94 | private InstallPathCollection childPaths; | ||
95 | |||
96 | /// <summary> | ||
97 | /// Gets or sets the source name of the InstallPath. | ||
98 | /// </summary> | ||
99 | public string SourceName | ||
100 | { | ||
101 | get | ||
102 | { | ||
103 | return sourceName; | ||
104 | } | ||
105 | set | ||
106 | { | ||
107 | if(value == null) | ||
108 | { | ||
109 | throw new ArgumentNullException(); | ||
110 | } | ||
111 | sourceName = value; | ||
112 | ResetSourcePath(); | ||
113 | } | ||
114 | } | ||
115 | private string sourceName; | ||
116 | |||
117 | /// <summary> | ||
118 | /// Gets or sets the target name of the install path. | ||
119 | /// </summary> | ||
120 | public string TargetName | ||
121 | { | ||
122 | get | ||
123 | { | ||
124 | return targetName; | ||
125 | } | ||
126 | set | ||
127 | { | ||
128 | if(value == null) | ||
129 | { | ||
130 | throw new ArgumentNullException(); | ||
131 | } | ||
132 | targetName = value; | ||
133 | ResetTargetPath(); | ||
134 | } | ||
135 | } | ||
136 | private string targetName; | ||
137 | |||
138 | /// <summary> | ||
139 | /// Gets the full source path. | ||
140 | /// </summary> | ||
141 | public string SourcePath | ||
142 | { | ||
143 | get | ||
144 | { | ||
145 | if(sourcePath == null) | ||
146 | { | ||
147 | if(parentPath != null) | ||
148 | { | ||
149 | sourcePath = (sourceName.Equals(".") ? parentPath.SourcePath | ||
150 | : Path.Combine(parentPath.SourcePath, sourceName)); | ||
151 | } | ||
152 | else | ||
153 | { | ||
154 | sourcePath = sourceName; | ||
155 | } | ||
156 | } | ||
157 | return sourcePath; | ||
158 | } | ||
159 | set | ||
160 | { | ||
161 | ResetSourcePath(); | ||
162 | sourcePath = value; | ||
163 | } | ||
164 | } | ||
165 | private string sourcePath; | ||
166 | |||
167 | /// <summary> | ||
168 | /// Gets the full target path. | ||
169 | /// </summary> | ||
170 | public string TargetPath | ||
171 | { | ||
172 | get | ||
173 | { | ||
174 | if(targetPath == null) | ||
175 | { | ||
176 | if(parentPath != null) | ||
177 | { | ||
178 | targetPath = (targetName.Equals(".") ? parentPath.TargetPath | ||
179 | : Path.Combine(parentPath.TargetPath, targetName)); | ||
180 | } | ||
181 | else | ||
182 | { | ||
183 | targetPath = targetName; | ||
184 | } | ||
185 | } | ||
186 | return targetPath; | ||
187 | } | ||
188 | set | ||
189 | { | ||
190 | ResetTargetPath(); | ||
191 | targetPath = value; | ||
192 | } | ||
193 | } | ||
194 | private string targetPath; | ||
195 | |||
196 | private void ResetSourcePath() | ||
197 | { | ||
198 | if(sourcePath != null) | ||
199 | { | ||
200 | sourcePath = null; | ||
201 | if(childPaths != null) | ||
202 | { | ||
203 | foreach(InstallPath ip in childPaths) | ||
204 | { | ||
205 | ip.ResetSourcePath(); | ||
206 | } | ||
207 | } | ||
208 | } | ||
209 | } | ||
210 | |||
211 | private void ResetTargetPath() | ||
212 | { | ||
213 | if(targetPath != null) | ||
214 | { | ||
215 | targetPath = null; | ||
216 | if(childPaths != null) | ||
217 | { | ||
218 | foreach(InstallPath ip in childPaths) | ||
219 | { | ||
220 | ip.ResetTargetPath(); | ||
221 | } | ||
222 | } | ||
223 | } | ||
224 | } | ||
225 | |||
226 | /// <summary> | ||
227 | /// Gets the full source path. | ||
228 | /// </summary> | ||
229 | /// <returns><see cref="SourcePath"/></returns> | ||
230 | public override String ToString() | ||
231 | { | ||
232 | return SourcePath; | ||
233 | } | ||
234 | } | ||
235 | |||
236 | /// <summary> | ||
237 | /// Represents a collection of InstallPaths that are the child paths of the same parent directory. | ||
238 | /// </summary> | ||
239 | public class InstallPathCollection : IList<InstallPath> | ||
240 | { | ||
241 | private InstallPath parentPath; | ||
242 | private List<InstallPath> items; | ||
243 | |||
244 | internal InstallPathCollection(InstallPath parentPath) | ||
245 | { | ||
246 | this.parentPath = parentPath; | ||
247 | this.items = new List<InstallPath>(); | ||
248 | } | ||
249 | |||
250 | /// <summary> | ||
251 | /// Gets or sets the element at the specified index. | ||
252 | /// </summary> | ||
253 | public InstallPath this[int index] | ||
254 | { | ||
255 | get | ||
256 | { | ||
257 | return this.items[index]; | ||
258 | } | ||
259 | set | ||
260 | { | ||
261 | this.OnSet(this.items[index], value); | ||
262 | this.items[index] = value; | ||
263 | } | ||
264 | } | ||
265 | |||
266 | /// <summary> | ||
267 | /// Adds a new child path to the collection. | ||
268 | /// </summary> | ||
269 | /// <param name="item">The InstallPath to add.</param> | ||
270 | public void Add(InstallPath item) | ||
271 | { | ||
272 | this.OnInsert(item); | ||
273 | this.items.Add(item); | ||
274 | } | ||
275 | |||
276 | /// <summary> | ||
277 | /// Removes a child path to the collection. | ||
278 | /// </summary> | ||
279 | /// <param name="item">The InstallPath to remove.</param> | ||
280 | public bool Remove(InstallPath item) | ||
281 | { | ||
282 | int index = this.items.IndexOf(item); | ||
283 | if (index >= 0) | ||
284 | { | ||
285 | this.OnRemove(item); | ||
286 | this.items.RemoveAt(index); | ||
287 | return true; | ||
288 | } | ||
289 | else | ||
290 | { | ||
291 | return false; | ||
292 | } | ||
293 | } | ||
294 | |||
295 | /// <summary> | ||
296 | /// Gets the index of a child path in the collection. | ||
297 | /// </summary> | ||
298 | /// <param name="item">The InstallPath to search for.</param> | ||
299 | /// <returns>The index of the item, or -1 if not found.</returns> | ||
300 | public int IndexOf(InstallPath item) | ||
301 | { | ||
302 | return this.items.IndexOf(item); | ||
303 | } | ||
304 | |||
305 | /// <summary> | ||
306 | /// Inserts a child path into the collection. | ||
307 | /// </summary> | ||
308 | /// <param name="index">The insertion index.</param> | ||
309 | /// <param name="item">The InstallPath to insert.</param> | ||
310 | public void Insert(int index, InstallPath item) | ||
311 | { | ||
312 | this.OnInsert(item); | ||
313 | this.items.Insert(index, item); | ||
314 | } | ||
315 | |||
316 | /// <summary> | ||
317 | /// Tests if the collection contains a child path. | ||
318 | /// </summary> | ||
319 | /// <param name="item">The InstallPath to search for.</param> | ||
320 | /// <returns>true if the item is found; false otherwise</returns> | ||
321 | public bool Contains(InstallPath item) | ||
322 | { | ||
323 | return this.items.Contains(item); | ||
324 | } | ||
325 | |||
326 | /// <summary> | ||
327 | /// Copies the collection into an array. | ||
328 | /// </summary> | ||
329 | /// <param name="array">The array to copy into.</param> | ||
330 | /// <param name="index">The starting index in the destination array.</param> | ||
331 | public void CopyTo(InstallPath[] array, int index) | ||
332 | { | ||
333 | this.items.CopyTo(array, index); | ||
334 | } | ||
335 | |||
336 | private void OnInsert(InstallPath item) | ||
337 | { | ||
338 | if (item.ParentPath != null) | ||
339 | { | ||
340 | item.ParentPath.ChildPaths.Remove(item); | ||
341 | } | ||
342 | |||
343 | item.SetParentPath(this.parentPath); | ||
344 | } | ||
345 | |||
346 | private void OnRemove(InstallPath item) | ||
347 | { | ||
348 | item.SetParentPath(null); | ||
349 | } | ||
350 | |||
351 | private void OnSet(InstallPath oldItem, InstallPath newItem) | ||
352 | { | ||
353 | this.OnRemove(oldItem); | ||
354 | this.OnInsert(newItem); | ||
355 | } | ||
356 | |||
357 | /// <summary> | ||
358 | /// Removes an item from the collection. | ||
359 | /// </summary> | ||
360 | /// <param name="index">The index of the item to remove.</param> | ||
361 | public void RemoveAt(int index) | ||
362 | { | ||
363 | this.OnRemove(this[index]); | ||
364 | this.items.RemoveAt(index); | ||
365 | } | ||
366 | |||
367 | /// <summary> | ||
368 | /// Removes all items from the collection. | ||
369 | /// </summary> | ||
370 | public void Clear() | ||
371 | { | ||
372 | foreach (InstallPath item in this) | ||
373 | { | ||
374 | this.OnRemove(item); | ||
375 | } | ||
376 | |||
377 | this.items.Clear(); | ||
378 | } | ||
379 | |||
380 | /// <summary> | ||
381 | /// Gets the number of items in the collection. | ||
382 | /// </summary> | ||
383 | public int Count | ||
384 | { | ||
385 | get | ||
386 | { | ||
387 | return this.items.Count; | ||
388 | } | ||
389 | } | ||
390 | |||
391 | bool ICollection<InstallPath>.IsReadOnly | ||
392 | { | ||
393 | get | ||
394 | { | ||
395 | return false; | ||
396 | } | ||
397 | } | ||
398 | |||
399 | /// <summary> | ||
400 | /// Gets an enumerator over all items in the collection. | ||
401 | /// </summary> | ||
402 | /// <returns>An enumerator for the collection.</returns> | ||
403 | public IEnumerator<InstallPath> GetEnumerator() | ||
404 | { | ||
405 | return this.items.GetEnumerator(); | ||
406 | } | ||
407 | |||
408 | IEnumerator IEnumerable.GetEnumerator() | ||
409 | { | ||
410 | return ((IEnumerable<InstallPath>) this).GetEnumerator(); | ||
411 | } | ||
412 | } | ||
413 | |||
414 | /// <summary> | ||
415 | /// Represents a mapping of install paths for all directories, components, or files in | ||
416 | /// an installation database. | ||
417 | /// </summary> | ||
418 | public class InstallPathMap : IDictionary<string, InstallPath> | ||
419 | { | ||
420 | /// <summary> | ||
421 | /// Builds a mapping from File keys to installation paths. | ||
422 | /// </summary> | ||
423 | /// <param name="db">Installation database.</param> | ||
424 | /// <param name="componentPathMap">Component mapping returned by <see cref="BuildComponentPathMap"/>.</param> | ||
425 | /// <param name="useShortNames">true to use short file names; false to use long names</param> | ||
426 | /// <returns>An InstallPathMap with the described mapping.</returns> | ||
427 | public static InstallPathMap BuildFilePathMap(Database db, InstallPathMap componentPathMap, | ||
428 | bool useShortNames) | ||
429 | { | ||
430 | if(db == null) | ||
431 | { | ||
432 | throw new ArgumentNullException("db"); | ||
433 | } | ||
434 | |||
435 | if(componentPathMap == null) | ||
436 | { | ||
437 | componentPathMap = BuildComponentPathMap(db, BuildDirectoryPathMap(db, useShortNames)); | ||
438 | } | ||
439 | |||
440 | InstallPathMap filePathMap = new InstallPathMap(); | ||
441 | |||
442 | using (View fileView = db.OpenView("SELECT `File`, `Component_`, `FileName` FROM `File`")) | ||
443 | { | ||
444 | fileView.Execute(); | ||
445 | |||
446 | foreach (Record fileRec in fileView) | ||
447 | { | ||
448 | using (fileRec) | ||
449 | { | ||
450 | string file = (string) fileRec[1]; | ||
451 | string comp = (string) fileRec[2]; | ||
452 | string fileName = (string) fileRec[3]; | ||
453 | |||
454 | InstallPath compPath = (InstallPath) componentPathMap[comp]; | ||
455 | if(compPath != null) | ||
456 | { | ||
457 | InstallPath filePath = new InstallPath(fileName, useShortNames); | ||
458 | compPath.ChildPaths.Add(filePath); | ||
459 | filePathMap[file] = filePath; | ||
460 | } | ||
461 | } | ||
462 | } | ||
463 | } | ||
464 | |||
465 | return filePathMap; | ||
466 | } | ||
467 | |||
468 | /// <summary> | ||
469 | /// Builds a mapping from Component keys to installation paths. | ||
470 | /// </summary> | ||
471 | /// <param name="db">Installation database.</param> | ||
472 | /// <param name="directoryPathMap">Directory mapping returned by | ||
473 | /// <see cref="BuildDirectoryPathMap(Database,bool)"/>.</param> | ||
474 | /// <returns>An InstallPathMap with the described mapping.</returns> | ||
475 | public static InstallPathMap BuildComponentPathMap(Database db, InstallPathMap directoryPathMap) | ||
476 | { | ||
477 | if(db == null) | ||
478 | { | ||
479 | throw new ArgumentNullException("db"); | ||
480 | } | ||
481 | |||
482 | InstallPathMap compPathMap = new InstallPathMap(); | ||
483 | |||
484 | using (View compView = db.OpenView("SELECT `Component`, `Directory_` FROM `Component`")) | ||
485 | { | ||
486 | compView.Execute(); | ||
487 | |||
488 | foreach (Record compRec in compView) | ||
489 | { | ||
490 | using (compRec) | ||
491 | { | ||
492 | string comp = (string) compRec[1]; | ||
493 | InstallPath dirPath = (InstallPath) directoryPathMap[(string) compRec[2]]; | ||
494 | |||
495 | if (dirPath != null) | ||
496 | { | ||
497 | compPathMap[comp] = dirPath; | ||
498 | } | ||
499 | } | ||
500 | } | ||
501 | } | ||
502 | |||
503 | return compPathMap; | ||
504 | } | ||
505 | |||
506 | /// <summary> | ||
507 | /// Builds a mapping from Directory keys to installation paths. | ||
508 | /// </summary> | ||
509 | /// <param name="db">Installation database.</param> | ||
510 | /// <param name="useShortNames">true to use short directory names; false to use long names</param> | ||
511 | /// <returns>An InstallPathMap with the described mapping.</returns> | ||
512 | public static InstallPathMap BuildDirectoryPathMap(Database db, bool useShortNames) | ||
513 | { | ||
514 | return BuildDirectoryPathMap(db, useShortNames, null, null); | ||
515 | } | ||
516 | |||
517 | /// <summary> | ||
518 | /// Builds a mapping of Directory keys to directory paths, specifying root directories | ||
519 | /// for the source and target paths. | ||
520 | /// </summary> | ||
521 | /// <param name="db">Database containing the Directory table.</param> | ||
522 | /// <param name="useShortNames">true to use short directory names; false to use long names</param> | ||
523 | /// <param name="sourceRootDir">The root directory path of all source paths, or null to leave them relative.</param> | ||
524 | /// <param name="targetRootDir">The root directory path of all source paths, or null to leave them relative.</param> | ||
525 | /// <returns>An InstallPathMap with the described mapping.</returns> | ||
526 | public static InstallPathMap BuildDirectoryPathMap(Database db, bool useShortNames, | ||
527 | string sourceRootDir, string targetRootDir) | ||
528 | { | ||
529 | if(db == null) | ||
530 | { | ||
531 | throw new ArgumentNullException("db"); | ||
532 | } | ||
533 | |||
534 | if(sourceRootDir == null) sourceRootDir = ""; | ||
535 | if(targetRootDir == null) targetRootDir = ""; | ||
536 | |||
537 | InstallPathMap dirMap = new InstallPathMap(); | ||
538 | IDictionary dirTreeMap = new Hashtable(); | ||
539 | |||
540 | using (View dirView = db.OpenView("SELECT `Directory`, `Directory_Parent`, `DefaultDir` FROM `Directory`")) | ||
541 | { | ||
542 | dirView.Execute(); | ||
543 | |||
544 | foreach (Record dirRec in dirView) using (dirRec) | ||
545 | { | ||
546 | string key = (string) dirRec[1]; | ||
547 | string parentKey = (string) dirRec[2]; | ||
548 | InstallPath dir = new InstallPath((string) dirRec[3], useShortNames); | ||
549 | |||
550 | dirMap[key] = dir; | ||
551 | |||
552 | InstallPathMap siblingDirs = (InstallPathMap) dirTreeMap[parentKey]; | ||
553 | if (siblingDirs == null) | ||
554 | { | ||
555 | siblingDirs = new InstallPathMap(); | ||
556 | dirTreeMap[parentKey] = siblingDirs; | ||
557 | } | ||
558 | siblingDirs.Add(key, dir); | ||
559 | } | ||
560 | } | ||
561 | |||
562 | foreach (KeyValuePair<string, InstallPath> entry in (InstallPathMap) dirTreeMap[""]) | ||
563 | { | ||
564 | string key = (string) entry.Key; | ||
565 | InstallPath dir = (InstallPath) entry.Value; | ||
566 | LinkSubdirectories(key, dir, dirTreeMap); | ||
567 | } | ||
568 | |||
569 | InstallPath targetDirPath = (InstallPath) dirMap["TARGETDIR"]; | ||
570 | if(targetDirPath != null) | ||
571 | { | ||
572 | targetDirPath.SourcePath = sourceRootDir; | ||
573 | targetDirPath.TargetPath = targetRootDir; | ||
574 | } | ||
575 | |||
576 | return dirMap; | ||
577 | } | ||
578 | |||
579 | private static void LinkSubdirectories(string key, InstallPath dir, IDictionary dirTreeMap) | ||
580 | { | ||
581 | InstallPathMap subDirs = (InstallPathMap) dirTreeMap[key]; | ||
582 | if(subDirs != null) | ||
583 | { | ||
584 | foreach (KeyValuePair<string, InstallPath> entry in subDirs) | ||
585 | { | ||
586 | string subKey = (string) entry.Key; | ||
587 | InstallPath subDir = (InstallPath) entry.Value; | ||
588 | dir.ChildPaths.Add(subDir); | ||
589 | LinkSubdirectories(subKey, subDir, dirTreeMap); | ||
590 | } | ||
591 | } | ||
592 | } | ||
593 | |||
594 | private Dictionary<string, InstallPath> items; | ||
595 | |||
596 | /// <summary> | ||
597 | /// Creates a new empty InstallPathMap. | ||
598 | /// </summary> | ||
599 | public InstallPathMap() | ||
600 | { | ||
601 | this.items = new Dictionary<string,InstallPath>(StringComparer.Ordinal); | ||
602 | } | ||
603 | |||
604 | /// <summary> | ||
605 | /// Gets a mapping from keys to source paths. | ||
606 | /// </summary> | ||
607 | public IDictionary<string, string> SourcePaths | ||
608 | { | ||
609 | get | ||
610 | { | ||
611 | return new SourcePathMap(this); | ||
612 | } | ||
613 | } | ||
614 | |||
615 | /// <summary> | ||
616 | /// Gets a mapping from keys to target paths. | ||
617 | /// </summary> | ||
618 | public IDictionary<string, string> TargetPaths | ||
619 | { | ||
620 | get | ||
621 | { | ||
622 | return new TargetPathMap(this); | ||
623 | } | ||
624 | } | ||
625 | |||
626 | /// <summary> | ||
627 | /// Gets or sets an install path for a direcotry, component, or file key. | ||
628 | /// </summary> | ||
629 | /// <param name="key">Depending on the type of InstallPathMap, this is the primary key from the | ||
630 | /// either the Directory, Component, or File table.</param> | ||
631 | /// <remarks> | ||
632 | /// Changing an install path does not modify the Database used to generate this InstallPathMap. | ||
633 | /// </remarks> | ||
634 | public InstallPath this[string key] | ||
635 | { | ||
636 | get | ||
637 | { | ||
638 | InstallPath value = null; | ||
639 | this.items.TryGetValue(key, out value); | ||
640 | return value; | ||
641 | } | ||
642 | set | ||
643 | { | ||
644 | this.items[key] = value; | ||
645 | } | ||
646 | } | ||
647 | |||
648 | /// <summary> | ||
649 | /// Gets the collection of keys in the InstallPathMap. Depending on the type of InstallPathMap, | ||
650 | /// they are all directory, component, or file key strings. | ||
651 | /// </summary> | ||
652 | public ICollection<string> Keys | ||
653 | { | ||
654 | get | ||
655 | { | ||
656 | return this.items.Keys; | ||
657 | } | ||
658 | } | ||
659 | |||
660 | /// <summary> | ||
661 | /// Gets the collection of InstallPath values in the InstallPathMap. | ||
662 | /// </summary> | ||
663 | public ICollection<InstallPath> Values | ||
664 | { | ||
665 | get | ||
666 | { | ||
667 | return this.items.Values; | ||
668 | } | ||
669 | } | ||
670 | |||
671 | /// <summary> | ||
672 | /// Sets an install path for a direcotry, component, or file key. | ||
673 | /// </summary> | ||
674 | /// <param name="key">Depending on the type of InstallPathMap, this is the primary key from the | ||
675 | /// either the Directory, Component, or File table.</param> | ||
676 | /// <param name="installPath">The install path of the key item.</param> | ||
677 | /// <remarks> | ||
678 | /// Changing an install path does not modify the Database used to generate this InstallPathMap. | ||
679 | /// </remarks> | ||
680 | public void Add(string key, InstallPath installPath) | ||
681 | { | ||
682 | this.items.Add(key, installPath); | ||
683 | } | ||
684 | |||
685 | /// <summary> | ||
686 | /// Removes an install path from the map. | ||
687 | /// </summary> | ||
688 | /// <param name="key">Depending on the type of InstallPathMap, this is the primary key from the | ||
689 | /// either the Directory, Component, or File table.</param> | ||
690 | /// <returns>true if the item was removed, false if it did not exist</returns> | ||
691 | /// <remarks> | ||
692 | /// Changing an install path does not modify the Database used to generate this InstallPathMap. | ||
693 | /// </remarks> | ||
694 | public bool Remove(string key) | ||
695 | { | ||
696 | return this.items.Remove(key); | ||
697 | } | ||
698 | |||
699 | /// <summary> | ||
700 | /// Tests whether a direcotry, component, or file key exists in the map. | ||
701 | /// </summary> | ||
702 | /// <param name="key">Depending on the type of InstallPathMap, this is the primary key from the | ||
703 | /// either the Directory, Component, or File table.</param> | ||
704 | /// <returns>true if the key is found; false otherwise</returns> | ||
705 | public bool ContainsKey(string key) | ||
706 | { | ||
707 | return this.items.ContainsKey(key); | ||
708 | } | ||
709 | |||
710 | /* | ||
711 | public override string ToString() | ||
712 | { | ||
713 | System.Text.StringBuilder buf = new System.Text.StringBuilder(); | ||
714 | foreach(KeyValuePair<string, InstallPath> entry in this) | ||
715 | { | ||
716 | buf.AppendFormat("{0}={1}", entry.Key, entry.Value); | ||
717 | buf.Append("\n"); | ||
718 | } | ||
719 | return buf.ToString(); | ||
720 | } | ||
721 | */ | ||
722 | |||
723 | /// <summary> | ||
724 | /// Attempts to get a value from the dictionary. | ||
725 | /// </summary> | ||
726 | /// <param name="key">The key to lookup.</param> | ||
727 | /// <param name="value">Receives the value, or null if they key was not found.</param> | ||
728 | /// <returns>True if the value was found, else false.</returns> | ||
729 | public bool TryGetValue(string key, out InstallPath value) | ||
730 | { | ||
731 | return this.items.TryGetValue(key, out value); | ||
732 | } | ||
733 | |||
734 | void ICollection<KeyValuePair<string, InstallPath>>.Add(KeyValuePair<string, InstallPath> item) | ||
735 | { | ||
736 | ((ICollection<KeyValuePair<string, InstallPath>>) this.items).Add(item); | ||
737 | } | ||
738 | |||
739 | /// <summary> | ||
740 | /// Removes all entries from the dictionary. | ||
741 | /// </summary> | ||
742 | public void Clear() | ||
743 | { | ||
744 | this.items.Clear(); | ||
745 | } | ||
746 | |||
747 | bool ICollection<KeyValuePair<string, InstallPath>>.Contains(KeyValuePair<string, InstallPath> item) | ||
748 | { | ||
749 | return ((ICollection<KeyValuePair<string, InstallPath>>) this.items).Contains(item); | ||
750 | } | ||
751 | |||
752 | void ICollection<KeyValuePair<string, InstallPath>>.CopyTo(KeyValuePair<string, InstallPath>[] array, int arrayIndex) | ||
753 | { | ||
754 | ((ICollection<KeyValuePair<string, InstallPath>>) this.items).CopyTo(array, arrayIndex); | ||
755 | } | ||
756 | |||
757 | /// <summary> | ||
758 | /// Gets the number of entries in the dictionary. | ||
759 | /// </summary> | ||
760 | public int Count | ||
761 | { | ||
762 | get | ||
763 | { | ||
764 | return this.items.Count; | ||
765 | } | ||
766 | } | ||
767 | |||
768 | bool ICollection<KeyValuePair<string, InstallPath>>.IsReadOnly | ||
769 | { | ||
770 | get | ||
771 | { | ||
772 | return false; | ||
773 | } | ||
774 | } | ||
775 | |||
776 | bool ICollection<KeyValuePair<string, InstallPath>>.Remove(KeyValuePair<string, InstallPath> item) | ||
777 | { | ||
778 | return ((ICollection<KeyValuePair<string, InstallPath>>) this.items).Remove(item); | ||
779 | } | ||
780 | |||
781 | /// <summary> | ||
782 | /// Gets an enumerator over all entries in the dictionary. | ||
783 | /// </summary> | ||
784 | /// <returns>An enumerator for the dictionary.</returns> | ||
785 | public IEnumerator<KeyValuePair<string, InstallPath>> GetEnumerator() | ||
786 | { | ||
787 | return this.items.GetEnumerator(); | ||
788 | } | ||
789 | |||
790 | IEnumerator IEnumerable.GetEnumerator() | ||
791 | { | ||
792 | return this.items.GetEnumerator(); | ||
793 | } | ||
794 | } | ||
795 | |||
796 | internal class SourcePathMap : IDictionary<string, string> | ||
797 | { | ||
798 | private const string RO_MSG = | ||
799 | "The SourcePathMap collection is read-only. " + | ||
800 | "Modify the InstallPathMap instead."; | ||
801 | |||
802 | private InstallPathMap map; | ||
803 | |||
804 | internal SourcePathMap(InstallPathMap map) | ||
805 | { | ||
806 | this.map = map; | ||
807 | } | ||
808 | |||
809 | public void Add(string key, string value) | ||
810 | { | ||
811 | throw new InvalidOperationException(RO_MSG); | ||
812 | } | ||
813 | |||
814 | public bool ContainsKey(string key) | ||
815 | { | ||
816 | return this.map.ContainsKey(key); | ||
817 | } | ||
818 | |||
819 | public ICollection<string> Keys | ||
820 | { | ||
821 | get | ||
822 | { | ||
823 | return this.map.Keys; | ||
824 | } | ||
825 | } | ||
826 | |||
827 | public bool Remove(string key) | ||
828 | { | ||
829 | throw new InvalidOperationException(RO_MSG); | ||
830 | } | ||
831 | |||
832 | public bool TryGetValue(string key, out string value) | ||
833 | { | ||
834 | InstallPath installPath; | ||
835 | if (this.map.TryGetValue(key, out installPath)) | ||
836 | { | ||
837 | value = installPath.SourcePath; | ||
838 | return true; | ||
839 | } | ||
840 | else | ||
841 | { | ||
842 | value = null; | ||
843 | return false; | ||
844 | } | ||
845 | } | ||
846 | |||
847 | public ICollection<string> Values | ||
848 | { | ||
849 | get | ||
850 | { | ||
851 | List<string> values = new List<string>(this.Count); | ||
852 | foreach (KeyValuePair<string, InstallPath> entry in this.map) | ||
853 | { | ||
854 | values.Add(entry.Value.SourcePath); | ||
855 | } | ||
856 | return values; | ||
857 | } | ||
858 | } | ||
859 | |||
860 | public string this[string key] | ||
861 | { | ||
862 | get | ||
863 | { | ||
864 | string value = null; | ||
865 | this.TryGetValue(key, out value); | ||
866 | return value; | ||
867 | } | ||
868 | set | ||
869 | { | ||
870 | throw new InvalidOperationException(RO_MSG); | ||
871 | } | ||
872 | } | ||
873 | |||
874 | public void Add(KeyValuePair<string, string> item) | ||
875 | { | ||
876 | throw new InvalidOperationException(RO_MSG); | ||
877 | } | ||
878 | |||
879 | public void Clear() | ||
880 | { | ||
881 | throw new InvalidOperationException(RO_MSG); | ||
882 | } | ||
883 | |||
884 | public bool Contains(KeyValuePair<string, string> item) | ||
885 | { | ||
886 | string value = this[item.Key]; | ||
887 | return value == item.Value; | ||
888 | } | ||
889 | |||
890 | public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex) | ||
891 | { | ||
892 | foreach (KeyValuePair<string, string> entry in this) | ||
893 | { | ||
894 | array[arrayIndex] = entry; | ||
895 | arrayIndex++; | ||
896 | } | ||
897 | } | ||
898 | |||
899 | public int Count | ||
900 | { | ||
901 | get | ||
902 | { | ||
903 | return this.map.Count; | ||
904 | } | ||
905 | } | ||
906 | |||
907 | public bool IsReadOnly | ||
908 | { | ||
909 | get | ||
910 | { | ||
911 | return true; | ||
912 | } | ||
913 | } | ||
914 | |||
915 | public bool Remove(KeyValuePair<string, string> item) | ||
916 | { | ||
917 | throw new InvalidOperationException(RO_MSG); | ||
918 | } | ||
919 | |||
920 | public IEnumerator<KeyValuePair<string, string>> GetEnumerator() | ||
921 | { | ||
922 | foreach (KeyValuePair<string, InstallPath> entry in this.map) | ||
923 | { | ||
924 | yield return new KeyValuePair<string, string>( | ||
925 | entry.Key, entry.Value.SourcePath); | ||
926 | } | ||
927 | } | ||
928 | |||
929 | IEnumerator IEnumerable.GetEnumerator() | ||
930 | { | ||
931 | return this.GetEnumerator(); | ||
932 | } | ||
933 | } | ||
934 | |||
935 | internal class TargetPathMap : IDictionary<string, string> | ||
936 | { | ||
937 | private const string RO_MSG = | ||
938 | "The TargetPathMap collection is read-only. " + | ||
939 | "Modify the InstallPathMap instead."; | ||
940 | |||
941 | private InstallPathMap map; | ||
942 | |||
943 | internal TargetPathMap(InstallPathMap map) | ||
944 | { | ||
945 | this.map = map; | ||
946 | } | ||
947 | |||
948 | public void Add(string key, string value) | ||
949 | { | ||
950 | throw new InvalidOperationException(RO_MSG); | ||
951 | } | ||
952 | |||
953 | public bool ContainsKey(string key) | ||
954 | { | ||
955 | return this.map.ContainsKey(key); | ||
956 | } | ||
957 | |||
958 | public ICollection<string> Keys | ||
959 | { | ||
960 | get | ||
961 | { | ||
962 | return this.map.Keys; | ||
963 | } | ||
964 | } | ||
965 | |||
966 | public bool Remove(string key) | ||
967 | { | ||
968 | throw new InvalidOperationException(RO_MSG); | ||
969 | } | ||
970 | |||
971 | public bool TryGetValue(string key, out string value) | ||
972 | { | ||
973 | InstallPath installPath; | ||
974 | if (this.map.TryGetValue(key, out installPath)) | ||
975 | { | ||
976 | value = installPath.TargetPath; | ||
977 | return true; | ||
978 | } | ||
979 | else | ||
980 | { | ||
981 | value = null; | ||
982 | return false; | ||
983 | } | ||
984 | } | ||
985 | |||
986 | public ICollection<string> Values | ||
987 | { | ||
988 | get | ||
989 | { | ||
990 | List<string> values = new List<string>(this.Count); | ||
991 | foreach (KeyValuePair<string, InstallPath> entry in this.map) | ||
992 | { | ||
993 | values.Add(entry.Value.TargetPath); | ||
994 | } | ||
995 | return values; | ||
996 | } | ||
997 | } | ||
998 | |||
999 | public string this[string key] | ||
1000 | { | ||
1001 | get | ||
1002 | { | ||
1003 | string value = null; | ||
1004 | this.TryGetValue(key, out value); | ||
1005 | return value; | ||
1006 | } | ||
1007 | set | ||
1008 | { | ||
1009 | throw new InvalidOperationException(RO_MSG); | ||
1010 | } | ||
1011 | } | ||
1012 | |||
1013 | public void Add(KeyValuePair<string, string> item) | ||
1014 | { | ||
1015 | throw new InvalidOperationException(RO_MSG); | ||
1016 | } | ||
1017 | |||
1018 | public void Clear() | ||
1019 | { | ||
1020 | throw new InvalidOperationException(RO_MSG); | ||
1021 | } | ||
1022 | |||
1023 | public bool Contains(KeyValuePair<string, string> item) | ||
1024 | { | ||
1025 | string value = this[item.Key]; | ||
1026 | return value == item.Value; | ||
1027 | } | ||
1028 | |||
1029 | public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex) | ||
1030 | { | ||
1031 | foreach (KeyValuePair<string, string> entry in this) | ||
1032 | { | ||
1033 | array[arrayIndex] = entry; | ||
1034 | arrayIndex++; | ||
1035 | } | ||
1036 | } | ||
1037 | |||
1038 | public int Count | ||
1039 | { | ||
1040 | get | ||
1041 | { | ||
1042 | return this.map.Count; | ||
1043 | } | ||
1044 | } | ||
1045 | |||
1046 | public bool IsReadOnly | ||
1047 | { | ||
1048 | get | ||
1049 | { | ||
1050 | return true; | ||
1051 | } | ||
1052 | } | ||
1053 | |||
1054 | public bool Remove(KeyValuePair<string, string> item) | ||
1055 | { | ||
1056 | throw new InvalidOperationException(RO_MSG); | ||
1057 | } | ||
1058 | |||
1059 | public IEnumerator<KeyValuePair<string, string>> GetEnumerator() | ||
1060 | { | ||
1061 | foreach (KeyValuePair<string, InstallPath> entry in this.map) | ||
1062 | { | ||
1063 | yield return new KeyValuePair<string, string>( | ||
1064 | entry.Key, entry.Value.TargetPath); | ||
1065 | } | ||
1066 | } | ||
1067 | |||
1068 | IEnumerator IEnumerable.GetEnumerator() | ||
1069 | { | ||
1070 | return this.GetEnumerator(); | ||
1071 | } | ||
1072 | } | ||
1073 | } | ||