2 * Copyright (c) 2017 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
9 package org.opendaylight.mdsal.binding.javav2.java.api.generator.renderers;
11 import static java.util.Objects.requireNonNull;
13 import java.util.AbstractMap.SimpleEntry;
14 import java.util.ArrayDeque;
15 import java.util.ArrayList;
16 import java.util.Deque;
17 import java.util.List;
18 import java.util.Map.Entry;
19 import java.util.Optional;
20 import org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes;
21 import org.opendaylight.mdsal.binding.javav2.generator.util.JavaIdentifier;
22 import org.opendaylight.mdsal.binding.javav2.generator.util.JavaIdentifierNormalizer;
23 import org.opendaylight.mdsal.binding.javav2.java.api.generator.txt.constantsTemplate;
24 import org.opendaylight.mdsal.binding.javav2.java.api.generator.txt.enumTemplate;
25 import org.opendaylight.mdsal.binding.javav2.java.api.generator.txt.interfaceTemplate;
26 import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil;
27 import org.opendaylight.mdsal.binding.javav2.model.api.AnnotationType;
28 import org.opendaylight.mdsal.binding.javav2.model.api.Enumeration;
29 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedTransferObject;
30 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedType;
31 import org.opendaylight.mdsal.binding.javav2.model.api.MethodSignature;
32 import org.opendaylight.mdsal.binding.javav2.model.api.Type;
33 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTypeBuilder;
34 import org.opendaylight.mdsal.binding.javav2.spec.base.InstanceIdentifier;
35 import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingNamespaceType;
36 import org.opendaylight.yangtools.yang.common.QName;
38 public class InterfaceRenderer extends BaseRenderer {
40 private static final char NEW_LINE = '\n';
43 * Creates the instance of this class which is used for generating the interface file source
44 * code from <code>type</code>.
45 * @param type generated type
47 public InterfaceRenderer(final GeneratedType type) {
49 requireNonNull(type, "Generated type reference cannot be NULL!");
53 protected String body() {
54 // mainAnnotations string with annotations for whole interface
55 final String mainAnnotations = generateAnnotations(getType().getAnnotations());
56 // StringBuilder string with the declaration of methods source code in JAVA format
57 final StringBuilder sb1 = new StringBuilder();
58 for (MethodSignature method : getType().getMethodDefinitions()) {
59 if (isAccessor(method)) {
60 sb1.append(TextTemplateUtil.asJavadoc(method.getComment()));
62 sb1.append(TextTemplateUtil.getJavaDocForInterface(method));
64 sb1.append(generateAnnotations(method.getAnnotations()))
65 .append(importedName(method.getReturnType()))
67 .append(method.getName())
69 .append(generateParameters(method.getParameters()))
73 final String methodList = sb1.toString();
75 // enums string with rendered enums from template
76 final StringBuilder sb2 = new StringBuilder();
77 for (Enumeration enumeration : getType().getEnumerations()) {
78 final String importedName = importedName(String.class);
79 final String enumBody = enumTemplate.render(enumeration, importedName).body();
82 final String enums = sb2.toString();
84 final String generatedImports = generateImports(getType().getImplements());
86 getImportedNames().put("qname", importedName(QName.class));
87 final String generatedConstants = constantsTemplate.render(getType(), getImportedNames(),
88 this::importedName, true).body();
90 final Entry<String, String> identifier = generateInstanceIdentifier();
92 final List<String> innerClasses = new ArrayList<>(getType().getEnclosedTypes().size());
93 for (GeneratedType innerClass : getType().getEnclosedTypes()) {
94 if (innerClass instanceof GeneratedTransferObject) {
95 if (((GeneratedTransferObject) innerClass).isUnionType()) {
96 final UnionRenderer unionRenderer = new UnionRenderer((GeneratedTransferObject) innerClass);
97 innerClasses.add(unionRenderer.generateAsInnerClass());
98 this.putAllToImportMap(unionRenderer.getImportMap());
100 final ClassRenderer classRenderer = new ClassRenderer((GeneratedTransferObject) innerClass);
101 innerClasses.add(classRenderer.generateAsInnerClass());
102 this.putAllToImportMap(classRenderer.getImportMap());
106 final String generatedInnerClasses = String.join("\n", innerClasses);
108 return interfaceTemplate.render(getType(), enums, mainAnnotations, methodList, generatedImports,
109 generatedConstants, generatedInnerClasses, identifier.getKey(), identifier.getValue()).body();
112 private static boolean isAccessor(final MethodSignature maybeGetter) {
113 return maybeGetter.getName().startsWith("is") || maybeGetter.getName().startsWith("get");
117 * Return string of annotations.
118 * @param annotationTypeList list of annotations
119 * @return String of annotations in format:
121 * (parameterName1=ParameterSingleValue1,...)
124 private String generateAnnotations(final List<AnnotationType> annotationTypeList) {
125 final StringBuilder sb1 = new StringBuilder();
126 for (AnnotationType annotationType : annotationTypeList) {
127 sb1.append('@').append(importedName(annotationType));
128 if (!annotationType.getParameters().isEmpty()) {
131 final List<String> parameterList = new ArrayList<>(annotationType.getParameters().size());
132 for (AnnotationType.Parameter parameter : annotationType.getParameters()) {
133 final StringBuilder sb2 = new StringBuilder();
134 sb2.append(parameter.getName()).append('=').append(parameter.getSingleValue());
135 parameterList.add(sb2.toString());
137 sb1.append(String.join(",", parameterList));
138 if (!annotationType.getParameters().isEmpty()) {
141 sb1.append(NEW_LINE);
143 return sb1.toString();
147 * Generate default method getInstanceIdentifier.
148 * @return string pair of instance identifier and key parameters
150 private Entry<String, String> generateInstanceIdentifier() {
151 //Only tree data nodes need to generate the method.
152 if (null == getType().getBindingNamespaceType()
153 || !BindingNamespaceType.isTreeData(getType().getBindingNamespaceType())
154 || !getType().getImplements().contains(BindingTypes.TREE_CHILD_NODE)) {
155 return new SimpleEntry<>(null, null);
158 final Deque<GeneratedType> dataPath = new ArrayDeque<>();
159 GeneratedType type = getType();
160 GeneratedTypeBuilder parentTypeBuilder;
162 while (type != null) {
165 parentTypeBuilder = (GeneratedTypeBuilder) type.getParentTypeForBuilder();
166 type = parentTypeBuilder != null ? parentTypeBuilder.toInstance() : null;
171 final StringBuilder iiBuidler = new StringBuilder();
172 type = dataPath.pop();
173 iiBuidler.append("InstanceIdentifier.builder(").append(type.getName()).append(".class)");
174 importedName(InstanceIdentifier.class);
175 final List<String> keys = new ArrayList<>();
176 while (dataPath.peek() != null) {
177 type = dataPath.pop();
178 if (type.getImplements().contains(BindingTypes.AUGMENTATION)) {
179 iiBuidler.append(".augmentation(").append(type.getName()).append(".class)");
181 Optional<MethodSignature> method = type.getMethodDefinitions().stream().filter(m ->
182 m.getName().equals("getIdentifier")).findFirst();
183 if (method.isPresent()) {
184 importedName(method.get().getReturnType());
185 final String keyName = method.get().getReturnType().getName();
186 final String normalizedKeyName = JavaIdentifierNormalizer.normalizeSpecificIdentifier(keyName,
187 JavaIdentifier.METHOD);
188 keys.add(new StringBuilder().append("final ").append(keyName).append(" _")
189 .append(normalizedKeyName).toString());
190 iiBuidler.append(".child(").append(type.getFullyQualifiedName()).append(".class, _")
191 .append(normalizedKeyName).append(")");
193 iiBuidler.append(".child(").append(type.getFullyQualifiedName()).append(".class)");
197 iiBuidler.append(".build()");
198 return new SimpleEntry<>(iiBuidler.toString(), String.join(", ", keys));
203 * Return list of parameters.
204 * @param parameters list of parameters
205 * @return list of parameters separated with ","
207 private String generateImports(final List<Type> parameters) {
208 final List<String> strings = new ArrayList<>(parameters.size());
209 for (Type parameter : parameters) {
210 strings.add(importedName(parameter));
213 return String.join(", ", strings);