private void WriteCollection(ManyRelationCascadeEnum cascadeEnum,
		                             Type targetType, RelationType type, string name,
		                             string accessString, string table, string schema, bool lazy,
		                             bool inverse, string orderBy, string where, string sort,
		                             string columnKey, string[] compositeKeyColumnKeys, string element, string elementType,
		                             string columnRef, string[] compositeKeyColumnRefs,
		                             IVisitable extraModel, string index, string indexType, CacheEnum cache, string cacheregion,
		                             NotFoundBehaviour notFoundBehaviour, FetchEnum fetch, int batchSize, Type collectionType)
		{
			bool extraModelVisited = false;

			String cascade = TranslateCascadeEnum(cascadeEnum);
			String notFoundMode = TranslateNotFoundBehaviourEnum(notFoundBehaviour);
			String fetchString = TranslateFetch(fetch);

			String closingTag = null;

			if (type == RelationType.Guess)
				throw new ActiveRecordException(string.Format("Failed to guess the relation for {0}", name));

			if (type == RelationType.Bag)
			{
				closingTag = "</bag>";

				AppendF("<bag{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}>",
				        MakeAtt("name", name),
				        MakeAtt("access", accessString),
				        WriteIfNonNull("table", table),
				        WriteIfNonNull("schema", schema),
				        MakeAtt("lazy", lazy),
				        WriteIfTrue("inverse", inverse),
				        WriteIfNonNull("cascade", cascade),
				        WriteIfNonNull("order-by", orderBy),
				        WriteIfNonNull("where", where),
				        WriteIfNonNull("fetch", fetchString),						
                        WriteIfNotOne("batch-size", batchSize),
						WriteIfNonNull("collection-type", MakeTypeName(collectionType)));
			}
			else if (type == RelationType.Set)
			{
				closingTag = "</set>";

				AppendF("<set{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}{12}>",
				        MakeAtt("name", name),
				        MakeAtt("access", accessString),
				        WriteIfNonNull("table", table),
				        WriteIfNonNull("schema", schema),
				        MakeAtt("lazy", lazy),
				        WriteIfTrue("inverse", inverse),
				        WriteIfNonNull("cascade", cascade),
				        WriteIfNonNull("order-by", orderBy),
				        WriteIfNonNull("where", where),
				        WriteIfNonNull("sort", sort),
                        WriteIfNonNull("fetch", fetchString),
						WriteIfNotOne("batch-size", batchSize),
						WriteIfNonNull("collection-type", MakeTypeName(collectionType)));
			}
			else if (type == RelationType.IdBag)
			{
				closingTag = "</idbag>";

				AppendF("<idbag{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}>",
				        MakeAtt("name", name),
				        MakeAtt("access", accessString),
				        WriteIfNonNull("table", table),
				        WriteIfNonNull("schema", schema),
				        MakeAtt("lazy", lazy),
				        WriteIfNonNull("cascade", cascade),
				        WriteIfNonNull("order-by", orderBy),
				        WriteIfNonNull("where", where),
                        WriteIfNonNull("fetch", fetchString),
						WriteIfNotOne("batch-size", batchSize),
						WriteIfNonNull("collection-type", MakeTypeName(collectionType)));
				extraModelVisited = true;
				Ident();
				VisitNode(extraModel);
				Dedent();
			}
			else if (type == RelationType.Map)
			{
				closingTag = "</map>";

				AppendF("<map{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}{12}>",
				        MakeAtt("name", name),
				        MakeAtt("access", accessString),
				        WriteIfNonNull("table", table),
				        WriteIfNonNull("schema", schema),
				        MakeAtt("lazy", lazy),
				        WriteIfTrue("inverse", inverse),
				        WriteIfNonNull("cascade", cascade),
				        WriteIfNonNull("order-by", orderBy),
				        WriteIfNonNull("where", where),
				        WriteIfNonNull("sort", sort),
                        WriteIfNonNull("fetch", fetchString),
						WriteIfNotOne("batch-size", batchSize),
						WriteIfNonNull("collection-type", MakeTypeName(collectionType)));
			}
			else if (type == RelationType.List)
			{
				closingTag = "</list>";
				AppendF("<list{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}>",
				        MakeAtt("name", name),
				        MakeAtt("access", accessString),
				        WriteIfNonNull("table", table),
				        WriteIfNonNull("schema", schema),
				        MakeAtt("lazy", lazy),
				        WriteIfTrue("inverse", inverse),
				        WriteIfNonNull("cascade", cascade),
				        WriteIfNonNull("where", where),
                        WriteIfNonNull("fetch", fetchString),
						WriteIfNotOne("batch-size", batchSize),
						WriteIfNonNull("collection-type", MakeTypeName(collectionType)));
			}


			Ident();

			WriteCache(cache, cacheregion);

			if (columnKey == null)
			{
				Append("<key>");
				Ident();
				WriteCompositeColumns(compositeKeyColumnKeys);
				Dedent();
				Append("</key>");
			}
			else
			{
				WriteKey(columnKey);
			}

			if (type == RelationType.Map || type == RelationType.List)
			{
				WriteIndex(index, indexType);
			}

			if (element != null || elementType != null)
			{
				WriteElement(element, elementType, targetType);
			}
			else if (columnRef == null && compositeKeyColumnRefs == null)
			{
				if (extraModel == null)
				{
					WriteOneToMany(targetType, notFoundMode);
				}
				else if (!extraModelVisited)
				{
					VisitNode(extraModel);
				}
			}
			else
			{
				if (columnRef != null)
				{
					WriteManyToMany(targetType, columnRef, notFoundMode);
				}
				else
				{
					WriteManyToMany(targetType, compositeKeyColumnRefs, notFoundMode);
				}
			}

			Dedent();

			Append(closingTag);
		}
		private static string TranslateFetch(FetchEnum fetch)
		{
			switch(fetch)
			{
				case FetchEnum.Select:
					return "select";
				case FetchEnum.Join:
					return "join";
				case FetchEnum.SubSelect:
					return "subselect";
				default:
					return null;
			}
		}