@Override
  protected void doXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
    if (dynamicDateTimeFormatters != Defaults.DYNAMIC_DATE_TIME_FORMATTERS) {
      if (dynamicDateTimeFormatters.length > 0) {
        builder.startArray("dynamic_date_formats");
        for (FormatDateTimeFormatter dateTimeFormatter : dynamicDateTimeFormatters) {
          builder.value(dateTimeFormatter.format());
        }
        builder.endArray();
      }
    }

    if (dynamicTemplates != null && dynamicTemplates.length > 0) {
      builder.startArray("dynamic_templates");
      for (DynamicTemplate dynamicTemplate : dynamicTemplates) {
        builder.startObject();
        builder.field(dynamicTemplate.name());
        builder.map(dynamicTemplate.conf());
        builder.endObject();
      }
      builder.endArray();
    }

    if (dateDetection != Defaults.DATE_DETECTION) {
      builder.field("date_detection", dateDetection);
    }
    if (numericDetection != Defaults.NUMERIC_DETECTION) {
      builder.field("numeric_detection", numericDetection);
    }
  }
 @Override
 public DateFieldMapper build(BuilderContext context) {
   fieldType.setOmitNorms(fieldType.omitNorms() && boost == 1.0f);
   if (!locale.equals(dateTimeFormatter.locale())) {
     dateTimeFormatter =
         new FormatDateTimeFormatter(
             dateTimeFormatter.format(),
             dateTimeFormatter.parser(),
             dateTimeFormatter.printer(),
             locale);
   }
   DateFieldMapper fieldMapper =
       new DateFieldMapper(
           buildNames(context),
           dateTimeFormatter,
           fieldType.numericPrecisionStep(),
           boost,
           fieldType,
           docValues,
           nullValue,
           timeUnit,
           ignoreMalformed(context),
           coerce(context),
           postingsProvider,
           docValuesProvider,
           similarity,
           normsLoading,
           fieldDataSettings,
           context.indexSettings(),
           multiFieldsBuilder.build(this, context),
           copyTo);
   fieldMapper.includeInAll(includeInAll);
   return fieldMapper;
 }
 public Builder dynamicDateTimeFormatter(Iterable<FormatDateTimeFormatter> dateTimeFormatters) {
   for (FormatDateTimeFormatter dateTimeFormatter : dateTimeFormatters) {
     if (!seenDateFormats.contains(dateTimeFormatter.format())) {
       seenDateFormats.add(dateTimeFormatter.format());
       this.dynamicDateTimeFormatters.add(dateTimeFormatter);
     }
   }
   return builder;
 }
 private long parseValue(Object value) {
   if (value instanceof Number) {
     return ((Number) value).longValue();
   }
   if (value instanceof BytesRef) {
     return dateTimeFormatter.parser().parseMillis(((BytesRef) value).utf8ToString());
   }
   return dateTimeFormatter.parser().parseMillis(value.toString());
 }
  @Test
  public void testMultipleDifferentFormats() {
    FormatDateTimeFormatter formatter = Joda.forPattern("yyyy/MM/dd HH:mm:ss||yyyy/MM/dd");
    String input = "1970/01/01 00:00:00";
    long millis = formatter.parser().parseMillis(input);
    assertThat(input, is(formatter.printer().print(millis)));

    Joda.forPattern("yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||dateOptionalTime");
    Joda.forPattern("dateOptionalTime||yyyy/MM/dd HH:mm:ss||yyyy/MM/dd");
    Joda.forPattern("yyyy/MM/dd HH:mm:ss||dateOptionalTime||yyyy/MM/dd");
    Joda.forPattern("date_time||date_time_no_millis");
    Joda.forPattern(" date_time || date_time_no_millis");
  }
  @Test
  public void testIsoVsCustom() {
    DateTimeFormatter formatter =
        ISODateTimeFormat.dateOptionalTimeParser().withZone(DateTimeZone.UTC);
    long millis = formatter.parseMillis("1970-01-01T00:00:00");
    assertThat(millis, equalTo(0l));

    formatter = DateTimeFormat.forPattern("yyyy/MM/dd HH:mm:ss").withZone(DateTimeZone.UTC);
    millis = formatter.parseMillis("1970/01/01 00:00:00");
    assertThat(millis, equalTo(0l));

    FormatDateTimeFormatter formatter2 = Joda.forPattern("yyyy/MM/dd HH:mm:ss");
    millis = formatter2.parser().parseMillis("1970/01/01 00:00:00");
    assertThat(millis, equalTo(0l));
  }
  @Test
  public void testSlashInFormat() {
    FormatDateTimeFormatter formatter = Joda.forPattern("MM/yyyy");
    formatter.parser().parseMillis("01/2001");

    formatter = Joda.forPattern("yyyy/MM/dd HH:mm:ss");
    long millis = formatter.parser().parseMillis("1970/01/01 00:00:00");
    formatter.printer().print(millis);

    try {
      millis = formatter.parser().parseMillis("1970/01/01");
      assert false;
    } catch (IllegalArgumentException e) {
      // it really can't parse this one
    }
  }
 private long parseStringValue(String value) {
   try {
     return dateTimeFormatter.parser().parseMillis(value);
   } catch (RuntimeException e) {
     try {
       long time = Long.parseLong(value);
       return timeUnit.toMillis(time);
     } catch (NumberFormatException e1) {
       throw new MapperParsingException(
           "failed to parse date field ["
               + value
               + "], tried both date format ["
               + dateTimeFormatter.format()
               + "], and timestamp number with locale ["
               + dateTimeFormatter.locale()
               + "]",
           e);
     }
   }
 }
 /** Dates should return as a string. */
 @Override
 public Object valueForSearch(Object value) {
   if (value instanceof String) {
     // assume its the string that was indexed, just return it... (for example, with get)
     return value;
   }
   Long val = value(value);
   if (val == null) {
     return null;
   }
   return dateTimeFormatter.printer().print(val);
 }
  @Override
  protected void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params)
      throws IOException {
    super.doXContentBody(builder, includeDefaults, params);

    if (includeDefaults || precisionStep != Defaults.PRECISION_STEP_64_BIT) {
      builder.field("precision_step", precisionStep);
    }
    builder.field("format", dateTimeFormatter.format());
    if (includeDefaults || nullValue != null) {
      builder.field("null_value", nullValue);
    }
    if (includeInAll != null) {
      builder.field("include_in_all", includeInAll);
    } else if (includeDefaults) {
      builder.field("include_in_all", false);
    }

    if (includeDefaults || timeUnit != Defaults.TIME_UNIT) {
      builder.field("numeric_resolution", timeUnit.name().toLowerCase(Locale.ROOT));
    }
    // only serialize locale if needed, ROOT is the default, so no need to serialize that case as
    // well...
    if (dateTimeFormatter.locale() != null && dateTimeFormatter.locale() != Locale.ROOT) {
      builder.field("locale", dateTimeFormatter.locale());
    } else if (includeDefaults) {
      if (dateTimeFormatter.locale() == null) {
        builder.field("locale", Locale.ROOT);
      } else {
        builder.field("locale", dateTimeFormatter.locale());
      }
    }
  }
  private void serializeValue(
      final ParseContext context, String currentFieldName, XContentParser.Token token)
      throws IOException {
    if (currentFieldName == null) {
      throw new MapperParsingException(
          "object mapping ["
              + name
              + "] trying to serialize a value with no field associated with it, current value ["
              + context.parser().textOrNull()
              + "]");
    }
    Mapper mapper = mappers.get(currentFieldName);
    if (mapper != null) {
      mapper.parse(context);
      return;
    }
    Dynamic dynamic = this.dynamic;
    if (dynamic == null) {
      dynamic = context.root().dynamic();
    }
    if (dynamic == Dynamic.STRICT) {
      throw new StrictDynamicMappingException(fullPath, currentFieldName);
    }
    if (dynamic == Dynamic.FALSE) {
      return;
    }
    // we sync here since we don't want to add this field twice to the document mapper
    // its not the end of the world, since we add it to the mappers once we create it
    // so next time we won't even get here for this field
    boolean newMapper = false;
    synchronized (mutex) {
      mapper = mappers.get(currentFieldName);
      if (mapper == null) {
        newMapper = true;
        BuilderContext builderContext = new BuilderContext(context.indexSettings(), context.path());
        if (token == XContentParser.Token.VALUE_STRING) {
          boolean resolved = false;

          // do a quick test to see if its fits a dynamic template, if so, use it.
          // we need to do it here so we can handle things like attachment templates, where calling
          // text (to see if its a date) causes the binary value to be cleared
          if (!resolved) {
            Mapper.Builder builder =
                context.root().findTemplateBuilder(context, currentFieldName, "string", null);
            if (builder != null) {
              mapper = builder.build(builderContext);
              resolved = true;
            }
          }

          if (!resolved && context.parser().textLength() == 0) {
            // empty string with no mapping, treat it like null value
            return;
          }

          if (!resolved && context.root().dateDetection()) {
            String text = context.parser().text();
            // a safe check since "1" gets parsed as well
            if (Strings.countOccurrencesOf(text, ":") > 1
                || Strings.countOccurrencesOf(text, "-") > 1
                || Strings.countOccurrencesOf(text, "/") > 1) {
              for (FormatDateTimeFormatter dateTimeFormatter :
                  context.root().dynamicDateTimeFormatters()) {
                try {
                  dateTimeFormatter.parser().parseMillis(text);
                  Mapper.Builder builder =
                      context.root().findTemplateBuilder(context, currentFieldName, "date");
                  if (builder == null) {
                    builder = dateField(currentFieldName).dateTimeFormatter(dateTimeFormatter);
                  }
                  mapper = builder.build(builderContext);
                  resolved = true;
                  break;
                } catch (Exception e) {
                  // failure to parse this, continue
                }
              }
            }
          }
          if (!resolved && context.root().numericDetection()) {
            String text = context.parser().text();
            try {
              Long.parseLong(text);
              Mapper.Builder builder =
                  context.root().findTemplateBuilder(context, currentFieldName, "long");
              if (builder == null) {
                builder = longField(currentFieldName);
              }
              mapper = builder.build(builderContext);
              resolved = true;
            } catch (Exception e) {
              // not a long number
            }
            if (!resolved) {
              try {
                Double.parseDouble(text);
                Mapper.Builder builder =
                    context.root().findTemplateBuilder(context, currentFieldName, "double");
                if (builder == null) {
                  builder = doubleField(currentFieldName);
                }
                mapper = builder.build(builderContext);
                resolved = true;
              } catch (Exception e) {
                // not a long number
              }
            }
          }
          // DON'T do automatic ip detection logic, since it messes up with docs that have hosts and
          // ips
          // check if its an ip
          //                if (!resolved && text.indexOf('.') != -1) {
          //                    try {
          //                        IpFieldMapper.ipToLong(text);
          //                        XContentMapper.Builder builder =
          // context.root().findTemplateBuilder(context, currentFieldName, "ip");
          //                        if (builder == null) {
          //                            builder = ipField(currentFieldName);
          //                        }
          //                        mapper = builder.build(builderContext);
          //                        resolved = true;
          //                    } catch (Exception e) {
          //                        // failure to parse, not ip...
          //                    }
          //                }
          if (!resolved) {
            Mapper.Builder builder =
                context.root().findTemplateBuilder(context, currentFieldName, "string");
            if (builder == null) {
              builder = stringField(currentFieldName);
            }
            mapper = builder.build(builderContext);
          }
        } else if (token == XContentParser.Token.VALUE_NUMBER) {
          XContentParser.NumberType numberType = context.parser().numberType();
          if (numberType == XContentParser.NumberType.INT) {
            if (context.parser().estimatedNumberType()) {
              Mapper.Builder builder =
                  context.root().findTemplateBuilder(context, currentFieldName, "long");
              if (builder == null) {
                builder = longField(currentFieldName);
              }
              mapper = builder.build(builderContext);
            } else {
              Mapper.Builder builder =
                  context.root().findTemplateBuilder(context, currentFieldName, "integer");
              if (builder == null) {
                builder = integerField(currentFieldName);
              }
              mapper = builder.build(builderContext);
            }
          } else if (numberType == XContentParser.NumberType.LONG) {
            Mapper.Builder builder =
                context.root().findTemplateBuilder(context, currentFieldName, "long");
            if (builder == null) {
              builder = longField(currentFieldName);
            }
            mapper = builder.build(builderContext);
          } else if (numberType == XContentParser.NumberType.FLOAT) {
            if (context.parser().estimatedNumberType()) {
              Mapper.Builder builder =
                  context.root().findTemplateBuilder(context, currentFieldName, "double");
              if (builder == null) {
                builder = doubleField(currentFieldName);
              }
              mapper = builder.build(builderContext);
            } else {
              Mapper.Builder builder =
                  context.root().findTemplateBuilder(context, currentFieldName, "float");
              if (builder == null) {
                builder = floatField(currentFieldName);
              }
              mapper = builder.build(builderContext);
            }
          } else if (numberType == XContentParser.NumberType.DOUBLE) {
            Mapper.Builder builder =
                context.root().findTemplateBuilder(context, currentFieldName, "double");
            if (builder == null) {
              builder = doubleField(currentFieldName);
            }
            mapper = builder.build(builderContext);
          }
        } else if (token == XContentParser.Token.VALUE_BOOLEAN) {
          Mapper.Builder builder =
              context.root().findTemplateBuilder(context, currentFieldName, "boolean");
          if (builder == null) {
            builder = booleanField(currentFieldName);
          }
          mapper = builder.build(builderContext);
        } else if (token == XContentParser.Token.VALUE_EMBEDDED_OBJECT) {
          Mapper.Builder builder =
              context.root().findTemplateBuilder(context, currentFieldName, "binary");
          if (builder == null) {
            builder = binaryField(currentFieldName);
          }
          mapper = builder.build(builderContext);
        } else {
          Mapper.Builder builder =
              context.root().findTemplateBuilder(context, currentFieldName, null);
          if (builder != null) {
            mapper = builder.build(builderContext);
          } else {
            // TODO how do we identify dynamically that its a binary value?
            throw new ElasticSearchIllegalStateException(
                "Can't handle serializing a dynamic type with content token ["
                    + token
                    + "] and field name ["
                    + currentFieldName
                    + "]");
          }
        }
        putMapper(mapper);
        context.setMappingsModified();
      }
    }
    if (newMapper) {
      mapper.traverse(context.newFieldMappers());
    }
    mapper.parse(context);
  }
  private static Mapper.Builder<?, ?> createBuilderFromDynamicValue(
      final ParseContext context, XContentParser.Token token, String currentFieldName)
      throws IOException {
    if (token == XContentParser.Token.VALUE_STRING) {
      // do a quick test to see if its fits a dynamic template, if so, use it.
      // we need to do it here so we can handle things like attachment templates, where calling
      // text (to see if its a date) causes the binary value to be cleared
      {
        Mapper.Builder builder =
            context.root().findTemplateBuilder(context, currentFieldName, "string", null);
        if (builder != null) {
          return builder;
        }
      }

      if (context.root().dateDetection()) {
        String text = context.parser().text();
        // a safe check since "1" gets parsed as well
        if (Strings.countOccurrencesOf(text, ":") > 1
            || Strings.countOccurrencesOf(text, "-") > 1
            || Strings.countOccurrencesOf(text, "/") > 1) {
          for (FormatDateTimeFormatter dateTimeFormatter :
              context.root().dynamicDateTimeFormatters()) {
            try {
              dateTimeFormatter.parser().parseMillis(text);
              Mapper.Builder builder =
                  context.root().findTemplateBuilder(context, currentFieldName, "date");
              if (builder == null) {
                builder =
                    MapperBuilders.dateField(currentFieldName).dateTimeFormatter(dateTimeFormatter);
              }
              return builder;
            } catch (Exception e) {
              // failure to parse this, continue
            }
          }
        }
      }
      if (context.root().numericDetection()) {
        String text = context.parser().text();
        try {
          Long.parseLong(text);
          Mapper.Builder builder =
              context.root().findTemplateBuilder(context, currentFieldName, "long");
          if (builder == null) {
            builder = MapperBuilders.longField(currentFieldName);
          }
          return builder;
        } catch (NumberFormatException e) {
          // not a long number
        }
        try {
          Double.parseDouble(text);
          Mapper.Builder builder =
              context.root().findTemplateBuilder(context, currentFieldName, "double");
          if (builder == null) {
            builder = MapperBuilders.doubleField(currentFieldName);
          }
          return builder;
        } catch (NumberFormatException e) {
          // not a long number
        }
      }
      Mapper.Builder builder =
          context.root().findTemplateBuilder(context, currentFieldName, "string");
      if (builder == null) {
        builder = MapperBuilders.stringField(currentFieldName);
      }
      return builder;
    } else if (token == XContentParser.Token.VALUE_NUMBER) {
      XContentParser.NumberType numberType = context.parser().numberType();
      if (numberType == XContentParser.NumberType.INT
          || numberType == XContentParser.NumberType.LONG) {
        Mapper.Builder builder =
            context.root().findTemplateBuilder(context, currentFieldName, "long");
        if (builder == null) {
          builder = MapperBuilders.longField(currentFieldName);
        }
        return builder;
      } else if (numberType == XContentParser.NumberType.FLOAT
          || numberType == XContentParser.NumberType.DOUBLE) {
        Mapper.Builder builder =
            context.root().findTemplateBuilder(context, currentFieldName, "double");
        if (builder == null) {
          // no templates are defined, we use float by default instead of double
          // since this is much more space-efficient and should be enough most of
          // the time
          builder = MapperBuilders.floatField(currentFieldName);
        }
        return builder;
      }
    } else if (token == XContentParser.Token.VALUE_BOOLEAN) {
      Mapper.Builder builder =
          context.root().findTemplateBuilder(context, currentFieldName, "boolean");
      if (builder == null) {
        builder = MapperBuilders.booleanField(currentFieldName);
      }
      return builder;
    } else if (token == XContentParser.Token.VALUE_EMBEDDED_OBJECT) {
      Mapper.Builder builder =
          context.root().findTemplateBuilder(context, currentFieldName, "binary");
      if (builder == null) {
        builder = MapperBuilders.binaryField(currentFieldName);
      }
      return builder;
    } else {
      Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, null);
      if (builder != null) {
        return builder;
      }
    }
    // TODO how do we identify dynamically that its a binary value?
    throw new IllegalStateException(
        "Can't handle serializing a dynamic type with content token ["
            + token
            + "] and field name ["
            + currentFieldName
            + "]");
  }
  public void parseDynamicValue(
      final ParseContext context, String currentFieldName, XContentParser.Token token)
      throws IOException {
    Dynamic dynamic = this.dynamic;
    if (dynamic == null) {
      dynamic = context.root().dynamic();
    }
    if (dynamic == Dynamic.STRICT) {
      throw new StrictDynamicMappingException(fullPath, currentFieldName);
    }
    if (dynamic == Dynamic.FALSE) {
      return;
    }
    // we sync here since we don't want to add this field twice to the document mapper
    // its not the end of the world, since we add it to the mappers once we create it
    // so next time we won't even get here for this field
    synchronized (mutex) {
      Mapper mapper = mappers.get(currentFieldName);
      if (mapper == null) {
        BuilderContext builderContext = new BuilderContext(context.indexSettings(), context.path());
        if (token == XContentParser.Token.VALUE_STRING) {
          boolean resolved = false;

          // do a quick test to see if its fits a dynamic template, if so, use it.
          // we need to do it here so we can handle things like attachment templates, where calling
          // text (to see if its a date) causes the binary value to be cleared
          if (!resolved) {
            Mapper.Builder builder =
                context.root().findTemplateBuilder(context, currentFieldName, "string", null);
            if (builder != null) {
              mapper = builder.build(builderContext);
              resolved = true;
            }
          }

          if (!resolved && context.parser().textLength() == 0) {
            // empty string with no mapping, treat it like null value
            return;
          }

          if (!resolved && context.root().dateDetection()) {
            String text = context.parser().text();
            // a safe check since "1" gets parsed as well
            if (Strings.countOccurrencesOf(text, ":") > 1
                || Strings.countOccurrencesOf(text, "-") > 1
                || Strings.countOccurrencesOf(text, "/") > 1) {
              for (FormatDateTimeFormatter dateTimeFormatter :
                  context.root().dynamicDateTimeFormatters()) {
                try {
                  dateTimeFormatter.parser().parseMillis(text);
                  Mapper.Builder builder =
                      context.root().findTemplateBuilder(context, currentFieldName, "date");
                  if (builder == null) {
                    builder = dateField(currentFieldName).dateTimeFormatter(dateTimeFormatter);
                  }
                  mapper = builder.build(builderContext);
                  resolved = true;
                  break;
                } catch (Exception e) {
                  // failure to parse this, continue
                }
              }
            }
          }
          if (!resolved && context.root().numericDetection()) {
            String text = context.parser().text();
            try {
              Long.parseLong(text);
              Mapper.Builder builder =
                  context.root().findTemplateBuilder(context, currentFieldName, "long");
              if (builder == null) {
                builder = longField(currentFieldName);
              }
              mapper = builder.build(builderContext);
              resolved = true;
            } catch (Exception e) {
              // not a long number
            }
            if (!resolved) {
              try {
                Double.parseDouble(text);
                Mapper.Builder builder =
                    context.root().findTemplateBuilder(context, currentFieldName, "double");
                if (builder == null) {
                  builder = doubleField(currentFieldName);
                }
                mapper = builder.build(builderContext);
                resolved = true;
              } catch (Exception e) {
                // not a long number
              }
            }
          }
          if (!resolved) {
            Mapper.Builder builder =
                context.root().findTemplateBuilder(context, currentFieldName, "string");
            if (builder == null) {
              builder = stringField(currentFieldName);
            }
            mapper = builder.build(builderContext);
          }
        } else if (token == XContentParser.Token.VALUE_NUMBER) {
          XContentParser.NumberType numberType = context.parser().numberType();
          if (numberType == XContentParser.NumberType.INT) {
            if (context.parser().estimatedNumberType()) {
              Mapper.Builder builder =
                  context.root().findTemplateBuilder(context, currentFieldName, "long");
              if (builder == null) {
                builder = longField(currentFieldName);
              }
              mapper = builder.build(builderContext);
            } else {
              Mapper.Builder builder =
                  context.root().findTemplateBuilder(context, currentFieldName, "integer");
              if (builder == null) {
                builder = integerField(currentFieldName);
              }
              mapper = builder.build(builderContext);
            }
          } else if (numberType == XContentParser.NumberType.LONG) {
            Mapper.Builder builder =
                context.root().findTemplateBuilder(context, currentFieldName, "long");
            if (builder == null) {
              builder = longField(currentFieldName);
            }
            mapper = builder.build(builderContext);
          } else if (numberType == XContentParser.NumberType.FLOAT) {
            if (context.parser().estimatedNumberType()) {
              Mapper.Builder builder =
                  context.root().findTemplateBuilder(context, currentFieldName, "double");
              if (builder == null) {
                builder = doubleField(currentFieldName);
              }
              mapper = builder.build(builderContext);
            } else {
              Mapper.Builder builder =
                  context.root().findTemplateBuilder(context, currentFieldName, "float");
              if (builder == null) {
                builder = floatField(currentFieldName);
              }
              mapper = builder.build(builderContext);
            }
          } else if (numberType == XContentParser.NumberType.DOUBLE) {
            Mapper.Builder builder =
                context.root().findTemplateBuilder(context, currentFieldName, "double");
            if (builder == null) {
              builder = doubleField(currentFieldName);
            }
            mapper = builder.build(builderContext);
          }
        } else if (token == XContentParser.Token.VALUE_BOOLEAN) {
          Mapper.Builder builder =
              context.root().findTemplateBuilder(context, currentFieldName, "boolean");
          if (builder == null) {
            builder = booleanField(currentFieldName);
          }
          mapper = builder.build(builderContext);
        } else if (token == XContentParser.Token.VALUE_EMBEDDED_OBJECT) {
          Mapper.Builder builder =
              context.root().findTemplateBuilder(context, currentFieldName, "binary");
          if (builder == null) {
            builder = binaryField(currentFieldName);
          }
          mapper = builder.build(builderContext);
        } else {
          Mapper.Builder builder =
              context.root().findTemplateBuilder(context, currentFieldName, null);
          if (builder != null) {
            mapper = builder.build(builderContext);
          } else {
            // TODO how do we identify dynamically that its a binary value?
            throw new ElasticsearchIllegalStateException(
                "Can't handle serializing a dynamic type with content token ["
                    + token
                    + "] and field name ["
                    + currentFieldName
                    + "]");
          }
        }

        if (context.isWithinNewMapper()) {
          mapper.parse(context);
        } else {
          context.setWithinNewMapper();
          try {
            mapper.parse(context);
            FieldMapperListener.Aggregator newFields = new FieldMapperListener.Aggregator();
            mapper.traverse(newFields);
            context.docMapper().addFieldMappers(newFields.mappers);
          } finally {
            context.clearWithinNewMapper();
          }
        }

        // only put after we traversed and did the callbacks, so other parsing won't see it only
        // after we
        // properly traversed it and adding the mappers
        putMapper(mapper);
        context.setMappingsModified();
      } else {
        mapper.parse(context);
      }
    }
  }
 @Test
 public void testMultipleFormats() {
   FormatDateTimeFormatter formatter = Joda.forPattern("yyyy/MM/dd HH:mm:ss||yyyy/MM/dd");
   long millis = formatter.parser().parseMillis("1970/01/01 00:00:00");
   assertThat("1970/01/01 00:00:00", is(formatter.printer().print(millis)));
 }
