diff --git a/CSharp/Libraries/UniversalEditor.Core/Association.cs b/CSharp/Libraries/UniversalEditor.Core/Association.cs
index f13d267c..c7b32839 100644
--- a/CSharp/Libraries/UniversalEditor.Core/Association.cs
+++ b/CSharp/Libraries/UniversalEditor.Core/Association.cs
@@ -32,6 +32,9 @@ namespace UniversalEditor
///
public class Association
{
+ ///
+ /// Defines a collection of s.
+ ///
public class AssociationCollection
: System.Collections.ObjectModel.Collection
{
@@ -40,24 +43,42 @@ namespace UniversalEditor
private static List _associations = new List();
-
+ ///
+ /// Registers the specified if it is not already registered.
+ ///
+ /// true if the is not already registered and has been added; false otherwise.
+ /// The to register.
public static bool Register(Association assoc)
{
if (_associations.Contains(assoc)) return false;
_associations.Add(assoc);
return true;
}
+ ///
+ /// Unregisters the specified if it has been registered.
+ ///
+ /// true if the given has been unregistered; false if the given has not been registered.
+ /// The to unregister.
public static bool Unregister(Association assoc)
{
if (!_associations.Contains(assoc)) return false;
_associations.Remove(assoc);
return true;
}
-
+ ///
+ /// Returns an array of all known s.
+ ///
+ /// The all associations.
public static Association[] GetAllAssociations()
{
return _associations.ToArray();
}
+ ///
+ /// Gets an array of s that match the given or .
+ ///
+ /// An array of s that match the given or .
+ /// The to compare.
+ /// The to compare.
public static Association[] FromObjectModelOrDataFormat(ObjectModelReference objectModel = null, DataFormatReference dataFormat = null)
{
Association[] _associations = Association.GetAllAssociations();
@@ -71,11 +92,18 @@ namespace UniversalEditor
}
return associations.ToArray();
}
+ ///
+ /// Gets an array of s that match the given or file name filters.
+ ///
+ /// An array of s that match the given or file name filters.
+ /// The to compare.
+ /// Not implemented.
public static Association[] FromAccessor(Accessor accessor = null, string fileNameFilter = null)
{
Association[] assocs = Association.GetAllAssociations();
List associations = new List();
+ // FIXME: the fileNameFilter parameter is not referenced in this method body
// stopwatch diagnostics determined a nested for loop is 0.0547024 ms faster than foreach
for (int i = 0; i < assocs.Length; i++)
{
@@ -120,6 +148,10 @@ namespace UniversalEditor
///
public DataFormatReference.DataFormatReferenceCollection DataFormats { get { return mvarDataFormats; } }
+ ///
+ /// Returns a that represents the current .
+ ///
+ /// A that represents the current .
public override string ToString()
{
StringBuilder sb = new StringBuilder();
@@ -149,6 +181,11 @@ namespace UniversalEditor
return sb.ToString();
}
+ ///
+ /// Returns an array of s that satisfy the given .
+ ///
+ /// An array of s that match the specified criteria.
+ /// The that define the criteria to match when searching for s.
public static Association[] FromCriteria(AssociationCriteria ac)
{
List associations = new List();
diff --git a/CSharp/Libraries/UniversalEditor.Core/DataFormat.cs b/CSharp/Libraries/UniversalEditor.Core/DataFormat.cs
index ab1c0d5c..4c0458d1 100644
--- a/CSharp/Libraries/UniversalEditor.Core/DataFormat.cs
+++ b/CSharp/Libraries/UniversalEditor.Core/DataFormat.cs
@@ -28,8 +28,14 @@ using UniversalEditor.IO;
namespace UniversalEditor
{
+ ///
+ /// The on-disk representation of data stored in an and accessed by an .
+ ///
public abstract class DataFormat : References
{
+ ///
+ /// Represents a collection of objects.
+ ///
public class DataFormatCollection
: System.Collections.ObjectModel.Collection
{
@@ -45,20 +51,34 @@ namespace UniversalEditor
get { return mvarReference; }
}
+ ///
+ /// Creates a for this and registers it for future use.
+ ///
+ /// The that provides metadata and other information about this .
public DataFormatReference MakeReference()
{
DataFormatReference dfr = MakeReferenceInternal();
DataFormatReference.Register(dfr);
return dfr;
}
+ ///
+ /// Creates a new . The returned is not cached. It is recommended that subclasses
+ /// override this method and cache their own personal instances of containing the appropriate metadata for their
+ /// subclassed implementations.
+ ///
+ /// The that provides metadata and other information about this .
protected virtual DataFormatReference MakeReferenceInternal()
{
DataFormatReference dfr = new DataFormatReference(GetType());
return dfr;
}
-
- private Accessor mvarAccessor = null;
- protected internal Accessor Accessor { get { return mvarAccessor; } set { mvarAccessor = value; } }
+
+ ///
+ /// The used to read and write data.
+ ///
+ /// The used to read and write data.
+ [Obsolete("In next version, Accessor will be a parameter passed into LoadInternal / SaveInternal methods")]
+ protected internal Accessor Accessor { get; set; } = null;
///
/// Continues loading the file into the specified with a different
@@ -68,10 +88,15 @@ namespace UniversalEditor
/// The used to parse the document.
protected void ContinueLoading(ref ObjectModel objectModel, DataFormat otherDataFormat)
{
- otherDataFormat.Accessor = mvarAccessor;
+ otherDataFormat.Accessor = Accessor;
otherDataFormat.Load(ref objectModel);
}
+ ///
+ /// Determines if the given is supported by this .
+ ///
+ /// true, if the specified is supported by this , false otherwise.
+ /// The whose support should be checked.
protected virtual bool IsObjectModelSupported(ObjectModel objectModel)
{
DataFormatReference dfr = MakeReferenceInternal();
@@ -79,6 +104,26 @@ namespace UniversalEditor
return dfr.Capabilities.Contains(omr.Type) || dfr.Capabilities.Contains(omr.ID);
}
+ ///
+ /// Reads the contents of the specified from the using this .
+ ///
+ ///
+ ///
+ /// Before the actual content is read using this 's method, a is
+ /// created and the specified is pushed onto the stack. The method is then called, with the
+ /// stack as its only parameter. A single is then popped off the stack, and the method is called
+ /// with this as its only parameter. After the actual content is read, the method is called,
+ /// again passing in the stack as its only parameter.
+ ///
+ ///
+ /// Note that the passed into the method may not necessarily be the same as the
+ /// that is eventually passed into the method. It is possible to subclass s to create new formats
+ /// based on existing ones. XML, ZIP, and RIFF are a few good examples of s that serve as the base for others. For more
+ /// information, refer to the documentation for the , , and
+ /// methods.
+ ///
+ ///
+ /// The whose content should be written using this .
[DebuggerNonUserCode()]
public void Load(ref ObjectModel objectModel)
{
@@ -99,9 +144,29 @@ namespace UniversalEditor
*/
AfterLoadInternal(stack);
}
+ ///
+ /// Writes the contents of the specified to the using this .
+ ///
+ ///
+ ///
+ /// Before the actual content is written using this 's method, a is
+ /// created and the specified is pushed onto the stack. The method is then called, with the
+ /// stack as its only parameter. A single is then popped off the stack, and the method is called
+ /// with this as its only parameter. After the actual content is written, the method is called,
+ /// again passing in the stack as its only parameter.
+ ///
+ ///
+ /// Note that the passed into the method may not necessarily be the same as the
+ /// that is eventually passed into the method. It is possible to subclass s to create new formats
+ /// based on existing ones. XML, ZIP, and RIFF are a few good examples of s that serve as the base for others. For more
+ /// information, refer to the documentation for the , , and
+ /// methods.
+ ///
+ ///
+ /// The whose content should be written using this .
public void Save(ObjectModel objectModel)
{
- if (objectModel == null) throw new ArgumentNullException("objectModel", "objectModel cannot be null");
+ if (objectModel == null) throw new ArgumentNullException(nameof(objectModel), "objectModel cannot be null");
Stack stack = new Stack();
stack.Push(objectModel);
@@ -114,18 +179,83 @@ namespace UniversalEditor
AfterSaveInternal(stack);
}
+ ///
+ /// Reads the data from the into the specified .
+ ///
+ /// The into which to load data.
protected abstract void LoadInternal(ref ObjectModel objectModel);
+ ///
+ /// Writes the contents of the specified to the .
+ ///
+ /// The from which to save data.
protected abstract void SaveInternal(ObjectModel objectModel);
+ ///
+ /// Method called BEFORE the method is called on the original 's subclass.
+ ///
+ ///
+ /// When inheriting from a
+ /// subclass (e.g. XMLDataFormat), you need to create a new instance of the appropriate that the
+ /// subclass expects, and push that onto the stack, i.e. objectModels.Push(new MarkupObjectModel()); This is
+ /// usually the only line of code in the overridden method's body.
+ ///
+ ///
+ /// objectModels.Push(new BaseObjectModel()); // this is all we need to do
+ ///
+ /// The stack of s used by this .
protected virtual void BeforeLoadInternal(Stack objectModels)
{
}
+ ///
+ /// Method called AFTER the method is called on the original 's subclass.
+ ///
+ ///
+ /// When inheriting from a subclass (e.g. XMLDataFormat), you need to first pop the that you pushed
+ /// onto the stack in your implementation, then pop the that
+ /// your class expects to get passed. Now you can read data from the original and modify the second .
+ /// Because these objects are passed by reference, you do not need to push them back onto the stack for them to get properly loaded.
+ ///
+ ///
+ /// BaseObjectModel bom = (objectModels.Pop() as BaseObjectModel); // base object model comes first
+ /// MyVerySpecificObjectModel myOM = (objectModels.Pop() as MyVerySpecificObjectModel);
+ ///
+ /// // populate MyVerySpecificObjectModel... and we're done. nothing else needs to be pushed back onto the stack.
+ ///
+ /// The stack of s used by this .
protected virtual void AfterLoadInternal(Stack objectModels)
{
}
+ ///
+ /// Method called BEFORE the method is called on the original 's subclass.
+ ///
+ ///
+ /// When inheriting from a subclass (e.g. XMLDataFormat), you need to first pop the that your class
+ /// expects to get passed, then create a new instance of the proper type of the base class is expecting. Now you can retrieve
+ /// data from the that your class expects and properly format it for the the base class expects.
+ /// When you're done, you need to push the newly-created onto the stack so that the underlying
+ /// method will be able to see it.
+ ///
+ ///
+ /// MyVerySpecificObjectModel myOM = (objectModels.Pop() as MyVerySpecificObjectModel);
+ /// BaseObjectModel bom = new BaseObjectModel();
+ ///
+ /// // populate BaseObjectModel...
+ ///
+ /// objectModels.Push(bom); // aaand we're done
+ ///
+ /// The stack of s used by this .
protected virtual void BeforeSaveInternal(Stack objectModels)
{
}
+ ///
+ /// Method called AFTER the method is called on the original 's subclass.
+ ///
+ ///
+ /// Although this method does get called after the method is called, there does not seem to be any reason to actually use it.
+ /// The standard practice of inheriting s utilizes the , , and
+ /// methods.
+ ///
+ /// The stack of s used by this .
protected virtual void AfterSaveInternal(Stack objectModels)
{
}
diff --git a/CSharp/Libraries/UniversalEditor.Core/ObjectModel.cs b/CSharp/Libraries/UniversalEditor.Core/ObjectModel.cs
index 0f9671ee..4bd4fcd3 100644
--- a/CSharp/Libraries/UniversalEditor.Core/ObjectModel.cs
+++ b/CSharp/Libraries/UniversalEditor.Core/ObjectModel.cs
@@ -25,45 +25,95 @@ using System.Text;
namespace UniversalEditor
{
+ ///
+ /// The in-memory representation of data serialized to and from an using a particular .
+ ///
public abstract class ObjectModel : ICloneable, References
{
+ ///
+ /// Represents a collection of objects.
+ ///
public class ObjectModelCollection
: System.Collections.ObjectModel.Collection
{
}
+ ///
+ /// Creates a for this and registers it for future use.
+ ///
+ /// The that provides metadata and other information about this .
public ObjectModelReference MakeReference()
{
ObjectModelReference omr = MakeReferenceInternal();
ObjectModelReference.Register(omr);
return omr;
}
+ ///
+ /// Creates a new . The returned is not cached. It is recommended that subclasses
+ /// override this method and cache their own personal instances of containing the appropriate metadata for their
+ /// subclassed implementations.
+ ///
+ /// The that provides metadata and other information about this .
protected virtual ObjectModelReference MakeReferenceInternal()
{
ObjectModelReference omr = new ObjectModelReference(GetType());
return omr;
}
- private Accessor mvarAccessor = null;
- public Accessor Accessor { get { return mvarAccessor; } internal set { mvarAccessor = value; } }
+ ///
+ /// The that was last used to read or write this .
+ ///
+ /// The accessor.
+ [Obsolete("ObjectModels should be Accessor-agnostic and not rely on being able to communicate with the Accessor")]
+ public Accessor Accessor { get; internal set; }
+ ///
+ /// Clears all data from this and returns it to a pristine state.
+ ///
public abstract void Clear();
+ ///
+ /// Copies all data from this to the specified .
+ ///
+ /// The into which to copy the data of this .
+ /// The conversion between this and the given is not supported.
public abstract void CopyTo(ObjectModel where);
+ ///
+ /// Copies all data from this to the specified .
+ ///
+ /// The into which to copy the data of this .
+ /// When false, the method is called on the destination before the copy is performed.
+ /// The conversion between this and the given is not supported.
public void CopyTo(ObjectModel where, bool append)
{
if (!append) where.Clear();
CopyTo(where);
}
+ ///
+ /// Copies all data from the given into this .
+ ///
+ /// The from which to copy the data.
+ /// The conversion between this and the given is not supported.
public void CopyFrom(ObjectModel where)
{
where.CopyTo(this);
}
+ ///
+ /// Copies all data from the given into this .
+ ///
+ /// The from which to copy the data.
+ /// When false, the method is called on this before the copy is performed.
+ /// The conversion between this and the given is not supported.
public void CopyFrom(ObjectModel where, bool append)
{
if (!append) Clear();
CopyFrom(where);
}
+ ///
+ /// Creates a clone of this and returns it. This is normally implemented as creating a new instance of this
+ /// , then calling the original instance's method passing in the new instance as the target.
+ ///
+ /// The cloned .
public object Clone()
{
Type type = this.GetType();
@@ -72,6 +122,12 @@ namespace UniversalEditor
return clone;
}
+ ///
+ /// Performs a simple find and replace on the public properties of this using reflection. For a more in-depth find and replace
+ /// solution, individual authors should annotate individual parameters that should participate in the find-and-replace feature.
+ ///
+ /// The string to search for.
+ /// The string with which the found string should be replaced.
public virtual void Replace(string FindWhat, string ReplaceWith)
{
Type type = GetType();
@@ -88,6 +144,17 @@ namespace UniversalEditor
}
private Dictionary> _customProperties = new Dictionary>();
+
+ // TODO: should this use the MBS.Framework "ISupportsExtraData" interface? Or is this specifically UE functionality (with DataFormatReference)?
+ ///
+ /// Gets the value of the custom property with the specified name for the given . If no custom property with the given
+ /// name is registered for the specified , return the value specified as .
+ ///
+ /// The value of the custom property with the specified name for the given .
+ /// The for which to look up custom properties.
+ /// The name of the custom property to search for.
+ /// The value that should be returned if no custom property with the given name is registered for the specified .
+ /// The type of custom property that should be returned.
public T GetCustomProperty(DataFormatReference dfr, string name, T defaultValue = default(T))
{
if (_customProperties.ContainsKey(dfr))
@@ -99,10 +166,26 @@ namespace UniversalEditor
}
return defaultValue;
}
+ ///
+ /// Gets the value of the custom property with the specified name for the given . If no custom property with the given
+ /// name is registered for the specified , return the value specified as .
+ ///
+ /// The value of the custom property with the specified name for the given .
+ /// The for which to look up custom properties.
+ /// The name of the custom property to search for.
+ /// The value that should be returned if no custom property with the given name is registered for the specified .
public object GetCustomProperty(DataFormatReference dfr, string name, object defaultValue = null)
{
return GetCustomProperty