Inheritance: IVisitable
		/// <summary>
		/// Dispatches the call to the extensions.
		/// </summary>
		/// <param name="pi">The property info reflection object.</param>
		/// <param name="belongsToModel">The belongs to model.</param>
		/// <param name="model">The model.</param>
		public void ProcessBelongsTo(PropertyInfo pi, BelongsToModel belongsToModel, ActiveRecordModel model)
		{
			foreach(IModelBuilderExtension extension in extensions)
			{
				extension.ProcessBelongsTo(pi, belongsToModel, model);
			}
		}
 /// <summary>
 /// Dispatches the call to the extensions.
 /// </summary>
 /// <param name="pi">The property info reflection object.</param>
 /// <param name="belongsToModel">The belongs to model.</param>
 /// <param name="model">The model.</param>
 public void ProcessBelongsTo(PropertyInfo pi, BelongsToModel belongsToModel, ActiveRecordModel model)
 {
     foreach (IModelBuilderExtension extension in extensions)
     {
         extension.ProcessBelongsTo(pi, belongsToModel, model);
     }
 }
Exemple #3
0
        public override void VisitBelongsTo(BelongsToModel model)
        {
            String cascade   = TranslateCascadeEnum(model.BelongsToAtt.Cascade);
            String outerJoin = TranslateOuterJoin(model.BelongsToAtt.OuterJoin);

            AppendF("<many-to-one {0} {1} {2} {3} {4} {5} {6} {7} {8} {9}/>",
                    MakeAtt("name", model.Property.Name),
                    MakeAtt("access", model.BelongsToAtt.AccessString),
                    MakeAtt("class", MakeTypeName(model.BelongsToAtt.Type)),
                    MakeAtt("column", model.BelongsToAtt.Column),
                    WriteIfFalse("insert", model.BelongsToAtt.Insert),
                    WriteIfFalse("update", model.BelongsToAtt.Update),
                    WriteIfTrue("not-null", model.BelongsToAtt.NotNull),
                    WriteIfTrue("unique", model.BelongsToAtt.Unique),
                    WriteIfNonNull("cascade", cascade),
                    WriteIfNonNull("outer-join", outerJoin));
        }
        /// <summary>
        /// Visits the belongs to.
        /// </summary>
        /// <remarks>
        /// Infer column name and type
        /// Verify that the property is virtual if the class was marked lazy.
        /// </remarks>
        /// <param name="model">The model.</param>
        public override void VisitBelongsTo(BelongsToModel model)
        {
            if (currentModel.ActiveRecordAtt != null)
            {
                if (currentModel.ActiveRecordAtt.Lazy ||
                    (currentModel.ActiveRecordAtt.LazySpecified == false && ActiveRecordModel.isLazyByDefault))
                {
                    //Assuming that a property must have at least a single accessor
                    MethodInfo accessor = model.Property.GetAccessors(true)[0];

                    if (!accessor.IsVirtual)
                    {
                        throw new ActiveRecordException(
                                  String.Format("Property {0} must be virtual because " +
                                                "class {1} support lazy loading [ActiveRecord(Lazy=true)]",
                                                model.Property.Name, model.Property.DeclaringType.Name));
                    }
                }
            }

            if (model.BelongsToAtt.Column == null && model.BelongsToAtt.CompositeKeyColumns == null)
            {
                model.BelongsToAtt.Column = model.Property.Name;
            }

            // Append column prefix
            if (model.BelongsToAtt.Column != null)
            {
                model.BelongsToAtt.Column = columnPrefix + model.BelongsToAtt.Column;
            }

            if (model.BelongsToAtt.Type == null)
            {
                model.BelongsToAtt.Type = model.Property.PropertyType;
            }

            JoinedTableModel joinedTable = ObtainJoinedTableIfPresent(model.Property, model.BelongsToAtt);

            if (joinedTable != null)
            {
                joinedTable.BelongsTo.Add(model);
            }
        }
 public override void VisitBelongsTo(BelongsToModel model)
 {
     if (currentModel.ActiveRecordAtt.Lazy)
     {
         //Assuming that a property must have at least a single accessor
         MethodInfo accessor = model.Property.GetAccessors(true)[0];
         if (!accessor.IsVirtual)
         {
             throw new ActiveRecordException(
                       string.Format("Property {0} must be virtual because " +
                                     "class {1} support lazy loading [ActiveRecord(Lazy=true)]",
                                     model.Property.Name,
                                     model.Property.DeclaringType.Name));
         }
     }
     if (model.BelongsToAtt.Column == null)
     {
         model.BelongsToAtt.Column = model.Property.Name;
     }
     if (model.BelongsToAtt.Type == null)
     {
         model.BelongsToAtt.Type = model.Property.PropertyType;
     }
 }
		private void ProcessProperties(Type type, ActiveRecordModel model)
		{
			// Check persistent properties of the base class as well
			if (ShouldCheckBase(type))
			{
				ProcessProperties(type.BaseType, model);
			}

			PropertyInfo[] props = type.GetProperties(DefaultBindingFlags);

			foreach(PropertyInfo prop in props)
			{
				bool isArProperty = false;
				AnyModel anyModel;
				HasManyToAnyModel hasManyToAnyModel;

				if (extension != null)
				{
					extension.ProcessProperty(prop, model);
				}

				object[] valAtts = prop.GetCustomAttributes(typeof(AbstractValidationAttribute), true);

				foreach(AbstractValidationAttribute valAtt in valAtts)
				{
					IValidator validator = valAtt.Build();
					validator.Initialize(validatorRegistry, prop);

					model.Validators.Add(validator);
				}

				foreach(object attribute in prop.GetCustomAttributes(false))
				{
					if (attribute is PrimaryKeyAttribute)
					{
						PrimaryKeyAttribute propAtt = attribute as PrimaryKeyAttribute;
						isArProperty = true;

						// Joined Subclasses must not have PrimaryKey
						if (type.IsDefined(typeof(JoinedBaseAttribute), true) && // JoinedBase in a superclass
							!type.IsDefined(typeof(JoinedBaseAttribute), false)) // but not here
						{
							throw new ActiveRecordException("You can't specify a PrimaryKeyAttribute in a joined subclass. " +
															"Check type " + model.Type.FullName);
						}

						if (prop.PropertyType.IsDefined(typeof(CompositeKeyAttribute), true))
						{
							object[] att = prop.PropertyType.GetCustomAttributes(typeof(CompositeKeyAttribute), true);

							CompositeKeyAttribute cAtt = att[0] as CompositeKeyAttribute;

							model.CompositeKey = new CompositeKeyModel(prop, cAtt);
						}
						else
						{
							if (!propAtt.IsOverride && model.PrimaryKey != null)
							{
								throw new ActiveRecordException("You can't specify more than one PrimaryKeyAttribute in a " +
								                                "class. Check type " + model.Type.FullName);
							}

							model.PrimaryKey = new PrimaryKeyModel(prop, propAtt);
						}
					}
					else if (attribute is CompositeKeyAttribute)
					{
						CompositeKeyAttribute propAtt = attribute as CompositeKeyAttribute;
						isArProperty = true;

						model.CompositeKey = new CompositeKeyModel(prop, propAtt);
					}
					else if (attribute is AnyAttribute)
					{
						AnyAttribute anyAtt = attribute as AnyAttribute;
						isArProperty = true;
						anyModel = new AnyModel(prop, anyAtt);
						model.Anys.Add(anyModel);

						CollectMetaValues(anyModel.MetaValues, prop);
					}
					else if (attribute is PropertyAttribute)
					{
						PropertyAttribute propAtt = attribute as PropertyAttribute;
						isArProperty = true;

						// If this property overrides a base class property remove the old one
						if (propAtt.IsOverride)
						{
							for (int index = 0; index < model.Properties.Count; ++index)
							{
								PropertyModel oldModel = (PropertyModel)model.Properties[index];

								if (oldModel.Property.Name == prop.Name)
								{
									model.Properties.RemoveAt(index);
									break;
								}
							}
						}

						PropertyModel propModel = new PropertyModel(prop, propAtt);
						model.Properties.Add(propModel);
						model.PropertyDictionary[prop.Name] = propModel;
					}
					else if (attribute is NestedAttribute)
					{
						NestedAttribute propAtt = attribute as NestedAttribute;
						isArProperty = true;

						ActiveRecordModel nestedModel = new ActiveRecordModel(prop.PropertyType);

						nestedModel.IsNestedType = true;

						Type nestedType = propAtt.MapType ?? prop.PropertyType;
						nestedModel.IsNestedCompositeType = model.IsNestedCompositeType;
						ProcessProperties(nestedType, nestedModel);
						ProcessFields(nestedType, nestedModel);

						NestedModel nested = new NestedModel(prop, propAtt, nestedModel);
						nestedModel.ParentNested = nested;

						model.Components.Add(nested);
					}
					else if (attribute is NestedParentReferenceAttribute)
					{
						NestedParentReferenceAttribute nestedParentAtt = attribute as NestedParentReferenceAttribute;
						isArProperty = true;

						model.ComponentParent.Add(new NestedParentReferenceModel(prop, nestedParentAtt));
					}
					else if (attribute is JoinedKeyAttribute)
					{
						JoinedKeyAttribute propAtt = attribute as JoinedKeyAttribute;
						isArProperty = true;

						if (model.Key != null)
						{
							throw new ActiveRecordException("You can't specify more than one JoinedKeyAttribute. " +
															"Check type " + model.Type.FullName);
						}

						model.Key = new KeyModel(prop, propAtt);
					}
					else if (attribute is VersionAttribute)
					{
						VersionAttribute propAtt = attribute as VersionAttribute;
						isArProperty = true;

						if (model.Version != null)
						{
							throw new ActiveRecordException("You can't specify more than one VersionAttribute. " +
															"Check type " + model.Type.FullName);
						}

						model.Version = new VersionModel(prop, propAtt);
					}
					else if (attribute is TimestampAttribute)
					{
						TimestampAttribute propAtt = attribute as TimestampAttribute;
						isArProperty = true;

						if (model.Timestamp != null)
						{
							throw new ActiveRecordException("You can't specify more than one TimestampAttribute. " +
															"Check type " + model.Type.FullName);
						}

						model.Timestamp = new TimestampModel(prop, propAtt);
					}
					// Relations
					else if (attribute is OneToOneAttribute)
					{
						OneToOneAttribute propAtt = attribute as OneToOneAttribute;
						isArProperty = true;

						model.OneToOnes.Add(new OneToOneModel(prop, propAtt));
					}
					else if (attribute is BelongsToAttribute)
					{
						BelongsToAttribute propAtt = attribute as BelongsToAttribute;
						isArProperty = true;

						BelongsToModel btModel = new BelongsToModel(prop, propAtt);
						model.BelongsTo.Add(btModel);
						model.BelongsToDictionary[prop.Name] = btModel;

						if (extension != null)
						{
							extension.ProcessBelongsTo(prop, btModel, model);
						}
					}
					// The ordering is important here, HasManyToAny must comes before HasMany!
					else if (attribute is HasManyToAnyAttribute)
					{
						HasManyToAnyAttribute propAtt = attribute as HasManyToAnyAttribute;
						isArProperty = true;

						hasManyToAnyModel = new HasManyToAnyModel(prop, propAtt);
						model.HasManyToAny.Add(hasManyToAnyModel);
						model.HasManyToAnyDictionary[prop.Name] = hasManyToAnyModel;

						CollectMetaValues(hasManyToAnyModel.MetaValues, prop);

						if (extension != null)
						{
							extension.ProcessHasManyToAny(prop, hasManyToAnyModel, model);
						}
					}
					else if (attribute is HasManyAttribute)
					{
						HasManyAttribute propAtt = attribute as HasManyAttribute;
						isArProperty = true;

						HasManyModel hasManyModel = new HasManyModel(prop, propAtt);
						if (propAtt.DependentObjects)
						{
							ActiveRecordModel dependentObjectModel = new ActiveRecordModel(propAtt.MapType);
							dependentObjectModel.IsNestedType = true;
							dependentObjectModel.IsNestedCompositeType = true;
							ProcessProperties(propAtt.MapType, dependentObjectModel);

							hasManyModel.DependentObjectModel = new DependentObjectModel(prop, propAtt, dependentObjectModel);
						}
						model.HasMany.Add(hasManyModel);
						model.HasManyDictionary[prop.Name] = hasManyModel;

						if (extension != null)
						{
							extension.ProcessHasMany(prop, hasManyModel, model);
						}
					}
					else if (attribute is HasAndBelongsToManyAttribute)
					{
						HasAndBelongsToManyAttribute propAtt = attribute as HasAndBelongsToManyAttribute;
						isArProperty = true;

						HasAndBelongsToManyModel habtManyModel = new HasAndBelongsToManyModel(prop, propAtt);
						model.HasAndBelongsToMany.Add(habtManyModel);
						model.HasAndBelongsToManyDictionary[prop.Name] = habtManyModel;

						if (extension != null)
						{
							extension.ProcessHasAndBelongsToMany(prop, habtManyModel, model);
						}
					}
					else if (attribute is Any.MetaValueAttribute)
					{
						if (prop.GetCustomAttributes(typeof(HasManyToAnyAttribute), false).Length == 0 &&
							prop.GetCustomAttributes(typeof(AnyAttribute), false).Length == 0
							)
							throw new ActiveRecordException(
								"You can't specify an Any.MetaValue without specifying the Any or HasManyToAny attribute. " +
								"Check type " + prop.DeclaringType.FullName);
					}
					else if (attribute is CompositeUserTypeAttribute)
					{
						CompositeUserTypeAttribute propAtt = attribute as CompositeUserTypeAttribute;
						isArProperty = true;

						model.CompositeUserType.Add(new CompositeUserTypeModel(prop, propAtt));
					}

					if (attribute is CollectionIDAttribute)
					{
						CollectionIDAttribute propAtt = attribute as CollectionIDAttribute;

						model.CollectionIDs.Add(new CollectionIDModel(prop, propAtt));
					}
					if (attribute is HiloAttribute)
					{
						HiloAttribute propAtt = attribute as HiloAttribute;

						model.Hilos.Add(new HiloModel(prop, propAtt));
					}
				}

				if (!isArProperty)
				{
					model.NotMappedProperties.Add(prop);
				}
			}
		}
		/// <summary>
		/// Visits the belongs to.
		/// </summary>
		/// <remarks>
		/// Infer column name and type
		/// Verify that the property is virtual if the class was marked lazy.
		/// </remarks>
		/// <param name="model">The model.</param>
		public override void VisitBelongsTo(BelongsToModel model)
		{
			if (currentModel.ActiveRecordAtt != null)
			{
				if (currentModel.ActiveRecordAtt.Lazy ||
				    (currentModel.ActiveRecordAtt.LazySpecified == false && ActiveRecordModel.isLazyByDefault))
				{
					//Assuming that a property must have at least a single accessor
					MethodInfo accessor = model.Property.GetAccessors(true)[0];

					if (!accessor.IsVirtual)
					{
						throw new ActiveRecordException(
							String.Format("Property {0} must be virtual because " +
							              "class {1} support lazy loading [ActiveRecord(Lazy=true)]",
							              model.Property.Name, model.Property.DeclaringType.Name));
					}
				}
			}

			if (model.BelongsToAtt.Column == null && model.BelongsToAtt.CompositeKeyColumns == null)
			{
				model.BelongsToAtt.Column = model.Property.Name;
			}

			// Append column prefix
			if (model.BelongsToAtt.Column != null)
			{
				model.BelongsToAtt.Column = columnPrefix + model.BelongsToAtt.Column;
			}

			if (model.BelongsToAtt.Type == null)
			{
				model.BelongsToAtt.Type = model.Property.PropertyType;
			}

			JoinedTableModel joinedTable = ObtainJoinedTableIfPresent(model.Property, model.BelongsToAtt);

			if (joinedTable != null)
			{
				joinedTable.BelongsTo.Add(model);
			}
		}
		/// <summary>
		/// Visits the belongs to.
		/// </summary>
		/// <param name="model">The model.</param>
		public override void VisitBelongsTo(BelongsToModel model)
		{
			if (!AppliesToCurrentTable(model.BelongsToAtt))
			{
				return;
			}

			String cascade = TranslateCascadeEnum(model.BelongsToAtt.Cascade);
			String fetch = TranslateFetch(model.BelongsToAtt.Fetch);
			String notFoundMode = TranslateNotFoundBehaviourEnum(model.BelongsToAtt.NotFoundBehaviour);

			if (model.BelongsToAtt.Column == null)
			{
				AppendF("<many-to-one{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}{12}>",
				        MakeAtt("name", model.Property.Name),
				        MakeAtt("access", model.BelongsToAtt.AccessString),
				        MakeAtt("class", MakeTypeName(model.BelongsToAtt.Type)),
				        WriteIfTrue("not-null", model.BelongsToAtt.NotNull),
				        WriteIfTrue("unique", model.BelongsToAtt.Unique),
				        WriteIfNonNull("unique-key", model.BelongsToAtt.UniqueKey),
				        WriteIfNonNull("cascade", cascade),
				        WriteIfNonNull("fetch", fetch),
				        WriteIfFalse("update", model.BelongsToAtt.Update),
				        WriteIfFalse("insert", model.BelongsToAtt.Insert),
						WriteIfNonNull("property-ref", model.BelongsToAtt.PropertyRef),
				        WriteIfNonNull("foreign-key", model.BelongsToAtt.ForeignKey),
				        WriteIfNonNull("not-found", notFoundMode));
				Ident();
				WriteCompositeColumns(model.BelongsToAtt.CompositeKeyColumns);
				Dedent();
				Append("</many-to-one>");
			}
			else
			{
				AppendF("<many-to-one{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}{12}{13} />",
				        MakeAtt("name", model.Property.Name),
				        MakeAtt("access", model.BelongsToAtt.AccessString),
				        MakeAtt("class", MakeTypeName(model.BelongsToAtt.Type)),
				        MakeAtt("column", model.BelongsToAtt.Column),
				        WriteIfFalse("insert", model.BelongsToAtt.Insert),
				        WriteIfFalse("update", model.BelongsToAtt.Update),
						WriteIfNonNull("property-ref", model.BelongsToAtt.PropertyRef),
				        WriteIfTrue("not-null", model.BelongsToAtt.NotNull),
				        WriteIfTrue("unique", model.BelongsToAtt.Unique),
				        WriteIfNonNull("unique-key", model.BelongsToAtt.UniqueKey),
				        WriteIfNonNull("foreign-key", model.BelongsToAtt.ForeignKey),
				        WriteIfNonNull("cascade", cascade),
				        WriteIfNonNull("fetch", fetch),
				        WriteIfNonNull("not-found", notFoundMode));
			}
		}
