de6e4800ec274c75967b8775a187b21d1508075e
[yangtools.git] / yang / yang-common / src / main / java / org / opendaylight / yangtools / yang / common / CanonicalValueViolation.java
1 /*
2  * Copyright (c) 2018 Pantheon Technologies, s.r.o. 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 package org.opendaylight.yangtools.yang.common;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.annotations.Beta;
13 import com.google.common.base.MoreObjects;
14 import com.google.common.base.MoreObjects.ToStringHelper;
15 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
16 import java.io.Serializable;
17 import java.util.Objects;
18 import java.util.Optional;
19 import javax.annotation.concurrent.ThreadSafe;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.opendaylight.yangtools.concepts.Variant;
23
24 /**
25  * A violation of a {@link CanonicalValue} validation. Contains details as mandated by RFC7950 Section 8.3.1.
26  *
27  * @author Robert Varga
28  */
29 @Beta
30 @NonNullByDefault
31 @ThreadSafe
32 public abstract class CanonicalValueViolation implements Serializable {
33     public static class Regular extends CanonicalValueViolation {
34         private static final long serialVersionUID = 1L;
35
36         private final @Nullable String appTag;
37         private final @Nullable String message;
38
39         Regular(final @Nullable String appTag, final @Nullable String message) {
40             this.appTag = appTag;
41             this.message = message;
42         }
43
44         @Override
45         @Nullable String appTag() {
46             return appTag;
47         }
48
49         @Override
50         @Nullable String message() {
51             return message;
52         }
53
54         @Override
55         ToStringHelper addToString(final ToStringHelper helper) {
56             return helper.omitNullValues().add("app-tag", appTag).add("message", message);
57         }
58     }
59
60     @SuppressFBWarnings("NM_CLASS_NOT_EXCEPTION")
61     public static class WithException extends CanonicalValueViolation {
62         private static final long serialVersionUID = 1L;
63
64         private final Exception cause;
65
66         WithException(final Exception cause) {
67             this.cause = requireNonNull(cause);
68         }
69
70         @Override
71         @SuppressFBWarnings("NP_NONNULL_RETURN_VIOLATION")
72         @Nullable String appTag() {
73             return null;
74         }
75
76         @Override
77         @Nullable String message() {
78             return cause.getMessage();
79         }
80
81         public final Exception getCause() {
82             return cause;
83         }
84
85         @Override
86         ToStringHelper addToString(final ToStringHelper helper) {
87             return helper.add("cause", cause);
88         }
89     }
90
91     private static final CanonicalValueViolation EMPTY = new Regular(null, null);
92     private static final Variant<?, CanonicalValueViolation> EMPTY_VARIANT = Variant.ofSecond(EMPTY);
93     private static final long serialVersionUID = 1L;
94
95     public static CanonicalValueViolation empty() {
96         return EMPTY;
97     }
98
99     public static CanonicalValueViolation of(final Exception cause) {
100         return new WithException(cause);
101     }
102
103     public static CanonicalValueViolation of(final @Nullable String appTag, final @Nullable String message) {
104         return appTag == null && message == null ? EMPTY : new Regular(appTag, message);
105     }
106
107     @SuppressWarnings("unchecked")
108     public static <T> Variant<T, CanonicalValueViolation> emptyVariant() {
109         return (Variant<T, CanonicalValueViolation>) EMPTY_VARIANT;
110     }
111
112     public static <T> Variant<T, CanonicalValueViolation> variantOf(final Exception cause) {
113         return Variant.ofSecond(CanonicalValueViolation.of(cause));
114     }
115
116     public static <T> Variant<T, CanonicalValueViolation> variantOf(final String message) {
117         return variantOf(null, message);
118     }
119
120     public static <T> Variant<T, CanonicalValueViolation> variantOf(final @Nullable String appTag,
121             final String message) {
122         return Variant.ofSecond(CanonicalValueViolation.of(appTag, message));
123     }
124
125     public final Optional<String> getAppTag() {
126         return nullableString(appTag());
127     }
128
129     public final Optional<String> getMessage() {
130         return nullableString(appTag());
131     }
132
133     abstract @Nullable String appTag();
134
135     abstract @Nullable String message();
136
137     @Override
138     public final int hashCode() {
139         return Objects.hash(appTag(), message());
140     }
141
142     @Override
143     public final boolean equals(final @Nullable Object obj) {
144         if (this == obj) {
145             return true;
146         }
147         if (!(obj instanceof CanonicalValueViolation)) {
148             return false;
149         }
150         final CanonicalValueViolation other = (CanonicalValueViolation) obj;
151         return Objects.equals(appTag(), other.appTag()) && Objects.equals(message(), other.message());
152     }
153
154     @Override
155     public final String toString() {
156         return addToString(MoreObjects.toStringHelper(this)).toString();
157     }
158
159     abstract ToStringHelper addToString(ToStringHelper helper);
160
161     private static Optional<String> nullableString(@Nullable final String str) {
162         return str != null ? Optional.of(str) : Optional.empty();
163     }
164 }