/**
   * Main serialization method needs to be overridden to allow XML-specific extra handling, such as
   * indication of whether to write attributes or elements.
   */
  @Override
  protected void serializeFields(Object bean, JsonGenerator jgen0, SerializerProvider provider)
      throws IOException, JsonGenerationException {
    // 19-Aug-2013, tatu: During 'convertValue()', need to skip
    if (!(jgen0 instanceof ToXmlGenerator)) {
      super.serializeFields(bean, jgen0, provider);
      return;
    }

    final ToXmlGenerator xgen = (ToXmlGenerator) jgen0;
    final BeanPropertyWriter[] props;
    if (_filteredProps != null && provider.getActiveView() != null) {
      props = _filteredProps;
    } else {
      props = _props;
    }

    final int attrCount = _attributeCount;
    if (attrCount > 0) {
      xgen.setNextIsAttribute(true);
    }
    final int textIndex = _textPropertyIndex;
    final QName[] xmlNames = _xmlNames;
    int i = 0;

    try {
      for (final int len = props.length; i < len; ++i) {
        if (i == attrCount) {
          xgen.setNextIsAttribute(false);
        }
        // also: if this is property to write as text ("unwrap"), need to:
        if (i == textIndex) {
          xgen.setNextIsUnwrapped(true);
        }
        xgen.setNextName(xmlNames[i]);
        BeanPropertyWriter prop = props[i];
        if (prop != null) { // can have nulls in filtered list
          prop.serializeAsField(bean, xgen, provider);
        }
        // Reset to avoid next value being written as unwrapped,
        // for example when property is suppressed
        if (i == textIndex) {
          xgen.setNextIsUnwrapped(false);
        }
      }
      if (_anyGetterWriter != null) {
        _anyGetterWriter.getAndSerialize(bean, xgen, provider);
      }
    } catch (Exception e) {
      String name = (i == props.length) ? "[anySetter]" : props[i].getName();
      wrapAndThrow(provider, e, bean, name);
    } catch (StackOverflowError e) { // Bit tricky, can't do more calls as stack is full; so:
      JsonMappingException mapE =
          new JsonMappingException("Infinite recursion (StackOverflowError)");
      String name = (i == props.length) ? "[anySetter]" : props[i].getName();
      mapE.prependPath(new JsonMappingException.Reference(bean, name));
      throw mapE;
    }
  }
 /**
  * Method that can be used to serialize any Java value as a String. Functionally equivalent to
  * calling {@link #writeValue(Writer,Object)} with {@link java.io.StringWriter} and constructing
  * String, but more efficient.
  *
  * <p>Note: prior to version 2.1, throws clause included {@link IOException}; 2.1 removed it.
  */
 public String writeValueAsString(Object value) throws JsonProcessingException {
   // alas, we have to pull the recycler directly here...
   SegmentedStringWriter sw = new SegmentedStringWriter(_jsonFactory._getBufferRecycler());
   try {
     _configAndWriteValue(_jsonFactory.createJsonGenerator(sw), value);
   } catch (JsonProcessingException e) { // to support [JACKSON-758]
     throw e;
   } catch (IOException e) { // shouldn't really happen, but is declared as possibility so:
     throw JsonMappingException.fromUnexpectedIOE(e);
   }
   return sw.getAndClear();
 }
 /**
  * Method that can be used to serialize any Java value as a byte array. Functionally equivalent to
  * calling {@link #writeValue(Writer,Object)} with {@link java.io.ByteArrayOutputStream} and
  * getting bytes, but more efficient. Encoding used will be UTF-8.
  *
  * <p>Note: prior to version 2.1, throws clause included {@link IOException}; 2.1 removed it.
  */
 public byte[] writeValueAsBytes(Object value) throws JsonProcessingException {
   ByteArrayBuilder bb = new ByteArrayBuilder(_jsonFactory._getBufferRecycler());
   try {
     _configAndWriteValue(_jsonFactory.createJsonGenerator(bb, JsonEncoding.UTF8), value);
   } catch (JsonProcessingException e) { // to support [JACKSON-758]
     throw e;
   } catch (IOException e) { // shouldn't really happen, but is declared as possibility so:
     throw JsonMappingException.fromUnexpectedIOE(e);
   }
   byte[] result = bb.toByteArray();
   bb.release();
   return result;
 }
  /** Offlined version used when we do not use the default deserialization method. */
  protected final String[] _deserializeCustom(
      JsonParser p, DeserializationContext ctxt, String[] old) throws IOException {
    final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
    int ix;
    Object[] chunk;

    if (old == null) {
      ix = 0;
      chunk = buffer.resetAndStart();
    } else {
      ix = old.length;
      chunk = buffer.resetAndStart(old, ix);
    }

    final JsonDeserializer<String> deser = _elementDeserializer;

    try {
      while (true) {
        /* 30-Dec-2014, tatu: This may look odd, but let's actually call method
         *   that suggest we are expecting a String; this helps with some formats,
         *   notably XML. Note, however, that while we can get String, we can't
         *   assume that's what we use due to custom deserializer
         */
        String value;
        if (p.nextTextValue() == null) {
          JsonToken t = p.getCurrentToken();
          if (t == JsonToken.END_ARRAY) {
            break;
          }
          // Ok: no need to convert Strings, but must recognize nulls
          value =
              (t == JsonToken.VALUE_NULL) ? deser.getNullValue(ctxt) : deser.deserialize(p, ctxt);
        } else {
          value = deser.deserialize(p, ctxt);
        }
        if (ix >= chunk.length) {
          chunk = buffer.appendCompletedChunk(chunk);
          ix = 0;
        }
        chunk[ix++] = value;
      }
    } catch (Exception e) {
      // note: pass String.class, not String[].class, as we need element type for error info
      throw JsonMappingException.wrapWithPath(e, String.class, ix);
    }
    String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
    ctxt.returnObjectBuffer(buffer);
    return result;
  }
  @Override
  public String[] deserialize(JsonParser p, DeserializationContext ctxt, String[] intoValue)
      throws IOException {
    // Ok: must point to START_ARRAY (or equivalent)
    if (!p.isExpectedStartArrayToken()) {
      String[] arr = handleNonArray(p, ctxt);
      if (arr == null) {
        return intoValue;
      }
      final int offset = intoValue.length;
      String[] result = new String[offset + arr.length];
      System.arraycopy(intoValue, 0, result, 0, offset);
      System.arraycopy(arr, 0, result, offset, arr.length);
      return result;
    }

    if (_elementDeserializer != null) {
      return _deserializeCustom(p, ctxt, intoValue);
    }
    final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
    int ix = intoValue.length;
    Object[] chunk = buffer.resetAndStart(intoValue, ix);

    try {
      while (true) {
        String value = p.nextTextValue();
        if (value == null) {
          JsonToken t = p.getCurrentToken();
          if (t == JsonToken.END_ARRAY) {
            break;
          }
          if (t != JsonToken.VALUE_NULL) {
            value = _parseString(p, ctxt);
          }
        }
        if (ix >= chunk.length) {
          chunk = buffer.appendCompletedChunk(chunk);
          ix = 0;
        }
        chunk[ix++] = value;
      }
    } catch (Exception e) {
      throw JsonMappingException.wrapWithPath(e, chunk, buffer.bufferedSize() + ix);
    }
    String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
    ctxt.returnObjectBuffer(buffer);
    return result;
  }
 public JsonMappingException endOfInputException(Class<?> instClass) {
   return JsonMappingException.from(
       _parser, "Unexpected end-of-input when trying to deserialize a " + instClass.getName());
 }
 /**
  * Helper method for constructing exception to indicate that given type id (parsed from JSON)
  * could not be converted to a Java type.
  */
 public JsonMappingException unknownTypeException(JavaType type, String id) {
   return JsonMappingException.from(
       _parser, "Could not resolve type id '" + id + "' into a subtype of " + type);
 }
 public JsonMappingException instantiationException(Class<?> instClass, String msg) {
   return JsonMappingException.from(
       _parser, "Can not construct instance of " + instClass.getName() + ", problem: " + msg);
 }
 /**
  * Helper method for constructing instantiation exception for specified type, to indicate problem
  * with physically constructing instance of specified class (missing constructor, exception from
  * constructor)
  */
 public JsonMappingException instantiationException(Class<?> instClass, Throwable t) {
   return JsonMappingException.from(
       _parser,
       "Can not construct instance of " + instClass.getName() + ", problem: " + t.getMessage(),
       t);
 }
 /**
  * Helper method for constructing generic mapping exception with specified message and current
  * location information
  */
 public JsonMappingException mappingException(String message) {
   return JsonMappingException.from(getParser(), message);
 }
 public JsonMappingException mappingException(Class<?> targetClass, JsonToken token) {
   String clsName = _calcName(targetClass);
   return JsonMappingException.from(
       _parser, "Can not deserialize instance of " + clsName + " out of " + token + " token");
 }
 /** Helper method for indicating that the current token was expected to be another token. */
 public JsonMappingException wrongTokenException(JsonParser jp, JsonToken expToken, String msg) {
   return JsonMappingException.from(
       jp, "Unexpected token (" + jp.getCurrentToken() + "), expected " + expToken + ": " + msg);
 }