123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Diagnostics.CodeAnalysis;
- using System.IO;
- using System.Linq;
- using System.Reflection;
- using System.Runtime.CompilerServices;
- using InABox.Clients;
- using InABox.Core;
- using InABox.Mobile;
- using Xamarin.Forms;
- namespace InABox.Mobile
- {
-
- public abstract class Model<TParent, TItem, TEntity> : BindableObject, IModel
- where TParent : Model<TParent, TItem, TEntity>, IModel
- where TEntity : Entity, IRemotable, IPersistent, new()
- where TItem : Shell<TParent, TEntity>, new()
- {
-
- public Model(IModelHost host, Func<Filter<TEntity>> filter, bool transient = false)
- {
- Reset();
- new TItem();
- Host = host;
- Filter = filter;
- Type = transient ? ModelType.Transient : ModelType.Normal;
- }
- public Model(IModelHost host, Func<Filter<TEntity>> filter, [NotNull] String filename)
- {
- Reset();
- new TItem();
- Host = host;
- Type = ModelType.Persistent;
- Filter = filter;
- FileName = filename;
- }
-
- #region INotifyPropertyChanged
-
- public event PropertyChangedEventHandler PropertyChanged;
- protected void DoPropertyChanged(object sender, PropertyChangedEventArgs args)
- {
- PropertyChanged?.Invoke(sender, args);
- }
-
- protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
- {
- if (EqualityComparer<T>.Default.Equals(field, value)) return false;
- field = value;
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
- return true;
- }
-
- #endregion
-
- public bool Loaded { get; protected set; }
-
- public abstract void BeforeLoad(MultiQuery query);
- public abstract void AfterLoad(MultiQuery query);
- public abstract void Load(Action loaded = null);
- public abstract IModel Refresh(bool force);
- public abstract void Refresh(bool force, Action loaded);
- public event ModelChangedEvent Changed;
- protected void NotifyChanged() => Changed?.Invoke(this, new ModelChangedEventArgs());
- protected abstract void Initialize();
-
- public void Reset()
- {
- Loaded = false;
- Images.Clear();
- Initialize();
- }
-
- protected Func<Filter<TEntity>> Filter { get; set; }
-
- // // Use "new" to replace this with your actual columns
- // public Columns<TEntity> Columns
- // {
- // get
- // {
- // var prop = typeof(TItem).GetProperty("Columns",
- // BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
- // var cols = prop?.GetValue(null) as IShellColumns<TEntity>;
- // return cols?.Columns;
- // }
- // }
-
- protected Columns<TOtherEntity> GetColumns<TOtherItem, TOtherEntity>()
- where TOtherItem : Shell<TParent, TOtherEntity>, new()
- where TOtherEntity : Entity, IRemotable, IPersistent, new()
- {
- return new TOtherItem().Columns.Columns;
- }
- //public IColumns GetColumns() => Columns;
-
- public Dictionary<Guid, byte[]> Images { get; private set; } = new Dictionary<Guid, byte[]>();
- public ImageSource GetImage(Guid id)
- {
- ImageSource result = null;
- if (Images.TryGetValue(id, out byte[] data))
- result = ImageSource.FromStream(() => new MemoryStream(data));
- return result;
-
- }
-
- public bool HasImages() => Images.Any();
- public IModelHost Host { get; private set; }
-
- public ModelType Type { get; private set; }
-
- public String FileName { get; private set; }
-
- protected void InitializeTables(MultiQuery query)
- {
- var defs = query.Definitions();
- foreach (var def in defs)
- {
- var table = InitializeTable(def.Value);
- query.Set(def.Key, table);
- }
- }
- protected CoreTable InitializeTable(IQueryDef def)
- {
- var table = new CoreTable();
- if (def.Columns != null)
- table.LoadColumns(def.Columns);
- else
- table.LoadColumns(def.Type);
- return table;
- }
- protected class QueryStorage : ISerializeBinary
- {
- private Dictionary<String, CoreTable> _data = new Dictionary<string, CoreTable>();
- public CoreTable Get([NotNull] String key) => _data[key];
-
- public void Set([NotNull] String key, CoreTable table) => _data[key] = table;
- public bool Contains([NotNull] String key) => _data.ContainsKey(key);
-
- public void SerializeBinary(CoreBinaryWriter writer)
- {
- writer.Write(_data.Count);
- foreach (var key in _data.Keys)
- {
- writer.Write(key);
- _data[key].SerializeBinary(writer);
- }
- }
- public void DeserializeBinary(CoreBinaryReader reader)
- {
- int count = reader.ReadInt32();
- for (int i = 0; i < count; i++)
- {
- String key = reader.ReadString();
- CoreTable table = new CoreTable();
- table.DeserializeBinary(reader);
- _data[key] = table;
- }
- }
- }
-
- protected void LoadFromStorage(MultiQuery query)
- {
- QueryStorage storage = new QueryStorage();
- var file = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), FileName);
- if (File.Exists(file))
- {
- using (var stream = new FileStream(file, FileMode.Open))
- storage = Serialization.ReadBinary<QueryStorage>(stream, BinarySerializationSettings.Latest);
- var defs = query.Definitions();
- foreach (var key in defs.Keys)
- {
- var table = storage.Contains(key.ToString())
- ? storage.Get(key.ToString())
- : InitializeTable(defs[key]);
- query.Set(key, table);
- }
- }
- else
- InitializeTables(query);
- }
-
- protected void SaveToStorage(MultiQuery query)
- {
- QueryStorage storage = new QueryStorage();
- var results = query.Results();
- foreach (var key in results.Keys)
- storage.Set(key.ToString(),results[key]);
- var data = storage.WriteBinary(BinarySerializationSettings.Latest);
- try
- {
- var file = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), FileName);
- File.WriteAllBytes(file,data);
- }
- catch (Exception e)
- {
- MobileLogging.Log(e);
- }
- }
- }
- }
|