d57f00daaee50cbe7d131a9b0ccfc8e1ba84a86f
[mdsal.git] / binding / mdsal-binding-java-api-generator / src / main / java / org / opendaylight / mdsal / binding / java / api / generator / AbstractPrimitiveRangeGenerator.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.mdsal.binding.java.api.generator;
9
10 import com.google.common.base.Preconditions;
11 import com.google.common.collect.Range;
12 import java.util.ArrayList;
13 import java.util.Collection;
14 import java.util.List;
15 import java.util.Set;
16 import java.util.function.Function;
17 import javax.annotation.Nonnull;
18 import org.opendaylight.yangtools.yang.binding.CodeHelpers;
19 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
22
23 abstract class AbstractPrimitiveRangeGenerator<T extends Number & Comparable<T>> extends AbstractRangeGenerator<T> {
24     private static final Logger LOG = LoggerFactory.getLogger(AbstractPrimitiveRangeGenerator.class);
25     private final String primitiveName;
26     private final T minValue;
27     private final T maxValue;
28
29     protected AbstractPrimitiveRangeGenerator(final Class<T> typeClass, final String primitiveName, final T minValue, final T maxValue) {
30         super(typeClass);
31         this.primitiveName = Preconditions.checkNotNull(primitiveName);
32         this.minValue = Preconditions.checkNotNull(minValue);
33         this.maxValue = Preconditions.checkNotNull(maxValue);
34     }
35
36     /**
37      * Return the name of the primitive type, as known by the Java language.
38      *
39      * @return Primitive type name
40      */
41     @Nonnull protected final String getPrimitiveName() {
42         return primitiveName;
43     }
44
45     private boolean needsMaximumEnforcement(final T maxToEnforce) {
46         return maxValue.compareTo(maxToEnforce) > 0;
47     }
48
49     private boolean needsMinimumEnforcement(final T minToEnforce) {
50         return minValue.compareTo(minToEnforce) < 0;
51     }
52
53     private Collection<String> createExpressions(final RangeConstraint<?> constraint) {
54         final Set<? extends Range<? extends Number>> constraints = constraint.getAllowedRanges().asRanges();
55         final Collection<String> ret = new ArrayList<>(constraints.size());
56
57         for (Range<? extends Number> r : constraints) {
58             final T min = getValue(r.lowerEndpoint());
59             final boolean needMin = needsMinimumEnforcement(min);
60
61             final T max = getValue(r.upperEndpoint());
62             final boolean needMax = needsMaximumEnforcement(max);
63
64             if (!needMin && !needMax) {
65                 LOG.debug("Type {} indicates [{}, {}] does not require enforcement", getTypeName(), min, max);
66                 continue;
67             }
68
69             final StringBuilder sb = new StringBuilder();
70             if (needMin) {
71                 sb.append("value >= ").append(format(min));
72             }
73             if (needMax) {
74                 if (needMin) {
75                     sb.append(" && ");
76                 }
77                 sb.append("value <= ").append(format(max));
78             }
79
80             ret.add(sb.toString());
81         }
82
83         return ret;
84     }
85
86     private String createRangeString(final RangeConstraint<?> constraint) {
87         final Set<? extends Range<? extends Number>> constraints = constraint.getAllowedRanges().asRanges();
88         final List<Range<T>> ranges = new ArrayList<>(constraints.size());
89
90         for (Range<? extends Number> c : constraints) {
91             ranges.add(Range.closed(getValue(c.lowerEndpoint()), getValue(c.upperEndpoint())));
92         }
93
94         return ranges.toString();
95     }
96
97     @Override
98     protected final String generateRangeCheckerImplementation(final String checkerName,
99             final RangeConstraint<?> constraints, final Function<Class<?>, String> classImporter) {
100         final StringBuilder sb = new StringBuilder();
101         final Collection<String> expressions = createExpressions(constraints);
102
103         sb.append("private static void ").append(checkerName).append("(final ").append(primitiveName).append(" value) {\n");
104
105         if (!expressions.isEmpty()) {
106             for (String exp : expressions) {
107                 sb.append("    if (").append(exp).append(") {\n");
108                 sb.append("        return;\n");
109                 sb.append("    }\n");
110             }
111
112             sb.append("    ").append(classImporter.apply(CodeHelpers.class)).append(".throwInvalidRange(\"")
113             .append(createRangeString(constraints)).append("\", value);\n");
114         }
115
116         sb.append("}\n");
117
118         return sb.toString();
119     }
120 }