using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Tango.PMR.Common;
using Tango.PMR.DataStore;
using Tango.PMR.Integration;
namespace Tango.PMR
{
///
/// Contains helper class for encoding and decoding PMR messages.
///
public static class MessageFactory
{
private static Dictionary _pmrTypes;
private static Dictionary _pmrDataStoreTypes;
private static MethodInfo _parseTangoMessageMethod;
static MessageFactory()
{
_parseTangoMessageMethod = typeof(MessageFactory).GetMethod("ParseTangoMessage", BindingFlags.Public | BindingFlags.Static);
_pmrTypes = new Dictionary();
var types = typeof(MessageFactory).Assembly.GetTypes().ToList();
foreach (var value in Enum.GetValues(typeof(MessageType)).OfType())
{
var type = types.SingleOrDefault(x => x.Name == value.ToOriginalName());
if (type != null)
{
_pmrTypes.Add(value, type);
}
}
_pmrDataStoreTypes = new Dictionary();
foreach (var value in Enum.GetValues(typeof(DataStoreMessageType)).OfType())
{
var type = types.SingleOrDefault(x => x.Name == value.ToOriginalName());
if (type != null)
{
_pmrDataStoreTypes.Add(value, type);
}
}
}
///
/// Returns the matching PMR type from the PMR message type.
///
/// Type of the message.
///
public static Type GetPMRTypeFromMessageType(MessageType messageType)
{
return _pmrTypes[messageType];
}
///
/// Returns the matching PMR type from the PMR message type.
///
/// Type of the message.
///
public static Type GetDataStorePMRTypeFromDataStoreMessageType(DataStoreMessageType messageType)
{
return _pmrDataStoreTypes[messageType];
}
///
/// Creates a new .
///
///
///
public static TangoMessage CreateTangoMessage() where T : IMessage
{
TangoMessage tango = new TangoMessage(Activator.CreateInstance(), ParseMessageType(typeof(T).Name));
return tango;
}
///
/// Creates a new .
///
///
///
public static TangoMessage CreateTangoMessage(T message) where T : IMessage
{
TangoMessage tango = CreateTangoMessage();
tango.Message = message;
return tango;
}
///
/// Creates a new .
///
///
///
public static TangoMessage CreateTangoMessage(String token) where T : IMessage
{
TangoMessage tango = CreateTangoMessage();
tango.Container.Token = token;
return tango;
}
///
/// Creates a new .
///
///
///
public static TangoMessage CreateTangoMessage(T message, String token) where T : IMessage
{
TangoMessage tango = CreateTangoMessage(token);
tango.Message = message;
return tango;
}
///
/// Parses the specified tango message type from the specified byte array.
///
///
/// The data.
///
public static TangoMessage ParseTangoMessage(byte[] data) where T : IMessage
{
MessageContainer container = MessageContainer.Parser.ParseFrom(data);
MessageParser parser = new MessageParser(() => Activator.CreateInstance());
TangoMessage tango = new TangoMessage(container, parser.ParseFrom(container.Data));
return tango;
}
///
/// Parses the specified tango message type from the specified message container.
///
///
/// The data.
///
public static TangoMessage ParseTangoMessageFromContainer(MessageContainer container) where T : IMessage
{
MessageParser parser = new MessageParser(() => Activator.CreateInstance());
TangoMessage tango = new TangoMessage(container, parser.ParseFrom(container.Data));
return tango;
}
///
/// Parses an unknown tango message from the specified byte array.
///
/// The data.
///
public static ITangoMessage ParseTangoMessageAgnostic(byte[] data)
{
MessageContainer container = MessageContainer.Parser.ParseFrom(data);
IMessage message = ExtractMessageFromContainer(container);
return (ITangoMessage)_parseTangoMessageMethod.MakeGenericMethod(message.GetType()).Invoke(null, new[] { data });
}
///
/// Parses the message from the specified container.
///
///
/// The container.
///
public static T ExtractMessageFromContainer(MessageContainer container) where T : IMessage
{
MessageParser parser = new MessageParser(() => Activator.CreateInstance());
return parser.ParseFrom(container.Data);
}
///
/// Parses the message from the specified container.
///
///
/// The container.
///
public static IMessage ExtractMessageFromContainer(MessageContainer container)
{
var type = _pmrTypes[container.Type];
MessageParser parser = type.GetProperty("Parser").GetValue(container) as MessageParser;
return parser.ParseFrom(container.Data);
}
///
/// Parses a message container from the specified byte array.
///
/// The data.
///
public static MessageContainer ParseContainer(byte[] data)
{
MessageContainer container = MessageContainer.Parser.ParseFrom(data);
return container;
}
///
/// Parses a message container from the specified byte array containing JSON data.
///
/// The data.
///
public static MessageContainer ParseContainerJson(byte[] data)
{
MessageContainer container = MessageContainer.Parser.ParseJson(Encoding.UTF8.GetString(data));
return container;
}
///
/// Parses the specified text to a PMR .
///
/// The text.
///
/// Could not parse message type " + text
public static MessageType ParseMessageType(String text)
{
MessageType t;
if (Enum.TryParse(text, true, out t))
{
return t;
}
else
{
throw new InvalidCastException("Message type " + text + " was not found on PMR MessageType enumeration!");
}
}
///
/// Parses the specified text to a PMR .
///
/// The text.
///
/// Could not parse message type " + text
public static DataStoreMessageType ParseDataStoreMessageType(String text)
{
DataStoreMessageType t;
if (Enum.TryParse(text, true, out t))
{
return t;
}
else
{
throw new InvalidCastException("Data Store Message type " + text + " was not found on PMR DataStoreMessageType enumeration!");
}
}
///
/// Gets the available request stubs.
///
///
public static List GetAvailableRequestStubs()
{
return typeof(MessageFactory).Assembly.GetTypes().Where(x => x.Namespace != null && x.Namespace.Contains("Stubs") && x.Name.Contains("Request") && !x.Name.Contains("Reflection")).ToList();
}
///
/// Gets the available request & response stubs.
///
///
public static List GetAvailableRequestResponseStubs()
{
return typeof(MessageFactory).Assembly.GetTypes().Where(x => x.Namespace != null && x.Namespace.Contains("Stubs") && !x.Name.Contains("Reflection")).ToList();
}
///
/// Parses the proto message from the specified bytes. Requires the message type.
///
/// The data.
/// The type.
///
public static IMessage ParseProtoMessage(byte[] data, Type type)
{
using (MemoryStream ms = new MemoryStream(data))
{
ms.Position = 0;
using (BinaryReader reader = new BinaryReader(ms))
{
IMessage message = Activator.CreateInstance(type) as IMessage;
MessageParser parser = type.GetProperty("Parser").GetValue(message) as MessageParser;
return parser.ParseFrom(data);
}
}
}
}
}