Use java.io.Serial in yang-common
[yangtools.git] / common / yang-common / src / main / java / org / opendaylight / yangtools / yang / common / DerivedString.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 com.google.common.annotations.Beta;
11 import java.io.Serial;
12 import org.eclipse.jdt.annotation.NonNullByDefault;
13 import org.eclipse.jdt.annotation.Nullable;
14
15 /**
16  * Abstract base class for objects which are string-equivalent to canonical string representation specified
17  * in a YANG model. Note that each subclass of {@link DerivedString} defines its own {@link #hashCode()} and
18  * {@link #equals(Object)} contracts based on implementation particulars.
19  *
20  * <p>
21  * Given the following YANG snippet:
22  * <pre>
23  *     typedef foo {
24  *         type string;
25  *         pattern "[1-9]?[0-9]";
26  *     }
27  *
28  *     typedef bar {
29  *         type foo;
30  *         patter "[1-9][0-9]";
31  *     }
32  *
33  *     typedef baz {
34  *         type foo;
35  *     }
36  * </pre>
37  * it is obvious we could use a storage class with 'int' as the internal representation of all three types and define
38  * operations on top of it. In this case we would define:
39  * <ul>
40  *     <li>{@code public class FooDerivedString extends DerivedString<FooDerivedString>}, which implements all abstract
41  *         methods of {@link DerivedString} as final methods. It will notably not override {@link #validator()} and
42  *         must not be final.</li>
43  *     <li>{@code public final class FooDerivedStringSupport extends DerivedStringSupport<FooDerivedString>}, which
44  *         forms the baseline validator and instantiation for {@code FooDerivedString}. It should be a singleton class
45  *         with a getInstance() method.</li>
46  *     <li>{@code public class BarDerivedString extends FooDerivedString}, which overrides {@link #validator()} to
47  *         indicate its contents have been validated to conform to bar -- it does that by returning the singleton
48  *         instance of {@code BarDerivedStringValidator}.</li>
49  *     <li>{@code public final class BarDerivedStringValidator extends DerivedStringValidator<FooDerivedString,
50  *         BarDerivedString}. This method needs to notably implement
51  *         {@link CanonicalValueValidator#validateRepresentation(CanonicalValue)} to hand out BarDerivedString
52  *         instances. This class needs to be a singleton with a getInstance() method, too.</li>
53  * </ul>
54  * Since {@code baz} is not defining any new restrictions, all instances of FooDerivedString are valid for it and we
55  * do not have to define any additional support.
56  *
57  * <p>
58  * It is important for {@link DerivedString} subclasses not to be final because any YANG type can be further extended
59  * and adding a final class in that hierarchy would prevent a proper class from being defined.
60  *
61  * @param <T> derived string representation
62  * @author Robert Varga
63  */
64 @Beta
65 @NonNullByDefault
66 public abstract class DerivedString<T extends DerivedString<T>> implements CanonicalValue<T> {
67     @Serial
68     private static final long serialVersionUID = 1L;
69
70     @Override
71     public abstract int hashCode();
72
73     @Override
74     public abstract boolean equals(@Nullable Object obj);
75
76     @Override
77     public final String toString() {
78         return toCanonicalString();
79     }
80 }