/// <summary>
		/// Deserializes the graphtype, here's where all the smart stuff happens
		/// </summary>
		/// <param name="gml">the graphtype which acts as an intermediate storage between XML and the GraphAbstract
		/// </param>
		/// <returns></returns>
		private GraphAbstract Deserialize(NMLType gml)
		{
			GraphAbstract abs = new GraphAbstract();
			
			#region Load the graph information
			GraphType g = gml.Graph;
			
			abs.GraphInformation = g.GraphInformation.ToGraphInformation();		

			#endregion
			Shape shape = null;
			ShapeType node;
			DataType dt;				
			ConnectorType ct;
			Connection con = null;
			ConnectionType et;
			string linePath = string.Empty; //see the split deserialization of the connection
			
			FromToCollection ftc = new FromToCollection(); //temporary store for from-to relations of connections
			Hashtable connectors = new Hashtable(); //temporary collection of connector
			#region Loop over all items

			

			for(int k =0; k<g.Items.Count;k++) //loop over all serialized items
			{
				try
				{
					if(g.Items[k] is ShapeType)
					{
						Trace.WriteLine("Node: " + (g.Items[k] as ShapeType).UID,"NMLSerializer.Deserialize");
						node = g.Items[k] as ShapeType;

						#region find out which type of shape needs to be instantiated
						if(node!=null && node.InstanceKey!=string.Empty)
							shape = GetShape(node.InstanceKey);	
						if(shape==null)
						{
							Trace.WriteLine("...but failed to instantiate the appropriate shape (missing or not loaded library?", "NMLSerializer.Deserialize");
							continue;
						}

						#endregion
						#region use the attribs again to reconstruct the props				
						for(int m=0; m<node.Data.Count;m++) //loop over the serialized data
						{
							if(node.Data[m] is DataType)
							{
								#region Handle data node
								dt = node.Data[m] as DataType;												
								if(dt==null) continue;

								foreach (PropertyInfo pi in shape.GetType().GetProperties()) 
								{	
									if (Attribute.IsDefined(pi, typeof(GraphMLDataAttribute))) 
									{
										try
										{
											if(pi.Name==dt.Name)
											{
															
												if(pi.GetIndexParameters().Length==0)
												{
													if(pi.PropertyType.Equals(typeof(int)))
														pi.SetValue(shape,Convert.ToInt32(dt.Value[0]),null);
													else if(pi.PropertyType.Equals(typeof(Color))) //Color is stored as an integer
														pi.SetValue(shape,Color.FromArgb(int.Parse(dt.Value[0].ToString())),null);
													else if(pi.PropertyType.Equals(typeof(string)))
														pi.SetValue(shape,(string)(dt.Value[0]),null);
													else if(pi.PropertyType.Equals(typeof(bool)))
														pi.SetValue(shape,Convert.ToBoolean(dt.Value[0]),null);	
													else if(pi.PropertyType.Equals(typeof(Guid)))
														pi.SetValue(shape,new Guid((string) dt.Value[0]),null);	
													else if(pi.PropertyType.Equals(typeof(float)))
														pi.SetValue(shape, Convert.ToSingle(dt.Value[0]),null);
													else if(pi.PropertyType.BaseType.Equals(typeof(Enum)))//yesyes, you can imp/exp enum types too
														pi.SetValue(shape, Enum.Parse(pi.PropertyType,dt.Value[0].ToString()),null);													
													else if(dt.IsCollection)
													{
														#region Some explanations
														/* OK, here's the deal. 
														 * This part is related to the possibility to imp/exp property-collections from/to NML.
														 * However, since (see more specifically the ClassShape) the collections will usually be defined
														 * where the shapes is defined, i.e. in an external assembly, the collection-type is unknown.
														 * Importing/exporting collections to NML is itsel a problem and in this part of the code the data is reflected again.
														 * To bypass the problem that the collection-type is unknown I hereby assume that the collection can be built up again via
														 * a public constructor of the collection with argument 'ArrayList'. In the ArrayList the collection-elements are of type string[]
														 * whereby the order of the strings reflect the order of the GraphMLData-tagged properties of the collection elements.
														 * For example, the ClassPropertiesCollection has the required constructor and the ClassProperty object is instantiated via the string[] elements in the
														 * ArrayList.
														 * Of course, this brings some restriction but it's for the moment the most flexible way I have found.
														 * If the ClassProperty would itself have a property inheriting from CollectionBase this will not work...one has to draw a line somewhere.
														 * It's the price to pay for using reflection and external assemblies. The whole story can be forgotten if you link the shape-classes at compile-time.
														 * Remember; the Netron graphlib is more a toolkit than a all-in solution to all situations. 
														 * However, the current implementation will cover, I beleive, 90% of the needs.
														 */
														#endregion
														
														ArrayList list = new ArrayList();
														for(int p =0; p<dt.Value.Count; p++) //loop over the collection elements
														{
															DataType dat = dt.Value[p] as DataType; //take a collection element
															if(dat.IsCollection)	//is it itself a collection?
															{
																string[] str = new string[dat.Value.Count];
																for(int l=0;l<dat.Value.Count;l++)
																{
																	if((dat.Value[l] as DataType).Value.Count>0)
																		str[l] = (string) (dat.Value[l] as DataType).Value[0];
																	else
																		str[l] = string.Empty;
																}
																list.Add(str); 
															}
															else
															{
																list.Add(new string[]{(string) dat.Value[0]}); 
															}
															
														}
														object o;
														o = pi.PropertyType.GetConstructor(new Type[]{typeof(ArrayList)}).Invoke(new Object[]{list});
														pi.SetValue(shape,o,null);
														Trace.WriteLine("'" + dt.Name + "' is an array type","NMLSeriliazer.Deserialize");
													}

												}
												else
													pi.SetValue(shape,dt.Value,null);
												Trace.WriteLine("'" + dt.Name + "' deserialized.","NMLSeriliazer.Deserialize");
												break;
											}
										}
										catch(Exception exc)
										{
											Trace.WriteLine("Failed '" + dt.Name +"': " + exc.Message,"NMLSeriliazer.Deserialize");
											continue;//just try to make the best out of it
										}
														
									}
								
								}
								#endregion
							}
							else if (node.Data[m] is ConnectorType)
							{
								#region Handle connector data
								ct = node.Data[m] as ConnectorType;
								foreach(Connector c in shape.Connectors)
									if(c.Name==ct.Name)
									{
										c.UID = new Guid(ct.UID);
										break;
									}
								#endregion
							}
						
						}
						#endregion
						//at this point the shape is fully deserialized
						//but we still need to assign the ambient properties,
						//i.e. the properties associated to the current hosting of the control
						if(shape !=null)
						{
							shape.Site = site;
							shape.PostDeserialization();
							shape.Font = site.Font;
							//shape.FitSize(false);
							abs.Shapes.Add(shape);
							//keep the references to the connectors, to be used when creating the connections
							foreach(Connector cor in shape.Connectors)
								connectors.Add(cor.UID.ToString(),cor);
						}
					}
					else if(g.Items[k] is ConnectionType)
					{
						#region  handle the edge
						//we cannot create the connection here since not all shapes have been instantiated yet
						//keep the edges in temp collection, treated in next loop
						et = g.Items[k] as ConnectionType;
						con = new Connection(site);
						con.Font = site.Font;
						con.UID = new Guid(et.ID);
						Trace.WriteLine("Connection: " + et.ID,"NMLSeriliazer.Deserialize");
						#region use the attribs to reconstruct the props


						for(int m=0; m<et.Data.Count;m++) //loop over the serialized data
						{
							if(et.Data[m] is DataType)
							{
								#region Handle data node, same as the shape
								dt = et.Data[m] as DataType;												
								if(dt==null) continue;

								foreach (PropertyInfo pi in con.GetType().GetProperties()) 
								{	
									if (Attribute.IsDefined(pi, typeof(GraphMLDataAttribute))) 
									{
										try
										{
											if(pi.Name==dt.Name)
											{
												if(dt.Name=="LinePath")
												{
													//the LinePath will not work without non-null From and To, so set it afterwards
													linePath = dt.Value[0].ToString();
												}
												else if(pi.GetIndexParameters().Length==0)
												{
													if(pi.PropertyType.Equals(typeof(int)))
														pi.SetValue(con,Convert.ToInt32(dt.Value[0]),null);
													else if(pi.PropertyType.Equals(typeof(Color))) //Color is stored as an integer
														pi.SetValue(con,Color.FromArgb(int.Parse(dt.Value[0].ToString())),null);
													else if(pi.PropertyType.Equals(typeof(string)))
														pi.SetValue(con,(string)(dt.Value[0]),null);
													else if(pi.PropertyType.Equals(typeof(bool)))
														pi.SetValue(con,Convert.ToBoolean(dt.Value[0]),null);	
													else if(pi.PropertyType.Equals(typeof(Guid)))
														pi.SetValue(con,new Guid((string) dt.Value[0]),null);	
													else if(pi.PropertyType.Equals(typeof(float)))
														pi.SetValue(con, Convert.ToSingle(dt.Value[0]),null);
													else if (pi.PropertyType.Equals(typeof(ConnectionWeight)))
														pi.SetValue(con, Enum.Parse(typeof(ConnectionWeight),dt.Value[0].ToString()),null);
													else if (pi.PropertyType.Equals(typeof(System.Drawing.Drawing2D.DashStyle)))
														pi.SetValue(con, Enum.Parse(typeof(System.Drawing.Drawing2D.DashStyle),dt.Value[0].ToString()),null);

												}
												else
													pi.SetValue(con,dt.Value,null);
												Trace.WriteLine("'" + dt.Name + "' deserialized.","NMLSeriliazer.Deserialize");
												break;
											}
										}
										catch(Exception exc)
										{
											Trace.WriteLine("Failed '" + dt.Name +"': " + exc.Message,"NMLSeriliazer.Deserialize");
											continue;//just try to make the best out of it
										}
														
									}
								
								}
								#endregion
							}
						}

						#endregion
						ftc.Add(new FromTo(et.Sourceport,et.Targetport, con));
						#endregion
					}
				}
				catch(Exception exc)
				{
					Trace.WriteLine(exc.Message,"NMLSeriliazer.Deserialize");
					continue;
				}

			}//loop over items in the graph-XML
			#endregion

			#region now for the edges;
			//loop over the FromTo collections and pick up the corresponding connectors
			for(int k=0; k<ftc.Count; k++)
			{
				try
				{
					con = ftc[k].Connection;
					con.From = connectors[ftc[k].From] as Connector;
					con.To = connectors[ftc[k].To] as Connector;					
					con.From.Connections.Add(con);//if From is null we'll fail in the catch and continue
					con.LinePath = linePath; //only setable after the From and To are found
					con.To.Connections.Add(con);				
					abs.Insert(con);
					Trace.WriteLine("Connection '" + con.UID + "' added.","NMLSeriliazer.Deserialize");
				}
				catch(Exception exc)
				{
					Trace.WriteLine("Connection failed: " + exc.Message,"NMLSeriliazer.Deserialize");
					continue; //make the best of it
				}
			}
			#endregion
			

			//			for(int n=0; n<pcs.Count; n++)
			//			{	
			//				from = pcs[n].ChildShape;
			//				to = abs.Shapes[pcs[n].Parent];
			//				con = new Connection(from, to );
			//				abs.Connections.Add(con);
			//				con.site = site;
			//				if(pcs[n].ChildShape.visible)
			//					con.visible = true;
			//				from.connection = con;	//a lot of crossing...to make life easy really
			//				from.parentNode =to;
			//				to.childNodes.Add(from);
			//				
			//				
			//			}

			return abs;

		}
        /// <summary>
        /// Deserializes the graphtype, here's where all the smart stuff happens
        /// </summary>
        /// <param name="gml">the graphtype which acts as an intermediate storage between XML and the GraphAbstract
        /// </param>
        /// <returns></returns>
        private GraphAbstract Deserialize(NMLType gml)
        {
            GraphAbstract abs = new GraphAbstract();

            #region Load the graph information
            GraphType g = gml.Graph;

            abs.GraphInformation = g.GraphInformation.ToGraphInformation();

            #endregion
            Shape          shape = null;
            ShapeType      node;
            DataType       dt;
            ConnectorType  ct;
            Connection     con = null;
            ConnectionType et;
            string         linePath = string.Empty;               //see the split deserialization of the connection

            FromToCollection ftc        = new FromToCollection(); //temporary store for from-to relations of connections
            Hashtable        connectors = new Hashtable();        //temporary collection of connector
            #region Loop over all items



            for (int k = 0; k < g.Items.Count; k++)        //loop over all serialized items
            {
                try
                {
                    if (g.Items[k] is ShapeType)
                    {
                        Trace.WriteLine("Node: " + (g.Items[k] as ShapeType).UID, "NMLSerializer.Deserialize");
                        node = g.Items[k] as ShapeType;

                        #region find out which type of shape needs to be instantiated
                        if (node != null && node.InstanceKey != string.Empty)
                        {
                            shape = GetShape(node.InstanceKey);
                        }
                        if (shape == null)
                        {
                            Trace.WriteLine("...but failed to instantiate the appropriate shape (missing or not loaded library?", "NMLSerializer.Deserialize");
                            continue;
                        }

                        #endregion
                        #region use the attribs again to reconstruct the props
                        for (int m = 0; m < node.Data.Count; m++)                   //loop over the serialized data
                        {
                            if (node.Data[m] is DataType)
                            {
                                #region Handle data node
                                dt = node.Data[m] as DataType;
                                if (dt == null)
                                {
                                    continue;
                                }

                                foreach (PropertyInfo pi in shape.GetType().GetProperties())
                                {
                                    if (Attribute.IsDefined(pi, typeof(GraphMLDataAttribute)))
                                    {
                                        try
                                        {
                                            if (pi.Name == dt.Name)
                                            {
                                                if (pi.GetIndexParameters().Length == 0)
                                                {
                                                    if (pi.PropertyType.Equals(typeof(int)))
                                                    {
                                                        pi.SetValue(shape, Convert.ToInt32(dt.Value[0]), null);
                                                    }
                                                    else if (pi.PropertyType.Equals(typeof(Color)))                                                    //Color is stored as an integer
                                                    {
                                                        pi.SetValue(shape, Color.FromArgb(int.Parse(dt.Value[0].ToString())), null);
                                                    }
                                                    else if (pi.PropertyType.Equals(typeof(string)))
                                                    {
                                                        pi.SetValue(shape, (string)(dt.Value[0]), null);
                                                    }
                                                    else if (pi.PropertyType.Equals(typeof(bool)))
                                                    {
                                                        pi.SetValue(shape, Convert.ToBoolean(dt.Value[0]), null);
                                                    }
                                                    else if (pi.PropertyType.Equals(typeof(Guid)))
                                                    {
                                                        pi.SetValue(shape, new Guid((string)dt.Value[0]), null);
                                                    }
                                                    else if (pi.PropertyType.Equals(typeof(float)))
                                                    {
                                                        pi.SetValue(shape, Convert.ToSingle(dt.Value[0]), null);
                                                    }
                                                    else if (pi.PropertyType.BaseType.Equals(typeof(Enum)))                                                   //yesyes, you can imp/exp enum types too
                                                    {
                                                        pi.SetValue(shape, Enum.Parse(pi.PropertyType, dt.Value[0].ToString()), null);
                                                    }
                                                    else if (dt.IsCollection)
                                                    {
                                                        #region Some explanations

                                                        /* OK, here's the deal.
                                                         * This part is related to the possibility to imp/exp property-collections from/to NML.
                                                         * However, since (see more specifically the ClassShape) the collections will usually be defined
                                                         * where the shapes is defined, i.e. in an external assembly, the collection-type is unknown.
                                                         * Importing/exporting collections to NML is itsel a problem and in this part of the code the data is reflected again.
                                                         * To bypass the problem that the collection-type is unknown I hereby assume that the collection can be built up again via
                                                         * a public constructor of the collection with argument 'ArrayList'. In the ArrayList the collection-elements are of type string[]
                                                         * whereby the order of the strings reflect the order of the GraphMLData-tagged properties of the collection elements.
                                                         * For example, the ClassPropertiesCollection has the required constructor and the ClassProperty object is instantiated via the string[] elements in the
                                                         * ArrayList.
                                                         * Of course, this brings some restriction but it's for the moment the most flexible way I have found.
                                                         * If the ClassProperty would itself have a property inheriting from CollectionBase this will not work...one has to draw a line somewhere.
                                                         * It's the price to pay for using reflection and external assemblies. The whole story can be forgotten if you link the shape-classes at compile-time.
                                                         * Remember; the Netron graphlib is more a toolkit than a all-in solution to all situations.
                                                         * However, the current implementation will cover, I beleive, 90% of the needs.
                                                         */
                                                        #endregion

                                                        ArrayList list = new ArrayList();
                                                        for (int p = 0; p < dt.Value.Count; p++)                                                //loop over the collection elements
                                                        {
                                                            DataType dat = dt.Value[p] as DataType;                                             //take a collection element
                                                            if (dat.IsCollection)                                                               //is it itself a collection?
                                                            {
                                                                string[] str = new string[dat.Value.Count];
                                                                for (int l = 0; l < dat.Value.Count; l++)
                                                                {
                                                                    if ((dat.Value[l] as DataType).Value.Count > 0)
                                                                    {
                                                                        str[l] = (string)(dat.Value[l] as DataType).Value[0];
                                                                    }
                                                                    else
                                                                    {
                                                                        str[l] = string.Empty;
                                                                    }
                                                                }
                                                                list.Add(str);
                                                            }
                                                            else
                                                            {
                                                                list.Add(new string[] { (string)dat.Value[0] });
                                                            }
                                                        }
                                                        object o;
                                                        o = pi.PropertyType.GetConstructor(new Type[] { typeof(ArrayList) }).Invoke(new Object[] { list });
                                                        pi.SetValue(shape, o, null);
                                                        Trace.WriteLine("'" + dt.Name + "' is an array type", "NMLSeriliazer.Deserialize");
                                                    }
                                                }
                                                else
                                                {
                                                    pi.SetValue(shape, dt.Value, null);
                                                }
                                                Trace.WriteLine("'" + dt.Name + "' deserialized.", "NMLSeriliazer.Deserialize");
                                                break;
                                            }
                                        }
                                        catch (Exception exc)
                                        {
                                            Trace.WriteLine("Failed '" + dt.Name + "': " + exc.Message, "NMLSeriliazer.Deserialize");
                                            continue;                                            //just try to make the best out of it
                                        }
                                    }
                                }
                                #endregion
                            }
                            else if (node.Data[m] is ConnectorType)
                            {
                                #region Handle connector data
                                ct = node.Data[m] as ConnectorType;
                                foreach (Connector c in shape.Connectors)
                                {
                                    if (c.Name == ct.Name)
                                    {
                                        c.UID = new Guid(ct.UID);
                                        break;
                                    }
                                }
                                #endregion
                            }
                        }
                        #endregion
                        //at this point the shape is fully deserialized
                        //but we still need to assign the ambient properties,
                        //i.e. the properties associated to the current hosting of the control
                        if (shape != null)
                        {
                            shape.Site = site;
                            shape.PostDeserialization();
                            shape.Font = site.Font;
                            //shape.FitSize(false);
                            abs.Shapes.Add(shape);
                            //keep the references to the connectors, to be used when creating the connections
                            foreach (Connector cor in shape.Connectors)
                            {
                                connectors.Add(cor.UID.ToString(), cor);
                            }
                        }
                    }
                    else if (g.Items[k] is ConnectionType)
                    {
                        #region  handle the edge
                        //we cannot create the connection here since not all shapes have been instantiated yet
                        //keep the edges in temp collection, treated in next loop
                        et       = g.Items[k] as ConnectionType;
                        con      = new Connection(site);
                        con.Font = site.Font;
                        con.UID  = new Guid(et.ID);
                        Trace.WriteLine("Connection: " + et.ID, "NMLSeriliazer.Deserialize");
                        #region use the attribs to reconstruct the props


                        for (int m = 0; m < et.Data.Count; m++)                   //loop over the serialized data
                        {
                            if (et.Data[m] is DataType)
                            {
                                #region Handle data node, same as the shape
                                dt = et.Data[m] as DataType;
                                if (dt == null)
                                {
                                    continue;
                                }

                                foreach (PropertyInfo pi in con.GetType().GetProperties())
                                {
                                    if (Attribute.IsDefined(pi, typeof(GraphMLDataAttribute)))
                                    {
                                        try
                                        {
                                            if (pi.Name == dt.Name)
                                            {
                                                if (dt.Name == "LinePath")
                                                {
                                                    //the LinePath will not work without non-null From and To, so set it afterwards
                                                    linePath = dt.Value[0].ToString();
                                                }
                                                else if (pi.GetIndexParameters().Length == 0)
                                                {
                                                    if (pi.PropertyType.Equals(typeof(int)))
                                                    {
                                                        pi.SetValue(con, Convert.ToInt32(dt.Value[0]), null);
                                                    }
                                                    else if (pi.PropertyType.Equals(typeof(Color)))                                                    //Color is stored as an integer
                                                    {
                                                        pi.SetValue(con, Color.FromArgb(int.Parse(dt.Value[0].ToString())), null);
                                                    }
                                                    else if (pi.PropertyType.Equals(typeof(string)))
                                                    {
                                                        pi.SetValue(con, (string)(dt.Value[0]), null);
                                                    }
                                                    else if (pi.PropertyType.Equals(typeof(bool)))
                                                    {
                                                        pi.SetValue(con, Convert.ToBoolean(dt.Value[0]), null);
                                                    }
                                                    else if (pi.PropertyType.Equals(typeof(Guid)))
                                                    {
                                                        pi.SetValue(con, new Guid((string)dt.Value[0]), null);
                                                    }
                                                    else if (pi.PropertyType.Equals(typeof(float)))
                                                    {
                                                        pi.SetValue(con, Convert.ToSingle(dt.Value[0]), null);
                                                    }
                                                    else if (pi.PropertyType.Equals(typeof(ConnectionWeight)))
                                                    {
                                                        pi.SetValue(con, Enum.Parse(typeof(ConnectionWeight), dt.Value[0].ToString()), null);
                                                    }
                                                }
                                                else
                                                {
                                                    pi.SetValue(con, dt.Value, null);
                                                }
                                                Trace.WriteLine("'" + dt.Name + "' deserialized.", "NMLSeriliazer.Deserialize");
                                                break;
                                            }
                                        }
                                        catch (Exception exc)
                                        {
                                            Trace.WriteLine("Failed '" + dt.Name + "': " + exc.Message, "NMLSeriliazer.Deserialize");
                                            continue;                                            //just try to make the best out of it
                                        }
                                    }
                                }
                                #endregion
                            }
                        }

                        #endregion
                        ftc.Add(new FromTo(et.Sourceport, et.Targetport, con));
                        #endregion
                    }
                }
                catch (Exception exc)
                {
                    Trace.WriteLine(exc.Message, "NMLSeriliazer.Deserialize");
                    continue;
                }
            }            //loop over items in the graph-XML
            #endregion

            #region now for the edges;
            //loop over the FromTo collections and pick up the corresponding connectors
            for (int k = 0; k < ftc.Count; k++)
            {
                try
                {
                    con      = ftc[k].Connection;
                    con.From = connectors[ftc[k].From] as Connector;
                    con.To   = connectors[ftc[k].To] as Connector;
                    con.From.Connections.Add(con);               //if From is null we'll fail in the catch and continue
                    con.LinePath = linePath;                     //only setable after the From and To are found
                    con.To.Connections.Add(con);
                    abs.Insert(con);
                    Trace.WriteLine("Connection '" + con.UID + "' added.", "NMLSeriliazer.Deserialize");
                }
                catch (Exception exc)
                {
                    Trace.WriteLine("Connection failed: " + exc.Message, "NMLSeriliazer.Deserialize");
                    continue;                     //make the best of it
                }
            }
            #endregion


            //			for(int n=0; n<pcs.Count; n++)
            //			{
            //				from = pcs[n].ChildShape;
            //				to = abs.Shapes[pcs[n].Parent];
            //				con = new Connection(from, to );
            //				abs.Connections.Add(con);
            //				con.site = site;
            //				if(pcs[n].ChildShape.visible)
            //					con.visible = true;
            //				from.connection = con;	//a lot of crossing...to make life easy really
            //				from.parentNode =to;
            //				to.childNodes.Add(from);
            //
            //
            //			}

            return(abs);
        }