public <IFD extends IndexFieldData<?>> IFD getForField(FieldDataType type, String fieldName) {
   final FieldMapper<?> mapper;
   final BuilderContext context = new BuilderContext(null, new ContentPath(1));
   if (type.getType().equals("string")) {
     mapper =
         MapperBuilders.stringField(fieldName)
             .tokenized(false)
             .fieldDataSettings(type.getSettings())
             .build(context);
   } else if (type.getType().equals("float")) {
     mapper =
         MapperBuilders.floatField(fieldName).fieldDataSettings(type.getSettings()).build(context);
   } else if (type.getType().equals("double")) {
     mapper =
         MapperBuilders.doubleField(fieldName)
             .fieldDataSettings(type.getSettings())
             .build(context);
   } else if (type.getType().equals("long")) {
     mapper =
         MapperBuilders.longField(fieldName).fieldDataSettings(type.getSettings()).build(context);
   } else if (type.getType().equals("int")) {
     mapper =
         MapperBuilders.integerField(fieldName)
             .fieldDataSettings(type.getSettings())
             .build(context);
   } else if (type.getType().equals("short")) {
     mapper =
         MapperBuilders.shortField(fieldName).fieldDataSettings(type.getSettings()).build(context);
   } else if (type.getType().equals("byte")) {
     mapper =
         MapperBuilders.byteField(fieldName).fieldDataSettings(type.getSettings()).build(context);
   } else if (type.getType().equals("geo_point")) {
     mapper =
         MapperBuilders.geoPointField(fieldName)
             .fieldDataSettings(type.getSettings())
             .build(context);
   } else if (type.getType().equals("_parent")) {
     mapper = MapperBuilders.parent().type(fieldName).build(context);
   } else if (type.getType().equals("binary")) {
     mapper =
         MapperBuilders.binaryField(fieldName)
             .fieldDataSettings(type.getSettings())
             .build(context);
   } else {
     throw new UnsupportedOperationException(type.getType());
   }
   return ifdService.getForField(mapper);
 }
  private void serializeObject(final ParseContext context, String currentFieldName)
      throws IOException {
    if (currentFieldName == null) {
      throw new MapperParsingException(
          "object mapping ["
              + name
              + "] trying to serialize an object with no field associated with it, current value ["
              + context.parser().textOrNull()
              + "]");
    }
    context.path().add(currentFieldName);

    Mapper objectMapper = mappers.get(currentFieldName);
    if (objectMapper != null) {
      objectMapper.parse(context);
    } else {
      Dynamic dynamic = this.dynamic;
      if (dynamic == null) {
        dynamic = context.root().dynamic();
      }
      if (dynamic == Dynamic.STRICT) {
        throw new StrictDynamicMappingException(fullPath, currentFieldName);
      } else if (dynamic == Dynamic.TRUE) {
        // we sync here just so we won't add it twice. Its not the end of the world
        // to sync here since next operations will get it before
        synchronized (mutex) {
          objectMapper = mappers.get(currentFieldName);
          if (objectMapper == null) {
            // remove the current field name from path, since template search and the object builder
            // add it as well...
            context.path().remove();
            Mapper.Builder builder =
                context.root().findTemplateBuilder(context, currentFieldName, "object");
            if (builder == null) {
              builder = MapperBuilders.object(currentFieldName).enabled(true).pathType(pathType);
              // if this is a non root object, then explicitly set the dynamic behavior if set
              if (!(this instanceof RootObjectMapper) && this.dynamic != Defaults.DYNAMIC) {
                ((Builder) builder).dynamic(this.dynamic);
              }
            }
            BuilderContext builderContext =
                new BuilderContext(context.indexSettings(), context.path());
            objectMapper = builder.build(builderContext);
            putDynamicMapper(context, currentFieldName, objectMapper);
          } else {
            objectMapper.parse(context);
          }
        }
      } else {
        // not dynamic, read everything up to end object
        context.parser().skipChildren();
      }
    }

    context.path().remove();
  }
  private static ObjectMapper parseObject(
      final ParseContext context, ObjectMapper mapper, String currentFieldName) throws IOException {
    if (currentFieldName == null) {
      throw new MapperParsingException(
          "object mapping ["
              + mapper.name()
              + "] trying to serialize an object with no field associated with it, current value ["
              + context.parser().textOrNull()
              + "]");
    }
    context.path().add(currentFieldName);

    ObjectMapper update = null;
    Mapper objectMapper = mapper.getMapper(currentFieldName);
    if (objectMapper != null) {
      final Mapper subUpdate = parseObjectOrField(context, objectMapper);
      if (subUpdate != null) {
        // propagate mapping update
        update = mapper.mappingUpdate(subUpdate);
      }
    } else {
      ObjectMapper.Dynamic dynamic = mapper.dynamic();
      if (dynamic == null) {
        dynamic = dynamicOrDefault(context.root().dynamic());
      }
      if (dynamic == ObjectMapper.Dynamic.STRICT) {
        throw new StrictDynamicMappingException(mapper.fullPath(), currentFieldName);
      } else if (dynamic == ObjectMapper.Dynamic.TRUE) {
        // remove the current field name from path, since template search and the object builder add
        // it as well...
        context.path().remove();
        Mapper.Builder builder =
            context.root().findTemplateBuilder(context, currentFieldName, "object");
        if (builder == null) {
          builder = MapperBuilders.object(currentFieldName).enabled(true);
          // if this is a non root object, then explicitly set the dynamic behavior if set
          if (!(mapper instanceof RootObjectMapper)
              && mapper.dynamic() != ObjectMapper.Defaults.DYNAMIC) {
            ((ObjectMapper.Builder) builder).dynamic(mapper.dynamic());
          }
        }
        Mapper.BuilderContext builderContext =
            new Mapper.BuilderContext(context.indexSettings(), context.path());
        objectMapper = builder.build(builderContext);
        context.path().add(currentFieldName);
        update = mapper.mappingUpdate(parseAndMergeUpdate(objectMapper, context));
      } else {
        // not dynamic, read everything up to end object
        context.parser().skipChildren();
      }
    }

    context.path().remove();
    return update;
  }
    @Override
    public Mapper.Builder parse(String name, Map<String, Object> node, ParserContext parserContext)
        throws MapperParsingException {
      IndexFieldMapper.Builder builder = MapperBuilders.index();
      parseField(builder, builder.name, node, parserContext);

      for (Map.Entry<String, Object> entry : node.entrySet()) {
        String fieldName = Strings.toUnderscoreCase(entry.getKey());
        Object fieldNode = entry.getValue();
        if (fieldName.equals("enabled")) {
          builder.enabled(nodeBooleanValue(fieldNode));
        }
      }
      return builder;
    }
