Switch to Objects.requireNonNull
[mdsal.git] / binding2 / mdsal-binding2-generator-impl / src / main / java / org / opendaylight / mdsal / binding / javav2 / generator / impl / BindingGeneratorImpl.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 package org.opendaylight.mdsal.binding.javav2.generator.impl;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.annotations.Beta;
13 import com.google.common.base.Preconditions;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Set;
19 import org.opendaylight.mdsal.binding.javav2.generator.api.BindingGenerator;
20 import org.opendaylight.mdsal.binding.javav2.generator.context.ModuleContext;
21 import org.opendaylight.mdsal.binding.javav2.generator.spi.TypeProvider;
22 import org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeProviderImpl;
23 import org.opendaylight.mdsal.binding.javav2.model.api.Type;
24 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTypeBuilder;
25 import org.opendaylight.yangtools.yang.model.api.Module;
26 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
27 import org.opendaylight.yangtools.yang.model.util.ModuleDependencySort;
28
29 /**
30  * Main class for Binding generator v2. Provides transformation of Schema Context to
31  * generated transfer objects. Process is accompanied with Twirl templates to generate
32  * particular Javadoc for related YANG elements.
33  */
34 @Beta
35 public class BindingGeneratorImpl implements BindingGenerator {
36
37     /**
38      * When set to true, generated classes will include Javadoc comments
39      * which are useful for users.
40      */
41     private final boolean verboseClassComments;
42
43     /**
44      * Outer key represents the package name. Outer value represents map of all
45      * builders in the same package. Inner key represents the schema node name
46      * (in JAVA class/interface name format). Inner value represents instance of
47      * builder for schema node specified in key part.
48      */
49     //TODO: convert it to local variable eventually
50     private Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders = new HashMap<>();
51
52     private Map<Module, ModuleContext> genCtx = new HashMap<>();
53
54     /**
55      * Provide methods for converting YANG types to JAVA types.
56      */
57     private TypeProvider typeProvider;
58
59     /**
60      * Creates a new binding generator v2.
61      *
62      * @param verboseClassComments generate verbose comments
63      */
64     public BindingGeneratorImpl(final boolean verboseClassComments) {
65         this.verboseClassComments = verboseClassComments;
66     }
67
68     /**
69      * Resolves generated types from <code>context</code> schema nodes of all modules.
70      *
71      * <p>
72      * Generated types are created for modules, groupings, types, containers, lists, choices, augments, rpcs,
73      * notification, identities.
74      *
75      * @param context schema context which contains data about all schema nodes saved in modules
76      * @return list of types (usually <code>GeneratedType</code> <code>GeneratedTransferObject</code>which are generated
77      *         from <code>context</code> data.
78      * @throws IllegalArgumentException if arg <code>context</code> is null
79      * @throws IllegalStateException if <code>context</code> contain no modules
80      */
81     @Override
82     public List<Type> generateTypes(final SchemaContext context) {
83         Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL.");
84         Preconditions.checkState(context.getModules() != null, "Schema Context does not contain defined modules.");
85         final Set<Module> modules = context.getModules();
86         return generateTypes(context, modules);
87     }
88
89     /**
90      * Resolves generated types from <code>context</code> schema nodes only for
91      * modules specified in <code>modules</code>
92      *
93      * <p>
94      * Generated types are created for modules, groupings, types, containers,
95      * lists, choices, augments, rpcs, notification, identities.
96      *
97      * @param context
98      *            schema context which contains data about all schema nodes
99      *            saved in modules
100      * @param modules
101      *            set of modules for which schema nodes should be generated
102      *            types
103      * @return list of types (usually <code>GeneratedType</code> or
104      *         <code>GeneratedTransferObject</code>) which:
105      *         <ul>
106      *         <li>are generated from <code>context</code> schema nodes and</li>
107      *         <li>are also part of some of the module in <code>modules</code>
108      *         set.</li>
109      *         </ul>
110      * @throws IllegalArgumentException
111      *             <ul>
112      *             <li>if arg <code>context</code> is null or</li>
113      *             <li>if arg <code>modules</code> is null</li>
114      *             </ul>
115      * @throws IllegalStateException
116      *             if <code>context</code> contain no modules
117      */
118     @Override
119     public List<Type> generateTypes(final SchemaContext context, final Set<Module> modules) {
120         Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL.");
121         Preconditions.checkState(context.getModules() != null, "Schema Context does not contain defined modules.");
122         Preconditions.checkArgument(modules != null, "Set of Modules cannot be NULL.");
123
124         this.typeProvider = new TypeProviderImpl(context);
125         final List<Module> contextModules = ModuleDependencySort.sort(context.getModules());
126         this.genTypeBuilders = new HashMap<>();
127
128         for (final Module contextModule : contextModules) {
129             this.genCtx = ModuleToGenType.generate(contextModule, this.genTypeBuilders, context, this.typeProvider,
130                     this.genCtx, this.verboseClassComments);
131             this.genCtx.get(contextModule).cleanPackagesMap();
132         }
133         for (final Module contextModule : contextModules) {
134             this.genCtx = AugmentToGenType.generate(contextModule, context, this.typeProvider, this.genCtx,
135                     this.genTypeBuilders, this.verboseClassComments);
136             this.genCtx.get(contextModule).cleanPackagesMap();
137         }
138
139         final List<Type> filteredGenTypes = new ArrayList<>();
140         for (final Module m : modules) {
141             final ModuleContext ctx = requireNonNull(this.genCtx.get(m),
142                 () -> "Module context not found for module " + m);
143             filteredGenTypes.addAll(ctx.getGeneratedTypes());
144             final Set<Type> additionalTypes = ((TypeProviderImpl) this.typeProvider).getAdditionalTypes().get(m);
145             if (additionalTypes != null) {
146                 filteredGenTypes.addAll(additionalTypes);
147             }
148         }
149
150         return filteredGenTypes;
151     }
152
153     /**
154      * Return module contexts from generated types according to context.
155      *
156      * @param schemaContext
157      *            - for generating types
158      * @return module contexts
159      */
160     public Map<Module, ModuleContext> getModuleContexts(final SchemaContext schemaContext) {
161         generateTypes(schemaContext);
162         return this.genCtx;
163     }
164 }