2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.parser.util;
10 import java.util.Comparator;
11 import java.util.Date;
14 import java.util.TreeMap;
16 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
17 import org.opendaylight.yangtools.yang.model.api.Module;
18 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
19 import org.opendaylight.yangtools.yang.parser.builder.api.Builder;
20 import org.opendaylight.yangtools.yang.parser.builder.api.DataNodeContainerBuilder;
21 import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
22 import org.opendaylight.yangtools.yang.parser.builder.api.GroupingBuilder;
23 import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder;
24 import org.opendaylight.yangtools.yang.parser.builder.impl.ChoiceBuilder;
25 import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleBuilder;
26 import org.opendaylight.yangtools.yang.parser.builder.impl.RpcDefinitionBuilder;
28 public final class GroupingUtils {
30 private GroupingUtils() {
34 * Search given modules for grouping by name defined in uses node.
37 * builder of uses statement
42 * @return grouping with given name if found, null otherwise
44 public static GroupingBuilder getTargetGroupingFromModules(final UsesNodeBuilder usesBuilder,
45 final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
46 final int line = usesBuilder.getLine();
48 final String groupingString = usesBuilder.getGroupingPathAsString();
49 String groupingPrefix;
52 if (groupingString.contains(":")) {
53 String[] splitted = groupingString.split(":");
54 if (splitted.length != 2 || groupingString.contains("/")) {
55 throw new YangParseException(module.getName(), line, "Invalid name of target grouping");
57 groupingPrefix = splitted[0];
58 groupingName = splitted[1];
60 groupingPrefix = module.getPrefix();
61 groupingName = groupingString;
64 ModuleBuilder dependentModule;
65 if(groupingPrefix == null) {
66 dependentModule = module;
68 if (groupingPrefix.equals(module.getPrefix())) {
69 dependentModule = module;
71 dependentModule = ParserUtils.findModuleFromBuilders(modules, module, groupingPrefix, line);
74 if (dependentModule == null) {
78 GroupingBuilder result;
79 Set<GroupingBuilder> groupings = dependentModule.getGroupingBuilders();
80 result = findGroupingBuilder(groupings, groupingName);
85 Builder parent = usesBuilder.getParent();
87 while (parent != null) {
88 if (parent instanceof DataNodeContainerBuilder) {
89 groupings = ((DataNodeContainerBuilder) parent).getGroupingBuilders();
90 } else if (parent instanceof RpcDefinitionBuilder) {
91 groupings = ((RpcDefinitionBuilder) parent).getGroupings();
93 result = findGroupingBuilder(groupings, groupingName);
95 parent = parent.getParent();
101 if (result == null) {
102 throw new YangParseException(module.getName(), line, "Referenced grouping '" + groupingName
109 * Search context for grouping by name defined in uses node.
112 * builder of uses statement
116 * SchemaContext containing already resolved modules
117 * @return grouping with given name if found, null otherwise
119 public static GroupingDefinition getTargetGroupingFromContext(final UsesNodeBuilder usesBuilder,
120 final ModuleBuilder module, final SchemaContext context) {
121 final int line = usesBuilder.getLine();
122 String groupingString = usesBuilder.getGroupingPathAsString();
123 String groupingPrefix;
126 if (groupingString.contains(":")) {
127 String[] splitted = groupingString.split(":");
128 if (splitted.length != 2 || groupingString.contains("/")) {
129 throw new YangParseException(module.getName(), line, "Invalid name of target grouping");
131 groupingPrefix = splitted[0];
132 groupingName = splitted[1];
134 groupingPrefix = module.getPrefix();
135 groupingName = groupingString;
138 Module dependentModule = ParserUtils.findModuleFromContext(context, module, groupingPrefix, line);
139 return findGroupingDefinition(dependentModule.getGroupings(), groupingName);
143 * Find grouping by name.
146 * collection of grouping builders to search
149 * @return grouping with given name if present in collection, null otherwise
151 public static GroupingBuilder findGroupingBuilder(Set<GroupingBuilder> groupings, String name) {
152 for (GroupingBuilder grouping : groupings) {
153 if (grouping.getQName().getLocalName().equals(name)) {
161 * Find grouping by name.
164 * collection of grouping definitions to search
167 * @return grouping with given name if present in collection, null otherwise
169 public static GroupingDefinition findGroupingDefinition(Set<GroupingDefinition> groupings, String name) {
170 for (GroupingDefinition grouping : groupings) {
171 if (grouping.getQName().getLocalName().equals(name)) {
179 * Perform refinement of uses target grouping nodes. Uses process has to be
183 * uses node containing refine statements
185 public static void performRefine(UsesNodeBuilder usesNode) {
186 for (RefineHolder refine : usesNode.getRefines()) {
187 String refineTargetPath = refine.getName();
189 String[] splitted = refineTargetPath.split("/");
190 Builder currentNode = usesNode.getParent();
191 for (String pathElement : splitted) {
192 if (currentNode instanceof DataNodeContainerBuilder) {
193 currentNode = ((DataNodeContainerBuilder) currentNode).getDataChildByName(pathElement);
194 } else if (currentNode instanceof ChoiceBuilder) {
195 currentNode = ((ChoiceBuilder) currentNode).getCaseNodeByName(pathElement);
199 DataSchemaNodeBuilder nodeToRefine = (DataSchemaNodeBuilder) currentNode;
200 if (nodeToRefine == null) {
201 throw new YangParseException(refine.getModuleName(), refine.getLine(), "Refine target node '"
202 + refine.getName() + "' not found");
204 RefineUtils.performRefine(nodeToRefine, refine);
205 usesNode.addRefineNode(nodeToRefine);
209 public static class UsesComparator implements Comparator<UsesNodeBuilder> {
211 public int compare(UsesNodeBuilder o1, UsesNodeBuilder o2) {
212 return getElementPosition(o2) - getElementPosition(o1);
216 private static int getElementPosition(UsesNodeBuilder usesNode) {
218 Builder parent = usesNode.getParent();
219 while (!(parent instanceof ModuleBuilder)) {
220 parent = parent.getParent();