Established specialized CoreObject object model instead of shoehorning PropertyList

This commit is contained in:
Michael Becker 2015-05-19 08:04:22 -04:00
parent 5db6f35074
commit cc620541b9
8 changed files with 580 additions and 159 deletions

View File

@ -0,0 +1,168 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UniversalEditor.IO;
using UniversalEditor.ObjectModels.CoreObject;
namespace UniversalEditor.DataFormats.CoreObject
{
public class CoreObjectDataFormat : DataFormat
{
private static DataFormatReference _dfr = null;
protected override DataFormatReference MakeReferenceInternal()
{
if (_dfr == null)
{
_dfr = base.MakeReferenceInternal();
_dfr.Capabilities.Add(typeof(CoreObjectObjectModel), DataFormatCapabilities.All);
}
return _dfr;
}
protected override void LoadInternal(ref ObjectModel objectModel)
{
CoreObjectObjectModel core = (objectModel as CoreObjectObjectModel);
if (core == null) throw new ObjectModelNotSupportedException();
Reader reader = base.Accessor.Reader;
CoreObjectGroup currentGroup = null;
string lastPropertyKey = null;
string lastPropertyValue = null;
while (!reader.EndOfStream)
{
string line = reader.ReadLine();
if (line.StartsWith(" "))
{
if (lastPropertyValue == null)
{
throw new InvalidDataFormatException("Cannot continue a property that hasn't been declared");
}
line = line.Substring(1);
line = line.Replace("\\,", ",");
lastPropertyValue += line;
continue;
}
else
{
if (lastPropertyValue != null)
{
string[] lastPropertyValues = lastPropertyValue.Split(new char[] { ';' });
if (currentGroup != null)
{
currentGroup.Properties.Add(lastPropertyKey, lastPropertyValues);
}
else
{
core.Properties.Add(lastPropertyKey, lastPropertyValues);
}
}
}
// line = line.Trim();
if (String.IsNullOrEmpty(line)) continue;
string[] parts = line.Split(new char[] { ':' }, 2, StringSplitOptions.None);
string key = parts[0];
string value = parts[1];
value = value.Replace("\\,", ",");
if (key.ToUpper() == "BEGIN")
{
if (currentGroup != null)
{
currentGroup = currentGroup.Groups.Add(value);
}
else
{
currentGroup = core.Groups.Add(value);
}
}
else if (key.ToUpper() == "END")
{
if (currentGroup != null)
{
if (currentGroup.Name != value)
{
throw new InvalidDataFormatException("Cannot close a group that has not been opened yet ('" + value + "')");
}
else
{
currentGroup = currentGroup.ParentGroup;
}
}
else
{
throw new InvalidDataFormatException("Cannot close a group that has not been opened yet ('" + value + "')");
}
}
else
{
lastPropertyKey = key;
lastPropertyValue = value;
}
}
}
protected override void SaveInternal(ObjectModel objectModel)
{
CoreObjectObjectModel plom = (objectModel as CoreObjectObjectModel);
if (plom == null) throw new ObjectModelNotSupportedException();
Writer writer = base.Accessor.Writer;
foreach (CoreObjectProperty property in plom.Properties)
{
WriteProperty(writer, property);
}
foreach (CoreObjectGroup group in plom.Groups)
{
WriteGroup(writer, group);
}
writer.Flush();
}
private void WriteGroup(Writer writer, CoreObjectGroup group, int indent = 0)
{
writer.WriteLine("BEGIN:" + group.Name);
foreach (CoreObjectProperty property in group.Properties)
{
WriteProperty(writer, property, indent + 1);
}
foreach (CoreObjectGroup group1 in group.Groups)
{
WriteGroup(writer, group1);
}
writer.WriteLine("END:" + group.Name);
}
private void WriteProperty(Writer writer, CoreObjectProperty property, int indent = 0)
{
writer.Write(property.Name);
foreach (CoreObjectAttribute att in property.Attributes)
{
writer.Write(';');
writer.Write(att.Name);
if (att.Values.Count > 0)
{
writer.Write('=');
for (int i = 0; i < att.Values.Count; i++)
{
writer.Write(att.Values[i]);
if (i < att.Values.Count - 1) writer.Write(',');
}
}
}
writer.Write(':');
for (int i = 0; i < property.Values.Count; i++)
{
writer.Write(property.Values[i]);
if (i < property.Values.Count - 1) writer.Write(';');
}
writer.WriteLine();
}
}
}

View File

