MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System;5using System.Collections;6using System.Collections.Generic;7using System.Collections.ObjectModel;8 9namespace System.Management.Automation10{11 /// <summary>12 /// PSListModifier is a simple helper class created by the update-list cmdlet.13 /// The update-list cmdlet will either return an instance of this class, or14 /// it will internally use an instance of this class to implement the updates.15 ///16 /// Cmdlets can also take a PSListModifier as a parameter. Usage might look like:17 ///18 /// Get-Mailbox | Set-Mailbox -Alias @{Add='jim'}19 ///20 /// Alias would take a PSListModifier and the Cmdlet code would be responsible21 /// for apply updates (possibly using PSListModifier.ApplyTo or else using custom logic).22 /// </summary>23 public class PSListModifier24 {25 /// <summary>26 /// Create a new PSListModifier with empty lists for Add/Remove.27 /// </summary>28 public PSListModifier()29 {30 _itemsToAdd = new Collection<object>();31 _itemsToRemove = new Collection<object>();32 _replacementItems = new Collection<object>();33 }34 35 /// <summary>36 /// Create a new PSListModifier with the specified add and remove lists.37 /// </summary>38 /// <param name="removeItems">The items to remove.</param>39 /// <param name="addItems">The items to add.</param>40 public PSListModifier(Collection<object> removeItems, Collection<object> addItems)41 {42 _itemsToAdd = addItems ?? new Collection<object>();43 _itemsToRemove = removeItems ?? new Collection<object>();44 _replacementItems = new Collection<object>();45 }46 47 /// <summary>48 /// Create a new PSListModifier to replace a given list with replaceItems.49 /// </summary>50 /// <param name="replacementItems">The item(s) to replace an existing list with.</param>51 public PSListModifier(object replacementItems)52 {53 _itemsToAdd = new Collection<object>();54 _itemsToRemove = new Collection<object>();55 if (replacementItems == null)56 {57 _replacementItems = new Collection<object>();58 }59 else if (replacementItems is Collection<object>)60 {61 _replacementItems = (Collection<object>)replacementItems;62 }63 else if (replacementItems is IList<object>)64 {65 _replacementItems = new Collection<object>((IList<object>)replacementItems);66 }67 else if (replacementItems is IList)68 {69 _replacementItems = new Collection<object>();70 foreach (object item in (IList)replacementItems)71 {72 _replacementItems.Add(item);73 }74 }75 else76 {77 _replacementItems = new Collection<object>();78 _replacementItems.Add(replacementItems);79 }80 }81 82 /// <summary>83 /// Create a new PSListModifier with the specified add and remove lists (in the hash.)84 /// </summary>85 /// <param name="hash">A hashtable, where the value for key Add is the list to add86 /// and the value for Remove is the list to remove.</param>87 public PSListModifier(Hashtable hash)88 {89 if (hash == null)90 {91 throw PSTraceSource.NewArgumentNullException(nameof(hash));92 }93 94 _itemsToAdd = new Collection<object>();95 _itemsToRemove = new Collection<object>();96 _replacementItems = new Collection<object>();97 98 foreach (DictionaryEntry entry in hash)99 {100 if (entry.Key is string)101 {102 string key = entry.Key as string;103 bool isAdd = key.Equals(AddKey, StringComparison.OrdinalIgnoreCase);104 bool isRemove = key.Equals(RemoveKey, StringComparison.OrdinalIgnoreCase);105 bool isReplace = key.Equals(ReplaceKey, StringComparison.OrdinalIgnoreCase);106 107 if (!isAdd && !isRemove && !isReplace)108 {109 throw PSTraceSource.NewArgumentException(nameof(hash), PSListModifierStrings.ListModifierDisallowedKey, key);110 }111 112 Collection<object> collection;113 if (isRemove)114 {115 collection = _itemsToRemove;116 }117 else if (isAdd)118 {119 collection = _itemsToAdd;120 }121 else122 {123 collection = _replacementItems;124 }125 126 IEnumerable enumerable = LanguagePrimitives.GetEnumerable(entry.Value);127 if (enumerable != null)128 {129 foreach (object obj in enumerable)130 {131 collection.Add(obj);132 }133 }134 else135 {136 collection.Add(entry.Value);137 }138 }139 else140 {141 throw PSTraceSource.NewArgumentException(nameof(hash), PSListModifierStrings.ListModifierDisallowedKey, entry.Key);142 }143 }144 }145 146 /// <summary>147 /// The list of items to add when ApplyTo is called.148 /// </summary>149 public Collection<object> Add150 {151 get { return _itemsToAdd; }152 }153 154 private readonly Collection<object> _itemsToAdd;155 156 /// <summary>157 /// The list of items to remove when AppyTo is called.158 /// </summary>159 public Collection<object> Remove160 {161 get { return _itemsToRemove; }162 }163 164 private readonly Collection<object> _itemsToRemove;165 166 /// <summary>167 /// The list of items to replace an existing list with.168 /// </summary>169 public Collection<object> Replace170 {171 get { return _replacementItems; }172 }173 174 private readonly Collection<object> _replacementItems;175 176 /// <summary>177 /// Update the given collection with the items in Add and Remove.178 /// </summary>179 /// <param name="collectionToUpdate">The collection to update.</param>180 public void ApplyTo(IList collectionToUpdate)181 {182 if (collectionToUpdate == null)183 {184 throw PSTraceSource.NewArgumentNullException(nameof(collectionToUpdate));185 }186 187 if (_replacementItems.Count > 0)188 {189 collectionToUpdate.Clear();190 foreach (object obj in _replacementItems)191 {192 collectionToUpdate.Add(PSObject.Base(obj));193 }194 }195 else196 {197 foreach (object obj in _itemsToRemove)198 {199 collectionToUpdate.Remove(PSObject.Base(obj));200 }201 202 foreach (object obj in _itemsToAdd)203 {204 collectionToUpdate.Add(PSObject.Base(obj));205 }206 }207 }208 209 /// <summary>210 /// Update the given collection with the items in Add and Remove.211 /// </summary>212 /// <param name="collectionToUpdate">The collection to update.</param>213 public void ApplyTo(object collectionToUpdate)214 {215 ArgumentNullException.ThrowIfNull(collectionToUpdate);216 217 collectionToUpdate = PSObject.Base(collectionToUpdate);218 219 if (collectionToUpdate is not IList list)220 {221 throw PSTraceSource.NewInvalidOperationException(PSListModifierStrings.UpdateFailed);222 }223 224 ApplyTo(list);225 }226 227 internal Hashtable ToHashtable()228 {229 Hashtable result = new Hashtable(2);230 231 if (_itemsToAdd.Count > 0)232 {233 result.Add(AddKey, _itemsToAdd);234 }235 236 if (_itemsToRemove.Count > 0)237 {238 result.Add(RemoveKey, _itemsToRemove);239 }240 241 if (_replacementItems.Count > 0)242 {243 result.Add(ReplaceKey, _replacementItems);244 }245 246 return result;247 }248 249 internal const string AddKey = "Add";250 internal const string RemoveKey = "Remove";251 internal const string ReplaceKey = "Replace";252 }253 254 /// <summary>255 /// A generic version of PSListModifier that exists for the sole purpose of making256 /// cmdlets that accept a PSListModifier more usable. Users that look at the syntax257 /// of the command will see something like PSListModifier[Mailbox] and know they need258 /// to pass in Mailboxes.259 /// </summary>260 /// <typeparam name="T">The list element type</typeparam>261 public class PSListModifier<T> : PSListModifier262 {263 /// <summary>264 /// Create a new PSListModifier with empty lists for Add/Remove.265 /// </summary>266 public PSListModifier()267 : base()268 {269 }270 271 /// <summary>272 /// Create a new PSListModifier with the specified add and remove lists.273 /// </summary>274 /// <param name="removeItems">The items to remove.</param>275 /// <param name="addItems">The items to add.</param>276 public PSListModifier(Collection<object> removeItems, Collection<object> addItems)277 : base(removeItems, addItems)278 {279 }280 281 /// <summary>282 /// Create a new PSListModifier to replace a given list with replaceItems.283 /// </summary>284 /// <param name="replacementItems">The items to replace an existing list with.</param>285 public PSListModifier(object replacementItems)286 : base(replacementItems)287 {288 }289 290 /// <summary>291 /// Create a new PSListModifier with the specified add and remove lists (in the hash.)292 /// </summary>293 /// <param name="hash">A hashtable, where the value for key Add is the list to add294 /// and the value for Remove is the list to remove.</param>295 public PSListModifier(Hashtable hash)296 : base(hash)297 {298 }299 }300}301 