@Override
  public EnumMap<?, ?> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
    // Ok: must point to START_OBJECT
    if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
      return _deserializeFromEmpty(jp, ctxt);
    }
    EnumMap result = constructMap();
    final JsonDeserializer<Object> valueDes = _valueDeserializer;
    final TypeDeserializer typeDeser = _valueTypeDeserializer;

    while ((jp.nextToken()) == JsonToken.FIELD_NAME) {
      String keyName = jp.getCurrentName(); // just for error message
      // but we need to let key deserializer handle it separately, nonetheless
      Enum<?> key = (Enum<?>) _keyDeserializer.deserializeKey(keyName, ctxt);
      if (key == null) {
        if (!ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) {
          throw ctxt.weirdStringException(
              keyName,
              _enumClass,
              "value not one of declared Enum instance names for " + _mapType.getKeyType());
        }
        /* 24-Mar-2012, tatu: Null won't work as a key anyway, so let's
         *  just skip the entry then. But we must skip the value as well, if so.
         */
        jp.nextToken();
        jp.skipChildren();
        continue;
      }
      // And then the value...
      JsonToken t = jp.nextToken();
      /* note: MUST check for nulls separately: deserializers will
       * not handle them (and maybe fail or return bogus data)
       */
      Object value;

      try {
        if (t == JsonToken.VALUE_NULL) {
          value = valueDes.getNullValue(ctxt);
        } else if (typeDeser == null) {
          value = valueDes.deserialize(jp, ctxt);
        } else {
          value = valueDes.deserializeWithType(jp, ctxt, typeDeser);
        }
      } catch (Exception e) {
        wrapAndThrow(e, result, keyName);
        return null;
      }
      result.put(key, value);
    }
    return result;
  }
  @SuppressWarnings("unchecked")
  public Map<Object, Object> _deserializeUsingCreator(JsonParser jp, DeserializationContext ctxt)
      throws IOException, JsonProcessingException {
    final Creator.PropertyBased creator = _propertyBasedCreator;
    PropertyValueBuffer buffer = creator.startBuilding(jp, ctxt);

    JsonToken t = jp.getCurrentToken();
    if (t == JsonToken.START_OBJECT) {
      t = jp.nextToken();
    }
    final JsonDeserializer<Object> valueDes = _valueDeserializer;
    final TypeDeserializer typeDeser = _valueTypeDeserializer;
    for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
      String propName = jp.getCurrentName();
      t = jp.nextToken(); // to get to value
      if (_ignorableProperties != null && _ignorableProperties.contains(propName)) {
        jp.skipChildren(); // and skip it (in case of array/object)
        continue;
      }
      // creator property?
      SettableBeanProperty prop = creator.findCreatorProperty(propName);
      if (prop != null) {
        // Last property to set?
        Object value = prop.deserialize(jp, ctxt);
        if (buffer.assignParameter(prop.getCreatorIndex(), value)) {
          jp.nextToken();
          Map<Object, Object> result = (Map<Object, Object>) creator.build(buffer);
          _readAndBind(jp, ctxt, result);
          return result;
        }
        continue;
      }
      // other property? needs buffering
      String fieldName = jp.getCurrentName();
      Object key =
          (_keyDeserializer == null) ? fieldName : _keyDeserializer.deserializeKey(fieldName, ctxt);
      Object value;
      if (t == JsonToken.VALUE_NULL) {
        value = null;
      } else if (typeDeser == null) {
        value = valueDes.deserialize(jp, ctxt);
      } else {
        value = valueDes.deserializeWithType(jp, ctxt, typeDeser);
      }
      buffer.bufferMapProperty(key, value);
    }
    // end of JSON object?
    // if so, can just construct and leave...
    return (Map<Object, Object>) creator.build(buffer);
  }
 protected final void _readAndBind(
     JsonParser jp, DeserializationContext ctxt, Map<Object, Object> result)
     throws IOException, JsonProcessingException {
   JsonToken t = jp.getCurrentToken();
   if (t == JsonToken.START_OBJECT) {
     t = jp.nextToken();
   }
   final KeyDeserializer keyDes = _keyDeserializer;
   final JsonDeserializer<Object> valueDes = _valueDeserializer;
   final TypeDeserializer typeDeser = _valueTypeDeserializer;
   for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
     // Must point to field name
     String fieldName = jp.getCurrentName();
     Object key = (keyDes == null) ? fieldName : keyDes.deserializeKey(fieldName, ctxt);
     // And then the value...
     t = jp.nextToken();
     if (_ignorableProperties != null && _ignorableProperties.contains(fieldName)) {
       jp.skipChildren();
       continue;
     }
     // Note: must handle null explicitly here; value deserializers won't
     Object value;
     if (t == JsonToken.VALUE_NULL) {
       value = null;
     } else if (typeDeser == null) {
       value = valueDes.deserialize(jp, ctxt);
     } else {
       value = valueDes.deserializeWithType(jp, ctxt, typeDeser);
     }
     /* !!! 23-Dec-2008, tatu: should there be an option to verify
      *   that there are no duplicate field names? (and/or what
      *   to do, keep-first or keep-last)
      */
     result.put(key, value);
   }
 }