package Microsoft.Samples;
//-----------------------------------------------------------------------
//  This file is part of the Microsoft .NET Framework SDK Code Samples.
// 
//  Copyright (C) Microsoft Corporation.  All rights reserved.
// 
// This source code is intended only as a supplement to Microsoft
// Development Tools and/or on-line documentation.  See these other
// materials for detailed information regarding Microsoft code samples.
// 
// THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//-----------------------------------------------------------------------
import System.*;
import System.Globalization.*;
import System.IO.*;
import System.Diagnostics.*;
import System.Reflection.*;
import System.Runtime.Serialization.*;
import System.Runtime.Serialization.Formatters.Binary.*;
import System.Runtime.Serialization.Formatters.Soap.*;
import System.Text.*;
import System.Collections.*;
import System.Security.Permissions.*;

public class SimpleGraph
{
    public static void main(String[] args) throws System.Exception
    {
        Console.WriteLine("Create object graph");
        TreeNode node = new TreeNode("");
        FillTree(node);
        node.PrintTree(Console.get_Out());

        Console.Write("Serializing object graph to disk..");
        Stream s = (Stream)(File.Open("foo.xml", FileMode.Create,
            FileAccess.Write));
        SoapFormatter b = new SoapFormatter();
        b.Serialize(s, node);
        s.Close();
        Console.WriteLine("Complete.");
        Console.Write("Deserializing object graph from disk..");
        Stream r = (Stream)(File.Open("foo.xml", FileMode.Open,
            FileAccess.Read));
        SoapFormatter c = new SoapFormatter();
        TreeNode n = (TreeNode) c.Deserialize(r);
        Console.WriteLine("Complete.");
        r.Close();
        n.PrintTree(Console.get_Out());
        Console.WriteLine("\r\nPress Return to exit.");
        Console.Read();
    } //main

    public static void FillTree(TreeNode node) throws System.Exception
    {
        Type types[] = Object.class.ToType().get_Module().get_Assembly().
            GetTypes();
        node.AddChild(new TreeNode(Object.class.ToType().get_FullName()));

        for (int iCtr = 0; iCtr < types.get_Length(); iCtr++) {
            Type t = types[iCtr];
            if (t.get_BaseType() == null) {
                continue;
            }
            if (!(t.get_IsPublic())) {
                continue;
            }
            TreeNode n = node.Find(t.get_BaseType().get_FullName());
            if (n != null) {
                n.AddChild(new TreeNode(t));
            }
        }
    } //FillTree
} //SimpleGraph

/** @attribute Serializable()
 */
public class TreeNode implements ISerializable
{
    private Object value;
    private ArrayList children;

    protected TreeNode(SerializationInfo info, StreamingContext c) 
        throws System.Exception
    {
        value = info.GetValue("value", Object.class.ToType());
        children = new ArrayList();
        Object o;

        for (int i = 1; i < info.get_MemberCount(); i++) {
            o = info.GetValue(((Int32)i).ToString(new NumberFormatInfo()),
                Object.class.ToType());
            children.Add(o);
        }
    } //TreeNode

    public TreeNode(Object o) throws System.Exception
    {
        if (o == null) {
            throw new System.Exception("Object passed to constructor must not be null");
        }
        value = o;
        children = new ArrayList();
    } //TreeNode

    /** @attribute SecurityPermissionAttribute(SecurityAction.LinkDemand, 
            SerializationFormatter = true)
     */
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        if (value == null) {
            info.AddValue("value", "NULL");
        }
        else {
            info.AddValue("value", value.ToString() + "(SAVED)");
        }
        int i = 1;
        for (int iCtr1 = 0; iCtr1 < children.get_Count(); iCtr1++) {
            Object o = children.get_Item(iCtr1);
            if (o == null) {
                continue;
            }
            info.AddValue(((Int32)i).ToString(new NumberFormatInfo()), o);
            i++;
        }
    } //GetObjectData

    /** @property 
     */
    public Object get_Value()
    {
        return value;
    } //get_Value

    public void AddChild(TreeNode child)
    {
        if (!(children.Contains(child))) {
            children.Add(child);
        }
    } //AddChild

    public TreeNode Find(Object o) throws System.Exception
    {
        if (o == null) {
            throw new System.Exception("Object passed to find must not be null");
        }
        if (value.Equals(o)) {
            return this;
        }
        for (int iCtr2 = 0; iCtr2 < children.get_Count(); iCtr2++) {
            TreeNode t = (TreeNode)children.get_Item(iCtr2);
            TreeNode w = t.Find(o);
            if (w != null) {
                return w;
            }
        }
        return null;
    } //Find

    public boolean Equals(Object obj)
    {
        if (!(obj instanceof TreeNode)) {
            return false;
        }
        TreeNode t = (TreeNode)(obj);
        return t.value.Equals(this.value);
    } //Equals

    public int GetHashCode()
    {
        return 0;
    } //GetHashCode

    public String ToString()
    {
        return value.ToString();
    } //ToString

    public void PrintTree(TextWriter output)
    {
        PrintTree(output, 0);
    } //PrintTree

    private void PrintTree(TextWriter output, int offset)
    {
        StringBuilder sb1 = new StringBuilder();
        StringBuilder sb2 = new StringBuilder();
        for (int i = 0; i < offset - 1; i++) {
            sb1.Append(" ");
            sb1.Append("|");
            sb2.Append(" ");
            sb2.Append("|");
        }
        if (offset >= 1) {
            sb1.Append(" ");
            sb1.Append("+-");
            sb2.Append(" ");
            sb2.Append("|");
        }
        output.WriteLine("{0}", sb2);
        output.WriteLine("{0}{1}", sb1, value);
        for (int iCtr3 = 0; iCtr3 < children.get_Count(); iCtr3++) {
            TreeNode t = (TreeNode)children.get_Item(iCtr3);
            t.PrintTree(output, offset + 1);
        }
    } //PrintTree
} //TreeNode