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 «String.importedName» name = "«module.name»";
64 private final «String.importedName» namespace = "«module.namespace.toString»";
65 «val DateFormat df = new SimpleDateFormat("yyyy-MM-dd")»
66 private final «String.importedName» revision = "«df.format(module.revision)»";
67 private final «String.importedName» resourcePath = "«sourcePath»";
69 private final «Set.importedName»<YangModuleInfo> importedModules;
71 public static «YangModuleInfo.importedName» getInstance() {
79 package «packageName» ;
85 def String generateModelProvider() {
87 package «packageName»;
89 public final class «MODEL_BINDING_PROVIDER_CLASS_NAME» implements «YangModelBindingProvider.name» {
91 public «YangModuleInfo.name» getModuleInfo() {
92 return «MODULE_INFO_CLASS_NAME».getInstance();
99 private def CharSequence classBody(Module m) '''
100 private «MODULE_INFO_CLASS_NAME»() {
101 «IF m.imports.size != 0»
102 «Set.importedName»<«YangModuleInfo.importedName»> set = new «HashSet.importedName»<>();
103 «FOR imp : m.imports»
104 «val name = imp.moduleName»
105 «val rev = imp.revision»
107 «val Set<Module> modules = ctx.modules»
108 «val TreeMap<Date, Module> sorted = new TreeMap()»
109 «FOR module : modules»
110 «IF module.name.equals(name)»
111 «sorted.put(module.revision, module)»
114 set.add(«BindingGeneratorUtil.moduleNamespaceToPackageName(sorted.lastEntry().value)».«MODULE_INFO_CLASS_NAME».getInstance());
116 set.add(«BindingGeneratorUtil.moduleNamespaceToPackageName(ctx.findModuleByName(name, rev))».«MODULE_INFO_CLASS_NAME».getInstance());
119 importedModules = «ImmutableSet.importedName».copyOf(set);
121 importedModules = «Collections.importedName».emptySet();
123 «InputStream.importedName» stream = «MODULE_INFO_CLASS_NAME».class.getResourceAsStream(resourcePath);
124 if (stream == null) {
125 throw new IllegalStateException("Resource '" + resourcePath + "' is missing");
129 } catch («IOException.importedName» e) {
130 // Resource leak, but there is nothing we can do
135 public «String.importedName» getName() {
140 public «String.importedName» getRevision() {
145 public «String.importedName» getNamespace() {
150 public «InputStream.importedName» getModuleSourceStream() throws IOException {
151 «InputStream.importedName» stream = «MODULE_INFO_CLASS_NAME».class.getResourceAsStream(resourcePath);
152 if (stream == null) {
153 throw new «IOException.importedName»("Resource " + resourcePath + " is missing");
159 public «Set.importedName»<«YangModuleInfo.importedName»> getImportedModules() {
160 return importedModules;
164 public «String.importedName» toString() {
165 «StringBuilder.importedName» sb = new «StringBuilder.importedName»(this.getClass().getCanonicalName());
167 sb.append("name = " + name);
168 sb.append(", namespace = " + namespace);
169 sb.append(", revision = " + revision);
170 sb.append(", resourcePath = " + resourcePath);
171 sb.append(", imports = " + importedModules);
173 return sb.toString();
177 def getSourcePath() {
178 return "/" + module.moduleSourcePath.replace(java.io.File.separatorChar, '/')
181 private def imports() '''
182 «IF !importMap.empty»
183 «FOR entry : importMap.entrySet»
184 «IF entry.value != BindingGeneratorUtil.moduleNamespaceToPackageName(module)»
185 import «entry.value».«entry.key»;
191 final protected def importedName(Class<?> cls) {
192 val Type intype = Types.typeForClass(cls)
193 putTypeIntoImports(intype);
194 getExplicitType(intype)
197 final def void putTypeIntoImports(Type type) {
198 val String typeName = type.getName();
199 val String typePackageName = type.getPackageName();
200 if (typePackageName.startsWith("java.lang") || typePackageName.isEmpty()) {
203 if (!importMap.containsKey(typeName)) {
204 importMap.put(typeName, typePackageName);
206 if (type instanceof ParameterizedType) {
207 val ParameterizedType paramType = (type as ParameterizedType)
208 val Type[] params = paramType.getActualTypeArguments()
209 if (params != null) {
210 for (Type param : params) {
211 putTypeIntoImports(param);
217 final def String getExplicitType(Type type) {
218 val String typePackageName = type.getPackageName();
219 val String typeName = type.getName();
220 val String importedPackageName = importMap.get(typeName);
221 var StringBuilder builder;
222 if (typePackageName.equals(importedPackageName)) {
223 builder = new StringBuilder(type.getName());
224 addActualTypeParameters(builder, type);
225 if (builder.toString().equals("Void")) {
229 builder = new StringBuilder();
230 if (typePackageName.startsWith("java.lang")) {
231 builder.append(type.getName());
233 if (!typePackageName.isEmpty()) {
234 builder.append(typePackageName + Constants.DOT + type.getName());
236 builder.append(type.getName());
239 if (type.equals(Types.voidType())) {
242 addActualTypeParameters(builder, type);
244 return builder.toString();
247 final def StringBuilder addActualTypeParameters(StringBuilder builder, Type type) {
248 if (type instanceof ParameterizedType) {
249 val ParameterizedType pType = (type as ParameterizedType)
250 val Type[] pTypes = pType.getActualTypeArguments();
252 builder.append(getParameters(pTypes));
258 final def String getParameters(Type[] pTypes) {
259 if (pTypes == null || pTypes.length == 0) {
262 val StringBuilder builder = new StringBuilder();
265 for (pType : pTypes) {
266 val Type t = pTypes.get(i)
268 var String separator = ",";
269 if (i == (pTypes.length - 1)) {
273 var String wildcardParam = "";
274 if (t.equals(Types.voidType())) {
275 builder.append("java.lang.Void" + separator);
278 if (t instanceof WildcardType) {
279 wildcardParam = "? extends ";
282 builder.append(wildcardParam + getExplicitType(t) + separator);
286 return builder.toString();