2 * Copyright (c) 2014 Brocade Communications Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.common;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.collect.ImmutableList;
13 import com.google.common.util.concurrent.FluentFuture;
14 import com.google.common.util.concurrent.Futures;
15 import java.io.Serializable;
16 import java.util.Collection;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.opendaylight.yangtools.concepts.Mutable;
21 * A builder for creating RpcResult instances.
23 * @author Thomas Pantelis
25 * @param <T> the result value type
27 public final class RpcResultBuilder<T> implements Mutable {
29 private static class RpcResultImpl<T> implements RpcResult<T>, Serializable {
30 private static final long serialVersionUID = 1L;
32 private final ImmutableList<RpcError> errors;
33 private final T result;
34 private final boolean successful;
36 RpcResultImpl(final boolean successful, final T result, final ImmutableList<RpcError> errors) {
37 this.successful = successful;
39 this.errors = requireNonNull(errors);
43 public ImmutableList<RpcError> getErrors() {
48 public T getResult() {
53 public boolean isSuccessful() {
58 public String toString() {
59 return "RpcResult [successful=" + successful + ", result="
60 + result + ", errors=" + errors + "]";
64 private static class RpcErrorImpl implements RpcError, Serializable {
65 private static final long serialVersionUID = 1L;
67 private final String applicationTag;
68 private final ErrorTag tag;
69 private final String info;
70 private final ErrorSeverity severity;
71 private final String message;
72 private final ErrorType errorType;
73 private final Throwable cause;
75 RpcErrorImpl(final ErrorSeverity severity, final ErrorType errorType, final ErrorTag tag, final String message,
76 final String applicationTag, final String info, final Throwable cause) {
77 this.severity = severity;
78 this.errorType = errorType;
80 this.message = message;
81 this.applicationTag = applicationTag;
87 public String getApplicationTag() {
88 return applicationTag;
92 public ErrorTag getTag() {
97 public String getInfo() {
102 public ErrorSeverity getSeverity() {
107 public String getMessage() {
112 public ErrorType getErrorType() {
117 public Throwable getCause() {
122 public String toString() {
123 return "RpcError [message=" + message + ", severity="
124 + severity + ", errorType=" + errorType + ", tag=" + tag
125 + ", applicationTag=" + applicationTag + ", info=" + info
126 + ", cause=" + cause + "]";
130 private ImmutableList.Builder<RpcError> errors;
132 private final boolean successful;
134 private RpcResultBuilder(final boolean successful, final T result) {
135 this.successful = successful;
136 this.result = result;
140 * Returns a builder for a successful result.
142 public static <T> @NonNull RpcResultBuilder<T> success() {
143 return new RpcResultBuilder<>(true, null);
147 * Returns a builder for a successful result.
149 * @param result the result value
151 public static <T> @NonNull RpcResultBuilder<T> success(final T result) {
152 return new RpcResultBuilder<>(true, result);
156 * Returns a builder for a failed result.
158 public static <T> @NonNull RpcResultBuilder<T> failed() {
159 return new RpcResultBuilder<>(false, null);
163 * Returns a builder based on the given status.
165 * @param success true if successful, false otherwise.
167 public static <T> @NonNull RpcResultBuilder<T> status(final boolean success) {
168 return new RpcResultBuilder<>(success, null);
172 * Returns a builder from another RpcResult.
174 * @param other the other RpcResult.
176 public static <T> @NonNull RpcResultBuilder<T> from(final RpcResult<T> other) {
177 return new RpcResultBuilder<>(other.isSuccessful(), other.getResult())
178 .withRpcErrors(other.getErrors());
182 * Creates an RpcError with severity ERROR for reuse.
184 * @param errorType the conceptual layer at which the error occurred.
185 * @param tag a short string that identifies the general type of error condition. See
186 * {@link RpcError#getTag} for a list of suggested values.
187 * @param message a string suitable for human display that describes the error condition.
189 * @return an RpcError
191 public static @NonNull RpcError newError(final ErrorType errorType, final ErrorTag tag, final String message) {
192 return new RpcErrorImpl(ErrorSeverity.ERROR, errorType, tag != null ? tag : ErrorTag.OPERATION_FAILED, message,
197 * Creates an RpcError with severity ERROR for reuse.
199 * @param errorType the conceptual layer at which the error occurred.
200 * @param tag a short string that identifies the general type of error condition. See
201 * {@link RpcError#getTag} for a list of suggested values.
202 * @param message a string suitable for human display that describes the error condition.
203 * @param applicationTag a short string that identifies the specific type of error condition.
204 * @param info a string containing additional information to provide extended
205 * and/or implementation-specific debugging information.
206 * @param cause the exception that triggered the error.
208 * @return an RpcError
210 public static @NonNull RpcError newError(final ErrorType errorType, final ErrorTag tag, final String message,
211 final String applicationTag, final String info, final Throwable cause) {
212 return new RpcErrorImpl(ErrorSeverity.ERROR, errorType, tag != null ? tag : ErrorTag.OPERATION_FAILED, message,
213 applicationTag, info, cause);
217 * Creates an RpcError with severity WARNING for reuse.
219 * @param errorType the conceptual layer at which the warning occurred.
220 * @param tag a short string that identifies the general type of warning condition. See
221 * {@link RpcError#getTag} for a list of suggested values.
222 * @param message a string suitable for human display that describes the warning condition.
224 * @return an RpcError
226 public static @NonNull RpcError newWarning(final ErrorType errorType, final ErrorTag tag, final String message) {
227 return new RpcErrorImpl(ErrorSeverity.WARNING, errorType, tag, message, null, null, null);
231 * Creates an RpcError with severity WARNING for reuse.
233 * @param errorType the conceptual layer at which the warning occurred.
234 * @param tag a short string that identifies the general type of warning condition. See
235 * {@link RpcError#getTag} for a list of suggested values.
236 * @param message a string suitable for human display that describes the warning condition.
237 * @param applicationTag a short string that identifies the specific type of warning condition.
238 * @param info a string containing additional information to provide extended
239 * and/or implementation-specific debugging information.
240 * @param cause the exception that triggered the warning.
242 * @return an RpcError
244 public static @NonNull RpcError newWarning(final ErrorType errorType, final ErrorTag tag, final String message,
245 final String applicationTag, final String info, final Throwable cause) {
246 return new RpcErrorImpl(ErrorSeverity.WARNING, errorType, tag, message, applicationTag, info, cause);
250 * Sets the value of the result.
252 * @param result the result value
254 @SuppressWarnings("checkstyle:hiddenField")
255 public @NonNull RpcResultBuilder<T> withResult(final T result) {
256 this.result = result;
260 private void addError(final ErrorSeverity severity, final ErrorType errorType, final ErrorTag tag,
261 final String message, final String applicationTag, final String info, final Throwable cause) {
262 addError(new RpcErrorImpl(severity, errorType, tag != null ? tag : ErrorTag.OPERATION_FAILED, message,
263 applicationTag, info, cause));
266 private void addError(final RpcError error) {
268 if (errors == null) {
269 errors = new ImmutableList.Builder<>();
276 * Adds a warning to the result.
278 * @param errorType the conceptual layer at which the warning occurred.
279 * @param tag a short string that identifies the general type of warning condition. See
280 * {@link RpcError#getTag} for a list of suggested values.
281 * @param message a string suitable for human display that describes the warning condition.
283 public @NonNull RpcResultBuilder<T> withWarning(final ErrorType errorType, final ErrorTag tag,
284 final String message) {
285 addError(ErrorSeverity.WARNING, errorType, tag, message, null, null, null);
290 * Adds a warning to the result.
292 * @param errorType the conceptual layer at which the warning occurred.
293 * @param tag a short string that identifies the general type of warning condition. See
294 * {@link RpcError#getTag} for a list of suggested values.
295 * @param message a string suitable for human display that describes the warning condition.
296 * @param applicationTag a short string that identifies the specific type of warning condition.
297 * @param info a string containing additional information to provide extended
298 * and/or implementation-specific debugging information.
299 * @param cause the exception that triggered the warning.
301 public @NonNull RpcResultBuilder<T> withWarning(final ErrorType errorType, final ErrorTag tag, final String message,
302 final String applicationTag, final String info, final Throwable cause) {
303 addError(ErrorSeverity.WARNING, errorType, tag, message, applicationTag, info, cause);
308 * Adds an error to the result. The general error tag defaults to "operation-failed".
310 * @param errorType the conceptual layer at which the error occurred.
311 * @param message a string suitable for human display that describes the error condition.
313 public @NonNull RpcResultBuilder<T> withError(final ErrorType errorType, final String message) {
314 addError(ErrorSeverity.ERROR, errorType, null, message, null, null, null);
319 * Adds an error to the result.
321 * @param errorType the conceptual layer at which the error occurred.
322 * @param tag a short string that identifies the general type of error condition. See
323 * {@link RpcError#getTag} for a list of suggested values.
324 * @param message a string suitable for human display that describes the error condition.
326 public @NonNull RpcResultBuilder<T> withError(final ErrorType errorType, final ErrorTag tag, final String message) {
327 addError(ErrorSeverity.ERROR, errorType, tag, message, null, null, null);
332 * Adds an error to the result. The general error tag defaults to "operation-failed".
334 * @param errorType the conceptual layer at which the error occurred.
335 * @param message a string suitable for human display that describes the error condition.
336 * @param cause the exception that triggered the error.
338 public @NonNull RpcResultBuilder<T> withError(final ErrorType errorType, final String message,
339 final Throwable cause) {
340 addError(ErrorSeverity.ERROR, errorType, null, message, null, null, cause);
345 * Adds an error to the result.
347 * @param errorType the conceptual layer at which the error occurred.
348 * @param tag a short string that identifies the general type of error condition. See
349 * {@link RpcError#getTag} for a list of suggested values.
350 * @param message a string suitable for human display that describes the error condition.
351 * @param applicationTag a short string that identifies the specific type of error condition.
352 * @param info a string containing additional information to provide extended
353 * and/or implementation-specific debugging information.
354 * @param cause the exception that triggered the error.
356 public @NonNull RpcResultBuilder<T> withError(final ErrorType errorType, final ErrorTag tag, final String message,
357 final String applicationTag, final String info, final Throwable cause) {
358 addError(ErrorSeverity.ERROR, errorType, tag, message, applicationTag, info, cause);
365 * @param error the RpcError
367 public @NonNull RpcResultBuilder<T> withRpcError(final RpcError error) {
375 * @param rpcErrors the list of RpcErrors
377 public RpcResultBuilder<T> withRpcErrors(final Collection<? extends RpcError> rpcErrors) {
378 if (rpcErrors != null) {
379 for (RpcError error : rpcErrors) {
387 * Build the resulting {@link RpcResult}.
389 * @return An RpcResult instance
391 public @NonNull RpcResult<T> build() {
392 return new RpcResultImpl<>(successful, result, errors != null ? errors.build() : ImmutableList.of());
396 * Builds RpcResult and wraps it in a Future.
399 * This is a convenience method to assist those writing RPCs that produce immediate results. It allows you to
400 * replace {@code FluentFuture.from(Futures.immediateFuture(rpcResult.build()))} with
401 * {@code rpcResult.buildFuture()}
403 * @return Future for RpcResult built by RpcResultBuilder
405 public @NonNull FluentFuture<RpcResult<T>> buildFuture() {
406 return FluentFuture.from(Futures.immediateFuture(build()));