Exemple #15
0
  private String innerDetect() throws Exception {
    StringBuilder sb = new StringBuilder();

    sb.append("Hot threads at ");
    sb.append(DATE_TIME_FORMATTER.printer().print(System.currentTimeMillis()));
    sb.append(", interval=");
    sb.append(interval);
    sb.append(", busiestThreads=");
    sb.append(busiestThreads);
    sb.append(", ignoreIdleThreads=");
    sb.append(ignoreIdleThreads);
    sb.append(":\n");

    ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
    boolean enabledCpu = false;
    try {
      if (threadBean.isThreadCpuTimeSupported()) {
        if (!threadBean.isThreadCpuTimeEnabled()) {
          enabledCpu = true;
          threadBean.setThreadCpuTimeEnabled(true);
        }
      } else {
        throw new IllegalStateException("MBean doesn't support thread CPU Time");
      }
      Map<Long, MyThreadInfo> threadInfos = new HashMap<>();
      for (long threadId : threadBean.getAllThreadIds()) {
        // ignore our own thread...
        if (Thread.currentThread().getId() == threadId) {
          continue;
        }
        long cpu = threadBean.getThreadCpuTime(threadId);
        if (cpu == -1) {
          continue;
        }
        ThreadInfo info = threadBean.getThreadInfo(threadId, 0);
        if (info == null) {
          continue;
        }
        threadInfos.put(threadId, new MyThreadInfo(cpu, info));
      }
      Thread.sleep(interval.millis());
      for (long threadId : threadBean.getAllThreadIds()) {
        // ignore our own thread...
        if (Thread.currentThread().getId() == threadId) {
          continue;
        }
        long cpu = threadBean.getThreadCpuTime(threadId);
        if (cpu == -1) {
          threadInfos.remove(threadId);
          continue;
        }
        ThreadInfo info = threadBean.getThreadInfo(threadId, 0);
        if (info == null) {
          threadInfos.remove(threadId);
          continue;
        }
        MyThreadInfo data = threadInfos.get(threadId);
        if (data != null) {
          data.setDelta(cpu, info);
        } else {
          threadInfos.remove(threadId);
        }
      }
      // sort by delta CPU time on thread.
      List<MyThreadInfo> hotties = new ArrayList<>(threadInfos.values());
      final int busiestThreads = Math.min(this.busiestThreads, hotties.size());
      // skip that for now
      CollectionUtil.introSort(
          hotties,
          new Comparator<MyThreadInfo>() {
            @Override
            public int compare(MyThreadInfo o1, MyThreadInfo o2) {
              if ("cpu".equals(type)) {
                return (int) (o2.cpuTime - o1.cpuTime);
              } else if ("wait".equals(type)) {
                return (int) (o2.waitedTime - o1.waitedTime);
              } else if ("block".equals(type)) {
                return (int) (o2.blockedTime - o1.blockedTime);
              }
              throw new IllegalArgumentException();
            }
          });
      // analyse N stack traces for M busiest threads
      long[] ids = new long[busiestThreads];
      for (int i = 0; i < busiestThreads; i++) {
        MyThreadInfo info = hotties.get(i);
        ids[i] = info.info.getThreadId();
      }
      ThreadInfo[][] allInfos = new ThreadInfo[threadElementsSnapshotCount][];
      for (int j = 0; j < threadElementsSnapshotCount; j++) {
        // NOTE, javadoc of getThreadInfo says: If a thread of the given ID is not alive or does not
        // exist,
        // null will be set in the corresponding element in the returned array. A thread is alive if
        // it has
        // been started and has not yet died.
        allInfos[j] = threadBean.getThreadInfo(ids, Integer.MAX_VALUE);
        Thread.sleep(threadElementsSnapshotDelay.millis());
      }
      for (int t = 0; t < busiestThreads; t++) {
        long time = 0;
        if ("cpu".equals(type)) {
          time = hotties.get(t).cpuTime;
        } else if ("wait".equals(type)) {
          time = hotties.get(t).waitedTime;
        } else if ("block".equals(type)) {
          time = hotties.get(t).blockedTime;
        }
        String threadName = null;
        for (ThreadInfo[] info : allInfos) {
          if (info != null && info[t] != null) {
            if (ignoreIdleThreads && isIdleThread(info[t])) {
              info[t] = null;
              continue;
            }
            threadName = info[t].getThreadName();
            break;
          }
        }
        if (threadName == null) {
          continue; // thread is not alive yet or died before the first snapshot - ignore it!
        }
        double percent = (((double) time) / interval.nanos()) * 100;
        sb.append(
            String.format(
                Locale.ROOT,
                "%n%4.1f%% (%s out of %s) %s usage by thread '%s'%n",
                percent,
                TimeValue.timeValueNanos(time),
                interval,
                type,
                threadName));
        // for each snapshot (2nd array index) find later snapshot for same thread with max number
        // of
        // identical StackTraceElements (starting from end of each)
        boolean[] done = new boolean[threadElementsSnapshotCount];
        for (int i = 0; i < threadElementsSnapshotCount; i++) {
          if (done[i]) continue;
          int maxSim = 1;
          boolean[] similars = new boolean[threadElementsSnapshotCount];
          for (int j = i + 1; j < threadElementsSnapshotCount; j++) {
            if (done[j]) continue;
            int similarity = similarity(allInfos[i][t], allInfos[j][t]);
            if (similarity > maxSim) {
              maxSim = similarity;
              similars = new boolean[threadElementsSnapshotCount];
            }
            if (similarity == maxSim) similars[j] = true;
          }
          // print out trace maxSim levels of i, and mark similar ones as done
          int count = 1;
          for (int j = i + 1; j < threadElementsSnapshotCount; j++) {
            if (similars[j]) {
              done[j] = true;
              count++;
            }
          }
          if (allInfos[i][t] != null) {
            final StackTraceElement[] show = allInfos[i][t].getStackTrace();
            if (count == 1) {
              sb.append(String.format(Locale.ROOT, "  unique snapshot%n"));
              for (int l = 0; l < show.length; l++) {
                sb.append(String.format(Locale.ROOT, "    %s%n", show[l]));
              }
            } else {
              sb.append(
                  String.format(
                      Locale.ROOT,
                      "  %d/%d snapshots sharing following %d elements%n",
                      count,
                      threadElementsSnapshotCount,
                      maxSim));
              for (int l = show.length - maxSim; l < show.length; l++) {
                sb.append(String.format(Locale.ROOT, "    %s%n", show[l]));
              }
            }
          }
        }
      }
      return sb.toString();
    } finally {
      if (enabledCpu) {
        threadBean.setThreadCpuTimeEnabled(false);
      }
    }
  }