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.mdsal.binding.java.api.generator
10 import static extension org.opendaylight.mdsal.binding.spec.naming.BindingMapping.getClassName
11 import static extension org.opendaylight.mdsal.binding.spec.naming.BindingMapping.getRootPackageName
12 import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.MODEL_BINDING_PROVIDER_CLASS_NAME
13 import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.MODULE_INFO_CLASS_NAME
14 import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.MODULE_INFO_QNAMEOF_METHOD_NAME
16 import com.google.common.base.Preconditions
17 import com.google.common.collect.ImmutableSet
18 import java.util.Comparator
19 import java.util.HashSet
20 import java.util.Optional
22 import java.util.TreeMap
23 import java.util.function.Function
24 import org.eclipse.xtend.lib.annotations.Accessors
25 import org.opendaylight.yangtools.yang.binding.YangModuleInfo
26 import org.opendaylight.yangtools.yang.common.Revision
27 import org.opendaylight.yangtools.yang.model.api.Module
28 import org.opendaylight.yangtools.yang.model.api.SchemaContext
31 * Template for {@link YangModuleInfo} implementation for a particular module. Aside from fulfilling that contract,
32 * this class provides a static {@code createQName(String)} method, which is used by co-generated code to initialize
35 class YangModuleInfoTemplate {
36 static val Comparator<Optional<Revision>> REVISION_COMPARATOR =
37 [ Optional<Revision> first, Optional<Revision> second | Revision.compare(first, second) ]
39 // These are always imported. Note we need to import even java.lang members, as there can be conflicting definitions
41 static val CORE_IMPORT_STR = '''
42 import com.google.common.collect.ImmutableSet;
43 import java.lang.Override;
44 import java.lang.String;
45 import org.eclipse.jdt.annotation.NonNull;
46 import org.opendaylight.yangtools.yang.binding.ResourceYangModuleInfo;
47 import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
48 import org.opendaylight.yangtools.yang.common.QName;
50 static val EXT_IMPORT_STR = '''
51 import com.google.common.collect.ImmutableSet;
52 import java.lang.Override;
53 import java.lang.String;
54 import java.util.HashSet;
56 import org.eclipse.jdt.annotation.NonNull;
57 import org.opendaylight.yangtools.yang.binding.ResourceYangModuleInfo;
58 import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
59 import org.opendaylight.yangtools.yang.common.QName;
64 val Function<Module, Optional<String>> moduleFilePathResolver
66 var importedTypes = CORE_IMPORT_STR
69 val String packageName
72 val String modelBindingProviderName
74 new(Module module, SchemaContext ctx, Function<Module, Optional<String>> moduleFilePathResolver) {
75 Preconditions.checkArgument(module !== null, "Module must not be null.")
78 this.moduleFilePathResolver = moduleFilePathResolver
79 packageName = module.QNameModule.rootPackageName;
80 modelBindingProviderName = '''«packageName».«MODEL_BINDING_PROVIDER_CLASS_NAME»'''
83 def String generate() {
84 val Set<Module> submodules = new HashSet
85 collectSubmodules(submodules, module)
88 public final class «MODULE_INFO_CLASS_NAME» extends ResourceYangModuleInfo {
89 «val rev = module.revision»
90 private static final @NonNull QName NAME = QName.create("«module.namespace.toString»", «IF rev.present»"«rev.get.toString»", «ENDIF»"«module.name»").intern();
91 private static final @NonNull YangModuleInfo INSTANCE = new «MODULE_INFO_CLASS_NAME»();
93 private final @NonNull ImmutableSet<YangModuleInfo> importedModules;
95 public static @NonNull YangModuleInfo getInstance() {
99 public static @NonNull QName «MODULE_INFO_QNAMEOF_METHOD_NAME»(final String localName) {
100 return QName.create(NAME, localName).intern();
103 «classBody(module, MODULE_INFO_CLASS_NAME, submodules)»
107 package «packageName»;
115 def String generateModelProvider() '''
116 package «packageName»;
118 import java.lang.Override;
119 import org.opendaylight.yangtools.yang.binding.YangModelBindingProvider;
120 import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
122 public final class «MODEL_BINDING_PROVIDER_CLASS_NAME» implements YangModelBindingProvider {
124 public YangModuleInfo getModuleInfo() {
125 return «MODULE_INFO_CLASS_NAME».getInstance();
130 private static def void collectSubmodules(Set<Module> dest, Module module) {
131 for (Module submodule : module.submodules) {
132 if (dest.add(submodule)) {
133 collectSubmodules(dest, submodule)
138 private def CharSequence classBody(Module m, String className, Set<Module> submodules) '''
139 private «className»() {
140 «IF !m.imports.empty || !submodules.empty»
142 Set<YangModuleInfo> set = new HashSet<>();
144 «IF !m.imports.empty»
145 «FOR imp : m.imports»
146 «val name = imp.moduleName»
147 «val rev = imp.revision»
149 «val Set<Module> modules = ctx.modules»
150 «val TreeMap<Optional<Revision>, Module> sorted = new TreeMap(REVISION_COMPARATOR)»
151 «FOR module : modules»
152 «IF module.name.equals(name)»
153 «sorted.put(module.revision, module)»
156 set.add(«sorted.lastEntry().value.QNameModule.rootPackageName».«MODULE_INFO_CLASS_NAME».getInstance());
158 set.add(«(ctx.findModule(name, rev).get.QNameModule).rootPackageName».«MODULE_INFO_CLASS_NAME».getInstance());
162 «FOR submodule : submodules»
163 set.add(«submodule.name.className»Info.getInstance());
165 «IF m.imports.empty && submodules.empty»
166 importedModules = ImmutableSet.of();
168 importedModules = ImmutableSet.copyOf(set);
173 public QName getName() {
178 protected String resourceName() {
179 return "«sourcePath(m)»";
183 public ImmutableSet<YangModuleInfo> getImportedModules() {
184 return importedModules;
186 «generateSubInfo(submodules)»
189 private def void extendImports() {
190 importedTypes = EXT_IMPORT_STR
193 private def sourcePath(Module module) {
194 val opt = moduleFilePathResolver.apply(module)
195 Preconditions.checkState(opt.isPresent, "Module %s does not have a file path", module)
199 private def generateSubInfo(Set<Module> submodules) '''
200 «FOR submodule : submodules»
201 «val className = submodule.name.className»
203 private static final class «className»Info extends ResourceYangModuleInfo {
204 «val rev = submodule.revision»
205 private final @NonNull QName NAME = QName.create("«submodule.namespace.toString»", «
206 IF rev.present»"«rev.get.toString»", «ENDIF»"«submodule.name»").intern();
207 private static final @NonNull YangModuleInfo INSTANCE = new «className»Info();
209 private final @NonNull ImmutableSet<YangModuleInfo> importedModules;
211 public static @NonNull YangModuleInfo getInstance() {
215 «classBody(submodule, className + "Info", ImmutableSet.of)»