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 org.opendaylight.yangtools.yang.model.api.Module
11 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
12 import org.opendaylight.yangtools.yang.binding.YangModuleInfo
13 import java.io.InputStream
14 import com.google.common.collect.ImmutableSet
16 import java.util.LinkedHashMap
17 import org.opendaylight.yangtools.binding.generator.util.Types
18 import org.opendaylight.yangtools.sal.binding.model.api.Type
19 import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType
20 import org.opendaylight.yangtools.sal.binding.model.api.WildcardType
21 import java.io.IOException
23 import java.util.HashSet
24 import org.opendaylight.yangtools.yang.model.api.SchemaContext
26 import java.util.TreeMap
27 import java.text.DateFormat
28 import java.text.SimpleDateFormat
30 class YangModuleInfoTemplate {
31 val CLASS = "$YangModuleInfoImpl"
35 val Map<String, String> importMap = new LinkedHashMap()
37 new (Module module, SchemaContext ctx) {
39 throw new IllegalArgumentException("Module reference cannot be NULL!")
45 def String generate() {
46 val String classBody = body().toString
48 package «BindingGeneratorUtil.moduleNamespaceToPackageName(module)» ;
57 public class «CLASS» implements «YangModuleInfo.importedName» {
59 private static final «YangModuleInfo.importedName» INSTANCE = new «CLASS»();
63 public static «YangModuleInfo.importedName» getInstance() {
72 private def CharSequence classBody(Module m) '''
74 public «String.importedName» getName() {
79 public «String.importedName» getRevision() {
80 «val DateFormat df = new SimpleDateFormat("yyyy-MM-dd")»
81 return "«df.format(m.revision)»";
85 public «String.importedName» getNamespace() {
86 return "«m.namespace.toString»";
90 public «InputStream.importedName» getModuleSourceStream() throws «IOException.importedName» {
91 «val path = m.moduleSourcePath»
95 return «CLASS».class.getResourceAsStream("«path»");
100 public «ImmutableSet.importedName»<«YangModuleInfo.importedName»> getImportedModules() {
101 «Set.importedName»<«YangModuleInfo.importedName»> set = new «HashSet.importedName»<>();
102 «FOR imp : m.imports»
103 «val name = imp.moduleName»
104 «val rev = imp.revision»
106 «val Set<Module> modules = ctx.modules»
107 «val TreeMap<Date, Module> sorted = new TreeMap()»
108 «FOR module : modules»
109 «IF module.name.equals(name)»
110 «sorted.put(module.revision, module)»
113 set.add(«BindingGeneratorUtil.moduleNamespaceToPackageName(sorted.lastEntry().value)».«CLASS».getInstance());
115 set.add(«BindingGeneratorUtil.moduleNamespaceToPackageName(ctx.findModuleByName(name, rev))».«CLASS».getInstance());
118 return «ImmutableSet.importedName».copyOf(set);
122 private def imports() '''
123 «IF !importMap.empty»
124 «FOR entry : importMap.entrySet»
125 «IF entry.value != BindingGeneratorUtil.moduleNamespaceToPackageName(module)»
126 import «entry.value».«entry.key»;
133 final protected def importedName(Class<?> cls) {
134 val Type intype = Types.typeForClass(cls)
135 putTypeIntoImports(intype);
136 getExplicitType(intype)
139 final def void putTypeIntoImports(Type type) {
140 val String typeName = type.getName();
141 val String typePackageName = type.getPackageName();
142 if (typePackageName.startsWith("java.lang") || typePackageName.isEmpty()) {
145 if (!importMap.containsKey(typeName)) {
146 importMap.put(typeName, typePackageName);
148 if (type instanceof ParameterizedType) {
149 val ParameterizedType paramType = (type as ParameterizedType)
150 val Type[] params = paramType.getActualTypeArguments()
151 if (params != null) {
152 for (Type param : params) {
153 putTypeIntoImports(param);
159 final def String getExplicitType(Type type) {
160 val String typePackageName = type.getPackageName();
161 val String typeName = type.getName();
162 val String importedPackageName = importMap.get(typeName);
163 var StringBuilder builder;
164 if (typePackageName.equals(importedPackageName)) {
165 builder = new StringBuilder(type.getName());
166 addActualTypeParameters(builder, type);
167 if (builder.toString().equals("Void")) {
171 builder = new StringBuilder();
172 if (typePackageName.startsWith("java.lang")) {
173 builder.append(type.getName());
175 if (!typePackageName.isEmpty()) {
176 builder.append(typePackageName + Constants.DOT + type.getName());
178 builder.append(type.getName());
181 if (type.equals(Types.voidType())) {
184 addActualTypeParameters(builder, type);
186 return builder.toString();
189 final def StringBuilder addActualTypeParameters(StringBuilder builder, Type type) {
190 if (type instanceof ParameterizedType) {
191 val ParameterizedType pType = (type as ParameterizedType)
192 val Type[] pTypes = pType.getActualTypeArguments();
194 builder.append(getParameters(pTypes));
200 final def String getParameters(Type[] pTypes) {
201 if (pTypes == null || pTypes.length == 0) {
204 val StringBuilder builder = new StringBuilder();
207 for (pType : pTypes) {
208 val Type t = pTypes.get(i)
210 var String separator = ",";
211 if (i == (pTypes.length - 1)) {
215 var String wildcardParam = "";
216 if (t.equals(Types.voidType())) {
217 builder.append("java.lang.Void" + separator);
220 if (t instanceof WildcardType) {
221 wildcardParam = "? extends ";
224 builder.append(wildcardParam + getExplicitType(t) + separator);
228 return builder.toString();