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.Serial;
16 import java.io.Serializable;
17 import java.util.Collection;
18 import org.eclipse.jdt.annotation.NonNull;
19 import org.opendaylight.yangtools.concepts.Mutable;
22 * A builder for creating RpcResult instances.
24 * @author Thomas Pantelis
26 * @param <T> the result value type
28 public final class RpcResultBuilder<T> implements Mutable {
30 private static class RpcResultImpl<T> implements RpcResult<T>, Serializable {
32 private static final long serialVersionUID = 1L;
34 private final ImmutableList<RpcError> errors;
35 private final T result;
36 private final boolean successful;
38 RpcResultImpl(final boolean successful, final T result, final ImmutableList<RpcError> errors) {
39 this.successful = successful;
41 this.errors = requireNonNull(errors);
45 public ImmutableList<RpcError> getErrors() {
50 public T getResult() {
55 public boolean isSuccessful() {
60 public String toString() {
61 return "RpcResult [successful=" + successful + ", result="
62 + result + ", errors=" + errors + "]";
66 private static class RpcErrorImpl implements RpcError, Serializable {
68 private static final long serialVersionUID = 1L;
70 private final String applicationTag;
71 private final ErrorTag tag;
72 private final String info;
73 private final ErrorSeverity severity;
74 private final String message;
75 private final ErrorType errorType;
76 private final Throwable cause;
78 RpcErrorImpl(final ErrorSeverity severity, final ErrorType errorType, final ErrorTag tag, final String message,
79 final String applicationTag, final String info, final Throwable cause) {
80 this.severity = severity;
81 this.errorType = errorType;
83 this.message = message;
84 this.applicationTag = applicationTag;
90 public String getApplicationTag() {
91 return applicationTag;
95 public ErrorTag getTag() {
100 public String getInfo() {
105 public ErrorSeverity getSeverity() {
110 public String getMessage() {
115 public ErrorType getErrorType() {
120 public Throwable getCause() {
125 public String toString() {
126 return "RpcError [message=" + message + ", severity="
127 + severity + ", errorType=" + errorType + ", tag=" + tag
128 + ", applicationTag=" + applicationTag + ", info=" + info
129 + ", cause=" + cause + "]";
133 private ImmutableList.Builder<RpcError> errors;
135 private final boolean successful;
137 private RpcResultBuilder(final boolean successful, final T result) {
138 this.successful = successful;
139 this.result = result;
143 * Returns a builder for a successful result.
145 public static <T> @NonNull RpcResultBuilder<T> success() {
146 return new RpcResultBuilder<>(true, null);
150 * Returns a builder for a successful result.
152 * @param result the result value
154 public static <T> @NonNull RpcResultBuilder<T> success(final T result) {
155 return new RpcResultBuilder<>(true, result);
159 * Returns a builder for a failed result.
161 public static <T> @NonNull RpcResultBuilder<T> failed() {
162 return new RpcResultBuilder<>(false, null);
166 * Returns a builder based on the given status.
168 * @param success true if successful, false otherwise.
170 public static <T> @NonNull RpcResultBuilder<T> status(final boolean success) {
171 return new RpcResultBuilder<>(success, null);
175 * Returns a builder from another RpcResult.
177 * @param other the other RpcResult.
179 public static <T> @NonNull RpcResultBuilder<T> from(final RpcResult<T> other) {
180 return new RpcResultBuilder<>(other.isSuccessful(), other.getResult())
181 .withRpcErrors(other.getErrors());
185 * Creates an RpcError with severity ERROR for reuse.
187 * @param errorType the conceptual layer at which the error occurred.
188 * @param tag a short string that identifies the general type of error condition. See
189 * {@link RpcError#getTag} for a list of suggested values.
190 * @param message a string suitable for human display that describes the error condition.
192 * @return an RpcError
194 public static @NonNull RpcError newError(final ErrorType errorType, final ErrorTag tag, final String message) {
195 return new RpcErrorImpl(ErrorSeverity.ERROR, errorType, tag != null ? tag : ErrorTag.OPERATION_FAILED, message,
200 * Creates an RpcError with severity ERROR for reuse.
202 * @param errorType the conceptual layer at which the error occurred.
203 * @param tag a short string that identifies the general type of error condition. See
204 * {@link RpcError#getTag} for a list of suggested values.
205 * @param message a string suitable for human display that describes the error condition.
206 * @param applicationTag a short string that identifies the specific type of error condition.
207 * @param info a string containing additional information to provide extended
208 * and/or implementation-specific debugging information.
209 * @param cause the exception that triggered the error.
211 * @return an RpcError
213 public static @NonNull RpcError newError(final ErrorType errorType, final ErrorTag tag, final String message,
214 final String applicationTag, final String info, final Throwable cause) {
215 return new RpcErrorImpl(ErrorSeverity.ERROR, errorType, tag != null ? tag : ErrorTag.OPERATION_FAILED, message,
216 applicationTag, info, cause);
220 * Creates an RpcError with severity WARNING for reuse.
222 * @param errorType the conceptual layer at which the warning occurred.
223 * @param tag a short string that identifies the general type of warning condition. See
224 * {@link RpcError#getTag} for a list of suggested values.
225 * @param message a string suitable for human display that describes the warning condition.
227 * @return an RpcError
229 public static @NonNull RpcError newWarning(final ErrorType errorType, final ErrorTag tag, final String message) {
230 return new RpcErrorImpl(ErrorSeverity.WARNING, errorType, tag, message, null, null, null);
234 * Creates an RpcError with severity WARNING for reuse.
236 * @param errorType the conceptual layer at which the warning occurred.
237 * @param tag a short string that identifies the general type of warning condition. See
238 * {@link RpcError#getTag} for a list of suggested values.
239 * @param message a string suitable for human display that describes the warning condition.
240 * @param applicationTag a short string that identifies the specific type of warning condition.
241 * @param info a string containing additional information to provide extended
242 * and/or implementation-specific debugging information.
243 * @param cause the exception that triggered the warning.
245 * @return an RpcError
247 public static @NonNull RpcError newWarning(final ErrorType errorType, final ErrorTag tag, final String message,
248 final String applicationTag, final String info, final Throwable cause) {
249 return new RpcErrorImpl(ErrorSeverity.WARNING, errorType, tag, message, applicationTag, info, cause);
253 * Sets the value of the result.
255 * @param result the result value
257 @SuppressWarnings("checkstyle:hiddenField")
258 public @NonNull RpcResultBuilder<T> withResult(final T result) {
259 this.result = result;
263 private void addError(final ErrorSeverity severity, final ErrorType errorType, final ErrorTag tag,
264 final String message, final String applicationTag, final String info, final Throwable cause) {
265 addError(new RpcErrorImpl(severity, errorType, tag != null ? tag : ErrorTag.OPERATION_FAILED, message,
266 applicationTag, info, cause));
269 private void addError(final RpcError error) {
271 if (errors == null) {
272 errors = new ImmutableList.Builder<>();
279 * Adds a warning to the result.
281 * @param errorType the conceptual layer at which the warning occurred.
282 * @param tag a short string that identifies the general type of warning condition. See
283 * {@link RpcError#getTag} for a list of suggested values.
284 * @param message a string suitable for human display that describes the warning condition.
286 public @NonNull RpcResultBuilder<T> withWarning(final ErrorType errorType, final ErrorTag tag,
287 final String message) {
288 addError(ErrorSeverity.WARNING, errorType, tag, message, null, null, null);
293 * Adds a warning to the result.
295 * @param errorType the conceptual layer at which the warning occurred.
296 * @param tag a short string that identifies the general type of warning condition. See
297 * {@link RpcError#getTag} for a list of suggested values.
298 * @param message a string suitable for human display that describes the warning condition.
299 * @param applicationTag a short string that identifies the specific type of warning condition.
300 * @param info a string containing additional information to provide extended
301 * and/or implementation-specific debugging information.
302 * @param cause the exception that triggered the warning.
304 public @NonNull RpcResultBuilder<T> withWarning(final ErrorType errorType, final ErrorTag tag, final String message,
305 final String applicationTag, final String info, final Throwable cause) {
306 addError(ErrorSeverity.WARNING, errorType, tag, message, applicationTag, info, cause);
311 * Adds an error to the result. The general error tag defaults to "operation-failed".
313 * @param errorType the conceptual layer at which the error occurred.
314 * @param message a string suitable for human display that describes the error condition.
316 public @NonNull RpcResultBuilder<T> withError(final ErrorType errorType, final String message) {
317 addError(ErrorSeverity.ERROR, errorType, null, message, null, null, null);
322 * Adds an error to the result.
324 * @param errorType the conceptual layer at which the error occurred.
325 * @param tag a short string that identifies the general type of error condition. See
326 * {@link RpcError#getTag} for a list of suggested values.
327 * @param message a string suitable for human display that describes the error condition.
329 public @NonNull RpcResultBuilder<T> withError(final ErrorType errorType, final ErrorTag tag, final String message) {
330 addError(ErrorSeverity.ERROR, errorType, tag, message, null, null, null);
335 * Adds an error to the result. The general error tag defaults to "operation-failed".
337 * @param errorType the conceptual layer at which the error occurred.
338 * @param message a string suitable for human display that describes the error condition.
339 * @param cause the exception that triggered the error.
341 public @NonNull RpcResultBuilder<T> withError(final ErrorType errorType, final String message,
342 final Throwable cause) {
343 addError(ErrorSeverity.ERROR, errorType, null, message, null, null, cause);
348 * Adds an error to the result.
350 * @param errorType the conceptual layer at which the error occurred.
351 * @param tag a short string that identifies the general type of error condition. See
352 * {@link RpcError#getTag} for a list of suggested values.
353 * @param message a string suitable for human display that describes the error condition.
354 * @param applicationTag a short string that identifies the specific type of error condition.
355 * @param info a string containing additional information to provide extended
356 * and/or implementation-specific debugging information.
357 * @param cause the exception that triggered the error.
359 public @NonNull RpcResultBuilder<T> withError(final ErrorType errorType, final ErrorTag tag, final String message,
360 final String applicationTag, final String info, final Throwable cause) {
361 addError(ErrorSeverity.ERROR, errorType, tag, message, applicationTag, info, cause);
368 * @param error the RpcError
370 public @NonNull RpcResultBuilder<T> withRpcError(final RpcError error) {
378 * @param rpcErrors the list of RpcErrors
380 public RpcResultBuilder<T> withRpcErrors(final Collection<? extends RpcError> rpcErrors) {
381 if (rpcErrors != null) {
382 for (RpcError error : rpcErrors) {
390 * Build the resulting {@link RpcResult}.
392 * @return An RpcResult instance
394 public @NonNull RpcResult<T> build() {
395 return new RpcResultImpl<>(successful, result, errors != null ? errors.build() : ImmutableList.of());
399 * Builds RpcResult and wraps it in a Future.
402 * This is a convenience method to assist those writing RPCs that produce immediate results. It allows you to
403 * replace {@code FluentFuture.from(Futures.immediateFuture(rpcResult.build()))} with
404 * {@code rpcResult.buildFuture()}
406 * @return Future for RpcResult built by RpcResultBuilder
408 public @NonNull FluentFuture<RpcResult<T>> buildFuture() {
409 return FluentFuture.from(Futures.immediateFuture(build()));