blob: a08c04a81a738bf8991d81efa06a02382c25683f [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
18import static com.google.common.base.Preconditions.checkArgument;
19import static org.slf4j.LoggerFactory.getLogger;
20
Yuta HIGUCHIe057dee2017-09-15 13:56:10 -070021import java.util.Iterator;
22import java.util.Objects;
23
Yuta HIGUCHI24057822017-08-02 15:03:51 -070024import org.onosproject.yang.model.DataNode;
25import org.onosproject.yang.model.KeyLeaf;
26import org.onosproject.yang.model.LeafListKey;
27import org.onosproject.yang.model.ListKey;
Yuta HIGUCHIe057dee2017-09-15 13:56:10 -070028import org.onosproject.yang.model.NodeKey;
Yuta HIGUCHI24057822017-08-02 15:03:51 -070029import org.onosproject.yang.model.ResourceId;
Yuta HIGUCHI24057822017-08-02 15:03:51 -070030import org.onosproject.yang.model.SchemaId;
31import org.slf4j.Logger;
32
33import com.google.common.annotations.Beta;
34
35/**
36 * Utility related to ResourceId.
37 */
38@Beta
39public abstract class ResourceIds {
40
41 private static final Logger log = getLogger(ResourceIds.class);
42
43 /**
Yuta HIGUCHIe057dee2017-09-15 13:56:10 -070044 * Absolute ResourceId pointing at root node.
45 */
46 public static final ResourceId ROOT_ID = ResourceId.builder()
47 .addBranchPointSchema(DeviceResourceIds.ROOT_NAME,
48 DeviceResourceIds.DCS_NAMESPACE)
49 .build();
50
51 /**
Yuta HIGUCHI24057822017-08-02 15:03:51 -070052 * Builds the ResourceId of specified {@code node}.
53 *
54 * @param parent ResourceId of {@code node} parent
55 * @param node to create ResourceId.
56 * @return ResourceId of {@code node}
57 */
58 public static ResourceId resourceId(ResourceId parent, DataNode node) {
59 final ResourceId.Builder builder;
60 if (parent == null) {
61 builder = ResourceId.builder();
62 } else {
63 try {
64 builder = parent.copyBuilder();
65 } catch (CloneNotSupportedException e) {
66 throw new IllegalArgumentException(e);
67 }
68 }
69
70 SchemaId sid = node.key().schemaId();
71 switch (node.type()) {
72 case MULTI_INSTANCE_LEAF_VALUE_NODE:
73 builder.addLeafListBranchPoint(sid.name(), sid.namespace(),
74 ((LeafListKey) node.key()).asString());
75 break;
76
77 case MULTI_INSTANCE_NODE:
78 builder.addBranchPointSchema(sid.name(), sid.namespace());
79 for (KeyLeaf keyLeaf : ((ListKey) node.key()).keyLeafs()) {
80 builder.addKeyLeaf(keyLeaf.leafSchema().name(),
81 keyLeaf.leafSchema().namespace(),
82 keyLeaf.leafValAsString());
83 }
84 break;
85
86 case SINGLE_INSTANCE_LEAF_VALUE_NODE:
87 case SINGLE_INSTANCE_NODE:
88 builder.addBranchPointSchema(sid.name(), sid.namespace());
89 break;
90
91 default:
92 throw new IllegalArgumentException("Unknown type " + node);
93
94 }
95
96 return builder.build();
97 }
98
99 /**
100 * Concats {@code path} after {@code prefix}.
101 *
102 * @param prefix path
103 * @param path to append after {@code path}
104 * @return concatenated ResouceId
105 */
106 public static ResourceId concat(ResourceId prefix, ResourceId path) {
107 checkArgument(!path.nodeKeys().contains(DeviceResourceIds.ROOT_NODE),
108 "%s was already absolute path", path);
109 try {
110 return prefix.copyBuilder().append(path).build();
111 } catch (CloneNotSupportedException e) {
112 log.error("Could not copy {}", path, e);
113 throw new IllegalArgumentException("Could not copy " + path, e);
114 }
115 }
116
117
118 /**
Yuta HIGUCHI4070c042017-08-28 13:47:20 -0700119 * Returns {@code child} as relative ResourceId against {@code base}.
Yuta HIGUCHI24057822017-08-02 15:03:51 -0700120 *
121 * @param base ResourceId
122 * @param child ResourceId to relativize
123 * @return relative ResourceId
124 */
125 public static ResourceId relativize(ResourceId base, ResourceId child) {
126 checkArgument(child.nodeKeys().size() >= base.nodeKeys().size(),
127 "%s path must be deeper than base prefix %s", child, base);
Yuta HIGUCHIe057dee2017-09-15 13:56:10 -0700128 @SuppressWarnings("rawtypes")
129 Iterator<NodeKey> bIt = base.nodeKeys().iterator();
130 @SuppressWarnings("rawtypes")
131 Iterator<NodeKey> cIt = child.nodeKeys().iterator();
132 while (bIt.hasNext()) {
133 NodeKey<?> b = bIt.next();
134 NodeKey<?> c = cIt.next();
135
136 checkArgument(Objects.equals(b, c),
137 "%s is not a prefix of %s.\n" +
138 "b:%s != c:%s",
139 base, child,
140 b, c);
141 }
Yuta HIGUCHI24057822017-08-02 15:03:51 -0700142
Yuta HIGUCHI4070c042017-08-28 13:47:20 -0700143 return ResourceId.builder().append(child.nodeKeys().subList(base.nodeKeys().size(),
144 child.nodeKeys().size())).build();
Yuta HIGUCHI24057822017-08-02 15:03:51 -0700145 }
146
147 /**
148 * Tests if {@code child} starts with {@code prefix}.
149 *
150 * @param prefix expected
151 * @param child to test
152 * @return true if {@code child} starts with {@code prefix}
153 */
154 public static boolean isPrefix(ResourceId prefix, ResourceId child) {
155
156 return child.nodeKeys().size() >= prefix.nodeKeys().size() &&
157 prefix.nodeKeys().equals(child.nodeKeys().subList(0, prefix.nodeKeys().size()));
158 }
159
Yuta HIGUCHIe057dee2017-09-15 13:56:10 -0700160 public static boolean startsWithRootNode(ResourceId path) {
161 return !path.nodeKeys().isEmpty() &&
162 DeviceResourceIds.ROOT_NAME.equals(path.nodeKeys().get(0).schemaId().name());
163 }
164
Yuta HIGUCHI24057822017-08-02 15:03:51 -0700165}