Added serialVersionUID field to classes generated from list key.
[mdsal.git] / code-generator / binding-generator-util / src / main / java / org / opendaylight / yangtools / binding / generator / util / BindingGeneratorUtil.java
index 27961a9065f8f12820aae6ffb06d09ccf2b8e328..57e319f5904aacbf7146988bbd99136d40b52742 100644 (file)
@@ -1,27 +1,46 @@
 package org.opendaylight.yangtools.binding.generator.util;
 
+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.Collections;
+import java.util.Comparator;
 import java.util.HashSet;
 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.MethodSignatureBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.TypeMemberBuilder;
 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.
      */
@@ -46,17 +65,17 @@ public final class BindingGeneratorUtil {
 
     /**
      * Converts string <code>packageName</code> 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.split("\\.");
+            final String[] packNameParts = packageName.toLowerCase().split("\\.");
             if (packNameParts != null) {
                 final StringBuilder builder = new StringBuilder();
                 for (int i = 0; i < packNameParts.length; ++i) {
@@ -79,15 +98,15 @@ public final class BindingGeneratorUtil {
 
     /**
      * Converts <code>parameterName</code> to valid JAVA parameter name.
-     * 
+     *
      * If the <code>parameterName</code> 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 validateParameterName(final String parameterName) {
+    public static String resolveJavaReservedWordEquivalency(final String parameterName) {
         if (parameterName != null && JAVA_RESERVED_WORDS.contains(parameterName)) {
             return "_" + parameterName;
         }
@@ -96,7 +115,7 @@ public final class BindingGeneratorUtil {
 
     /**
      * Converts module name to valid JAVA package name.
-     * 
+     *
      * The package name consists of:
      * <ul>
      * <li>prefix - <i>org.opendaylight.yang.gen.v</i></li>
@@ -105,7 +124,7 @@ public final class BindingGeneratorUtil {
      * <li>revision prefix - <i>.rev</i></li>
      * <li>revision - YYYYMMDD (MM and DD aren't spread to the whole length)</li>
      * </ul>
-     * 
+     *
      * @param module
      *            module which contains data about namespace and revision date
      * @return string with the valid JAVA package name
@@ -141,18 +160,18 @@ public final class BindingGeneratorUtil {
         packageNameBuilder.append(namespace);
         packageNameBuilder.append(".rev");
         packageNameBuilder.append(DATE_FORMAT.format(module.getRevision()));
-        
+
         return validateJavaPackage(packageNameBuilder.toString());
     }
 
     /**
      * Creates package name from specified <code>basePackageName</code> (package
      * name for module) and <code>schemaPath</code>.
-     * 
+     *
      * Resulting package name is concatenation of <code>basePackageName</code>
      * and all local names of YANG nodes which are parents of some node for
      * which <code>schemaPath</code> is specified.
-     * 
+     *
      * @param basePackageName
      *            string with package name of the module
      * @param schemaPath
@@ -186,7 +205,7 @@ public final class BindingGeneratorUtil {
     /**
      * Generates the package name for type definition from
      * <code>typeDefinition</code> and <code>basePackageName</code>.
-     * 
+     *
      * @param basePackageName
      *            string with the package name of the module
      * @param typeDefinition
@@ -215,7 +234,7 @@ public final class BindingGeneratorUtil {
     /**
      * Converts <code>token</code> 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
@@ -223,24 +242,13 @@ public final class BindingGeneratorUtil {
      *         name.
      */
     public static String parseToClassName(String token) {
-        String correctStr = token.replace(".", "");
-        correctStr = parseToCamelCase(correctStr);
-
-        // make first char upper-case
-        char first = Character.toUpperCase(correctStr.charAt(0));
-        if (first >= '0' && first <= '9') {
-
-            correctStr = "_" + correctStr;
-        } else {
-            correctStr = first + correctStr.substring(1);
-        }
-        return correctStr;
+        return parseToCamelCase(token, true);
     }
 
     /**
      * Converts <code>token</code> 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
@@ -248,36 +256,18 @@ public final class BindingGeneratorUtil {
      *         parameter name.
      */
     public static String parseToValidParamName(final String token) {
-        final String validToken = token.replace(".", "");
-        String correctStr = parseToCamelCase(validToken);
-
-        // make first char lower-case
-        char first = Character.toLowerCase(correctStr.charAt(0));
-        correctStr = first + correctStr.substring(1);
-        return validateParameterName(correctStr);
+        return resolveJavaReservedWordEquivalency(parseToCamelCase(token, false));
     }
 
     /**
-     * Converts <code>token</code> to capital letters and removes invalid
-     * characters.
-     * 
-     * @param token
-     *            string with characters which should be conversed to capital
-     * @return string with capital letters
-     */
-    public static String convertToCapitalLetters(final String token) {
-        String convertedStr = token.replace(" ", "_");
-        convertedStr = convertedStr.replace(".", "_");
-        convertedStr = convertedStr.toUpperCase();
-        return convertedStr;
-    }
-
-    /**
-     * 
+     *
      * Converts string <code>token</code> 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
+     *            <code>token</code> should|shuldn't be uppercased
      * @return string in the cammel case format
      * @throws IllegalArgumentException
      *             <ul>
@@ -285,12 +275,15 @@ public final class BindingGeneratorUtil {
      *             <li>if <code>token</code> equals null</li>
      *             </ul>
      */
-    private static String parseToCamelCase(String token) {
+
+    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");
         }
@@ -298,6 +291,19 @@ public final class BindingGeneratorUtil {
         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;
     }
 
@@ -305,7 +311,7 @@ public final class BindingGeneratorUtil {
      * Replaces all the occurances of the <code>removalChar</code> in the
      * <code>text</code> with empty string and converts following character to
      * upper case.
-     * 
+     *
      * @param text
      *            string with source text which should be converted
      * @param removalChar
@@ -333,4 +339,94 @@ public final class BindingGeneratorUtil {
         }
         return sb.toString();
     }
+
+    public static long computeDefaultSUID(GeneratedTOBuilderImpl to) {
+        try {
+            ByteArrayOutputStream bout = new ByteArrayOutputStream();
+            DataOutputStream dout = new DataOutputStream(bout);
+
+            dout.writeUTF(to.getName());
+            dout.writeInt(to.isAbstract() ? 3 : 7);
+
+            List<Type> impl = to.getImplementsTypes();
+            Collections.sort(impl, new Comparator<Type>() {
+                @Override
+                public int compare(Type o1, Type o2) {
+                    return o1.getFullyQualifiedName().compareTo(o2.getFullyQualifiedName());
+                }
+            });
+            for (Type ifc : impl) {
+                dout.writeUTF(ifc.getFullyQualifiedName());
+            }
+
+            Comparator<TypeMemberBuilder<?>> comparator = new Comparator<TypeMemberBuilder<?>>() {
+                @Override
+                public int compare(TypeMemberBuilder<?> o1, TypeMemberBuilder<?> o2) {
+                    return o1.getName().compareTo(o2.getName());
+                }
+            };
+
+            List<GeneratedPropertyBuilder> props = to.getProperties();
+            Collections.sort(props, comparator);
+            for (GeneratedPropertyBuilder gp : props) {
+                dout.writeUTF(gp.getName());
+            }
+
+            List<MethodSignatureBuilder> methods = to.getMethodDefinitions();
+            Collections.sort(methods, comparator);
+            for (MethodSignatureBuilder m : methods) {
+                if (!(m.getAccessModifier().equals(AccessModifier.PRIVATE))) {
+                    dout.writeUTF(m.getName());
+                    dout.write(m.getAccessModifier().ordinal());
+                }
+            }
+
+            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);
+            }
+            return hash;
+        } catch (IOException ex) {
+            throw new InternalError();
+        } catch (NoSuchAlgorithmException ex) {
+            throw new SecurityException(ex.getMessage());
+        }
+    }
+
+    public static Restrictions getRestrictions(TypeDefinition<?> type) {
+        final List<LengthConstraint> length = new ArrayList<>();
+        final List<PatternConstraint> pattern = new ArrayList<>();
+        final List<RangeConstraint> 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<RangeConstraint> getRangeConstraints() {
+                return range;
+            }
+            @Override
+            public List<PatternConstraint> getPatternConstraints() {
+                return pattern;
+            }
+            @Override
+            public List<LengthConstraint> getLengthConstraints() {
+                return length;
+            }
+            @Override
+            public boolean isEmpty() {
+                return range.isEmpty() && pattern.isEmpty() && length.isEmpty();
+            }
+        };
+    }
+
 }