- goalbook.zip
- GoalBook
- Dependencies
- CAG WPF 2
- Microsoft.Practices.Composite.dll
- Microsoft.Practices.Composite.Presentation.dll
- Microsoft.Practices.Composite.UnityExtensions.dll
- Microsoft.Practices.ObjectBuilder2.dll
- Microsoft.Practices.ServiceLocation.dll
- Microsoft.Practices.Unity.dll
- vssver2.scc
- CSLA
- Csla.dll
- Csla.XmlSerializers.dll
- vssver2.scc
- Infragistics
- Infragistics3.Wpf.DataPresenter.v9.1.Express.dll
- Infragistics3.Wpf.Editors.v9.1.Express.dll
- Infragistics3.Wpf.v9.1.Express.dll
- vssver2.scc
- WPFToolkit
- vssver2.scc
- WPFToolkit.dll
- GoalBook.Controls
- GoalBook.Goals
- GoalBook.Infrastructure
- GoalBook.Notes
- GoalBook.Public
- GoalBook.Shell
- App.ico
- App.xaml
- App.xaml.cs
- Bootstrapper.cs
- Commands
- GoalBook.Shell.csproj
- GoalBook.Shell.csproj.user
- Journal.ico
- Journal48.ico
- Misc
- Modules
- Properties
- Resources
- arrow_refresh.png
- arrow_undo.png
- checked.gif
- cross.png
- disk.png
- email.png
- erase.png
- error.png
- exclamation.png
- flag_red.png
- group.png
- help.png
- information.png
- magnifier.png
- page_red.png
- pencil.png
- printer.png
- user.png
- vssver2.scc
- Wave.jpg
- world.png
- world_link.png
- Services
- Splash.png
- Views
- vssver2.scc
- Windows
- GoalBook.sln
- GoalBook.snk
- GoalBook.Synchronisation
- GoalBook.Tasks
- License.txt
- ReadMe.txt
- SolutionInfo.cs
- vssver2.scc
|
//===============================================================================
// Goal Book.
// Copyright � 2009 Mark Brownsword.
//===============================================================================
#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Csla;
using GoalBook.Infrastructure.Interfaces;
#endregion
namespace GoalBook.Infrastructure.ObjectModel
{
[Serializable]
public sealed class GoalList : BusinessListBase<GoalList, Goal>, IXDocSerializable
{
#region Constants and Enums
private const string SERIALIZATION_ROOT = "GoalList";
private const string SERIALIZATION_GOALS = "Goals";
private const string SERIALIZATION_DELETED_GOALS = "DeletedGoals";
private const string SERIALIZATION_LAST_SERVER_GOAL_EDIT = "LastServerGoalEdit";
#endregion
#region Inner Classes and Structures
#endregion
#region Delegates and Events
#endregion
#region Instance and Shared Fields
private List<Goal> _deleted;
private DateTime _lastServerGoalEdit;
private bool _lastServerGoalEditChanged = false;
#endregion
#region Constructors
/// <summary>
/// Constructor.
/// </summary>
public GoalList()
{
AllowEdit =
AllowNew =
AllowRemove = true;
}
#endregion
#region Properties
/// <summary>
/// Expose the EditLevel so can call ApplyEdit the
/// correct number of times.
/// </summary>
public new int EditLevel { get { return base.EditLevel; } }
/// <summary>
/// Reference to LastServerGoalEdit. A timestamp that indicates
/// the last time an edit occurred on the server.
/// </summary>
public DateTime LastServerGoalEdit
{
get { return _lastServerGoalEdit;}
set { _lastServerGoalEdit = value; _lastServerGoalEditChanged = true; }
}
/// <summary>
/// Reference to SyncRequired. A flag indicating if any
/// goals have been edited and require synchronisation.
/// </summary>
public bool SyncRequired
{
get
{
foreach (Goal goal in this)
{
if (goal.SyncRequired) { return true; }
}
foreach (Goal goal in this.DeletedList)
{
if (goal.ExternalIdentifier > 0) { return true; }
}
if (this.DeletedPendingSync.Count > 0) { return true; }
return false;
}
}
/// <summary>
/// Deleted goals. For synchronisation.
/// </summary>
public List<Goal> DeletedPendingSync
{
get
{
if (_deleted == null) { DeletedPendingSync = new List<Goal>(); }
return _deleted;
}
set { _deleted = value; }
}
#endregion
#region Private and Protected Methods
/// <summary>
/// Get Goal FromElement.
/// </summary>
private Goal GetGoalFromElement(XElement element)
{
Guid goalID = new Guid(GetGoalAttributeFromElement(element, Constants.GoalSerializationContants.SERIALIZATION_GOALID));
int levelID = int.Parse(GetGoalAttributeFromElement(element, Constants.GoalSerializationContants.SERIALIZATION_LEVELID));
Guid contributesID = new Guid(GetGoalAttributeFromElement(element, Constants.GoalSerializationContants.SERIALIZATION_CONTRIBUTESID));
bool archived = bool.Parse(GetGoalAttributeFromElement(element, Constants.GoalSerializationContants.SERIALIZATION_ARCHIVED));
string title = GetGoalAttributeFromElement(element, Constants.GoalSerializationContants.SERIALIZATION_TITLE);
int externalIdentifier = int.Parse(GetGoalAttributeFromElement(element, Constants.GoalSerializationContants.SERIALIZATION_EXTERNALIDENTIFIER));
Goal goal = new Goal(goalID, levelID, contributesID, archived, title, externalIdentifier);
goal.LastModified = DateTime.Parse(GetGoalAttributeFromElement(element, Constants.GoalSerializationContants.SERIALIZATION_LASTMODIFIED));
goal.SyncRequired = bool.Parse(GetGoalAttributeFromElement(element, Constants.GoalSerializationContants.SERIALIZATION_SYNCREQUIRED));
return goal;
}
/// <summary>
/// Get Goal with the specified id.
/// </summary>
private Goal GetGoal(GoalList goalList, Guid id)
{
var targetList = from g in goalList where g.GoalID == id select g;
foreach (Goal goal in targetList)
{
return goal; //One only can exist.
}
return null;
}
/// <summary>
/// Get Goal Attribute From Element.
/// </summary>
private string GetGoalAttributeFromElement(XElement element, string attribute)
{
if (element.Attribute(attribute) == null) { return null; }
return element.Attribute(attribute).Value;
}
#endregion
#region Public and internal Methods
#region IXDocSerializable Members
/// <summary>
/// Get Goals List as XDocument.
/// </summary>
public XDocument GetXDocument()
{
//Serialize the GoalsList Element.
XElement goalsElement = new XElement(SERIALIZATION_GOALS, new XAttribute(SERIALIZATION_LAST_SERVER_GOAL_EDIT,
LastServerGoalEdit.ToString()));
//Serialize the Goals.
foreach (Goal goal in this)
{
goalsElement.Add(goal.SerializeAsXElement());
}
XElement deletedPendingSyncElement = new XElement(SERIALIZATION_DELETED_GOALS);
//Serialize the deleted Goals.
foreach (Goal goal in this.DeletedPendingSync)
{
deletedPendingSyncElement.Add(goal.SerializeAsXElement());
}
XElement rootElement = new XElement(SERIALIZATION_ROOT, goalsElement, deletedPendingSyncElement);
return new XDocument(rootElement);
}
/// <summary>
/// Create GoalsList From XDocument.
/// </summary>
public void CreateFromXDocument(XDocument xDoc)
{
if (xDoc == null) return;
XElement root = xDoc.Element(SERIALIZATION_ROOT);
XElement goals = root.Element(SERIALIZATION_GOALS);
XElement deletedGoals = root.Element(SERIALIZATION_DELETED_GOALS);
//LastServerGoalEdit
if (!string.IsNullOrEmpty(GetGoalAttributeFromElement(goals, SERIALIZATION_LAST_SERVER_GOAL_EDIT)))
{
this._lastServerGoalEdit = Convert.ToDateTime(GetGoalAttributeFromElement(goals, SERIALIZATION_LAST_SERVER_GOAL_EDIT));
}
//Load the Goals.
foreach (XElement element in goals.Descendants(Constants.GoalSerializationContants.SERIALIZATION_GOAL))
{
this.Add(GetGoalFromElement(element));
}
//Load the deletedPendingSync Goals.
this.DeletedPendingSync.Clear();
foreach (XElement element in deletedGoals.Descendants(Constants.GoalSerializationContants.SERIALIZATION_GOAL))
{
this.DeletedPendingSync.Add(GetGoalFromElement(element));
}
}
/// <summary>
/// MarkListOld. Mark all list items as old.
/// </summary>
public void MarkListOld()
{
//Wind back the EditLevel.
while (this.EditLevel > 0) { this.ApplyEdit(); }
//Mark each child as old (clean).
foreach (Goal goal in this) { goal.MarkGoalOld(); }
//Move the Deleted items with an ExternalIdentifier to the Deleted list. The DeletedList
//holds goals that have been deleted on the client but have not yet been synchronised.
var deleted = from g in DeletedList where g.ExternalIdentifier > 0 select g;
foreach (Goal goal in deleted)
{
if (DeletedPendingSync.Contains(goal)) { continue; }
DeletedPendingSync.Add(goal);
}
//The list remains dirty until the DeletedList is clear, so clear it now.
DeletedList.Clear();
//Set to true after sync, so set false during save.
_lastServerGoalEditChanged = false;
}
#endregion
/// <summary>
/// Validate RefIntegrity.
/// </summary>
public bool ValidateRefIntegrity(Goal goal)
{
//Find old self
Goal self = null;
foreach (Goal checkGoal in this)
{
if (checkGoal.GoalID == goal.GoalID)
{
self = checkGoal; break;
}
}
if (self == null)
{
//Goal has been deleted. Remove all references.
foreach (Goal checkGoal in this)
{
if (checkGoal.ContributesID == goal.GoalID)
{
this.BeginEdit();
checkGoal.ContributesID = Guid.Empty;
}
}
}
else
{
if (goal.LevelID == 0)
{
//Lifelong goals can't contribute
goal.ContributesID = Guid.Empty;
}
//Compare new and old self. Goal has moved up e.g. short (2) --> long (1)
if (goal.LevelID < self.LevelID)
{
//Get Contributes Goal.
Goal contributesGoal = GetGoal(this, goal.ContributesID);
if (contributesGoal != null && contributesGoal.LevelID == goal.LevelID)
{
//Contributes Goal is at same level, so set empty.
goal.ContributesID = Guid.Empty;
}
}
//Compare new and old self. Goal has moved down e.g. long (1) --> short (2)
if (goal.LevelID > self.LevelID)
{
//Locate all goals at new level that have this GoalId
//as ContributesID and set to null
foreach (Goal checkGoal in this)
{
if (checkGoal.LevelID <= goal.LevelID && checkGoal.ContributesID == goal.GoalID)
{
this.BeginEdit();
checkGoal.ContributesID = Guid.Empty;
}
}
}
}
return true;
}
/// <summary>
/// Merge goals. Synchronisation occurs in a cloned GoalList,
/// so need to merge changes back into the primary GoalList.
/// </summary>
public void Merge(GoalList syncGoals)
{
foreach (Goal goal in syncGoals)
{
Goal target = GetGoal(this, goal.GoalID);
if (target == null)
{
//Add
this.BeginEdit();
this.Add(goal);
this.EndNew(this.IndexOf(goal));
}
else
{
//Edit
if (goal.IsDirty) //Dirty means changes occured during sync.
{
this.BeginEdit();
target.MapFields(goal);
}
//Set SyncRequired flag (so client edits only get pushed to server once).
target.SyncRequired = goal.SyncRequired;
}
}
foreach (Goal goal in syncGoals.DeletedList)
{
//Remove
Goal target = GetGoal(this, goal.GoalID);
if (target != null)
{
this.Remove(target);
}
}
//Clear Deleted. Sync of Deleted items is complete.
if (this.DeletedList.Count > 0) { this.DeletedList.Clear(); }
this.DeletedPendingSync.Clear();
foreach (Goal goal in syncGoals.DeletedPendingSync)
{
//Goals remaining in syncGoals.DeletedPendingSync were not
//successfully deleted during the client changes synchronisation.
//These need to be retained so can attempt delete again.
this.DeletedPendingSync.Add(goal);
}
//Map LastServerGoalEdit.
if (syncGoals.LastServerGoalEdit > this.LastServerGoalEdit)
{
this.LastServerGoalEdit = syncGoals.LastServerGoalEdit;
}
}
#endregion
#region Event Handlers
#endregion
#region Base Class Overrides
/// <summary>
/// AddNewCore. Initialises and adds a new Goal item to the List.
/// </summary>
protected override object AddNewCore()
{
Guid guid = Guid.NewGuid();
Goal goal = new Goal(guid);
Add(goal);
return goal;
}
/// <summary>
/// IsSavable.
/// </summary>
public override bool IsSavable
{
get
{
if (_lastServerGoalEditChanged)
{
return base.IsValid;
}
return base.IsSavable;
}
}
#endregion
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
I've been working as a software developer since 2000 and hold a Bachelor of Business degree from The Open Polytechnic of New Zealand. Computers are for people and I aim to build applications for people that they would want to use.