Exemple #9
0
        private void ProcessProperties(Type type, ActiveRecordModel model)
        {
            // Check persistent properties of the base class as well
            if (ShouldCheckBase(type))
            {
                ProcessProperties(type.BaseType, model);
            }

            PropertyInfo[] props = type.GetProperties(DefaultBindingFlags);

            foreach (PropertyInfo prop in props)
            {
                bool              isArProperty = false;
                AnyModel          anyModel;
                HasManyToAnyModel hasManyToAnyModel;

                if (extension != null)
                {
                    extension.ProcessProperty(prop, model);
                }

                object[] valAtts = prop.GetCustomAttributes(typeof(AbstractValidationAttribute), true);

                foreach (AbstractValidationAttribute valAtt in valAtts)
                {
                    IValidator validator = valAtt.Build();
                    validator.Initialize(validatorRegistry, prop);

                    model.Validators.Add(validator);
                }

                foreach (object attribute in prop.GetCustomAttributes(false))
                {
                    if (attribute is PrimaryKeyAttribute)
                    {
                        PrimaryKeyAttribute propAtt = attribute as PrimaryKeyAttribute;
                        isArProperty = true;

                        // Joined Subclasses must not have PrimaryKey
                        if (HasJoinedBase(type))
                        {
                            throw new ActiveRecordException("You can't specify a PrimaryKeyAttribute in a joined subclass. " +
                                                            "Check type " + model.Type.FullName);
                        }

                        if (prop.PropertyType.IsDefined(typeof(CompositeKeyAttribute), true))
                        {
                            object[] att = prop.PropertyType.GetCustomAttributes(typeof(CompositeKeyAttribute), true);

                            CompositeKeyAttribute cAtt = att[0] as CompositeKeyAttribute;

                            model.CompositeKey = new CompositeKeyModel(prop, cAtt);
                        }
                        else
                        {
                            if (!propAtt.IsOverride && model.PrimaryKey != null)
                            {
                                throw new ActiveRecordException("You can't specify more than one PrimaryKeyAttribute in a " +
                                                                "class. Check type " + model.Type.FullName);
                            }

                            model.PrimaryKey = new PrimaryKeyModel(prop, propAtt);
                        }
                    }
                    else if (attribute is CompositeKeyAttribute)
                    {
                        CompositeKeyAttribute propAtt = attribute as CompositeKeyAttribute;
                        isArProperty = true;

                        model.CompositeKey = new CompositeKeyModel(prop, propAtt);
                    }
                    else if (attribute is AnyAttribute)
                    {
                        AnyAttribute anyAtt = attribute as AnyAttribute;
                        isArProperty = true;
                        anyModel     = new AnyModel(prop, anyAtt);
                        model.Anys.Add(anyModel);

                        CollectMetaValues(anyModel.MetaValues, prop);
                    }
                    else if (attribute is PropertyAttribute)
                    {
                        PropertyAttribute propAtt = attribute as PropertyAttribute;
                        isArProperty = true;

                        // If this property overrides a base class property remove the old one
                        if (propAtt.IsOverride)
                        {
                            for (int index = 0; index < model.Properties.Count; ++index)
                            {
                                PropertyModel oldModel = (PropertyModel)model.Properties[index];

                                if (oldModel.Property.Name == prop.Name)
                                {
                                    model.Properties.RemoveAt(index);
                                    break;
                                }
                            }
                        }

                        PropertyModel propModel = new PropertyModel(prop, propAtt);
                        model.Properties.Add(propModel);
                        model.PropertyDictionary[prop.Name] = propModel;
                    }
                    else if (attribute is NestedAttribute)
                    {
                        NestedAttribute propAtt = attribute as NestedAttribute;
                        isArProperty = true;

                        ActiveRecordModel nestedModel = new ActiveRecordModel(prop.PropertyType);

                        nestedModel.IsNestedType = true;

                        Type nestedType = propAtt.MapType ?? prop.PropertyType;
                        nestedModel.IsNestedCompositeType = model.IsNestedCompositeType;
                        ProcessProperties(nestedType, nestedModel);
                        ProcessFields(nestedType, nestedModel);

                        NestedModel nested = new NestedModel(prop, propAtt, nestedModel);
                        nestedModel.ParentNested = nested;

                        model.Components.Add(nested);
                    }
                    else if (attribute is NestedParentReferenceAttribute)
                    {
                        NestedParentReferenceAttribute nestedParentAtt = attribute as NestedParentReferenceAttribute;
                        isArProperty = true;

                        model.ComponentParent.Add(new NestedParentReferenceModel(prop, nestedParentAtt));
                    }
                    else if (attribute is JoinedKeyAttribute)
                    {
                        JoinedKeyAttribute propAtt = attribute as JoinedKeyAttribute;
                        isArProperty = true;

                        if (model.Key != null)
                        {
                            throw new ActiveRecordException("You can't specify more than one JoinedKeyAttribute. " +
                                                            "Check type " + model.Type.FullName);
                        }

                        model.Key = new KeyModel(prop, propAtt);
                    }
                    else if (attribute is VersionAttribute)
                    {
                        VersionAttribute propAtt = attribute as VersionAttribute;
                        isArProperty = true;

                        if (model.Version != null)
                        {
                            throw new ActiveRecordException("You can't specify more than one VersionAttribute. " +
                                                            "Check type " + model.Type.FullName);
                        }

                        model.Version = new VersionModel(prop, propAtt);
                    }
                    else if (attribute is TimestampAttribute)
                    {
                        TimestampAttribute propAtt = attribute as TimestampAttribute;
                        isArProperty = true;

                        if (model.Timestamp != null)
                        {
                            throw new ActiveRecordException("You can't specify more than one TimestampAttribute. " +
                                                            "Check type " + model.Type.FullName);
                        }

                        model.Timestamp = new TimestampModel(prop, propAtt);
                    }
                    // Relations
                    else if (attribute is OneToOneAttribute)
                    {
                        OneToOneAttribute propAtt = attribute as OneToOneAttribute;
                        isArProperty = true;

                        model.OneToOnes.Add(new OneToOneModel(prop, propAtt));
                    }
                    else if (attribute is BelongsToAttribute)
                    {
                        BelongsToAttribute propAtt = attribute as BelongsToAttribute;
                        isArProperty = true;

                        BelongsToModel btModel = new BelongsToModel(prop, propAtt);
                        model.BelongsTo.Add(btModel);
                        model.BelongsToDictionary[prop.Name] = btModel;

                        if (extension != null)
                        {
                            extension.ProcessBelongsTo(prop, btModel, model);
                        }
                    }
                    // The ordering is important here, HasManyToAny must comes before HasMany!
                    else if (attribute is HasManyToAnyAttribute)
                    {
                        HasManyToAnyAttribute propAtt = attribute as HasManyToAnyAttribute;
                        isArProperty = true;

                        hasManyToAnyModel = new HasManyToAnyModel(prop, propAtt);
                        model.HasManyToAny.Add(hasManyToAnyModel);
                        model.HasManyToAnyDictionary[prop.Name] = hasManyToAnyModel;

                        CollectMetaValues(hasManyToAnyModel.MetaValues, prop);

                        if (extension != null)
                        {
                            extension.ProcessHasManyToAny(prop, hasManyToAnyModel, model);
                        }
                    }
                    else if (attribute is HasManyAttribute)
                    {
                        HasManyAttribute propAtt = attribute as HasManyAttribute;
                        isArProperty = true;

                        HasManyModel hasManyModel = new HasManyModel(prop, propAtt, model);
                        if (propAtt.DependentObjects)
                        {
                            ActiveRecordModel dependentObjectModel = new ActiveRecordModel(propAtt.MapType);
                            dependentObjectModel.IsNestedType          = true;
                            dependentObjectModel.IsNestedCompositeType = true;
                            ProcessProperties(propAtt.MapType, dependentObjectModel);

                            hasManyModel.DependentObjectModel = new DependentObjectModel(prop, propAtt, dependentObjectModel);
                        }
                        model.HasMany.Add(hasManyModel);
                        model.HasManyDictionary[prop.Name] = hasManyModel;

                        if (extension != null)
                        {
                            extension.ProcessHasMany(prop, hasManyModel, model);
                        }
                    }
                    else if (attribute is HasAndBelongsToManyAttribute)
                    {
                        HasAndBelongsToManyAttribute propAtt = attribute as HasAndBelongsToManyAttribute;
                        isArProperty = true;

                        HasAndBelongsToManyModel habtManyModel = new HasAndBelongsToManyModel(prop, propAtt);
                        model.HasAndBelongsToMany.Add(habtManyModel);
                        model.HasAndBelongsToManyDictionary[prop.Name] = habtManyModel;

                        if (extension != null)
                        {
                            extension.ProcessHasAndBelongsToMany(prop, habtManyModel, model);
                        }
                    }
                    else if (attribute is Any.MetaValueAttribute)
                    {
                        if (prop.GetCustomAttributes(typeof(HasManyToAnyAttribute), false).Length == 0 &&
                            prop.GetCustomAttributes(typeof(AnyAttribute), false).Length == 0
                            )
                        {
                            throw new ActiveRecordException(
                                      "You can't specify an Any.MetaValue without specifying the Any or HasManyToAny attribute. " +
                                      "Check type " + prop.DeclaringType.FullName);
                        }
                    }
                    else if (attribute is CompositeUserTypeAttribute)
                    {
                        CompositeUserTypeAttribute propAtt = attribute as CompositeUserTypeAttribute;
                        isArProperty = true;

                        model.CompositeUserType.Add(new CompositeUserTypeModel(prop, prop.PropertyType, propAtt));
                    }

                    if (attribute is CollectionIDAttribute)
                    {
                        CollectionIDAttribute propAtt = attribute as CollectionIDAttribute;

                        model.CollectionIDs.Add(new CollectionIDModel(prop, propAtt));
                    }
                    if (attribute is HiloAttribute)
                    {
                        HiloAttribute propAtt = attribute as HiloAttribute;

                        model.Hilos.Add(new HiloModel(prop, propAtt));
                    }
                }

                if (!isArProperty)
                {
                    model.NotMappedProperties.Add(prop);
                }
            }
        }
