Add RFC6643 parser support
[yangtools.git] / yang / 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
23 /**
24  * An OID, or ObjectIdentifier, as defined by ITU and ISO/IEC.
25  */
26 // TODO: this class could also be Comparable<ObjectIdentifier>
27 @Beta
28 public final class ObjectIdentifier implements Identifier, WritableObject {
29     private static final long serialVersionUID = 1L;
30     @Regex
31     private static final String CHECK_OID_REGEX = "^\\d+(\\.\\d+)*$";
32     private static final Pattern CHECK_OID_PATTERN = Pattern.compile(CHECK_OID_REGEX);
33     private static final Pattern SPLIT_PATTERN = Pattern.compile(".", Pattern.LITERAL);
34
35     private final int[] components;
36
37     private ObjectIdentifier(final int[] components) {
38         this.components = components;
39     }
40
41     /**
42      * Create an {@link ObjectIdentifier} from its integer components.
43      *
44      * @param components OID items
45      * @return An ObjectIdentifier.
46      */
47     public static ObjectIdentifier forComponents(final int... components) {
48         return new ObjectIdentifier(components.clone());
49     }
50
51     /**
52      * Create an {@link ObjectIdentifier} from its string representation.
53      *
54      * @param str String OID representation.
55      * @return An ObjectIdentifier.
56      */
57     public static ObjectIdentifier forString(final String str) {
58         return new ObjectIdentifier(parseObjectId(str));
59     }
60
61     public int[] getComponents() {
62         // Always make a defensive copy
63         return components.clone();
64     }
65
66     public IntStream streamComponents() {
67         return Arrays.stream(components);
68     }
69
70     /**
71      * Read an {@link ObjectIdentifier} from a DataInput, performing the inverse of {@link #writeTo(DataOutput)}. For
72      * details see {@link WritableObject}.
73      *
74      * @param in Data input
75      * @return Object identifier
76      * @throws IOException If an I/O error is reported
77      */
78     public static ObjectIdentifier readFrom(final DataInput in) throws IOException {
79         final int count = in.readInt();
80         checkArgument(count >= 0, "Illegal item count");
81
82         final int[] oid = new int[count];
83         for (int index = 0; index < count; ++index) {
84             oid[index] = in.readInt();
85         }
86
87         return new ObjectIdentifier(oid);
88     }
89
90     @Override
91     public void writeTo(final DataOutput out) throws IOException {
92         out.writeInt(components.length);
93         for (int i : components) {
94             out.writeInt(i);
95         }
96     }
97
98     @Override
99     public int hashCode() {
100         return Arrays.hashCode(components);
101     }
102
103     @Override
104     public boolean equals(final Object obj) {
105         return this == obj || obj instanceof ObjectIdentifier
106                 && Arrays.equals(components, ((ObjectIdentifier) obj).components);
107     }
108
109     @Override
110     public String toString() {
111         StringBuilder stringBuilder = new StringBuilder();
112         stringBuilder.append(components[0]);
113         for (int index = 1; index < components.length; index++) {
114             stringBuilder.append('.').append(components[index]);
115         }
116         return stringBuilder.toString();
117     }
118
119     private static int[] parseObjectId(final String objectId) {
120         checkArgument(CHECK_OID_PATTERN.matcher(objectId).matches(), "Wrong format for OID: '%s'", objectId);
121
122         final String[] splitOid = SPLIT_PATTERN.split(objectId);
123         final int[] oid = new int[splitOid.length];
124         for (int index = 0; index < splitOid.length; index ++) {
125             oid[index] = Integer.parseInt(splitOid[index]);
126         }
127         return oid;
128     }
129 }