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