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 «val path = m.moduleSourcePath»
102 «InputStream.importedName» stream = «CLASS».class.getResourceAsStream("«path»");
103 if (stream == null) {
104 throw new IllegalStateException("Resource «path» is missing");
108 } catch («IOException.importedName» e) {
109 // Resource leak, but there's nothing we can do
115 public «String.importedName» getName() {
120 public «String.importedName» getRevision() {
121 «val DateFormat df = new SimpleDateFormat("yyyy-MM-dd")»
122 return "«df.format(m.revision)»";
126 public «String.importedName» getNamespace() {
127 return "«m.namespace.toString»";
131 public «InputStream.importedName» getModuleSourceStream() throws IOException {
135 «InputStream.importedName» stream = «CLASS».class.getResourceAsStream("«path»");
136 if (stream == null) {
137 throw new «IOException.importedName»("Resource «path» is missing");
144 public «Set.importedName»<«YangModuleInfo.importedName»> getImportedModules() {
145 return importedModules;
149 private def imports() '''
150 «IF !importMap.empty»
151 «FOR entry : importMap.entrySet»
152 «IF entry.value != BindingGeneratorUtil.moduleNamespaceToPackageName(module)»
153 import «entry.value».«entry.key»;
160 final protected def importedName(Class<?> cls) {
161 val Type intype = Types.typeForClass(cls)
162 putTypeIntoImports(intype);
163 getExplicitType(intype)
166 final def void putTypeIntoImports(Type type) {
167 val String typeName = type.getName();
168 val String typePackageName = type.getPackageName();
169 if (typePackageName.startsWith("java.lang") || typePackageName.isEmpty()) {
172 if (!importMap.containsKey(typeName)) {
173 importMap.put(typeName, typePackageName);
175 if (type instanceof ParameterizedType) {
176 val ParameterizedType paramType = (type as ParameterizedType)
177 val Type[] params = paramType.getActualTypeArguments()
178 if (params != null) {
179 for (Type param : params) {
180 putTypeIntoImports(param);
186 final def String getExplicitType(Type type) {
187 val String typePackageName = type.getPackageName();
188 val String typeName = type.getName();
189 val String importedPackageName = importMap.get(typeName);
190 var StringBuilder builder;
191 if (typePackageName.equals(importedPackageName)) {
192 builder = new StringBuilder(type.getName());
193 addActualTypeParameters(builder, type);
194 if (builder.toString().equals("Void")) {
198 builder = new StringBuilder();
199 if (typePackageName.startsWith("java.lang")) {
200 builder.append(type.getName());
202 if (!typePackageName.isEmpty()) {
203 builder.append(typePackageName + Constants.DOT + type.getName());
205 builder.append(type.getName());
208 if (type.equals(Types.voidType())) {
211 addActualTypeParameters(builder, type);
213 return builder.toString();
216 final def StringBuilder addActualTypeParameters(StringBuilder builder, Type type) {
217 if (type instanceof ParameterizedType) {
218 val ParameterizedType pType = (type as ParameterizedType)
219 val Type[] pTypes = pType.getActualTypeArguments();
221 builder.append(getParameters(pTypes));
227 final def String getParameters(Type[] pTypes) {
228 if (pTypes == null || pTypes.length == 0) {
231 val StringBuilder builder = new StringBuilder();
234 for (pType : pTypes) {
235 val Type t = pTypes.get(i)
237 var String separator = ",";
238 if (i == (pTypes.length - 1)) {
242 var String wildcardParam = "";
243 if (t.equals(Types.voidType())) {
244 builder.append("java.lang.Void" + separator);
247 if (t instanceof WildcardType) {
248 wildcardParam = "? extends ";
251 builder.append(wildcardParam + getExplicitType(t) + separator);
255 return builder.toString();