SmartAPI
Open Source .NET RQL library for RedDot CMS / OpenText WSM Management Server
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Pages
IndexedCachedList.cs
Go to the documentation of this file.
1 ï»¿// SmartAPI - .Net programmatic access to RedDot servers
2 //
3 // Copyright (C) 2013 erminas GbR
4 //
5 // This program is free software: you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License as published by the Free Software Foundation,
7 // either version 3 of the License, or (at your option) any later version.
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 // See the GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License along with this program.
14 // If not, see <http://www.gnu.org/licenses/>.
15 
16 using System;
17 using System.Collections.Generic;
18 using System.Linq;
19 
20 namespace erminas.SmartAPI.Utils.CachedCollections
21 {
25  public class IndexedCachedList<TK, T> : CachedList<T>, IIndexedCachedList<TK, T> where T : class
26  {
27  private readonly Func<T, TK> _indexFunc;
28  private Dictionary<TK, T> _index = new Dictionary<TK, T>();
29 
30  public IndexedCachedList(Func<List<T>> retrieveFunc, Func<T, TK> indexFunc, Caching caching) : base(retrieveFunc, caching)
31  {
32  _indexFunc = indexFunc;
33  }
34 
35  protected IndexedCachedList(Func<T, TK> indexFunc, Caching caching) : base(caching)
36  {
37  _indexFunc = indexFunc;
38  }
39 
40  protected override List<T> List
41  {
42  set
43  {
44  base.List = value;
45  if (IsCachingEnabled)
46  {
47  _index.Clear();
48  if (value != null)
49  {
50  //TODO hier auf duplikate pruefen bei fehler und bessere exception ausgeben
51  try
52  {
53  _index = value.ToDictionary(_indexFunc);
54  }
55  catch (ArgumentException e)
56  {
57  ThrowDuplicatesException(value, e);
58  }
59  }
60  }
61  }
62  }
63 
64  private void ThrowDuplicatesException(List<T> value, ArgumentException e)
65  {
66  var duplicates = value.GroupBy(_indexFunc)
67  .Where(g => g.Count() > 1)
68  .Select(y => y.Key)
69  .ToArray();
70  throw new Exception("Duplicate key/s: " + string.Join(", ", duplicates), e);
71  }
72 
73  #region IIndexedCachedList<TK,T> Members
74 
75  public bool ContainsKey(TK key)
76  {
77  EnsureListIsLoaded();
78  return _index.ContainsKey(key);
79  }
80 
81  public T Get(TK key)
82  {
83  EnsureListIsLoaded();
84  try
85  {
86  return IsCachingEnabled
87  ? _index[key]
88  : List.First(
89  x => _indexFunc(x)
90  .Equals(key));
91  }
92  catch (InvalidOperationException e)
93  {
94  throw new KeyNotFoundException(String.Format("No element with key '{0}' found", key), e);
95  }
96  }
97 
98  public override bool IsCachingEnabled
99  {
100  set
101  {
102  if (value && !base.IsCachingEnabled && List != null)
103  {
104  try
105  {
106  _index = List.ToDictionary(_indexFunc);
107  }
108  catch (ArgumentException e)
109  {
110  ThrowDuplicatesException(List, e);
111  }
112  }
113  else
114  {
115  if (!value && base.IsCachingEnabled)
116  {
117  _index = null;
118  }
119  }
120 
121  base.IsCachingEnabled = value;
122  }
123  }
124 
125  public T this[TK key]
126  {
127  get { return Get(key); }
128  }
129 
130  public new IIndexedCachedList<TK, T> Refreshed()
131  {
132  Refresh();
133  return this;
134  }
135 
136  public bool TryGet(TK key, out T obj)
137  {
138  if (key == null)
139  {
140  obj = null;
141  return false;
142  }
143  EnsureListIsLoaded();
144  if (IsCachingEnabled)
145  {
146  return _index.TryGetValue(key, out obj);
147  }
148 
149  obj = List.FirstOrDefault(
150  x => _indexFunc(x)
151  .Equals(key));
152  return obj != null;
153  }
154 
155  public void WaitFor(Predicate<IIndexedCachedList<TK, T>> predicate, TimeSpan maxWait, TimeSpan retryPeriod)
156  {
157  Wait.For(() => predicate(Refreshed()), maxWait, retryPeriod);
158  }
159 
160  #endregion
161  }
162 }