/// /// Copyright © 2003-2008 JetBrains s.r.o. /// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder). /// using System; using System.Collections; using System.Collections.Generic; using System.Text; namespace JetBrains.Omea.OpenAPI { public class BusinessObject { private IResource _resource; private string _newResourceType; private Dictionary _props; protected BusinessObject(string resourceType) { _newResourceType = resourceType; } protected BusinessObject(IResource res) { _resource = res; } public IResource Resource { get { return _resource; } } public T GetProp(PropId propId) { lock(this) { if (_props != null) { return (T)_props[propId.Id]; } if (_resource != null) { return _resource.GetProp(propId); } } return default(T); } public void SetProp(PropId propId, T value) { lock(this) { if (_resource != null && Core.ResourceAP.IsOwnerThread) { _resource.SetProp(propId, value); } else { if (_props == null) { _props = new Dictionary(); } _props[propId.Id] = value; } } } public bool HasProp(PropId propId) { lock(this) { return (_props != null && _props.ContainsKey(propId.Id)) || (_resource != null && _resource.HasProp(propId.Id)); } } public void Save() { if (_props != null || _newResourceType != null) { Core.ResourceAP.RunJob("Saving BusinessObject", DoSave); } } public void SaveAsync() { if (_props != null || _newResourceType != null) { Core.ResourceAP.QueueJob("Saving BusinessObject", DoSave); } } private void DoSave() { lock(this) { if (_resource == null) { _resource = Core.ResourceStore.BeginNewResource(_newResourceType); BusinessObjectCache.Put(this); } else { _resource.BeginUpdate(); } if (_props != null) { foreach (var prop in _props) { _resource.SetProp(prop.Key, prop.Value); } _props = null; } _resource.EndUpdate(); } } public void Delete() { int id = _resource.Id; if (Core.ResourceAP.IsOwnerThread) { _resource.Delete(); } else { new ResourceProxy(_resource).Delete(); } BusinessObjectCache.Remove(id); } } public abstract class ResourceTypeId where T: BusinessObject { private readonly string _name; protected ResourceTypeId(string name) { _name = name; } public string Name { get { return _name; } } public abstract T CreateBusinessObject(IResource res); } public class BusinessObjectCache { private static readonly Dictionary _cache = new Dictionary(); public static T Get(IResource res, ResourceTypeId resourceTypeId) where T: BusinessObject { lock(_cache) { WeakReference reference; if (_cache.TryGetValue(res.Id, out reference)) { object target = reference.Target; if (target != null) { return (T) target; } } T result = resourceTypeId.CreateBusinessObject(res); _cache[res.Id] = new WeakReference(result); return result; } } internal static void Put(BusinessObject o) { lock(_cache) { _cache [o.Resource.Id] = new WeakReference(o); } } internal static void Remove(int id) { lock(_cache) { _cache.Remove(id); } } } public class BusinessObjectList: IEnumerable where T: BusinessObject { private readonly ResourceTypeId _resourceTypeId; private readonly IResourceList _baseList; public BusinessObjectList(ResourceTypeId resourceTypeId, IResourceList baseList) { _resourceTypeId = resourceTypeId; _baseList = baseList; } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable) this).GetEnumerator(); } public IEnumerator GetEnumerator() { return new BusinessObjectEnumerator(_resourceTypeId, _baseList.ValidResources.GetEnumerator()); } public int Count { get { return _baseList.Count; } } public T this[int i] { get { return BusinessObjectCache.Get(_baseList[i], _resourceTypeId); } } public BusinessObjectList Intersect(BusinessObjectList list) { return new BusinessObjectList(_resourceTypeId, _baseList.Intersect(list._baseList)); } class BusinessObjectEnumerator: IEnumerator where T: BusinessObject { private readonly ResourceTypeId _resourceType; private readonly IEnumerator _resourceEnumerator; public BusinessObjectEnumerator(ResourceTypeId resourceType, IEnumerator idEnumerator) { _resourceType = resourceType; _resourceEnumerator = idEnumerator; } public void Dispose() { } public bool MoveNext() { return _resourceEnumerator.MoveNext(); } public void Reset() { _resourceEnumerator.Reset(); } object IEnumerator.Current { get { return GetCurrentItem(); } } public T Current { get { return GetCurrentItem(); } } private T GetCurrentItem() { IResource res = (IResource) _resourceEnumerator.Current; return BusinessObjectCache.Get(res, _resourceType); } } } }