2 * Copyright (c) 2016 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.binding2.java.api.generator.renderers;
11 import static org.opendaylight.mdsal.binding2.generator.util.Binding2Mapping.MEMBER_PATTERN_LIST;
12 import static org.opendaylight.mdsal.binding2.generator.util.Binding2Mapping.PATTERN_CONSTANT_NAME;
13 import static org.opendaylight.mdsal.binding2.java.api.generator.util.TextTemplateUtil.fieldName;
14 import static org.opendaylight.mdsal.binding2.java.api.generator.util.TextTemplateUtil.setterMethod;
16 import com.google.common.base.Preconditions;
17 import com.google.common.collect.Collections2;
18 import com.google.common.collect.ImmutableList;
19 import com.google.common.collect.Lists;
20 import com.google.common.io.BaseEncoding;
21 import java.beans.ConstructorProperties;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.Comparator;
27 import java.util.HashMap;
28 import java.util.LinkedList;
29 import java.util.List;
31 import java.util.Objects;
32 import java.util.regex.Pattern;
33 import org.opendaylight.mdsal.binding2.java.api.generator.rangeGenerators.AbstractRangeGenerator;
34 import org.opendaylight.mdsal.binding2.java.api.generator.rangeGenerators.LengthGenerator;
35 import org.opendaylight.mdsal.binding2.model.api.Constant;
36 import org.opendaylight.mdsal.binding2.model.api.Enumeration;
37 import org.opendaylight.mdsal.binding2.model.api.GeneratedProperty;
38 import org.opendaylight.mdsal.binding2.model.api.GeneratedTransferObject;
39 import org.opendaylight.mdsal.binding2.model.api.GeneratedType;
40 import org.opendaylight.mdsal.binding2.model.api.Restrictions;
41 import org.opendaylight.mdsal.binding2.model.api.Type;
42 import org.opendaylight.mdsal.binding2.txt.classTemplate;
43 import org.opendaylight.mdsal.binding2.txt.classTemplateConstructors;
44 import org.opendaylight.mdsal.binding2.txt.classTemplateInitBlock;
45 import org.opendaylight.mdsal.binding2.txt.classTemplateRestrictions;
46 import org.opendaylight.mdsal.binding2.txt.classTemplateUnionConstr;
48 public class ClassRenderer extends BaseRenderer {
49 protected final GeneratedTransferObject genTO;
50 protected final Restrictions restrictions;
51 private final List<GeneratedProperty> properties;
52 private final List<GeneratedProperty> finalProperties;
53 private final List<GeneratedProperty> parentProperties;
54 private final List<Enumeration> enums;
55 private final List<Constant> consts;
56 private final List<GeneratedType> enclosedGeneratedTypes;
57 private final List<GeneratedProperty> allProperties;
58 private final Map<String, String> importedNames = new HashMap<>();
59 private final AbstractRangeGenerator<?> rangeGenerator;
61 public ClassRenderer(final GeneratedTransferObject genType) {
64 properties = ImmutableList.copyOf(genTO.getProperties());
65 finalProperties = ImmutableList.copyOf(resolveReadOnlyPropertiesFromTO(genTO.getProperties()));
66 parentProperties = ImmutableList.copyOf(getPropertiesOfAllParents(genTO));
67 enums = ImmutableList.copyOf(genTO.getEnumerations());
68 consts = ImmutableList.copyOf(genTO.getConstantDefinitions());
69 enclosedGeneratedTypes = ImmutableList.copyOf(genTO.getEnclosedTypes());
70 restrictions = genTO.getRestrictions();
72 final List<GeneratedProperty> sorted = new ArrayList<>();
73 sorted.addAll(properties);
74 sorted.addAll(parentProperties);
75 final Comparator<GeneratedProperty> function = (GeneratedProperty p1, GeneratedProperty p2) -> {
76 final String name = p1.getName();
77 final String name1 = p2.getName();
78 return name.compareTo(name1);
80 Collections.sort(sorted, function);
81 allProperties = ImmutableList.copyOf(sorted);
83 if (restrictions != null && !(restrictions.getRangeConstraints() != null && !restrictions.getLengthConstraints
85 rangeGenerator = AbstractRangeGenerator.forType(findProperty(genType, "value").getReturnType());
86 Preconditions.checkNotNull(rangeGenerator);
88 rangeGenerator = null;
92 protected List<GeneratedProperty> getProperties() {
96 protected List<GeneratedProperty> getFinalProperties() {
97 return finalProperties;
100 protected List<GeneratedProperty> getParentProperties() {
101 return parentProperties;
104 protected List<Enumeration> getEnums() {
108 protected List<Constant> getConsts() {
112 protected List<GeneratedType> getEnclosedGeneratedTypes() {
113 return enclosedGeneratedTypes;
116 protected Collection<GeneratedProperty> getAllProperties() {
117 return allProperties;
120 protected String generateAsInnerClass() {
121 return generateBody(true);
125 protected String body() {
126 return generateBody(false);
129 protected String generateBody(final boolean isInnerClass) {
130 importedNames.put("genTypeSuper", importedName(genTO.getSuperType()));
131 importedNames.put("type", importedName(getType()));
132 importedNames.put("arrays", importedName(Arrays.class));
133 importedNames.put("objects", importedName(Objects.class));
134 importedNames.put("string", importedName(String.class));
135 importedNames.put("byte", importedName(Byte.class));
136 importedNames.put("short", importedName(Short.class));
137 importedNames.put("integer", importedName(Integer.class));
138 importedNames.put("long", importedName(Long.class));
139 importedNames.put("stringBuilder", importedName(StringBuilder.class));
140 importedNames.put("list", importedName(List.class));
141 importedNames.put("lists", importedName(Lists.class));
142 importedNames.put("illegalArgumentException", importedName(IllegalArgumentException.class));
143 importedNames.put("boolean", importedName(Boolean.class));
145 final List<String> implementsListBuilder = new LinkedList<>();
146 if (!getType().getImplements().isEmpty()) {
147 for (Type impl : getType().getImplements()) {
148 implementsListBuilder.add((importedName(impl)));
151 final String implementsList = String.join(", ", implementsListBuilder);
153 final List<String> classTemplateBuilder = new LinkedList<>();
154 if (!enclosedGeneratedTypes.isEmpty()) {
155 for (GeneratedType innerClass : enclosedGeneratedTypes) {
156 if (innerClass instanceof GeneratedTransferObject) {
157 classTemplateBuilder.add(new ClassRenderer((GeneratedTransferObject) innerClass).generateAsInnerClass());
161 final String innerClasses = String.join("\n", classTemplateBuilder);
163 final List<String> enumList = new LinkedList<>();
164 if (!enums.isEmpty()) {
165 for (Enumeration enumeration : enums) {
166 enumList.add(new EnumRenderer(enumeration).body());
169 final String enumerations = String.join("\n", enumList);
171 final StringBuilder sb1 = new StringBuilder();
172 final String initBlock = classTemplateInitBlock.render(importedName(Pattern.class)).body();
173 if (!consts.isEmpty()) {
174 for (Constant constant : consts) {
175 if (PATTERN_CONSTANT_NAME.equals(constant.getName())) {
176 if (constant.getValue() instanceof List<?>) {
177 sb1.append("private static final ")
178 .append(importedName(Pattern.class))
180 .append(MEMBER_PATTERN_LIST)
181 .append(";\npublic static final ")
182 .append(importedName(List.class))
184 .append(PATTERN_CONSTANT_NAME)
186 .append(importedName(ImmutableList.class))
188 final List<String> constantList = new LinkedList<>();
189 for (Object item : (List) constant.getValue()) {
190 if (item instanceof String) {
191 constantList.add("\"" + item + "\"");
194 sb1.append(String.join(", ", constantList));
199 sb1.append(emitConstant(constant));
203 final String constants = sb1.toString();
205 if (genTO.getSuperType() != null) {
206 importedNames.put("superType", importedName(genTO.getSuperType()));
209 for (GeneratedProperty property : properties) {
210 importedNames.put(property.getReturnType().toString(), importedName(property.getReturnType()));
213 final String constructors = generateConstructors();
215 final StringBuilder lengthRangeCheckerBuilder = new StringBuilder();
216 if (restrictions != null) {
217 if (restrictions.getLengthConstraints() != null && !restrictions.getLengthConstraints().isEmpty()) {
218 lengthRangeCheckerBuilder.append(LengthGenerator.generateLengthChecker("_value", findProperty(genTO,
219 "value").getReturnType(), restrictions.getLengthConstraints()))
222 if (restrictions.getRangeConstraints() != null && !restrictions.getRangeConstraints().isEmpty()) {
223 lengthRangeCheckerBuilder.append(rangeGenerator.generateRangeChecker("_value", restrictions
224 .getRangeConstraints()))
228 final String lengthRangeChecker = lengthRangeCheckerBuilder.toString();
230 final StringBuilder sb2 = new StringBuilder();
231 if (!properties.isEmpty()) {
232 for (GeneratedProperty property : properties) {
233 final String isFinal = property.isReadOnly() ? " final " : " ";
234 sb2.append("private")
236 .append(importedName(property.getReturnType()))
238 .append(fieldName(property))
242 final String fields = sb2.toString();
243 importedNames.put("baseEncoding", importedName(BaseEncoding.class));
244 importedNames.put("defProp", importedName(((GeneratedProperty)((List) allProperties).get(0)).getReturnType()));
246 final StringBuilder sb3 = new StringBuilder();
247 for (GeneratedProperty property : properties) {
248 sb3.append(getterMethod(property));
249 if (!property.isReadOnly()) {
250 sb3.append(setterMethod(property, getType().getName(), importedName(property
254 final String propertyMethod = sb3.toString();
256 return classTemplate.render(getType(), genTO, importedNames, implementsList, innerClasses, enumerations,
257 constants, constructors, lengthRangeChecker, fields, (List) allProperties, propertyMethod,
258 isInnerClass).body();
261 protected String generateConstructors() {
262 importedNames.put("constructorProperties", importedName(ConstructorProperties.class));
263 importedNames.put("preconditions", importedName(Preconditions.class));
265 final StringBuilder sb1 = new StringBuilder();
266 for (GeneratedProperty allProperty : allProperties) {
267 sb1.append(classTemplateRestrictions.render(getType(), fieldName(allProperty), allProperty
268 .getReturnType(), rangeGenerator).body());
270 final String genRestrictions = sb1.toString();
272 final StringBuilder sb2 = new StringBuilder();
273 if (genTO.isUnionType()) {
274 for (GeneratedProperty allProperty : allProperties) {
275 final List other = new ArrayList<>(properties);
276 if (other.remove(allProperty)) {
277 sb2.append(classTemplateUnionConstr.render(getType(), parentProperties, allProperty,
278 other, importedName(allProperty.getReturnType()), genRestrictions).body());
282 final String unionConstructor = sb2.toString();
284 final String argumentsDeclaration = asArgumentsDeclaration(allProperties);
285 return classTemplateConstructors.render(genTO, (List) allProperties, properties, parentProperties,
286 importedNames, argumentsDeclaration, unionConstructor, genRestrictions).body();
290 * Selects from input list of properties only those which have read only
291 * attribute set to true.
294 * list of properties of generated transfer object
295 * @return subset of <code>properties</code> which have read only attribute
298 private List<GeneratedProperty> resolveReadOnlyPropertiesFromTO(final List<GeneratedProperty> properties) {
299 return new ArrayList(Collections2.transform(properties, GeneratedProperty::isReadOnly));
303 * Returns the list of the read only properties of all extending generated
304 * transfer object from <code>genTO</code> to highest parent generated
308 * generated transfer object for which is the list of read only
309 * properties generated
310 * @return list of all read only properties from actual to highest parent
311 * generated transfer object. In case when extension exists the
312 * method is recursive called.
314 private List<GeneratedProperty> getPropertiesOfAllParents(final GeneratedTransferObject genTO) {
315 final List<GeneratedProperty> propertiesOfAllParents = new ArrayList<>();
316 if (genTO.getSuperType() != null) {
317 final List<GeneratedProperty> allPropertiesOfTO = genTO.getSuperType().getProperties();
318 List<GeneratedProperty> readOnlyPropertiesOfTO = resolveReadOnlyPropertiesFromTO(allPropertiesOfTO);
319 propertiesOfAllParents.addAll(readOnlyPropertiesOfTO);
320 propertiesOfAllParents.addAll(getPropertiesOfAllParents(genTO.getSuperType()));
322 return propertiesOfAllParents;