Merge "Bug 560: Fixed incoherent API implementation."
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / builder / util / AbstractDocumentedDataNodeContainerBuilder.java
1 /*
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
6  */
7 package org.opendaylight.yangtools.yang.parser.builder.util;
8
9 import java.util.HashSet;
10 import java.util.Map;
11 import java.util.Set;
12 import java.util.TreeMap;
13 import java.util.TreeSet;
14
15 import org.opendaylight.yangtools.yang.common.QName;
16 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
17 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
18 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
19 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
20 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
21 import org.opendaylight.yangtools.yang.model.api.UsesNode;
22 import org.opendaylight.yangtools.yang.parser.builder.api.DataNodeContainerBuilder;
23 import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
24 import org.opendaylight.yangtools.yang.parser.builder.api.GroupingBuilder;
25 import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder;
26 import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder;
27 import org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils;
28 import org.opendaylight.yangtools.yang.parser.util.YangParseException;
29
30 /**
31  * Basic implementation of DataNodeContainerBuilder.
32  */
33 public abstract class AbstractDocumentedDataNodeContainerBuilder extends AbstractDocumentedNodeBuilder implements DataNodeContainerBuilder {
34     protected final QName qname;
35
36     private final Map<QName, DataSchemaNode> childNodes = new TreeMap<>();
37     private final Set<DataSchemaNodeBuilder> addedChildNodes = new HashSet<>();
38
39     private final Set<GroupingDefinition> groupings = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
40     private final Set<GroupingBuilder> addedGroupings = new HashSet<>();
41
42     private final Set<TypeDefinition<?>> typedefs = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
43     private final Set<TypeDefinitionBuilder> addedTypedefs = new HashSet<>();
44
45     private final Set<UsesNode> usesNodes = new HashSet<>();
46     private final Set<UsesNodeBuilder> addedUsesNodes = new HashSet<>();
47
48     protected AbstractDocumentedDataNodeContainerBuilder(final String moduleName, final int line, final QName qname) {
49         super(moduleName, line);
50         this.qname = qname;
51     }
52
53     protected AbstractDocumentedDataNodeContainerBuilder(final String moduleName, final int line, final QName qname, final SchemaPath path, final DataNodeContainer base) {
54         super(moduleName, line);
55         this.qname = qname;
56
57         // We do copy of child nodes with namespace change
58         // FIXME: Copy should be part of builder API so impl we prevent
59         // cyclic dependencies and each builder carries its own semantic for copy.
60         addedChildNodes.addAll(BuilderUtils.wrapChildNodes(moduleName, line, base.getChildNodes(), path, qname));
61         addedGroupings.addAll(BuilderUtils.wrapGroupings(moduleName, line, base.getGroupings(), path, qname));
62         addedTypedefs.addAll(BuilderUtils.wrapTypedefs(moduleName, line, base, path, qname));
63         // FIXME: unkownSchemaNodes should be available in DataNodeContainer
64         // addedUnknownNodes.addAll(BuilderUtils.wrapUnknownNodes(moduleName,
65         // line, base.getUnknownSchemaNodes(), path, qname));
66         usesNodes.addAll(base.getUses());
67     }
68
69     @Override
70     public final QName getQName() {
71         return qname;
72     }
73
74     @Override
75     public final Map<QName, DataSchemaNode> getChildNodes() {
76         return childNodes;
77     }
78
79     @Override
80     public final Set<DataSchemaNodeBuilder> getChildNodeBuilders() {
81         return addedChildNodes;
82     }
83
84     @Override
85     public final DataSchemaNodeBuilder getDataChildByName(final String name) {
86         for (DataSchemaNodeBuilder child : addedChildNodes) {
87             if (child.getQName().getLocalName().equals(name)) {
88                 return child;
89             }
90         }
91         return null;
92     }
93
94     @Override
95     public final void addChildNode(final DataSchemaNodeBuilder child) {
96         QName childName = child.getQName();
97         for (DataSchemaNodeBuilder addedChildNode : addedChildNodes) {
98             if (addedChildNode.getQName().equals(childName)) {
99                 throw new YangParseException(child.getModuleName(), child.getLine(), String.format(
100                         "Can not add '%s' to '%s' in module '%s': node with same name already declared at line %d",
101                         child, this, getModuleName(), addedChildNode.getLine()));
102             }
103         }
104         addedChildNodes.add(child);
105     }
106
107     @Override
108     public final void addChildNodeToContext(final DataSchemaNodeBuilder child) {
109         addedChildNodes.add(child);
110     }
111
112     @Override
113     public final void addChildNode(final DataSchemaNode child) {
114         checkNotSealed();
115         QName childName = child.getQName();
116         for (DataSchemaNode childNode : childNodes.values()) {
117             if (childNode.getQName().equals(childName)) {
118                 throw new YangParseException(getModuleName(), getLine(), String.format(
119                         "Can not add '%s' to '%s' in module '%s': node with same name already declared", child, this,
120                         getModuleName()));
121             }
122         }
123         childNodes.put(child.getQName(), child);
124     }
125
126     @Override
127     public final Set<GroupingDefinition> getGroupings() {
128         return groupings;
129     }
130
131     @Override
132     public final Set<GroupingBuilder> getGroupingBuilders() {
133         return addedGroupings;
134     }
135
136     @Override
137     public final void addGrouping(final GroupingBuilder grouping) {
138         checkNotSealed();
139         QName groupingName = grouping.getQName();
140         for (GroupingBuilder addedGrouping : addedGroupings) {
141             if (addedGrouping.getQName().equals(groupingName)) {
142                 throw new YangParseException(grouping.getModuleName(), grouping.getLine(), String.format(
143                         "Can not add '%s': grouping with same name already declared in module '%s' at line %d",
144                         grouping, getModuleName(), addedGrouping.getLine()));
145             }
146         }
147         addedGroupings.add(grouping);
148     }
149
150     @Override
151     public final Set<TypeDefinition<?>> getTypeDefinitions() {
152         return typedefs;
153     }
154
155     public final Set<UsesNode> getUsesNodes() {
156         return usesNodes;
157     }
158
159     @Override
160     public final Set<UsesNodeBuilder> getUsesNodeBuilders() {
161         return addedUsesNodes;
162     }
163
164     @Override
165     public final void addUsesNode(final UsesNodeBuilder usesNode) {
166         checkNotSealed();
167         addedUsesNodes.add(usesNode);
168     }
169
170
171     @Override
172     public final Set<TypeDefinitionBuilder> getTypeDefinitionBuilders() {
173         return addedTypedefs;
174     }
175
176     @Override
177     public void addTypedef(final TypeDefinitionBuilder type) {
178         checkNotSealed();
179         String typeName = type.getQName().getLocalName();
180         for (TypeDefinitionBuilder addedTypedef : addedTypedefs) {
181             if (addedTypedef.getQName().getLocalName().equals(typeName)) {
182                 throw new YangParseException(getModuleName(), type.getLine(), "Can not add typedef '" + typeName
183                         + "': typedef with same name already declared at line " + addedTypedef.getLine());
184             }
185         }
186         addedTypedefs.add(type);
187     }
188
189     protected abstract String getStatementName();
190
191     protected void buildChildren() {
192         checkNotSealed();
193         seal();
194
195         for (DataSchemaNodeBuilder node : addedChildNodes) {
196             childNodes.put(node.getQName(), node.build());
197         }
198
199         for (GroupingBuilder builder : addedGroupings) {
200             groupings.add(builder.build());
201         }
202
203         for (TypeDefinitionBuilder entry : addedTypedefs) {
204             typedefs.add(entry.build());
205         }
206
207         for (UsesNodeBuilder builder : addedUsesNodes) {
208             usesNodes.add(builder.build());
209         }
210     }
211
212     @Deprecated
213     protected static DataSchemaNode getChildNode(final Set<DataSchemaNode> childNodes, final QName name) {
214         for (DataSchemaNode node : childNodes) {
215             if (node.getQName().equals(name)) {
216                 return node;
217             }
218         }
219         return null;
220     }
221
222     @Deprecated
223     protected static DataSchemaNode getChildNode(final Set<DataSchemaNode> childNodes, final String name) {
224         for (DataSchemaNode node : childNodes) {
225             if (node.getQName().getLocalName().equals(name)) {
226                 return node;
227             }
228         }
229         return null;
230     }
231
232
233 }