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