Populate data/ hierarchy
[yangtools.git] / model / rfc6643-model-api / src / main / java / org / opendaylight / yangtools / rfc6643 / model / api / ObjectIdentifier.java
1 /*
2  * Copyright (c) 2016, 2020 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.rfc6643.model.api;
9
10 import static com.google.common.base.Preconditions.checkArgument;
11
12 import com.google.common.annotations.Beta;
13 import java.io.DataInput;
14 import java.io.DataOutput;
15 import java.io.IOException;
16 import java.util.Arrays;
17 import java.util.regex.Pattern;
18 import java.util.stream.IntStream;
19 import org.checkerframework.checker.regex.qual.Regex;
20 import org.opendaylight.yangtools.concepts.Identifier;
21 import org.opendaylight.yangtools.concepts.WritableObject;
22 import org.opendaylight.yangtools.yang.common.Uint32;
23
24 /**
25  * An OID, or ObjectIdentifier, as defined by ITU and ISO/IEC.
26  */
27 // TODO: this class could also be Comparable<ObjectIdentifier>
28 @Beta
29 public final class ObjectIdentifier implements Identifier, WritableObject {
30     private static final long serialVersionUID = 1L;
31     @Regex
32     private static final String CHECK_OID_REGEX = "^\\d+(\\.\\d+)*$";
33     private static final Pattern CHECK_OID_PATTERN = Pattern.compile(CHECK_OID_REGEX);
34     private static final Pattern SPLIT_PATTERN = Pattern.compile(".", Pattern.LITERAL);
35
36     private final int[] subIdentifiers;
37
38     private ObjectIdentifier(final int[] subIdentifiers) {
39         this.subIdentifiers = subIdentifiers;
40     }
41
42     /**
43      * Create an {@link ObjectIdentifier} from its integer components. Each sub-identifier is interpreted as an unsigned
44      * integer.
45      *
46      * @param subIdentifiers OID sub-identifiers
47      * @return An ObjectIdentifier.
48      */
49     public static ObjectIdentifier of(final int... subIdentifiers) {
50         return new ObjectIdentifier(subIdentifiers.clone());
51     }
52
53     /**
54      * Create an {@link ObjectIdentifier} from its string representation.
55      *
56      * @param str String OID representation.
57      * @return An ObjectIdentifier.
58      */
59     public static ObjectIdentifier forString(final String str) {
60         return new ObjectIdentifier(parseObjectId(str));
61     }
62
63     public int[] getSubIdentifiers() {
64         // Always make a defensive copy
65         return subIdentifiers.clone();
66     }
67
68     public IntStream streamSubIdentifiers() {
69         return Arrays.stream(subIdentifiers);
70     }
71
72     /**
73      * Read an {@link ObjectIdentifier} from a DataInput, performing the inverse of {@link #writeTo(DataOutput)}. For
74      * details see {@link WritableObject}.
75      *
76      * @param in Data input
77      * @return Object identifier
78      * @throws IOException If an I/O error is reported
79      */
80     public static ObjectIdentifier readFrom(final DataInput in) throws IOException {
81         final int count = in.readUnsignedByte();
82         checkArgument(count >= 0 && count <= 128, "Illegal item count %s", count);
83
84         final int[] oid = new int[count];
85         for (int index = 0; index < count; ++index) {
86             oid[index] = in.readInt();
87         }
88
89         return new ObjectIdentifier(oid);
90     }
91
92     @Override
93     public void writeTo(final DataOutput out) throws IOException {
94         out.writeByte(subIdentifiers.length);
95         for (int i : subIdentifiers) {
96             out.writeInt(i);
97         }
98     }
99
100     @Override
101     public int hashCode() {
102         return Arrays.hashCode(subIdentifiers);
103     }
104
105     @Override
106     public boolean equals(final Object obj) {
107         return this == obj || obj instanceof ObjectIdentifier
108                 && Arrays.equals(subIdentifiers, ((ObjectIdentifier) obj).subIdentifiers);
109     }
110
111     @Override
112     public String toString() {
113         StringBuilder stringBuilder = new StringBuilder();
114         stringBuilder.append(subIdentifiers[0]);
115         for (int index = 1; index < subIdentifiers.length; index++) {
116             stringBuilder.append('.').append(subIdentifiers[index]);
117         }
118         return stringBuilder.toString();
119     }
120
121     private static int[] parseObjectId(final String objectId) {
122         checkArgument(CHECK_OID_PATTERN.matcher(objectId).matches(), "Wrong format for OID: '%s'", objectId);
123
124         final String[] splitOid = SPLIT_PATTERN.split(objectId);
125         checkArgument(splitOid.length <= 128, "Object Identifier can have at most 128 sub-identifiers");
126
127         final int[] oid = new int[splitOid.length];
128         for (int index = 0; index < splitOid.length; index ++) {
129             oid[index] = Uint32.valueOf(splitOid[index]).intValue();
130         }
131         return oid;
132     }
133 }