protected ObjectMapper createMapper(String name, String fullPath, boolean enabled, Nested nested, Dynamic dynamic, Boolean includeInAll, Map<String, Mapper> mappers, @Nullable Settings settings) { return new ObjectMapper(name, fullPath, enabled, nested, dynamic, includeInAll, mappers, settings); } }
@Override public ObjectMapper merge(Mapper mergeWith, boolean updateAllTypes) { if (!(mergeWith instanceof ObjectMapper)) { throw new IllegalArgumentException("Can't merge a non object mapping [" + mergeWith.name() + "] with an object mapping [" + name() + "]"); } ObjectMapper mergeWithObject = (ObjectMapper) mergeWith; ObjectMapper merged = clone(); merged.doMerge(mergeWithObject, updateAllTypes); return merged; }
public void toXContent(XContentBuilder builder, Params params, ToXContent custom) throws IOException { builder.startObject(simpleName()); if (nested.isNested()) { builder.field("type", NESTED_CONTENT_TYPE); doXContent(builder, params);
private static void checkObjectsCompatibility(Collection<ObjectMapper> objectMappers, Map<String, ObjectMapper> fullPathObjectMappers, boolean updateAllTypes) { for (ObjectMapper newObjectMapper : objectMappers) { ObjectMapper existingObjectMapper = fullPathObjectMappers.get(newObjectMapper.fullPath()); if (existingObjectMapper != null) { // simulate a merge and ignore the result, we are just interested // in exceptions here existingObjectMapper.merge(newObjectMapper, updateAllTypes); } } }
private static void checkEnabledFieldChange(ObjectMapper mergeWith, Mapper mergeWithMapper, Mapper mergeIntoMapper) { if (mergeIntoMapper instanceof ObjectMapper && mergeWithMapper instanceof ObjectMapper) { final ObjectMapper mergeIntoObjectMapper = (ObjectMapper) mergeIntoMapper; final ObjectMapper mergeWithObjectMapper = (ObjectMapper) mergeWithMapper; if (mergeIntoObjectMapper.isEnabled() != mergeWithObjectMapper.isEnabled()) { final String path = mergeWith.fullPath() + "." + mergeWithObjectMapper.simpleName() + ".enabled"; throw new MapperException("Can't update attribute for type [" + path + "] in index mapping"); } } }
static void parseObjectOrNested(ParseContext context, ObjectMapper mapper) throws IOException { if (mapper.isEnabled() == false) { context.parser().skipChildren(); return; throw new MapperParsingException("object mapping for [" + mapper.name() + "] tried to parse field [" + currentFieldName + "] as object, but found a concrete value"); ObjectMapper.Nested nested = mapper.nested(); if (nested.isNested()) { context = nestedContext(context, mapper); Boolean includeInAll = mapper.includeInAll(); if (includeInAll != null) { context = context.setIncludeInAllDefault(includeInAll);
ObjectMapper nestedObjectMapper = null; for (ObjectMapper objectMapper : objectMappers().values()) { if (!objectMapper.nested().isNested()) { continue; Query filter = objectMapper.nestedTypeFilter(); if (filter == null) { continue; nestedObjectMapper = objectMapper; } else { if (nestedObjectMapper.fullPath().length() < objectMapper.fullPath().length()) { nestedObjectMapper = objectMapper;
} else if (mapper instanceof ObjectMapper) { final ObjectMapper objectMapper = (ObjectMapper)mapper; final ObjectMapper.Nested nested = objectMapper.nested(); beginNestedDocument(objectMapper.fullPath(),new Uid(docMapper.type(), id)); final ParseContext.Document nestedDoc = doc(); final ParseContext.Document parentDoc = nestedDoc.getParent(); nestedDoc.add(new Field(UidFieldMapper.NAME, uidField.stringValue(), UidFieldMapper.Defaults.NESTED_FIELD_TYPE)); nestedDoc.add(new Field(TypeFieldMapper.NAME, objectMapper.nestedTypePathAsString(), TypeFieldMapper.Defaults.FIELD_TYPE)); Mapper subMapper = objectMapper.getMapper(entry.getKey()); subMapper = newObjectMapper.getMapper(entry.getKey()); try { if ((subMapper = objectMapper.getMapper(entry.getKey())) == null) { final String valueType = ClusterService.cqlMapping.get(((MapType)ctype).getValuesType().asCQL3Type().toString()); final DynamicTemplate dynamicTemplate = docMapper.root().findTemplate(path, objectMapper.name()+"."+entry.getKey(), null); DocumentMapper docMapper = indexInfo.indexService.mapperService().documentMapper(indexInfo.type); ObjectMapper newObjectMapper = docMapper.objectMappers().get(mapper.name()); subMapper = newObjectMapper.getMapper(entry.getKey());
/** Build an update for the parent which will contain the given mapper and any intermediate fields. */ private static ObjectMapper createUpdate(ObjectMapper parent, String[] nameParts, int i, Mapper mapper) { List<ObjectMapper> parentMappers = new ArrayList<>(); ObjectMapper previousIntermediate = parent; for (; i < nameParts.length - 1; ++i) { Mapper intermediate = previousIntermediate.getMapper(nameParts[i]); assert intermediate != null : "Field " + previousIntermediate.name() + " does not have a subfield " + nameParts[i]; assert intermediate instanceof ObjectMapper; parentMappers.add((ObjectMapper)intermediate); previousIntermediate = (ObjectMapper)intermediate; } if (parentMappers.isEmpty() == false) { // add the new mapper to the stack, and pop down to the original parent level addToLastMapper(parentMappers, mapper, false); popMappers(parentMappers, 1, false); mapper = parentMappers.get(0); } return parent.mappingUpdate(mapper); }
/** Returns true if a query on the given field might match parent documents * or documents that are nested under a different path. */ boolean mightMatchNonNestedDocs(String field, String nestedPath) { if (field.startsWith("_")) { // meta field. Every meta field behaves differently, eg. nested // documents have the same _uid as their parent, put their path in // the _type field but do not have _field_names. So we just ignore // meta fields and return true, which is always safe, it just means // we might add a nested filter when it is nor required. return true; } if (mapperService.fullName(field) == null) { return false; } for (String parent = parentObject(field); parent != null; parent = parentObject(parent)) { ObjectMapper mapper = mapperService.getObjectMapper(parent); if (mapper!= null && mapper.nested().isNested()) { if (mapper.fullPath().equals(nestedPath)) { // If the mapper does not include in its parent or in the root object then // the query might only match nested documents with the given path return mapper.nested().isIncludeInParent() || mapper.nested().isIncludeInRoot(); } else { // the first parent nested mapper does not have the expected path // It might be misconfiguration or a sub nested mapper return true; } } } return true; // the field is not a sub field of the nested path }
continue; columnsMap.put(column, objectMapper.cqlPartialUpdate()); if (objectMapper.cqlPrimaryKeyOrder() >= 0) { if (objectMapper.cqlPrimaryKeyOrder() < primaryKeyList.length && primaryKeyList[objectMapper.cqlPrimaryKeyOrder()] == null) { primaryKeyList[objectMapper.cqlPrimaryKeyOrder()] = column; primaryKeyLength = Math.max(primaryKeyLength, objectMapper.cqlPrimaryKeyOrder()+1); if (objectMapper.cqlPartitionKey()) { partitionKeyLength++; if (!objectMapper.isEnabled()) { logger.debug("Object [{}] not enabled stored as text", column); cqlType = "text"; } else if (objectMapper.cqlStruct().equals(CqlStruct.MAP)) { if (!objectMapper.cqlCollection().equals(CqlCollection.SINGLETON)) { cqlType = objectMapper.cqlCollectionTag()+"<"+cqlType+">"; } else if (objectMapper.cqlStruct().equals(CqlStruct.UDT)) { cqlType = (objectMapper.isEnabled()) ? "frozen<" + ColumnIdentifier.maybeQuote(buildCql(ksName, cfName, column, objectMapper)) + ">" : "text"; if (!objectMapper.cqlCollection().equals(CqlCollection.SINGLETON) && !(cfName.equals(PERCOLATOR_TABLE) && column.equals("query"))) { cqlType = objectMapper.cqlCollectionTag()+"<"+cqlType+">"; isStatic = objectMapper.cqlStaticColumn();
/** * Returns the parent {@link ObjectMapper} instance of the specified object mapper or <code>null</code> if there * isn't any. */ public ObjectMapper getParentObjectMapper(MapperService mapperService) { int indexOfLastDot = fullPath().lastIndexOf('.'); if (indexOfLastDot != -1) { String parentNestObjectPath = fullPath().substring(0, indexOfLastDot); return mapperService.getObjectMapper(parentNestObjectPath); } else { return null; } }
private static void parseNullValue(ParseContext context, ObjectMapper parentMapper, String lastFieldName) throws IOException { // we can only handle null values if we have mappings for them Mapper mapper = getMapper(parentMapper, lastFieldName, splitAndValidatePath(lastFieldName)); if (mapper != null) { // TODO: passing null to an object seems bogus? parseObjectOrField(context, mapper); } else if (parentMapper.dynamic() == ObjectMapper.Dynamic.STRICT) { throw new StrictDynamicMappingException(parentMapper.fullPath(), lastFieldName); } }
/** * Adds a mapper as an update into the last mapper. If merge is true, the new mapper * will be merged in with other child mappers of the last parent, otherwise it will be a new update. */ private static void addToLastMapper(List<ObjectMapper> parentMappers, Mapper mapper, boolean merge) { assert parentMappers.size() >= 1; int lastIndex = parentMappers.size() - 1; ObjectMapper withNewMapper = parentMappers.get(lastIndex).mappingUpdate(mapper); if (merge) { withNewMapper = parentMappers.get(lastIndex).merge(withNewMapper, false); } parentMappers.set(lastIndex, withNewMapper); }
private static Mapper getMapper(ObjectMapper objectMapper, String fieldName, String[] subfields) { for (int i = 0; i < subfields.length - 1; ++i) { Mapper mapper = objectMapper.getMapper(subfields[i]); if (mapper == null || (mapper instanceof ObjectMapper) == false) { return null; } objectMapper = (ObjectMapper)mapper; if (objectMapper.nested().isNested()) { throw new MapperParsingException("Cannot add a value for field [" + fieldName + "] since one of the intermediate objects is mapped as a nested object: [" + mapper.name() + "]"); } } return objectMapper.getMapper(subfields[subfields.length - 1]); } }
private static ObjectMapper.Dynamic dynamicOrDefault(ObjectMapper parentMapper, ParseContext context) { ObjectMapper.Dynamic dynamic = parentMapper.dynamic(); while (dynamic == null) { int lastDotNdx = parentMapper.name().lastIndexOf('.'); if (lastDotNdx == -1) { // no dot means we the parent is the root, so just delegate to the default outside the loop break; } String parentName = parentMapper.name().substring(0, lastDotNdx); parentMapper = context.docMapper().objectMappers().get(parentName); if (parentMapper == null) { // If parentMapper is ever null, it means the parent of the current mapper was dynamically created. // But in order to be created dynamically, the dynamic setting of that parent was necessarily true return ObjectMapper.Dynamic.TRUE; } dynamic = parentMapper.dynamic(); } if (dynamic == null) { return context.root().dynamic() == null ? ObjectMapper.Dynamic.TRUE : context.root().dynamic(); } return dynamic; }
private static ParseContext nestedContext(ParseContext context, ObjectMapper mapper) { context = context.createNestedContext(mapper.fullPath()); ParseContext.Document nestedDoc = context.doc(); ParseContext.Document parentDoc = nestedDoc.getParent(); nestedDoc.add(new Field(TypeFieldMapper.NAME, mapper.nestedTypePathAsString(), TypeFieldMapper.Defaults.FIELD_TYPE)); return context;
/** * Adds mappers from the end of the stack that exist as updates within those mappers. * Returns the next unprocessed index from nameParts. */ private static int expandCommonMappers(List<ObjectMapper> parentMappers, String[] nameParts, int i) { ObjectMapper last = parentMappers.get(parentMappers.size() - 1); while (i < nameParts.length - 1 && last.getMapper(nameParts[i]) != null) { Mapper newLast = last.getMapper(nameParts[i]); assert newLast instanceof ObjectMapper; last = (ObjectMapper) newLast; parentMappers.add(last); ++i; } return i; }