/**
   * Returns a <code>String</code> that describes this shaper. This method is used for debugging
   * purposes only.
   *
   * @return a <code>String</code> describing this shaper.
   */
  public String toString() {
    StringBuilder buf = new StringBuilder(super.toString());

    buf.append("[contextual:").append(isContextual());

    String[] keyNames = null;
    if (isContextual()) {
      buf.append(", context:");
      buf.append(shapingRange == null ? Range.values()[key] : shapingRange);
    }

    if (rangeSet == null) {
      buf.append(", range(s): ");
      boolean first = true;
      for (int i = 0; i < NUM_KEYS; ++i) {
        if ((mask & (1 << i)) != 0) {
          if (first) {
            first = false;
          } else {
            buf.append(", ");
          }
          buf.append(Range.values()[i]);
        }
      }
    } else {
      buf.append(", range set: ").append(rangeSet);
    }
    buf.append(']');

    return buf.toString();
  }
 private static Set<Range> maskToRangeSet(int mask) {
   Set<Range> set = EnumSet.noneOf(Range.class);
   Range[] a = Range.values();
   for (int i = 0; i < NUM_KEYS; i++) {
     if ((mask & (1 << i)) != 0) {
       set.add(a[i]);
     }
   }
   return set;
 }
 /**
  * Converts the digits in the text that occur between start and start + count, using the provided
  * context. Context is ignored if the shaper is not a contextual shaper.
  *
  * @param text an array of characters
  * @param start the index into <code>text</code> to start converting
  * @param count the number of characters in <code>text</code> to convert
  * @param context the context to which to convert the characters, such as <code>
  *     NumericShaper.EUROPEAN</code>
  * @throws IndexOutOfBoundsException if start or start + count is out of bounds
  * @throws NullPointerException if text is null
  * @throws IllegalArgumentException if this is a contextual shaper and the specified <code>context
  *     </code> is not a single valid range.
  */
 public void shape(char[] text, int start, int count, int context) {
   checkParams(text, start, count);
   if (isContextual()) {
     int ctxKey = getKeyFromMask(context);
     if (rangeSet == null) {
       shapeContextually(text, start, count, ctxKey);
     } else {
       shapeContextually(text, start, count, Range.values()[ctxKey]);
     }
   } else {
     shapeNonContextually(text, start, count);
   }
 }
 private static Range indexToRange(int index) {
   return index < NUM_KEYS ? Range.values()[index] : null;
 }