/**
  * Replaces all the occurrences of variables in the given source object with their matching values
  * from the resolver. The input source object is converted to a string using <code>toString</code>
  * and is not altered.
  *
  * @param source the source to replace in, null returns null
  * @return the result of the replace operation
  */
 public String replace(final Object source) {
   if (source == null) {
     return null;
   }
   final StrBuilder buf = new StrBuilder().append(source);
   substitute(buf, 0, buf.length());
   return buf.toString();
 }
 /**
  * Replaces all the occurrences of variables with their matching values from the resolver using
  * the given source builder as a template. The builder is not altered by this method.
  *
  * <p>Only the specified portion of the builder will be processed. The rest of the builder is not
  * processed, and is not returned.
  *
  * @param source the builder to use as a template, not changed, null returns null
  * @param offset the start offset within the array, must be valid
  * @param length the length within the array to be processed, must be valid
  * @return the result of the replace operation
  */
 public String replace(final StrBuilder source, final int offset, final int length) {
   if (source == null) {
     return null;
   }
   final StrBuilder buf = new StrBuilder(length).append(source, offset, length);
   substitute(buf, 0, length);
   return buf.toString();
 }
 /**
  * Replaces all the occurrences of variables with their matching values from the resolver using
  * the given source array as a template. The array is not altered by this method.
  *
  * @param source the character array to replace in, not altered, null returns null
  * @return the result of the replace operation
  */
 public String replace(final char[] source) {
   if (source == null) {
     return null;
   }
   final StrBuilder buf = new StrBuilder(source.length).append(source);
   substitute(buf, 0, source.length);
   return buf.toString();
 }
 /**
  * Replaces all the occurrences of variables with their matching values from the resolver using
  * the given source string as a template.
  *
  * <p>Only the specified portion of the string will be processed. The rest of the string is not
  * processed, and is not returned.
  *
  * @param source the string to replace in, null returns null
  * @param offset the start offset within the array, must be valid
  * @param length the length within the array to be processed, must be valid
  * @return the result of the replace operation
  */
 public String replace(final String source, final int offset, final int length) {
   if (source == null) {
     return null;
   }
   final StrBuilder buf = new StrBuilder(length).append(source, offset, length);
   if (substitute(buf, 0, length) == false) {
     return source.substring(offset, offset + length);
   }
   return buf.toString();
 }
 /**
  * Replaces all the occurrences of variables with their matching values from the resolver using
  * the given source string as a template.
  *
  * @param source the string to replace in, null returns null
  * @return the result of the replace operation
  */
 public String replace(final String source) {
   if (source == null) {
     return null;
   }
   final StrBuilder buf = new StrBuilder(source);
   if (substitute(buf, 0, source.length()) == false) {
     return source;
   }
   return buf.toString();
 }
 /**
  * Replaces all the occurrences of variables within the given source builder with their matching
  * values from the resolver. The builder is updated with the result.
  *
  * <p>Only the specified portion of the buffer will be processed. The rest of the buffer is not
  * processed, but it is not deleted.
  *
  * @param source the buffer to replace in, updated, null returns zero
  * @param offset the start offset within the array, must be valid
  * @param length the length within the buffer to be processed, must be valid
  * @return true if altered
  * @since 3.2
  */
 public boolean replaceIn(final StringBuilder source, final int offset, final int length) {
   if (source == null) {
     return false;
   }
   final StrBuilder buf = new StrBuilder(length).append(source, offset, length);
   if (substitute(buf, 0, length) == false) {
     return false;
   }
   source.replace(offset, offset + length, buf.toString());
   return true;
 }
 /**
  * Checks if the specified variable is already in the stack (list) of variables.
  *
  * @param varName the variable name to check
  * @param priorVariables the list of prior variables
  */
 private void checkCyclicSubstitution(final String varName, final List<String> priorVariables) {
   if (priorVariables.contains(varName) == false) {
     return;
   }
   final StrBuilder buf = new StrBuilder(256);
   buf.append("Infinite loop in property interpolation of ");
   buf.append(priorVariables.remove(0));
   buf.append(": ");
   buf.appendWithSeparators(priorVariables, "->");
   throw new IllegalStateException(buf.toString());
 }
  /**
   * Recursive handler for multiple levels of interpolation. This is the main interpolation method,
   * which resolves the values of all variable references contained in the passed in text.
   *
   * @param buf the string builder to substitute into, not null
   * @param offset the start offset within the builder, must be valid
   * @param length the length within the builder to be processed, must be valid
   * @param priorVariables the stack keeping track of the replaced variables, may be null
   * @return the length change that occurs, unless priorVariables is null when the int represents a
   *     boolean flag as to whether any change occurred.
   */
  private int substitute(
      final StrBuilder buf, final int offset, final int length, List<String> priorVariables) {
    final StrMatcher pfxMatcher = getVariablePrefixMatcher();
    final StrMatcher suffMatcher = getVariableSuffixMatcher();
    final char escape = getEscapeChar();
    final StrMatcher valueDelimMatcher = getValueDelimiterMatcher();
    final boolean substitutionInVariablesEnabled = isEnableSubstitutionInVariables();

    final boolean top = priorVariables == null;
    boolean altered = false;
    int lengthChange = 0;
    char[] chars = buf.buffer;
    int bufEnd = offset + length;
    int pos = offset;
    while (pos < bufEnd) {
      final int startMatchLen = pfxMatcher.isMatch(chars, pos, offset, bufEnd);
      if (startMatchLen == 0) {
        pos++;
      } else {
        // found variable start marker
        if (pos > offset && chars[pos - 1] == escape) {
          // escaped
          buf.deleteCharAt(pos - 1);
          chars = buf.buffer; // in case buffer was altered
          lengthChange--;
          altered = true;
          bufEnd--;
        } else {
          // find suffix
          final int startPos = pos;
          pos += startMatchLen;
          int endMatchLen = 0;
          int nestedVarCount = 0;
          while (pos < bufEnd) {
            if (substitutionInVariablesEnabled
                && (endMatchLen = pfxMatcher.isMatch(chars, pos, offset, bufEnd)) != 0) {
              // found a nested variable start
              nestedVarCount++;
              pos += endMatchLen;
              continue;
            }

            endMatchLen = suffMatcher.isMatch(chars, pos, offset, bufEnd);
            if (endMatchLen == 0) {
              pos++;
            } else {
              // found variable end marker
              if (nestedVarCount == 0) {
                String varNameExpr =
                    new String(chars, startPos + startMatchLen, pos - startPos - startMatchLen);
                if (substitutionInVariablesEnabled) {
                  final StrBuilder bufName = new StrBuilder(varNameExpr);
                  substitute(bufName, 0, bufName.length());
                  varNameExpr = bufName.toString();
                }
                pos += endMatchLen;
                final int endPos = pos;

                String varName = varNameExpr;
                String varDefaultValue = null;

                if (valueDelimMatcher != null) {
                  final char[] varNameExprChars = varNameExpr.toCharArray();
                  int valueDelimiterMatchLen = 0;
                  for (int i = 0; i < varNameExprChars.length; i++) {
                    // if there's any nested variable when nested variable substitution disabled,
                    // then stop resolving name and default value.
                    if (!substitutionInVariablesEnabled
                        && pfxMatcher.isMatch(varNameExprChars, i, i, varNameExprChars.length)
                            != 0) {
                      break;
                    }
                    if ((valueDelimiterMatchLen = valueDelimMatcher.isMatch(varNameExprChars, i))
                        != 0) {
                      varName = varNameExpr.substring(0, i);
                      varDefaultValue = varNameExpr.substring(i + valueDelimiterMatchLen);
                      break;
                    }
                  }
                }

                // on the first call initialize priorVariables
                if (priorVariables == null) {
                  priorVariables = new ArrayList<String>();
                  priorVariables.add(new String(chars, offset, length));
                }

                // handle cyclic substitution
                checkCyclicSubstitution(varName, priorVariables);
                priorVariables.add(varName);

                // resolve the variable
                String varValue = resolveVariable(varName, buf, startPos, endPos);
                if (varValue == null) {
                  varValue = varDefaultValue;
                }
                if (varValue != null) {
                  // recursive replace
                  final int varLen = varValue.length();
                  buf.replace(startPos, endPos, varValue);
                  altered = true;
                  int change = substitute(buf, startPos, varLen, priorVariables);
                  change = change + varLen - (endPos - startPos);
                  pos += change;
                  bufEnd += change;
                  lengthChange += change;
                  chars = buf.buffer; // in case buffer was
                  // altered
                }

                // remove variable from the cyclic stack
                priorVariables.remove(priorVariables.size() - 1);
                break;
              }
              nestedVarCount--;
              pos += endMatchLen;
            }
          }
        }
      }
    }
    if (top) {
      return altered ? 1 : 0;
    }
    return lengthChange;
  }
 /**
  * Replaces all the occurrences of variables within the given source builder with their matching
  * values from the resolver.
  *
  * @param source the builder to replace in, updated, null returns zero
  * @return true if altered
  */
 public boolean replaceIn(final StrBuilder source) {
   if (source == null) {
     return false;
   }
   return substitute(source, 0, source.length());
 }