@ -1,136 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UniversalEditor.IO;
using UniversalEditor.ObjectModels.PropertyList;
namespace UniversalEditor.DataFormats.PropertyList.CoreObject
{
public class CoreObjectDataFormat : DataFormat
{
private static DataFormatReference _dfr = null;
protected override DataFormatReference MakeReferenceInternal()
{
if (_dfr == null)
{
_dfr = base.MakeReferenceInternal();
_dfr.Capabilities.Add(typeof(PropertyListObjectModel), DataFormatCapabilities.All);
}
return _dfr;
}
protected override void LoadInternal(ref ObjectModel objectModel)
{
PropertyListObjectModel plom = (objectModel as PropertyListObjectModel);
if (plom == null) throw new ObjectModelNotSupportedException();
Reader reader = base.Accessor.Reader;
Group currentGroup = null;
Property lastProperty = null;
while (!reader.EndOfStream)
{
string line = reader.ReadLine();
if (line.StartsWith(" "))
{
if (lastProperty == null)
{
throw new InvalidDataFormatException("Cannot continue a property that hasn't been declared");
}
line = line.Substring(1);
line = line.Replace("\\,", ",");
lastProperty.Value += line;
continue;
}
// line = line.Trim();
if (String.IsNullOrEmpty(line)) continue;
string[] parts = line.Split(new char[] { ':' }, 2, StringSplitOptions.None);
string key = parts[0];
string value = parts[1];
value = value.Replace("\\,", ",");
if (key.ToUpper() == "BEGIN")
{
if (currentGroup != null)
{
currentGroup = currentGroup.Groups.Add(value);
}
else
{
currentGroup = plom.Groups.Add(value);
}
}
else if (key.ToUpper() == "END")
{
if (currentGroup != null)
{
if (currentGroup.Name != value)
{
throw new InvalidDataFormatException("Cannot close a group that has not been opened yet ('" + value + "')");
}
else
{
currentGroup = currentGroup.Parent;
}
}
else
{
throw new InvalidDataFormatException("Cannot close a group that has not been opened yet ('" + value + "')");
}
}
else
{
if (currentGroup != null)
{
lastProperty = currentGroup.Properties.Add(key, value);
}
else
{
lastProperty = plom.Properties.Add(key, value);
}
}
}
}
protected override void SaveInternal(ObjectModel objectModel)
{
PropertyListObjectModel plom = (objectModel as PropertyListObjectModel);
if (plom == null) throw new ObjectModelNotSupportedException();
Writer writer = base.Accessor.Writer;
foreach (Property property in plom.Properties)
{
WriteProperty(writer, property);
}
foreach (Group group in plom.Groups)
{
WriteGroup(writer, group);
}
writer.Flush();
}
private void WriteGroup(Writer writer, Group group, int indent = 0)
{
writer.WriteLine("BEGIN:" + group.Name);
foreach (Property property in group.Properties)
{
WriteProperty(writer, property, indent + 1);
}
foreach (Group group1 in group.Groups)
{
WriteGroup(writer, group1);
}
writer.WriteLine("END:" + group.Name);
}
private void WriteProperty(Writer writer, Property property, int indent = 0)
{
writer.WriteLine(property.Name + ":" + property.Value.ToString());
}
}
}

View File

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.ObjectModels.CoreObject
{
public class CoreObjectAttribute : ICloneable
{
public class CoreObjectAttributeCollection
: System.Collections.ObjectModel.Collection<CoreObjectAttribute>
{
public CoreObjectAttribute Add(string name, string value = null)
{
CoreObjectAttribute item = new CoreObjectAttribute(name, value);
Add(item);
return item;
}
}
public CoreObjectAttribute()
{
mvarName = String.Empty;
}
public CoreObjectAttribute(string name, params string[] values)
{
mvarName = name;
foreach (string value in values)
{
mvarValues.Add(value);
}
}
private string mvarName = String.Empty;
public string Name { get { return mvarName; } set { mvarName = value; } }
private System.Collections.Specialized.StringCollection mvarValues = new System.Collections.Specialized.StringCollection();
public System.Collections.Specialized.StringCollection Values { get { return mvarValues; } }
public object Clone()
{
CoreObjectAttribute clone = new CoreObjectAttribute();
clone.Name = (mvarName.Clone() as string);
foreach (string value in mvarValues)
{
clone.Values.Add(value.Clone() as string);
}
return clone;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append(mvarName);
if (mvarValues.Count > 0)
{
sb.Append("=");
for (int i = 0; i < mvarValues.Count; i++)
{
sb.Append(mvarValues[i]);
if (i < mvarValues.Count - 1) sb.Append(",");
}
}
return sb.ToString();
}
}
}

