@Override
  public PropertyName findNameForDeserialization(Annotated a) {
    String name;

    // @JsonSetter has precedence over @JsonProperty, being more specific
    // @JsonDeserialize implies that there is a property, but no name
    JsonSetter js = _findAnnotation(a, JsonSetter.class);
    if (js != null) {
      name = js.value();
    } else {
      JsonProperty pann = _findAnnotation(a, JsonProperty.class);
      if (pann != null) {
        name = pann.value();
        /* 22-Apr-2014, tatu: Should figure out a better way to do this, but
         *   it's actually bit tricky to do it more efficiently (meta-annotations
         *   add more lookups; AnnotationMap costs etc)
         */
      } else if (_hasAnnotation(a, JsonDeserialize.class)
          || _hasAnnotation(a, JsonView.class)
          || _hasAnnotation(a, JsonUnwrapped.class) // [#442]
          || _hasAnnotation(a, JsonBackReference.class)
          || _hasAnnotation(a, JsonManagedReference.class)) {
        name = "";
      } else {
        return null;
      }
    }
    return PropertyName.construct(name);
  }
 protected PropertyName _propertyName(String localName, String namespace) {
   if (localName.isEmpty()) {
     return PropertyName.USE_DEFAULT;
   }
   if (namespace == null || namespace.isEmpty()) {
     return PropertyName.construct(localName);
   }
   return PropertyName.construct(localName, namespace);
 }
 @Override
 public ObjectIdInfo findObjectIdInfo(Annotated ann) {
   JsonIdentityInfo info = _findAnnotation(ann, JsonIdentityInfo.class);
   if (info == null || info.generator() == ObjectIdGenerators.None.class) {
     return null;
   }
   // In future may need to allow passing namespace?
   PropertyName name = PropertyName.construct(info.property());
   return new ObjectIdInfo(name, info.scope(), info.generator(), info.resolver());
 }
 @Override
 public PropertyName findRootName(AnnotatedClass ac) {
   JsonRootName ann = _findAnnotation(ac, JsonRootName.class);
   if (ann == null) {
     return null;
   }
   String ns = ann.namespace();
   if (ns != null && ns.length() == 0) {
     ns = null;
   }
   return PropertyName.construct(ann.value(), ns);
 }
  @Override
  public PropertyName findNameForSerialization(Annotated a) {
    String name = null;

    JsonGetter jg = _findAnnotation(a, JsonGetter.class);
    if (jg != null) {
      name = jg.value();
    } else {
      JsonProperty pann = _findAnnotation(a, JsonProperty.class);
      if (pann != null) {
        name = pann.value();
      } else if (_hasAnnotation(a, JsonSerialize.class)
          || _hasAnnotation(a, JsonView.class)
          || _hasAnnotation(a, JsonRawValue.class)) {
        name = "";
      } else {
        return null;
      }
    }
    return PropertyName.construct(name);
  }
  protected BeanPropertyWriter _constructVirtualProperty(
      JsonAppend.Attr attr, MapperConfig<?> config, AnnotatedClass ac, JavaType type) {
    PropertyMetadata metadata =
        attr.required() ? PropertyMetadata.STD_REQUIRED : PropertyMetadata.STD_OPTIONAL;
    // could add Index, Description in future, if those matter
    String attrName = attr.value();

    // allow explicit renaming; if none, default to attribute name
    PropertyName propName = _propertyName(attr.propName(), attr.propNamespace());
    if (!propName.hasSimpleName()) {
      propName = PropertyName.construct(attrName);
    }
    // now, then, we need a placeholder for member (no real Field/Method):
    AnnotatedMember member =
        new VirtualAnnotatedMember(ac, ac.getRawType(), attrName, type.getRawClass());
    // and with that and property definition
    SimpleBeanPropertyDefinition propDef =
        SimpleBeanPropertyDefinition.construct(config, member, propName, metadata, attr.include());
    // can construct the property writer
    return AttributePropertyWriter.construct(attrName, propDef, ac.getAnnotations(), type);
  }