8db4e8e6fd56e8656679926ff38433696740ee27
[controller.git] / opendaylight / sal / yang-prototype / code-generator / yang-model-parser-impl / src / main / java / org / opendaylight / controller / 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.controller.yang.parser.util;
9
10 import static org.opendaylight.controller.yang.parser.util.ParserUtils.*;
11
12 import java.lang.reflect.Method;
13 import java.util.List;
14
15 import org.opendaylight.controller.yang.model.api.AnyXmlSchemaNode;
16 import org.opendaylight.controller.yang.model.api.ChoiceNode;
17 import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
18 import org.opendaylight.controller.yang.model.api.GroupingDefinition;
19 import org.opendaylight.controller.yang.model.api.LeafListSchemaNode;
20 import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
21 import org.opendaylight.controller.yang.model.api.ListSchemaNode;
22 import org.opendaylight.controller.yang.model.api.MustDefinition;
23 import org.opendaylight.controller.yang.model.api.TypeDefinition;
24 import org.opendaylight.controller.yang.model.util.ExtendedType;
25 import org.opendaylight.controller.yang.parser.builder.api.Builder;
26 import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
27 import org.opendaylight.controller.yang.parser.builder.api.SchemaNodeBuilder;
28 import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
29 import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
30 import org.opendaylight.controller.yang.parser.builder.impl.AnyXmlBuilder;
31 import org.opendaylight.controller.yang.parser.builder.impl.ChoiceBuilder;
32 import org.opendaylight.controller.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
33 import org.opendaylight.controller.yang.parser.builder.impl.LeafListSchemaNodeBuilder;
34 import org.opendaylight.controller.yang.parser.builder.impl.LeafSchemaNodeBuilder;
35 import org.opendaylight.controller.yang.parser.builder.impl.ListSchemaNodeBuilder;
36 import org.opendaylight.controller.yang.parser.builder.impl.TypeDefinitionBuilderImpl;
37 import org.opendaylight.controller.yang.parser.builder.impl.UnknownSchemaNodeBuilder;
38
39 /**
40  * Utility class with helper methods to perform operations tied to refine
41  * process.
42  */
43 public class RefineUtils {
44
45     private RefineUtils() {
46     }
47
48     /**
49      * Find original builder of node to refine and return copy of this builder.
50      * <p>
51      * We must create and use a copy of builder to preserve original builder
52      * state, because this object will be refined (modified) and later added to
53      * {@link UsesNodeBuilder}.
54      * </p>
55      *
56      * @param targetGrouping
57      *            builder of grouping which should contains node to refine
58      * @param refine
59      *            refine object containing informations about refine
60      * @param moduleName
61      *            current module name
62      * @return
63      */
64     public static SchemaNodeBuilder getRefineNodeFromGroupingBuilder(final GroupingBuilder targetGrouping,
65             final RefineHolder refine, final String moduleName) {
66         Builder result = null;
67         final Builder lookedUpBuilder = findRefineTargetBuilder(targetGrouping, refine.getName());
68         if (lookedUpBuilder instanceof LeafSchemaNodeBuilder) {
69             result = copyLeafBuilder((LeafSchemaNodeBuilder) lookedUpBuilder);
70         } else if (lookedUpBuilder instanceof ContainerSchemaNodeBuilder) {
71             result = copyContainerBuilder((ContainerSchemaNodeBuilder) lookedUpBuilder);
72         } else if (lookedUpBuilder instanceof ListSchemaNodeBuilder) {
73             result = copyListBuilder((ListSchemaNodeBuilder) lookedUpBuilder);
74         } else if (lookedUpBuilder instanceof LeafListSchemaNodeBuilder) {
75             result = copyLeafListBuilder((LeafListSchemaNodeBuilder) lookedUpBuilder);
76         } else if (lookedUpBuilder instanceof ChoiceBuilder) {
77             result = copyChoiceBuilder((ChoiceBuilder) lookedUpBuilder);
78         } else if (lookedUpBuilder instanceof AnyXmlBuilder) {
79             result = copyAnyXmlBuilder((AnyXmlBuilder) lookedUpBuilder);
80         } else if (lookedUpBuilder instanceof GroupingBuilder) {
81             result = copyGroupingBuilder((GroupingBuilder) lookedUpBuilder);
82         } else if (lookedUpBuilder instanceof TypeDefinitionBuilder) {
83             result = copyTypedefBuilder((TypeDefinitionBuilderImpl) lookedUpBuilder);
84         } else {
85             throw new YangParseException(moduleName, refine.getLine(), "Target '" + refine.getName()
86                     + "' can not be refined");
87         }
88         return (SchemaNodeBuilder) result;
89     }
90
91     /**
92      * Create builder object from refine target node.
93      *
94      * @param grouping
95      *            grouping which should contains node to refine
96      * @param refine
97      *            refine object containing informations about refine
98      * @param moduleName
99      *            current module name
100      * @return
101      */
102     public static SchemaNodeBuilder getRefineNodeFromGroupingDefinition(final GroupingDefinition grouping,
103             final RefineHolder refine, final String moduleName) {
104         SchemaNodeBuilder result = null;
105         final int line = refine.getLine();
106         final Object lookedUpNode = findRefineTargetNode(grouping, refine.getName());
107         if (lookedUpNode instanceof LeafSchemaNode) {
108             result = createLeafBuilder((LeafSchemaNode) lookedUpNode, line);
109         } else if (lookedUpNode instanceof ContainerSchemaNode) {
110             result = createContainer((ContainerSchemaNode) lookedUpNode, line);
111         } else if (lookedUpNode instanceof ListSchemaNode) {
112             result = createList((ListSchemaNode) lookedUpNode, line);
113         } else if (lookedUpNode instanceof LeafListSchemaNode) {
114             result = createLeafList((LeafListSchemaNode) lookedUpNode, line);
115         } else if (lookedUpNode instanceof ChoiceNode) {
116             result = createChoice((ChoiceNode) lookedUpNode, line);
117         } else if (lookedUpNode instanceof AnyXmlSchemaNode) {
118             result = createAnyXml((AnyXmlSchemaNode) lookedUpNode, line);
119         } else if (lookedUpNode instanceof GroupingDefinition) {
120             result = createGrouping((GroupingDefinition) lookedUpNode, line);
121         } else if (lookedUpNode instanceof TypeDefinition) {
122             result = createTypedef((ExtendedType) lookedUpNode, line);
123         } else {
124             throw new YangParseException(moduleName, line, "Target '" + refine.getName() + "' can not be refined");
125         }
126         return result;
127     }
128
129     public static void refineLeaf(LeafSchemaNodeBuilder leaf, RefineHolder refine, int line) {
130         String defaultStr = refine.getDefaultStr();
131         Boolean mandatory = refine.isMandatory();
132         MustDefinition must = refine.getMust();
133         List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
134
135         if (defaultStr != null && !("".equals(defaultStr))) {
136             leaf.setDefaultStr(defaultStr);
137         }
138         if (mandatory != null) {
139             leaf.getConstraints().setMandatory(mandatory);
140         }
141         if (must != null) {
142             leaf.getConstraints().addMustDefinition(must);
143         }
144         if (unknownNodes != null) {
145             for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
146                 leaf.addUnknownSchemaNode(unknown);
147             }
148         }
149     }
150
151     public static void refineContainer(ContainerSchemaNodeBuilder container, RefineHolder refine, int line) {
152         Boolean presence = refine.isPresence();
153         MustDefinition must = refine.getMust();
154         List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
155
156         if (presence != null) {
157             container.setPresence(presence);
158         }
159         if (must != null) {
160             container.getConstraints().addMustDefinition(must);
161         }
162         if (unknownNodes != null) {
163             for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
164                 container.addUnknownSchemaNode(unknown);
165             }
166         }
167     }
168
169     public static void refineList(ListSchemaNodeBuilder list, RefineHolder refine, int line) {
170         MustDefinition must = refine.getMust();
171         Integer min = refine.getMinElements();
172         Integer max = refine.getMaxElements();
173         List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
174
175         if (must != null) {
176             list.getConstraints().addMustDefinition(must);
177         }
178         if (min != null) {
179             list.getConstraints().setMinElements(min);
180         }
181         if (max != null) {
182             list.getConstraints().setMaxElements(max);
183         }
184         if (unknownNodes != null) {
185             for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
186                 list.addUnknownSchemaNode(unknown);
187             }
188         }
189     }
190
191     public static void refineLeafList(LeafListSchemaNodeBuilder leafList, RefineHolder refine, int line) {
192         MustDefinition must = refine.getMust();
193         Integer min = refine.getMinElements();
194         Integer max = refine.getMaxElements();
195         List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
196
197         if (must != null) {
198             leafList.getConstraints().addMustDefinition(must);
199         }
200         if (min != null) {
201             leafList.getConstraints().setMinElements(min);
202         }
203         if (max != null) {
204             leafList.getConstraints().setMaxElements(max);
205         }
206         if (unknownNodes != null) {
207             for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
208                 leafList.addUnknownSchemaNode(unknown);
209             }
210         }
211     }
212
213     public static void refineChoice(ChoiceBuilder choice, RefineHolder refine, int line) {
214         String defaultStr = refine.getDefaultStr();
215         Boolean mandatory = refine.isMandatory();
216         List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
217
218         if (defaultStr != null) {
219             choice.setDefaultCase(defaultStr);
220         }
221         if (mandatory != null) {
222             choice.getConstraints().setMandatory(mandatory);
223         }
224         if (unknownNodes != null) {
225             for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
226                 choice.addUnknownSchemaNode(unknown);
227             }
228         }
229     }
230
231     public static void refineAnyxml(AnyXmlBuilder anyXml, RefineHolder refine, int line) {
232         Boolean mandatory = refine.isMandatory();
233         MustDefinition must = refine.getMust();
234         List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
235
236         if (mandatory != null) {
237             anyXml.getConstraints().setMandatory(mandatory);
238         }
239         if (must != null) {
240             anyXml.getConstraints().addMustDefinition(must);
241         }
242         if (unknownNodes != null) {
243             for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
244                 anyXml.addUnknownSchemaNode(unknown);
245             }
246         }
247     }
248
249     /**
250      * Check if refine can be performed on given node.
251      *
252      * @param node
253      *            node to refine
254      * @param refine
255      *            refine object containing information about refine process
256      */
257     public static void checkRefine(SchemaNodeBuilder node, RefineHolder refine) {
258         String name = node.getQName().getLocalName();
259         int line = refine.getLine();
260
261         String defaultStr = refine.getDefaultStr();
262         Boolean mandatory = refine.isMandatory();
263         Boolean presence = refine.isPresence();
264         MustDefinition must = refine.getMust();
265         Integer min = refine.getMinElements();
266         Integer max = refine.getMaxElements();
267
268         if (node instanceof AnyXmlBuilder) {
269             checkRefineDefault(node, defaultStr, line);
270             checkRefinePresence(node, presence, line);
271             checkRefineMinMax(name, line, min, max);
272         } else if (node instanceof ChoiceBuilder) {
273             checkRefinePresence(node, presence, line);
274             checkRefineMust(node, must, line);
275             checkRefineMinMax(name, line, min, max);
276         } else if (node instanceof ContainerSchemaNodeBuilder) {
277             checkRefineDefault(node, defaultStr, line);
278             checkRefineMandatory(node, mandatory, line);
279             checkRefineMust(node, must, line);
280             checkRefineMinMax(name, line, min, max);
281         } else if (node instanceof LeafSchemaNodeBuilder) {
282             checkRefinePresence(node, presence, line);
283             checkRefineMinMax(name, line, min, max);
284         } else if (node instanceof LeafListSchemaNodeBuilder || node instanceof ListSchemaNodeBuilder) {
285             checkRefineDefault(node, defaultStr, line);
286             checkRefinePresence(node, presence, line);
287             checkRefineMandatory(node, mandatory, line);
288         } else if (node instanceof GroupingBuilder || node instanceof TypeDefinitionBuilder
289                 || node instanceof UsesNodeBuilder) {
290             checkRefineDefault(node, defaultStr, line);
291             checkRefinePresence(node, presence, line);
292             checkRefineMandatory(node, mandatory, line);
293             checkRefineMust(node, must, line);
294             checkRefineMinMax(name, line, min, max);
295         }
296     }
297
298     private static void checkRefineDefault(SchemaNodeBuilder node, String defaultStr, int line) {
299         if (defaultStr != null) {
300             throw new YangParseException(line, "Can not refine 'default' for '" + node.getQName().getLocalName() + "'.");
301         }
302     }
303
304     private static void checkRefineMandatory(SchemaNodeBuilder node, Boolean mandatory, int line) {
305         if (mandatory != null) {
306             throw new YangParseException(line, "Can not refine 'mandatory' for '" + node.getQName().getLocalName()
307                     + "'.");
308         }
309     }
310
311     private static void checkRefinePresence(SchemaNodeBuilder node, Boolean presence, int line) {
312         if (presence != null) {
313             throw new YangParseException(line, "Can not refine 'presence' for '" + node.getQName().getLocalName()
314                     + "'.");
315         }
316     }
317
318     private static void checkRefineMust(SchemaNodeBuilder node, MustDefinition must, int line) {
319         if (must != null) {
320             throw new YangParseException(line, "Can not refine 'must' for '" + node.getQName().getLocalName() + "'.");
321         }
322     }
323
324     private static void checkRefineMinMax(String refineTargetName, int refineLine, Integer min, Integer max) {
325         if (min != null || max != null) {
326             throw new YangParseException(refineLine, "Can not refine 'min-elements' or 'max-elements' for '"
327                     + refineTargetName + "'.");
328         }
329     }
330
331     /**
332      * Perform refine operation of following parameters:
333      * <ul>
334      * <li>description</li>
335      * <li>reference</li>
336      * <li>config</li>
337      * </ul>
338      *
339      * These parameters may be refined for any node.
340      *
341      * @param node
342      *            node to refine
343      * @param refine
344      *            refine object containing information about refine process
345      * @param line
346      *            current line in yang model
347      */
348     public static void refineDefault(final Builder node, final RefineHolder refine, final int line) {
349         Class<? extends Builder> cls = node.getClass();
350
351         String description = refine.getDescription();
352         if (description != null) {
353             try {
354                 Method method = cls.getDeclaredMethod("setDescription", String.class);
355                 method.invoke(node, description);
356             } catch (Exception e) {
357                 throw new YangParseException(line, "Cannot refine description in " + cls.getName(), e);
358             }
359         }
360
361         String reference = refine.getReference();
362         if (reference != null) {
363             try {
364                 Method method = cls.getDeclaredMethod("setReference", String.class);
365                 method.invoke(node, reference);
366             } catch (Exception e) {
367                 throw new YangParseException(line, "Cannot refine reference in " + cls.getName(), e);
368             }
369         }
370
371         Boolean config = refine.isConfig();
372         if (config != null) {
373             try {
374                 Method method = cls.getDeclaredMethod("setConfiguration", Boolean.TYPE);
375                 method.invoke(node, config);
376             } catch (Exception e) {
377                 throw new YangParseException(line, "Cannot refine config in " + cls.getName(), e);
378             }
379         }
380     }
381
382     /**
383      * Perform refine operation on given node.
384      *
385      * @param nodeToRefine
386      *            builder of node to refine
387      * @param refine
388      *            refine object containing information about refine process
389      * @param line
390      *            current line in yang model
391      */
392     public static void performRefine(SchemaNodeBuilder nodeToRefine, RefineHolder refine, int line) {
393         checkRefine(nodeToRefine, refine);
394         refineDefault(nodeToRefine, refine, line);
395         if (nodeToRefine instanceof LeafSchemaNodeBuilder) {
396             refineLeaf((LeafSchemaNodeBuilder) nodeToRefine, refine, line);
397         } else if (nodeToRefine instanceof ContainerSchemaNodeBuilder) {
398             refineContainer((ContainerSchemaNodeBuilder) nodeToRefine, refine, line);
399         } else if (nodeToRefine instanceof ListSchemaNodeBuilder) {
400             refineList((ListSchemaNodeBuilder) nodeToRefine, refine, line);
401         } else if (nodeToRefine instanceof LeafListSchemaNodeBuilder) {
402             refineLeafList((LeafListSchemaNodeBuilder) nodeToRefine, refine, line);
403         } else if (nodeToRefine instanceof ChoiceBuilder) {
404             refineChoice((ChoiceBuilder) nodeToRefine, refine, line);
405         } else if (nodeToRefine instanceof AnyXmlBuilder) {
406             refineAnyxml((AnyXmlBuilder) nodeToRefine, refine, line);
407         }
408     }
409
410 }