#region Disclaimer / License
// Copyright (C) 2006, Kenneth Skovhede
// http://www.hexad.dk, opensource@hexad.dk
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
#endregion
using System;
using System.Drawing;
using Topology.Geometries;
namespace OSGeo.MapGuide.MaestroAPI
{
///
/// Various helper functions
///
public class Utility
{
//Americans NEVER obey nationalization when outputting decimal values, so the rest of the world always have to work around their bugs :(
private static System.Globalization.CultureInfo m_enCI = new System.Globalization.CultureInfo("en-US");
///
/// Parses a color in HTML notation (ea. #ffaabbff)
///
/// The HTML representation of the color
/// The .Net color structure that matches the color
public static Color ParseHTMLColor(string color)
{
if (color.Length == 8)
{
int a = int.Parse(color.Substring(0,2), System.Globalization.NumberStyles.HexNumber);
int r = int.Parse(color.Substring(2,2), System.Globalization.NumberStyles.HexNumber);
int g = int.Parse(color.Substring(4,2), System.Globalization.NumberStyles.HexNumber);
int b = int.Parse(color.Substring(6,2), System.Globalization.NumberStyles.HexNumber);
return Color.FromArgb(a, r,g,b);
}
else if (color.Length == 6)
{
int r = int.Parse(color.Substring(0,2), System.Globalization.NumberStyles.HexNumber);
int g = int.Parse(color.Substring(2,2), System.Globalization.NumberStyles.HexNumber);
int b = int.Parse(color.Substring(4,2), System.Globalization.NumberStyles.HexNumber);
return Color.FromArgb(r,g,b);
}
else
throw new Exception("Bad HTML color: \"" + color + "\"");
}
///
/// Returns the HTML representation of an .Net color structure
///
/// The color to encode
/// A flag indicating if the color structures alpha value should be included
/// The HTML representation of the color structure
public static string SerializeHTMLColor(Color color, bool includeAlpha)
{
string res = "";
if (includeAlpha)
res += color.A.ToString("x02");
res += color.R.ToString("x02");
res += color.G.ToString("x02");
res += color.B.ToString("x02");
return res;
}
///
/// Parses a string with a decimal value in EN-US format
///
/// The string value
/// The parsed value
public static float ParseDigit(string digit)
{
return (float)double.Parse(digit, m_enCI);
}
///
/// Turns a decimal value into a string representation in EN-US format
///
/// The value to encode
/// The encoded value
public static string SerializeDigit(float digit)
{
return digit.ToString(m_enCI);
}
///
/// Turns a decimal value into a string representation in EN-US format
///
/// The value to encode
/// The encoded value
public static string SerializeDigit(double digit)
{
return digit.ToString(m_enCI);
}
///
/// Copies the content of a stream into another stream
///
/// The source stream
/// The target stream
public static void CopyStream(System.IO.Stream source, System.IO.Stream target)
{
int r;
byte[] buf = new byte[1024];
do
{
r = source.Read(buf, 0, buf.Length);
target.Write(buf, 0, r);
} while (r > 0);
}
///
/// Makes a deep copy of an object, by copying all the public properties.
/// This overload tries to maintain object references by assigning properties
///
/// The object to copy
/// The object to assign to
/// A copied object
public static object DeepCopy(object source, object target)
{
foreach(System.Reflection.PropertyInfo pi in source.GetType().GetProperties())
{
if (!pi.CanRead || !pi.CanWrite)
continue;
if (!pi.PropertyType.IsClass || pi.PropertyType == typeof(string) )
pi.SetValue(target, pi.GetValue(source, null) , null);
else if (pi.GetValue(source, null) == null)
pi.SetValue(target, null, null);
else if (pi.GetValue(source, null).GetType().GetInterface(typeof(System.Collections.ICollection).FullName) != null)
{
System.Collections.ICollection srcList = (System.Collections.ICollection)pi.GetValue(source, null);
System.Collections.ICollection trgList = (System.Collections.ICollection)Activator.CreateInstance(srcList.GetType());
foreach(object o in srcList)
trgList.GetType().GetMethod("Add").Invoke(trgList, new object[] { DeepCopy(o) } );
pi.SetValue(target, trgList, null);
}
else if (pi.GetValue(source, null).GetType().IsArray)
{
System.Array sourceArr = (System.Array)pi.GetValue(source, null);
System.Array targetArr = (System.Array)Activator.CreateInstance(sourceArr.GetType(), new object[] { sourceArr.Length });
for(int i = 0; i < targetArr.Length; i++)
targetArr.SetValue(DeepCopy(sourceArr.GetValue(i)), i);
pi.SetValue(target, targetArr, null);
}
else
{
if (pi.GetValue(target, null) == null)
pi.SetValue(target, Activator.CreateInstance(pi.GetValue(source, null).GetType()), null);
DeepCopy(pi.GetValue(source, null), pi.GetValue(target, null));
}
}
return target;
}
///
/// Makes a deep copy of an object, by copying all the public properties
///
/// The object to copy
/// A copied object
public static object DeepCopy(object source)
{
object target = Activator.CreateInstance(source.GetType());
foreach(System.Reflection.PropertyInfo pi in source.GetType().GetProperties())
{
if (!pi.CanRead || !pi.CanWrite)
continue;
if (!pi.PropertyType.IsClass || pi.PropertyType == typeof(string) )
pi.SetValue(target, pi.GetValue(source, null) , null);
else if (pi.GetValue(source, null) == null)
pi.SetValue(target, null, null);
else if (pi.GetValue(source, null).GetType().GetInterface(typeof(System.Collections.ICollection).FullName) != null)
{
System.Collections.ICollection srcList = (System.Collections.ICollection)pi.GetValue(source, null);
System.Collections.ICollection trgList = (System.Collections.ICollection)Activator.CreateInstance(srcList.GetType());
foreach(object o in srcList)
trgList.GetType().GetMethod("Add").Invoke(trgList, new object[] { DeepCopy(o) } );
pi.SetValue(target, trgList, null);
}
else if (pi.GetValue(source, null).GetType().IsArray)
{
System.Array sourceArr = (System.Array)pi.GetValue(source, null);
System.Array targetArr = (System.Array)Activator.CreateInstance(sourceArr.GetType(), new object[] { sourceArr.Length });
for(int i = 0; i < targetArr.Length; i++)
targetArr.SetValue(DeepCopy(sourceArr.GetValue(i)), i);
pi.SetValue(target, targetArr, null);
}
else
pi.SetValue(target, DeepCopy(pi.GetValue(source, null)), null);
}
return target;
}
public static System.IO.MemoryStream MgStreamToNetStream(object source, System.Reflection.MethodInfo mi, object[] args)
{
OSGeo.MapGuide.MgByteReader rd = (OSGeo.MapGuide.MgByteReader)mi.Invoke(source, args);
System.IO.MemoryStream ms = new System.IO.MemoryStream();
byte[] buf = new byte[1024];
int c = 0;
do
{
c = rd.Read(buf, buf.Length);
ms.Write(buf, 0, c);
} while (c != 0);
ms.Position = 0;
return ms;
}
public static byte[] StreamAsArray(System.IO.Stream s)
{
if (s as System.IO.MemoryStream != null)
return ((System.IO.MemoryStream)s).ToArray();
if (!s.CanSeek)
{
System.IO.MemoryStream ms = new System.IO.MemoryStream();
byte[] buf = new byte[1024];
int c;
while((c = s.Read(buf, 0, buf.Length)) > 0)
ms.Write(buf, 0, c);
return ms.ToArray();
}
else
{
byte[] buf = new byte[s.Length];
s.Position = 0;
s.Read(buf, 0, buf.Length);
return buf;
}
}
///
/// Creates a copy of the stream, with removed Utf8 BOM, if any
///
/// The stream to fix
/// A stream with no Utf8 BOM
public static System.IO.MemoryStream RemoveUTF8BOM(System.IO.MemoryStream ms)
{
//Skip UTF file header, since the XmlParser is broken
ms.Position = 0;
byte[] utfheader = new byte[3];
if (ms.Read(utfheader, 0, utfheader.Length) == utfheader.Length)
if (utfheader[0] == 0xEF && utfheader[1] == 0xBB && utfheader[2] == 0xBF)
{
ms.Position = 3;
System.IO.MemoryStream mxs = new System.IO.MemoryStream();
Utility.CopyStream(ms, mxs);
mxs.Position = 0;
return mxs;
}
ms.Position = 0;
return ms;
}
///
/// Gets the type of an item, givne the MapGuide type id
///
/// The MapGuide type id
/// The corresponding .Net type
public static Type ConvertMgTypeToNetType(int MgType)
{
switch(MgType)
{
case OSGeo.MapGuide.MgPropertyType.Byte:
return typeof(byte);
case OSGeo.MapGuide.MgPropertyType.Int16:
return typeof(short);
case OSGeo.MapGuide.MgPropertyType.Int32:
return typeof(int);
case OSGeo.MapGuide.MgPropertyType.Int64:
return typeof(long);
case OSGeo.MapGuide.MgPropertyType.Single:
return typeof(float);
case OSGeo.MapGuide.MgPropertyType.Double:
return typeof(double);
case OSGeo.MapGuide.MgPropertyType.Boolean:
return typeof(bool);
case OSGeo.MapGuide.MgPropertyType.Geometry:
return Utility.GeometryType;
case OSGeo.MapGuide.MgPropertyType.String:
return typeof(string);
case OSGeo.MapGuide.MgPropertyType.DateTime:
return typeof(DateTime);
case OSGeo.MapGuide.MgPropertyType.Raster:
return Utility.RasterType;
case OSGeo.MapGuide.MgPropertyType.Blob:
return typeof(byte[]);
case OSGeo.MapGuide.MgPropertyType.Clob:
return typeof(byte[]);
default:
throw new Exception("Failed to find type for: " + MgType.ToString());
}
}
///
/// Gets the MapGuide id for a given type
///
/// The .Net type
/// The corresponding MapGuide type id
public static int ConvertNetTypeToMgType(Type type)
{
if (type == typeof(short))
return OSGeo.MapGuide.MgPropertyType.Int16;
else if (type == typeof(byte))
return OSGeo.MapGuide.MgPropertyType.Byte;
else if (type == typeof(bool))
return OSGeo.MapGuide.MgPropertyType.Boolean;
else if (type == typeof(int))
return OSGeo.MapGuide.MgPropertyType.Int32;
else if (type == typeof(long))
return OSGeo.MapGuide.MgPropertyType.Int64;
else if (type == typeof(float))
return OSGeo.MapGuide.MgPropertyType.Single;
else if (type == typeof(double))
return OSGeo.MapGuide.MgPropertyType.Double;
else if (type == Utility.GeometryType)
return OSGeo.MapGuide.MgPropertyType.Geometry;
else if (type == typeof(string))
return OSGeo.MapGuide.MgPropertyType.String;
else if (type == typeof(DateTime))
return OSGeo.MapGuide.MgPropertyType.DateTime;
else if (type == Utility.RasterType)
return OSGeo.MapGuide.MgPropertyType.Raster;
else if (type == typeof(byte[]))
return OSGeo.MapGuide.MgPropertyType.Blob;
throw new Exception("Failed to find type for: " + type.FullName.ToString());
}
public static Type RasterType
{
get { return typeof(System.Drawing.Bitmap); }
}
public static Type GeometryType
{
get { return typeof(Topology.Geometries.IGeometry); }
}
}
}