00001 using System;
00002 using System.Collections.Generic;
00003 using System.Text;
00004 using Foodolini.Database;
00005 using System.Diagnostics;
00006
00007 namespace Foodolini.BusinessLogic
00008 {
00009 public partial class Recipe
00010 {
00011 private class RatingDictionary : IDictionary<Person, double>{
00012
00013 private Dictionary<long, Rating> cachedRatings = new Dictionary<long, Rating>();
00014 private Dictionary<long, Rating> changedRatings = new Dictionary<long, Rating>();
00015 private Dictionary<long, Rating> deletedRatings = new Dictionary<long, Rating>();
00016
00023 public RatingDictionary(long recipeId){
00024 if(recipeId != 0){
00025 var query = Settings.Repo.Where<Rating>("RecipeId = @0", recipeId);
00026 foreach(var rating in query)
00027 this.cachedRatings.Add(rating.UserId, rating);
00028 }
00029 }
00030
00041 private void setValue(long person, double rating){
00042 Rating val = null;
00043
00044 if(this.cachedRatings.TryGetValue(person, out val)){
00045 val.Score = rating;
00046 this.cachedRatings.Remove(person);
00047 this.changedRatings.Add(person, val);
00048
00049 }else if(this.changedRatings.TryGetValue(person, out val)){
00050 val.Score = rating;
00051
00052 }else if(this.deletedRatings.TryGetValue(person, out val)){
00053 val.Score = rating;
00054 this.deletedRatings.Remove(person);
00055 this.changedRatings.Add(person, val);
00056
00057 }else{
00058 val = new Rating();
00059 val.Score = rating;
00060 val.UserId = person;
00061 val.RecipeId = 0;
00062 this.changedRatings.Add(person, val);
00063 }
00064 }
00065
00072 public void Save(long recipeId){
00073
00074 foreach(Rating rating in this.cachedRatings.Values){
00075 if(rating.RecipeId != recipeId){
00076 Debug.Fail("This RatingDictionary was created for another recipe!");
00077 rating.RecipeId = recipeId;
00078 Settings.Repo.Add<Rating>(rating);
00079 }
00080 }
00081
00082 foreach(Rating rating in this.changedRatings.Values){
00083
00084 if(rating.RatingId != 0 && rating.RecipeId == recipeId){
00085 Settings.Repo.Update<Rating>(rating);
00086 }else{
00087 Debug.Assert(rating.RatingId == 0, "This RatingDictionary was created for another recipe!");
00088
00089
00090 rating.RecipeId = recipeId;
00091 Settings.Repo.Add<Rating>(rating);
00092 }
00093
00094 this.cachedRatings.Add(rating.UserId, rating);
00095 }
00096 this.changedRatings.Clear();
00097
00098 foreach(Rating rating in this.deletedRatings.Values){
00099
00100 if(rating.RatingId != 0 && rating.RecipeId == recipeId)
00101 Settings.Repo.Delete<Rating>(rating);
00102 else
00103 Debug.Assert(rating.RecipeId == recipeId, "This RatingDictionary was created for another recipe!");
00104 }
00105
00106 this.deletedRatings.Clear();
00107 }
00108
00112 public void Delete(long recipeId){
00113
00114 foreach(Rating rating in this.cachedRatings.Values){
00115 if(rating.RecipeId == recipeId){
00116 Settings.Repo.Delete<Rating>(rating);
00117 rating.RatingId = 0;
00118 }else
00119 Debug.Assert(rating.RecipeId == 0, "This RatingDictionary was created for another recipe!");
00120 this.changedRatings.Add(rating.UserId, rating);
00121 }
00122
00123 this.cachedRatings.Clear();
00124
00125 foreach(Rating rating in this.changedRatings.Values){
00126 if(rating.RatingId != 0 && rating.RecipeId == recipeId){
00127 Settings.Repo.Delete<Rating>(rating);
00128 rating.RatingId = 0;
00129 }else
00130 Debug.Assert(rating.RecipeId == 0, "This RatingDictionary was created for another recipe!");
00131 }
00132
00133 foreach(Rating rating in this.deletedRatings.Values){
00134 if(rating.RatingId != 0 && rating.RecipeId == recipeId)
00135 Settings.Repo.Delete<Rating>(rating);
00136 else
00137 Debug.Assert(rating.RecipeId == 0, "This RatingDictionary was created for another recipe!");
00138 }
00139
00140 this.deletedRatings.Clear();
00141 }
00142
00143 #region IDictionary<Person, double> implementation
00144 public void Add (Person key, double value){
00145 this.setValue(key.Id, value);
00146 }
00147
00148 public bool ContainsKey (Person key){
00149 return this.cachedRatings.ContainsKey(key.Id) || this.changedRatings.ContainsKey(key.Id);
00150 }
00151
00152 public bool Remove (Person key){
00153 Rating val = null;
00154 if(this.cachedRatings.TryGetValue(key.Id, out val)){
00155
00156 if(val.RatingId != 0)
00157 this.deletedRatings.Add(key.Id, val);
00158 this.cachedRatings.Remove(key.Id);
00159 return true;
00160 }
00161 if(this.changedRatings.TryGetValue(key.Id, out val)){
00162
00163 if(val.RatingId != 0)
00164 this.deletedRatings.Add(key.Id, val);
00165 this.changedRatings.Remove(key.Id);
00166 return true;
00167 }
00168 return false;
00169 }
00170
00171 public bool TryGetValue (Person key, out double value){
00172 Rating val = null;
00173 if(this.cachedRatings.TryGetValue(key.Id, out val)){
00174 value = val.Score;
00175 return true;
00176 }
00177 if(this.changedRatings.TryGetValue(key.Id, out val)){
00178 value = val.Score;
00179 return true;
00180 }
00181 value = new double();
00182 return false;
00183 }
00184
00185
00186 public double this[Person key] {
00187 get {
00188 double val;
00189 if(this.TryGetValue(key, out val))
00190 return val;
00191 throw new KeyNotFoundException(key.FullName + " was not found in the dictionary.");
00192 }
00193 set {
00194 this.setValue(key.Id, value);
00195 }
00196 }
00197
00198 #region PersonCollection
00199
00200 private class PersonCollection : ICollection<Person>{
00201 private RatingDictionary owner;
00202
00203 public PersonCollection(RatingDictionary owner){
00204 this.owner = owner;
00205 }
00206
00207 #region IEnumerable implementation
00208 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator (){
00209 return this.GetEnumerator();
00210 }
00211 #endregion
00212
00213 #region IEnumerable<Person> implementation
00214 public IEnumerator<Person> GetEnumerator (){
00215 foreach(var p in this.owner.cachedRatings.Keys)
00216 yield return Person.GetById(p);
00217 foreach(var p in this.owner.changedRatings.Keys)
00218 yield return Person.GetById(p);
00219 }
00220 #endregion
00221
00222 #region ICollection<Person> implementation
00223 public void Add (Person item){
00224 throw new NotSupportedException("This is a read-only collection, modify the RatingDictionary instead!");
00225 }
00226
00227 public void Clear (){
00228 throw new NotSupportedException("This is a read-only collection, modify the RatingDictionary instead!");
00229 }
00230
00231 public bool Contains (Person item){
00232 return this.owner.ContainsKey(item);
00233 }
00234
00235 public void CopyTo (Person[] array, int arrayIndex){
00236 if(arrayIndex < 0)
00237 throw new ArgumentOutOfRangeException("arrayIndex", "arrayIndex cannot be less than 0");
00238 foreach(Person val in this)
00239 array[arrayIndex++] = val;
00240 }
00241
00242 public bool Remove (Person item){
00243 throw new NotSupportedException("This is a read-only collection, modify the RatingDictionary instead!");
00244 }
00245
00246 public int Count {
00247 get {
00248 return this.owner.Count;
00249 }
00250 }
00251
00252 public bool IsReadOnly {
00253 get {
00254 return true;
00255 }
00256 }
00257 #endregion
00258 }
00259 #endregion
00260
00261 public ICollection<Person> Keys {
00262 get {
00263 return new PersonCollection(this);
00264 }
00265 }
00266
00267 #region RatingCollection
00268
00269 private class RatingCollection : ICollection<double>{
00270 private RatingDictionary owner;
00271
00272 public RatingCollection(RatingDictionary owner){
00273 this.owner = owner;
00274 }
00275
00276 #region IEnumerable implementation
00277 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator (){
00278 return this.GetEnumerator();
00279 }
00280 #endregion
00281
00282 #region IEnumerable<double> implementation
00283 public IEnumerator<double> GetEnumerator (){
00284 foreach(var v in this.owner.cachedRatings.Values)
00285 yield return v.Score;
00286 foreach(var v in this.owner.changedRatings.Values)
00287 yield return v.Score;
00288 }
00289 #endregion
00290
00291 #region ICollection<double> implementation
00292 public void Add (double item){
00293 throw new NotSupportedException("This is a read-only collection, modify the RatingDictionary instead!");
00294 }
00295
00296 public void Clear (){
00297 throw new NotSupportedException("This is a read-only collection, modify the RatingDictionary instead!");
00298 }
00299
00300 public bool Contains (double item){
00301 foreach(double d in this){
00302 if(d == item)
00303 return true;
00304 }
00305 return false;
00306 }
00307
00308 public void CopyTo (double[] array, int arrayIndex){
00309 if(arrayIndex < 0)
00310 throw new ArgumentOutOfRangeException("arrayIndex", "arrayIndex cannot be less than 0");
00311 foreach(double val in this)
00312 array[arrayIndex++] = val;
00313 }
00314
00315 public bool Remove (double item){
00316 throw new NotSupportedException("This is a read-only collection, modify the RatingDictionary instead!");
00317 }
00318
00319 public int Count {
00320 get {
00321 return this.owner.Count;
00322 }
00323 }
00324
00325 public bool IsReadOnly {
00326 get {
00327 return true;
00328 }
00329 }
00330 #endregion
00331 }
00332 #endregion
00333
00334 public ICollection<double> Values {
00335 get {
00336 return new RatingCollection(this);
00337 }
00338 }
00339 #endregion
00340
00341 #region IEnumerable<KeyValuePair<Person, double>> implementation
00342 public IEnumerator<KeyValuePair<Person, double>> GetEnumerator (){
00343 foreach(var entry in this.cachedRatings)
00344 yield return new KeyValuePair<Person,double>(Person.GetById(entry.Key), entry.Value.Score);
00345 foreach(var entry in this.changedRatings)
00346 yield return new KeyValuePair<Person,double>(Person.GetById(entry.Key), entry.Value.Score);
00347 }
00348
00349 #endregion
00350
00351 #region IEnumerable implementation
00352 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator (){
00353 return this.GetEnumerator();
00354 }
00355
00356 #endregion
00357
00358 #region ICollection<KeyValuePair<Person, double>> implementation
00359 public void Add (KeyValuePair<Person, double> item){
00360 this.setValue(item.Key.Id, item.Value);
00361 }
00362
00363 public void Clear (){
00364 List<long> ids = new List<long>(this.cachedRatings.Keys);
00365 foreach(var id in ids)
00366 this.Remove(Person.GetById(id));
00367 ids = new List<long>(this.changedRatings.Keys);
00368 foreach(var id in ids)
00369 this.Remove(Person.GetById(id));
00370 }
00371
00372 public bool Contains (KeyValuePair<Person, double> item){
00373 double val;
00374 return this.TryGetValue(item.Key, out val) && val == item.Value;
00375 }
00376
00377 public void CopyTo (KeyValuePair<Person, double>[] array, int arrayIndex){
00378 if(arrayIndex < 0)
00379 throw new ArgumentOutOfRangeException("arrayIndex", "arrayIndex cannot be less than 0");
00380 foreach(KeyValuePair<Person, double> pair in this)
00381 array[arrayIndex++] = pair;
00382 }
00383
00384 public bool Remove (KeyValuePair<Person, double> item){
00385 Rating val = null;
00386 if(this.cachedRatings.TryGetValue(item.Key.Id, out val)){
00387 if(val.Score == item.Value)
00388 return this.Remove(item.Key);
00389 }
00390 if(this.changedRatings.TryGetValue(item.Key.Id, out val)){
00391 if(val.Score == item.Value)
00392 return this.Remove(item.Key);
00393 }
00394 return false;
00395 }
00396
00397 public int Count {
00398 get {
00399 return this.cachedRatings.Count + this.changedRatings.Count;
00400 }
00401 }
00402
00403 public bool IsReadOnly {
00404 get {
00405 return false;
00406 }
00407 }
00408 #endregion
00409
00410 }
00411 }
00412 }