Migrate yang-model-util annotations
[yangtools.git] / yang / yang-model-util / src / main / java / org / opendaylight / yangtools / yang / model / util / type / CompatUtils.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. 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.model.util.type;
9
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static java.util.Objects.requireNonNull;
12
13 import java.util.List;
14 import java.util.Optional;
15 import org.eclipse.jdt.annotation.NonNull;
16 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
17 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
18 import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode;
19 import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
20 import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
21 import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
22 import org.opendaylight.yangtools.yang.model.api.type.Int16TypeDefinition;
23 import org.opendaylight.yangtools.yang.model.api.type.Int32TypeDefinition;
24 import org.opendaylight.yangtools.yang.model.api.type.Int64TypeDefinition;
25 import org.opendaylight.yangtools.yang.model.api.type.Int8TypeDefinition;
26 import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
27 import org.opendaylight.yangtools.yang.model.api.type.LengthRestrictedTypeDefinition;
28 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
29 import org.opendaylight.yangtools.yang.model.api.type.RangeRestrictedTypeDefinition;
30 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
31 import org.opendaylight.yangtools.yang.model.api.type.Uint16TypeDefinition;
32 import org.opendaylight.yangtools.yang.model.api.type.Uint32TypeDefinition;
33 import org.opendaylight.yangtools.yang.model.api.type.Uint64TypeDefinition;
34 import org.opendaylight.yangtools.yang.model.api.type.Uint8TypeDefinition;
35
36 /**
37  * Compatibility utilities for dealing with differences between the old parser's ExtendedType-driven type
38  * representation versus the representation this package models.
39  *
40  * @deprecated This class is provided strictly for compatibility only. No new users should be introduced, as this class
41  *             is scheduled for removal when its two OpenDaylight users, Java Binding v1 and YANG JMX Bindings are
42  *             removed.
43  */
44 @Deprecated
45 public final class CompatUtils {
46     private CompatUtils() {
47         throw new UnsupportedOperationException();
48     }
49
50     /**
51      * This package's type hierarchy model generates a type which encapsulates the default value and units for leaves.
52      * Java Binding specification is implemented in a way, where it needs to revert this process if the internal
53      * declaration has not restricted the type further -- which is not something available via
54      * {@link TypeDefinition#getBaseType()}.
55      *
56      * <p>
57      * Here are the possible scenarios:
58      *
59      * <pre>
60      * leaf foo {
61      *     type uint8 {
62      *         range 1..2;
63      *     }
64      * }
65      * </pre>
66      * The leaf type's schema path does not match the schema path of the leaf. We do NOT want to strip it, as
67      * we need to generate an inner class to hold the restrictions.
68      *
69      * <pre>
70      * leaf foo {
71      *     type uint8 {
72      *         range 1..2;
73      *     }
74      *     default 1;
75      * }
76      * </pre>
77      * The leaf type's schema path will match the schema path of the leaf. We do NOT want to strip it, as we need
78      * to generate an inner class to hold the restrictions.
79      *
80      * <pre>
81      * leaf foo {
82      *     type uint8;
83      *     default 1;
84      * }
85      * </pre>
86      * The leaf type's schema path will match the schema path of the leaf. We DO want to strip it, as we will deal
87      * with the default value ourselves.
88      *
89      * <pre>
90      * leaf foo {
91      *     type uint8;
92      * }
93      * </pre>
94      * The leaf type's schema path will not match the schema path of the leaf. We do NOT want to strip it.
95      *
96      * <p>
97      * The situation is different for types which do not have a default instantiation in YANG: leafref, enumeration,
98      * identityref, decimal64, bits and union. If these types are defined within this leaf's statement, a base type
99      * will be instantiated. If the leaf defines a default statement, this base type will be visible via getBaseType().
100      *
101      * <pre>
102      * leaf foo {
103      *     type decimal64 {
104      *         fraction-digits 2;
105      *     }
106      * }
107      * </pre>
108      * The leaf type's schema path will not match the schema path of the leaf, and we do not want to strip it, as it
109      * needs to be generated.
110      *
111      * <pre>
112      * leaf foo {
113      *     type decimal64 {
114      *         fraction-digits 2;
115      *     }
116      *     default 1;
117      * }
118      * </pre>
119      * The leaf type's schema path will match the schema path of the leaf, and we DO want to strip it.
120      *
121      * @param leaf Leaf for which we are acquiring the type
122      * @return Potentially base type of the leaf type.
123      */
124     public static @NonNull TypeDefinition<?> compatType(final @NonNull TypedDataSchemaNode leaf) {
125         final TypeDefinition<?> leafType = requireNonNull(leaf.getType());
126
127         if (!leaf.getPath().equals(leafType.getPath())) {
128             // Old parser semantics, or no new default/units defined for this leaf
129             return leafType;
130         }
131
132         // We are dealing with a type generated for the leaf itself
133         final TypeDefinition<?> baseType = leafType.getBaseType();
134         checkArgument(baseType != null, "Leaf %s has type for leaf, but no base type", leaf);
135
136         if (leaf.getPath().equals(baseType.getPath().getParent())) {
137             // Internal instantiation of a base YANG type (decimal64 and similar)
138             return baseType;
139         }
140
141         // At this point we have dealt with the easy cases. Now we need to perform per-type checking if there are no
142         // new constraints introduced by this type. If there were not, we will return the base type.
143         if (leafType instanceof BinaryTypeDefinition) {
144             return baseTypeIfNotConstrained((BinaryTypeDefinition) leafType);
145         } else if (leafType instanceof DecimalTypeDefinition) {
146             return baseTypeIfNotConstrained((DecimalTypeDefinition) leafType);
147         } else if (leafType instanceof InstanceIdentifierTypeDefinition) {
148             return baseTypeIfNotConstrained((InstanceIdentifierTypeDefinition) leafType);
149         } else if (leafType instanceof Int8TypeDefinition) {
150             return baseTypeIfNotConstrained((Int8TypeDefinition) leafType);
151         } else if (leafType instanceof Int16TypeDefinition) {
152             return baseTypeIfNotConstrained((Int16TypeDefinition) leafType);
153         } else if (leafType instanceof Int32TypeDefinition) {
154             return baseTypeIfNotConstrained((Int32TypeDefinition) leafType);
155         } else if (leafType instanceof Int64TypeDefinition) {
156             return baseTypeIfNotConstrained((Int64TypeDefinition) leafType);
157         } else if (leafType instanceof StringTypeDefinition) {
158             return baseTypeIfNotConstrained((StringTypeDefinition) leafType);
159         } else if (leafType instanceof Uint8TypeDefinition) {
160             return baseTypeIfNotConstrained((Uint8TypeDefinition) leafType);
161         } else if (leafType instanceof Uint16TypeDefinition) {
162             return baseTypeIfNotConstrained((Uint16TypeDefinition) leafType);
163         } else if (leafType instanceof Uint32TypeDefinition) {
164             return baseTypeIfNotConstrained((Uint32TypeDefinition) leafType);
165         } else if (leafType instanceof Uint64TypeDefinition) {
166             return baseTypeIfNotConstrained((Uint64TypeDefinition) leafType);
167         } else {
168             // Other types cannot be constrained, return the base type
169             return baseType;
170         }
171     }
172
173     // FIXME: 3.0.0: remove this method
174     public static @NonNull TypeDefinition<?> compatLeafType(final @NonNull LeafSchemaNode leaf) {
175         return compatType(leaf);
176     }
177
178     private static BinaryTypeDefinition baseTypeIfNotConstrained(final @NonNull BinaryTypeDefinition type) {
179         return baseTypeIfNotConstrained(type, type.getBaseType());
180     }
181
182     private static TypeDefinition<?> baseTypeIfNotConstrained(final @NonNull DecimalTypeDefinition type) {
183         return baseTypeIfNotConstrained(type, type.getBaseType());
184     }
185
186     private static TypeDefinition<?> baseTypeIfNotConstrained(final @NonNull InstanceIdentifierTypeDefinition type) {
187         final InstanceIdentifierTypeDefinition base = type.getBaseType();
188         return type.requireInstance() == base.requireInstance() ? base : type;
189     }
190
191     private static TypeDefinition<?> baseTypeIfNotConstrained(final @NonNull StringTypeDefinition type) {
192         final StringTypeDefinition base = type.getBaseType();
193         final List<PatternConstraint> patterns = type.getPatternConstraints();
194         final Optional<LengthConstraint> optLengths = type.getLengthConstraint();
195
196         if ((patterns.isEmpty() || patterns.equals(base.getPatternConstraints()))
197                 && (!optLengths.isPresent() || optLengths.equals(base.getLengthConstraint()))) {
198             return base;
199         }
200
201         return type;
202     }
203
204     private static <T extends RangeRestrictedTypeDefinition<T, ?>> T baseTypeIfNotConstrained(final @NonNull T type) {
205         return baseTypeIfNotConstrained(type, type.getBaseType());
206     }
207
208     private static <T extends RangeRestrictedTypeDefinition<T, ?>> T baseTypeIfNotConstrained(final @NonNull T type,
209             final T base) {
210         final Optional<?> optConstraint = type.getRangeConstraint();
211         if (!optConstraint.isPresent()) {
212             return base;
213         }
214         return optConstraint.equals(base.getRangeConstraint()) ? base : type;
215     }
216
217     private static <T extends LengthRestrictedTypeDefinition<T>> T baseTypeIfNotConstrained(final @NonNull T type,
218             final T base) {
219         final Optional<LengthConstraint> optConstraint = type.getLengthConstraint();
220         if (!optConstraint.isPresent()) {
221             return base;
222         }
223         return optConstraint.equals(base.getLengthConstraint()) ? base : type;
224     }
225 }