001    /*
002     * Copyright 2005 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.metro;
020    
021    import java.io.Serializable;
022    import java.net.URI;
023    
024    import net.dpml.component.ModelException;
025    
026    /**
027     * Exception that describes a series of validation issues.
028     *
029     * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
030     * @version 1.2.0
031     */
032    public final class ValidationException extends ModelException
033    {
034        //--------------------------------------------------------------------------
035        // static
036        //--------------------------------------------------------------------------
037        
038       /**
039        * Serial version identifier.
040        */
041        static final long serialVersionUID = 1L;
042    
043        //--------------------------------------------------------------------------
044        // state
045        //--------------------------------------------------------------------------
046        
047        private final Object m_source;
048        private final Issue[] m_issues;
049        
050        //--------------------------------------------------------------------------
051        // constructor
052        //--------------------------------------------------------------------------
053        
054       /**
055        * Creation of a new <tt>ValidationException</tt>.
056        * @param uri controller uri
057        * @param source the source object
058        * @param issues the array of issues
059        */
060        public ValidationException( URI uri, Object source, Issue[] issues )
061        {
062            super( uri, createMessage( source, issues ) );
063            if( null == source )
064            {
065                throw new NullPointerException( "source" );
066            }
067            if( null == issues )
068            {
069                throw new NullPointerException( "issues" );
070            }
071            m_source = source;
072            m_issues = issues;
073        }
074        
075       /**
076        * Return the source object.
077        * @return the source of the validation errors
078        */
079        public Object getSource()
080        {
081            return m_source;
082        }
083        
084       /**
085        * Return the array iof issues.
086        * @return the issues array
087        */
088        public Issue[] getIssues()
089        {
090            return m_issues;
091        }
092        
093        //--------------------------------------------------------------------------
094        // utilities
095        //--------------------------------------------------------------------------
096        
097        private static String createMessage( final Object source, final Issue[] issues )
098        {
099            if( null == source )
100            {
101                throw new NullPointerException( "source" );
102            }
103            if( null == issues )
104            {
105                throw new NullPointerException( "issues" );
106            }
107            String message = 
108              "Validation failure in ["
109                + source.getClass().getName()
110                + "#" 
111                + System.identityHashCode( source )
112                + "] due to ["
113                + issues.length
114                + "] unresolved issue(s).";
115            return message;
116        }
117        
118       /**
119        * Issue implementation.
120        */
121        public static final class Issue implements Serializable
122        {
123            private final String m_issueKey;
124            private final String m_issueMessage;
125        
126           /**
127            * Creation of a new issue.
128            * @param key the key
129            * @param message the message
130            */
131            public Issue( String key, String message )
132            {
133                if( null == key )
134                {
135                    throw new NullPointerException( "key" );
136                }
137                if( null == message )
138                {
139                    throw new NullPointerException( "message" );
140                }
141                m_issueKey = key;
142                m_issueMessage = message;
143            }
144            
145           /**
146            * Return the issue key.
147            * @return the key
148            */
149            public String getKey()
150            {
151                return m_issueKey;
152            }
153            
154           /**
155            * Return the issue message.
156            * @return the message
157            */
158            public String getMessage()
159            {
160                return m_issueMessage;
161            }
162            
163           /**
164            * Test is the supplied object is equal to this object.
165            * @param other the other object
166            * @return true if the object are equivalent
167            */
168            public boolean equals( Object other )
169            {
170                if( null == other )
171                {
172                    return false;
173                }
174                else if( other instanceof Issue )
175                {
176                    Issue issue = (Issue) other;
177                    if( !m_issueKey.equals( issue.m_issueKey ) )
178                    {
179                        return false;
180                    }
181                    return m_issueMessage.equals( issue.m_issueMessage );
182                }
183                else
184                {
185                    return false;
186                }
187            }
188            
189           /**
190            * Return the hashcode for the object.
191            * @return the hashcode value
192            */
193            public int hashCode()
194            {
195                return m_issueKey.hashCode() + m_issueMessage.hashCode();
196            }
197            
198           /**
199            * Return a string representation of the type.
200            * @return the stringified type
201            */
202            public String toString()
203            {
204                return "issue:[" + m_issueKey + "] " + m_issueMessage;
205            }
206        }
207    }