-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathReference.cs
More file actions
182 lines (159 loc) · 6.12 KB
/
Copy pathReference.cs
File metadata and controls
182 lines (159 loc) · 6.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
using System;
using System.Linq;
using System.Reflection;
using Rock;
using Rock.Data;
using Rock.Model;
namespace EntityCoding
{
/// <summary>
/// Most entities in Rock reference other entities by Id number, i.e. CategoryId.
/// This is not useful when exporting/importing entities between systems. So we
/// embed a Reference object that contains the Property name that originally
/// contained the Id number. During an import operation that Property is filled in
/// with the Id number of the object identified by the EntityType and the Guid.
/// Other reference types are possible, <see cref="ReferenceType"/> for a list.
/// </summary>
public class Reference
{
#region Properties
/// <summary>
/// The name of the property to be filled in with the Id number of the
/// referenced entity.
/// </summary>
public string Property { get; set; }
/// <summary>
/// The entity type name that will be loaded by it's Guid.
/// </summary>
public string EntityType { get; set; }
/// <summary>
/// The type of reference this is.
/// </summary>
public ReferenceType Type { get; set; }
/// <summary>
/// The data used to re-create the reference, depends on Type.
/// </summary>
public string Data { get; set; }
#endregion
#region Instance Methods
/// <summary>
/// Create a new empty reference. This should only be used by Newtonsoft when deserializing.
/// </summary>
public Reference()
{
}
/// <summary>
/// Creates a new entity reference object that is used to reconstruct the
/// link between two entities in the database.
/// </summary>
/// <param name="entity">The entity we are creating a reference to.</param>
/// <param name="propertyName">The name of the property in the containing entity.</param>
public Reference( IEntity entity, string propertyName )
{
Type entityType = EntityCoder.GetEntityType( entity );
EntityType = entityType.FullName;
Property = propertyName;
if ( entity is EntityType )
{
Type = ReferenceType.EntityType;
Data = ( ( EntityType ) entity ).Name;
}
else if ( entity is FieldType )
{
Type = ReferenceType.FieldType;
Data = ( ( FieldType ) entity ).Class;
}
else
{
Type = ReferenceType.Guid;
Data = entity.Guid.ToString();
}
}
/// <summary>
/// Initializes a new instance of the <see cref="Reference"/> class as a user reference.
/// </summary>
/// <param name="propertyName">The name of the property in the containing entity.</param>
/// <param name="key">The key that will be used to retrieve the entity value at import time.</param>
static public Reference UserDefinedReference( string propertyName, string key )
{
return new Reference
{
EntityType = string.Empty,
Property = propertyName,
Type = ReferenceType.UserDefined,
Data = key
};
}
/// <summary>
/// Restore this reference into the entity object.
/// </summary>
/// <param name="entity">The entity to restore the reference into.</param>
/// <param name="helper">The helper that provides us data access.</param>
public void Restore( IEntity entity, EntityDecoder helper )
{
PropertyInfo property = entity.GetType().GetProperty( Property );
object otherEntity = null;
if ( property == null || Type == ReferenceType.Null )
{
return;
}
//
// Find the referenced entity based on the reference type.
//
if ( Type == ReferenceType.Guid )
{
otherEntity = helper.GetExistingEntity( EntityType, helper.FindMappedGuid( new Guid( ( string ) Data ) ) );
}
else if ( Type == ReferenceType.EntityType )
{
otherEntity = new EntityTypeService( helper.RockContext ).Queryable().Where( e => e.Name == ( string ) Data ).FirstOrDefault();
}
else if ( Type == ReferenceType.FieldType )
{
otherEntity = new FieldTypeService( helper.RockContext ).Queryable().Where( f => f.Class == ( string ) Data ).FirstOrDefault();
}
else if ( Type == ReferenceType.UserDefined )
{
otherEntity = helper.GetUserDefinedValue( ( string ) Data );
}
else
{
throw new Exception( string.Format( "Don't know how to handle reference type {0}.", Type ) );
}
//
// If we found an entity then get its Id number and store that.
//
if ( otherEntity != null )
{
property.SetValue( entity, EntityCoder.ChangeType( property.PropertyType, otherEntity.GetPropertyValue( "Id" ) ) );
}
}
#endregion
}
/// <summary>
/// The type of reference that is being performed.
/// </summary>
public enum ReferenceType
{
/// <summary>
/// A null value, no target entity exists or should be created.
/// </summary>
Null = 0,
/// <summary>
/// The reference is being performed by a Guid, which is contained in the Data.
/// </summary>
Guid = 1,
/// <summary>
/// The reference is to an EntityType, whose name is contained in the Data.
/// </summary>
EntityType = 2,
/// <summary>
/// The reference is to a FieldType, whose class name is contained in the Data.
/// </summary>
FieldType = 3,
/// <summary>
/// The user will have defined the target entity.
/// </summary>
UserDefined = 4
}
}