1 //Copyright 2010 Microsoft Corporation
2 //
3 //Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
4 //You may obtain a copy of the License at
5 //
6 //http://www.apache.org/licenses/LICENSE-2.0
7 //
8 //Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
9 //"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 //See the License for the specific language governing permissions and limitations under the License.
11 
12 
13 namespace System.Data.Services.Common
14 {
15     using System.Collections.Generic;
16     using System.Diagnostics;
17     using System.Linq;
18     using System.Data.Services.Client;
19 
20 
21     internal sealed class EpmSourceTree
22     {
23         #region Fields
24 
25         private readonly EpmSourcePathSegment root;
26 
27         private readonly EpmTargetTree epmTargetTree;
28 
29         #endregion
30 
EpmSourceTree(EpmTargetTree epmTargetTree)31         internal EpmSourceTree(EpmTargetTree epmTargetTree)
32         {
33             this.root = new EpmSourcePathSegment("");
34             this.epmTargetTree = epmTargetTree;
35         }
36 
37         #region Properties
38 
39         internal EpmSourcePathSegment Root
40         {
41             get
42             {
43                 return this.root;
44             }
45         }
46 
47         #endregion
48 
Add(EntityPropertyMappingInfo epmInfo)49         internal void Add(EntityPropertyMappingInfo epmInfo)
50         {
51             String sourceName = epmInfo.Attribute.SourcePath;
52             EpmSourcePathSegment currentProperty = this.Root;
53             IList<EpmSourcePathSegment> activeSubProperties = currentProperty.SubProperties;
54             EpmSourcePathSegment foundProperty = null;
55 
56             Debug.Assert(!String.IsNullOrEmpty(sourceName), "Must have been validated during EntityPropertyMappingAttribute construction");
57             foreach (String propertyName in sourceName.Split('/'))
58             {
59                 if (propertyName.Length == 0)
60                 {
61                     throw new InvalidOperationException(Strings.EpmSourceTree_InvalidSourcePath(epmInfo.DefiningType.Name, sourceName));
62                 }
63 
64                 foundProperty = activeSubProperties.SingleOrDefault(e => e.PropertyName == propertyName);
65                 if (foundProperty != null)
66                 {
67                     currentProperty = foundProperty;
68                 }
69                 else
70                 {
71                     currentProperty = new EpmSourcePathSegment(propertyName);
72                     activeSubProperties.Add(currentProperty);
73                 }
74 
75                 activeSubProperties = currentProperty.SubProperties;
76             }
77 
78             if (foundProperty != null)
79             {
80                 Debug.Assert(Object.ReferenceEquals(foundProperty, currentProperty), "currentProperty variable should have been updated already to foundProperty");
81 
82                 if (foundProperty.EpmInfo.DefiningType.Name == epmInfo.DefiningType.Name)
83                 {
84                     throw new InvalidOperationException(Strings.EpmSourceTree_DuplicateEpmAttrsWithSameSourceName(epmInfo.Attribute.SourcePath, epmInfo.DefiningType.Name));
85                 }
86                 this.epmTargetTree.Remove(foundProperty.EpmInfo);
87             }
88 
89             currentProperty.EpmInfo = epmInfo;
90             this.epmTargetTree.Add(epmInfo);
91         }
92     }
93 }