/Libraries/Source/NHibernate/Collection/PersistentArrayHolder.cs
C# | 353 lines | 255 code | 42 blank | 56 comment | 26 complexity | 3e4ec508763d2ab04718ee122acc1cde MD5 | raw file
1using System;
2using System.Collections;
3using System.Data;
4using System.Diagnostics;
5using log4net;
6using NHibernate.DebugHelpers;
7using NHibernate.Engine;
8using NHibernate.Loader;
9using NHibernate.Persister.Collection;
10using NHibernate.Type;
11
12namespace NHibernate.Collection
13{
14 /// <summary>
15 /// A persistent wrapper for an array. lazy initialization is NOT supported
16 /// </summary>
17 [Serializable]
18 [DebuggerTypeProxy(typeof(CollectionProxy))]
19 public class PersistentArrayHolder : AbstractPersistentCollection
20 {
21 private static readonly ILog log = LogManager.GetLogger(typeof(PersistentArrayHolder));
22
23 /// <summary>
24 /// The <see cref="Array"/> that NHibernate is wrapping.
25 /// </summary>
26 private Array array;
27
28 [NonSerialized]
29 private System.Type elementClass;
30
31 /// <summary>
32 /// A temporary list that holds the objects while the PersistentArrayHolder is being
33 /// populated from the database.
34 /// </summary>
35 [NonSerialized]
36 private ArrayList tempList;
37
38
39 public PersistentArrayHolder(ISessionImplementor session, object array) : base(session)
40 {
41 this.array = (Array) array;
42 SetInitialized();
43 }
44
45 /// <summary>
46 ///
47 /// </summary>
48 /// <param name="persister"></param>
49 /// <returns></returns>
50 protected override ICollection Snapshot(ICollectionPersister persister)
51 {
52 EntityMode entityMode = Session.EntityMode;
53
54 int length = /*(array==null) ? temp.Count :*/ array.Length;
55 Array result = System.Array.CreateInstance(persister.ElementClass, length);
56 for (int i = 0; i < length; i++)
57 {
58 object elt = /*(array==null) ? temp[i] :*/ array.GetValue(i);
59 try
60 {
61 result.SetValue(persister.ElementType.DeepCopy(elt, entityMode, persister.Factory), i);
62 }
63 catch (Exception e)
64 {
65 log.Error("Array element type error", e);
66 throw new HibernateException("Array element type error", e);
67 }
68 }
69 return result;
70 }
71
72 public override ICollection GetOrphans(object snapshot, string entityName)
73 {
74 object[] sn = (object[]) snapshot;
75 object[] arr = (object[]) array;
76 ArrayList result = new ArrayList(sn.Length);
77 for (int i = 0; i < sn.Length; i++)
78 {
79 result.Add(sn[i]);
80 }
81 for (int i = 0; i < sn.Length; i++)
82 {
83 IdentityRemove(result, arr[i], entityName, Session);
84 }
85 return result;
86 }
87
88
89 public PersistentArrayHolder(ISessionImplementor session, ICollectionPersister persister)
90 : base(session)
91 {
92 elementClass = persister.ElementClass;
93 }
94
95 /// <summary>
96 ///
97 /// </summary>
98 public object Array
99 {
100 get { return array; }
101 }
102
103 /// <summary>
104 ///
105 /// </summary>
106 /// <param name="collection"></param>
107 /// <returns></returns>
108 public override bool IsWrapper(object collection)
109 {
110 return array == collection;
111 }
112
113 public override bool EqualsSnapshot(ICollectionPersister persister)
114 {
115 IType elementType = persister.ElementType;
116 Array snapshot = GetSnapshot() as Array;
117
118 int xlen = snapshot.Length;
119 if (xlen != array.Length)
120 {
121 return false;
122 }
123 for (int i = 0; i < xlen; i++)
124 {
125 if (elementType.IsDirty(snapshot.GetValue(i), array.GetValue(i), Session))
126 {
127 return false;
128 }
129 }
130 return true;
131 }
132
133 /// <summary>
134 ///
135 /// </summary>
136 /// <returns></returns>
137 public ICollection Elements()
138 {
139 //if (array==null) return tempList;
140 int length = array.Length;
141 IList list = new ArrayList(length);
142 for (int i = 0; i < length; i++)
143 {
144 list.Add(array.GetValue(i));
145 }
146 return list;
147 }
148
149 /// <summary>
150 ///
151 /// </summary>
152 public override bool Empty
153 {
154 get { return false; }
155 }
156
157 public override object ReadFrom(IDataReader rs, ICollectionPersister role, ICollectionAliases descriptor, object owner)
158 {
159 object element = role.ReadElement(rs, owner, descriptor.SuffixedElementAliases, Session);
160 int index = (int) role.ReadIndex(rs, descriptor.SuffixedIndexAliases, Session);
161 for (int i = tempList.Count; i <= index; i++)
162 {
163 tempList.Add(null);
164 }
165 tempList[index] = element;
166 return element;
167 }
168
169 /// <summary>
170 ///
171 /// </summary>
172 /// <returns></returns>
173 public override IEnumerable Entries()
174 {
175 return Elements();
176 }
177
178 /// <summary>
179 /// Before <see cref="ReadFrom" /> is called the PersistentArrayHolder needs to setup
180 /// a temporary list to hold the objects.
181 /// </summary>
182 public override void BeginRead()
183 {
184 base.BeginRead();
185 tempList = new ArrayList();
186 }
187
188 /// <summary>
189 /// Takes the contents stored in the temporary list created during <see cref="BeginRead" />
190 /// that was populated during <see cref="ReadFrom" /> and write it to the underlying
191 /// array.
192 /// </summary>
193 public override bool EndRead(ICollectionPersister persister)
194 {
195 SetInitialized();
196 array = System.Array.CreateInstance(elementClass, tempList.Count);
197 int index = 0;
198 foreach (object element in tempList)
199 {
200 array.SetValue(element, index);
201 index++;
202 }
203 tempList = null;
204
205 return true;
206 }
207
208 public override void BeforeInitialize(ICollectionPersister persister)
209 {
210 }
211
212 public override bool IsDirectlyAccessible
213 {
214 get { return true; }
215 }
216
217 /// <summary>
218 /// Initializes this array holder from the cached values.
219 /// </summary>
220 /// <param name="persister">The CollectionPersister to use to reassemble the Array.</param>
221 /// <param name="disassembled">The disassembled Array.</param>
222 /// <param name="owner">The owner object.</param>
223 public override void InitializeFromCache(ICollectionPersister persister, object disassembled, object owner)
224 {
225 object[] cached = (object[]) disassembled;
226
227 array = System.Array.CreateInstance(persister.ElementClass, cached.Length);
228
229 for (int i = 0; i < cached.Length; i++)
230 {
231 array.SetValue(persister.ElementType.Assemble(cached[i], Session, owner), i);
232 }
233 SetInitialized();
234 }
235
236 public override object Disassemble(ICollectionPersister persister)
237 {
238 int length = array.Length;
239 object[] result = new object[length];
240 for (int i = 0; i < length; i++)
241 {
242 result[i] = persister.ElementType.Disassemble(array.GetValue(i), Session, null);
243 }
244 return result;
245 }
246
247 /// <summary>
248 /// Returns the user-visible portion of the NHibernate PersistentArrayHolder.
249 /// </summary>
250 /// <returns>
251 /// The array that contains the data, not the NHibernate wrapper.
252 /// </returns>
253 public override object GetValue()
254 {
255 return array;
256 }
257
258 public override IEnumerable GetDeletes(IType elemType, bool indexIsFormula)
259 {
260 IList deletes = new ArrayList();
261 Array sn = GetSnapshot() as Array;
262 int snSize = sn.Length;
263 int arraySize = array.Length;
264 int end;
265 if (snSize > arraySize)
266 {
267 for (int i = arraySize; i < snSize; i++)
268 {
269 deletes.Add(i);
270 }
271 end = arraySize;
272 }
273 else
274 {
275 end = snSize;
276 }
277 for (int i = 0; i < end; i++)
278 {
279 if (array.GetValue(i) == null && sn.GetValue(i) != null)
280 {
281 deletes.Add(i);
282 }
283 }
284 return deletes;
285 }
286
287 public override bool NeedsInserting(object entry, int i, IType elemType)
288 {
289 Array sn = GetSnapshot() as Array;
290 return array.GetValue(i) != null && (i >= sn.Length || sn.GetValue(i) == null);
291 }
292
293 public override bool NeedsUpdating(object entry, int i, IType elemType)
294 {
295 Array sn = GetSnapshot() as Array;
296 return i < sn.Length &&
297 sn.GetValue(i) != null &&
298 array.GetValue(i) != null &&
299 elemType.IsDirty(array.GetValue(i), sn.GetValue(i), Session);
300 }
301
302 public override object GetIndex(object entry, int i)
303 {
304 return i;
305 }
306
307 public override object GetElement(object entry)
308 {
309 return entry;
310 }
311
312 public override object GetSnapshotElement(object entry, int i)
313 {
314 Array sn = (Array) GetSnapshot();
315 return sn.GetValue(i);
316 }
317
318 public override bool EntryExists(object entry, int i)
319 {
320 return entry != null;
321 }
322
323 public void CopyTo(Array array, int index)
324 {
325 this.array.CopyTo(array, index);
326 }
327
328 public int Count
329 {
330 get { return array.Length; }
331 }
332
333 public IEnumerator GetEnumerator()
334 {
335 return array.GetEnumerator();
336 }
337
338 public bool IsSynchronized
339 {
340 get { return false; }
341 }
342
343 public object SyncRoot
344 {
345 get { return this; }
346 }
347
348 public override IEnumerable Entries(ICollectionPersister persister)
349 {
350 return Elements();
351 }
352 }
353}