class PropertyHelper {

  public static String getPropertyCategory(String property) {
    int lastPathSep = -1;

    if( !containsArguments(property) ){
      lastPathSep = property.lastIndexOf(EXTERNAL_PATH_SEP);
      return lastPathSep == -1 ? null : property.substring(0, lastPathSep);
    }

    // attempt to split the property into its parts
    String[] tokens = METRIC_CATEGORY_TOKENIZE_REGEX.split(property);
    if (null == tokens || tokens.length == 0) {
      return null;
    }

    StringBuilder categoryBuilder = new StringBuilder();
    for (int i = 0; i < tokens.length - 1; i++) {
      String token = tokens[i];

      // if the token contains arguments, turn $1.method() into $1,
      if (containsArguments(token)) {
        int methodIndex = token.indexOf('.');

        if (methodIndex != -1) {
          // normally knowing where $1.method() is would be enough, but some
          // properties may omit the / (like FLUME) so the property would look
          // like /$1.method()FailureCount instead of /$1.method()/FailureCount
          int parensIndex = token.lastIndexOf(')');
          if (parensIndex < token.length() - 1) {
            // cut out $1
            String temp = token.substring(0, methodIndex);

            // append FailureCount
            temp += token.substring(parensIndex + 1);

            // $1.method()FailureCount -> $1FailureCount
            token = temp;
          } else {
            token = token.substring(0, methodIndex);
          }
        }
      }

      // only append a / if this is not the last part of the parent category
      categoryBuilder.append(token);
      if (i < tokens.length - 2) {
        categoryBuilder.append('/');
      }
    }

    String category = categoryBuilder.toString();
    return category;
  }

}