/**
   * Returns a map of public static final integer fields in the specified classes, to their String
   * representations. An optional filter can be specified to only include specific fields. The
   * target map may be null, in which case a new map is allocated and returned.
   *
   * <p>This method is useful when debugging to quickly identify values returned from the AL/GL/CL
   * APIs.
   *
   * @param filter the filter to use (optional)
   * @param target the target map (optional)
   * @param tokenClasses the classes to get tokens from
   * @return the token map
   */
  public static Map<Integer, String> getClassTokens(
      final TokenFilter filter, Map<Integer, String> target, final Iterable<Class> tokenClasses) {
    if (target == null) target = new HashMap<Integer, String>();

    final int TOKEN_MODIFIERS = Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL;

    for (final Class tokenClass : tokenClasses) {
      for (final Field field : tokenClass.getDeclaredFields()) {
        // Get only <public static final int> fields.
        if ((field.getModifiers() & TOKEN_MODIFIERS) == TOKEN_MODIFIERS
            && field.getType() == int.class) {
          try {
            final int value = field.getInt(null);
            if (filter != null && !filter.accept(field, value)) continue;

            if (target.containsKey(value)) // Print colliding tokens in their hex representation.
            target.put(value, toHexString(value));
            else target.put(value, field.getName());
          } catch (IllegalAccessException e) {
            // Ignore
          }
        }
      }
    }

    return target;
  }