Bug 1411 #5 BindingGeneratorImpl decomposition - Notifications
[mdsal.git] / binding2 / mdsal-binding2-generator-impl / src / main / java / org / opendaylight / mdsal / binding / javav2 / generator / impl / ModuleToGenType.java
1 /*
2  * Copyright (c) 2017 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
9 package org.opendaylight.mdsal.binding.javav2.generator.impl;
10
11 import static com.google.common.base.Preconditions.checkArgument;
12 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.createDescription;
13 import static org.opendaylight.mdsal.binding.javav2.generator.impl.GenHelperUtil.moduleTypeBuilder;
14 import static org.opendaylight.mdsal.binding.javav2.generator.impl.GenHelperUtil.resolveNotification;
15 import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.NOTIFICATION_LISTENER;
16
17 import com.google.common.annotations.Beta;
18 import com.google.common.base.Preconditions;
19 import java.util.Collection;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Set;
23 import org.opendaylight.mdsal.binding.javav2.generator.spi.TypeProvider;
24 import org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeProviderImpl;
25 import org.opendaylight.mdsal.binding.javav2.model.api.Type;
26 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTypeBuilder;
27 import org.opendaylight.mdsal.binding.javav2.util.BindingMapping;
28 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
29 import org.opendaylight.yangtools.yang.model.api.Module;
30 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
31 import org.opendaylight.yangtools.yang.model.api.NotificationNodeContainer;
32 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
33 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
34 import org.opendaylight.yangtools.yang.model.util.DataNodeIterator;
35
36 @Beta
37 final class ModuleToGenType {
38
39     private ModuleToGenType() {
40         throw new UnsupportedOperationException("Utility class");
41     }
42
43     static Map<Module, ModuleContext> generate(final Module module, Map<String, Map<String, GeneratedTypeBuilder>>
44             genTypeBuilders, final SchemaContext schemaContext, TypeProvider typeProvider, Map<Module,
45             ModuleContext> genCtx, final boolean verboseClassComments) {
46
47         genCtx.put(module, new ModuleContext());
48         genCtx = allTypeDefinitionsToGenTypes(module, genCtx, typeProvider);
49         genCtx = notificationsToGenType(module, genCtx, schemaContext, genTypeBuilders, verboseClassComments, typeProvider);
50
51         //TODO: call generate for other entities (groupings, rpcs, actions, identities)
52
53         if (!module.getChildNodes().isEmpty()) {
54             final GeneratedTypeBuilder moduleType = GenHelperUtil.moduleToDataType(module, genCtx, verboseClassComments);
55             genCtx.get(module).addModuleNode(moduleType);
56             final String basePackageName = BindingMapping.getRootPackageName(module);
57             GenHelperUtil.resolveDataSchemaNodes(module, basePackageName, moduleType, moduleType, module
58                     .getChildNodes(), genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider);
59         }
60
61         return genCtx;
62     }
63
64     /**
65      * Converts all extended type definitions of module to the list of
66      * <code>Type</code> objects.
67      *
68      * @param module
69      *            module from which is obtained set of type definitions
70      * @throws IllegalArgumentException
71      *             <ul>
72      *             <li>if module is null</li>
73      *             <li>if name of module is null</li>
74      *             </ul>
75      * @throws IllegalStateException
76      *             if set of type definitions from module is null
77      */
78     private static Map<Module, ModuleContext> allTypeDefinitionsToGenTypes(final Module module, Map<Module, ModuleContext> genCtx,
79             TypeProvider typeProvider) {
80         Preconditions.checkArgument(module != null, "Module reference cannot be NULL.");
81         Preconditions.checkArgument(module.getName() != null, "Module name cannot be NULL.");
82         final DataNodeIterator it = new DataNodeIterator(module);
83         final List<TypeDefinition<?>> typeDefinitions = it.allTypedefs();
84         Preconditions.checkState(typeDefinitions != null, "Type Definitions for module «module.name» cannot be NULL.");
85
86         typeDefinitions.stream().filter(typedef -> typedef != null).forEach(typedef -> {
87             final Type type = ((TypeProviderImpl) typeProvider).generatedTypeForExtendedDefinitionType(typedef,
88                     typedef);
89             if (type != null) {
90                 final ModuleContext ctx = genCtx.get(module);
91                 ctx.addTypedefType(typedef.getPath(), type);
92                 ctx.addTypeToSchema(type, typedef);
93             }
94         });
95         return genCtx;
96     }
97
98     /**
99      * Converts all <b>notifications</b> of the module to the list of
100      * <code>Type</code> objects. In addition are to this list added containers
101      * and lists which are part of this notification.
102      *
103      * @param module
104      *            module from which is obtained set of all notification objects
105      *            to iterate over them
106      * @throws IllegalArgumentException
107      *             <ul>
108      *             <li>if the module equals null</li>
109      *             <li>if the name of module equals null</li>
110      *             </ul>
111      * @throws IllegalStateException
112      *             if set of notifications from module is null
113      */
114     private static Map<Module, ModuleContext> notificationsToGenType(final Module module, Map<Module, ModuleContext> genCtx,
115             final SchemaContext schemaContext, Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders,
116             final boolean verboseClassComments, TypeProvider typeProvider) {
117         checkArgument(module != null, "Module reference cannot be NULL.");
118         checkArgument(module.getName() != null, "Module name cannot be NULL.");
119         final Set<NotificationDefinition> notifications = module.getNotifications();
120         if (notifications.isEmpty()) {
121             return genCtx;
122         }
123
124         final GeneratedTypeBuilder listenerInterface = moduleTypeBuilder(module, "Listener", verboseClassComments);
125         listenerInterface.addImplementsType(NOTIFICATION_LISTENER);
126         final String basePackageName = BindingMapping.getRootPackageName(module);
127
128         for (final NotificationDefinition notification : notifications) {
129             if (notification != null) {
130                 resolveNotification(listenerInterface, null, basePackageName, notification, module, schemaContext,
131                         verboseClassComments, genTypeBuilders, typeProvider, genCtx);
132             }
133         }
134
135         //YANG 1.1 allows notifications be tied to containers and lists
136         final Collection<DataSchemaNode> potentials = module.getChildNodes();
137
138         for (final DataSchemaNode potential : potentials) {
139             if (potential instanceof NotificationNodeContainer) {
140                 final Set<NotificationDefinition> tiedNotifications = ((NotificationNodeContainer) potential)
141                         .getNotifications();
142                 for (final NotificationDefinition tiedNotification: tiedNotifications) {
143                     if (tiedNotification != null) {
144                         resolveNotification(listenerInterface, potential.getQName().getLocalName(), basePackageName,
145                                 tiedNotification, module, schemaContext, verboseClassComments, genTypeBuilders,
146                                 typeProvider, genCtx);
147                         notifications.add(tiedNotification);
148                     }
149                 }
150             }
151         }
152
153         listenerInterface.setDescription(createDescription(notifications, module.getName(), verboseClassComments));
154
155         genCtx.get(module).addTopLevelNodeType(listenerInterface);
156
157         return genCtx;
158     }
159 }