## Copyright 2007-2008 Cisco Systems Inc.
##
## Licensed under the Apache License, Version 2.0 (the "License"); you may not
## use this file except in compliance with the License. You may obtain a copy
## of the License at
##
##      http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
## License for the specific language governing permissions and limitations
## under the License.
// This file automatically generated by:
//   $version
//   $now
// This file is automatically created and should not be edited!

using System;
using System.Collections.Generic;
using Org.Apache.Etch.Bindings.Csharp.Msg;
using Org.Apache.Etch.Bindings.Csharp.Support;
#foreach( $n in $intf.iterator() )
#if ($n.isExtern())
#if ($n.hasImport( $helper ))
using $n.getImport( $helper );
#end
#if ($n.hasSerializerImport( $helper ))
using $n.getSerializerImport( $helper );
#end
#end
#end
#set( $i = $intf.name() )
#set( $vf = "ValueFactory$i" )

namespace $intf.parent().name()
{

///<summary>ValueFactory for $i.</summary>
public class ${vf} : DefaultValueFactory
{
	private readonly static TypeMap types = new TypeMap();
    
	private readonly static Class2TypeMap class2type = new Class2TypeMap();
	 
	///<summary>Constructs ${vf}.</summary>
	public ${vf}(string uri) : base(uri, types, class2type)
	{
#foreach ( $n in $intf.iterator() )
#if ($n.isMixin())
#set( $m = $n.getModule() )
#set( $s = $m.iterator().next() )
		addMixin( new ${m.name()}.ValueFactory${s.name()}(uri) );
#end
#end		
	}
	
	private static void InitTypes()
	{
#foreach ( $n in $intf.iterator() )
#if ($n.isEnumx() || $n.isStruct() || $n.isExtern() || $n.isExcept() || $n.isMessage())
		$n.vname( $helper ) =  types.Get( "$n.fqname()" );
#end
#end
	}
	
	private static void InitResults() 
	{
#foreach ( $n in $intf.iterator() )
#if ($n.isMessage())
		${n.vname( $helper )}.SetDirection( Direction.$n.msgDir() );
#if (!$n.isHidden())
#if ($n.isQueuedAsyncReceiver())
		${n.vname( $helper )}.SetAsyncMode( AsyncMode.QUEUED );
#elseif ($n.isFreeAsyncReceiver())
		${n.vname( $helper )}.SetAsyncMode( AsyncMode.FREE );
#else
		${n.vname( $helper )}.SetAsyncMode( AsyncMode.NONE );
#end
#if (!$n.isOneway())
#set($r = $n.getResultMessage())
		${n.vname( $helper )}.SetResult( $r.vname( $helper ) );
		${r.vname( $helper )}.Timeout = $n.getTimeout();
#end
#end
#end
#end	
	}
	
	private static void InitFields()
	{
#set( $x = $params.clear() )
## standard params from DefaultValueFactory
#set( $x = $params.add( "msg" ) )
#set( $x = $params.add( "result" ) )
#foreach( $n in $intf.iterator() )
#if ($n.isEnumx() || $n.isStruct() || $n.isExcept() || $n.isMessage())
#foreach( $param in $n.iterator() )
#if (!$params.contains($param.name().name()))
#set( $x = $params.add($param.name().name()) )
		$param.vname( $helper ) = new Field( "$param.name().name()" );
#end
#end
#end
#end
#foreach ( $n in $intf.iterator() )
#if ($n.isMessage())
#if (!$n.isHidden())
#if (!$n.isOneway())
#set( $r = $n.getResultMessage() )
		${r.vname( $helper )}.ResponseField = _mf_result;
#end
#end
#end
#end	
	}
	
