protected BeanPropertyWriter _constructVirtualProperty(
      JsonAppend.Prop prop, MapperConfig<?> config, AnnotatedClass ac) {
    PropertyMetadata metadata =
        prop.required() ? PropertyMetadata.STD_REQUIRED : PropertyMetadata.STD_OPTIONAL;
    PropertyName propName = _propertyName(prop.name(), prop.namespace());
    JavaType type = config.constructType(prop.type());
    // now, then, we need a placeholder for member (no real Field/Method):
    AnnotatedMember member =
        new VirtualAnnotatedMember(
            ac, ac.getRawType(), propName.getSimpleName(), type.getRawClass());
    // and with that and property definition
    SimpleBeanPropertyDefinition propDef =
        SimpleBeanPropertyDefinition.construct(config, member, propName, metadata, prop.include());

    Class<?> implClass = prop.value();

    HandlerInstantiator hi = config.getHandlerInstantiator();
    VirtualBeanPropertyWriter bpw =
        (hi == null) ? null : hi.virtualPropertyWriterInstance(config, implClass);
    if (bpw == null) {
      bpw =
          (VirtualBeanPropertyWriter)
              ClassUtil.createInstance(implClass, config.canOverrideAccessModifiers());
    }

    // one more thing: give it necessary contextual information
    return bpw.withConfig(config, ac, propDef, type);
  }
  @Override
  public ObjectIdGenerator<?> objectIdGeneratorInstance(
      Annotated annotated, ObjectIdInfo objectIdInfo) throws JsonMappingException {
    Class<?> implClass = objectIdInfo.getGeneratorType();
    HandlerInstantiator hi = _config.getHandlerInstantiator();
    ObjectIdGenerator<?> gen;

    if (hi != null) {
      gen = hi.objectIdGeneratorInstance(_config, annotated, implClass);
    } else {
      gen =
          (ObjectIdGenerator<?>)
              ClassUtil.createInstance(implClass, _config.canOverrideAccessModifiers());
    }
    return gen.forScope(objectIdInfo.getScope());
  }
  @Override
  public JsonSerializer<Object> serializerInstance(Annotated annotated, Object serDef)
      throws JsonMappingException {

    if (serDef == null) {
      return null;
    }
    JsonSerializer<?> ser;

    if (serDef instanceof JsonSerializer) {
      ser = (JsonSerializer<?>) serDef;
    } else {
      /* Alas, there's no way to force return type of "either class
       * X or Y" -- need to throw an exception after the fact
       */
      if (!(serDef instanceof Class)) {
        throw new IllegalStateException(
            "AnnotationIntrospector returned serializer definition of type "
                + serDef.getClass().getName()
                + "; expected type JsonSerializer or Class<JsonSerializer> instead");
      }
      Class<?> serClass = (Class<?>) serDef;
      // there are some known "no class" markers to consider too:
      if (serClass == JsonSerializer.None.class || serClass == NoClass.class) {
        return null;
      }
      if (!JsonSerializer.class.isAssignableFrom(serClass)) {
        throw new IllegalStateException(
            "AnnotationIntrospector returned Class "
                + serClass.getName()
                + "; expected Class<JsonSerializer>");
      }
      HandlerInstantiator hi = _config.getHandlerInstantiator();
      if (hi != null) {
        ser = hi.serializerInstance(_config, annotated, serClass);
      } else {
        ser =
            (JsonSerializer<?>)
                ClassUtil.createInstance(serClass, _config.canOverrideAccessModifiers());
      }
    }
    return (JsonSerializer<Object>) _handleResolvable(ser);
  }