1 //
2 //  ========================================================================
3 //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4 //  ------------------------------------------------------------------------
5 //  All rights reserved. This program and the accompanying materials
6 //  are made available under the terms of the Eclipse Public License v1.0
7 //  and Apache License v2.0 which accompanies this distribution.
8 //
9 //      The Eclipse Public License is available at
10 //      http://www.eclipse.org/legal/epl-v10.html
11 //
12 //      The Apache License v2.0 is available at
13 //      http://www.opensource.org/licenses/apache2.0.php
14 //
15 //  You may elect to redistribute this code under either of these licenses.
16 //  ========================================================================
17 //
18 
19 module hunt.http.codec.http.model.MultiException;
20 
21 import hunt.collection;
22 
23 import hunt.Exceptions;
24 import hunt.text.Common;
25 import hunt.util.StringBuilder;
26 
27 /** 
28  * Wraps multiple exceptions.
29  *
30  * Allows multiple exceptions to be thrown as a single exception.
31  */
32 // 
33 class MultiException : Exception
34 {
35     private List!Exception nested;
36 
37     /* ------------------------------------------------------------ */
38     this()
39     {
40         super("Multiple exceptions");
41     }
42 
43     /* ------------------------------------------------------------ */
44     void add(Exception e)
45     {
46         if (e is null)
47             throw new IllegalArgumentException("");
48 
49         if(nested is null)
50         {
51             // initCause(e);
52             nested = new ArrayList!Exception();
53         }
54         // else
55         //     addSuppressed(e);
56         
57         if (typeid(e) == typeid(MultiException))
58         {
59             MultiException me = cast(MultiException)e;
60             // nested.addAll(me.nested);
61         }
62         else
63             nested.add(e);
64     }
65 
66     /* ------------------------------------------------------------ */
67     int size()
68     {
69         return (nested is null)?0:nested.size();
70     }
71     
72     /* ------------------------------------------------------------ */
73     List!Exception getThrowables()
74     {
75         if(nested is null)
76             return new EmptyList!Exception();  // Collections.emptyList();
77         return nested;
78     }
79     
80     /* ------------------------------------------------------------ */
81     Exception getThrowable(int i)
82     {
83         return nested.get(i);
84     }
85 
86     /* ------------------------------------------------------------ */
87     /** Throw a multiexception.
88      * If this multi exception is empty then no action is taken. If it
89      * contains a single exception that is thrown, otherwise the this
90      * multi exception is thrown. 
91      * @exception Exception the Error or Exception if nested is 1, or the MultiException itself if nested is more than 1.
92      */
93     void ifExceptionThrow()
94     {
95         if(nested is null)
96             return;
97         
98         switch (nested.size())
99         {
100           case 0:
101               break;
102           case 1:
103               Exception th=nested.get(0);
104               if (typeid(th) == typeid(Error))
105                   throw cast(Error)th;
106               if (typeid(th) == typeid(Exception))
107                   throw cast(Exception)th;
108                 break;
109 
110           default:
111               throw this;
112         }
113     }
114     
115     /* ------------------------------------------------------------ */
116     /** Throw a Runtime exception.
117      * If this multi exception is empty then no action is taken. If it
118      * contains a single error or runtime exception that is thrown, otherwise the this
119      * multi exception is thrown, wrapped in a runtime onException.
120      * @exception Error If this exception contains exactly 1 {@link Error} 
121      * @exception RuntimeException If this exception contains 1 {@link Exception} but it is not an error,
122      *                             or it contains more than 1 {@link Exception} of any type.
123      */
124     void ifExceptionThrowRuntime()
125     {
126         if(nested is null)
127             return;
128         
129         switch (nested.size())
130         {
131           case 0:
132               break;
133           case 1:
134                 Exception th = nested.get(0);
135                 Error err = cast(Error)th;
136                 if (err !is null)
137                     throw err;
138                     
139                 RuntimeException rex = cast(RuntimeException)th;
140                 if (rex !is null)
141                     throw rex;
142 
143                 throw new RuntimeException(th);
144 
145           default:
146                 throw new RuntimeException(this);
147         }
148     }
149     
150     /* ------------------------------------------------------------ */
151     /** Throw a multiexception.
152      * If this multi exception is empty then no action is taken. If it
153      * contains a any exceptions then this
154      * multi exception is thrown. 
155      * @throws MultiException the multiexception if there are nested exception
156      */
157     void ifExceptionThrowMulti()
158     {
159         if(nested is null)
160             return;
161         
162         if (nested.size()>0)
163             throw this;
164     }
165 
166     /* ------------------------------------------------------------ */
167     override
168     string toString()
169     {
170         StringBuilder str = new StringBuilder();
171         str.append(MultiException.stringof);
172         if((nested is null) || (nested.size()<=0)) {
173             str.append("[]");
174         } else {
175             str.append(nested.toString());
176         }
177         return str.toString();
178     }
179 
180 }