2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
3 * This program and the accompanying materials are made available under the
4 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
5 * and is available at http://www.eclipse.org/legal/epl-v10.html
7 package org.opendaylight.yangtools.yang.parser.builder.util;
9 import java.util.ArrayList;
10 import java.util.HashSet;
11 import java.util.LinkedHashMap;
12 import java.util.List;
15 import java.util.TreeSet;
16 import org.opendaylight.yangtools.yang.common.QName;
17 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
18 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
19 import org.opendaylight.yangtools.yang.model.api.DocumentedNode;
20 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
21 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
22 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
23 import org.opendaylight.yangtools.yang.model.api.UsesNode;
24 import org.opendaylight.yangtools.yang.parser.builder.api.DataNodeContainerBuilder;
25 import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
26 import org.opendaylight.yangtools.yang.parser.builder.api.GroupingBuilder;
27 import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder;
28 import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder;
29 import org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils;
30 import org.opendaylight.yangtools.yang.parser.util.YangParseException;
33 * Basic implementation of DataNodeContainerBuilder.
35 public abstract class AbstractDocumentedDataNodeContainerBuilder extends AbstractDocumentedNodeBuilder implements DataNodeContainerBuilder {
36 protected final QName qname;
38 private final Map<QName, DataSchemaNode> childNodes = new LinkedHashMap<>();
39 private final List<DataSchemaNodeBuilder> addedChildNodes = new ArrayList<>();
41 private final Set<GroupingDefinition> groupings = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
42 private final Set<GroupingBuilder> addedGroupings = new HashSet<>();
44 private final Set<TypeDefinition<?>> typedefs = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
45 private final Set<TypeDefinitionBuilder> addedTypedefs = new HashSet<>();
47 private final Set<UsesNode> usesNodes = new HashSet<>();
48 private final List<UsesNodeBuilder> addedUsesNodes = new ArrayList<>();
50 protected AbstractDocumentedDataNodeContainerBuilder(final String moduleName, final int line, final QName qname) {
51 super(moduleName, line);
55 protected AbstractDocumentedDataNodeContainerBuilder(final String moduleName, final int line, final QName qname, final SchemaPath path, final DataNodeContainer base) {
56 super(moduleName, line);
59 // We do copy of child nodes with namespace change
60 // FIXME: Copy should be part of builder API so impl we prevent
61 // cyclic dependencies and each builder carries its own semantic for copy.
62 addedChildNodes.addAll(BuilderUtils.wrapChildNodes(moduleName, line, base.getChildNodes(), path, qname));
63 addedGroupings.addAll(BuilderUtils.wrapGroupings(moduleName, line, base.getGroupings(), path, qname));
64 addedTypedefs.addAll(BuilderUtils.wrapTypedefs(moduleName, line, base, path, qname));
65 // FIXME: unkownSchemaNodes should be available in DataNodeContainer
66 // addedUnknownNodes.addAll(BuilderUtils.wrapUnknownNodes(moduleName,
67 // line, base.getUnknownSchemaNodes(), path, qname));
68 usesNodes.addAll(base.getUses());
70 if (base instanceof DocumentedNode) {
71 DocumentedNode node = (DocumentedNode) base;
72 setDescription(node.getDescription());
73 setReference(node.getReference());
74 setStatus(node.getStatus());
79 public final QName getQName() {
84 public final Map<QName, DataSchemaNode> getChildNodes() {
89 public final List<DataSchemaNodeBuilder> getChildNodeBuilders() {
90 return addedChildNodes;
94 public final DataSchemaNodeBuilder getDataChildByName(final String name) {
95 for (DataSchemaNodeBuilder child : addedChildNodes) {
96 if (child.getQName().getLocalName().equals(name)) {
104 public final void addChildNode(final DataSchemaNodeBuilder child) {
105 checkIsPresent(child);
106 addedChildNodes.add(child);
110 public final void addChildNode(final int index, final DataSchemaNodeBuilder child) {
111 checkIsPresent(child);
112 if (index > addedChildNodes.size()) {
113 addedChildNodes.add(child);
115 addedChildNodes.add(index, child);
119 private void checkIsPresent(final DataSchemaNodeBuilder child) {
120 for (DataSchemaNodeBuilder addedChildNode : addedChildNodes) {
121 if (addedChildNode.getQName().equals(child.getQName())) {
122 throw new YangParseException(child.getModuleName(), child.getLine(), String.format(
123 "Can not add '%s' to '%s' in module '%s': node with same name already declared at line %d",
124 child, this, getModuleName(), addedChildNode.getLine()));
130 public final void addChildNodeToContext(final DataSchemaNodeBuilder child) {
131 addedChildNodes.add(child);
135 public final void addChildNode(final DataSchemaNode child) {
137 QName childName = child.getQName();
138 if (childNodes.containsKey(childName)) {
139 throw new YangParseException(getModuleName(), getLine(), String.format(
140 "Can not add '%s' to '%s' in module '%s': node with same name already declared", child, this,
143 childNodes.put(childName, child);
147 public final Set<GroupingDefinition> getGroupings() {
152 public final Set<GroupingBuilder> getGroupingBuilders() {
153 return addedGroupings;
157 public void addGrouping(final GroupingBuilder grouping) {
159 QName groupingName = grouping.getQName();
160 for (GroupingBuilder addedGrouping : addedGroupings) {
161 if (addedGrouping.getQName().equals(groupingName)) {
162 throw new YangParseException(grouping.getModuleName(), grouping.getLine(), String.format(
163 "Can not add '%s': grouping with same name already declared in module '%s' at line %d",
164 grouping, getModuleName(), addedGrouping.getLine()));
167 addedGroupings.add(grouping);
171 public final Set<TypeDefinition<?>> getTypeDefinitions() {
175 public final Set<UsesNode> getUsesNodes() {
180 public final List<UsesNodeBuilder> getUsesNodeBuilders() {
181 return addedUsesNodes;
185 public final void addUsesNode(final UsesNodeBuilder usesNode) {
187 addedUsesNodes.add(usesNode);
192 public final Set<TypeDefinitionBuilder> getTypeDefinitionBuilders() {
193 return addedTypedefs;
197 public void addTypedef(final TypeDefinitionBuilder type) {
199 String typeName = type.getQName().getLocalName();
200 for (TypeDefinitionBuilder addedTypedef : addedTypedefs) {
201 if (addedTypedef.getQName().getLocalName().equals(typeName)) {
202 throw new YangParseException(getModuleName(), type.getLine(), "Can not add typedef '" + typeName
203 + "': typedef with same name already declared at line " + addedTypedef.getLine());
206 addedTypedefs.add(type);
209 protected abstract String getStatementName();
211 protected void buildChildren() {
215 for (DataSchemaNodeBuilder node : addedChildNodes) {
216 childNodes.put(node.getQName(), node.build());
219 for (GroupingBuilder builder : addedGroupings) {
220 groupings.add(builder.build());
223 for (TypeDefinitionBuilder entry : addedTypedefs) {
224 typedefs.add(entry.build());
227 for (UsesNodeBuilder builder : addedUsesNodes) {
228 usesNodes.add(builder.build());