2aa42ba86b8ce90c5110581ae81092304e710bc0
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Objects / RelationshipWrapper.cs
1 //---------------------------------------------------------------------
2 // <copyright file="RelationshipWrapper.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner       Microsoft
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
9 using System;
10 using System.Collections.Generic;
11 using System.Diagnostics;
12 using System.Data.Metadata.Edm;
13
14 namespace System.Data.Objects
15 {
16     internal sealed class RelationshipWrapper : IEquatable<RelationshipWrapper>
17     {
18         internal readonly AssociationSet AssociationSet;
19         internal readonly EntityKey Key0;
20         internal readonly EntityKey Key1;
21
22         internal RelationshipWrapper(AssociationSet extent, EntityKey key)
23         {
24             Debug.Assert(null != extent, "null RelationshipWrapper");
25             Debug.Assert(null != (object)key, "null key");
26
27             this.AssociationSet = extent;
28             this.Key0 = key;
29             this.Key1 = key;
30         }
31
32         internal RelationshipWrapper(RelationshipWrapper wrapper, int ordinal, EntityKey key)
33         {
34             Debug.Assert(null != wrapper, "null RelationshipWrapper");
35             Debug.Assert((uint)ordinal <= 1u, "ordinal out of range");
36             Debug.Assert(null != (object)key, "null key2");
37
38             this.AssociationSet = wrapper.AssociationSet;
39             this.Key0 = (0 == ordinal) ? key : wrapper.Key0;
40             this.Key1 = (0 == ordinal) ? wrapper.Key1 : key;
41         }
42
43         internal RelationshipWrapper(AssociationSet extent,
44                                      KeyValuePair<string, EntityKey> roleAndKey1,
45                                      KeyValuePair<string, EntityKey> roleAndKey2)
46             : this(extent, roleAndKey1.Key, roleAndKey1.Value, roleAndKey2.Key, roleAndKey2.Value)
47         {
48         }
49
50         internal RelationshipWrapper(AssociationSet extent,
51                                      string role0, EntityKey key0,
52                                      string role1, EntityKey key1)
53         {
54             Debug.Assert(null != extent, "null AssociationSet");
55             Debug.Assert(null != (object)key0, "null key0");
56             Debug.Assert(null != (object)key1, "null key1");
57
58             AssociationSet = extent;
59             Debug.Assert(extent.ElementType.AssociationEndMembers.Count == 2, "only 2 ends are supported");
60
61             // this assert is explictly commented out to show that the two are similar but different
62             // we should always use AssociationEndMembers, never CorrespondingAssociationEndMember
63             //Debug.Assert(AssociationSet.AssociationSetEnds.Count == 2, "only 2 set ends supported");
64             //Debug.Assert(extent.ElementType.AssociationEndMembers[0] == AssociationSet.AssociationSetEnds[0].CorrespondingAssociationEndMember, "should be same end member");
65             //Debug.Assert(extent.ElementType.AssociationEndMembers[1] == AssociationSet.AssociationSetEnds[1].CorrespondingAssociationEndMember, "should be same end member");
66
67             if (extent.ElementType.AssociationEndMembers[0].Name == role0)
68             {
69                 Debug.Assert(extent.ElementType.AssociationEndMembers[1].Name == role1, "a)roleAndKey1 Name differs");
70                 Key0 = key0;
71                 Key1 = key1;
72             }
73             else
74             {
75                 Debug.Assert(extent.ElementType.AssociationEndMembers[0].Name == role1, "b)roleAndKey1 Name differs");
76                 Debug.Assert(extent.ElementType.AssociationEndMembers[1].Name == role0, "b)roleAndKey0 Name differs");
77                 Key0 = key1;
78                 Key1 = key0;
79             }
80         }
81
82         internal ReadOnlyMetadataCollection<AssociationEndMember> AssociationEndMembers
83         {
84             get { return this.AssociationSet.ElementType.AssociationEndMembers; }
85         }
86
87         internal AssociationEndMember GetAssociationEndMember(EntityKey key)
88         {
89             Debug.Assert(Key0 == key || Key1 == key, "didn't match a key");
90             return AssociationEndMembers[(Key0 != key) ? 1 : 0];
91         }
92
93         internal EntityKey GetOtherEntityKey(EntityKey key)
94         {
95             return ((Key0 == key) ? Key1 : ((Key1 == key) ? Key0 : null));
96         }
97
98         internal EntityKey GetEntityKey(int ordinal)
99         {
100             switch (ordinal)
101             {
102                 case 0:
103                     return Key0;
104                 case 1:
105                     return Key1;
106                 default:
107                     throw EntityUtil.ArgumentOutOfRange("ordinal");
108             }
109         }
110
111         public override int GetHashCode()
112         {
113             return this.AssociationSet.Name.GetHashCode() ^ (this.Key0.GetHashCode() + this.Key1.GetHashCode());
114         }
115
116         public override bool Equals(object obj)
117         {
118             return Equals(obj as RelationshipWrapper);
119         }
120
121         public bool Equals(RelationshipWrapper wrapper)
122         {
123             return (Object.ReferenceEquals(this, wrapper) ||
124                     ((null != wrapper) &&
125                      Object.ReferenceEquals(this.AssociationSet, wrapper.AssociationSet) &&
126                      this.Key0.Equals(wrapper.Key0) &&
127                      this.Key1.Equals(wrapper.Key1)));
128         }
129     }
130 }