View File

@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.ObjectModels.CoreObject
{
public class CoreObjectGroup : ICloneable
{
public class CoreObjectGroupCollection
: System.Collections.ObjectModel.Collection<CoreObjectGroup>
{
private CoreObjectGroup _parent = null;
public CoreObjectGroupCollection(CoreObjectGroup parent = null)
{
_parent = parent;
}
public CoreObjectGroup Add(string name)
{
CoreObjectGroup item = new CoreObjectGroup();
item.Name = name;
Add(item);
return item;
}
private Dictionary<string, CoreObjectGroup> _itemsByName = new Dictionary<string, CoreObjectGroup>();
public CoreObjectGroup this[string name]
{
get
{
if (_itemsByName.ContainsKey(name)) return _itemsByName[name];
return null;
}
}
protected override void InsertItem(int index, CoreObjectGroup item)
{
base.InsertItem(index, item);
item.ParentGroup = _parent;
_itemsByName.Add(item.Name, item);
}
protected override void RemoveItem(int index)
{
this[index].ParentGroup = null;
_itemsByName.Remove(this[index].Name);
base.RemoveItem(index);
}
protected override void SetItem(int index, CoreObjectGroup item)
{
if (index > -1 && index < this.Count - 1)
{
this[index].ParentGroup = null;
_itemsByName.Remove(this[index].Name);
}
base.SetItem(index, item);
_itemsByName.Add(item.Name, item);
item.ParentGroup = _parent;
}
protected override void ClearItems()
{
foreach (CoreObjectGroup item in this)
{
item.ParentGroup = null;
}
_itemsByName.Clear();
base.ClearItems();
}
}
public CoreObjectGroup()
{
mvarGroups = new CoreObjectGroupCollection(this);
mvarProperties = new CoreObjectProperty.CoreObjectPropertyCollection(this);
}
private CoreObjectGroup mvarParentGroup = null;
public CoreObjectGroup ParentGroup
{
get { return mvarParentGroup; }
internal set
{
mvarParentGroup = value;
}
}
private string mvarName = String.Empty;
public string Name { get { return mvarName; } set { mvarName = value; } }
private CoreObjectGroup.CoreObjectGroupCollection mvarGroups = null;
public CoreObjectGroup.CoreObjectGroupCollection Groups { get { return mvarGroups; } }
private CoreObjectProperty.CoreObjectPropertyCollection mvarProperties = new CoreObjectProperty.CoreObjectPropertyCollection();
public CoreObjectProperty.CoreObjectPropertyCollection Properties { get { return mvarProperties; } }
public object Clone()
{
CoreObjectGroup clone = new CoreObjectGroup();
clone.Name = (mvarName.Clone() as string);
foreach (CoreObjectGroup item in mvarGroups)
{
clone.Groups.Add(item.Clone() as CoreObjectGroup);
}
foreach (CoreObjectProperty item in mvarProperties)
{
clone.Properties.Add(item.Clone() as CoreObjectProperty);
}
return clone;
}
}
}

View File

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.ObjectModels.CoreObject
{
public class CoreObjectObjectModel : ObjectModel
{
private static ObjectModelReference _omr = null;
protected override ObjectModelReference MakeReferenceInternal()
{
if (_omr == null)
{
_omr = base.MakeReferenceInternal();
_omr.Title = "Core Object";
}
return _omr;
}
private CoreObjectGroup.CoreObjectGroupCollection mvarGroups = new CoreObjectGroup.CoreObjectGroupCollection();
public CoreObjectGroup.CoreObjectGroupCollection Groups { get { return mvarGroups; } }
private CoreObjectProperty.CoreObjectPropertyCollection mvarProperties = new CoreObjectProperty.CoreObjectPropertyCollection();
public CoreObjectProperty.CoreObjectPropertyCollection Properties { get { return mvarProperties; } }
public override void Clear()
{
mvarGroups.Clear();
mvarProperties.Clear();
}
public override void CopyTo(ObjectModel where)
{
CoreObjectObjectModel clone = (where as CoreObjectObjectModel);
if (clone == null) throw new ObjectModelNotSupportedException();
foreach (CoreObjectGroup item in mvarGroups)
{
clone.Groups.Add(item.Clone() as CoreObjectGroup);
}
foreach (CoreObjectProperty item in mvarProperties)
{
clone.Properties.Add(item.Clone() as CoreObjectProperty);
}
}
}
}

