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