Rename org.opendaylight.yangtools.yang.binding
[yangtools.git] / binding / binding-lib / src / main / java / org / opendaylight / yangtools / binding / lib / DataObjectStep.java
1 /*
2  * Copyright (c) 2024 PANTHEON.tech, 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.binding.lib;
9
10 import java.io.Serializable;
11 import org.eclipse.jdt.annotation.NonNull;
12 import org.eclipse.jdt.annotation.Nullable;
13
14 /**
15  * A reference to a {@link DataObject} type forming a single step in a path similar to {@code instance-identifier}.
16  *
17  * @param <T> DataObject type
18  */
19 /*
20  * FIXME: this interface forms a partial model of the following RFC7950 construct:
21  *
22  *          ;; Instance Identifiers
23  *
24  *          instance-identifier = 1*("/" (node-identifier [1*key-predicate / leaf-list-predicate / pos]))
25  *
26  * We handle the 'node-identifier for DataObjects' and 'key-predicate' cases. What is missing are interfaces for:
27  * - 'leaf-list-predicate' (exact value match)
28  * - 'pos' interfaces (index into a list or a leaf-list}
29  * - 'node-identifier for non-DataObjects' (i.e. leaf, anydata, anyxml)
30  */
31 public sealed interface DataObjectStep<T extends DataObject> extends Comparable<DataObjectStep<?>>, Serializable
32         permits ExactDataObjectStep, KeylessStep {
33     /**
34      * Return the data object type backing this PathArgument.
35      *
36      * @return Data object type
37      */
38     @NonNull Class<T> type();
39
40     /**
41      * Return an optional enclosing case type. This is used only when {@link #type()} references a node defined
42      * in a {@code grouping} which is reference inside a {@code case} statement in order to safely reference the node.
43      *
44      * @return case class, or {@code null}
45      */
46     @Nullable Class<? extends DataObject> caseType();
47
48     @Override
49     default int compareTo(final DataObjectStep<?> other) {
50         final var typeCmp = compareClasses(type(), other.type());
51         if (typeCmp != 0) {
52             return typeCmp;
53         }
54         final var caseType = caseType();
55         final var otherCaseType = other.caseType();
56         if (caseType == null) {
57             return otherCaseType == null ? 0 : -1;
58         }
59         final var caseCmp = otherCaseType == null ? 1 : compareClasses(caseType, otherCaseType);
60         return caseCmp != 0 ? caseCmp : compareHierarchy(this, other);
61     }
62
63     private static int compareHierarchy(final DataObjectStep<?> recv, final DataObjectStep<?> other) {
64         if (recv instanceof NodeStep) {
65             if (other instanceof NodeStep) {
66                 return 0;
67             } else if (other instanceof KeylessStep || other instanceof KeyStep) {
68                 return -1;
69             }
70         } else if (recv instanceof KeyStep thisAware) {
71             if (other instanceof KeyStep otherAware) {
72                 @SuppressWarnings("unchecked")
73                 final var thisKey = (Comparable<Object>) thisAware.key();
74                 return  thisKey.compareTo(otherAware.key());
75             } else if (other instanceof NodeStep || other instanceof KeylessStep) {
76                 return 1;
77             }
78         } else if (recv instanceof KeylessStep) {
79             if (other instanceof KeylessStep) {
80                 return 0;
81             } else if (other instanceof NodeStep || other instanceof KeyStep) {
82                 return 1;
83             }
84         }
85         throw new IllegalStateException("Unhandled " + recv + ".compareTo(" + other + ")");
86     }
87
88     private static int compareClasses(final Class<?> first, final Class<?> second) {
89         return first.getCanonicalName().compareTo(second.getCanonicalName());
90     }
91 }