in hollow/src/main/java/com/netflix/hollow/core/read/filter/TypeFilter.java [398:460]
private Stream<TypeActions> descendants(Rule rule, HollowSchema schema) {
String type = schema.getName();
Action action = rule.apply(type, null);
TypeActions parent = TypeActions.newTypeActions(type, action);
switch (schema.getSchemaType()) {
case OBJECT:
HollowObjectSchema os = (HollowObjectSchema) schema;
return IntStream
.range(0, os.numFields())
.boxed()
.flatMap(i -> {
String field = os.getFieldName(i);
Action fa = rule.apply(type, field);
if (fa == next) return Stream.empty();
TypeActions child = newTypeActions(type, field, fa);
Action descendantAction = fa.recursive ? fa : action;
if (descendantAction.recursive && os.getFieldType(i) == REFERENCE) {
String refType = os.getReferencedType(i);
HollowSchema refSchema = schemas.get(refType);
assert refSchema != null;
Stream<TypeActions> descendants = descendants((t,f) -> descendantAction, refSchema);
return Stream.concat(Stream.of(parent, child), descendants);
} else {
return Stream.of(parent, child);
}
});
case SET:
case LIST:
if (action == next) {
return Stream.empty();
} else if (action.recursive) {
HollowCollectionSchema cs = (HollowCollectionSchema) schema;
HollowSchema elemSchema = schemas.get(cs.getElementType());
assert elemSchema != null;
Stream<TypeActions> descendants = descendants((t, f) -> action, elemSchema);
return Stream.concat(Stream.of(parent), descendants);
} else {
return Stream.of(parent);
}
case MAP:
if (action == next) {
return Stream.empty();
} else if (action.recursive) {
HollowMapSchema ms = (HollowMapSchema) schema;
HollowSchema kSchema = schemas.get(ms.getKeyType());
HollowSchema vSchema = schemas.get(ms.getValueType());
Stream<TypeActions> descendants = Stream.concat(
descendants((t, f) -> action, kSchema),
descendants((t1, f1) -> action, vSchema));
return Stream.concat(Stream.of(parent), descendants);
} else {
return Stream.of(parent);
}
default:
throw new UnrecognizedSchemaTypeException(type, schema.getSchemaType());
}
}