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.builder.impl;
10 import com.google.common.base.Splitter;
12 import java.util.Comparator;
13 import java.util.Date;
16 import java.util.TreeMap;
17 import org.opendaylight.yangtools.yang.common.QName;
18 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
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.RefineBuilder;
24 import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder;
25 import org.opendaylight.yangtools.yang.parser.util.YangParseException;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
29 public final class GroupingUtils {
30 private static final Logger LOG = LoggerFactory.getLogger(GroupingUtils.class);
32 private static final Splitter COLON_SPLITTER = Splitter.on(':');
33 private static final Splitter SLASH_SPLITTER = Splitter.on('/');
35 private GroupingUtils() {
39 * Search given modules for grouping by name defined in uses node.
42 * builder of uses statement
47 * @return grouping with given name, never null
48 * @throws YangParseException
49 * if no grouping found
51 public static GroupingBuilder getTargetGroupingFromModules(final UsesNodeBuilder usesBuilder,
52 final Map<URI, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
53 final int line = usesBuilder.getLine();
55 SchemaPath groupingPath = usesBuilder.getTargetGroupingPath();
56 QName groupingName = groupingPath.getPathFromRoot().iterator().next();
57 ModuleBuilder dependentModule = BuilderUtils.findModule(groupingName, modules);
59 Set<GroupingBuilder> groupings = dependentModule.getGroupingBuilders();
60 GroupingBuilder result = findGroupingBuilder(groupings, groupingName.getLocalName());
65 Builder parent = usesBuilder.getParent();
66 while (parent != null) {
67 if (parent instanceof DataNodeContainerBuilder) {
68 groupings = ((DataNodeContainerBuilder) parent).getGroupingBuilders();
69 } else if (parent instanceof RpcDefinitionBuilder) {
70 groupings = ((RpcDefinitionBuilder) parent).getGroupings();
72 result = findGroupingBuilder(groupings, groupingName.getLocalName());
74 parent = parent.getParent();
81 throw new YangParseException(module.getName(), line, "Grouping '" + groupingName + "' not found.");
87 * Find grouping by name.
90 * collection of grouping builders to search
93 * @return grouping with given name if present in collection, null otherwise
95 private static GroupingBuilder findGroupingBuilder(final Set<GroupingBuilder> groupings, final String name) {
96 for (GroupingBuilder grouping : groupings) {
97 if (grouping.getQName().getLocalName().equals(name)) {
105 * Perform refinement of uses target grouping nodes. Uses process has to be
109 * uses node containing refine statements
111 public static void performRefine(final UsesNodeBuilder usesNode) {
112 for (RefineBuilder refine : usesNode.getRefines()) {
113 String refineTargetPath = refine.getTargetPathString();
115 Builder currentNode = usesNode.getParent();
116 for (String pathElement : SLASH_SPLITTER.split(refineTargetPath)) {
117 if (currentNode instanceof DataNodeContainerBuilder) {
118 currentNode = ((DataNodeContainerBuilder) currentNode).getDataChildByName(pathElement);
119 } else if (currentNode instanceof ChoiceBuilder) {
120 currentNode = ((ChoiceBuilder) currentNode).getCaseNodeByName(pathElement);
124 DataSchemaNodeBuilder nodeToRefine = (DataSchemaNodeBuilder) currentNode;
125 if (nodeToRefine == null) {
126 // FIXME: exception replaced with log to avoid breakage when
127 // user tries to refine instance of extension (unknown node)
129 // throw new YangParseException(refine.getModuleName(),
130 // refine.getLine(), "Refine target node '" +
131 // refine.getTargetPathString() + "' not found");
132 LOG.warn("Error in module {} at line {}: Refine target node {} not found.", refine.getModuleName(),
133 refine.getLine(), refine.getTargetPathString());
136 RefineUtils.performRefine(nodeToRefine, refine);
137 usesNode.addRefineNode(nodeToRefine);
141 public static class UsesComparator implements Comparator<UsesNodeBuilder> {
143 public int compare(final UsesNodeBuilder o1, final UsesNodeBuilder o2) {
144 return getElementPosition(o2) - getElementPosition(o1);
148 private static int getElementPosition(final UsesNodeBuilder usesNode) {
150 Builder parent = usesNode.getParent();
151 while (!(parent instanceof ModuleBuilder)) {
152 parent = parent.getParent();