Exemple #10
0
 public virtual void VisitBelongsTo(BelongsToModel model)
 {
 }
 /// <summary>
 /// Visits the belongs to.
 /// </summary>
 /// <param name="model">The model.</param>
 public virtual void VisitBelongsTo(BelongsToModel model)
 {
 }
		public String CreateControl(ActiveRecordModel model, String prefix, 
		                            BelongsToModel belongsToModel, object instance)
		{
			stringBuilder.Length = 0;

			PropertyInfo prop = belongsToModel.Property;
			
			prefix += "." + prop.Name;

			ActiveRecordModel otherModel = ActiveRecordModel.GetModel(belongsToModel.BelongsToAtt.Type);

			PrimaryKeyModel keyModel = ObtainPKProperty(otherModel);

			if (otherModel == null || keyModel == null)
			{
				return "Model not found or PK not found";
			}

			object[] items = CommonOperationUtils.FindAll(otherModel.Type);

			String propName = CreatePropName(model, prefix, keyModel.Property.Name);

			stringBuilder.Append(LabelFor(propName, TextHelper.PascalCaseToWord(prop.Name) + ": &nbsp;"));
			
			IDictionary attrs = new HybridDictionary(true);
			
			attrs["value"] = keyModel.Property.Name;
			
			if (!belongsToModel.BelongsToAtt.NotNull)
			{
				attrs.Add("firstOption", "Empty");
				attrs.Add("firstOptionValue", "");
			}

			stringBuilder.Append(Select(propName, items, attrs));

			return stringBuilder.ToString();
		}
		public bool CanHandle(BelongsToModel model)
		{
			return CheckModelAndKeyAreAccessible(model.BelongsToAtt.Type);
		}
        /// <summary>
        /// Visits the belongs to.
        /// </summary>
        /// <param name="model">The model.</param>
        public override void VisitBelongsTo(BelongsToModel model)
        {
            if (!AppliesToCurrentTable(model.BelongsToAtt))
            {
                return;
            }

            String cascade = TranslateCascadeEnum(model.BelongsToAtt.Cascade);
            String fetch = TranslateFetch(model.BelongsToAtt.Fetch);
            String notFoundMode = TranslateNotFoundBehaviourEnum(model.BelongsToAtt.NotFoundBehaviour);
            String lazy = TranslateLazy(model.BelongsToAtt.Lazy);

            if (model.BelongsToAtt.Column == null)
            {
                AppendStartTag("many-to-one",
                        MakeAtt("name", model.Property.Name),
                        MakeAtt("access", model.BelongsToAtt.AccessString),
                        MakeAtt("class", MakeTypeName(model.BelongsToAtt.Type)),
                        WriteIfTrue("not-null", model.BelongsToAtt.NotNull),
                        WriteIfTrue("unique", model.BelongsToAtt.Unique),
                        WriteIfNonNull("unique-key", model.BelongsToAtt.UniqueKey),
                        WriteIfNonNull("index", model.BelongsToAtt.Index),
                        WriteIfNonNull("cascade", cascade),
                        WriteIfNonNull("fetch", fetch),
                        WriteIfNonNull("lazy", lazy),
                        WriteIfFalse("update", model.BelongsToAtt.Update),
                        WriteIfFalse("insert", model.BelongsToAtt.Insert),
                        WriteIfNonNull("property-ref", model.BelongsToAtt.PropertyRef),
                        WriteIfNonNull("foreign-key", model.BelongsToAtt.ForeignKey),
                        WriteIfFalse("optimistic-lock", model.BelongsToAtt.OptimisticLock),
                        WriteIfNonNull("not-found", notFoundMode));
                Ident();
                WriteCompositeColumns(model.BelongsToAtt.CompositeKeyColumns);
                Dedent();
                Append("</many-to-one>");
            }
            else
            {
                AppendFullTag("many-to-one",
                        MakeAtt("name", model.Property.Name),
                        MakeAtt("access", model.BelongsToAtt.AccessString),
                        MakeAtt("class", MakeTypeName(model.BelongsToAtt.Type)),
                        MakeAtt("column", model.BelongsToAtt.Column),
                        WriteIfFalse("insert", model.BelongsToAtt.Insert),
                        WriteIfFalse("update", model.BelongsToAtt.Update),
                        WriteIfNonNull("property-ref", model.BelongsToAtt.PropertyRef),
                        WriteIfTrue("not-null", model.BelongsToAtt.NotNull),
                        WriteIfTrue("unique", model.BelongsToAtt.Unique),
                        WriteIfNonNull("unique-key", model.BelongsToAtt.UniqueKey),
                        WriteIfNonNull("foreign-key", model.BelongsToAtt.ForeignKey),
                        WriteIfNonNull("index", model.BelongsToAtt.Index),
                        WriteIfNonNull("cascade", cascade),
                        WriteIfNonNull("fetch", fetch),
                        WriteIfNonNull("lazy", lazy),
                        WriteIfFalse("optimistic-lock", model.BelongsToAtt.OptimisticLock),
                        WriteIfNonNull("not-found", notFoundMode));
            }
        }
        public override void VisitHasMany(HasManyModel model)
        {
            model.HasManyAtt.RelationType = GuessRelation(model.Property, model.HasManyAtt.RelationType);

            if (model.HasManyAtt.RelationType == RelationType.IdBag)
            {
                throw new ActiveRecordException(String.Format(
                                                    "You can't use idbags in a many to one association (HasMany) {0}.{1}  ",
                                                    model.Property.DeclaringType.Name, model.Property.Name));
            }

            if (model.HasManyAtt.RelationType == RelationType.Map && model.HasManyAtt.Index == null)
            {
                throw new ActiveRecordException(String.Format(
                                                    "A HasMany with type Map requires that you specify an 'Index', use the Index property {0}.{1}  ",
                                                    model.Property.DeclaringType.Name, model.Property.Name));
            }

            // Infer table and column based on possible belongs to
            // on the target class

            String table     = model.HasManyAtt.Table;
            String keyColumn = model.HasManyAtt.ColumnKey;

            ActiveRecordModel target = arCollection[model.HasManyAtt.MapType];

            if ((table == null || keyColumn == null) && target == null)
            {
                throw new ActiveRecordException(String.Format(
                                                    "ActiveRecord tried to infer details about the relation {0}.{1} but " +
                                                    "it could not find information about the specified target type {2}",
                                                    model.Property.DeclaringType.Name, model.Property.Name, model.HasManyAtt.MapType));
            }

            BelongsToModel targetBtModel = null;

            if (target != null)
            {
                foreach (BelongsToModel btModel in target.BelongsTo)
                {
                    if (btModel.BelongsToAtt.Type == model.Property.DeclaringType ||
                        btModel.Property.PropertyType == model.Property.DeclaringType)
                    {
                        targetBtModel = btModel; break;
                    }
                }
            }

            if ((table == null || keyColumn == null) && targetBtModel == null)
            {
                throw new ActiveRecordException(String.Format(
                                                    "ActiveRecord tried to infer details about the relation {0}.{1} but " +
                                                    "it could not find a 'BelongsTo' mapped property in the target type {2}",
                                                    model.Property.DeclaringType.Name, model.Property.Name, model.HasManyAtt.MapType));
            }

            if (target != null)
            {
                VisitModel(target);
            }

            if (table == null)
            {
                table = target.ActiveRecordAtt.Table;
            }

            if (keyColumn == null)
            {
                keyColumn = targetBtModel.BelongsToAtt.Column;
            }

            model.HasManyAtt.Table     = table;
            model.HasManyAtt.ColumnKey = keyColumn;
        }
        /// <summary>
        /// Visits the has many.
        /// </summary>
        /// <remarks>
        /// Guess the type of the relation, if not specified explicitly
        /// Verify that the assoication is valid on [HasMany]
        /// Validate that required information is specified
        /// Infer the other side of the assoication and grab require data from it
        /// </remarks>
        /// <param name="model">The model.</param>
        public override void VisitHasMany(HasManyModel model)
        {
            if (model.HasManyAtt.MapType == null)
            {
                model.HasManyAtt.MapType = GuessType(null, model.Property.PropertyType);
            }

            model.HasManyAtt.RelationType = GuessRelation(model.Property, model.HasManyAtt.RelationType);

            // Guess the details about a map relation if needed
            if (model.HasManyAtt.RelationType == RelationType.Map)
            {
                if (string.IsNullOrEmpty(model.HasManyAtt.Table))
                {
                    model.HasManyAtt.Table = string.Format("{0}_{1}", model.Property.ReflectedType.Name, model.Property.Name);
                }
                if (model.HasManyAtt.IndexType == null)
                {
                    model.HasManyAtt.IndexType = GetIndexTypeFromDictionary(model.Property.PropertyType).Name;
                }
                if (model.HasManyAtt.MapType == null)
                {
                    model.HasManyAtt.MapType = GetMapTypeFromDictionary(model.Property.PropertyType);
                }
            }

            if (model.HasManyAtt.RelationType == RelationType.IdBag)
            {
                throw new ActiveRecordException(String.Format(
                                                    "You can't use idbags in a many to one association (HasMany) {0}.{1}  ",
                                                    model.Property.DeclaringType.Name, model.Property.Name));
            }

            if (model.HasManyAtt.RelationType == RelationType.Map && model.HasManyAtt.Index == null)
            {
                throw new ActiveRecordException(String.Format(
                                                    "A HasMany with type Map requires that you specify an 'Index', use the Index property {0}.{1}  ",
                                                    model.Property.DeclaringType.Name, model.Property.Name));
            }

            if (model.HasManyAtt.RelationType == RelationType.List && model.HasManyAtt.Index == null)
            {
                throw new ActiveRecordException(String.Format(
                                                    "A HasMany with type List requires that you specify an 'Index', use the Index property {0}.{1}  ",
                                                    model.Property.DeclaringType.Name, model.Property.Name));
            }

            // try to guess an <element> mapping if none of the mapping properties was set
            if (model.HasManyAtt.MapType.IsValueType && string.IsNullOrEmpty(model.HasManyAtt.Element) &&
                model.HasManyAtt.ElementType == null && string.IsNullOrEmpty(model.HasManyAtt.ColumnKey))
            {
                GuessElementMappingBasedOnEnum(model);
            }

            // Infer table and column based on possible belongs to
            // on the target class

            String table     = model.HasManyAtt.Table;
            String keyColumn = model.HasManyAtt.ColumnKey;

            String[] compositeKeyColumnKeys = model.HasManyAtt.CompositeKeyColumnKeys;

            Type type = model.HasManyAtt.MapType;
            ActiveRecordModel target = arCollection[type];

            if ((table == null || (keyColumn == null && compositeKeyColumnKeys == null)) && target == null)
            {
                throw new ActiveRecordException(String.Format(
                                                    "ActiveRecord tried to infer details about the relation {0}.{1} but " +
                                                    "it could not find information about the specified target type {2}. If you have mapped a Collection or Dictionary of value types, please make sure you have specified the Table property.",
                                                    model.Property.DeclaringType.Name, model.Property.Name, type));
            }

            BelongsToModel    targetBtModel = null;
            ActiveRecordModel tmpModel      = target;

            while (tmpModel != null && targetBtModel == null)
            {
                foreach (BelongsToModel btModel in tmpModel.BelongsTo)
                {
                    if (btModel.BelongsToAtt.Type != model.Property.DeclaringType &&
                        btModel.BelongsToAtt.Type != model.ContainingTypeModel.Type &&
                        btModel.Property.PropertyType != model.Property.DeclaringType &&
                        btModel.Property.PropertyType != model.ContainingTypeModel.Type)
                    {
                        continue;
                    }
                    targetBtModel = btModel;
                    break;
                }

                tmpModel = tmpModel.Parent;
            }

            if ((table == null || (keyColumn == null && compositeKeyColumnKeys == null)) && targetBtModel == null)
            {
                throw new ActiveRecordException(String.Format(
                                                    "ActiveRecord tried to infer details about the relation {0}.{1} but " +
                                                    "it could not find a 'BelongsTo' mapped property in the target type {2}",
                                                    model.Property.DeclaringType.Name, model.Property.Name, type));
            }

            if (target != null)
            {
                VisitModel(target);
            }
            else if (model.HasManyAtt.DependentObjects)
            {
                VisitDependentObject(model.DependentObjectModel);
            }

            if (table == null)
            {
                table = target.ActiveRecordAtt.Table;
            }

            if (targetBtModel != null)
            {
                if (keyColumn == null && targetBtModel.BelongsToAtt.CompositeKeyColumns == null)
                {
                    keyColumn = targetBtModel.BelongsToAtt.Column;
                }
                else
                {
                    compositeKeyColumnKeys = targetBtModel.BelongsToAtt.CompositeKeyColumns;
                }
            }

            model.HasManyAtt.Table = table;

            if (keyColumn != null)
            {
                model.HasManyAtt.ColumnKey = keyColumn;
            }
            else
            {
                model.HasManyAtt.CompositeKeyColumnKeys = compositeKeyColumnKeys;
            }
        }