1600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/*
2600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* Conditions Of Use
3600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang*
4600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* This software was developed by employees of the National Institute of
5600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* Standards and Technology (NIST), an agency of the Federal Government.
6600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* Pursuant to title 15 Untied States Code Section 105, works of NIST
7600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* employees are not subject to copyright protection in the United States
8600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* and are considered to be in the public domain.  As a result, a formal
9600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* license is not needed to use the software.
10600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang*
11600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* This software is provided by NIST as a service and is expressly
12600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
13600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
14600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
15600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* AND DATA ACCURACY.  NIST does not warrant or make any representations
16600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* regarding the use of the software or the results thereof, including but
17600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* not limited to the correctness, accuracy, reliability or usefulness of
18600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* the software.
19600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang*
20600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* Permission to use this software is contingent upon your acceptance
21600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* of the terms of this agreement
22600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang*
23600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* .
24600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang*
25600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang*/
26600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/******************************************************************************
27600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Product of NIST/ITL Advanced Networking Technologies Division (ANTD).      *
28600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ******************************************************************************/
29600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpackage gov.nist.core;
30600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.lang.reflect.*;
31600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.io.Serializable;
32600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.*;
33600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
34600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/**
35600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* The base class from which all the other classes in the
36600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* sipheader, sdpfields and sipmessage packages are extended.
37600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* Provides a few utility funcitons such as indentation and
38600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* pretty printing that all other classes benifit from.
39600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang*
40600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang*@version 1.2
41600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang*
42600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang*@author M. Ranganathan   <br/>
43600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang*
44600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang*
45600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang*
46600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang*/
47600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
48600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpublic abstract class GenericObject implements Serializable, Cloneable {
49600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Useful constants.
50600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final String SEMICOLON = Separators.SEMICOLON;
51600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final String COLON = Separators.COLON;
52600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final String COMMA = Separators.COMMA;
53600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final String SLASH = Separators.SLASH;
54600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final String SP = Separators.SP;
55600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final String EQUALS = Separators.EQUALS;
56600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final String STAR = Separators.STAR;
57600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final String NEWLINE = Separators.NEWLINE;
58600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final String RETURN = Separators.RETURN;
59600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final String LESS_THAN = Separators.LESS_THAN;
60600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final String GREATER_THAN = Separators.GREATER_THAN;
61600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final String AT = Separators.AT;
62600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final String DOT = Separators.DOT;
63600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final String QUESTION = Separators.QUESTION;
64600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final String POUND = Separators.POUND;
65600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final String AND = Separators.AND;
66600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final String LPAREN = Separators.LPAREN;
67600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final String RPAREN = Separators.RPAREN;
68600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final String DOUBLE_QUOTE = Separators.DOUBLE_QUOTE;
69600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final String QUOTE = Separators.QUOTE;
70600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final String HT = Separators.HT;
71600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final String PERCENT = Separators.PERCENT;
72600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
73600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final Set<Class<?>> immutableClasses = new HashSet<Class<?>> (10);
74600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    static final String[] immutableClassNames ={
75600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        "String", "Character",
76600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        "Boolean", "Byte", "Short", "Integer", "Long",
77600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        "Float", "Double"
78600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        };
79600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
80600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected int indentation;
81600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected String stringRepresentation;
82600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected Match matchExpression; // Pattern matcher.
83600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
84600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    static {
85600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
86600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            for (int i = 0; i < immutableClassNames.length; i++)
87600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                immutableClasses.add(Class.forName("java.lang." + immutableClassNames [i]));
88600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (ClassNotFoundException e) {
89600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new RuntimeException ("Internal error", e);
90600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
91600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
92600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
93600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Set the  pattern matcher. To match on the
94600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * field of a sip message, set the match expression in the match template
95600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * and invoke the match function. This useful because
96600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * SIP headers and parameters may appear in different orders and are not
97600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * necessarily in canonical form. This makes it hard to write a pattern
98600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * matcher that relies on regular expressions alone.
99600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Thus we rely on the following  strategy i.e. To do pattern matching on
100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * an incoming message, first parse it, and then construct a match template,
101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * filling in the fields that you want to
102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * match. The rules for matching are: A null object matches wild card -
103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * that is a match template of null matches any parsed SIP object.
104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * To match with any subfield, set the match template on a template object
105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * of the same type and invoke the match interface.
106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Regular expressions matching implements the gov.nist.sip.Match interface
107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * that can be done using the Jakarta regexp package for example.
108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * package included herein. This can be used to implement the Match interface
109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * <a href=http://www.apache.org> See the APACHE website for documents </a>
110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void setMatcher(Match matchExpression) {
113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (matchExpression == null)
114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new IllegalArgumentException("null arg!");
115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.matchExpression = matchExpression;
116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Return the match expression.
119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *@return the match expression that has previously been set.
120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public Match getMatcher() {
122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return matchExpression;
123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static Class<?> getClassFromName(String className) {
126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return Class.forName(className);
128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (Exception ex) {
129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            InternalErrorHandler.handleException(ex);
130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return null;
131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static boolean isMySubclass(Class<?> other) {
135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return GenericObject.class.isAssignableFrom(other);
137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Clones the given object.
141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *  If the object is a wrapped type, an array, a GenericObject
142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *  or a GenericObjectList, it is cast to the appropriate type
143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *  and the clone() method is invoked. Else if the object implements
144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *  Cloneable, reflection is used to discover and invoke
145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *  clone() method. Otherwise, the original object is returned.
146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static Object makeClone(Object obj) {
148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (obj == null)
149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new NullPointerException("null obj!");
150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Class<?> c = obj.getClass();
151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Object clone_obj = obj;
152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (immutableClasses.contains (c))
153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return obj;
154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        else if (c.isArray ()) {
155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Class<?> ec = c.getComponentType();
156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (! ec.isPrimitive())
157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                clone_obj = ((Object []) obj).clone();
158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            else {
159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (ec == Character.TYPE)
160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    clone_obj = ((char []) obj).clone();
161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                else if (ec == Boolean.TYPE)
162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    clone_obj = ((boolean []) obj).clone();
163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (ec == Byte.TYPE)
164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    clone_obj = ((byte []) obj).clone();
165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                else if (ec == Short.TYPE)
166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    clone_obj = ((short []) obj).clone();
167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                else if (ec == Integer.TYPE)
168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    clone_obj = ((int []) obj).clone();
169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                else if (ec == Long.TYPE)
170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    clone_obj = ((long []) obj).clone();
171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                else if (ec == Float.TYPE)
172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    clone_obj = ((float []) obj).clone();
173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                else if (ec == Double.TYPE)
174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    clone_obj = ((double []) obj).clone();
175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } else if (GenericObject.class.isAssignableFrom (c))
177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            clone_obj = ((GenericObject) obj).clone();
178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        else if (GenericObjectList.class.isAssignableFrom (c))
179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            clone_obj = ((GenericObjectList) obj).clone();
180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        else if (Cloneable.class.isAssignableFrom (c)) {
181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // If a clone method exists for the object, then
182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // invoke it
183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            try {
184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                Method meth = c.getMethod("clone", (Class[]) null);
185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                clone_obj = meth.invoke(obj,(Object[]) null);
186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } catch (SecurityException ex) {
187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } catch (IllegalArgumentException ex) {
188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                InternalErrorHandler.handleException(ex);
189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } catch (IllegalAccessException ex) {
190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } catch (InvocationTargetException ex) {
191600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } catch (NoSuchMethodException ex) {
192600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
193600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
194600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return clone_obj;
195600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
196600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
197600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Clones this object.
198600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
199600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public Object clone() {
200600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
201600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return super.clone();
202600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (CloneNotSupportedException e) {
203600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new RuntimeException("Internal error");
204600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
205600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
206600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
207600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Recursively override the fields of this object with the fields
208600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * of a new object. This is useful when you want to genrate a template
209600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * and override the fields of an incoming SIPMessage with another
210600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * SIP message that you have already generated.
211600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
212600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param mergeObject is the replacement object.  The override
213600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * obect must be of the same class as this object.
214600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Set any fields that you do not want to override as null in the
215600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * mergeOject object.
216600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
217600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void merge(Object mergeObject) {
218600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Base case.
219600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (mergeObject == null)
220600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return;
221600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
222600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (!mergeObject.getClass().equals(this.getClass()))
223600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new IllegalArgumentException("Bad override object");
224600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
225600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Class<?> myclass = this.getClass();
226600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        while (true) {
227600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Field[] fields = myclass.getDeclaredFields();
228600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            for (int i = 0; i < fields.length; i++) {
229600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                Field f = fields[i];
230600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                int modifier = f.getModifiers();
231600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (Modifier.isPrivate(modifier)) {
232600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    continue;
233600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                } else if (Modifier.isStatic(modifier)) {
234600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    continue;
235600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                } else if (Modifier.isInterface(modifier)) {
236600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    continue;
237600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
238600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                Class<?> fieldType = f.getType();
239600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                String fname = fieldType.toString();
240600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                try {
241600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    // Primitive fields are printed with type: value
242600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (fieldType.isPrimitive()) {
243600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        if (fname.compareTo("int") == 0) {
244600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            int intfield = f.getInt(mergeObject);
245600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            f.setInt(this, intfield);
246600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        } else if (fname.compareTo("short") == 0) {
247600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            short shortField = f.getShort(mergeObject);
248600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            f.setShort(this, shortField);
249600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        } else if (fname.compareTo("char") == 0) {
250600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            char charField = f.getChar(mergeObject);
251600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            f.setChar(this, charField);
252600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        } else if (fname.compareTo("long") == 0) {
253600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            long longField = f.getLong(mergeObject);
254600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            f.setLong(this, longField);
255600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        } else if (fname.compareTo("boolean") == 0) {
256600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            boolean booleanField = f.getBoolean(mergeObject);
257600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            f.setBoolean(this, booleanField);
258600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        } else if (fname.compareTo("double") == 0) {
259600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            double doubleField = f.getDouble(mergeObject);
260600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            f.setDouble(this, doubleField);
261600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        } else if (fname.compareTo("float") == 0) {
262600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            float floatField = f.getFloat(mergeObject);
263600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            f.setFloat(this, floatField);
264600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        }
265600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    } else {
266600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        Object obj = f.get(this);
267600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        Object mobj = f.get(mergeObject);
268600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        if (mobj == null)
269600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            continue;
270600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        if (obj == null) {
271600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            f.set(this, mobj);
272600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            continue;
273600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        }
274600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        if (obj instanceof GenericObject) {
275600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            GenericObject gobj = (GenericObject) obj;
276600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            gobj.merge(mobj);
277600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        } else {
278600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            f.set(this, mobj);
279600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        }
280600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
281600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                } catch (IllegalAccessException ex1) {
282600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    ex1.printStackTrace();
283600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    continue; // we are accessing a private field...
284600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
285600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
286600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            myclass = myclass.getSuperclass();
287600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (myclass.equals(GenericObject.class))
288600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                break;
289600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
290600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
291600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
292600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected GenericObject() {
293600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        indentation = 0;
294600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        stringRepresentation = "";
295600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
296600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
297600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected String getIndentation() {
298600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    char [] chars = new char [indentation];
299600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    java.util.Arrays.fill (chars, ' ');
300600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    return new String (chars);
301600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
302600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
303600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
304600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Add a new string to the accumulated string representation.
305600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
306600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
307600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected void sprint(String a) {
308600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (a == null) {
309600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            stringRepresentation += getIndentation();
310600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            stringRepresentation += "<null>\n";
311600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return;
312600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
313600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (a.compareTo("}") == 0 || a.compareTo("]") == 0) {
314600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            indentation--;
315600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
316600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        stringRepresentation += getIndentation();
317600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        stringRepresentation += a;
318600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        stringRepresentation += "\n";
319600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (a.compareTo("{") == 0 || a.compareTo("[") == 0) {
320600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            indentation++;
321600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
322600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
323600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
324600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
325600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
326600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Pretty printing function accumulator for objects.
327600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
328600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
329600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected void sprint(Object o) {
330600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        sprint(o.toString());
331600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
332600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
333600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
334600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Pretty printing accumulator function for ints
335600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
336600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
337600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected void sprint(int intField) {
338600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        sprint(String.valueOf(intField));
339600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
340600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
341600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
342600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Pretty printing accumulator function for shorts
343600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
344600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected void sprint(short shortField) {
345600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        sprint(String.valueOf(shortField));
346600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
347600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
348600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
349600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Pretty printing accumulator function for chars
350600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
351600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
352600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected void sprint(char charField) {
353600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        sprint(String.valueOf(charField));
354600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
355600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
356600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
357600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
358600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Pretty printing accumulator function for longs
359600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
360600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
361600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected void sprint(long longField) {
362600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        sprint(String.valueOf(longField));
363600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
364600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
365600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
366600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Pretty printing accumulator function for booleans
367600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
368600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
369600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected void sprint(boolean booleanField) {
370600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        sprint(String.valueOf(booleanField));
371600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
372600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
373600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
374600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Pretty printing accumulator function for doubles
375600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
376600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
377600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected void sprint(double doubleField) {
378600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        sprint(String.valueOf(doubleField));
379600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
380600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
381600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
382600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Pretty printing accumulator function for floats
383600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
384600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
385600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected void sprint(float floatField) {
386600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        sprint(String.valueOf(floatField));
387600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
388600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
389600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
390600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Debug printing function.
391600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
392600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
393600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected void dbgPrint() {
394600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Debug.println(debugDump());
395600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
396600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
397600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
398600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Debug printing function.
399600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
400600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected void dbgPrint(String s) {
401600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Debug.println(s);
402600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
403600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
404600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
405600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * An introspection based equality predicate for GenericObjects.
406600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *@param that is the other object to test against.
407600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *@return true if the objects are euqal and false otherwise
408600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
409600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public boolean equals(Object that) {
410600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if ( that == null ) return false;
411600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (!this.getClass().equals(that.getClass()))
412600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return false;
413600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Class<?> myclass = this.getClass();
414600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Class<?> hisclass = that.getClass();
415600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        while (true) {
416600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Field[] fields = myclass.getDeclaredFields();
417600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Field[] hisfields = hisclass.getDeclaredFields();
418600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            for (int i = 0; i < fields.length; i++) {
419600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                Field f = fields[i];
420600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                Field g = hisfields[i];
421600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // Only print protected and public members.
422600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                int modifier = f.getModifiers();
423600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE)
424600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    continue;
425600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                Class<?> fieldType = f.getType();
426600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                String fieldName = f.getName();
427600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (fieldName.compareTo("stringRepresentation") == 0) {
428600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    continue;
429600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
430600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (fieldName.compareTo("indentation") == 0) {
431600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    continue;
432600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
433600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                try {
434600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    // Primitive fields are printed with type: value
435600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (fieldType.isPrimitive()) {
436600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        String fname = fieldType.toString();
437600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        if (fname.compareTo("int") == 0) {
438600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            if (f.getInt(this) != g.getInt(that))
439600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                return false;
440600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        } else if (fname.compareTo("short") == 0) {
441600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            if (f.getShort(this) != g.getShort(that))
442600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                return false;
443600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        } else if (fname.compareTo("char") == 0) {
444600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            if (f.getChar(this) != g.getChar(that))
445600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                return false;
446600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        } else if (fname.compareTo("long") == 0) {
447600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            if (f.getLong(this) != g.getLong(that))
448600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                return false;
449600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        } else if (fname.compareTo("boolean") == 0) {
450600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            if (f.getBoolean(this) != g.getBoolean(that))
451600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                return false;
452600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        } else if (fname.compareTo("double") == 0) {
453600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            if (f.getDouble(this) != g.getDouble(that))
454600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                return false;
455600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        } else if (fname.compareTo("float") == 0) {
456600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            if (f.getFloat(this) != g.getFloat(that))
457600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                return false;
458600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        }
459600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    } else if (g.get(that) == f.get(this))
460600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        return true;
461600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    else if (f.get(this) == null)
462600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        return false;
463600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    else if (g.get(that) == null)
464600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        return false;
465600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    else if (g.get(that) == null && f.get(this) != null)
466600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        return false;
467600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    else if (!f.get(this).equals(g.get(that)))
468600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        return false;
469600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                } catch (IllegalAccessException ex1) {
470600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    InternalErrorHandler.handleException(ex1);
471600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
472600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
473600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (myclass.equals(GenericObject.class))
474600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                break;
475600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            else {
476600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                myclass = myclass.getSuperclass();
477600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                hisclass = hisclass.getSuperclass();
478600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
479600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
480600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
481600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return true;
482600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
483600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
484600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** An introspection based predicate matching using a template
485600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * object. Allows for partial match of two protocl Objects.
486600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *@param other the match pattern to test against. The match object
487600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * has to be of the same type (class). Primitive types
488600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * and non-sip fields that are non null are matched for equality.
489600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Null in any field  matches anything. Some book-keeping fields
490600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * are ignored when making the comparison.
491600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
492600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
493600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public boolean match(Object other) {
494600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (other == null)
495600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return true;
496600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (!this.getClass().equals(other.getClass()))
497600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return false;
498600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        GenericObject that = (GenericObject) other;
499600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Class<?> myclass = this.getClass();
500600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Field[] fields = myclass.getDeclaredFields();
501600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Class<?> hisclass = other.getClass();
502600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Field[] hisfields = hisclass.getDeclaredFields();
503600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        for (int i = 0; i < fields.length; i++) {
504600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Field f = fields[i];
505600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Field g = hisfields[i];
506600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // Only print protected and public members.
507600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            int modifier = f.getModifiers();
508600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE)
509600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                continue;
510600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Class<?> fieldType = f.getType();
511600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            String fieldName = f.getName();
512600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (fieldName.compareTo("stringRepresentation") == 0) {
513600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                continue;
514600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
515600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (fieldName.compareTo("indentation") == 0) {
516600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                continue;
517600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
518600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            try {
519600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // Primitive fields are printed with type: value
520600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (fieldType.isPrimitive()) {
521600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    String fname = fieldType.toString();
522600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (fname.compareTo("int") == 0) {
523600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        if (f.getInt(this) != g.getInt(that))
524600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            return false;
525600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    } else if (fname.compareTo("short") == 0) {
526600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        if (f.getShort(this) != g.getShort(that))
527600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            return false;
528600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    } else if (fname.compareTo("char") == 0) {
529600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        if (f.getChar(this) != g.getChar(that))
530600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            return false;
531600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    } else if (fname.compareTo("long") == 0) {
532600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        if (f.getLong(this) != g.getLong(that))
533600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            return false;
534600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    } else if (fname.compareTo("boolean") == 0) {
535600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        if (f.getBoolean(this) != g.getBoolean(that))
536600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            return false;
537600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    } else if (fname.compareTo("double") == 0) {
538600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        if (f.getDouble(this) != g.getDouble(that))
539600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            return false;
540600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    } else if (fname.compareTo("float") == 0) {
541600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        if (f.getFloat(this) != g.getFloat(that))
542600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            return false;
543600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
544600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                } else {
545600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    Object myObj = f.get(this);
546600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    Object hisObj = g.get(that);
547600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (hisObj != null && myObj == null)
548600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        return false;
549600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    else if (hisObj == null && myObj != null)
550600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        continue;
551600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    else if (hisObj == null && myObj == null)
552600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        continue;
553600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    else if (
554600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        hisObj instanceof java.lang.String
555600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            && myObj instanceof java.lang.String) {
556600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        if ((((String) hisObj).trim()).equals(""))
557600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            continue;
558600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        if (((String) myObj)
559600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            .compareToIgnoreCase((String) hisObj)
560600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            != 0)
561600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            return false;
562600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    } else if (
563600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        GenericObject.isMySubclass(myObj.getClass())
564600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            && !((GenericObject) myObj).match(hisObj))
565600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        return false;
566600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    else if (
567600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        GenericObjectList.isMySubclass(myObj.getClass())
568600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            && !((GenericObjectList) myObj).match(hisObj))
569600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        return false;
570600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
571600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
572600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } catch (IllegalAccessException ex1) {
573600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                InternalErrorHandler.handleException(ex1);
574600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
575600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
576600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return true;
577600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
578600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
579600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
580600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Generic print formatting function:
581600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Does depth-first descent of the structure and
582600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * recursively prints all non-private objects pointed to
583600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * by this object.
584600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * <bf>
585600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Warning - the following generic string routine will
586600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * bomb (go into infinite loop) if there are any circularly linked
587600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * structures so if you have these, they had better be private!
588600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * </bf>
589600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * We dont have to worry about such things for our structures
590600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *(we never use circular linked structures).
591600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
592600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
593600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String debugDump() {
594600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        stringRepresentation = "";
595600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Class<?> myclass = getClass();
596600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        sprint(myclass.getName());
597600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        sprint("{");
598600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Field[] fields = myclass.getDeclaredFields();
599600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        for (int i = 0; i < fields.length; i++) {
600600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Field f = fields[i];
601600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // Only print protected and public members.
602600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            int modifier = f.getModifiers();
603600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE)
604600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                continue;
605600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Class<?> fieldType = f.getType();
606600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            String fieldName = f.getName();
607600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (fieldName.compareTo("stringRepresentation") == 0) {
608600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // avoid nasty recursions...
609600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                continue;
610600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
611600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (fieldName.compareTo("indentation") == 0) {
612600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // formatting stuff - not relevant here.
613600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                continue;
614600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
615600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sprint(fieldName + ":");
616600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            try {
617600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // Primitive fields are printed with type: value
618600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (fieldType.isPrimitive()) {
619600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    String fname = fieldType.toString();
620600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    sprint(fname + ":");
621600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (fname.compareTo("int") == 0) {
622600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        int intfield = f.getInt(this);
623600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        sprint(intfield);
624600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    } else if (fname.compareTo("short") == 0) {
625600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        short shortField = f.getShort(this);
626600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        sprint(shortField);
627600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    } else if (fname.compareTo("char") == 0) {
628600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        char charField = f.getChar(this);
629600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        sprint(charField);
630600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    } else if (fname.compareTo("long") == 0) {
631600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        long longField = f.getLong(this);
632600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        sprint(longField);
633600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    } else if (fname.compareTo("boolean") == 0) {
634600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        boolean booleanField = f.getBoolean(this);
635600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        sprint(booleanField);
636600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    } else if (fname.compareTo("double") == 0) {
637600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        double doubleField = f.getDouble(this);
638600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        sprint(doubleField);
639600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    } else if (fname.compareTo("float") == 0) {
640600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        float floatField = f.getFloat(this);
641600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        sprint(floatField);
642600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
643600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                } else if (GenericObject.class.isAssignableFrom(fieldType)) {
644600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (f.get(this) != null) {
645600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        sprint(
646600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            ((GenericObject) f.get(this)).debugDump(
647600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                indentation + 1));
648600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    } else {
649600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        sprint("<null>");
650600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
651600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
652600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                } else if (
653600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    GenericObjectList.class.isAssignableFrom(fieldType)) {
654600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (f.get(this) != null) {
655600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        sprint(
656600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            ((GenericObjectList) f.get(this)).debugDump(
657600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                indentation + 1));
658600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    } else {
659600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        sprint("<null>");
660600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
661600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
662600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                } else {
663600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    // Dont do recursion on things that are not
664600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    // of our header type...
665600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (f.get(this) != null) {
666600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        sprint(f.get(this).getClass().getName() + ":");
667600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    } else {
668600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        sprint(fieldType.getName() + ":");
669600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
670600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
671600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    sprint("{");
672600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (f.get(this) != null) {
673600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        sprint(f.get(this).toString());
674600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    } else {
675600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        sprint("<null>");
676600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
677600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    sprint("}");
678600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
679600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } catch (IllegalAccessException ex1) {
680600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                continue; // we are accessing a private field...
681600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } catch (Exception ex) {
682600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                InternalErrorHandler.handleException(ex);
683600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
684600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
685600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        sprint("}");
686600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return stringRepresentation;
687600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
688600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
689600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
690600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Formatter with a given starting indentation.
691600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
692600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String debugDump(int indent) {
693600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        indentation = indent;
694600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String retval = this.debugDump();
695600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        indentation = 0;
696600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return retval;
697600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
698600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
699600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
700600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
701600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *  Get the string encoded version of this object
702600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @since v1.0
703600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
704600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public abstract String encode();
705600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
706600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
707600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Put the encoded version of this object in the given StringBuffer.
708600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
709600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public StringBuffer encode(StringBuffer buffer) {
710600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return buffer.append(encode());
711600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
712600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang}
713