using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.IO.IsolatedStorage;
using System.Xml.Serialization;
using System.Security.Permissions;
namespace IndianHealthService.BMXNet.WinForm.Configuration
{
///
/// LocalPersistentStore is the core BMX implementation for the most common
/// local setting store patterns:
///
/// 1) In a special folder
/// 2) In any specified path
/// 3) In IsolatedStorage
///
/// Use the object factory static class methods to create the different storage
/// mechanisms.
///
public class LocalPersistentStore : PersistentStore
{
private bool _attemptAncestorKeysOnRead = false;
public bool AttemptAncestorKeysOnRead
{
get { return _attemptAncestorKeysOnRead; }
set { _attemptAncestorKeysOnRead = value; }
}
public static LocalPersistentStore CreateIn(Environment.SpecialFolder aSpecialFolder, String subDirectoryPath,bool tryParentKeysOnRead)
{
LocalPersistentStore answer = new LocalPersistentStore();
answer.SpecialFolder = aSpecialFolder;
answer.DirectoryPath = subDirectoryPath;
answer.AttemptAncestorKeysOnRead = tryParentKeysOnRead;
return answer;
}
public static LocalPersistentStore CreateIn(String aDirectoryPath, bool tryParentKeysOnRead)
{
LocalPersistentStore answer = new LocalPersistentStore();
answer.DirectoryPath = aDirectoryPath;
answer.AttemptAncestorKeysOnRead = tryParentKeysOnRead;
return answer;
}
protected static LocalPersistentStore CreateIn(IsolatedStorageScope aScope, bool tryParentKeysOnRead)
{
LocalPersistentStore answer = new LocalPersistentStore();
answer.IsolatedStorageScope = aScope;
answer.AttemptAncestorKeysOnRead = tryParentKeysOnRead;
return answer;
}
public static LocalPersistentStore CreateDefaultStorage(bool tryParentKeysOnRead)
{
return CreateIn(System.IO.IsolatedStorage.IsolatedStorageScope.User | System.IO.IsolatedStorage.IsolatedStorageScope.Assembly, tryParentKeysOnRead);
}
private Environment.SpecialFolder? _specialFolder = null;
public Environment.SpecialFolder? SpecialFolder
{
get { return _specialFolder; }
set { _specialFolder = value; }
}
private String _directoryPath = null;
public String DirectoryPath
{
get { return _directoryPath; }
set { _directoryPath = value; }
}
private IsolatedStorageScope? _isolatedStorageScope = null;
public IsolatedStorageScope? IsolatedStorageScope
{
get { return _isolatedStorageScope; }
set { _isolatedStorageScope = value; }
}
private T ReadFromFileSystem(String aDirectory, params string[] keys)
{
String path = Path.Combine(aDirectory, this.TranslateToValidFileName(keys));
T result = default(T);
using (Stream stream = File.OpenRead(path))
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
result=(T)serializer.Deserialize(stream);
}
return result;
}
private void WriteToFileSystem(String aDirectory, T anObject, params string[] keys)
{
String path = Path.Combine(aDirectory, this.TranslateToValidFileName(keys));
if (!Directory.Exists(aDirectory))
{
Directory.CreateDirectory(aDirectory);
}
using (Stream stream = File.Create(path))
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
serializer.Serialize(stream, anObject);
}
}
///
/// Remove on non-letters, digits, to _ and add Bmx_ to the front.
///
///
///
private string TranslateToValidFileName(params string[] keys)
{
StringBuilder builder = new StringBuilder();
builder.Append("bmx_");
foreach (String key in keys)
{
foreach (char each in key)
{
builder.Append((Char.IsLetterOrDigit(each)) ? each : '_');
}
builder.Append("_");
}
builder.Append("config.xml");
return builder.ToString();
}
///
/// Isolated storage is scoped on user/application isolated storage
///
///
///
private T ReadFromIsolatedStorage(params string[] keys)
{
T result = default(T);
String validFileName = this.TranslateToValidFileName(keys) + ".is";
using (IsolatedStorageFile storage = IsolatedStorageFile.GetStore(this.IsolatedStorageScope.Value,null, null))
{
using (Stream stream = new IsolatedStorageFileStream(validFileName, FileMode.Open, FileAccess.Read, storage))
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
result = (T)serializer.Deserialize(stream);
}
}
return result;
}
///
/// Isolated storage is scoped on user/application isolated storage
///
///
///
private void WriteToIsolatedStorage(T anObject, string[] keys)
{
String validFileName = this.TranslateToValidFileName(keys) + ".is";
using (IsolatedStorageFile storage = IsolatedStorageFile.GetStore(this.IsolatedStorageScope.Value, null,null))
{
using (Stream stream = new IsolatedStorageFileStream(validFileName, FileMode.Create, FileAccess.Write, storage))
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
serializer.Serialize(stream,anObject);
}
}
}
public T Read(params string[] keys)
{
String[] keysToUse = keys;
try
{
if (this.IsolatedStorageScope.HasValue)
{
return this.ReadFromIsolatedStorage(keysToUse);
}
else if (this.SpecialFolder.HasValue)
{
return this.ReadFromFileSystem(Path.Combine(Environment.GetFolderPath(this.SpecialFolder.Value),this.DirectoryPath), keysToUse);
}
else if (this.DirectoryPath != null)
{
return this.ReadFromFileSystem(this.DirectoryPath, keysToUse);
}
else
{
return default(T);
}
}
catch
{
if (this.AttemptAncestorKeysOnRead && keysToUse.Length>1) {
string[] newKeysToUse=new string[keysToUse.Length-1];
Array.Copy(keysToUse, newKeysToUse, keysToUse.Length - 1);
return this.Read(newKeysToUse);
}
return default(T);
}
}
public void Write(T anObject, params string[] keys)
{
if (this.IsolatedStorageScope.HasValue)
{
this.WriteToIsolatedStorage(anObject, keys);
}
else if (this.SpecialFolder.HasValue)
{
this.WriteToFileSystem(Path.Combine(Environment.GetFolderPath(this.SpecialFolder.Value),this.DirectoryPath), anObject, keys);
}
else if (this.DirectoryPath != null)
{
this.WriteToFileSystem(this.DirectoryPath, anObject, keys);
}
else
{
throw new Exception("Local persistent store not configured.");
}
}
}
}