public void testField() throws Exception {
    IndexService indexService = createIndex("test");
    DocumentMapperParser parser = indexService.mapperService().documentMapperParser();
    String mapping =
        XContentFactory.jsonBuilder()
            .startObject()
            .startObject("type")
            .endObject()
            .endObject()
            .string();

    DocumentMapper mapper = parser.parse(mapping);
    assertEquals(mapping, serialize(mapper));

    Mapper update =
        parse(
            mapper,
            parser,
            XContentFactory.jsonBuilder().startObject().field("foo", "bar").endObject());
    assertNotNull(update);
    // original mapping not modified
    assertEquals(mapping, serialize(mapper));
    // but we have an update
    assertEquals("{\"type\":{\"properties\":{\"foo\":{\"type\":\"string\"}}}}", serialize(update));
  }
 public void testRejectNorms() throws IOException {
   // not supported as of 5.0
   for (String type : Arrays.asList("byte", "short", "integer", "long", "float", "double")) {
     DocumentMapperParser parser =
         createIndex("index-" + type).mapperService().documentMapperParser();
     String mapping =
         XContentFactory.jsonBuilder()
             .startObject()
             .startObject("type")
             .startObject("properties")
             .startObject("foo")
             .field("type", type)
             .field("norms", random().nextBoolean())
             .endObject()
             .endObject()
             .endObject()
             .endObject()
             .string();
     MapperParsingException e =
         expectThrows(
             MapperParsingException.class,
             () -> parser.parse("type", new CompressedXContent(mapping)));
     assertThat(
         e.getMessage(),
         containsString("Mapping definition for [foo] has unsupported parameters:  [norms"));
   }
 }
  public void testObject() throws Exception {
    IndexService indexService = createIndex("test");
    DocumentMapperParser parser = indexService.mapperService().documentMapperParser();
    String mapping =
        XContentFactory.jsonBuilder()
            .startObject()
            .startObject("type")
            .endObject()
            .endObject()
            .string();

    DocumentMapper mapper = parser.parse("type", new CompressedXContent(mapping));
    assertEquals(mapping, serialize(mapper));

    Mapper update =
        parse(
            mapper,
            parser,
            XContentFactory.jsonBuilder()
                .startObject()
                .startObject("foo")
                .startObject("bar")
                .field("baz", "foo")
                .endObject()
                .endObject()
                .endObject());
    assertNotNull(update);
    // original mapping not modified
    assertEquals(mapping, serialize(mapper));
    // but we have an update
    assertEquals(
        XContentFactory.jsonBuilder()
            .startObject()
            .startObject("type")
            .startObject("properties")
            .startObject("foo")
            .startObject("properties")
            .startObject("bar")
            .startObject("properties")
            .startObject("baz")
            .field("type", "text")
            .startObject("fields")
            .startObject("keyword")
            .field("type", "keyword")
            .field("ignore_above", 256)
            .endObject()
            .endObject()
            .endObject()
            .endObject()
            .endObject()
            .endObject()
            .endObject()
            .endObject()
            .endObject()
            .endObject()
            .string(),
        serialize(update));
  }
  public void testIncremental() throws Exception {
    IndexService indexService = createIndex("test");
    DocumentMapperParser parser = indexService.mapperService().documentMapperParser();
    // Make sure that mapping updates are incremental, this is important for performance otherwise
    // every new field introduction runs in linear time with the total number of fields
    String mapping =
        XContentFactory.jsonBuilder()
            .startObject()
            .startObject("type")
            .startObject("properties")
            .startObject("foo")
            .field("type", "text")
            .endObject()
            .endObject()
            .endObject()
            .string();

    DocumentMapper mapper = parser.parse("type", new CompressedXContent(mapping));
    assertEquals(mapping, serialize(mapper));

    Mapper update =
        parse(
            mapper,
            parser,
            XContentFactory.jsonBuilder()
                .startObject()
                .field("foo", "bar")
                .field("bar", "baz")
                .endObject());
    assertNotNull(update);
    // original mapping not modified
    assertEquals(mapping, serialize(mapper));
    // but we have an update
    assertEquals(
        XContentFactory.jsonBuilder()
            .startObject()
            .startObject("type")
            .startObject("properties")
            // foo is NOT in the update
            .startObject("bar")
            .field("type", "text")
            .startObject("fields")
            .startObject("keyword")
            .field("type", "keyword")
            .field("ignore_above", 256)
            .endObject()
            .endObject()
            .endObject()
            .endObject()
            .endObject()
            .string(),
        serialize(update));
  }
  public void testComplexArray() throws Exception {
    IndexService indexService = createIndex("test");
    DocumentMapperParser parser = indexService.mapperService().documentMapperParser();
    String mapping =
        XContentFactory.jsonBuilder()
            .startObject()
            .startObject("type")
            .endObject()
            .endObject()
            .string();

    DocumentMapper mapper = parser.parse(mapping);
    assertEquals(mapping, serialize(mapper));

    Mapper update =
        parse(
            mapper,
            parser,
            XContentFactory.jsonBuilder()
                .startObject()
                .startArray("foo")
                .startObject()
                .field("bar", "baz")
                .endObject()
                .startObject()
                .field("baz", 3)
                .endObject()
                .endArray()
                .endObject());
    assertEquals(mapping, serialize(mapper));
    assertEquals(
        XContentFactory.jsonBuilder()
            .startObject()
            .startObject("type")
            .startObject("properties")
            .startObject("foo")
            .startObject("properties")
            .startObject("bar")
            .field("type", "string")
            .endObject()
            .startObject("baz")
            .field("type", "long")
            .endObject()
            .endObject()
            .endObject()
            .endObject()
            .endObject()
            .endObject()
            .string(),
        serialize(update));
  }
 public DocumentMapper merge(
     String type, CompressedXContent mappingSource, MergeReason reason, boolean updateAllTypes) {
   if (DEFAULT_MAPPING.equals(type)) {
     // verify we can parse it
     // NOTE: never apply the default here
     DocumentMapper mapper = documentParser.parse(type, mappingSource);
     // still add it as a document mapper so we have it registered and, for example, persisted back
     // into
     // the cluster meta data if needed, or checked for existence
     synchronized (this) {
       mappers = newMapBuilder(mappers).put(type, mapper).map();
     }
     try {
       defaultMappingSource = mappingSource.string();
     } catch (IOException e) {
       throw new ElasticsearchGenerationException("failed to un-compress", e);
     }
     return mapper;
   } else {
     synchronized (this) {
       final boolean applyDefault =
           // the default was already applied if we are recovering
           reason != MergeReason.MAPPING_RECOVERY
               // only apply the default mapping if we don't have the type yet
               && mappers.containsKey(type) == false;
       DocumentMapper mergeWith = parse(type, mappingSource, applyDefault);
       return merge(mergeWith, reason, updateAllTypes);
     }
   }
 }
 public DocumentMapper parse(String mappingType, String mappingSource, boolean applyDefault)
     throws MapperParsingException {
   String defaultMappingSource;
   if (PercolatorService.TYPE_NAME.equals(mappingType)) {
     defaultMappingSource = this.defaultPercolatorMappingSource;
   } else {
     defaultMappingSource = this.defaultMappingSource;
   }
   return documentParser.parse(
       mappingType, mappingSource, applyDefault ? defaultMappingSource : null);
 }
 public void add(String type, String mappingSource) {
   if (DEFAULT_MAPPING.equals(type)) {
     // verify we can parse it
     DocumentMapper mapper = documentParser.parse(type, mappingSource);
     // still add it as a document mapper so we have it registered and, for example, persisted back
     // into
     // the cluster meta data if needed, or checked for existence
     synchronized (mutex) {
       mappers = newMapBuilder(mappers).put(type, mapper).map();
     }
     defaultMappingSource = mappingSource;
   } else {
     add(parse(type, mappingSource));
   }
 }
  public void testDynamicMappingsNotNeeded() throws Exception {
    IndexService indexService = createIndex("test");
    DocumentMapperParser parser = indexService.mapperService().documentMapperParser();
    String mapping =
        XContentFactory.jsonBuilder()
            .startObject()
            .startObject("type")
            .startObject("properties")
            .startObject("foo")
            .field("type", "text")
            .endObject()
            .endObject()
            .endObject()
            .string();

    DocumentMapper mapper = parser.parse("type", new CompressedXContent(mapping));
    Mapper update =
        parse(
            mapper,
            parser,
            XContentFactory.jsonBuilder().startObject().field("foo", "bar").endObject());
    // foo is already defined in the mappings
    assertNull(update);
  }
 public DocumentMapper merge(
     String type, CompressedXContent mappingSource, boolean applyDefault, boolean updateAllTypes) {
   if (DEFAULT_MAPPING.equals(type)) {
     // verify we can parse it
     DocumentMapper mapper = documentParser.parseCompressed(type, mappingSource);
     // still add it as a document mapper so we have it registered and, for example, persisted back
     // into
     // the cluster meta data if needed, or checked for existence
     try (ReleasableLock lock = mappingWriteLock.acquire()) {
       mappers = newMapBuilder(mappers).put(type, mapper).map();
     }
     try {
       defaultMappingSource = mappingSource.string();
     } catch (IOException e) {
       throw new ElasticsearchGenerationException("failed to un-compress", e);
     }
     return mapper;
   } else {
     return merge(parse(type, mappingSource, applyDefault), updateAllTypes);
   }
 }
 public DocumentMapper parse(
     String mappingType, CompressedXContent mappingSource, boolean applyDefault)
     throws MapperParsingException {
   return documentParser.parse(
       mappingType, mappingSource, applyDefault ? defaultMappingSource : null);
 }
 /** Just parses and returns the mapper without adding it. */
 public DocumentMapper parse(String mappingType, String mappingSource)
     throws MapperParsingException {
   return documentParser.parse(mappingType, mappingSource, defaultMappingSource);
 }
    @SuppressWarnings({"unchecked"})
    @Override
    public Mapper.Builder parse(String name, Map<String, Object> node, ParserContext parserContext)
        throws MapperParsingException {
      AttachmentMapper.Builder builder = new AttachmentMapper.Builder(name);

      for (Iterator<Map.Entry<String, Object>> iterator = node.entrySet().iterator();
          iterator.hasNext(); ) {
        Map.Entry<String, Object> entry = iterator.next();
        String fieldName = entry.getKey();
        Object fieldNode = entry.getValue();
        if (fieldName.equals("path")
            && parserContext.indexVersionCreated().before(Version.V_2_0_0_beta1)) {
          builder.pathType(parsePathType(name, fieldNode.toString()));
          iterator.remove();
        } else if (fieldName.equals("fields")) {
          Map<String, Object> fieldsNode = (Map<String, Object>) fieldNode;
          for (Iterator<Map.Entry<String, Object>> fieldsIterator =
                  fieldsNode.entrySet().iterator();
              fieldsIterator.hasNext(); ) {
            Map.Entry<String, Object> entry1 = fieldsIterator.next();
            String propName = entry1.getKey();
            Map<String, Object> propNode = (Map<String, Object>) entry1.getValue();

            Mapper.Builder<?, ?> mapperBuilder =
                findMapperBuilder(propNode, propName, parserContext);
            if (parseMultiField(
                (FieldMapper.Builder) mapperBuilder,
                fieldName,
                parserContext,
                propName,
                propNode)) {
              fieldsIterator.remove();
            } else if (propName.equals(name)
                && parserContext.indexVersionCreated().before(Version.V_2_0_0_beta1)) {
              builder.content(mapperBuilder);
              fieldsIterator.remove();
            } else {
              switch (propName) {
                case FieldNames.CONTENT:
                  builder.content(mapperBuilder);
                  fieldsIterator.remove();
                  break;
                case FieldNames.DATE:
                  builder.date(mapperBuilder);
                  fieldsIterator.remove();
                  break;
                case FieldNames.AUTHOR:
                  builder.author(mapperBuilder);
                  fieldsIterator.remove();
                  break;
                case FieldNames.CONTENT_LENGTH:
                  builder.contentLength(mapperBuilder);
                  fieldsIterator.remove();
                  break;
                case FieldNames.CONTENT_TYPE:
                  builder.contentType(mapperBuilder);
                  fieldsIterator.remove();
                  break;
                case FieldNames.KEYWORDS:
                  builder.keywords(mapperBuilder);
                  fieldsIterator.remove();
                  break;
                case FieldNames.LANGUAGE:
                  builder.language(mapperBuilder);
                  fieldsIterator.remove();
                  break;
                case FieldNames.TITLE:
                  builder.title(mapperBuilder);
                  fieldsIterator.remove();
                  break;
                case FieldNames.NAME:
                  builder.name(mapperBuilder);
                  fieldsIterator.remove();
                  break;
              }
            }
          }
          DocumentMapperParser.checkNoRemainingFields(
              fieldName, fieldsNode, parserContext.indexVersionCreated());
          iterator.remove();
        }
      }

      return builder;
    }