context: using System;
  using System.Linq;
  using System.Data.Common;
  using NHibernate.Cfg.MappingSchema;
  using NHibernate.Engine;
  using NHibernate.Mapping.ByCode;
  using NHibernate.Mapping.ByCode.Impl;
  using NHibernate.Properties;
  using NHibernate.SqlTypes;
  using NHibernate.Type;
  using NHibernate.UserTypes;
  using NUnit.Framework;
  
  namespace NHibernate.Test.MappingByCode.MappersTests
  {
  	[TestFixture]
  	public class PropertyMapperTest
  	{
  		private enum MyEnum
  		{
  			One
  		}
  		private class MyClass
  		{
  			public string Autoproperty { get; set; }
  			public string ReadOnly { get { return ""; } }
  			public MyEnum EnumProp { get; set; }
  		}
  
  		private class MyAccessorMapper : IAccessorPropertyMapper
  		{
  			public bool AccessorCalled { get; set; }
  			public void Access(Accessor accessor)
  			{
  				AccessorCalled = true;
  			}
  
  			public void Access(System.Type accessorType)
  			{
  			}
  		}
  		[Test]
  		public void WhenCreateWithGivenAccessorMapperThenUseTheGivenAccessoMapper()
  		{
  			var member = typeof (MyClass).GetProperty("ReadOnly");
  			var mapping = new HbmProperty();
  			var myAccessorMapper = new MyAccessorMapper();
  			var mapper = new PropertyMapper(member, mapping, myAccessorMapper);
  			mapper.Access(Accessor.Field);
  			Assert.That(myAccessorMapper.AccessorCalled, Is.True);
  		}
  
  		[Test]
  		public void WhenSettingByTypeThenCheckCompatibility()
  		{
  			var member = typeof(MyClass).GetProperty("ReadOnly");
  			var mapping = new HbmProperty();
  			var mapper = new PropertyMapper(member, mapping);
  
  			Assert.That(() => mapper.Access(typeof(object)), Throws.TypeOf<ArgumentOutOfRangeException>());
  			Assert.That(() => mapper.Access(typeof(FieldAccessor)), Throws.Nothing);
  			Assert.That(mapping.Access, Is.EqualTo(typeof(FieldAccessor).AssemblyQualifiedName));
  		}
  
  		[Test]
  		public void WhenSetTypeByITypeThenSetTypeName()
  		{
  			var member = typeof(MyClass).GetProperty("ReadOnly");
  			var mapping = new HbmProperty();
  			var mapper = new PropertyMapper(member, mapping);
  			mapper.Type(NHibernateUtil.String);
  
  			Assert.That(mapping.Type.name, Is.EqualTo("String"));
  		}
  
  		[Test]
  		public void WhenSetTypeByIUserTypeThenSetTypeName()
  		{
  			var member = typeof(MyClass).GetProperty("ReadOnly");
  			var mapping = new HbmProperty();
  			var mapper = new PropertyMapper(member, mapping);
  			mapper.Type<MyType>();
  
  			Assert.That(mapping.Type.name, Does.Contain("MyType"));
  			Assert.That(mapping.type, Is.Null);
  		}
  
  		[Test]
  		public void WhenSetTypeByICompositeUserTypeThenSetTypeName()
  		{
  			var member = typeof(MyClass).GetProperty("ReadOnly");
  			var mapping = new HbmProperty();
  			var mapper = new PropertyMapper(member, mapping);
  			mapper.Type<MyCompoType>();
  
  			Assert.That(mapping.Type.name, Does.Contain("MyCompoType"));
  			Assert.That(mapping.type, Is.Null);
  		}
  
  		[Test]
  		public void WhenSetTypeByIUserTypeWithParamsThenSetType()
  		{
  			var member = typeof(MyClass).GetProperty("ReadOnly");
  			var mapping = new HbmProperty();
  			var mapper = new PropertyMapper(member, mapping);
  			mapper.Type<MyType>(new { Param1 = "a", Param2 = 12 });
  
  			Assert.That(mapping.type1, Is.Null);
  			Assert.That(mapping.Type.name, Does.Contain("MyType"));
  			Assert.That(mapping.Type.param, Has.Length.EqualTo(2));
  			Assert.That(mapping.Type.param.Select(p => p.name), Is.EquivalentTo(new [] {"Param1", "Param2"}));
  			Assert.That(mapping.Type.param.Select(p => p.GetText()), Is.EquivalentTo(new [] {"a", "12"}));
  		}
  
  		[Test]
  		public void WhenSetTypeByIUserTypeWithNullParamsThenSetTypeName()
  		{
  			var member = typeof(MyClass).GetProperty("ReadOnly");
  			var mapping = new HbmProperty();
  			var mapper = new PropertyMapper(member, mapping);
  			mapper.Type<MyType>(null);
  
  			Assert.That(mapping.Type.name, Does.Contain("MyType"));
  			Assert.That(mapping.type, Is.Null);
  		}
  
  		[Test]
  		public void WhenSetTypeByITypeTypeThenSetType()
  		{
  			var member = For<MyClass>.Property(c => c.EnumProp);
  			var mapping = new HbmProperty();
  			var mapper = new PropertyMapper(member, mapping);
  			mapper.Type<EnumStringType<MyEnum>>();
  
  			Assert.That(mapping.Type.name, Does.Contain(typeof(EnumStringType<MyEnum>).FullName));
  			Assert.That(mapping.type, Is.Null);
  		}
  
  		[Test]
  		public void WhenSetInvalidTypeThenThrow()
  		{
  			var member = typeof(MyClass).GetProperty("ReadOnly");
  			var mapping = new HbmProperty();
  			var mapper = new PropertyMapper(member, mapping);
  			Assert.That(() => mapper.Type(typeof(object), null), Throws.TypeOf<ArgumentOutOfRangeException>());
  			Assert.That(() => mapper.Type(null, null), Throws.TypeOf<ArgumentNullException>());
  		}
  
  		[Test]
  		public void WhenSetDifferentColumnNameThenSetTheName()
  		{
  			var member = typeof(MyClass).GetProperty("Autoproperty");
  			var mapping = new HbmProperty();
  			var mapper = new PropertyMapper(member, mapping);
  			mapper.Column(cm => cm.Name("pepe"));
  
  			Assert.That(mapping.Columns.Count(), Is.EqualTo(1));
  			Assert.That(mapping.Columns.Single().name, Is.EqualTo("pepe"));
  		}
  
  		[Test]
  		public void WhenSetDefaultColumnNameThenDoesNotSetTheName()
  		{
  			var member = typeof(MyClass).GetProperty("Autoproperty");
  			var mapping = new HbmProperty();
  			var mapper = new PropertyMapper(member, mapping);
  			mapper.Column(cm => { cm.Name("Autoproperty"); cm.Length(50); });
  			Assert.That(mapping.column, Is.Null);
  			Assert.That(mapping.length, Is.EqualTo("50"));
  			Assert.That(mapping.Columns, Is.Empty);
  		}
  
  		[Test]
  		public void WhenSetBasicColumnValuesThenSetPlainValues()
  		{
  			var member = typeof(MyClass).GetProperty("Autoproperty");
  			var mapping = new HbmProperty();
  			var mapper = new PropertyMapper(member, mapping);
  			mapper.Column(cm =>
  			{
  				cm.Length(50);
  				cm.NotNullable(true);
  			});
  			Assert.That(mapping.Items, Is.Null);
  			Assert.That(mapping.length, Is.EqualTo("50"));
  			Assert.That(mapping.notnull, Is.EqualTo(true));
  			Assert.That(mapping.notnullSpecified, Is.EqualTo(true));
  		}
  
  		[Test]
  		public void WhenSetColumnValuesThenAddColumnTag()
  		{
  			var member = typeof(MyClass).GetProperty("Autoproperty");
  			var mapping = new HbmProperty();
  			var mapper = new PropertyMapper(member, mapping);
  			mapper.Column(cm =>
  			{
  				cm.SqlType("VARCHAR(50)");
  				cm.NotNullable(true);
  			});
  			Assert.That(mapping.Items, Is.Not.Null);
  			Assert.That(mapping.Columns.Count(), Is.EqualTo(1));
  		}
  
  		[Test]
  		public void WhenSetBasicColumnValuesMoreThanOnesThenMergeColumn()
  		{
  			var member = typeof(MyClass).GetProperty("Autoproperty");
  			var mapping = new HbmProperty();
  			var mapper = new PropertyMapper(member, mapping);
  			mapper.Column(cm => cm.Length(50));
  			mapper.Column(cm => cm.NotNullable(true));
  
  			Assert.That(mapping.Items, Is.Null);
  			Assert.That(mapping.length, Is.EqualTo("50"));
  			Assert.That(mapping.notnull, Is.EqualTo(true));
  			Assert.That(mapping.notnullSpecified, Is.EqualTo(true));
  		}
  
  		[Test]
  		public void WhenSetMultiColumnsValuesThenAddColumns()
  		{
  			var member = typeof(MyClass).GetProperty("ReadOnly");
  			var mapping = new HbmProperty();
  			var mapper = new PropertyMapper(member, mapping);
  			mapper.Type<MyType>();
  			mapper.Columns(cm =>
  				{
  					cm.Name("column1");
  					cm.Length(50);
  				}, cm =>
  					{
  						cm.Name("column2");
  						cm.SqlType("VARCHAR(10)");
  					});
  			Assert.That(mapping.Columns.Count(), Is.EqualTo(2));
  		}
  
  		[Test]
  		public void WhenSetMultiColumnsValuesThenAutoassignColumnNames()
  		{
  			var member = typeof(MyClass).GetProperty("ReadOnly");
  			var mapping = new HbmProperty();
  
gt: 			var mapper = new PropertyMapper(member, mapping);