Bug 1411-3: MDSAL Binding2 Generator Util
[mdsal.git] / binding2 / mdsal-binding2-generator-util / src / main / java / org / opendaylight / mdsal / binding2 / generator / util / Binding2GeneratorUtil.java
1 /*
2  * Copyright (c) 2016 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
9 package org.opendaylight.mdsal.binding2.generator.util;
10
11 import com.google.common.annotations.Beta;
12 import com.google.common.base.CharMatcher;
13 import com.google.common.collect.ImmutableList;
14 import com.google.common.collect.Iterables;
15 import java.util.Comparator;
16 import java.util.Iterator;
17 import java.util.List;
18 import org.opendaylight.mdsal.binding2.model.api.Restrictions;
19 import org.opendaylight.mdsal.binding2.model.api.Type;
20 import org.opendaylight.mdsal.binding2.model.api.type.builder.TypeMemberBuilder;
21 import org.opendaylight.yangtools.yang.common.QName;
22 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
23 import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
24 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
25 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
26
27 /**
28  * Standard Util class that contains various method for converting
29  * input strings to valid JAVA language strings e.g. package names,
30  * class names, attribute names and/or valid JavaDoc comments.
31  */
32 @Beta
33 public final class Binding2GeneratorUtil {
34
35     private Binding2GeneratorUtil() {
36         throw new UnsupportedOperationException("Utility class");
37     }
38
39     private static final CharMatcher GT_MATCHER = CharMatcher.is('>');
40     private static final CharMatcher LT_MATCHER = CharMatcher.is('<');
41
42     private static final Restrictions EMPTY_RESTRICTIONS = new Restrictions() {
43         @Override
44         public List<LengthConstraint> getLengthConstraints() {
45             return ImmutableList.of();
46         }
47
48         @Override
49         public List<PatternConstraint> getPatternConstraints() {
50             return ImmutableList.of();
51         }
52
53         @Override
54         public List<RangeConstraint> getRangeConstraints() {
55             return ImmutableList.of();
56         }
57
58         @Override
59         public boolean isEmpty() {
60             return true;
61         }
62     };
63
64     private static final Comparator<TypeMemberBuilder<?>> SUID_MEMBER_COMPARATOR =
65             (o1, o2) -> o1.getName().compareTo(o2.getName());
66
67     private static final Comparator<Type> SUID_NAME_COMPARATOR =
68             (o1, o2) -> o1.getFullyQualifiedName().compareTo(o2.getFullyQualifiedName());
69
70     /**
71      * Creates package name from specified <code>basePackageName</code> (package
72      * name for module) and <code>schemaPath</code>.
73      *
74      * Resulting package name is concatenation of <code>basePackageName</code>
75      * and all local names of YANG nodes which are parents of some node for
76      * which <code>schemaPath</code> is specified.
77      *
78      * Based on type of node, there is also possible suffix added in order
79      * to prevent package name conflicts.
80      *
81      * @param basePackageName
82      *            string with package name of the module, MUST be normalized,
83      *            otherwise this method may return an invalid string.
84      * @param schemaPath
85      *            list of names of YANG nodes which are parents of some node +
86      *            name of this node
87      * @return string with valid JAVA package name
88      * @throws NullPointerException if any of the arguments are null
89      */
90     public static String packageNameForGeneratedType(final String basePackageName, final SchemaPath schemaPath) {
91         final Iterable<QName> pathTowardsRoot = schemaPath.getPathTowardsRoot();
92         final Iterable<QName> pathFromRoot = schemaPath.getPathFromRoot();
93         final int size = Iterables.size(pathTowardsRoot) - 1;
94         if (size <= 0) {
95             return basePackageName;
96         }
97
98         return generateNormalizedPackageName(basePackageName, pathFromRoot, size);
99     }
100
101     /**
102      * Creates package name from specified <code>basePackageName</code> (package
103      * name for module) and <code>schemaPath</code> which crosses an augmentation.
104      *
105      * Resulting package name is concatenation of <code>basePackageName</code>
106      * and all local names of YANG nodes which are parents of some node for
107      * which <code>schemaPath</code> is specified.
108      *
109      * Based on type of node, there is also possible suffix added in order
110      * to prevent package name conflicts.
111      *
112      * @param basePackageName
113      *            string with package name of the module, MUST be normalized,
114      *            otherwise this method may return an invalid string.
115      * @param schemaPath
116      *            list of names of YANG nodes which are parents of some node +
117      *            name of this node
118      * @return string with valid JAVA package name
119      * @throws NullPointerException if any of the arguments are null
120      */
121     public static String packageNameForAugmentedGeneratedType(final String basePackageName, final SchemaPath schemaPath) {
122         final Iterable<QName> pathTowardsRoot = schemaPath.getPathTowardsRoot();
123         final Iterable<QName> pathFromRoot = schemaPath.getPathFromRoot();
124         final int size = Iterables.size(pathTowardsRoot);
125         if (size == 0) {
126             return basePackageName;
127         }
128
129         return generateNormalizedPackageName(basePackageName, pathFromRoot, size);
130     }
131
132
133     private static String generateNormalizedPackageName(final String base, final Iterable<QName> path, final int size) {
134         final StringBuilder builder = new StringBuilder(base);
135         final Iterator<QName> iterator = path.iterator();
136         for (int i = 0; i < size; ++i) {
137             builder.append('.');
138             String nodeLocalName = iterator.next().getLocalName();
139             //FIXME: colon or dash in identifier?
140             builder.append(nodeLocalName);
141         }
142         return Binding2Mapping.normalizePackageName(builder.toString());
143     }
144
145     /**
146      * Encodes angle brackets in yang statement description
147      * @param description description of a yang statement which is used to generate javadoc comments
148      * @return string with encoded angle brackets
149      */
150     public static String encodeAngleBrackets(String description) {
151         if (description != null) {
152             description = LT_MATCHER.replaceFrom(description, "&lt;");
153             description = GT_MATCHER.replaceFrom(description, "&gt;");
154         }
155         return description;
156     }
157
158     //TODO: further implementation of static util methods...
159 }