blob: 95c8276818c105dbfc561c1fd56bd7b03996d7ad [file] [log] [blame]
Yuta HIGUCHI24057822017-08-02 15:03:51 -07001/*
2 * Copyright 2017-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.d.config;
17
Henry Yu830b5dc2017-11-16 10:44:45 -050018import com.google.common.annotations.Beta;
Yuta HIGUCHI24057822017-08-02 15:03:51 -070019import org.onosproject.yang.model.DataNode;
20import org.onosproject.yang.model.KeyLeaf;
21import org.onosproject.yang.model.LeafListKey;
22import org.onosproject.yang.model.ListKey;
Yuta HIGUCHIe057dee2017-09-15 13:56:10 -070023import org.onosproject.yang.model.NodeKey;
Yuta HIGUCHI24057822017-08-02 15:03:51 -070024import org.onosproject.yang.model.ResourceId;
Yuta HIGUCHI24057822017-08-02 15:03:51 -070025import org.onosproject.yang.model.SchemaId;
26import org.slf4j.Logger;
27
Henry Yu830b5dc2017-11-16 10:44:45 -050028import java.util.Iterator;
29import java.util.Objects;
30
31import static com.google.common.base.Preconditions.checkArgument;
32import static org.slf4j.LoggerFactory.getLogger;
Yuta HIGUCHI24057822017-08-02 15:03:51 -070033
34/**
35 * Utility related to ResourceId.
36 */
37@Beta
38public abstract class ResourceIds {
39
40 private static final Logger log = getLogger(ResourceIds.class);
41
42 /**
Yuta HIGUCHIe057dee2017-09-15 13:56:10 -070043 * Absolute ResourceId pointing at root node.
44 */
45 public static final ResourceId ROOT_ID = ResourceId.builder()
46 .addBranchPointSchema(DeviceResourceIds.ROOT_NAME,
47 DeviceResourceIds.DCS_NAMESPACE)
48 .build();
49
50 /**
Yuta HIGUCHI24057822017-08-02 15:03:51 -070051 * Builds the ResourceId of specified {@code node}.
52 *
53 * @param parent ResourceId of {@code node} parent
Henry Yu830b5dc2017-11-16 10:44:45 -050054 * @param node to create ResourceId.
Yuta HIGUCHI24057822017-08-02 15:03:51 -070055 * @return ResourceId of {@code node}
56 */
57 public static ResourceId resourceId(ResourceId parent, DataNode node) {
58 final ResourceId.Builder builder;
59 if (parent == null) {
60 builder = ResourceId.builder();
61 } else {
62 try {
63 builder = parent.copyBuilder();
64 } catch (CloneNotSupportedException e) {
65 throw new IllegalArgumentException(e);
66 }
67 }
68
69 SchemaId sid = node.key().schemaId();
70 switch (node.type()) {
Henry Yu830b5dc2017-11-16 10:44:45 -050071 case MULTI_INSTANCE_LEAF_VALUE_NODE:
72 builder.addLeafListBranchPoint(sid.name(), sid.namespace(),
73 ((LeafListKey) node.key()).asString());
74 break;
Yuta HIGUCHI24057822017-08-02 15:03:51 -070075
Henry Yu830b5dc2017-11-16 10:44:45 -050076 case MULTI_INSTANCE_NODE:
77 builder.addBranchPointSchema(sid.name(), sid.namespace());
78 for (KeyLeaf keyLeaf : ((ListKey) node.key()).keyLeafs()) {
79 builder.addKeyLeaf(keyLeaf.leafSchema().name(),
80 keyLeaf.leafSchema().namespace(),
81 keyLeaf.leafValAsString());
82 }
83 break;
Yuta HIGUCHI24057822017-08-02 15:03:51 -070084
Henry Yu830b5dc2017-11-16 10:44:45 -050085 case SINGLE_INSTANCE_LEAF_VALUE_NODE:
86 case SINGLE_INSTANCE_NODE:
87 builder.addBranchPointSchema(sid.name(), sid.namespace());
88 break;
Yuta HIGUCHI24057822017-08-02 15:03:51 -070089
Henry Yu830b5dc2017-11-16 10:44:45 -050090 default:
91 throw new IllegalArgumentException("Unknown type " + node);
Yuta HIGUCHI24057822017-08-02 15:03:51 -070092
93 }
94
95 return builder.build();
96 }
97
98 /**
99 * Concats {@code path} after {@code prefix}.
100 *
101 * @param prefix path
Henry Yu830b5dc2017-11-16 10:44:45 -0500102 * @param path to append after {@code path}
Yuta HIGUCHI24057822017-08-02 15:03:51 -0700103 * @return concatenated ResouceId
104 */
105 public static ResourceId concat(ResourceId prefix, ResourceId path) {
106 checkArgument(!path.nodeKeys().contains(DeviceResourceIds.ROOT_NODE),
107 "%s was already absolute path", path);
108 try {
109 return prefix.copyBuilder().append(path).build();
110 } catch (CloneNotSupportedException e) {
111 log.error("Could not copy {}", path, e);
112 throw new IllegalArgumentException("Could not copy " + path, e);
113 }
114 }
115
116
117 /**
Yuta HIGUCHI4070c042017-08-28 13:47:20 -0700118 * Returns {@code child} as relative ResourceId against {@code base}.
Yuta HIGUCHI24057822017-08-02 15:03:51 -0700119 *
Henry Yu830b5dc2017-11-16 10:44:45 -0500120 * @param base ResourceId
Yuta HIGUCHI24057822017-08-02 15:03:51 -0700121 * @param child ResourceId to relativize
122 * @return relative ResourceId
123 */
124 public static ResourceId relativize(ResourceId base, ResourceId child) {
125 checkArgument(child.nodeKeys().size() >= base.nodeKeys().size(),
126 "%s path must be deeper than base prefix %s", child, base);
Yuta HIGUCHIe057dee2017-09-15 13:56:10 -0700127 @SuppressWarnings("rawtypes")
128 Iterator<NodeKey> bIt = base.nodeKeys().iterator();
129 @SuppressWarnings("rawtypes")
130 Iterator<NodeKey> cIt = child.nodeKeys().iterator();
131 while (bIt.hasNext()) {
132 NodeKey<?> b = bIt.next();
133 NodeKey<?> c = cIt.next();
134
135 checkArgument(Objects.equals(b, c),
136 "%s is not a prefix of %s.\n" +
Henry Yu830b5dc2017-11-16 10:44:45 -0500137 "b:%s != c:%s",
Yuta HIGUCHIe057dee2017-09-15 13:56:10 -0700138 base, child,
139 b, c);
140 }
Yuta HIGUCHI24057822017-08-02 15:03:51 -0700141
Yuta HIGUCHI4070c042017-08-28 13:47:20 -0700142 return ResourceId.builder().append(child.nodeKeys().subList(base.nodeKeys().size(),
143 child.nodeKeys().size())).build();
Yuta HIGUCHI24057822017-08-02 15:03:51 -0700144 }
145
146 /**
Henry Yu830b5dc2017-11-16 10:44:45 -0500147 * Removes the root node from {@code path}.
148 *
149 * @param path given resource ID
150 * @return resource ID without root node
151 */
152 public static ResourceId removeRootNode(ResourceId path) {
153 if (!startsWithRootNode(path)) {
154 return path;
155 }
156
157 return ResourceId.builder().append(path.nodeKeys().subList(1,
158 path.nodeKeys().size())).build();
159 }
160
161 /**
162 * Returns the resource ID of the parent data node pointed by {@code path}.
163 *
164 * @param path resource ID of the given data node
165 * @return resource ID of the parent data node
166 */
167 public static ResourceId parentOf(ResourceId path) {
168 try {
169 return path.copyBuilder().removeLastKey().build();
170 } catch (CloneNotSupportedException e) {
171 log.error("Could not copy {}", path, e);
172 throw new IllegalArgumentException("Could not copy " + path, e);
173 }
174 }
175
176 /**
Yuta HIGUCHI24057822017-08-02 15:03:51 -0700177 * Tests if {@code child} starts with {@code prefix}.
178 *
179 * @param prefix expected
Henry Yu830b5dc2017-11-16 10:44:45 -0500180 * @param child to test
Yuta HIGUCHI24057822017-08-02 15:03:51 -0700181 * @return true if {@code child} starts with {@code prefix}
182 */
183 public static boolean isPrefix(ResourceId prefix, ResourceId child) {
184
185 return child.nodeKeys().size() >= prefix.nodeKeys().size() &&
Henry Yu830b5dc2017-11-16 10:44:45 -0500186 prefix.nodeKeys().equals(child.nodeKeys().subList(0, prefix.nodeKeys().size()));
Yuta HIGUCHI24057822017-08-02 15:03:51 -0700187 }
188
Yuta HIGUCHIe057dee2017-09-15 13:56:10 -0700189 public static boolean startsWithRootNode(ResourceId path) {
190 return !path.nodeKeys().isEmpty() &&
191 DeviceResourceIds.ROOT_NAME.equals(path.nodeKeys().get(0).schemaId().name());
192 }
193
Yuta HIGUCHI24057822017-08-02 15:03:51 -0700194}