Beispiel #5
0
    @Override
    public OntologyMapper build(BuilderContext context) {
      ContentPath.Type origPathType = context.path().pathType();
      context.path().pathType(pathType);

      Map<String, FieldMapper<String>> fieldMappers = Maps.newHashMap();

      context.path().add(name);

      if (propertyBuilders != null) {
        for (String property : propertyBuilders.keySet()) {
          StringFieldMapper sfm = propertyBuilders.get(property).build(context);
          fieldMappers.put(sfm.names().indexName(), sfm);
        }
      }

      // Initialise field mappers for the pre-defined fields
      for (FieldMappings mapping : ontologySettings.getFieldMappings()) {
        if (!fieldMappers.containsKey(context.path().fullPathAsText(mapping.getFieldName()))) {
          StringFieldMapper mapper =
              MapperBuilders.stringField(mapping.getFieldName())
                  .store(true)
                  .index(true)
                  .tokenized(!mapping.isUriField())
                  .build(context);
          fieldMappers.put(mapper.names().indexName(), mapper);
        }
      }

      context.path().remove(); // remove name
      context.path().pathType(origPathType);

      return new OntologyMapper(
          buildNames(context),
          fieldType,
          docValues,
          indexAnalyzer,
          searchAnalyzer,
          postingsProvider,
          docValuesProvider,
          similarity,
          fieldDataSettings,
          context.indexSettings(),
          new MultiFields.Builder().build(this, context),
          ontologySettings,
          fieldMappers,
          threadPool);
    }
 private static Mapper.Builder<?, ?> createBuilderFromFieldType(
     final ParseContext context, MappedFieldType fieldType, String currentFieldName) {
   Mapper.Builder builder = null;
   if (fieldType instanceof StringFieldType) {
     builder = context.root().findTemplateBuilder(context, currentFieldName, "string");
     if (builder == null) {
       builder = MapperBuilders.stringField(currentFieldName);
     }
   } else if (fieldType instanceof DateFieldType) {
     builder = context.root().findTemplateBuilder(context, currentFieldName, "date");
     if (builder == null) {
       builder = MapperBuilders.dateField(currentFieldName);
     }
   } else if (fieldType.numericType() != null) {
     switch (fieldType.numericType()) {
       case LONG:
         builder = context.root().findTemplateBuilder(context, currentFieldName, "long");
         if (builder == null) {
           builder = MapperBuilders.longField(currentFieldName);
         }
         break;
       case DOUBLE:
         builder = context.root().findTemplateBuilder(context, currentFieldName, "double");
         if (builder == null) {
           builder = MapperBuilders.doubleField(currentFieldName);
         }
         break;
       case INT:
         builder = context.root().findTemplateBuilder(context, currentFieldName, "integer");
         if (builder == null) {
           builder = MapperBuilders.integerField(currentFieldName);
         }
         break;
       case FLOAT:
         builder = context.root().findTemplateBuilder(context, currentFieldName, "float");
         if (builder == null) {
           builder = MapperBuilders.floatField(currentFieldName);
         }
         break;
       default:
         throw new AssertionError("Unexpected numeric type " + fieldType.numericType());
     }
   }
   return builder;
 }
  /** Creates an copy of the current field with given field name and boost */
  private static void parseCopy(String field, ParseContext context) throws IOException {
    FieldMapper fieldMapper = context.docMapper().mappers().getMapper(field);
    if (fieldMapper != null) {
      fieldMapper.parse(context);
    } else {
      // The path of the dest field might be completely different from the current one so we need to
      // reset it
      context = context.overridePath(new ContentPath(0));

      String[] paths = Strings.splitStringToArray(field, '.');
      String fieldName = paths[paths.length - 1];
      ObjectMapper mapper = context.root();
      ObjectMapper[] mappers = new ObjectMapper[paths.length - 1];
      if (paths.length > 1) {
        ObjectMapper parent = context.root();
        for (int i = 0; i < paths.length - 1; i++) {
          mapper = context.docMapper().objectMappers().get(context.path().pathAsText(paths[i]));
          if (mapper == null) {
            // One mapping is missing, check if we are allowed to create a dynamic one.
            ObjectMapper.Dynamic dynamic = parent.dynamic();
            if (dynamic == null) {
              dynamic = dynamicOrDefault(context.root().dynamic());
            }

            switch (dynamic) {
              case STRICT:
                throw new StrictDynamicMappingException(parent.fullPath(), paths[i]);
              case TRUE:
                Mapper.Builder builder =
                    context.root().findTemplateBuilder(context, paths[i], "object");
                if (builder == null) {
                  // if this is a non root object, then explicitly set the dynamic behavior if set
                  if (!(parent instanceof RootObjectMapper)
                      && parent.dynamic() != ObjectMapper.Defaults.DYNAMIC) {
                    ((ObjectMapper.Builder) builder).dynamic(parent.dynamic());
                  }
                  builder = MapperBuilders.object(paths[i]).enabled(true);
                }
                Mapper.BuilderContext builderContext =
                    new Mapper.BuilderContext(context.indexSettings(), context.path());
                mapper = (ObjectMapper) builder.build(builderContext);
                if (mapper.nested() != ObjectMapper.Nested.NO) {
                  throw new MapperParsingException(
                      "It is forbidden to create dynamic nested objects (["
                          + context.path().pathAsText(paths[i])
                          + "]) through `copy_to`");
                }
                break;
              case FALSE:
                // Maybe we should log something to tell the user that the copy_to is ignored in
                // this case.
                break;
              default:
                throw new AssertionError("Unexpected dynamic type " + dynamic);
            }
          }
          context.path().add(paths[i]);
          mappers[i] = mapper;
          parent = mapper;
        }
      }
      ObjectMapper update =
          parseDynamicValue(context, mapper, fieldName, context.parser().currentToken());
      assert update
          != null; // we are parsing a dynamic value so we necessarily created a new mapping

      if (paths.length > 1) {
        for (int i = paths.length - 2; i >= 0; i--) {
          ObjectMapper parent = context.root();
          if (i > 0) {
            parent = mappers[i - 1];
          }
          assert parent != null;
          update = parent.mappingUpdate(update);
        }
      }
      context.addDynamicMappingsUpdate(update);
    }
  }
  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
            + "]");
  }
