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
34 class YangModuleInfoTemplate {
35 val CLASS = "$YangModuleInfoImpl"
39 val Map<String, String> importMap = new LinkedHashMap()
41 new (Module module, SchemaContext ctx) {
43 throw new IllegalArgumentException("Module reference cannot be NULL!")
49 def String generate() {
50 val String classBody = body().toString
52 package «BindingGeneratorUtil.moduleNamespaceToPackageName(module)» ;
61 public final class «CLASS» implements «YangModuleInfo.importedName» {
63 private static final «YangModuleInfo.importedName» INSTANCE = new «CLASS»();
65 private final Set<YangModuleInfo> importedModules;
67 public static «YangModuleInfo.importedName» getInstance() {
75 private def CharSequence classBody(Module m) '''
77 «IF m.imports.size != 0»
78 «Set.importedName»<«YangModuleInfo.importedName»> set = new «HashSet.importedName»<>();
80 «val name = imp.moduleName»
81 «val rev = imp.revision»
83 «val Set<Module> modules = ctx.modules»
84 «val TreeMap<Date, Module> sorted = new TreeMap()»
85 «FOR module : modules»
86 «IF module.name.equals(name)»
87 «sorted.put(module.revision, module)»
90 set.add(«BindingGeneratorUtil.moduleNamespaceToPackageName(sorted.lastEntry().value)».«CLASS».getInstance());
92 set.add(«BindingGeneratorUtil.moduleNamespaceToPackageName(ctx.findModuleByName(name, rev))».«CLASS».getInstance());
95 importedModules = «ImmutableSet.importedName».copyOf(set);
97 importedModules = «Collections.importedName».emptySet();
100 «InputStream.importedName» stream = «CLASS».class.getResourceAsStream("«sourcePath»");
101 if (stream == null) {
102 throw new IllegalStateException("Resource «sourcePath» is missing");
106 } catch («IOException.importedName» e) {
107 // Resource leak, but there is nothing we can do
112 public «String.importedName» getName() {
117 public «String.importedName» getRevision() {
118 «val DateFormat df = new SimpleDateFormat("yyyy-MM-dd")»
119 return "«df.format(m.revision)»";
123 public «String.importedName» getNamespace() {
124 return "«m.namespace.toString»";
128 public «InputStream.importedName» getModuleSourceStream() throws IOException {
129 «InputStream.importedName» stream = «CLASS».class.getResourceAsStream("«sourcePath»");
130 if (stream == null) {
131 throw new «IOException.importedName»("Resource «sourcePath» is missing");
137 public «Set.importedName»<«YangModuleInfo.importedName»> getImportedModules() {
138 return importedModules;
142 def getSourcePath() {
143 return "/" + module.moduleSourcePath.replace(java.io.File.separatorChar, '/')
146 private def imports() '''
147 «IF !importMap.empty»
148 «FOR entry : importMap.entrySet»
149 «IF entry.value != BindingGeneratorUtil.moduleNamespaceToPackageName(module)»
150 import «entry.value».«entry.key»;
157 final protected def importedName(Class<?> cls) {
158 val Type intype = Types.typeForClass(cls)
159 putTypeIntoImports(intype);
160 getExplicitType(intype)
163 final def void putTypeIntoImports(Type type) {
164 val String typeName = type.getName();
165 val String typePackageName = type.getPackageName();
166 if (typePackageName.startsWith("java.lang") || typePackageName.isEmpty()) {
169 if (!importMap.containsKey(typeName)) {
170 importMap.put(typeName, typePackageName);
172 if (type instanceof ParameterizedType) {
173 val ParameterizedType paramType = (type as ParameterizedType)
174 val Type[] params = paramType.getActualTypeArguments()
175 if (params != null) {
176 for (Type param : params) {
177 putTypeIntoImports(param);
183 final def String getExplicitType(Type type) {
184 val String typePackageName = type.getPackageName();
185 val String typeName = type.getName();
186 val String importedPackageName = importMap.get(typeName);
187 var StringBuilder builder;
188 if (typePackageName.equals(importedPackageName)) {
189 builder = new StringBuilder(type.getName());
190 addActualTypeParameters(builder, type);
191 if (builder.toString().equals("Void")) {
195 builder = new StringBuilder();
196 if (typePackageName.startsWith("java.lang")) {
197 builder.append(type.getName());
199 if (!typePackageName.isEmpty()) {
200 builder.append(typePackageName + Constants.DOT + type.getName());
202 builder.append(type.getName());
205 if (type.equals(Types.voidType())) {
208 addActualTypeParameters(builder, type);
210 return builder.toString();
213 final def StringBuilder addActualTypeParameters(StringBuilder builder, Type type) {
214 if (type instanceof ParameterizedType) {
215 val ParameterizedType pType = (type as ParameterizedType)
216 val Type[] pTypes = pType.getActualTypeArguments();
218 builder.append(getParameters(pTypes));
224 final def String getParameters(Type[] pTypes) {
225 if (pTypes == null || pTypes.length == 0) {
228 val StringBuilder builder = new StringBuilder();
231 for (pType : pTypes) {
232 val Type t = pTypes.get(i)
234 var String separator = ",";
235 if (i == (pTypes.length - 1)) {
239 var String wildcardParam = "";
240 if (t.equals(Types.voidType())) {
241 builder.append("java.lang.Void" + separator);
244 if (t instanceof WildcardType) {
245 wildcardParam = "? extends ";
248 builder.append(wildcardParam + getExplicitType(t) + separator);
252 return builder.toString();