#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); } } } }