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