Merge "Bug 762: Verify input in typedef codecs"
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / builder / impl / RefineUtils.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.parser.builder.impl;
9
10 import java.util.List;
11
12 import org.opendaylight.yangtools.yang.model.api.MustDefinition;
13 import org.opendaylight.yangtools.yang.parser.builder.api.Builder;
14 import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
15 import org.opendaylight.yangtools.yang.parser.builder.api.DocumentedNodeBuilder;
16 import org.opendaylight.yangtools.yang.parser.builder.api.GroupingBuilder;
17 import org.opendaylight.yangtools.yang.parser.builder.api.RefineBuilder;
18 import org.opendaylight.yangtools.yang.parser.builder.api.SchemaNodeBuilder;
19 import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder;
20 import org.opendaylight.yangtools.yang.parser.builder.api.UnknownSchemaNodeBuilder;
21 import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder;
22 import org.opendaylight.yangtools.yang.parser.util.YangParseException;
23
24 /**
25  * Utility class with helper methods to perform operations tied to refine
26  * process.
27  */
28 public final class RefineUtils {
29
30     private RefineUtils() {
31     }
32
33     public static void refineLeaf(final LeafSchemaNodeBuilder leaf, final RefineBuilder refine) {
34         String defaultStr = refine.getDefaultStr();
35         Boolean mandatory = refine.isMandatory();
36         MustDefinition must = refine.getMust();
37         List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
38
39         if (defaultStr != null && !("".equals(defaultStr))) {
40             leaf.setDefaultStr(defaultStr);
41         }
42         if (mandatory != null) {
43             leaf.getConstraints().setMandatory(mandatory);
44         }
45         if (must != null) {
46             leaf.getConstraints().addMustDefinition(must);
47         }
48         if (unknownNodes != null) {
49             for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
50                 unknown.setParent(leaf);
51                 leaf.addUnknownNodeBuilder(unknown);
52             }
53         }
54     }
55
56     public static void refineContainer(final ContainerSchemaNodeBuilder container, final RefineBuilder refine) {
57         Boolean presence = refine.isPresence();
58         MustDefinition must = refine.getMust();
59         List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
60
61         if (presence != null) {
62             container.setPresence(presence);
63         }
64         if (must != null) {
65             container.getConstraints().addMustDefinition(must);
66         }
67         if (unknownNodes != null) {
68             for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
69                 unknown.setParent(container);
70                 container.addUnknownNodeBuilder(unknown);
71             }
72         }
73     }
74
75     public static void refineList(final ListSchemaNodeBuilder list, final RefineBuilder refine) {
76         MustDefinition must = refine.getMust();
77         Integer min = refine.getMinElements();
78         Integer max = refine.getMaxElements();
79         List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
80
81         if (must != null) {
82             list.getConstraints().addMustDefinition(must);
83         }
84         if (min != null) {
85             list.getConstraints().setMinElements(min);
86         }
87         if (max != null) {
88             list.getConstraints().setMaxElements(max);
89         }
90         if (unknownNodes != null) {
91             for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
92                 unknown.setParent(list);
93                 list.addUnknownNodeBuilder(unknown);
94             }
95         }
96     }
97
98     public static void refineLeafList(final LeafListSchemaNodeBuilder leafList, final RefineBuilder refine) {
99         MustDefinition must = refine.getMust();
100         Integer min = refine.getMinElements();
101         Integer max = refine.getMaxElements();
102         List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
103
104         if (must != null) {
105             leafList.getConstraints().addMustDefinition(must);
106         }
107         if (min != null) {
108             leafList.getConstraints().setMinElements(min);
109         }
110         if (max != null) {
111             leafList.getConstraints().setMaxElements(max);
112         }
113         if (unknownNodes != null) {
114             for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
115                 unknown.setParent(leafList);
116                 leafList.addUnknownNodeBuilder(unknown);
117             }
118         }
119     }
120
121     public static void refineChoice(final ChoiceBuilder choice, final RefineBuilder refine) {
122         String defaultStr = refine.getDefaultStr();
123         Boolean mandatory = refine.isMandatory();
124         List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
125
126         if (defaultStr != null) {
127             choice.setDefaultCase(defaultStr);
128         }
129         if (mandatory != null) {
130             choice.getConstraints().setMandatory(mandatory);
131         }
132         if (unknownNodes != null) {
133             for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
134                 unknown.setParent(choice);
135                 choice.addUnknownNodeBuilder(unknown);
136             }
137         }
138     }
139
140     public static void refineAnyxml(final AnyXmlBuilder anyXml, final RefineBuilder refine) {
141         Boolean mandatory = refine.isMandatory();
142         MustDefinition must = refine.getMust();
143         List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
144
145         if (mandatory != null) {
146             anyXml.getConstraints().setMandatory(mandatory);
147         }
148         if (must != null) {
149             anyXml.getConstraints().addMustDefinition(must);
150         }
151         if (unknownNodes != null) {
152             for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
153                 unknown.setParent(anyXml);
154                 anyXml.addUnknownNodeBuilder(unknown);
155             }
156         }
157     }
158
159     /**
160      * Check if refine can be performed on given node.
161      *
162      * @param node
163      *            node to refine
164      * @param refine
165      *            refine object containing information about refine process
166      */
167     private static void checkRefine(final SchemaNodeBuilder node, final RefineBuilder refine) {
168         String moduleName = refine.getModuleName();
169         int line = refine.getLine();
170         String name = node.getQName().getLocalName();
171
172         String defaultStr = refine.getDefaultStr();
173         Boolean mandatory = refine.isMandatory();
174         Boolean presence = refine.isPresence();
175         MustDefinition must = refine.getMust();
176         Integer min = refine.getMinElements();
177         Integer max = refine.getMaxElements();
178
179         if (node instanceof AnyXmlBuilder) {
180             checkRefineDefault(node, defaultStr, moduleName, line);
181             checkRefinePresence(node, presence, moduleName, line);
182             checkRefineMinMax(name, min, max, moduleName, line);
183         } else if (node instanceof ChoiceBuilder) {
184             checkRefinePresence(node, presence, moduleName, line);
185             checkRefineMust(node, must, moduleName, line);
186             checkRefineMinMax(name, min, max, moduleName, line);
187         } else if (node instanceof ContainerSchemaNodeBuilder) {
188             checkRefineDefault(node, defaultStr, moduleName, line);
189             checkRefineMandatory(node, mandatory, moduleName, line);
190             checkRefineMust(node, must, moduleName, line);
191             checkRefineMinMax(name, min, max, moduleName, line);
192         } else if (node instanceof LeafSchemaNodeBuilder) {
193             checkRefinePresence(node, presence, moduleName, line);
194             checkRefineMinMax(name, min, max, moduleName, line);
195         } else if (node instanceof LeafListSchemaNodeBuilder || node instanceof ListSchemaNodeBuilder) {
196             checkRefineDefault(node, defaultStr, moduleName, line);
197             checkRefinePresence(node, presence, moduleName, line);
198             checkRefineMandatory(node, mandatory, moduleName, line);
199         } else if (node instanceof GroupingBuilder || node instanceof TypeDefinitionBuilder
200                 || node instanceof UsesNodeBuilder) {
201             checkRefineDefault(node, defaultStr, moduleName, line);
202             checkRefinePresence(node, presence, moduleName, line);
203             checkRefineMandatory(node, mandatory, moduleName, line);
204             checkRefineMust(node, must, moduleName, line);
205             checkRefineMinMax(name, min, max, moduleName, line);
206         }
207     }
208
209     private static void checkRefineDefault(final SchemaNodeBuilder node, final String defaultStr, final String moduleName, final int line) {
210         if (defaultStr != null) {
211             throw new YangParseException(moduleName, line, "Can not refine 'default' for '"
212                     + node.getQName().getLocalName() + "'.");
213         }
214     }
215
216     private static void checkRefineMandatory(final SchemaNodeBuilder node, final Boolean mandatory, final String moduleName, final int line) {
217         if (mandatory != null) {
218             throw new YangParseException(moduleName, line, "Can not refine 'mandatory' for '"
219                     + node.getQName().getLocalName() + "'.");
220         }
221     }
222
223     private static void checkRefinePresence(final SchemaNodeBuilder node, final Boolean presence, final String moduleName, final int line) {
224         if (presence != null) {
225             throw new YangParseException(moduleName, line, "Can not refine 'presence' for '"
226                     + node.getQName().getLocalName() + "'.");
227         }
228     }
229
230     private static void checkRefineMust(final SchemaNodeBuilder node, final MustDefinition must, final String moduleName, final int line) {
231         if (must != null) {
232             throw new YangParseException(moduleName, line, "Can not refine 'must' for '"
233                     + node.getQName().getLocalName() + "'.");
234         }
235     }
236
237     private static void checkRefineMinMax(final String refineTargetName, final Integer min, final Integer max, final String moduleName, final int line) {
238         if (min != null || max != null) {
239             throw new YangParseException(moduleName, line, "Can not refine 'min-elements' or 'max-elements' for '"
240                     + refineTargetName + "'.");
241         }
242     }
243
244     /**
245      * Perform refine operation of following parameters:
246      * <ul>
247      * <li>description</li>
248      * <li>reference</li>
249      * <li>config</li>
250      * </ul>
251      *
252      * These parameters may be refined for any node.
253      *
254      * @param node
255      *            node to refine
256      * @param refine
257      *            refine object containing information about refine process
258      */
259     private static void refineDefault(final Builder node, final RefineBuilder refine) {
260         final String moduleName = refine.getModuleName();
261         final int line = refine.getLine();
262         Class<? extends Builder> cls = node.getClass();
263
264
265         final DocumentedNodeBuilder documentedNode;
266         if(node instanceof DocumentedNodeBuilder) {
267             documentedNode = ((DocumentedNodeBuilder) node);
268         } else {
269             documentedNode = null;
270         }
271
272         String description = refine.getDescription();
273
274
275         if (description != null) {
276             if(documentedNode != null) {
277                 documentedNode.setDescription(description);
278             } else {
279                 throw new YangParseException(moduleName, line, String.format("Cannot refine description in of target %s",refine.getTargetPathString()));
280             }
281
282         }
283
284         String reference = refine.getReference();
285         if (reference != null) {
286             if(documentedNode != null) {
287                 documentedNode.setReference(reference);
288             } else {
289                 throw new YangParseException(moduleName, line, String.format("Cannot refine reference in of target %s",refine.getTargetPathString()));
290             }
291         }
292
293         Boolean config = refine.isConfiguration();
294         if (config != null) {
295             if(node instanceof DataSchemaNodeBuilder) {
296                 ((DataSchemaNodeBuilder) node).setConfiguration(config);
297             } else {
298                 throw new YangParseException(moduleName, line, String.format("Cannot refine config of target %s ",refine.getTargetPathString()));
299             }
300         }
301     }
302
303     /**
304      * Perform refine operation on given node.
305      *
306      * @param nodeToRefine
307      *            builder of node to refine
308      * @param refine
309      *            refine object containing information about refine process
310      */
311     static void performRefine(final SchemaNodeBuilder nodeToRefine, final RefineBuilder refine) {
312         checkRefine(nodeToRefine, refine);
313         refineDefault(nodeToRefine, refine);
314         if (nodeToRefine instanceof LeafSchemaNodeBuilder) {
315             refineLeaf((LeafSchemaNodeBuilder) nodeToRefine, refine);
316         } else if (nodeToRefine instanceof ContainerSchemaNodeBuilder) {
317             refineContainer((ContainerSchemaNodeBuilder) nodeToRefine, refine);
318         } else if (nodeToRefine instanceof ListSchemaNodeBuilder) {
319             refineList((ListSchemaNodeBuilder) nodeToRefine, refine);
320         } else if (nodeToRefine instanceof LeafListSchemaNodeBuilder) {
321             refineLeafList((LeafListSchemaNodeBuilder) nodeToRefine, refine);
322         } else if (nodeToRefine instanceof ChoiceBuilder) {
323             refineChoice((ChoiceBuilder) nodeToRefine, refine);
324         } else if (nodeToRefine instanceof AnyXmlBuilder) {
325             refineAnyxml((AnyXmlBuilder) nodeToRefine, refine);
326         }
327     }
328
329 }