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.container;
22 
23 import hunt.lang.exception;
24 import hunt.string;
25 
26 /** 
27  * Wraps multiple exceptions.
28  *
29  * Allows multiple exceptions to be thrown as a single exception.
30  */
31 // 
32 class MultiException :Exception
33 {
34     private List!Exception nested;
35 
36     /* ------------------------------------------------------------ */
37     this()
38     {
39         super("Multiple exceptions");
40     }
41 
42     /* ------------------------------------------------------------ */
43     void add(Exception e)
44     {
45         if (e is null)
46             throw new IllegalArgumentException("");
47 
48         if(nested is null)
49         {
50             // initCause(e);
51             nested = new ArrayList!Exception();
52         }
53         // else
54         //     addSuppressed(e);
55         
56         if (typeid(e) == typeid(MultiException))
57         {
58             MultiException me = cast(MultiException)e;
59             // nested.addAll(me.nested);
60         }
61         else
62             nested.add(e);
63     }
64 
65     /* ------------------------------------------------------------ */
66     int size()
67     {
68         return (nested is null)?0:nested.size();
69     }
70     
71     /* ------------------------------------------------------------ */
72     List!Exception getThrowables()
73     {
74         if(nested is null)
75             return new EmptyList!Exception();  // Collections.emptyList();
76         return nested;
77     }
78     
79     /* ------------------------------------------------------------ */
80     Exception getThrowable(int i)
81     {
82         return nested.get(i);
83     }
84 
85     /* ------------------------------------------------------------ */
86     /** Throw a multiexception.
87      * If this multi exception is empty then no action is taken. If it
88      * contains a single exception that is thrown, otherwise the this
89      * multi exception is thrown. 
90      * @exception Exception the Error or Exception if nested is 1, or the MultiException itself if nested is more than 1.
91      */
92     void ifExceptionThrow()
93     {
94         if(nested is null)
95             return;
96         
97         switch (nested.size())
98         {
99           case 0:
100               break;
101           case 1:
102               Exception th=nested.get(0);
103               if (typeid(th) == typeid(Error))
104                   throw cast(Error)th;
105               if (typeid(th) == typeid(Exception))
106                   throw cast(Exception)th;
107                 break;
108 
109           default:
110               throw this;
111         }
112     }
113     
114     /* ------------------------------------------------------------ */
115     /** Throw a Runtime exception.
116      * If this multi exception is empty then no action is taken. If it
117      * contains a single error or runtime exception that is thrown, otherwise the this
118      * multi exception is thrown, wrapped in a runtime onException.
119      * @exception Error If this exception contains exactly 1 {@link Error} 
120      * @exception RuntimeException If this exception contains 1 {@link Exception} but it is not an error,
121      *                             or it contains more than 1 {@link Exception} of any type.
122      */
123     void ifExceptionThrowRuntime()
124     {
125         if(nested is null)
126             return;
127         
128         switch (nested.size())
129         {
130           case 0:
131               break;
132           case 1:
133               Exception th=nested.get(0);
134               if (typeid(th) == typeid(Error))
135                   throw cast(Error)th;
136               else if (typeid(th) == typeid(RuntimeException))
137                   throw cast(RuntimeException)th;
138               else
139                   throw new RuntimeException(th);
140           default:
141               throw new RuntimeException(this);
142         }
143     }
144     
145     /* ------------------------------------------------------------ */
146     /** Throw a multiexception.
147      * If this multi exception is empty then no action is taken. If it
148      * contains a any exceptions then this
149      * multi exception is thrown. 
150      * @throws MultiException the multiexception if there are nested exception
151      */
152     void ifExceptionThrowMulti()
153     {
154         if(nested is null)
155             return;
156         
157         if (nested.size()>0)
158             throw this;
159     }
160 
161     /* ------------------------------------------------------------ */
162     override
163     string toString()
164     {
165         StringBuilder str = new StringBuilder();
166         str.append(MultiException.stringof);
167         if((nested is null) || (nested.size()<=0)) {
168             str.append("[]");
169         } else {
170             str.append(nested.toString());
171         }
172         return str.toString();
173     }
174 
175 }