Beispiel #9
0
  @Override
  public void parse(ParseContext context) throws IOException {
    String iri;
    XContentParser parser = context.parser();
    XContentParser.Token token = parser.currentToken();

    if (token == XContentParser.Token.VALUE_STRING) {
      iri = parser.text();
    } else {
      throw new MapperParsingException(name() + " does not contain String value");
    }

    ContentPath.Type origPathType = context.path().pathType();
    context.path().pathType(ContentPath.Type.FULL);
    context.path().add(names.name());

    try {
      OntologyHelper helper = getHelper(ontologySettings, threadPool);

      OntologyData data = findOntologyData(helper, iri);
      if (data == null) {
        logger.debug("Cannot find OWL class for IRI {}", iri);
      } else {
        addFieldData(
            context,
            getPredefinedMapper(FieldMappings.URI, context),
            Collections.singletonList(iri));

        // Look up the label(s)
        addFieldData(context, getPredefinedMapper(FieldMappings.LABEL, context), data.getLabels());

        // Look up the synonyms
        addFieldData(
            context, getPredefinedMapper(FieldMappings.SYNONYMS, context), data.getLabels());

        // Add the child details
        addRelatedNodesWithLabels(
            context,
            data.getChildIris(),
            getPredefinedMapper(FieldMappings.CHILD_URI, context),
            data.getChildLabels(),
            getPredefinedMapper(FieldMappings.CHILD_LABEL, context));

        // Add the parent details
        addRelatedNodesWithLabels(
            context,
            data.getParentIris(),
            getPredefinedMapper(FieldMappings.PARENT_URI, context),
            data.getParentLabels(),
            getPredefinedMapper(FieldMappings.PARENT_LABEL, context));

        if (ontologySettings.isIncludeIndirect()) {
          // Add the descendant details
          addRelatedNodesWithLabels(
              context,
              data.getDescendantIris(),
              getPredefinedMapper(FieldMappings.DESCENDANT_URI, context),
              data.getDescendantLabels(),
              getPredefinedMapper(FieldMappings.DESCENDANT_LABEL, context));

          // Add the ancestor details
          addRelatedNodesWithLabels(
              context,
              data.getAncestorIris(),
              getPredefinedMapper(FieldMappings.ANCESTOR_URI, context),
              data.getAncestorLabels(),
              getPredefinedMapper(FieldMappings.ANCESTOR_LABEL, context));
        }

        if (ontologySettings.isIncludeRelations()) {
          // Add the related nodes
          Map<String, Collection<String>> relations = data.getRelationIris();

          for (String relation : relations.keySet()) {
            // Sanitise the relation name
            String sanRelation = relation.replaceAll("\\W+", "_");
            String uriMapperName = sanRelation + DYNAMIC_URI_FIELD_SUFFIX;
            String labelMapperName = sanRelation + DYNAMIC_LABEL_FIELD_SUFFIX;

            // Get the mapper for the relation
            FieldMapper<String> uriMapper =
                mappers.get(context.path().fullPathAsText(uriMapperName));
            FieldMapper<String> labelMapper =
                mappers.get(context.path().fullPathAsText(labelMapperName));

            if (uriMapper == null) {
              // No mappers created yet - build new ones for URI and label
              BuilderContext builderContext =
                  new BuilderContext(context.indexSettings(), context.path());
              uriMapper =
                  MapperBuilders.stringField(uriMapperName)
                      .store(true)
                      .index(true)
                      .tokenized(false)
                      .build(builderContext);
              labelMapper =
                  MapperBuilders.stringField(labelMapperName)
                      .store(true)
                      .index(true)
                      .tokenized(true)
                      .build(builderContext);
            }

            addRelatedNodesWithLabels(
                context,
                relations.get(relation),
                uriMapper,
                helper.findLabelsForIRIs(relations.get(relation)),
                labelMapper);
          }
        }
      }

      helper.updateLastCallTime();
    } catch (OntologyHelperException e) {
      throw new ElasticsearchException("Could not initialise ontology helper", e);
    } finally {
      context.path().remove();
      context.path().pathType(origPathType);
    }
  }
  private void serializeObject(final ParseContext context, String currentFieldName)
      throws IOException {
    if (currentFieldName == null) {
      throw new MapperParsingException(
          "object mapping ["
              + name
              + "] trying to serialize an object with no field associated with it, current value ["
              + context.parser().textOrNull()
              + "]");
    }
    context.path().add(currentFieldName);

    Mapper objectMapper = mappers.get(currentFieldName);
    if (objectMapper != null) {
      objectMapper.parse(context);
    } else {
      Dynamic dynamic = this.dynamic;
      if (dynamic == null) {
        dynamic = context.root().dynamic();
      }
      if (dynamic == Dynamic.STRICT) {
        throw new StrictDynamicMappingException(currentFieldName);
      } else if (dynamic == Dynamic.TRUE) {
        // we sync here just so we won't add it twice. Its not the end of the world
        // to sync here since next operations will get it before
        boolean newMapper = false;
        synchronized (mutex) {
          objectMapper = mappers.get(currentFieldName);
          if (objectMapper == null) {
            newMapper = true;
            Mapper.Builder builder =
                context.root().findTemplateBuilder(context, currentFieldName, "object");
            if (builder == null) {
              builder =
                  MapperBuilders.object(currentFieldName)
                      .enabled(true)
                      .dynamic(dynamic)
                      .pathType(pathType);
            }
            // remove the current field name from path, since the object builder adds it as well...
            context.path().remove();
            BuilderContext builderContext =
                new BuilderContext(context.indexSettings(), context.path());
            objectMapper = builder.build(builderContext);
            putMapper(objectMapper);
            // now re add it
            context.path().add(currentFieldName);
            context.addedMapper();
          }
        }
        // traverse and parse outside of the mutex
        if (newMapper) {
          // we need to traverse in case we have a dynamic template and need to add field mappers
          // introduced by it
          objectMapper.traverse(
              new FieldMapperListener() {
                @Override
                public void fieldMapper(FieldMapper fieldMapper) {
                  context.docMapper().addFieldMapper(fieldMapper);
                }
              });
          objectMapper.traverse(
              new ObjectMapperListener() {
                @Override
                public void objectMapper(ObjectMapper objectMapper) {
                  context.docMapper().addObjectMapper(objectMapper);
                }
              });
        }
        // now, parse it
        objectMapper.parse(context);
      } else {
        // not dynamic, read everything up to end object
        context.parser().skipChildren();
      }
    }

    context.path().remove();
  }