blob: b226ec194bdae56c668525360b5b00afa79d0c93 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.Generic;
using System.Reflection;
using Org.Apache.REEF.Utilities.Logging;
using Org.Apache.REEF.Wake.Remote.Proto;
namespace Org.Apache.REEF.Wake.Remote.Impl
{
/// <summary>
/// Encoder using the WakeTuple protocol buffer
/// (class name and bytes)
/// </summary>
public class MultiEncoder<T> : IEncoder<T>
{
private static readonly Logger Logger = Logger.GetLogger(typeof(MultiEncoder<>));
private readonly Dictionary<Type, object> _encoderMap;
private readonly Dictionary<Type, string> _nameMap;
/// <summary>
/// Constructs an encoder that encodes an object to bytes based on the class name
/// </summary>
public MultiEncoder()
{
_encoderMap = new Dictionary<Type, object>();
_nameMap = new Dictionary<Type, string>();
}
public void Register<U>(IEncoder<U> encoder) where U : T
{
_encoderMap[typeof(U)] = encoder;
_nameMap[typeof(U)] = typeof(U).ToString();
}
public void Register<U>(IEncoder<U> encoder, string name) where U : T
{
_encoderMap[typeof(U)] = encoder;
_nameMap[typeof(U)] = name;
Logger.Log(Level.Verbose, "Registering name for " + name);
}
/// <summary>Encodes an object to a byte array</summary>
/// <param name="obj"></param>
public byte[] Encode(T obj)
{
// Find encoder for object type
object encoder;
if (!_encoderMap.TryGetValue(obj.GetType(), out encoder))
{
return null;
}
// Invoke encoder for this type
Type handlerType = typeof(IEncoder<>).MakeGenericType(new[] { obj.GetType() });
MethodInfo info = handlerType.GetMethod("Encode");
byte[] data = (byte[])info.Invoke(encoder, new[] { (object)obj });
// Serialize object type and object data into well known tuple
// To decode, deserialize the tuple, get object type, and look up the
// decoder for that type
string name = _nameMap[obj.GetType()];
Logger.Log(Level.Verbose, "Encoding name for " + name);
WakeTuplePBuf pbuf = new WakeTuplePBuf { className = name, data = data };
pbuf.className = name;
pbuf.data = data;
return pbuf.Serialize();
}
}
}