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