/Source/ResourceManagement.Client/RmResourceFactory.cs
C# | 276 lines | 233 code | 21 blank | 22 comment | 48 complexity | c1478073f83148deda925742ee835e85 MD5 | raw file
1using System; 2using System.Collections; 3using System.Collections.Generic; 4using Microsoft.ResourceManagement.Client.WsTransfer; 5using Microsoft.ResourceManagement.Client.WsEnumeration; 6using Microsoft.ResourceManagement.ObjectModel; 7using System.Xml; 8using System.Xml.Schema; 9using System.Text; 10 11namespace Microsoft.ResourceManagement.Client 12{ 13 /// <summary> 14 /// This class constructs RmResource objects from web service request and response messages. 15 /// </summary> 16 public class RmResourceFactory : RmFactory 17 { 18 IResourceTypeFactory resourceTypeFactory; 19 20 const String ObjectType = @"ObjectType"; 21 const String ObjectID = @"ObjectID"; 22 23 public RmResourceFactory() 24 : this(new XmlSchemaSet()) 25 { } 26 public RmResourceFactory(XmlSchemaSet rmSchema) 27 : this(rmSchema, new DefaultResourceTypeFactory()) 28 { 29 30 } 31 32 public RmResourceFactory(XmlSchemaSet rmSchema, IResourceTypeFactory resourceTypeFactory) 33 : base(rmSchema) 34 { 35 if (resourceTypeFactory == null) 36 { 37 throw new ArgumentNullException("resourceTypeFactory"); 38 } 39 this.resourceTypeFactory = resourceTypeFactory; 40 } 41 /// <summary> 42 /// Returns a generic RmResource object from the getResponse object. 43 /// </summary> 44 /// <param name="getResponse">The get response from the server.</param> 45 /// <returns>The RmResource object with the attributes returned in getResponse.</returns> 46 public RmResource CreateResource(GetResponse getResponse) 47 { 48 if (getResponse == null) 49 { 50 throw new ArgumentNullException("getResponse"); 51 } 52 if (getResponse.BaseObjectSearchResponse == null) 53 { 54 throw new ArgumentNullException("getResponse.BaseObjectSearchResponse"); 55 } 56 lock (getResponse) 57 { 58 // look ahead for the type 59 String objectType = null; 60 foreach (PartialAttributeType partialAttribute in getResponse.BaseObjectSearchResponse.PartialAttributes) 61 { 62 if (partialAttribute.Values.Count > 0) 63 { 64 String localName = partialAttribute.Values[0].LocalName; 65 if (String.IsNullOrEmpty(localName)) 66 { 67 continue; 68 } 69 if (localName.Equals(ObjectType)) 70 { 71 objectType = partialAttribute.Values[0].InnerText; 72 break; 73 } 74 75 } 76 } 77 78 if (objectType == null) 79 { 80 objectType = string.Empty; 81 } 82 83 RmResource rmResource = this.resourceTypeFactory.CreateResource(objectType); 84 85 // fill in the attribute values 86 foreach (PartialAttributeType partialAttribute in getResponse.BaseObjectSearchResponse.PartialAttributes) 87 { 88 RmAttributeName attributeName = null; 89 RmAttributeValue newAttribute = null; 90 if (partialAttribute.Values.Count > 0) 91 { 92 String localName = partialAttribute.Values[0].LocalName; 93 if (String.IsNullOrEmpty(localName)) 94 { 95 continue; 96 } 97 else 98 { 99 attributeName = new RmAttributeName(localName); 100 } 101 } 102 else 103 { 104 continue; 105 } 106 107 if (rmResource.TryGetValue(attributeName, out newAttribute) == false) 108 { 109 newAttribute = new RmAttributeValue(); 110 } 111 112 // add values to the typed list 113 foreach (XmlNode value in partialAttribute.Values) 114 { 115 IComparable newValue = this.ConstructAttributeValue(attributeName, value.InnerText); 116 if (base.IsMultiValued(attributeName) == false) 117 newAttribute.Values.Clear(); 118 if (attributeName.Name.Equals(ObjectType) || attributeName.Name.Equals(ObjectID)) 119 newAttribute.Values.Clear(); 120 121 newAttribute.Values.Add(newValue); 122 } 123 } 124 return rmResource; 125 } 126 } 127 128 /// <summary> 129 /// Creates a list of resources based on the pull or enumerate response. 130 /// </summary> 131 /// <param name="pullOrEnumerateResponse">The pull or enumerate response to use when creating resources.</param> 132 /// <returns>The list of strongly-typed resources in the pull or enumerate response.</returns> 133 public List<RmResource> CreateResource(PullResponse pullOrEnumerateResponse) 134 { 135 if (pullOrEnumerateResponse == null) 136 { 137 throw new ArgumentNullException("pullOrEnumerateResponse"); 138 } 139 if (pullOrEnumerateResponse.Items == null || pullOrEnumerateResponse.Items.Values == null) 140 { 141 return new List<RmResource>(); 142 } 143 lock (pullOrEnumerateResponse) 144 { 145 List<RmResource> retList = new List<RmResource>(); 146 147 foreach (XmlNode obj in pullOrEnumerateResponse.Items.Values) 148 { 149 // look ahead for the type info; 150 String objectType = null; 151 foreach (XmlNode child in obj.ChildNodes) 152 { 153 if (child.NodeType == XmlNodeType.Element) 154 { 155 if (child.LocalName.Equals(@"ObjectType")) 156 { 157 objectType = child.InnerText; 158 break; 159 } 160 } 161 } 162 if (objectType == null) 163 { 164 objectType = String.Empty; 165 } 166 167 RmResource rmResource = this.resourceTypeFactory.CreateResource(objectType); 168 169 // now add the attributes to the resource object 170 foreach (XmlNode child in obj.ChildNodes) 171 { 172 if (child.NodeType == XmlNodeType.Element) 173 { 174 RmAttributeName attributeName = new RmAttributeName(child.LocalName); 175 IComparable attributeValue = this.ConstructAttributeValue(attributeName, child.InnerText); 176 if (attributeValue == null) 177 continue; 178 179 RmAttributeValue newAttribute = null; 180 if (rmResource.TryGetValue(attributeName, out newAttribute) == false) 181 { 182 newAttribute = new RmAttributeValue(); 183 rmResource[attributeName] = newAttribute; 184 } 185 if (base.IsMultiValued(attributeName) == false) 186 newAttribute.Values.Clear(); 187 if (attributeName.Name.Equals(ObjectType) || attributeName.Name.Equals(ObjectID)) 188 newAttribute.Values.Clear(); 189 newAttribute.Values.Add(attributeValue); 190 } 191 } 192 retList.Add(rmResource); 193 } 194 195 return retList; 196 } 197 } 198 199 protected IComparable ConstructAttributeValue(RmAttributeName attributeName, String innerText) 200 { 201 if (innerText == null) 202 return null; 203 RmAttributeInfo info = null; 204 if (base.RmAttributeCache.TryGetValue(attributeName, out info) == false) 205 { 206 // just in case they forget to load schema... we know that ObjectId must remove the uuid reference 207 if (attributeName.Name.Equals(ObjectID)) 208 { 209 return new RmReference(innerText); 210 } 211 else 212 { 213 return innerText; 214 } 215 } 216 217 try 218 { 219 switch (info.AttributeType) 220 { 221 case RmAttributeType.String: 222 return innerText; 223 case RmAttributeType.DateTime: 224 return DateTime.Parse(innerText); 225 case RmAttributeType.Integer: 226 return Int32.Parse(innerText); 227 case RmAttributeType.Reference: 228 return new RmReference(innerText); 229 case RmAttributeType.Binary: 230 return new RmBinary(innerText); 231 case RmAttributeType.Boolean: 232 return Boolean.Parse(innerText); 233 default: 234 return innerText; 235 } 236 } 237 catch (FormatException ex) 238 { 239 throw new ArgumentException( 240 String.Format( 241 "Failed to parse attribute {0} with value {1} into type {2}. Please ensure the resource management schema is up to date.", 242 attributeName, 243 innerText, 244 info.AttributeType.ToString()), 245 ex); 246 } 247 catch (System.Text.EncoderFallbackException ex) 248 { 249 throw new ArgumentException( 250 String.Format( 251 "Failed to convert the string on binary attribute {0} into byte array.", 252 attributeName), 253 ex); 254 } 255 } 256 257 /// <summary> 258 /// Gets or Sets the ResourceTypeFactory used to construct individual resource objects. 259 /// </summary> 260 public IResourceTypeFactory ResourceTypeFactory 261 { 262 get 263 { 264 return this.resourceTypeFactory; 265 } 266 set 267 { 268 if (value == null) 269 { 270 throw new ArgumentNullException("ResourceTypeFactory"); 271 } 272 this.resourceTypeFactory = value; 273 } 274 } 275 } 276}