View File

@ -0,0 +1,145 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.ObjectModels.CoreObject
{
public class CoreObjectProperty : ICloneable
{
public class CoreObjectPropertyCollection
: System.Collections.ObjectModel.Collection<CoreObjectProperty>
{
private CoreObjectGroup _parent = null;
public CoreObjectPropertyCollection(CoreObjectGroup parent = null)
{
_parent = parent;
}
public CoreObjectProperty Add(string name, string[] values = null, CoreObjectAttribute[] attributes = null)
{
CoreObjectProperty item = new CoreObjectProperty();
item.Name = name;
if (values != null)
{
foreach (string value in values)
{
item.Values.Add(value);
}
}
if (attributes != null)
{
foreach (CoreObjectAttribute att in attributes)
{
item.Attributes.Add(att);
}
}
Add(item);
return item;
}
private Dictionary<string, CoreObjectProperty> _itemsByName = new Dictionary<string, CoreObjectProperty>();
public CoreObjectProperty this[string name]
{
get
{
if (_itemsByName.ContainsKey(name)) return _itemsByName[name];
return null;
}
}
protected override void InsertItem(int index, CoreObjectProperty item)
{
base.InsertItem(index, item);
item.ParentGroup = _parent;
_itemsByName.Add(item.Name, item);
}
protected override void RemoveItem(int index)
{
this[index].ParentGroup = null;
_itemsByName.Remove(this[index].Name);
base.RemoveItem(index);
}
protected override void SetItem(int index, CoreObjectProperty item)
{
if (index > -1 && index < this.Count - 1)
{
this[index].ParentGroup = null;
_itemsByName.Remove(this[index].Name);
}
base.SetItem(index, item);
_itemsByName.Add(item.Name, item);
item.ParentGroup = _parent;
}
protected override void ClearItems()
{
foreach (CoreObjectProperty item in this)
{
item.ParentGroup = null;
}
_itemsByName.Clear();
base.ClearItems();
}
}
private string mvarName = String.Empty;
public string Name { get { return mvarName; } set { mvarName = value; } }
private CoreObjectGroup mvarParentGroup = null;
public CoreObjectGroup ParentGroup
{
get { return mvarParentGroup; }
internal set
{
mvarParentGroup = value;
}
}
private CoreObjectAttribute.CoreObjectAttributeCollection mvarAttributes = new CoreObjectAttribute.CoreObjectAttributeCollection();
public CoreObjectAttribute.CoreObjectAttributeCollection Attributes { get { return mvarAttributes; } }
private System.Collections.Specialized.StringCollection mvarValues = new System.Collections.Specialized.StringCollection();
public System.Collections.Specialized.StringCollection Values { get { return mvarValues; } }
public object Clone()
{
CoreObjectProperty clone = new CoreObjectProperty();
clone.Name = (mvarName.Clone() as string);
foreach (CoreObjectAttribute item in mvarAttributes)
{
clone.Attributes.Add(item.Clone() as CoreObjectAttribute);
}
foreach (string item in mvarValues)
{
clone.Values.Add(item);
}
return clone;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append(mvarName);
if (mvarAttributes.Count > 0)
{
sb.Append(";");
foreach (CoreObjectAttribute att in mvarAttributes)
{
sb.Append(att.Name);
if (att.Values.Count > 0)
{
sb.Append("=");
for (int i = 0; i < att.Values.Count; i++)
{
sb.Append(att.Values[i]);
if (i < att.Values.Count - 1) sb.Append(',');
}
}
}
}
return sb.ToString();
}
}
}

View File

@ -51,7 +51,7 @@
<Compile Include="DataFormats\RichTextMarkup\RTML\RTMLDataFormat.cs" />
<Compile Include="DataFormats\Markup\XML\XMLDataFormat.cs" />
<Compile Include="DataFormats\Markup\XML\XMLDataFormatSettings.cs" />
<Compile Include="DataFormats\PropertyList\CoreObject\CoreObjectDataFormat.cs" />
<Compile Include="DataFormats\CoreObject\CoreObjectDataFormat.cs" />
<Compile Include="DataFormats\PropertyList\ExtensibleConfiguration\ExtensibleConfigurationDataFormat.cs" />
<Compile Include="DataFormats\PropertyList\ExtensibleConfiguration\ExtensibleConfigurationSettings.cs" />
<Compile Include="DataFormats\PropertyList\Text\TextPropertyListDataFormat.cs" />
@ -84,6 +84,10 @@
<Compile Include="ObjectModels\Chunked\RIFFMetadata.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="ObjectModels\CoreObject\CoreObjectAttribute.cs" />
<Compile Include="ObjectModels\CoreObject\CoreObjectObjectModel.cs" />
<Compile Include="ObjectModels\CoreObject\CoreObjectGroup.cs" />
<Compile Include="ObjectModels\CoreObject\CoreObjectProperty.cs" />
<Compile Include="ObjectModels\DataLink\DataLinkObjectModel.cs" />
<Compile Include="ObjectModels\FileSystem\CompressedFile.cs" />
<Compile Include="ObjectModels\FileSystem\DataRequestEvent.cs" />

