/**
   * Method called to locate regular serializer, matching type serializer, and if both found, wrap
   * them in a serializer that calls both in correct sequence. This method is currently only used
   * for root-level serializer handling to allow for simpler caching. A call can always be replaced
   * by equivalent calls to access serializer and type serializer separately.
   *
   * @param valueType Declared type of value being serialized (which may not be actual runtime
   *     type); used for finding both value serializer and type serializer to use for adding
   *     polymorphic type (if any)
   * @param cache Whether resulting value serializer should be cached or not; this is just a hint
   * @param property When creating secondary serializers, property for which serializer is needed:
   *     annotations of the property (or bean that contains it) may be checked to create contextual
   *     serializers.
   */
  public JsonSerializer<Object> findTypedValueSerializer(
      JavaType valueType, boolean cache, BeanProperty property) throws JsonMappingException {
    // Two-phase lookups; local non-shared cache, then shared:
    JsonSerializer<Object> ser = _knownSerializers.typedValueSerializer(valueType);
    if (ser != null) {
      return ser;
    }
    // If not, maybe shared map already has it?
    ser = _serializerCache.typedValueSerializer(valueType);
    if (ser != null) {
      return ser;
    }

    // Well, let's just compose from pieces:
    ser = findValueSerializer(valueType, property);
    TypeSerializer typeSer = _serializerFactory.createTypeSerializer(_config, valueType);
    if (typeSer != null) {
      typeSer = typeSer.forProperty(property);
      ser = new TypeWrappedSerializer(typeSer, ser);
    }
    if (cache) {
      _serializerCache.addTypedSerializer(valueType, ser);
    }
    return ser;
  }