X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=code-generator%2Fbinding-generator-util%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fbinding%2Fgenerator%2Futil%2FBindingGeneratorUtil.java;h=41bcb83c71d01d33513d1c26f04602813c31d08f;hb=refs%2Fchanges%2F59%2F12159%2F3;hp=57e319f5904aacbf7146988bbd99136d40b52742;hpb=ebe09fa86aeeb694c758a4f1ea6a152023fde3f7;p=yangtools.git diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/BindingGeneratorUtil.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/BindingGeneratorUtil.java index 57e319f590..41bcb83c71 100644 --- a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/BindingGeneratorUtil.java +++ b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/BindingGeneratorUtil.java @@ -1,34 +1,44 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ package org.opendaylight.yangtools.binding.generator.util; +import com.google.common.base.CharMatcher; +import com.google.common.collect.Iterables; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.text.DateFormat; -import java.text.SimpleDateFormat; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; -import java.util.HashSet; +import java.util.Iterator; import java.util.List; -import java.util.Set; - -import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl; import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier; import org.opendaylight.yangtools.sal.binding.model.api.Restrictions; import org.opendaylight.yangtools.sal.binding.model.api.Type; import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPropertyBuilder; +import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilderBase; import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSignatureBuilder; import org.opendaylight.yangtools.sal.binding.model.api.type.builder.TypeMemberBuilder; +import org.opendaylight.yangtools.yang.binding.BindingMapping; import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.QNameModule; 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.DecimalTypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition; 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.api.type.UnsignedIntegerTypeDefinition; import org.opendaylight.yangtools.yang.model.util.ExtendedType; /** @@ -39,18 +49,6 @@ import org.opendaylight.yangtools.yang.model.util.ExtendedType; */ 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. @@ -59,42 +57,46 @@ public final class BindingGeneratorUtil { } /** - * Hash set of words which are reserved in JAVA language. + * Pre-compiled replacement pattern. */ - private static final Set JAVA_RESERVED_WORDS = new HashSet(Arrays.asList(SET_VALUES)); + private static final CharMatcher DOT_MATCHER = CharMatcher.is('.'); + private static final CharMatcher DASH_COLON_MATCHER = CharMatcher.anyOf("-:"); - /** - * 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(); - } + private static final Restrictions EMPTY_RESTRICTIONS = new Restrictions() { + @Override + public List getLengthConstraints() { + return Collections.emptyList(); } - return packageName; - } + + @Override + public List getPatternConstraints() { + return Collections.emptyList(); + } + + @Override + public List getRangeConstraints() { + return Collections.emptyList(); + } + + @Override + public boolean isEmpty() { + return true; + } + }; + + private static final Comparator> SUID_MEMBER_COMPARATOR = new Comparator>() { + @Override + public int compare(final TypeMemberBuilder o1, final TypeMemberBuilder o2) { + return o1.getName().compareTo(o2.getName()); + } + }; + + private static final Comparator SUID_NAME_COMPARATOR = new Comparator() { + @Override + public int compare(final Type o1, final Type o2) { + return o1.getFullyQualifiedName().compareTo(o2.getFullyQualifiedName()); + } + }; /** * Converts parameterName to valid JAVA parameter name. @@ -107,7 +109,7 @@ public final class BindingGeneratorUtil { * @return string with the admissible parameter name */ public static String resolveJavaReservedWordEquivalency(final String parameterName) { - if (parameterName != null && JAVA_RESERVED_WORDS.contains(parameterName)) { + if (parameterName != null && BindingMapping.JAVA_RESERVED_WORDS.contains(parameterName)) { return "_" + parameterName; } return parameterName; @@ -131,37 +133,15 @@ public final class BindingGeneratorUtil { * @throws IllegalArgumentException * if the revision date of the module equals * null + * @deprecated USe {@link BindingMapping#getRootPackageName(QNameModule)} with {@link Module#getQNameModule()}. */ + @Deprecated public static String moduleNamespaceToPackageName(final Module module) { - final StringBuilder packageNameBuilder = new StringBuilder(); + return BindingMapping.getRootPackageName(module.getQNameModule()); + } - 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()); + public static String packageNameForGeneratedType(final String basePackageName, final SchemaPath schemaPath) { + return packageNameForGeneratedType(basePackageName, schemaPath, false); } /** @@ -179,7 +159,8 @@ public final class BindingGeneratorUtil { * name of this node * @return string with valid JAVA package name */ - public static String packageNameForGeneratedType(final String basePackageName, final SchemaPath schemaPath) { + public static String packageNameForGeneratedType(final String basePackageName, final SchemaPath schemaPath, + final boolean isUsesAugment) { if (basePackageName == null) { throw new IllegalArgumentException("Base Package Name cannot be NULL!"); } @@ -189,17 +170,22 @@ public final class BindingGeneratorUtil { final StringBuilder builder = new StringBuilder(); builder.append(basePackageName); - final List pathToNode = schemaPath.getPath(); - final int traversalSteps = (pathToNode.size() - 1); + final Iterable iterable = schemaPath.getPathFromRoot(); + final Iterator iterator = iterable.iterator(); + int size = Iterables.size(iterable); + final int traversalSteps; + if (isUsesAugment) { + traversalSteps = size; + } else { + traversalSteps = 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); + builder.append('.'); + String nodeLocalName = iterator.next().getLocalName(); + // FIXME: Collon ":" is invalid in node local name as per RFC6020, identifier statement. + builder.append(DASH_COLON_MATCHER.replaceFrom(nodeLocalName, '.')); } - return validateJavaPackage(builder.toString()); + return BindingMapping.normalizePackageName(builder.toString()); } /** @@ -228,7 +214,7 @@ public final class BindingGeneratorUtil { final StringBuilder builder = new StringBuilder(); builder.append(basePackageName); - return validateJavaPackage(builder.toString()); + return BindingMapping.normalizePackageName(builder.toString()); } /** @@ -240,8 +226,11 @@ public final class BindingGeneratorUtil { * JAVA class name * @return string which is in accordance with best practices for JAVA class * name. + * + * @deprecated Use {@link BindingMapping#getClassName(QName)} instead. */ - public static String parseToClassName(String token) { + @Deprecated + public static String parseToClassName(final String token) { return parseToCamelCase(token, true); } @@ -254,8 +243,10 @@ public final class BindingGeneratorUtil { * JAVA parameter name * @return string which is in accordance with best practices for JAVA * parameter name. + * + * @deprecated Use {@link BindingMapping#getPropertyName(String)} instead. */ - public static String parseToValidParamName(final String token) { + @Deprecated public static String parseToValidParamName(final String token) { return resolveJavaReservedWordEquivalency(parseToCamelCase(token, false)); } @@ -281,34 +272,27 @@ public final class BindingGeneratorUtil { throw new IllegalArgumentException("Name can not be null"); } - String correctStr = token.trim(); - correctStr = correctStr.replace(".", ""); - + String correctStr = DOT_MATCHER.removeFrom(token.trim()); if (correctStr.isEmpty()) { - throw new IllegalArgumentException("Name can not be emty"); + throw new IllegalArgumentException("Name can not be empty"); } correctStr = replaceWithCamelCase(correctStr, ' '); correctStr = replaceWithCamelCase(correctStr, '-'); correctStr = replaceWithCamelCase(correctStr, '_'); - String firstChar = correctStr.substring(0, 1); - if (uppercase) { - firstChar = firstChar.toUpperCase(); - } else { - firstChar = firstChar.toLowerCase(); - } + char firstChar = correctStr.charAt(0); + firstChar = uppercase ? Character.toUpperCase(firstChar) : Character.toLowerCase(firstChar); - if (firstChar.matches("[0-9]")) { - correctStr = "_" + correctStr; + if (firstChar >= '0' && firstChar <= '9') { + return correctStr = '_' + correctStr; } else { - correctStr = firstChar + correctStr.substring(1); + return correctStr = firstChar + correctStr.substring(1); } - return correctStr; } /** - * Replaces all the occurances of the removalChar in the + * Replaces all the occurrences of the removalChar in the * text with empty string and converts following character to * upper case. * @@ -321,26 +305,40 @@ public final class BindingGeneratorUtil { * @throws IllegalArgumentException * if the length of the returning string has length 0 */ - private static String replaceWithCamelCase(String text, char removalChar) { + private static String replaceWithCamelCase(final String text, final char removalChar) { + int toBeRemovedPos = text.indexOf(removalChar); + if (toBeRemovedPos == -1) { + return text; + } + StringBuilder sb = new StringBuilder(text); String toBeRemoved = String.valueOf(removalChar); - - int toBeRemovedPos = sb.indexOf(toBeRemoved); - while (toBeRemovedPos != -1) { + do { 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)); + char replacement = Character.toUpperCase(sb.charAt(toBeRemovedPos)); + sb.setCharAt(toBeRemovedPos, replacement); toBeRemovedPos = sb.indexOf(toBeRemoved); - } + } while (toBeRemovedPos != -1); + return sb.toString(); } - public static long computeDefaultSUID(GeneratedTOBuilderImpl to) { + private static Iterable sortedCollection(final Comparator comparator, final Collection input) { + if (input.size() > 1) { + final List ret = new ArrayList<>(input); + Collections.sort(ret, comparator); + return ret; + } else { + return input; + } + } + + public static long computeDefaultSUID(final GeneratedTypeBuilderBase to) { try { ByteArrayOutputStream bout = new ByteArrayOutputStream(); DataOutputStream dout = new DataOutputStream(bout); @@ -348,33 +346,15 @@ public final class BindingGeneratorUtil { dout.writeUTF(to.getName()); dout.writeInt(to.isAbstract() ? 3 : 7); - List impl = to.getImplementsTypes(); - Collections.sort(impl, new Comparator() { - @Override - public int compare(Type o1, Type o2) { - return o1.getFullyQualifiedName().compareTo(o2.getFullyQualifiedName()); - } - }); - for (Type ifc : impl) { + for (Type ifc : sortedCollection(SUID_NAME_COMPARATOR, to.getImplementsTypes())) { dout.writeUTF(ifc.getFullyQualifiedName()); } - Comparator> comparator = new Comparator>() { - @Override - public int compare(TypeMemberBuilder o1, TypeMemberBuilder o2) { - return o1.getName().compareTo(o2.getName()); - } - }; - - List props = to.getProperties(); - Collections.sort(props, comparator); - for (GeneratedPropertyBuilder gp : props) { + for (GeneratedPropertyBuilder gp : sortedCollection(SUID_MEMBER_COMPARATOR, to.getProperties())) { dout.writeUTF(gp.getName()); } - List methods = to.getMethodDefinitions(); - Collections.sort(methods, comparator); - for (MethodSignatureBuilder m : methods) { + for (MethodSignatureBuilder m : sortedCollection(SUID_MEMBER_COMPARATOR, to.getMethodDefinitions())) { if (!(m.getAccessModifier().equals(AccessModifier.PRIVATE))) { dout.writeUTF(m.getName()); dout.write(m.getAccessModifier().ordinal()); @@ -383,32 +363,52 @@ public final class BindingGeneratorUtil { dout.flush(); - MessageDigest md = MessageDigest.getInstance("SHA"); - byte[] hashBytes = md.digest(bout.toByteArray()); - long hash = 0; - for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) { - hash = (hash << 8) | (hashBytes[i] & 0xFF); + try { + MessageDigest md = MessageDigest.getInstance("SHA"); + byte[] hashBytes = md.digest(bout.toByteArray()); + long hash = 0; + for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) { + hash = (hash << 8) | (hashBytes[i] & 0xFF); + } + return hash; + } catch (NoSuchAlgorithmException ex) { + throw new SecurityException(ex.getMessage()); } - return hash; } catch (IOException ex) { throw new InternalError(); - } catch (NoSuchAlgorithmException ex) { - throw new SecurityException(ex.getMessage()); } } - public static Restrictions getRestrictions(TypeDefinition type) { - final List length = new ArrayList<>(); - final List pattern = new ArrayList<>(); - final List range = new ArrayList<>(); + public static Restrictions getRestrictions(final TypeDefinition type) { + // Base types have no constraints, so get over it quickly + if (!(type instanceof ExtendedType)) { + return EMPTY_RESTRICTIONS; + } + + // Take care of the extended types ... + final ExtendedType ext = (ExtendedType)type; + final List length = ext.getLengthConstraints(); + final List pattern = ext.getPatternConstraints(); + + List tmp = ext.getRangeConstraints(); + if (tmp.isEmpty()) { + final TypeDefinition base = ext.getBaseType(); + if (base instanceof IntegerTypeDefinition) { + tmp = ((IntegerTypeDefinition)base).getRangeConstraints(); + } else if (base instanceof UnsignedIntegerTypeDefinition) { + tmp = ((UnsignedIntegerTypeDefinition)base).getRangeConstraints(); + } else if (base instanceof DecimalTypeDefinition) { + tmp = ((DecimalTypeDefinition)base).getRangeConstraints(); + } + } - if (type instanceof ExtendedType) { - ExtendedType ext = (ExtendedType)type; - length.addAll(ext.getLengthConstraints()); - pattern.addAll(ext.getPatternConstraints()); - range.addAll(ext.getRangeConstraints()); + // Now, this may have ended up being empty, too... + if (length.isEmpty() && pattern.isEmpty() && tmp.isEmpty()) { + return EMPTY_RESTRICTIONS; } + // Nope, not empty allocate a holder + final List range = tmp; return new Restrictions() { @Override public List getRangeConstraints() { @@ -424,7 +424,7 @@ public final class BindingGeneratorUtil { } @Override public boolean isEmpty() { - return range.isEmpty() && pattern.isEmpty() && length.isEmpty(); + return false; } }; }