protected List<Object> parse(String string) {
   // break it down into fields
   List<Object> template = new ArrayList<Object>();
   while (string.contains("{")) {
     int startPattern = string.indexOf("{");
     template.add(string.substring(0, startPattern));
     int endPattern = string.indexOf("}");
     Assert.isTrue(endPattern > startPattern + 1, "Invalid pattern given " + string);
     String nestedString = string.substring(startPattern + 1, endPattern);
     int separator = nestedString.indexOf(":");
     if (separator > 0) {
       Assert.isTrue(
           nestedString.length() > separator + 1, "Invalid format given " + nestedString);
       String format = nestedString.substring(separator + 1);
       nestedString = nestedString.substring(0, separator);
       template.add(wrapWithFormatter(format, createFieldExtractor(nestedString)));
     } else {
       template.add(createFieldExtractor(nestedString));
     }
     string = string.substring(endPattern + 1).trim();
   }
   if (StringUtils.hasText(string)) {
     template.add(string);
   }
   return template;
 }
  @Override
  public void compile(String pattern) {
    this.pattern = pattern;
    // break it down into index/type
    String[] split = pattern.split("/");
    Assert.isTrue(!ObjectUtils.isEmpty(split), "invalid pattern given " + pattern);
    Assert.isTrue(split.length == 2, "invalid pattern given " + pattern);

    // check pattern
    hasPattern = pattern.contains("{") && pattern.contains("}");
    index = parse(split[0].trim());
    type = parse(split[1].trim());
  }
  @Override
  protected String extractField(Object target) {
    if (target instanceof HiveType) {
      HiveType type = (HiveType) target;
      ObjectInspector inspector = type.getObjectInspector();
      if (inspector instanceof StructObjectInspector) {
        StructObjectInspector soi = (StructObjectInspector) inspector;
        StructField field = soi.getStructFieldRef(fieldName);
        ObjectInspector foi = field.getFieldObjectInspector();
        Assert.isTrue(
            foi.getCategory() == ObjectInspector.Category.PRIMITIVE,
            String.format(
                "Field [%s] needs to be a primitive; found [%s]", fieldName, foi.getTypeName()));

        // expecting a writeable - simply do a toString
        Object data = soi.getStructFieldData(type.getObject(), field);
        if (data == null || data instanceof NullWritable) {
          return StringUtils.EMPTY;
        }
        return data.toString();
      }
    }

    return null;
  }
  @Override
  public void setSettings(Settings settings) {
    this.settings = settings;

    String paramString = settings.getUpdateScriptParams();
    List<String> fields = StringUtils.tokenize(paramString);
    for (String string : fields) {
      List<String> param = StringUtils.tokenize(string, ":");
      Assert.isTrue(param.size() == 2, "Invalid param definition " + string);

      params.put(param.get(0), createFieldExtractor(param.get(1)));
    }
  }