Use pattern matching on instanceof in yang-common
[yangtools.git] / common / 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 org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.opendaylight.yangtools.concepts.Either;
22 import org.opendaylight.yangtools.concepts.Immutable;
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 public abstract class CanonicalValueViolation implements Immutable, Serializable {
32     public static class Regular extends CanonicalValueViolation {
33         private static final long serialVersionUID = 1L;
34
35         private final @Nullable String appTag;
36         private final @Nullable String message;
37
38         Regular(final @Nullable String appTag, final @Nullable String message) {
39             this.appTag = appTag;
40             this.message = message;
41         }
42
43         @Override
44         @Nullable String appTag() {
45             return appTag;
46         }
47
48         @Override
49         @Nullable String message() {
50             return message;
51         }
52
53         @Override
54         ToStringHelper addToString(final ToStringHelper helper) {
55             return helper.omitNullValues().add("app-tag", appTag).add("message", message);
56         }
57     }
58
59     @SuppressFBWarnings("NM_CLASS_NOT_EXCEPTION")
60     public static class WithException extends CanonicalValueViolation {
61         private static final long serialVersionUID = 1L;
62
63         private final Exception cause;
64
65         WithException(final Exception cause) {
66             this.cause = requireNonNull(cause);
67         }
68
69         @Override
70         @Nullable String appTag() {
71             return null;
72         }
73
74         @Override
75         @Nullable String message() {
76             return cause.getMessage();
77         }
78
79         public final Exception getCause() {
80             return cause;
81         }
82
83         @Override
84         ToStringHelper addToString(final ToStringHelper helper) {
85             return helper.add("cause", cause);
86         }
87     }
88
89     private static final CanonicalValueViolation EMPTY = new Regular(null, null);
90     private static final Either<?, CanonicalValueViolation> EMPTY_VARIANT = Either.ofSecond(EMPTY);
91     private static final long serialVersionUID = 1L;
92
93     public static CanonicalValueViolation empty() {
94         return EMPTY;
95     }
96
97     public static CanonicalValueViolation of(final Exception cause) {
98         return new WithException(cause);
99     }
100
101     public static CanonicalValueViolation of(final @Nullable String appTag, final @Nullable String message) {
102         return appTag == null && message == null ? EMPTY : new Regular(appTag, message);
103     }
104
105     @SuppressWarnings("unchecked")
106     public static <T> Either<T, CanonicalValueViolation> emptyVariant() {
107         return (Either<T, CanonicalValueViolation>) EMPTY_VARIANT;
108     }
109
110     public static <T> Either<T, CanonicalValueViolation> variantOf(final Exception cause) {
111         return Either.ofSecond(CanonicalValueViolation.of(cause));
112     }
113
114     public static <T> Either<T, CanonicalValueViolation> variantOf(final String message) {
115         return variantOf(null, message);
116     }
117
118     public static <T> Either<T, CanonicalValueViolation> variantOf(final @Nullable String appTag,
119             final String message) {
120         return Either.ofSecond(CanonicalValueViolation.of(appTag, message));
121     }
122
123     public final Optional<String> getAppTag() {
124         return nullableString(appTag());
125     }
126
127     public final Optional<String> getMessage() {
128         return nullableString(message());
129     }
130
131     abstract @Nullable String appTag();
132
133     abstract @Nullable String message();
134
135     @Override
136     public final int hashCode() {
137         return Objects.hash(appTag(), message());
138     }
139
140     @Override
141     public final boolean equals(final @Nullable Object obj) {
142         return this == obj || obj instanceof CanonicalValueViolation other
143             && Objects.equals(appTag(), other.appTag()) && Objects.equals(message(), other.message());
144     }
145
146     @Override
147     public final String toString() {
148         return addToString(MoreObjects.toStringHelper(this)).toString();
149     }
150
151     abstract ToStringHelper addToString(ToStringHelper helper);
152
153     private static Optional<String> nullableString(@Nullable final String str) {
154         return str != null ? Optional.of(str) : Optional.empty();
155     }
156 }