/*
 * This file is released under terms of BSD license
 * See LICENSE file for more information
 */
package claw.tatsu.xcodeml.xnode.fortran;

import claw.tatsu.xcodeml.xnode.Xname;

import java.util.Random;

/**
 * Enum representing the type coming from OMNI Compiler.
 *
 * @author clementval
 */
public enum FortranType {

  // Type prefix from OMNI Compiler. Taken for the F-output-xcodeml.c file.
  ARRAY('A', ""),
  CHARACTER('C', Xname.TYPE_F_CHAR),
  COMPLEX('P', Xname.TYPE_F_COMPLEX),
  FUNCTION('F', ""),
  INTEGER('I', Xname.TYPE_F_INT),
  REAL('R', Xname.TYPE_F_REAL),
  LOGICAL('L', Xname.TYPE_F_LOGICAL),
  STRUCT('S', ""),
  VOID('V', Xname.TYPE_F_VOID),
  NONE('N', "");

  // Java 1.8 should use SecureRandom
  private final Random rand = new Random();

  private static final int HASH_LENGTH = 12;
  private final char _prefix;
  private final String _irValue;

  FortranType(char prefix, String type) {
    _prefix = prefix;
    _irValue = type;
  }

  /**
   * Check whether the given type is a built-in type or is a type defined in the
   * type table.
   *
   * @param type Type to check.
   * @return True if the type is built-in. False otherwise.
   */
  public static boolean isBuiltInType(String type) {
    if(type == null) {
      return false;
    }
    switch(type) {
      case Xname.TYPE_F_CHAR:
      case Xname.TYPE_F_COMPLEX:
      case Xname.TYPE_F_INT:
      case Xname.TYPE_F_LOGICAL:
      case Xname.TYPE_F_REAL:
      case Xname.TYPE_F_VOID:
        return true;
      default:
        return false;
    }
  }

  /**
   * Get type from XcodeML/F IR value.
   *
   * @param value Type value from XcodeML/F IR.
   * @return Corresponding enum value. NONE if value corresponds to nothing.
   */
  public static FortranType fromString(String value) {
    if(value == null) {
      return NONE;
    }
    switch(value) {
      case Xname.TYPE_F_INT:
        return INTEGER;
      case Xname.TYPE_F_REAL:
        return REAL;
      case Xname.TYPE_F_COMPLEX:
        return COMPLEX;
      case Xname.TYPE_F_LOGICAL:
        return LOGICAL;
      case Xname.TYPE_F_CHAR:
        return CHARACTER;
      case Xname.TYPE_F_VOID:
        return VOID;
      default:
        return NONE;
    }
  }

  /**
   * Get a new unique hash with the current FortranType prefix.
   *
   * @return New unique hash.
   */
  public String generateHash() {
    return _prefix + generateHash(HASH_LENGTH);
  }

  /**
   * Generate a new unique type hash for the table.
   *
   * @param length Length of the hash string to be generated.
   * @return The new unique hash.
   */
  private String generateHash(int length) {
    StringBuilder sb = new StringBuilder();
    while(sb.length() < length) {
      sb.append(Integer.toHexString(this.rand.nextInt()));
    }
    return sb.toString().substring(0, length);
  }

  /**
   * Check whether the giving hash is from the current type.
   *
   * @param hash Hash to be checked.
   * @return True if the hash is of current type. False otherwise.
   */
  public boolean isOfType(String hash) {
    return hash != null && !hash.isEmpty()
        && (hash.charAt(0) == _prefix || hash.equals(_irValue));
  }

  @Override
  public String toString() {
    return _irValue.isEmpty() ? null : _irValue;
  }
}

@@ -2311,17 +2311,21 @@
 @return 
-N
+The n
 ew uniqu
@@ -2379,270 +2379,8 @@
     
-return _prefix + generateHash(HASH_LENGTH);%0A  %7D%0A%0A  /**%0A   * Generate a new unique type hash for the table.%0A   *%0A   * @param length Length of the hash string to be generated.%0A   * @return The new unique hash.%0A   */%0A  private String generateHash(int length) %7B%0A    
 Stri
@@ -2412,16 +2412,40 @@
 Builder(
+);%0A    sb.append(_prefix
 );%0A    w
@@ -2463,22 +2463,27 @@
 gth() %3C 
-length
+HASH_LENGTH
 ) %7B%0A    
@@ -2581,22 +2581,27 @@
 ring(0, 
-length
+HASH_LENGTH
 );%0A  %7D%0A%0A

Simplify generateHash