//-----------------------------------------------------------------------------
//
// Company copyright tag.
//
// fiedlchr
// 05.07.2013
//-----------------------------------------------------------------------------
namespace CampusAppWPortalLib8.Model
{
using System;
using System.Collections.Generic;
using CampusAppWPortalLib8.Model.Utility;
using CampusAppWPortalLib8.Utility;
///
/// abstract Base model io handling class.
///
/// model type
public abstract class AbstractMainModel
{
#region Member
///
/// File object.
///
private AbstractFile file = null;
///
/// Model io type.
///
private ModelType modelType;
///
/// Model object.
///
private T model = default(T);
///
/// Web object.
///
private AbstractHttpRequest api = null;
///
/// Filename of saved data.
///
private string fileName = string.Empty;
///
/// Url of the feed data.
///
private Uri httpApiUri = null;
///
/// Parameterized uri of the feed.
///
private Uri paramizedUri = null;
#endregion
#region Constructor
///
/// Initializes a new instance of the class.
///
/// Model IO type
/// name of the file
/// url of the feed
public AbstractMainModel(ModelType modelType, string fileName, string url)
{
this.Init(modelType, fileName, url);
}
///
/// Initializes a new instance of the class.
///
/// Model IO type
/// name of the file or the url of the feed
public AbstractMainModel(ModelType modelType, string sourceName)
{
if (modelType == ModelType.File)
{
this.Init(modelType, sourceName, string.Empty);
}
else if (modelType == ModelType.Feed)
{
this.Init(modelType, string.Empty, sourceName);
}
else
{
throw new NotSupportedException("Wrong constructor was called for Feed and File support.");
}
}
#endregion
#region Events
///
/// Delegate of the OnIO callback function.
///
public delegate void OnIO();
///
/// Delegate of the OnFailed(File/Web) callback function.
///
public delegate void OnFailed();
///
/// Delegate of the IsModelUpToDate callback function.
///
/// data model
/// true, model is up to date
public delegate bool IsModelUpToDate(T model);
///
/// Callback pointer, called before loading.
///
public event OnIO OnLoading = null;
///
/// Callback pointer, called after loading.
///
public event OnIO OnLoaded = null;
///
/// Callback pointer, called before saving.
///
public event OnIO OnSaving = null;
///
/// Callback pointer, called after saving.
///
public event OnIO OnSaved = null;
///
/// Callback pointer, called after failed file loading.
///
public event OnFailed OnFailedFile = null;
///
/// Callback pointer, called after failed web loading.
///
public event OnFailed OnFailedWeb = null;
///
/// Callback pointer, called after failed file or web loading, if there
/// is no specialized onFailed callback set.
///
public event OnFailed OnFailedLoad = null;
///
/// Callback pointer, called after failed saving data to file.
///
public event OnFailed OnFailedSave = null;
///
/// Callback pointer, for checking if model is up to date at loading.
///
public event IsModelUpToDate IsModelUpToDateOnLoad = null;
///
/// Callback pointer, for checking if model is up to date at saving.
/// (currently unused)
///
#pragma warning disable 0067
public event IsModelUpToDate IsModelUpToDateOnSave = null;
#endregion
#region Property
///
/// Gets or sets the Model.
///
public T Model
{
get
{
return this.model;
}
set
{
this.model = value;
}
}
///
/// Gets or sets the File.
///
public AbstractFile File
{
get { return this.file; }
protected set { this.file = value; }
}
///
/// Gets or sets the ModelType.
///
public ModelType ModelType
{
get { return this.modelType; }
protected set { this.modelType = value; }
}
///
/// Gets or sets the Api.
///
public AbstractHttpRequest Api
{
get { return this.api; }
protected set { this.api = value; }
}
///
/// Gets or sets the ApiUrl.
///
public Uri HttpApiUri
{
get { return this.httpApiUri; }
protected set { this.httpApiUri = value; }
}
///
/// Gets or sets the FileName.
///
public string FileName
{
get { return this.fileName; }
protected set { this.fileName = value; }
}
#endregion
#region Method
#region public
///
/// Method Fire all Events for fail load
///
public void FireLoadFailEvents()
{
this.RunOnFailedCallback(this.OnFailedWeb, this.OnFailedLoad);
}
///
/// Method Fire all Events for load is complete
///
public void FireLoadCompletedEvents()
{
this.RunOnIOCallback(this.OnLoaded);
}
///
/// Forces a update from web.
///
public void ForceWebUpdate()
{
this.LoadData(ForceType.FORCE_WEB);
}
///
/// Forces a update from file.
///
public void ForceReadFile()
{
this.LoadData(ForceType.FORCE_FILE);
}
///
/// Load the data if necessary, from web or from file, regarding if
/// the file data is up to date.
///
/// if set/not invalid/not default, force to load from web or file
public void LoadData(ForceType force = ForceType.INVALID)
{
this.RunOnIOCallback(this.OnLoading);
// check which source is used for loading the data
if (force == ForceType.INVALID)
{
// if the model is not up to date
if (this.CheckIsNotUpToDate(this.IsModelUpToDateOnLoad) == true)
{
force = ForceType.FORCE_FILE;
if (this.file != null)
{
// if the file does not exist or is size of 0 or is not
// up to date, then load from web
if ((this.file.Exist() == false)
|| (this.CheckLoadFileIsNotUpToDate() == true))
{
force = ForceType.FORCE_WEB;
}
}
else
{
// if the file object does not exist, load from web
force = ForceType.FORCE_WEB;
}
// if the web object does not exist, load from file
if (this.api == null)
{
force = ForceType.FORCE_FILE;
}
}
else
{
// if it is up to date, nothing has to be loaded
this.RunOnIOCallback(this.OnLoaded);
}
}
// load from web
if (force == ForceType.FORCE_WEB)
{
if (this.api != null)
{
if (this.paramizedUri != null)
{
this.SendHttpGet(this.paramizedUri);
}
else
{
this.SendHttpGet(this.httpApiUri);
}
}
else
{
// if web object does not exist, call OnFailed callbacks
this.RunOnFailedCallback(this.OnFailedWeb, this.OnFailedLoad);
}
}
// load from file
if (force == ForceType.FORCE_FILE)
{
if (this.file != null)
{
byte[] data = this.file.ReadFile();
if (data == null)
{
this.RunOnFailedCallback(this.OnFailedFile, this.OnFailedLoad);
}
else
{
if (data.Length > 0)
{
this.DeserializeModel(data);
}
this.RunOnIOCallback(this.OnLoaded);
}
}
else
{
// if file object does not exist, call OnFailed callbacks
this.RunOnFailedCallback(this.OnFailedFile, this.OnFailedLoad);
}
}
}
///
/// Save the model data if necessary.
///
/// force saving. DEFAULT: false
public void SaveData(bool force = false)
{
if ((this.file != null)
&& ((this.CheckSaveFileIsNotUpToDate() == true) || (force == true)))
{
this.RunOnIOCallback(this.OnSaving);
byte[] data = this.SerializeModel();
if ((this.OnSaved != null) && (this.OnFailedSave != null))
{
this.file.WriteFile(data, delegate { this.OnSaved(); }, delegate { this.OnFailedSave(); });
}
else if (this.OnSaved != null)
{
this.file.WriteFile(data, delegate { this.OnSaved(); }, null);
}
else if (this.OnFailedSave != null)
{
this.file.WriteFile(data, null, delegate { this.OnFailedSave(); });
}
else
{
this.file.WriteFile(data, null, null);
}
}
}
///
/// Return the model io type.
///
/// model io type
public ModelType GetModelType()
{
return this.modelType;
}
///
/// Create the parameterized uri.
///
/// uri parameter list
public void SetUriParams(List parameters)
{
if (this.api != null)
{
this.paramizedUri = this.api.CreateGetUrl(parameters);
}
}
///
/// Clear the parameterized uri.
///
public void ClearUriParams()
{
this.paramizedUri = null;
}
#endregion
#region protected
///
/// Abstract declaration of the model deserialize function.
///
/// model data as byte array
/// true, is succeeded
protected abstract bool DeserializeModel(byte[] modelData);
///
/// Abstract declaration of the model serialize function.
///
/// model data as byte array
protected abstract byte[] SerializeModel();
///
/// Method send a HttpGet
///
/// the url
protected abstract void SendHttpGet(Uri url);
///
/// Method check if model or file is Not up-to-date
///
/// the check function
/// true if it is not up-to-date, otherwise false
protected abstract bool CheckIsNotUpToDate(object checkFunc);
///
/// Method check if file is Not up-to-date for load process
///
/// true if it is not up-to-date, otherwise false
protected abstract bool CheckLoadFileIsNotUpToDate();
///
/// Method check if file is Not up-to-date for load process
///
/// true if it is not up-to-date, otherwise false
protected abstract bool CheckSaveFileIsNotUpToDate();
///
/// Initializes the file object.
///
protected abstract void InitFile();
///
/// Initializes the web object.
///
protected abstract void InitHttpApi();
///
/// Check if the model io type is file.
///
/// true, if the model io type has file.
protected bool IsFile()
{
bool retValue = false;
if ((this.modelType & ModelType.File) != 0)
{
retValue = true;
}
return retValue;
}
///
/// Check if the model io type is feed.
///
/// true if the model io type has feed.
protected bool IsHttpApi()
{
bool retValue = false;
if ((this.modelType & ModelType.Feed) != 0)
{
retValue = true;
}
return retValue;
}
#endregion
#region private
///
/// Initialize the class. Is called by the constructors.
///
/// model IO type
/// name of the data file
/// url of the feed data
private void Init(ModelType modelType, string fileName, string url)
{
this.modelType = modelType;
if ((url != null) && (url.Equals(string.Empty) == false))
{
this.httpApiUri = new Uri(url, UriKind.Absolute);
}
this.fileName = fileName;
if ((this.IsFile() == true)
&& (fileName.Equals(string.Empty) == false))
{
this.InitFile();
}
if ((this.IsHttpApi() == true)
&& (url.Equals(string.Empty) == false))
{
this.InitHttpApi();
}
}
///
/// Executes the on i/o callback operation.
///
/// The callback function.
private void RunOnIOCallback(OnIO callbackFunc)
{
if (callbackFunc != null)
{
callbackFunc();
}
}
/// Executes the on failed callback operation.
/// The special function.
/// The default function.
private void RunOnFailedCallback(OnFailed specialFunc, OnFailed defaultFunc)
{
if (specialFunc != null)
{
specialFunc();
}
else if (defaultFunc != null)
{
defaultFunc();
}
}
#endregion
#endregion
}
}