package org.opendaylight.yangtools.binding.generator.util; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import org.opendaylight.yangtools.sal.binding.model.api.Restrictions; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.SchemaPath; import org.opendaylight.yangtools.yang.model.api.TypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint; import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint; import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint; import org.opendaylight.yangtools.yang.model.util.ExtendedType; /** * Contains the methods for converting strings to valid JAVA language strings * (package names, class names, attribute names). * * */ public final class BindingGeneratorUtil { private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyMMdd"); /** * Array of strings values which represents JAVA reserved words. */ private static final String[] SET_VALUES = new String[] { "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default", "double", "do", "else", "enum", "extends", "false", "final", "finally", "float", "for", "goto", "if", "implements", "import", "instanceof", "int", "interface", "long", "native", "new", "null", "package", "private", "protected", "public", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "void", "volatile", "while" }; /** * Impossible to instantiate this class. All of the methods or attributes * are static. */ private BindingGeneratorUtil() { } /** * Hash set of words which are reserved in JAVA language. */ private static final Set JAVA_RESERVED_WORDS = new HashSet(Arrays.asList(SET_VALUES)); /** * Converts string packageName to valid JAVA package name. * * If some words of package name are digits of JAVA reserved words they are * prefixed with underscore character. * * @param packageName * string which contains words separated by point. * @return package name which contains words separated by point. */ private static String validateJavaPackage(final String packageName) { if (packageName != null) { final String[] packNameParts = packageName.toLowerCase().split("\\."); if (packNameParts != null) { final StringBuilder builder = new StringBuilder(); for (int i = 0; i < packNameParts.length; ++i) { final String packNamePart = packNameParts[i]; if (Character.isDigit(packNamePart.charAt(0))) { packNameParts[i] = "_" + packNamePart; } else if (JAVA_RESERVED_WORDS.contains(packNamePart)) { packNameParts[i] = "_" + packNamePart; } if (i > 0) { builder.append("."); } builder.append(packNameParts[i]); } return builder.toString(); } } return packageName; } /** * Converts parameterName to valid JAVA parameter name. * * If the parameterName is one of the JAVA reserved words then * it is prefixed with underscore character. * * @param parameterName * string with the parameter name * @return string with the admissible parameter name */ public static String resolveJavaReservedWordEquivalency(final String parameterName) { if (parameterName != null && JAVA_RESERVED_WORDS.contains(parameterName)) { return "_" + parameterName; } return parameterName; } /** * Converts module name to valid JAVA package name. * * The package name consists of: * * * @param module * module which contains data about namespace and revision date * @return string with the valid JAVA package name * @throws IllegalArgumentException * if the revision date of the module equals * null */ public static String moduleNamespaceToPackageName(final Module module) { final StringBuilder packageNameBuilder = new StringBuilder(); if (module.getRevision() == null) { throw new IllegalArgumentException("Module " + module.getName() + " does not specify revision date!"); } packageNameBuilder.append("org.opendaylight.yang.gen.v"); packageNameBuilder.append(module.getYangVersion()); packageNameBuilder.append("."); String namespace = module.getNamespace().toString(); namespace = namespace.replace("://", "."); namespace = namespace.replace("/", "."); namespace = namespace.replace(":", "."); namespace = namespace.replace("-", "."); namespace = namespace.replace("@", "."); namespace = namespace.replace("$", "."); namespace = namespace.replace("#", "."); namespace = namespace.replace("'", "."); namespace = namespace.replace("*", "."); namespace = namespace.replace("+", "."); namespace = namespace.replace(",", "."); namespace = namespace.replace(";", "."); namespace = namespace.replace("=", "."); packageNameBuilder.append(namespace); packageNameBuilder.append(".rev"); packageNameBuilder.append(DATE_FORMAT.format(module.getRevision())); return validateJavaPackage(packageNameBuilder.toString()); } /** * Creates package name from specified basePackageName (package * name for module) and schemaPath. * * Resulting package name is concatenation of basePackageName * and all local names of YANG nodes which are parents of some node for * which schemaPath is specified. * * @param basePackageName * string with package name of the module * @param schemaPath * list of names of YANG nodes which are parents of some node + * name of this node * @return string with valid JAVA package name */ public static String packageNameForGeneratedType(final String basePackageName, final SchemaPath schemaPath) { if (basePackageName == null) { throw new IllegalArgumentException("Base Package Name cannot be NULL!"); } if (schemaPath == null) { throw new IllegalArgumentException("Schema Path cannot be NULL!"); } final StringBuilder builder = new StringBuilder(); builder.append(basePackageName); final List pathToNode = schemaPath.getPath(); final int traversalSteps = (pathToNode.size() - 1); for (int i = 0; i < traversalSteps; ++i) { builder.append("."); String nodeLocalName = pathToNode.get(i).getLocalName(); nodeLocalName = nodeLocalName.replace(":", "."); nodeLocalName = nodeLocalName.replace("-", "."); builder.append(nodeLocalName); } return validateJavaPackage(builder.toString()); } /** * Generates the package name for type definition from * typeDefinition and basePackageName. * * @param basePackageName * string with the package name of the module * @param typeDefinition * type definition for which the package name will be generated * * @return string with valid JAVA package name * @throws IllegalArgumentException *
    *
  • if basePackageName equals null
  • *
  • if typeDefinition equals null
  • *
*/ public static String packageNameForTypeDefinition(final String basePackageName, final TypeDefinition typeDefinition) { if (basePackageName == null) { throw new IllegalArgumentException("Base Package Name cannot be NULL!"); } if (typeDefinition == null) { throw new IllegalArgumentException("Type Definition reference cannot be NULL!"); } final StringBuilder builder = new StringBuilder(); builder.append(basePackageName); return validateJavaPackage(builder.toString()); } /** * Converts token to string which is in accordance with best * practices for JAVA class names. * * @param token * string which contains characters which should be converted to * JAVA class name * @return string which is in accordance with best practices for JAVA class * name. */ public static String parseToClassName(String token) { return parseToCamelCase(token, true); } /** * Converts token to string which is in accordance with best * practices for JAVA parameter names. * * @param token * string which contains characters which should be converted to * JAVA parameter name * @return string which is in accordance with best practices for JAVA * parameter name. */ public static String parseToValidParamName(final String token) { return resolveJavaReservedWordEquivalency(parseToCamelCase(token, false)); } /** * * Converts string token to the cammel case format. * * @param token * string which should be converted to the cammel case format * @param uppercase * boolean value which says whether the first character of the * token should|shuldn't be uppercased * @return string in the cammel case format * @throws IllegalArgumentException *
    *
  • if token without white spaces is empty
  • *
  • if token equals null
  • *
*/ private static String parseToCamelCase(final String token, final boolean uppercase) { if (token == null) { throw new IllegalArgumentException("Name can not be null"); } String correctStr = token.trim(); correctStr = correctStr.replace(".", ""); if (correctStr.isEmpty()) { throw new IllegalArgumentException("Name can not be emty"); } correctStr = replaceWithCamelCase(correctStr, ' '); correctStr = replaceWithCamelCase(correctStr, '-'); correctStr = replaceWithCamelCase(correctStr, '_'); String firstChar = correctStr.substring(0, 1); if (uppercase) { firstChar = firstChar.toUpperCase(); } else { firstChar = firstChar.toLowerCase(); } if (firstChar.matches("[0-9]")) { correctStr = "_" + correctStr; } else { correctStr = firstChar + correctStr.substring(1); } return correctStr; } /** * Replaces all the occurances of the removalChar in the * text with empty string and converts following character to * upper case. * * @param text * string with source text which should be converted * @param removalChar * character which is sought in the text * @return string which doesn't contain removalChar and has * following characters converted to upper case * @throws IllegalArgumentException * if the length of the returning string has length 0 */ private static String replaceWithCamelCase(String text, char removalChar) { StringBuilder sb = new StringBuilder(text); String toBeRemoved = String.valueOf(removalChar); int toBeRemovedPos = sb.indexOf(toBeRemoved); while (toBeRemovedPos != -1) { sb.replace(toBeRemovedPos, toBeRemovedPos + 1, ""); // check if 'toBeRemoved' character is not the only character in // 'text' if (sb.length() == 0) { throw new IllegalArgumentException("The resulting string can not be empty"); } String replacement = String.valueOf(sb.charAt(toBeRemovedPos)).toUpperCase(); sb.setCharAt(toBeRemovedPos, replacement.charAt(0)); toBeRemovedPos = sb.indexOf(toBeRemoved); } return sb.toString(); } public static Restrictions getRestrictions(TypeDefinition type) { final List length = new ArrayList<>(); final List pattern = new ArrayList<>(); final List range = new ArrayList<>(); if (type instanceof ExtendedType) { ExtendedType ext = (ExtendedType)type; length.addAll(ext.getLengthConstraints()); pattern.addAll(ext.getPatternConstraints()); range.addAll(ext.getRangeConstraints()); } return new Restrictions() { @Override public List getRangeConstraints() { return range; } @Override public List getPatternConstraints() { return pattern; } @Override public List getLengthConstraints() { return length; } @Override public boolean isEmpty() { return range.isEmpty() && pattern.isEmpty() && length.isEmpty(); } }; } }