Correct docs declaration
[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.GenHelperUtil.groupingsToGenTypes;
13 import static org.opendaylight.mdsal.binding.javav2.generator.impl.GenHelperUtil.moduleTypeBuilder;
14 import static org.opendaylight.mdsal.binding.javav2.generator.impl.GenHelperUtil.processUsesImplements;
15 import static org.opendaylight.mdsal.binding.javav2.generator.impl.GenHelperUtil.resolveNotification;
16 import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.NOTIFICATION_LISTENER;
17
18 import com.google.common.annotations.Beta;
19 import com.google.common.base.Preconditions;
20 import com.google.common.collect.ImmutableSet;
21
22 import java.util.Collection;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Objects;
26 import java.util.Set;
27
28 import org.opendaylight.mdsal.binding.javav2.generator.context.ModuleContext;
29 import org.opendaylight.mdsal.binding.javav2.generator.spi.TypeProvider;
30 import org.opendaylight.mdsal.binding.javav2.generator.util.TypeComments;
31 import org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeProviderImpl;
32 import org.opendaylight.mdsal.binding.javav2.model.api.Type;
33 import org.opendaylight.mdsal.binding.javav2.model.api.YangSourceDefinition;
34 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTypeBuilder;
35 import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingNamespaceType;
36 import org.opendaylight.mdsal.binding.javav2.util.BindingMapping;
37 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
38 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
39 import org.opendaylight.yangtools.yang.model.api.Module;
40 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
41 import org.opendaylight.yangtools.yang.model.api.NotificationNodeContainer;
42 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
43 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
44 import org.opendaylight.yangtools.yang.model.util.DataNodeIterator;
45
46 @Beta
47 final class ModuleToGenType {
48
49     private ModuleToGenType() {
50         throw new UnsupportedOperationException("Utility class");
51     }
52
53     static Map<Module, ModuleContext> generate(final Module module, final Map<String, Map<String, GeneratedTypeBuilder>>
54             genTypeBuilders, final SchemaContext schemaContext, final TypeProvider typeProvider, Map<Module,
55             ModuleContext> genCtx, final boolean verboseClassComments) {
56
57         genCtx.put(module, new ModuleContext());
58         genCtx = allTypeDefinitionsToGenTypes(module, genCtx, typeProvider);
59         genCtx = groupingsToGenTypes(module, module.getGroupings(), genCtx, schemaContext, verboseClassComments,
60                 genTypeBuilders, typeProvider);
61         genCtx = allIdentitiesToGenTypes(module, schemaContext, genCtx, verboseClassComments, genTypeBuilders,
62                 typeProvider);
63
64         if (!module.getChildNodes().isEmpty()) {
65             final GeneratedTypeBuilder moduleType = GenHelperUtil.moduleToDataType(module, genCtx,
66                     verboseClassComments);
67             genCtx.get(module).addModuleNode(moduleType);
68             final String basePackageName = BindingMapping.getRootPackageName(module);
69             GenHelperUtil.resolveDataSchemaNodes(module, basePackageName, moduleType, moduleType, module
70                             .getChildNodes(), genCtx, schemaContext, verboseClassComments, genTypeBuilders,
71                     typeProvider,
72                     BindingNamespaceType.Data);
73             processUsesImplements(module, module, schemaContext, genCtx, BindingNamespaceType.Data);
74         }
75
76         genCtx = notificationsToGenType(module, genCtx, schemaContext, genTypeBuilders, verboseClassComments,
77                 typeProvider);
78
79         //after potential parent data schema nodes
80         genCtx = actionsAndRPCMethodsToGenType(module, genCtx, schemaContext, verboseClassComments,
81                 genTypeBuilders, typeProvider);
82
83         return genCtx;
84     }
85
86     /**
87      * Converts all extended type definitions of module to the list of
88      * <code>Type</code> objects.
89      *
90      * @param module module from which is obtained set of type definitions
91      * @throws IllegalArgumentException <ul>
92      *                                  <li>if module is null</li>
93      *                                  <li>if name of module is null</li>
94      *                                  </ul>
95      * @throws IllegalStateException    if set of type definitions from module is null
96      */
97     private static Map<Module, ModuleContext> allTypeDefinitionsToGenTypes(final Module module, final Map<Module,
98             ModuleContext> genCtx,
99                                                                            final TypeProvider typeProvider) {
100         Preconditions.checkArgument(module != null, "Module reference cannot be NULL.");
101         Preconditions.checkArgument(module.getName() != null, "Module name cannot be NULL.");
102         final DataNodeIterator it = new DataNodeIterator(module);
103         final List<TypeDefinition<?>> typeDefinitions = it.allTypedefs();
104         Preconditions.checkState(typeDefinitions != null, "Type Definitions for module «module.name» cannot be NULL.");
105
106         typeDefinitions.stream().filter(Objects::nonNull).forEach(typedef -> {
107             final Type type = ((TypeProviderImpl) typeProvider).generatedTypeForExtendedDefinitionType(typedef,
108                     typedef);
109             if (type != null) {
110                 final ModuleContext ctx = genCtx.get(module);
111                 ctx.addTypedefType(typedef.getPath(), type);
112                 ctx.addTypeToSchema(type, typedef);
113             }
114         });
115         return genCtx;
116     }
117
118     private static Map<Module, ModuleContext> actionsAndRPCMethodsToGenType(final Module module, Map<Module,
119             ModuleContext> genCtx, final SchemaContext schemaContext, final boolean verboseClassComments,
120                                                                             final Map<String, Map<String,
121                                                                                     GeneratedTypeBuilder>>
122                                                                                     genTypeBuilders, final
123                                                                             TypeProvider typeProvider) {
124
125         genCtx = RpcActionGenHelper.rpcMethodsToGenType(module, genCtx, schemaContext, verboseClassComments,
126                 genTypeBuilders, typeProvider);
127         genCtx = RpcActionGenHelper.actionMethodsToGenType(module, genCtx, schemaContext, verboseClassComments,
128                 genTypeBuilders, typeProvider);
129
130         return genCtx;
131     }
132
133     /**
134      * Converts all <b>identities</b> of the module to the list of
135      * <code>Type</code> objects.
136      *
137      * @param module        module from which is obtained set of all identity objects to
138      *                      iterate over them
139      * @param schemaContext schema context only used as input parameter for method
140      *      {@link GenHelperUtil#identityToGenType(Module, String, IdentitySchemaNode, SchemaContext,Map, boolean)}
141      * @param genCtx        generated context
142      * @return returns generated context
143      */
144     private static Map<Module, ModuleContext> allIdentitiesToGenTypes(final Module module,
145                                                                       final SchemaContext schemaContext, Map<Module,
146             ModuleContext> genCtx, boolean verboseClassComments,
147                                                                       final Map<String, Map<String,
148                                                                               GeneratedTypeBuilder>> genTypeBuilders,
149                                                                       final TypeProvider typeProvider) {
150
151         final Set<IdentitySchemaNode> schemaIdentities = module.getIdentities();
152         final String basePackageName = BindingMapping.getRootPackageName(module);
153
154         if (schemaIdentities != null && !schemaIdentities.isEmpty()) {
155             for (final IdentitySchemaNode identity : schemaIdentities) {
156                 GenHelperUtil.identityToGenType(module, basePackageName, identity, schemaContext, genCtx,
157                         verboseClassComments);
158             }
159         }
160
161         return genCtx;
162     }
163
164     /**
165      * Converts all <b>notifications</b> of the module to the list of
166      * <code>Type</code> objects. In addition are to this list added containers
167      * and lists which are part of this notification.
168      *
169      * @param module module from which is obtained set of all notification objects
170      *               to iterate over them
171      * @throws IllegalArgumentException <ul>
172      *                                  <li>if the module equals null</li>
173      *                                  <li>if the name of module equals null</li>
174      *                                  </ul>
175      * @throws IllegalStateException    if set of notifications from module is null
176      */
177     private static Map<Module, ModuleContext> notificationsToGenType(final Module module, final Map<Module,
178             ModuleContext> genCtx,
179                                                                      final SchemaContext schemaContext, final
180                                                                      Map<String, Map<String, GeneratedTypeBuilder>>
181                                                                              genTypeBuilders,
182                                                                      final boolean verboseClassComments, final
183                                                                      TypeProvider typeProvider) {
184         checkArgument(module != null, "Module reference cannot be NULL.");
185         checkArgument(module.getName() != null, "Module name cannot be NULL.");
186         final Set<NotificationDefinition> notifications = module.getNotifications();
187         if (notifications.isEmpty()) {
188             return genCtx;
189         }
190
191         final GeneratedTypeBuilder listenerInterface = moduleTypeBuilder(module, "Listener", verboseClassComments,
192                 genCtx.get(module));
193         listenerInterface.addImplementsType(NOTIFICATION_LISTENER);
194         final String basePackageName = BindingMapping.getRootPackageName(module);
195
196         for (final NotificationDefinition notification : notifications) {
197             if (notification != null) {
198                 resolveNotification(listenerInterface, null, basePackageName, notification, module, schemaContext,
199                         verboseClassComments, genTypeBuilders, typeProvider, genCtx);
200                 processUsesImplements(notification, module, schemaContext, genCtx, BindingNamespaceType.Notification);
201             }
202         }
203
204         //YANG 1.1 allows notifications be tied to containers and lists
205         final Collection<DataSchemaNode> potentials = module.getChildNodes();
206         Set<NotificationDefinition> tiedNotifications = null;
207
208         for (final DataSchemaNode potential : potentials) {
209             if (potential instanceof NotificationNodeContainer) {
210                 tiedNotifications = ((NotificationNodeContainer) potential)
211                         .getNotifications();
212                 for (final NotificationDefinition tiedNotification : tiedNotifications) {
213                     if (tiedNotification != null) {
214                         resolveNotification(listenerInterface, potential.getQName().getLocalName(), basePackageName,
215                                 tiedNotification, module, schemaContext, verboseClassComments, genTypeBuilders,
216                                 typeProvider, genCtx);
217                         processUsesImplements(tiedNotification, module, schemaContext, genCtx, BindingNamespaceType
218                                 .Notification);
219                     }
220                 }
221             }
222         }
223
224         if (verboseClassComments) {
225             if (tiedNotifications != null) {
226                 YangSourceDefinition.of(module,
227                         ImmutableSet.<NotificationDefinition>builder().addAll(notifications).addAll(tiedNotifications)
228                                 .build()).ifPresent(listenerInterface::setYangSourceDefinition);
229             } else {
230                 YangSourceDefinition.of(module, notifications).ifPresent(listenerInterface::setYangSourceDefinition);
231             }
232             listenerInterface.addComment(TypeComments.javadoc(
233                     "Interface for receiving the following YANG notifications defined in module <b>" + module.getName()
234                             + "</b>").get());
235         }
236
237         genCtx.get(module).addTopLevelNodeType(listenerInterface);
238
239         return genCtx;
240     }
241 }