From: <fab...@us...> - 2008-10-10 19:19:47
|
Revision: 3835 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=3835&view=rev Author: fabiomaulo Date: 2008-10-10 19:19:40 +0000 (Fri, 10 Oct 2008) Log Message: ----------- Few test passed Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Mapping/Property.cs trunk/nhibernate/src/NHibernate/NHibernate.csproj trunk/nhibernate/src/NHibernate/Properties/PropertyAccessorFactory.cs trunk/nhibernate/src/NHibernate/Type/NullableType.cs trunk/nhibernate/src/NHibernate.Test/EntityModeTest/Xml/Accessors/XmlAccessorFixture.cs Added Paths: ----------- trunk/nhibernate/src/NHibernate/Properties/XmlAccessor.cs Modified: trunk/nhibernate/src/NHibernate/Mapping/Property.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Mapping/Property.cs 2008-10-10 16:29:37 UTC (rev 3834) +++ trunk/nhibernate/src/NHibernate/Mapping/Property.cs 2008-10-10 19:19:40 UTC (rev 3835) @@ -187,6 +187,11 @@ get { return PropertyAccessorFactory.GetPropertyAccessor(PropertyAccessorName); } } + public virtual string GetAccessorPropertyName(EntityMode mode) + { + return mode == EntityMode.Xml ? nodeName : Name; + } + public virtual bool IsBasicPropertyAccessor { // NH Different behavior : see IPropertyAccessor.CanAccessThroughReflectionOptimizer (ref. NH-1304) Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2008-10-10 16:29:37 UTC (rev 3834) +++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2008-10-10 19:19:40 UTC (rev 3835) @@ -1109,6 +1109,7 @@ <SubType>Code</SubType> </Compile> <Compile Include="Util\XmlHelper.cs" /> + <Compile Include="Properties\XmlAccessor.cs" /> <EmbeddedResource Include="nhibernate-configuration.xsd"> <SubType>Designer</SubType> </EmbeddedResource> Modified: trunk/nhibernate/src/NHibernate/Properties/PropertyAccessorFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Properties/PropertyAccessorFactory.cs 2008-10-10 16:29:37 UTC (rev 3834) +++ trunk/nhibernate/src/NHibernate/Properties/PropertyAccessorFactory.cs 2008-10-10 19:19:40 UTC (rev 3835) @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using NHibernate.Type; using NHibernate.Util; +using NHibernate.Engine; namespace NHibernate.Properties { @@ -213,11 +215,20 @@ return GetPocoPropertyAccessor(property.PropertyAccessorName); case EntityMode.Map: return DynamicMapPropertyAccessor; + case EntityMode.Xml: + return GetXmlPropertyAccessor(property.GetAccessorPropertyName(modeToUse), property.Type, null); default: throw new MappingException("Unknown entity mode [" + mode + "]"); } } + private static IPropertyAccessor GetXmlPropertyAccessor(string nodeName, IType type, ISessionFactoryImplementor factory) + { + //TODO: need some caching scheme? really comes down to decision + // regarding amount of state (if any) kept on PropertyAccessors + return new XmlAccessor(nodeName, type, factory); + } + private static IPropertyAccessor GetPocoPropertyAccessor(string accessorName) { string accName = string.IsNullOrEmpty(accessorName) ? DefaultAccessorName : accessorName; Added: trunk/nhibernate/src/NHibernate/Properties/XmlAccessor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Properties/XmlAccessor.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Properties/XmlAccessor.cs 2008-10-10 19:19:40 UTC (rev 3835) @@ -0,0 +1,425 @@ +using System; +using System.Collections; +using System.Reflection; +using System.Xml; +using NHibernate.Engine; +using NHibernate.Type; + +namespace NHibernate.Properties +{ + /// <summary> + /// Responsible for accessing property values represented as a XmlElement + /// or XmlAttribute. + /// </summary> + public class XmlAccessor : IPropertyAccessor + { + private readonly ISessionFactoryImplementor factory; + private readonly string nodeName; + private readonly IType propertyType; + + public XmlAccessor(string nodeName, IType propertyType, ISessionFactoryImplementor factory) + { + this.factory = factory; + this.nodeName = nodeName; + this.propertyType = propertyType; + } + + #region Implementation of IPropertyAccessor + + public IGetter GetGetter(System.Type theClass, string propertyName) + { + if (nodeName == null) + { + throw new MappingException("no node name for property: " + propertyName); + } + if (".".Equals(nodeName)) + { + return new TextGetter(propertyType, factory); + } + else if (nodeName.IndexOf('/') > -1) + { + return new ElementAttributeGetter(nodeName, propertyType, factory); + } + else if (nodeName.IndexOf('@') > -1) + { + return new AttributeGetter(nodeName, propertyType, factory); + } + else + { + return new ElementGetter(nodeName, propertyType, factory); + } + } + + public ISetter GetSetter(System.Type theClass, string propertyName) + { + if (nodeName == null) + { + throw new MappingException("no node name for property: " + propertyName); + } + if (".".Equals(nodeName)) + { + return new TextSetter(propertyType); + } + else if (nodeName.IndexOf('/') > -1) + { + return new ElementAttributeSetter(nodeName, propertyType); + } + else if (nodeName.IndexOf('@') > -1) + { + return new AttributeSetter(nodeName, propertyType); + } + else + { + return new ElementSetter(nodeName, propertyType); + } + } + + public bool CanAccessThroughReflectionOptimizer + { + get { return true; } + } + + #endregion + + #region Nested type: AttributeGetter + + /// <summary> For nodes like <tt>"@bar"</tt></summary> + [Serializable] + public class AttributeGetter : XmlGetter + { + private readonly string attributeName; + + public AttributeGetter(string name, IType propertyType, ISessionFactoryImplementor factory) + : base(propertyType, factory) + { + attributeName = name.Substring(1); + } + + public override object Get(object owner) + { + var ownerElement = (XmlNode) owner; + XmlNode attribute = ownerElement.Attributes[attributeName]; + return attribute == null ? null : propertyType.FromXMLNode(attribute, factory); + } + } + + #endregion + + #region Nested type: AttributeSetter + + /// <summary> For nodes like <tt>"@bar"</tt></summary> + [Serializable] + public class AttributeSetter : XmlSetter + { + private readonly string attributeName; + + public AttributeSetter(string name, IType propertyType) : base(propertyType) + { + attributeName = name.Substring(1); + } + + public override void Set(object target, object value) + { + var owner = (XmlElement) target; + XmlAttribute attribute = owner.Attributes[attributeName]; + if (value == null) + { + if (attribute != null) + { + owner.Attributes.Remove(attribute); + } + } + else + { + if (attribute == null) + { + owner.SetAttribute(attributeName, "null"); + attribute = owner.Attributes[attributeName]; + } + propertyType.SetToXMLNode(attribute, value, null); + } + } + } + + #endregion + + #region Nested type: ElementAttributeGetter + + /// <summary> For nodes like <tt>"foo/@bar"</tt></summary> + [Serializable] + public class ElementAttributeGetter : XmlGetter + { + private readonly string attributeName; + private readonly string elementName; + + public ElementAttributeGetter(string name, IType propertyType, ISessionFactoryImplementor factory) + : base(propertyType, factory) + { + elementName = name.Substring(0, (name.IndexOf('/'))); + attributeName = name.Substring(name.IndexOf('/') + 2); + } + + public override object Get(object owner) + { + var ownerElement = (XmlNode) owner; + + XmlNode element = ownerElement[elementName]; + + if (element == null) + { + return null; + } + else + { + XmlAttribute attribute = element.Attributes[attributeName]; + if (attribute == null) + { + return null; + } + else + { + return propertyType.FromXMLNode(attribute, factory); + } + } + } + } + + #endregion + + #region Nested type: ElementAttributeSetter + + /// <summary> For nodes like <tt>"foo/@bar"</tt></summary> + [Serializable] + public class ElementAttributeSetter : XmlSetter + { + private readonly string attributeName; + private readonly string elementName; + + public ElementAttributeSetter(string name, IType propertyType) : base(propertyType) + { + elementName = name.Substring(0, name.IndexOf('/')); + attributeName = name.Substring(name.IndexOf('/') + 2); + } + + public override void Set(object target, object value) + { + var owner = (XmlElement) target; + XmlElement element = owner[elementName]; + if (value == null) + { + if (element != null) + { + owner.RemoveChild(element); + } + } + else + { + XmlAttribute attribute; + if (element == null) + { + element = owner.OwnerDocument.CreateElement(elementName); + owner.AppendChild(element); + attribute = null; + } + else + { + attribute = element.Attributes[attributeName]; + } + + if (attribute == null) + { + element.SetAttribute(attributeName, "null"); + attribute = element.Attributes[attributeName]; + } + propertyType.SetToXMLNode(attribute, value, null); + } + } + } + + #endregion + + #region Nested type: ElementGetter + + /// <summary> For nodes like <tt>"foo"</tt></summary> + [Serializable] + public class ElementGetter : XmlGetter + { + private readonly string elementName; + + public ElementGetter(string name, IType propertyType, ISessionFactoryImplementor factory) + : base(propertyType, factory) + { + elementName = name; + } + + public override object Get(object owner) + { + var ownerElement = (XmlNode) owner; + XmlNode element = ownerElement[elementName]; + return element == null ? null : propertyType.FromXMLNode(element, factory); + } + } + + #endregion + + #region Nested type: ElementSetter + + /// <summary> For nodes like <tt>"foo"</tt></summary> + [Serializable] + public class ElementSetter : XmlSetter + { + private readonly string elementName; + + public ElementSetter(string name, IType propertyType) : base(propertyType) + { + elementName = name; + } + + public override void Set(object target, object value) + { + if (value != CollectionType.UnfetchedCollection) + { + var owner = (XmlElement) target; + XmlElement existing = owner[elementName]; + if (existing != null) + { + owner.RemoveChild(existing); + } + if (value != null) + { + XmlElement element = owner.OwnerDocument.CreateElement(elementName); + owner.AppendChild(element); + propertyType.SetToXMLNode(element, value, null); + } + } + } + } + + #endregion + + #region Nested type: TextGetter + + /// <summary> For nodes like <tt>"."</tt></summary> + [Serializable] + public class TextGetter : XmlGetter + { + public TextGetter(IType propertyType, ISessionFactoryImplementor factory) : base(propertyType, factory) {} + + public override object Get(object owner) + { + var ownerElement = (XmlNode) owner; + return propertyType.FromXMLNode(ownerElement, factory); + } + } + + #endregion + + #region Nested type: TextSetter + + /// <summary> For nodes like <tt>"."</tt></summary> + [Serializable] + public class TextSetter : XmlSetter + { + public TextSetter(IType propertyType) : base(propertyType) {} + + public override void Set(object target, object value) + { + var owner = (XmlNode) target; + if (!propertyType.IsXMLElement) + { + //kinda ugly, but needed for collections with a "." node mapping + if (value == null) + { + owner.InnerText = ""; //is this ok? + } + else + { + propertyType.SetToXMLNode(owner, value, null); + } + } + } + } + + #endregion + + #region Nested type: XmlGetter + + /// <summary> Defines the strategy for getting property values out of a dom4j Node.</summary> + [Serializable] + public abstract class XmlGetter : IGetter + { + protected ISessionFactoryImplementor factory; + protected IType propertyType; + + internal XmlGetter(IType propertyType, ISessionFactoryImplementor factory) + { + this.propertyType = propertyType; + this.factory = factory; + } + + #region IGetter Members + + /// <summary> Get the declared type</summary> + public virtual System.Type ReturnType + { + get { return typeof (object); } + } + + /// <summary> Optional operation (return null)</summary> + public virtual string PropertyName + { + get { return null; } + } + + /// <summary> Optional operation (return null)</summary> + public virtual MethodInfo Method + { + get { return null; } + } + + public virtual object GetForInsert(object owner, IDictionary mergeMap, ISessionImplementor session) + { + return Get(owner); + } + + public abstract object Get(object target); + + #endregion + } + + #endregion + + #region Nested type: XmlSetter + + [Serializable] + public abstract class XmlSetter : ISetter + { + protected internal IType propertyType; + + internal XmlSetter(IType propertyType) + { + this.propertyType = propertyType; + } + + #region ISetter Members + + /// <summary> Optional operation (return null)</summary> + public virtual string PropertyName + { + get { return null; } + } + + /// <summary> Optional operation (return null)</summary> + public virtual MethodInfo Method + { + get { return null; } + } + + public abstract void Set(object target, object value); + + #endregion + } + + #endregion + } +} \ No newline at end of file Property changes on: trunk/nhibernate/src/NHibernate/Properties/XmlAccessor.cs ___________________________________________________________________ Added: svn:mergeinfo + Modified: trunk/nhibernate/src/NHibernate/Type/NullableType.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Type/NullableType.cs 2008-10-10 16:29:37 UTC (rev 3834) +++ trunk/nhibernate/src/NHibernate/Type/NullableType.cs 2008-10-10 19:19:40 UTC (rev 3835) @@ -345,12 +345,12 @@ public override object FromXMLNode(XmlNode xml, IMapping factory) { - return FromXMLString(xml.Value, factory); + return FromXMLString(xml.InnerText, factory); } public override void SetToXMLNode(XmlNode xml, object value, ISessionFactoryImplementor factory) { - xml.Value = ToXMLString(value, factory); + xml.InnerText = ToXMLString(value, factory); } public string ToXMLString(object value, ISessionFactoryImplementor pc) Modified: trunk/nhibernate/src/NHibernate.Test/EntityModeTest/Xml/Accessors/XmlAccessorFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/EntityModeTest/Xml/Accessors/XmlAccessorFixture.cs 2008-10-10 16:29:37 UTC (rev 3834) +++ trunk/nhibernate/src/NHibernate.Test/EntityModeTest/Xml/Accessors/XmlAccessorFixture.cs 2008-10-10 19:19:40 UTC (rev 3835) @@ -1,3 +1,4 @@ +using System; using System.Xml; using NHibernate.Mapping; using NHibernate.Properties; @@ -6,7 +7,7 @@ namespace NHibernate.Test.EntityModeTest.Xml.Accessors { - [TestFixture, Ignore("Not supported yet.")] + [TestFixture] public class XmlAccessorFixture { public static XmlElement dom = GenerateTestElement(); @@ -77,6 +78,7 @@ nameSetter.Set(root, "NHForge"); accountIdSetter.Set(root, 456L); + Console.WriteLine(dom.OuterXml); //Assert.That(new NodeComparator().Compare(dom, root) == 0); } @@ -107,7 +109,7 @@ Assert.That(name, Is.EqualTo("NHForge")); } - [Test] + [Test, Ignore("Not supported yet.")] public void StringTextExtraction() { Property property = GenerateTextProperty(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |