initialize
This commit is contained in:
453
interface/asm/dotnet/MesTools/ImsApi/ImsApiMapTool.cs
Normal file
453
interface/asm/dotnet/MesTools/ImsApi/ImsApiMapTool.cs
Normal file
@@ -0,0 +1,453 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace com.itac.mes.imsapi
|
||||
{
|
||||
/// <summary>
|
||||
/// tool fuer das automatische Mapping von Werten in Strukturen nach String-Arrays und umgekehrt
|
||||
///
|
||||
/// Prinzip uebernommen aus dem ImsInterfaces, Klasse ImsApiMapTool
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class ImsApiMapTool<T>
|
||||
{
|
||||
|
||||
// von einem Typ
|
||||
private static Dictionary<Type, Dictionary<String, FieldInfo>> fieldMapperTable = new Dictionary<Type, Dictionary<String, FieldInfo>>();
|
||||
private static Dictionary<Type, Dictionary<String, PropertyInfo>> propertyMapperTable = new Dictionary<Type, Dictionary<String, PropertyInfo>>();
|
||||
|
||||
public static void clearClassCache(Type clazz)
|
||||
{
|
||||
Dictionary<String, FieldInfo> fieldKeyMapper = null;
|
||||
if (fieldMapperTable.ContainsKey(clazz))
|
||||
{
|
||||
fieldKeyMapper = fieldMapperTable[clazz];
|
||||
fieldMapperTable.Remove(clazz);
|
||||
}
|
||||
Dictionary<String, PropertyInfo> propertyKeyMapper = null;
|
||||
if (propertyMapperTable.ContainsKey(clazz))
|
||||
{
|
||||
propertyKeyMapper = propertyMapperTable[clazz];
|
||||
propertyMapperTable.Remove(clazz);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// eine Abbildungstabelle fuer einen Typ ermitteln (Namen von Feldern und IMSAPI-Keys)
|
||||
/// </summary>
|
||||
/// <param name="clazz"></param>
|
||||
/// <returns></returns>
|
||||
protected Dictionary<String, FieldInfo> getFieldMapperTable(Type clazz)
|
||||
{
|
||||
Dictionary<String, FieldInfo> keyMapper = null;
|
||||
if (fieldMapperTable.ContainsKey(clazz))
|
||||
{
|
||||
keyMapper = fieldMapperTable[clazz];
|
||||
}
|
||||
else
|
||||
{
|
||||
keyMapper = new Dictionary<String, FieldInfo>();
|
||||
// welche ImsApiKeys werden auf welche Fields abgebildet
|
||||
// iterate over all fields
|
||||
FieldInfo[] fields = clazz.GetFields();
|
||||
foreach (FieldInfo field in fields)
|
||||
{
|
||||
// get relevant annotation
|
||||
object[] annotation = field.GetCustomAttributes(typeof(ImsApiKey), true);
|
||||
if (annotation != null && annotation.Length > 0)
|
||||
{
|
||||
// add field mappings
|
||||
keyMapper.Add(((ImsApiKey)annotation[0]).Key, field);
|
||||
}
|
||||
}
|
||||
fieldMapperTable.Add(clazz, keyMapper);
|
||||
}
|
||||
return keyMapper;
|
||||
}
|
||||
|
||||
protected Dictionary<String, PropertyInfo> getPropertyMapperTable(Type clazz)
|
||||
{
|
||||
Dictionary<String, PropertyInfo> keyMapper = null;
|
||||
if (propertyMapperTable.ContainsKey(clazz))
|
||||
{
|
||||
keyMapper = propertyMapperTable[clazz];
|
||||
}
|
||||
else
|
||||
{
|
||||
keyMapper = new Dictionary<String, PropertyInfo>();
|
||||
// welche ImsApiKeys werden auf welche Fields abgebildet
|
||||
// iterate over all fields
|
||||
PropertyInfo[] properties = clazz.GetProperties();
|
||||
foreach (PropertyInfo property in properties)
|
||||
{
|
||||
// get relevant annotation
|
||||
object[] annotation = property.GetCustomAttributes(typeof(ImsApiKey), true);
|
||||
if (annotation != null && annotation.Length > 0)
|
||||
{
|
||||
// add field mappings
|
||||
keyMapper.Add(((ImsApiKey)annotation[0]).Key, property);
|
||||
}
|
||||
}
|
||||
propertyMapperTable.Add(clazz, keyMapper);
|
||||
}
|
||||
return keyMapper;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// aus einem String-Array mit Keys und Werten eine Struktur erzeugen.
|
||||
/// alle Felder in der Struktur muessen dafuer mit dem Attribut [IMSAPIKEY]
|
||||
/// versehen sein
|
||||
/// </summary>
|
||||
/// <param name="clazz"></param>
|
||||
/// <param name="imsApiKeys"></param>
|
||||
/// <param name="imsApiValues"></param>
|
||||
/// <returns></returns>
|
||||
public T getStruct(Type clazz, string[] imsApiKeys, string[] imsApiValues)
|
||||
{
|
||||
if (clazz == null)
|
||||
{
|
||||
throw new ArgumentException("parameter clazz must not be null");
|
||||
}
|
||||
if (imsApiKeys == null)
|
||||
{
|
||||
throw new ArgumentException("parameter imsApiKeys must not be null");
|
||||
}
|
||||
if (imsApiValues == null)
|
||||
{
|
||||
throw new ArgumentException("parameter imsApiValues must not be null");
|
||||
}
|
||||
// Anzahl der Werte muss identisch sein mit der Anzahl der Keys
|
||||
if (imsApiKeys.Length != imsApiValues.Length)
|
||||
{
|
||||
throw new ArgumentException("parameter imsApiKeys and imsApiValues must have the same size");
|
||||
}
|
||||
Dictionary<String, FieldInfo> keyMapper = getFieldMapperTable(clazz);
|
||||
Dictionary<String, PropertyInfo> propertyKeyMapper = getPropertyMapperTable(clazz);
|
||||
|
||||
T instance = getInstance(clazz, imsApiKeys, imsApiValues, keyMapper, propertyKeyMapper, 0);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private T getInstance(Type clazz, String[] imsApiKeys, String[] imsApiValues, Dictionary<String, FieldInfo> keyMapper,
|
||||
Dictionary<String, PropertyInfo> propertyMapper, int baseIndex)
|
||||
{
|
||||
T instance = (T)Activator.CreateInstance(clazz);
|
||||
// now map all keyValues to fields
|
||||
for (int index = 0; index < imsApiKeys.Length; index++)
|
||||
{
|
||||
String key = imsApiKeys[index];
|
||||
String sValue = imsApiValues[baseIndex + index];
|
||||
if (!keyMapper.ContainsKey(key))
|
||||
{
|
||||
// dieser key ist nicht zur Abbildung definiert, d.h. es gibt keine Annotation in der Zielklasse mit diesem Key
|
||||
if (!propertyMapper.ContainsKey(key))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
PropertyInfo propInfo = propertyMapper[key];
|
||||
safeSetProperty(instance, propInfo, sValue);
|
||||
|
||||
continue;
|
||||
}
|
||||
FieldInfo f = keyMapper[key];
|
||||
safeSetField(instance, f, sValue);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// aus einem String-Array mit Keys und Werten ein Array von Strukturen erzeugen.
|
||||
/// alle Felder in der Struktur muessen dafuer mit dem Attribut [IMSAPIKEY]
|
||||
/// versehen sein
|
||||
/// </summary>
|
||||
/// <param name="clazz"></param>
|
||||
/// <param name="imsApiKeys"></param>
|
||||
/// <param name="imsApiValues"></param>
|
||||
/// <returns></returns>
|
||||
public T[] getArray(Type clazz, String[] imsApiKeys, String[] imsApiValues)
|
||||
{
|
||||
// Check parameters
|
||||
if (clazz == null)
|
||||
{
|
||||
throw new ArgumentException("parameter clazz must not be null");
|
||||
}
|
||||
if (imsApiKeys == null)
|
||||
{
|
||||
throw new ArgumentException("parameter imsApiKeys must not be null");
|
||||
}
|
||||
if (imsApiValues == null || imsApiValues.Length == 0)
|
||||
{
|
||||
throw new ArgumentException("parameter imsApiValues must not be null");
|
||||
}
|
||||
// Anzahl der Werte muss ein ganzzahliges Vielfaches der Anzahl der Keys sein
|
||||
if ((imsApiValues.Length % imsApiKeys.Length) != 0)
|
||||
{
|
||||
throw new ArgumentException("parameter imsApiValues must be a multiple of imsApiKeys");
|
||||
}
|
||||
Dictionary<String, FieldInfo> keyMapper = getFieldMapperTable(clazz);
|
||||
Dictionary<String, PropertyInfo> propertyKeyMapper = getPropertyMapperTable(clazz);
|
||||
|
||||
int length = imsApiValues.Length / imsApiKeys.Length;
|
||||
T[] resultArray = (T[])Array.CreateInstance(clazz, length);
|
||||
|
||||
for (int baseIndex = 0; baseIndex < imsApiValues.Length; baseIndex += imsApiKeys.Length)
|
||||
{
|
||||
T instance = getInstance(clazz, imsApiKeys, imsApiValues, keyMapper, propertyKeyMapper, baseIndex);
|
||||
resultArray[baseIndex / imsApiKeys.Length] = instance;
|
||||
}
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
|
||||
protected void safeSetField(T instance, FieldInfo field, String sValue)
|
||||
{
|
||||
//if ((field.getModifiers() & Modifier.PRIVATE) == Modifier.PRIVATE) {
|
||||
// field.setAccessible(true);
|
||||
//}
|
||||
try
|
||||
{
|
||||
if (field.FieldType == typeof(int) || field.FieldType == typeof(Int16) || field.FieldType == typeof(Int32) || field.FieldType == typeof(Int64))
|
||||
{
|
||||
try
|
||||
{
|
||||
field.SetValue(instance, Int32.Parse(sValue));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// replace all , by .
|
||||
string s = sValue.Replace(",", ".");
|
||||
CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
|
||||
field.SetValue(instance, Convert.ToInt32(Double.Parse(s, culture)));
|
||||
}
|
||||
}
|
||||
else if (field.FieldType == typeof(String) || field.FieldType == typeof(string))
|
||||
{
|
||||
field.SetValue(instance, sValue);
|
||||
}
|
||||
//} else if (field.getType() == Boolean.class || field.getType() == boolean.class) {
|
||||
// field.setBoolean(instance, Boolean.parseBoolean(sValue));
|
||||
else if (field.FieldType == typeof(DateTime))
|
||||
{
|
||||
field.SetValue(instance, getDateValue(sValue));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("unknown type mapper for " + field.FieldType.Name);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new ArgumentException("unknown type mapper or invalid value for " + field.Name + ":" + sValue, e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void safeSetProperty(T instance, PropertyInfo field, String sValue)
|
||||
{
|
||||
//if ((field.getModifiers() & Modifier.PRIVATE) == Modifier.PRIVATE) {
|
||||
// field.setAccessible(true);
|
||||
//}
|
||||
try
|
||||
{
|
||||
if (field.PropertyType== typeof(int) || field.PropertyType == typeof(Int16) || field.PropertyType == typeof(Int32) || field.PropertyType == typeof(Int64))
|
||||
{
|
||||
try
|
||||
{
|
||||
field.SetValue(instance, Int32.Parse(sValue), new object[] { });
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// replace all , by .
|
||||
string s = sValue.Replace(",", ".");
|
||||
CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
|
||||
field.SetValue(instance, Convert.ToInt32(Double.Parse(s, culture)), new object[] { });
|
||||
}
|
||||
}
|
||||
else if (field.PropertyType == typeof(String) || field.PropertyType == typeof(string))
|
||||
{
|
||||
field.SetValue(instance, sValue, new object[] { });
|
||||
}
|
||||
//} else if (field.getType() == Boolean.class || field.getType() == boolean.class) {
|
||||
// field.setBoolean(instance, Boolean.parseBoolean(sValue));
|
||||
else if (field.PropertyType == typeof(DateTime))
|
||||
{
|
||||
field.SetValue(instance, getDateValue(sValue), new object[] { });
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("unknown type mapper for " + field.PropertyType.Name);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new ArgumentException("unknown type mapper or invalid value for " + field.Name + ":" + sValue, e);
|
||||
}
|
||||
}
|
||||
|
||||
public DateTime getDateValue(string sDateValue)
|
||||
{
|
||||
if (sDateValue == null || sDateValue.Equals(""))
|
||||
{
|
||||
return new DateTime(1899, 12, 31, 23, 59, 59, DateTimeKind.Utc);
|
||||
}
|
||||
string s = sDateValue.Replace(",", ".");
|
||||
CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
|
||||
double millies = Double.Parse(sDateValue, culture);
|
||||
if (millies <= 1000)
|
||||
{
|
||||
return new DateTime(1899, 12, 31, 23, 59, 59, DateTimeKind.Utc);
|
||||
}
|
||||
// treat date values >= 30.12.3000 as infinite...
|
||||
if (millies >= 32535039600000)
|
||||
{
|
||||
return new DateTime(9999, 12, 31, 23, 59, 59, DateTimeKind.Utc);
|
||||
}
|
||||
DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
DateTime expiry = epoch.AddMilliseconds(millies);
|
||||
return expiry;
|
||||
}
|
||||
|
||||
public String[] getValueArray(T[] value, String[] imsApiKeys)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentException("parameter value must not be null");
|
||||
}
|
||||
if (imsApiKeys == null)
|
||||
{
|
||||
throw new ArgumentException("parameter imsApiKeys must not be null");
|
||||
}
|
||||
if (value.Length == 0)
|
||||
{
|
||||
return new String[0];
|
||||
}
|
||||
// aus der uebergebenen Struktur ein String Array bilden, unter der Prämisse der Imsapikeys
|
||||
// Kein Element des ValueArray darf null sein !!!!!
|
||||
if (value[0] == null)
|
||||
{
|
||||
throw new ArgumentException("first element in value array must not be null");
|
||||
}
|
||||
|
||||
Dictionary<String, FieldInfo> keyMapper = getFieldMapperTable(value[0].GetType());
|
||||
|
||||
String[] resultArray = new String[imsApiKeys.Length * value.Length];
|
||||
// nicht in der Struktur enthaltene Keys führen zu Fehlern
|
||||
// in der Struktur enthaltene Keys, die nicht im imsapiKeysArray enthalten sind werden einfach ignoriert
|
||||
int startIndex = 0;
|
||||
foreach (T item in value)
|
||||
{
|
||||
toImsApiStringArray(item, resultArray, imsApiKeys, keyMapper, startIndex);
|
||||
startIndex += imsApiKeys.Length;
|
||||
}
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// aus einer Struktur ein String-Array erzeugen; alle als Keys uerbegebenen Felder
|
||||
/// sind im String-Array in der Reihenfolge der imsApiKeys enthalten
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="imsApiKeys"></param>
|
||||
/// <returns></returns>
|
||||
public String[] getValueArray(T value, String[] imsApiKeys)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentException("parameter value must not be null");
|
||||
}
|
||||
if (imsApiKeys == null)
|
||||
{
|
||||
throw new ArgumentException("parameter imsApiKeys must not be null");
|
||||
}
|
||||
// aus der uebergebenen Struktur ein String Array bilden, unter der Prämisse der Imsapikeys
|
||||
Dictionary<String, FieldInfo> keyMapper = getFieldMapperTable(value.GetType());
|
||||
|
||||
String[] resultArray = new String[imsApiKeys.Length];
|
||||
// nicht in der Struktur enthaltene Keys führen zu Fehlern
|
||||
// in der Struktur enthaltene Keys, die nicht im imsapiKeysArray enthalten sind werden einfach ignoriert
|
||||
toImsApiStringArray(value, resultArray, imsApiKeys, keyMapper, 0);
|
||||
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
protected void toImsApiStringArray(T value, String[] resultArray, String[] imsApiKeys,
|
||||
Dictionary<String, FieldInfo> keyMapper, int i)
|
||||
{
|
||||
int destinationIndex = i;
|
||||
foreach (String key in imsApiKeys)
|
||||
{
|
||||
if (!keyMapper.ContainsKey(key))
|
||||
{
|
||||
throw new ArgumentException("destination key '" + key + "' is not available in structure");
|
||||
}
|
||||
FieldInfo field = keyMapper[key];
|
||||
try
|
||||
{
|
||||
String imsapiString = safeGetField(field, value);
|
||||
resultArray[destinationIndex++] = imsapiString;
|
||||
}
|
||||
catch (NullReferenceException)
|
||||
{
|
||||
// field is null
|
||||
destinationIndex++;
|
||||
}
|
||||
catch (Exception )
|
||||
{
|
||||
destinationIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected String safeGetField(FieldInfo field, T value)
|
||||
{
|
||||
try
|
||||
{
|
||||
Object o = field.GetValue(value);
|
||||
if (field.FieldType == typeof(int) || field.FieldType == typeof(Int16) || field.FieldType == typeof(Int32) || field.FieldType == typeof(Int64) )
|
||||
{
|
||||
return o.ToString();
|
||||
}
|
||||
else if (field.FieldType == typeof(string) || field.FieldType == typeof(String))
|
||||
{
|
||||
return o.ToString();
|
||||
}
|
||||
else if (field.FieldType == typeof(Boolean) || field.FieldType == typeof(bool))
|
||||
{
|
||||
bool b = (Boolean)o;
|
||||
if (b)
|
||||
{
|
||||
return "1";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
else if (field.FieldType == typeof(DateTime))
|
||||
{
|
||||
DateTime d = (DateTime)o;
|
||||
if (d == null)
|
||||
{
|
||||
return "0";
|
||||
}
|
||||
return "" + d.Ticks;// todo:correction
|
||||
}
|
||||
}
|
||||
catch (NullReferenceException)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
catch (AccessViolationException)
|
||||
{
|
||||
// einfach ignorieren, dies sollte eigentlich nie vorkommen
|
||||
}
|
||||
throw new ArgumentException("unknown type mapper for " + field.FieldType.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user