2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.sal.java.api.generator
10 import java.io.InputStream
11 import java.io.IOException
12 import java.text.DateFormat
13 import java.text.SimpleDateFormat
15 import java.util.Collections
17 import java.util.HashSet
18 import java.util.LinkedHashMap
21 import java.util.TreeMap
23 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
24 import org.opendaylight.yangtools.binding.generator.util.Types
25 import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType
26 import org.opendaylight.yangtools.sal.binding.model.api.Type
27 import org.opendaylight.yangtools.sal.binding.model.api.WildcardType
28 import org.opendaylight.yangtools.yang.binding.YangModuleInfo
29 import org.opendaylight.yangtools.yang.model.api.Module
30 import org.opendaylight.yangtools.yang.model.api.SchemaContext
32 import com.google.common.collect.ImmutableSet
33 import static org.opendaylight.yangtools.yang.binding.BindingMapping.*
34 import org.opendaylight.yangtools.yang.binding.YangModelBindingProvider
35 import com.google.common.base.Preconditions
37 class YangModuleInfoTemplate {
41 val Map<String, String> importMap = new LinkedHashMap()
44 val String packageName;
47 val String modelBindingProviderName;
49 new(Module module, SchemaContext ctx) {
50 Preconditions.checkArgument(module != null, "Module must not be null.");
53 _packageName = BindingGeneratorUtil.moduleNamespaceToPackageName(module);
54 _modelBindingProviderName = '''«packageName».«MODEL_BINDING_PROVIDER_CLASS_NAME»''';
57 def String generate() {
59 public final class «MODULE_INFO_CLASS_NAME» implements «YangModuleInfo.importedName» {
61 private static final «YangModuleInfo.importedName» INSTANCE = new «MODULE_INFO_CLASS_NAME»();
63 private final Set<YangModuleInfo> importedModules;
65 public static «YangModuleInfo.importedName» getInstance() {
74 package «packageName» ;
80 def String generateModelProvider() {
82 package «packageName»;
84 public final class «MODEL_BINDING_PROVIDER_CLASS_NAME» implements «YangModelBindingProvider.name» {
86 public «YangModuleInfo.name» getModuleInfo() {
87 return «MODULE_INFO_CLASS_NAME».getInstance();
94 private def CharSequence classBody(Module m) '''
95 private «MODULE_INFO_CLASS_NAME»() {
96 «IF m.imports.size != 0»
97 «Set.importedName»<«YangModuleInfo.importedName»> set = new «HashSet.importedName»<>();
99 «val name = imp.moduleName»
100 «val rev = imp.revision»
102 «val Set<Module> modules = ctx.modules»
103 «val TreeMap<Date, Module> sorted = new TreeMap()»
104 «FOR module : modules»
105 «IF module.name.equals(name)»
106 «sorted.put(module.revision, module)»
109 set.add(«BindingGeneratorUtil.moduleNamespaceToPackageName(sorted.lastEntry().value)».«MODULE_INFO_CLASS_NAME».getInstance());
111 set.add(«BindingGeneratorUtil.moduleNamespaceToPackageName(ctx.findModuleByName(name, rev))».«MODULE_INFO_CLASS_NAME».getInstance());
114 importedModules = «ImmutableSet.importedName».copyOf(set);
116 importedModules = «Collections.importedName».emptySet();
118 «InputStream.importedName» stream = «MODULE_INFO_CLASS_NAME».class.getResourceAsStream("«sourcePath»");
119 if (stream == null) {
120 throw new IllegalStateException("Resource «sourcePath» is missing");
124 } catch («IOException.importedName» e) {
125 // Resource leak, but there is nothing we can do
130 public «String.importedName» getName() {
135 public «String.importedName» getRevision() {
136 «val DateFormat df = new SimpleDateFormat("yyyy-MM-dd")»
137 return "«df.format(m.revision)»";
141 public «String.importedName» getNamespace() {
142 return "«m.namespace.toString»";
146 public «InputStream.importedName» getModuleSourceStream() throws IOException {
147 «InputStream.importedName» stream = «MODULE_INFO_CLASS_NAME».class.getResourceAsStream("«sourcePath»");
148 if (stream == null) {
149 throw new «IOException.importedName»("Resource «sourcePath» is missing");
155 public «Set.importedName»<«YangModuleInfo.importedName»> getImportedModules() {
156 return importedModules;
160 def getSourcePath() {
161 return "/" + module.moduleSourcePath.replace(java.io.File.separatorChar, '/')
164 private def imports() '''
165 «IF !importMap.empty»
166 «FOR entry : importMap.entrySet»
167 «IF entry.value != BindingGeneratorUtil.moduleNamespaceToPackageName(module)»
168 import «entry.value».«entry.key»;
174 final protected def importedName(Class<?> cls) {
175 val Type intype = Types.typeForClass(cls)
176 putTypeIntoImports(intype);
177 getExplicitType(intype)
180 final def void putTypeIntoImports(Type type) {
181 val String typeName = type.getName();
182 val String typePackageName = type.getPackageName();
183 if (typePackageName.startsWith("java.lang") || typePackageName.isEmpty()) {
186 if (!importMap.containsKey(typeName)) {
187 importMap.put(typeName, typePackageName);
189 if (type instanceof ParameterizedType) {
190 val ParameterizedType paramType = (type as ParameterizedType)
191 val Type[] params = paramType.getActualTypeArguments()
192 if (params != null) {
193 for (Type param : params) {
194 putTypeIntoImports(param);
200 final def String getExplicitType(Type type) {
201 val String typePackageName = type.getPackageName();
202 val String typeName = type.getName();
203 val String importedPackageName = importMap.get(typeName);
204 var StringBuilder builder;
205 if (typePackageName.equals(importedPackageName)) {
206 builder = new StringBuilder(type.getName());
207 addActualTypeParameters(builder, type);
208 if (builder.toString().equals("Void")) {
212 builder = new StringBuilder();
213 if (typePackageName.startsWith("java.lang")) {
214 builder.append(type.getName());
216 if (!typePackageName.isEmpty()) {
217 builder.append(typePackageName + Constants.DOT + type.getName());
219 builder.append(type.getName());
222 if (type.equals(Types.voidType())) {
225 addActualTypeParameters(builder, type);
227 return builder.toString();
230 final def StringBuilder addActualTypeParameters(StringBuilder builder, Type type) {
231 if (type instanceof ParameterizedType) {
232 val ParameterizedType pType = (type as ParameterizedType)
233 val Type[] pTypes = pType.getActualTypeArguments();
235 builder.append(getParameters(pTypes));
241 final def String getParameters(Type[] pTypes) {
242 if (pTypes == null || pTypes.length == 0) {
245 val StringBuilder builder = new StringBuilder();
248 for (pType : pTypes) {
249 val Type t = pTypes.get(i)
251 var String separator = ",";
252 if (i == (pTypes.length - 1)) {
256 var String wildcardParam = "";
257 if (t.equals(Types.voidType())) {
258 builder.append("java.lang.Void" + separator);
261 if (t instanceof WildcardType) {
262 wildcardParam = "? extends ";
265 builder.append(wildcardParam + getExplicitType(t) + separator);
269 return builder.toString();