Merge "Bug 2480: Union objects are generated incorrectly when using bits type"
[yangtools.git] / yang / yang-common / src / main / java / org / opendaylight / yangtools / yang / common / RpcResultBuilder.java
1 /*
2  * Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.yangtools.yang.common;
10
11 import com.google.common.collect.ImmutableList;
12 import com.google.common.util.concurrent.Futures;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import java.util.Collection;
15 import java.util.Collections;
16 import org.opendaylight.yangtools.concepts.Builder;
17 import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
18 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
19
20 /**
21  * A builder for creating RpcResult instances.
22  *
23  * @author Thomas Pantelis
24  *
25  * @param <T> the result value type
26  */
27 public final class RpcResultBuilder<T> implements Builder<RpcResult<T>> {
28
29     private static class RpcResultImpl<T> implements RpcResult<T> {
30
31         private final Collection<RpcError> errors;
32         private final T result;
33         private final boolean successful;
34
35         RpcResultImpl( final boolean successful, final T result,
36                        final Collection<RpcError> errors ) {
37             this.successful = successful;
38             this.result = result;
39             this.errors = errors;
40         }
41
42         @Override
43         public Collection<RpcError> getErrors() {
44             return errors;
45         }
46
47         @Override
48         public T getResult() {
49             return result;
50         }
51
52         @Override
53         public boolean isSuccessful() {
54             return successful;
55         }
56
57         @Override
58         public String toString(){
59             return "RpcResult [successful=" + successful + ", result="
60                     + result + ", errors=" + errors + "]";
61         }
62     }
63
64     private static class RpcErrorImpl implements RpcError {
65
66         private final String applicationTag;
67         private final String tag;
68         private final String info;
69         private final ErrorSeverity severity;
70         private final String message;
71         private final ErrorType errorType;
72         private final Throwable cause;
73
74         RpcErrorImpl( final ErrorSeverity severity, final ErrorType errorType,
75                 final String tag, final String message, final String applicationTag, final String info,
76                 final Throwable cause ) {
77             this.severity = severity;
78             this.errorType = errorType;
79             this.tag = tag;
80             this.message = message;
81             this.applicationTag = applicationTag;
82             this.info = info;
83             this.cause = cause;
84         }
85
86         @Override
87         public String getApplicationTag() {
88             return applicationTag;
89         }
90
91         @Override
92         public String getTag() {
93             return tag;
94         }
95
96         @Override
97         public String getInfo() {
98             return info;
99         }
100
101         @Override
102         public ErrorSeverity getSeverity() {
103             return severity;
104         }
105
106         @Override
107         public String getMessage(){
108             return message;
109         }
110
111         @Override
112         public ErrorType getErrorType() {
113             return errorType;
114         }
115
116         @Override
117         public Throwable getCause() {
118             return cause;
119         }
120
121         @Override
122         public String toString(){
123             return "RpcError [message=" + message + ", severity="
124                     + severity + ", errorType=" + errorType + ", tag=" + tag
125                     + ", applicationTag=" + applicationTag + ", info=" + info
126                     + ", cause=" + cause + "]";
127         }
128     }
129
130     private ImmutableList.Builder<RpcError> errors;
131     private T result;
132     private final boolean successful;
133
134     private RpcResultBuilder( final boolean successful, final T result ) {
135         this.successful = successful;
136         this.result = result;
137     }
138
139     /**
140      * Returns a builder for a successful result.
141      */
142     public static <T> RpcResultBuilder<T> success() {
143         return new RpcResultBuilder<T>( true, null );
144     }
145
146     /**
147      * Returns a builder for a successful result.
148      *
149      * @param result the result value
150      */
151     public static <T> RpcResultBuilder<T> success( final T result ) {
152          return new RpcResultBuilder<T>( true, result );
153     }
154
155     /**
156      * Returns a builder for a successful result.
157      *
158      * @param builder builder for the result value
159      */
160     public static <T> RpcResultBuilder<T> success( final Builder<T> builder ) {
161         return success(builder.build());
162     }
163
164     /**
165      * Returns a builder for a failed result.
166      */
167     public static <T> RpcResultBuilder<T> failed() {
168         return new RpcResultBuilder<T>( false, null );
169     }
170
171     /**
172      * Returns a builder based on the given status.
173      *
174      * @param success true if successful, false otherwise.
175      */
176     public static <T> RpcResultBuilder<T> status( final boolean success ) {
177         return new RpcResultBuilder<T>( success, null );
178     }
179
180     /**
181      * Returns a builder from another RpcResult.
182      *
183      * @param other the other RpcResult.
184      */
185     public static <T> RpcResultBuilder<T> from( final RpcResult<T> other ) {
186         return new RpcResultBuilder<T>( other.isSuccessful(), other.getResult() )
187                                                       .withRpcErrors( other.getErrors() );
188     }
189
190     /**
191      * Creates an RpcError with severity ERROR for reuse.
192      *
193      * @param errorType the conceptual layer at which the error occurred.
194      * @param tag a short string that identifies the general type of error condition. See
195      *        {@link RpcError#getTag} for a list of suggested values.
196      * @param message a string suitable for human display that describes the error condition.
197      *
198      * @return an RpcError
199      */
200     public static RpcError newError( final ErrorType errorType, final String tag, final String message ) {
201         return new RpcErrorImpl( ErrorSeverity.ERROR, errorType,
202                 tag != null ? tag : "operation-failed", message, null, null, null );
203     }
204
205     /**
206      * Creates an RpcError with severity ERROR for reuse.
207      *
208      * @param errorType the conceptual layer at which the error occurred.
209      * @param tag a short string that identifies the general type of error condition. See
210      *        {@link RpcError#getTag} for a list of suggested values.
211      * @param message a string suitable for human display that describes the error condition.
212      * * @param applicationTag a short string that identifies the specific type of error condition.
213      * @param info a string containing additional information to provide extended
214      *        and/or implementation-specific debugging information.
215      * @param cause the exception that triggered the error.
216      *
217      * @return an RpcError
218      */
219     public static RpcError newError(  final ErrorType errorType, final String tag, final String message,
220             final String applicationTag, final String info, final Throwable cause ) {
221         return new RpcErrorImpl( ErrorSeverity.ERROR, errorType,
222                 tag != null ? tag : "operation-failed", message, applicationTag, info, cause );
223     }
224
225     /**
226      * Creates an RpcError with severity WARNING for reuse.
227      *
228      * @param errorType the conceptual layer at which the warning occurred.
229      * @param tag a short string that identifies the general type of warning condition. See
230      *        {@link RpcError#getTag} for a list of suggested values.
231      * @param message a string suitable for human display that describes the warning condition.
232      *
233      * @return an RpcError
234      */
235     public static RpcError newWarning( final ErrorType errorType, final String tag, final String message ) {
236         return new RpcErrorImpl( ErrorSeverity.WARNING, errorType, tag, message, null, null, null );
237     }
238
239     /**
240      * Creates an RpcError with severity WARNING for reuse.
241      *
242      * @param errorType the conceptual layer at which the warning occurred.
243      * @param tag a short string that identifies the general type of warning condition. See
244      *        {@link RpcError#getTag} for a list of suggested values.
245      * @param message a string suitable for human display that describes the warning condition.
246      * * @param applicationTag a short string that identifies the specific type of warning condition.
247      * @param info a string containing additional information to provide extended
248      *        and/or implementation-specific debugging information.
249      * @param cause the exception that triggered the warning.
250      *
251      * @return an RpcError
252      */
253     public static RpcError newWarning(  final ErrorType errorType, final String tag, final String message,
254             final String applicationTag, final String info, final Throwable cause ) {
255         return new RpcErrorImpl( ErrorSeverity.WARNING, errorType, tag, message,
256                                  applicationTag, info, cause );
257     }
258
259     /**
260      * Sets the value of the result.
261      *
262      * @param result the result value
263      */
264     public RpcResultBuilder<T> withResult( final T result ) {
265         this.result = result;
266         return this;
267     }
268
269     /**
270      * Sets the value of the result.
271      *
272      * @param builder builder for the result value
273      */
274     public RpcResultBuilder<T> withResult( final Builder<T> builder ) {
275         return withResult(builder.build());
276     }
277
278     private void addError( final ErrorSeverity severity, final ErrorType errorType,
279             final String tag, final String message, final String applicationTag, final String info,
280             final Throwable cause ) {
281
282         addError( new RpcErrorImpl( severity, errorType,
283                                     tag != null ? tag : "operation-failed", message,
284                                     applicationTag, info, cause ) );
285     }
286
287     private void addError( final RpcError error ) {
288
289         if( errors == null ) {
290             errors = new ImmutableList.Builder<RpcError>();
291         }
292
293         errors.add( error );
294     }
295
296     /**
297      * Adds a warning to the result.
298      *
299      * @param errorType the conceptual layer at which the warning occurred.
300      * @param tag a short string that identifies the general type of warning condition. See
301      *        {@link RpcError#getTag} for a list of suggested values.
302      * @param message a string suitable for human display that describes the warning condition.
303      */
304     public RpcResultBuilder<T> withWarning( final ErrorType errorType, final String tag, final String message ) {
305         addError( ErrorSeverity.WARNING, errorType, tag, message, null, null, null );
306         return this;
307     }
308
309     /**
310      * Adds a warning to the result.
311      *
312      * @param errorType the conceptual layer at which the warning occurred.
313      * @param tag a short string that identifies the general type of warning condition. See
314      *        {@link RpcError#getTag} for a list of suggested values.
315      * @param message a string suitable for human display that describes the warning condition.
316      * @param applicationTag a short string that identifies the specific type of warning condition.
317      * @param info a string containing additional information to provide extended
318      *        and/or implementation-specific debugging information.
319      * @param cause the exception that triggered the warning.
320      */
321     public RpcResultBuilder<T> withWarning( final ErrorType errorType, final String tag, final String message,
322             final String applicationTag, final String info, final Throwable cause ) {
323         addError( ErrorSeverity.WARNING, errorType, tag, message, applicationTag, info, cause );
324         return this;
325     }
326
327     /**
328      * Adds an error to the result. The general error tag defaults to "operation-failed".
329      *
330      * @param errorType the conceptual layer at which the error occurred.
331      * @param message a string suitable for human display that describes the error condition.
332      */
333     public RpcResultBuilder<T> withError( final ErrorType errorType, final String message ) {
334         addError( ErrorSeverity.ERROR, errorType, null, message, null, null, null );
335         return this;
336     }
337
338     /**
339      * Adds an error to the result.
340      *
341      * @param errorType the conceptual layer at which the error occurred.
342      * @param tag a short string that identifies the general type of error condition. See
343      *        {@link RpcError#getTag} for a list of suggested values.
344      * @param message a string suitable for human display that describes the error condition.
345      */
346     public RpcResultBuilder<T> withError( final ErrorType errorType, final String tag, final String message ) {
347         addError( ErrorSeverity.ERROR, errorType, tag, message, null, null, null );
348         return this;
349     }
350
351     /**
352      * Adds an error to the result. The general error tag defaults to "operation-failed".
353      *
354      * @param errorType the conceptual layer at which the error occurred.
355      * @param message a string suitable for human display that describes the error condition.
356      * @param cause the exception that triggered the error.
357      */
358     public RpcResultBuilder<T> withError( final ErrorType errorType, final String message,
359                                           final Throwable cause ) {
360         addError( ErrorSeverity.ERROR, errorType, null, message, null, null, cause );
361         return this;
362     }
363
364     /**
365      * Adds an error to the result.
366      *
367      * @param errorType the conceptual layer at which the error occurred.
368      * @param tag a short string that identifies the general type of error condition. See
369      *        {@link RpcError#getTag} for a list of suggested values.
370      * @param message a string suitable for human display that describes the error condition.
371      * @param applicationTag a short string that identifies the specific type of error condition.
372      * @param info a string containing additional information to provide extended
373      *        and/or implementation-specific debugging information.
374      * @param cause the exception that triggered the error.
375      */
376     public RpcResultBuilder<T> withError( final ErrorType errorType, final String tag, final String message,
377             final String applicationTag, final String info, final Throwable cause ) {
378         addError( ErrorSeverity.ERROR, errorType, tag, message, applicationTag, info, cause );
379         return this;
380     }
381
382     /**
383      * Adds an RpcError.
384      *
385      * @param error the RpcError
386      */
387     public RpcResultBuilder<T> withRpcError( final RpcError error ) {
388         addError( error );
389         return this;
390     }
391
392     /**
393      * Adds RpcErrors.
394      *
395      * @param errors the list of RpcErrors
396      */
397     public RpcResultBuilder<T> withRpcErrors( final Collection<RpcError> errors ) {
398         if( errors != null ) {
399             for( RpcError error: errors ) {
400                 addError( error );
401             }
402         }
403         return this;
404     }
405
406     @Override
407     public RpcResult<T> build() {
408
409         return new RpcResultImpl<T>( successful, result,
410                 errors != null ? errors.build() : Collections.<RpcError>emptyList() );
411     }
412
413     /**
414      * Builds RpcResult and wraps it in a Future
415      *
416      * This is a convenience method to assist those writing rpcs
417      * that produce immediate results.  It allows you to replace
418      *
419      * Futures.immediateFuture(rpcResult.build())
420      *
421      * with
422      *
423      * rpcResult.buildFuture();
424      *
425      * @return Future for RpcResult built by RpcResultBuilder
426      *
427      */
428     public ListenableFuture<RpcResult<T>> buildFuture() {
429         return Futures.immediateFuture(build());
430     }
431 }