001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements. See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership. The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the  "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    /*
019     * $Id: Hashtree2Node.java 475902 2006-11-16 20:03:16Z minchau $
020     */
021    
022    package org.apache.xml.utils;
023    
024    import java.util.ArrayList;
025    import java.util.Enumeration;
026    import java.util.Hashtable;
027    import java.util.Iterator;
028    import java.util.List;
029    
030    import org.w3c.dom.Document;
031    import org.w3c.dom.Element;
032    import org.w3c.dom.Node;
033    
034    /**
035     * Simple static utility to convert Hashtable to a Node.  
036     *
037     * @see org.apache.xalan.xslt.EnvironmentCheck
038     * @see org.apache.xalan.lib.Extensions
039     * @author shane_curcuru@us.ibm.com
040     * @version $Id: Hashtree2Node.java 475902 2006-11-16 20:03:16Z minchau $
041     * @xsl.usage general
042     */
043    public abstract class Hashtree2Node
044    {
045    
046        /**
047         * Convert a Hashtable into a Node tree.  
048         * 
049         * <p>The hash may have either Hashtables as values (in which 
050         * case we recurse) or other values, in which case we print them 
051         * as &lt;item> elements, with a 'key' attribute with the value 
052         * of the key, and the element contents as the value.</p>
053         *
054         * <p>If args are null we simply return without doing anything. 
055         * If we encounter an error, we will attempt to add an 'ERROR' 
056         * Element with exception info; if that doesn't work we simply 
057         * return without doing anything else byt printStackTrace().</p>
058         *
059         * @param hash to get info from (may have sub-hashtables)
060         * @param name to use as parent element for appended node
061         * futurework could have namespace and prefix as well
062         * @param container Node to append our report to
063         * @param factory Document providing createElement, etc. services
064         */
065        public static void appendHashToNode(Hashtable hash, String name, 
066                Node container, Document factory)
067        {
068            // Required arguments must not be null
069            if ((null == container) || (null == factory) || (null == hash))
070            {
071                return;
072            }
073    
074            // name we will provide a default value for
075            String elemName = null;
076            if ((null == name) || ("".equals(name)))
077                elemName = "appendHashToNode";
078            else
079                elemName = name;
080    
081            try
082            {
083                Element hashNode = factory.createElement(elemName);
084                container.appendChild(hashNode);
085    
086                Enumeration keys = hash.keys();
087                List v = new ArrayList();
088    
089                while (keys.hasMoreElements())
090                {
091                    Object key = keys.nextElement();
092                    String keyStr = key.toString();
093                    Object item = hash.get(key);
094    
095                    if (item instanceof Hashtable)
096                    {
097                        // Ensure a pre-order traversal; add this hashes 
098                        //  items before recursing to child hashes
099                        // Save name and hash in two steps
100                        v.add(keyStr);
101                        v.add((Hashtable) item);
102                    }
103                    else
104                    {
105                        try
106                        {
107                            // Add item to node
108                            Element node = factory.createElement("item");
109                            node.setAttribute("key", keyStr);
110                            node.appendChild(factory.createTextNode((String)item));
111                            hashNode.appendChild(node);
112                        }
113                        catch (Exception e)
114                        {
115                            Element node = factory.createElement("item");
116                            node.setAttribute("key", keyStr);
117                            node.appendChild(factory.createTextNode("ERROR: Reading " + key + " threw: " + e.toString()));
118                            hashNode.appendChild(node);
119                        }
120                    }
121                }
122    
123                // Now go back and do the saved hashes
124                Iterator it = v.iterator();
125                while (it.hasNext())
126                {
127                    // Retrieve name and hash in two steps
128                    String n = (String) it.next();
129                    Hashtable h = (Hashtable) it.next();
130    
131                    appendHashToNode(h, n, hashNode, factory);
132                }
133            }
134            catch (Exception e2)
135            {
136                // Ooops, just bail (suggestions for a safe thing 
137                //  to do in this case appreciated)
138                e2.printStackTrace();
139            }
140        }    
141    }