// $Id$
//
// 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.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Etch.Msg;
using Etch.Util;
namespace Etch.Support
{
/// Default implementation of ValueFactory which provides some dynamic type and field support, as well
/// as standard value conversions and import and export.
public class DefaultValueFactory : ValueFactory
{
private const String ETCH_RUNTIME_EXCEPTION_TYPE_NAME = "_Etch_RuntimeException";
private const String ETCH_LIST_TYPE_NAME = "_Etch_List";
private const String ETCH_MAP_TYPE_NAME = "_Etch_Map";
private const String ETCH_SET_TYPE_NAME = "_Etch_Set";
private const String ETCH_DATETIME_TYPE_NAME = "_Etch_Datetime";
private const String ETCH_AUTH_EXCEPTION_TYPE_NAME = "_Etch_AuthException";
private const String ETCH_EXCEPTION_MESSAGE_NAME = "_exception";
private const String MSG_FIELD_NAME = "msg";
private const String MESSAGE_ID_FIELD_NAME = "_messageId";
private const String IN_REPLY_TO_FIELD_NAME = "_inReplyTo";
private const String RESULT_FIELD_NAME = "result";
public static void Init( TypeMap types, Class2TypeMap class2type )
{
RuntimeExceptionSerializer.Init(
types.Get(ETCH_RUNTIME_EXCEPTION_TYPE_NAME), class2type);
ListSerializer.Init(
types.Get(ETCH_LIST_TYPE_NAME), class2type);
MapSerializer.Init(
types.Get(ETCH_MAP_TYPE_NAME), class2type);
/* SetSerializer.Init(
types.Get(ETCH_SET_TYPE_NAME), class2type); */
DateSerializer.Init(
types.Get(ETCH_DATETIME_TYPE_NAME), class2type);
AuthExceptionSerializer.Init(
types.Get(ETCH_AUTH_EXCEPTION_TYPE_NAME), class2type);
XType t3 = types.Get(ETCH_EXCEPTION_MESSAGE_NAME);
t3.PutValidator(_mf_result, Validator_RuntimeException.Get());
t3.PutValidator(_mf__messageId, Validator_long.Get(0));
t3.PutValidator(_mf__inReplyTo, Validator_long.Get(0));
}
/// The msg field of the standard unchecked exception.
public readonly static Field _mf_msg = new Field(MSG_FIELD_NAME);
/// The well-known _messageId field.
public readonly static Field _mf__messageId = new Field(MESSAGE_ID_FIELD_NAME);
/// The well-known _inReplyTo field.
public readonly static Field _mf__inReplyTo = new Field(IN_REPLY_TO_FIELD_NAME);
/// The well-known result field
public readonly static Field _mf_result = new Field(RESULT_FIELD_NAME);
private readonly TypeMap types;
private readonly TypeMap dynamicTypes = new TypeMap();
private readonly Class2TypeMap class2type;
private readonly XType _mt__Etch_RuntimeException;
private readonly XType _mt__Etch_AuthException;
private readonly XType _mt__exception;
private readonly XType _mt__Etch_List;
private readonly XType _mt__Etch_Map;
private readonly XType _mt__Etch_Set;
private readonly XType _mt__Etch_Datetime;
///
/// Constructs the DefaultValueFactory.
///
///
///
///
public DefaultValueFactory(String uri, TypeMap types, Class2TypeMap class2type)
{
URL u = new URL(uri);
String s = u.GetTerm("DefaultValueFactory.level", "FULL");
level = (Validator.Level) Enum.Parse(typeof(Validator.Level), s);
this.types = types;
this.class2type = class2type;
_mt__Etch_RuntimeException = types.Get(ETCH_RUNTIME_EXCEPTION_TYPE_NAME);
_mt__Etch_AuthException = types.Get(ETCH_AUTH_EXCEPTION_TYPE_NAME);
_mt__exception = types.Get(ETCH_EXCEPTION_MESSAGE_NAME);
_mt__Etch_List = types.Get(ETCH_LIST_TYPE_NAME);
_mt__Etch_Map = types.Get(ETCH_MAP_TYPE_NAME);
_mt__Etch_Set = types.Get(ETCH_SET_TYPE_NAME);
_mt__Etch_Datetime = types.Get(ETCH_DATETIME_TYPE_NAME);
}
public XType get_mt__Etch_RuntimeException()
{
return _mt__Etch_RuntimeException;
}
public XType get_mt__Etch_AuthException()
{
return _mt__Etch_AuthException;
}
public XType get_mt__exception()
{
return _mt__exception;
}
public XType Get_mt__Etch_List()
{
return _mt__Etch_List;
}
public XType Get_mt__Etch_Map()
{
return _mt__Etch_Map;
}
public XType Get_mt__Etch_Set()
{
return _mt__Etch_Set;
}
public XType Get_mt__Etch_Datetime()
{
return _mt__Etch_Datetime;
}
protected void addMixin(ValueFactory vf)
{
ValueFactory[] newMixins = new ValueFactory[mixins.Length + 1];
System.Array.Copy(mixins,newMixins,mixins.Length);
newMixins[mixins.Length] = vf;
mixins = newMixins;
}
private ValueFactory[] mixins = { };
/////////////////////
// STRING ENCODING //
/////////////////////
public Encoding GetStringEncoding()
{
return Encoding.UTF8;
}
////////////////
// MESSAGE ID //
////////////////
public long? GetMessageId(Message msg)
{
return (long?)(msg.Get(_mf__messageId));
}
public void SetMessageId(Message msg, long? msgid)
{
msg[_mf__messageId] = msgid;
}
public Field Get_mf__messageId()
{
return _mf__messageId;
}
/////////////////
// IN REPLY TO //
/////////////////
public long? GetInReplyTo(Message msg)
{
return (long?)(msg.Get(_mf__inReplyTo));
}
public void SetInReplyTo(Message msg, long? msgid)
{
msg[_mf__inReplyTo] = msgid;
}
public Field Get_mf__inReplyTo()
{
return _mf__inReplyTo;
}
//////////////////////
// VALUE CONVERSION //
//////////////////////
public Object ImportCustomValue( StructValue sv )
{
ImportExportHelper helper = sv.GetXType.GetImportExportHelper();
if ( helper == null )
return null;
return helper.ImportValue( sv );
}
#region ValueFactory members
public StructValue ExportCustomValue( Object value )
{
Type clss = value.GetType();
XType type;
try
{
type = GetCustomStructType(value.GetType());
}
catch (KeyNotFoundException)
{
type = null;
}
if (type == null && clss == typeof(StructValue) )
{
StructValue struct1 = (StructValue) value;
type = struct1.GetXType;
}
if (type == null)
// if (value is Exception)
if (typeof(Exception).IsAssignableFrom(clss))
type = _mt__Etch_RuntimeException;
else if (typeof(IList).IsAssignableFrom(clss))
type = _mt__Etch_List;
else if (typeof(IDictionary).IsAssignableFrom(clss))
type = _mt__Etch_Map;
// Need to add set, but in 2.0 there is no set so just use keys of IDictionary,
else
return null;
ImportExportHelper helper = type.GetImportExportHelper();
if (helper == null)
return null;
return helper.ExportValue( this, value );
}
public XType GetCustomStructType( Type t )
{
XType type = class2type.Get( t );
if (type != null)
return type;
foreach (ValueFactory vf in mixins)
if ((type = vf.GetCustomStructType( t )) != null)
return type;
return null;
}
public XType GetType( int id )
{
XType type = types.Get(id);
if (type != null)
return type;
foreach (ValueFactory vf in mixins)
if ((type = vf.GetType(id)) != null)
return type;
lock (dynamicTypes)
{
return dynamicTypes.Get(id);
}
}
public XType GetType( string name )
{
XType type = types.Get(name);
if (type != null)
return type;
foreach (ValueFactory vf in mixins)
if ((type = vf.GetType(name)) != null)
return type;
lock (dynamicTypes)
{
return dynamicTypes.Get(name);
}
}
public void AddType(XType type)
{
lock (dynamicTypes)
{
dynamicTypes.Add(type);
}
}
public ICollection GetTypes()
{
ICollection values = types.Values();
foreach (ValueFactory vf in mixins)
foreach (XType x in vf.GetTypes())
if (!values.Contains(x))
values.Add(x);
lock (dynamicTypes)
{
foreach (XType x in dynamicTypes.Values())
if (!values.Contains(x))
values.Add(x);
}
return values;
}
#endregion
public void LockDynamicTypes()
{
dynamicTypes.Lock();
}
public void UnlockDynamicTypes()
{
// TODO dynamicTypes.Unlock();
throw new NotSupportedException("The method or operation is not implemented.");
}
public Validator.Level GetLevel()
{
return level;
}
public Validator.Level SetLevel(Validator.Level level)
{
Validator.Level oldLevel = this.level;
this.level = level;
return oldLevel;
}
private Validator.Level level = Validator.Level.FULL;
}
}