Fix YANG snippet escaping
[mdsal.git] / binding / mdsal-binding-java-api-generator / src / main / java / org / opendaylight / mdsal / binding / java / api / generator / LengthGenerator.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.collect.Range;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.Set;
14 import org.eclipse.jdt.annotation.NonNull;
15 import org.eclipse.jdt.annotation.Nullable;
16 import org.opendaylight.mdsal.binding.model.api.Type;
17 import org.opendaylight.yangtools.yang.binding.CodeHelpers;
18 import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21
22 final class LengthGenerator {
23     private static final Logger LOG = LoggerFactory.getLogger(LengthGenerator.class);
24
25     private LengthGenerator() {
26         throw new UnsupportedOperationException();
27     }
28
29     private static String lengthCheckerName(final String member) {
30         return "check" + member + "Length";
31     }
32
33     private static Collection<String> createExpressions(final LengthConstraint constraint) {
34         final Set<Range<Integer>> constraints = constraint.getAllowedRanges().asRanges();
35         final Collection<String> ret = new ArrayList<>(constraints.size());
36
37         for (Range<Integer> l : constraints) {
38             // We have to deal with restrictions being out of integer's range
39             final String expr = createExpression(l.lowerEndpoint().intValue(), l.upperEndpoint().intValue());
40             if (expr == null) {
41                 // This range is implicitly capped by String/byte[] length returns
42                 LOG.debug("Constraint {} implied by int type value domain, skipping", l);
43             } else {
44                 ret.add(expr);
45             }
46         }
47
48         return ret;
49     }
50
51     private static @Nullable String createExpression(final int min, final int max) {
52         if (min == max) {
53             return min < Integer.MAX_VALUE ? "length == " + min : null;
54         }
55         if (min > 0) {
56             final StringBuilder sb = new StringBuilder("length >= ").append(min);
57             if (max < Integer.MAX_VALUE) {
58                 sb.append(" && length <= ").append(max);
59             }
60             return sb.toString();
61         }
62
63         return max < Integer.MAX_VALUE ? "length <= " + max : null;
64     }
65
66     private static String createLengthString(final LengthConstraint constraint) {
67         return new ArrayList<>(constraint.getAllowedRanges().asRanges()).toString();
68     }
69
70     private static String generateArrayLengthChecker(final String member, final LengthConstraint constraint,
71             final JavaFileTemplate template) {
72         final StringBuilder sb = new StringBuilder();
73         final Collection<String> expressions = createExpressions(constraint);
74
75         sb.append("private static void ").append(lengthCheckerName(member)).append("(final byte[] value) {\n");
76
77         if (!expressions.isEmpty()) {
78             sb.append("    final int length = value.length;\n");
79
80             for (String exp : expressions) {
81                 sb.append("    if (").append(exp).append(") {\n");
82                 sb.append("        return;\n");
83                 sb.append("    }\n");
84             }
85
86             sb.append("    ").append(template.importedName(CodeHelpers.class)).append(".throwInvalidLength(\"")
87             .append(createLengthString(constraint)).append("\", value);\n");
88         }
89
90         return sb.append("}\n").toString();
91     }
92
93     private static String generateStringLengthChecker(final String member, final LengthConstraint constraint,
94             final JavaFileTemplate template) {
95         final StringBuilder sb = new StringBuilder();
96         final Collection<String> expressions = createExpressions(constraint);
97
98         sb.append("private static void ").append(lengthCheckerName(member)).append("(final String value) {\n");
99
100         if (!expressions.isEmpty()) {
101             sb.append("    final int length = value.length();\n");
102
103             for (String exp : expressions) {
104                 sb.append("    if (").append(exp).append(") {\n");
105                 sb.append("        return;\n");
106                 sb.append("    }\n");
107             }
108
109             sb.append("    ").append(template.importedName(CodeHelpers.class)).append(".throwInvalidLength(\"")
110             .append(createLengthString(constraint)).append("\", value);\n");
111         }
112
113         return sb.append("}\n").toString();
114     }
115
116     static String generateLengthChecker(final String member, final Type type,
117             final LengthConstraint constraint, final JavaFileTemplate template) {
118         return TypeUtils.getBaseYangType(type).getName().indexOf('[') != -1
119                 ? generateArrayLengthChecker(member, constraint, template)
120                         : generateStringLengthChecker(member, constraint, template);
121     }
122
123     static String generateLengthCheckerCall(final @Nullable String member, final @NonNull String valueReference) {
124         return lengthCheckerName(member) + '(' + valueReference + ");\n";
125     }
126 }