001    /*
002     * Copyright 2006 Stephen J. McConnell.
003     *
004     * Licensed  under the  Apache License,  Version 2.0  (the "License");
005     * you may not use  this file  except in  compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *   http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed  under the  License is distributed on an "AS IS" BASIS,
012     * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
013     * implied.
014     *
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    
019    package net.dpml.util;
020    
021    import java.io.IOException;
022    
023    import org.w3c.dom.Document;
024    import org.w3c.dom.Element;
025    import org.w3c.dom.NamedNodeMap;
026    import org.w3c.dom.Node;
027    
028    /**
029     * Exception related to data decoding from a DOM element.
030     */
031    public class DecodingException extends IOException
032    {
033        private final Element m_element;
034        
035       /**
036        * Create a new decoding exception.
037        * @param element the element representing the source of the error
038        * @param message the exception message
039        */
040        public DecodingException( Element element, String message )
041        {
042            this( element, message, null );
043        }
044        
045       /**
046        * Create a new decoding exception.
047        * @param element the element representing the source of the error
048        * @param message the exception message
049        * @param cause the causal exception
050        */
051        public DecodingException( Element element, String message, Throwable cause )
052        {
053            super( message );
054            if( null != cause )
055            {
056                super.initCause( cause );
057            }
058            m_element = element;
059        }
060        
061       /**
062        * Get the element that is the subject of this exception.
063        * @return the subject element
064        */
065        public Element getElement()
066        {
067            return m_element;
068        }
069        
070       /**
071        * Return a string representation of the exception.
072        * @return the string value
073        */
074        public String getMessage()
075        {
076            try
077            {
078                String message = super.getMessage();
079                StringBuffer buffer = new StringBuffer( message );
080                buffer.append( "\n" );
081                Element element = getElement();
082                String listing = list( element );
083                buffer.append( listing );
084                Document document = element.getOwnerDocument();
085                String uri = document.getDocumentURI();
086                if( null != uri )
087                {
088                    buffer.append( "\nDocument: " + uri );
089                }
090                return buffer.toString();
091            }
092            catch( Throwable e )
093            {
094                return super.getMessage();
095            }
096        }
097        
098       /**
099        * Static utility operation that returns a syring representation of a DOM element.
100        * @param element the element to stringify
101        * @return the string value
102        */
103        public static String list( Element element )
104        {
105            return list( element, "" );
106        }
107        
108       /**
109        * Static utility operation that returns a syring representation of a DOM element.
110        * @param element the element to stringify
111        * @param pad padding offset
112        * @return the string value
113        */
114        public static String list( Element element, String pad )
115        {
116            StringBuffer buffer = new StringBuffer();
117            String tag = element.getTagName();
118            buffer.append( pad + "<" );
119            buffer.append( tag );
120            NamedNodeMap map = element.getAttributes();
121            for( int i=0; i<map.getLength(); i++ )
122            {
123                Node item = map.item( i );
124                buffer.append( " " + item.getNodeName() + "=\"" );
125                buffer.append( item.getNodeValue() );
126                buffer.append( "\"" );
127            }
128            
129            Element[] children = ElementHelper.getChildren( element );
130            if( children.length > 0 )
131            {
132                buffer.append( ">" );
133                for( int i=0; i<children.length; i++ )
134                {
135                    Element child = children[i];
136                    String listing = list( child, pad + "  " );
137                    String tagName = child.getTagName();
138                    buffer.append( "\n" + listing );
139                }
140                buffer.append( "\n" + pad + "</" + tag + ">" );
141            }
142            else
143            {
144                buffer.append( "/>" );
145            }
146            return buffer.toString();
147        }
148    }