示例#10
0
  public static void dumpClass(Class<?> cls) {
    xlog.INSTANCE.d("Dump Class Methods: ", cls.getName());
    StrBuilder sb = new StrBuilder(128);
    Field[] fs = cls.getDeclaredFields();
    Arrays.sort(
        fs,
        new Comparator<Field>() {

          @Override
          public int compare(Field lhs, Field rhs) {
            boolean s1 = Modifier.isStatic(lhs.getModifiers());
            boolean s2 = Modifier.isStatic(rhs.getModifiers());
            if (s1 && !s2) {
              return -1;
            }
            if (!s1 && s2) {
              return 1;
            }
            return lhs.getName().compareTo(rhs.getName());
          }
        });
    Method[] ms = cls.getDeclaredMethods();
    Arrays.sort(
        ms,
        new Comparator<Method>() {

          @Override
          public int compare(Method lhs, Method rhs) {
            boolean s1 = Modifier.isStatic(lhs.getModifiers());
            boolean s2 = Modifier.isStatic(rhs.getModifiers());
            if (s1 && !s2) {
              return -1;
            }
            if (!s1 && s2) {
              return 1;
            }

            return lhs.getName().compareTo(rhs.getName());
          }
        });
    for (Field f : fs) {
      sb.clear();
      int mod = f.getModifiers();
      if (Modifier.isPublic(mod)) {
        sb.append("public ");
      } else if (Modifier.isPrivate(mod)) {
        sb.append("private ");
      } else if (Modifier.isProtected(mod)) {
        sb.append("protected ");
      }
      boolean isStatic = Modifier.isStatic(f.getModifiers());
      if (isStatic) {
        sb.append("static ");
      }
      sb.append(f.getType().getSimpleName(), " ");
      sb.append(f.getName());
      if (isStatic) {
        sb.append(" = ", getStatic(cls, f.getName()));
      }
      xlog.INSTANCE.d(sb.toString());
    }

    for (Method m : ms) {
      sb.clear();
      if (Modifier.isPublic(m.getModifiers())) {
        sb.append("public ");
      }
      if (Modifier.isStatic(m.getModifiers())) {
        sb.append("static ");
      }
      sb.append(m.getReturnType().getSimpleName(), " ");
      sb.append(m.getName());
      sb.append("(");
      boolean first = true;
      for (Class<?> p : m.getParameterTypes()) {
        if (first) {
          first = false;
        } else {
          sb.append(",");
        }
        sb.append(p.getSimpleName());
      }
      sb.append(");");
      xlog.INSTANCE.d(sb.toString());
    }
  }