View File

@ -3,9 +3,9 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using UniversalEditor.DataFormats.PropertyList.CoreObject;
using UniversalEditor.DataFormats.CoreObject;
using UniversalEditor.ObjectModels.Contact;
using UniversalEditor.ObjectModels.PropertyList;
using UniversalEditor.ObjectModels.CoreObject;
namespace UniversalEditor.DataFormats.Contact.VCard
{
@ -33,20 +33,20 @@ namespace UniversalEditor.DataFormats.Contact.VCard
protected override void BeforeLoadInternal(Stack<ObjectModel> objectModels)
{
base.BeforeLoadInternal(objectModels);
objectModels.Push(new PropertyListObjectModel());
objectModels.Push(new CoreObjectObjectModel());
}
protected override void AfterLoadInternal(Stack<ObjectModel> objectModels)
{
base.AfterLoadInternal(objectModels);
PropertyListObjectModel plom = (objectModels.Pop() as PropertyListObjectModel);
CoreObjectObjectModel core = (objectModels.Pop() as CoreObjectObjectModel);
ContactObjectModel contact = (objectModels.Pop() as ContactObjectModel);
Group vcard = plom.Groups["VCARD"];
CoreObjectGroup vcard = core.Groups["VCARD"];
if (vcard == null) throw new InvalidDataFormatException("File does not contain a top-level VCARD group");
bool hasVersion = false;
foreach (Property prop in vcard.Properties)
foreach (CoreObjectProperty prop in vcard.Properties)
{
switch (prop.Name)
{
@ -54,27 +54,33 @@ namespace UniversalEditor.DataFormats.Contact.VCard
{
if (!hasVersion)
{
mvarFormatVersion = new Version(prop.Value.ToString());
hasVersion = true;
if (prop.Values.Count > 0)
{
mvarFormatVersion = new Version(prop.Values[0].ToString());
hasVersion = true;
}
}
break;
}
case "N":
{
ContactName name = new ContactName();
string[] splits = prop.Value.ToString().Split(new char[] { ';' });
if (splits.Length > 1)
if (prop.Values.Count > 0)
{
name.FamilyName = splits[0];
name.GivenName = splits[1];
if (splits.Length > 2)
name.GivenName = prop.Values[0];
if (prop.Values.Count > 1)
{
// third assuming is middle name
name.MiddleName = splits[2];
if (splits.Length > 3)
name.FamilyName = prop.Values[0];
name.GivenName = prop.Values[1];
if (prop.Values.Count > 2)
{
// per wikipedia fourth is title
name.Title = splits[3];
// third assuming is middle name
name.MiddleName = prop.Values[2];
if (prop.Values.Count > 3)
{
// per wikipedia fourth is title
name.Title = prop.Values[3];
}
}
}
}
@ -86,12 +92,18 @@ namespace UniversalEditor.DataFormats.Contact.VCard
// formatted name
if (contact.Names.Count > 0)
{
contact.Names[contact.Names.Count - 1].FormattedName = prop.Value.ToString();
if (prop.Values.Count > 0)
{
contact.Names[contact.Names.Count - 1].FormattedName = prop.Values[0].ToString();
}
}
else
{
ContactName name = new ContactName();
name.FormattedName = prop.Value.ToString();
if (prop.Values.Count > 0)
{
name.FormattedName = prop.Values[0].ToString();
}
contact.Names.Add(name);
}
break;
@ -116,9 +128,9 @@ namespace UniversalEditor.DataFormats.Contact.VCard
base.BeforeSaveInternal(objectModels);
ContactObjectModel contact = (objectModels.Pop() as ContactObjectModel);
PropertyListObjectModel plom = new PropertyListObjectModel();
CoreObjectObjectModel core = new CoreObjectObjectModel();
objectModels.Push(plom);
objectModels.Push(core);
}
}
}