/**
  * Writes the given marshaling tree to the given marshal target.
  *
  * <p>Any contained {@link RawObjectNode} will be marshaled in the same way as by {@link
  * #marshal(Object, Collection, MarshalTarget)}.
  *
  * <p>This method performs the equivalent of the following steps:
  *
  * <ul>
  *   <li>find the appropriate marshaler, either the one returned by {@link
  *       ObjectNode#getMarshaler()} if it is non-null, or otherwise the one returned by {@link
  *       #findMarshaler(Object, Collection)},
  *   <li>create a marshal context using {@link #create(Marshaler, Collection, MarshalTarget)},
  *   <li>process the marshaling tree using {@link #acceptTree(ObjectNode)}.
  * </ul>
  *
  * @param tree marshaling tree that needs to be transformed and marshaled
  * @param marshalers collection of {@link Marshaler} instances to choose from when a marshaler
  *     invokes {@link MarshalContext#writeObject(Object, Key)} recursively
  * @param marshalTarget marshal target for elementary marshal operations
  * @throws MarshalingException if a marshaling error occurs
  * @throws IOException if an I/O error occurs
  */
 public static void processMarshalingTree(
     ObjectNode tree, Collection<? extends Marshaler<?>> marshalers, MarshalTarget marshalTarget)
     throws IOException {
   Objects.requireNonNull(tree);
   Objects.requireNonNull(marshalers);
   Objects.requireNonNull(marshalTarget);
   Marshaler<?> marshaler = findMarshalerForObjectNode(tree, marshalers);
   try (DelegatingMarshalContext marshalContext = create(marshaler, marshalers, marshalTarget)) {
     marshalContext.acceptTree(tree);
   }
 }
 /**
  * Marshals an object using the given marshal target.
  *
  * <p>This method performs the equivalent of the following steps:
  *
  * <ul>
  *   <li>find the appropriate marshaler using {@link #findMarshaler(Object, Collection)},
  *   <li>create a marshal context using {@link #create(Marshaler, Collection, MarshalTarget)},
  *   <li>process the object using {@link #acceptObject(Object)}.
  * </ul>
  *
  * @param object object to marshal
  * @param marshalers collection of {@link Marshaler} instances to choose from when a marshaler
  *     invokes {@link MarshalContext#writeObject(Object, Key)} recursively
  * @param marshalTarget marshal target used for elementary marshal operations
  * @throws MarshalingException if a marshaling error occurs
  * @throws IOException if an I/O error occurs
  */
 public static void marshal(
     Object object, Collection<? extends Marshaler<?>> marshalers, MarshalTarget marshalTarget)
     throws IOException {
   Objects.requireNonNull(object);
   Objects.requireNonNull(marshalers);
   Objects.requireNonNull(marshalTarget);
   Marshaler<?> marshaler = findMarshaler(object, marshalers);
   try (DelegatingMarshalContext marshalContext = create(marshaler, marshalers, marshalTarget)) {
     marshalContext.acceptObject(object);
   }
 }
  @Override
  public void writeObject(Object object, Key key) throws IOException {
    Objects.requireNonNull(object);
    newKeyForObject(key);

    Marshaler<?> childMarshaler = findMarshaler(object, marshalers);
    try (DelegatingMarshalContext childContext =
        new DelegatingMarshalContext(
            key, marshalTarget.resolve(key), childMarshaler, marshalers, this)) {
      childContext.acceptObject(object);
    }
  }
 private IOException writeObjectNode(ObjectNode objectNode, @Nullable Key key) {
   assert key != null;
   try (DelegatingMarshalContext childContext =
       new DelegatingMarshalContext(
           key,
           marshalTarget.resolve(key),
           findMarshalerForObjectNode(objectNode, marshalers),
           marshalers,
           DelegatingMarshalContext.this)) {
     newKeyForObject(key);
     childContext.acceptTree(objectNode);
     return null;
   } catch (IOException exception) {
     return exception;
   }
 }
 @Nullable
 @Override
 public IOException visitRawObjectNode(
     RawObjectNode node, @Nullable DelegatingMarshalContext context) {
   assert context != null;
   return run(() -> context.acceptObject(node.getObject()));
 }