	private static void InitParams()
	{
#foreach( $n in $intf.iterator() )
#if ($n.isEnumx() || $n.isStruct() || $n.isExcept() || $n.isMessage())
#if ($n.isStruct() || $n.isExcept())
#foreach( $param in $n.getAllParameters() )
		${n.vname( $helper )}.PutValidator( $param.vname( $helper ), $helper.getValidator( $param ) );
#end
#else
		// params for $n.name()
#foreach( $param in $n.iterator() )
		${n.vname( $helper )}.PutValidator( $param.vname( $helper ), $helper.getValidator( $param ) );
#end
#end
#if ($n.isMessage())
		${n.vname( $helper )}.PutValidator( _mf__messageId, Validator_long.Get( 0 ) );
#if ($n.isHidden())
#set( $param = $n.getResultParam() )
#set( $reqMsg = $n.getRequestMessage() )
#foreach( $t in $reqMsg.thrown().iterator() )
		${n.vname( $helper )}.PutValidator( $param.vname( $helper ), $helper.getValidator( $t ) ); // thrown $t.name()
#end
		${n.vname( $helper )}.PutValidator( $param.vname( $helper ), Validator_RuntimeException.Get() ); // thrown RuntimeException
		${n.vname( $helper )}.PutValidator( _mf__inReplyTo, Validator_long.Get( 0 ) );
#end
#end
#end
#end
	}
	
	
	static ${vf}()
	{
		DefaultValueFactory.Init( types, class2type );
		InitTypes();		
		InitResults();
		InitFields();
		InitParams();

## --- import/export ----

#foreach ( $n in $intf.iterator() )
#if ($n.isStruct() || $n.isExcept())
#set( $tname = $n.efqname( $helper ) )

		class2type.Add( typeof( ${tname} ), ${n.vname( $helper )} );
		${n.vname( $helper )}.SetComponentType( typeof( ${tname} ) );
		#if ($n.hasExtends())
			${n.vname( $helper )}.SetSuperType( $n.getExtends().vname( $helper ) );
		#end
		${n.vname( $helper )}.SetImportExportHelper
			( 
				new ImportExportHelper(
					delegate( ValueFactory vf, Object value ) 
					{
						StructValue sv = new StructValue( ${n.vname( $helper )}, vf );
						$tname v = ($tname) value;
#foreach( $p in $n.getAllParameters()  )
						sv.Add( $p.vname( $helper ), v.$p.name() );
#end
						return sv;
					}, 
					delegate( StructValue sv ) 
					{
						$tname v = new ${tname}();
						#foreach ($p in $n.getAllParameters())
						v.$p.name() = ($helper.getTypeName( $p.type() )) sv.Get( $p.vname( $helper ) );
						#end
						return v;
						
					} 
				)
			);

#elseif ($n.isExtern())
#set( $tname = $n.efqname( $helper ) )
#elseif ($n.isEnumx())
#set( $tname = $n.efqname( $helper ) )

		class2type.Add( typeof( ${tname} ), ${n.vname( $helper )} );
		${n.vname( $helper )}.SetComponentType( typeof( ${tname} ) );
		${n.vname( $helper )}.SetImportExportHelper
			( 
				new ImportExportHelper( 
					
					delegate( ValueFactory vf, Object value ) 
					{
						StructValue sv = new StructValue( ${n.vname( $helper )}, vf );
						${tname} v = (${tname}) value;
						switch (v)
						{
#foreach ($p in $n.iterator())
							case ${tname}.$p.name(): sv.Add( $p.vname( $helper ), true ); break;
#end
						}
						return sv;
					}, 
					delegate( StructValue sv ) 
					{
						// there should only be a single key, so take the first
						// one. if there is no key, means they sent null or the
						// key they sent was unknown.
						Field key = null;
						IEnumerator<Field> myEnum = sv.Keys.GetEnumerator();
						if (myEnum.MoveNext())
							key = myEnum.Current;
						else
							return null;
						
#foreach ($p in $n.iterator())
						if (key == $p.vname( $helper )) return ${tname}.$p.name();
#end
						
						return null;
					} 
				)
			);

#end
#end

		// initialize the extern serializers:
#foreach( $n in $intf.iterator() )
#if ($n.isExtern())
		${n.sname( $helper )}.Init( ${n.vname( $helper )}, class2type );
#end
#end

		// done updating types and fields, lock them.
		types.Lock();
		foreach(XType t in types.Values())
			t.Lock();
		class2type.Lock();


	
	} // end of static constructor

	
	
#foreach ( $n in $intf.iterator() )
#if ($n.isEnumx() || $n.isStruct() || $n.isExtern() || $n.isExcept() || $n.isMessage())
	/// Type for $n.fqname() 
	public static XType $n.vname( $helper );
#end
#end
## ---------------------------------------------------------------------------
	
		
#set( $x = $params.clear() )
## standard params from DefaultValueFactory
#set( $x = $params.add( "msg" ) )
#set( $x = $params.add( "result" ) )
#foreach( $n in $intf.iterator() )
#if ($n.isEnumx() || $n.isStruct() || $n.isExcept() || $n.isMessage())
#foreach( $param in $n.iterator() )
#if (!$params.contains($param.name().name()))
#set( $x = $params.add($param.name().name()) )
	public static Field $param.vname( $helper );
#end
#end
#end
#end
	}
}