// $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; } }