class AnnotatedPropertyPathDetector extends TypedVisitor<TypeDefBuilder> {

  protected static final String DOT = ".";
  protected static final String STATUS = ".status.";

  private final String prefix;
  private final String annotationName;
  private final List<Property> parents;
  private final AtomicReference<String> reference;
  private final Deque<Runnable> toRun;

  public AnnotatedPropertyPathDetector(String prefix, String annotationName) {
    this(prefix, annotationName, new ArrayList<>(), new AtomicReference<>(), new ArrayDeque<>());
  }

  public AnnotatedPropertyPathDetector(String prefix, String annotationName, List<Property> parents,
      AtomicReference<String> reference, Deque<Runnable> toRun) {
    this.prefix = prefix;
    this.annotationName = annotationName;
    this.parents = parents;
    this.reference = reference;
    this.toRun = toRun;
  }

  private static boolean excludePropertyProcessing(Property p) {
    for (AnnotationRef annotation : p.getAnnotations()) {
      if (annotation.getClassRef().getFullyQualifiedName().equals(ANNOTATION_JSON_IGNORE)) {
        return true;
      }
    }
    return false;
  }

  @Override
  public void visit(TypeDefBuilder builder) {<FILL_FUNCTION_BODY>}

  private void visitProperties(List<Property> properties) {
    for (Property p : properties) {
      if (parents.contains(p)) {
        continue;
      }

      List<Property> newParents = new ArrayList<>(parents);
      boolean match = false;
      for (AnnotationRef annotation : p.getAnnotations()) {
        match = annotation.getClassRef().getName().equals(annotationName);
        if (match) {
          newParents.add(p);
          reference.set(newParents.stream().map(Property::getName).collect(Collectors.joining(DOT, prefix, "")));
          return;
        }
      }

      if (p.getTypeRef() instanceof ClassRef && !excludePropertyProcessing(p)) {
        ClassRef classRef = (ClassRef) p.getTypeRef();
        TypeDef propertyType = Types.typeDefFrom(classRef);
        if (!propertyType.isEnum() && !classRef.getPackageName().startsWith("java.")) {
          newParents.add(p);
          new TypeDefBuilder(propertyType)
              .accept(new AnnotatedPropertyPathDetector(prefix, annotationName, newParents, reference, toRun));
        }
      }
    }

    if (parents.isEmpty()) {
      while (!toRun.isEmpty() && reference.get() == null) {
        toRun.pop().run();
      }
    }
  }

  public Optional<String> getPath() {
    return Optional.ofNullable(reference.get());
  }
}

    TypeDef type = builder.build();
    final List<Property> properties = type.getProperties();
    visitProperties(properties);
  
<no_super_class>