001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.serializer;
018
019import static org.apache.juneau.commons.utils.AssertionUtils.*;
020import static org.apache.juneau.commons.utils.StringUtils.*;
021
022import java.io.*;
023import java.lang.reflect.*;
024import java.util.*;
025import java.util.function.*;
026
027import org.apache.juneau.*;
028import org.apache.juneau.httppart.*;
029import org.apache.juneau.svl.*;
030
031/**
032 * Subclass of {@link SerializerSession} for stream-based serializers.
033 *
034 * <h5 class='topic'>Description</h5>
035 *
036 * This class is the parent class of all byte-based serializers.
037 * <br>It has 1 abstract method to implement...
038 * <ul>
039 *    <li>{@link #doSerialize(SerializerPipe, Object)}
040 * </ul>
041 *
042 * <h5 class='section'>Notes:</h5><ul>
043 *    <li class='warn'>This class is not thread safe and is typically discarded after one use.
044 * </ul>
045 *
046 * <h5 class='section'>See Also:</h5><ul>
047 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/SerializersAndParsers">Serializers and Parsers</a>
048 * </ul>
049 */
050public class OutputStreamSerializerSession extends SerializerSession {
051   /**
052    * Builder class.
053    */
054   public static class Builder extends SerializerSession.Builder {
055
056      private OutputStreamSerializer ctx;
057
058      /**
059       * Constructor
060       *
061       * @param ctx The context creating this session.
062       *    <br>Cannot be <jk>null</jk>.
063       */
064      protected Builder(OutputStreamSerializer ctx) {
065         super(assertArgNotNull("ctx", ctx));
066         this.ctx = ctx;
067      }
068
069      @Override /* Overridden from Builder */
070      public <T> Builder apply(Class<T> type, Consumer<T> apply) {
071         super.apply(type, apply);
072         return this;
073      }
074
075      @Override
076      public OutputStreamSerializerSession build() {
077         return new OutputStreamSerializerSession(this);
078      }
079
080      @Override /* Overridden from Builder */
081      public Builder debug(Boolean value) {
082         super.debug(value);
083         return this;
084      }
085
086      @Override /* Overridden from Builder */
087      public Builder javaMethod(Method value) {
088         super.javaMethod(value);
089         return this;
090      }
091
092      @Override /* Overridden from Builder */
093      public Builder locale(Locale value) {
094         super.locale(value);
095         return this;
096      }
097
098      @Override /* Overridden from Builder */
099      public Builder mediaType(MediaType value) {
100         super.mediaType(value);
101         return this;
102      }
103
104      @Override /* Overridden from Builder */
105      public Builder mediaTypeDefault(MediaType value) {
106         super.mediaTypeDefault(value);
107         return this;
108      }
109
110      @Override /* Overridden from Builder */
111      public Builder properties(Map<String,Object> value) {
112         super.properties(value);
113         return this;
114      }
115
116      @Override /* Overridden from Builder */
117      public Builder property(String key, Object value) {
118         super.property(key, value);
119         return this;
120      }
121
122      @Override /* Overridden from Builder */
123      public Builder resolver(VarResolverSession value) {
124         super.resolver(value);
125         return this;
126      }
127
128      @Override /* Overridden from Builder */
129      public Builder schema(HttpPartSchema value) {
130         super.schema(value);
131         return this;
132      }
133
134      @Override /* Overridden from Builder */
135      public Builder schemaDefault(HttpPartSchema value) {
136         super.schemaDefault(value);
137         return this;
138      }
139
140      @Override /* Overridden from Builder */
141      public Builder timeZone(TimeZone value) {
142         super.timeZone(value);
143         return this;
144      }
145
146      @Override /* Overridden from Builder */
147      public Builder timeZoneDefault(TimeZone value) {
148         super.timeZoneDefault(value);
149         return this;
150      }
151
152      @Override /* Overridden from Builder */
153      public Builder unmodifiable() {
154         super.unmodifiable();
155         return this;
156      }
157
158      @Override /* Overridden from Builder */
159      public Builder uriContext(UriContext value) {
160         super.uriContext(value);
161         return this;
162      }
163   }
164
165   /**
166    * Creates a new builder for this object.
167    *
168    * @param ctx The context creating this session.
169    *    <br>Cannot be <jk>null</jk>.
170    * @return A new builder.
171    */
172   public static Builder create(OutputStreamSerializer ctx) {
173      return new Builder(assertArgNotNull("ctx", ctx));
174   }
175
176   private final OutputStreamSerializer ctx;
177
178   /**
179    * Constructor.
180    *
181    * @param builder The builder for this object.
182    */
183   protected OutputStreamSerializerSession(Builder builder) {
184      super(builder);
185      ctx = builder.ctx;
186   }
187
188   @Override /* Overridden from SerializerSession */
189   public final boolean isWriterSerializer() { return false; }
190
191   /**
192    * Convenience method for serializing an object to a <code><jk>byte</jk></code>.
193    *
194    * @param o The object to serialize.
195    * @return The output serialized to a byte array.
196    * @throws SerializeException If a problem occurred trying to convert the output.
197    */
198   @Override /* Overridden from SerializerSession */
199   public final byte[] serialize(Object o) throws SerializeException {
200      var baos = new ByteArrayOutputStream();
201      try {
202         serialize(o, baos);
203         baos.flush();
204      } catch (IOException e) {
205         throw new SerializeException(e); // Should never happen.
206      }
207      return baos.toByteArray();
208   }
209
210   @Override /* Overridden from SerializerSession */
211   public final String serializeToString(Object o) throws SerializeException {
212      var b = serialize(o);
213      return switch (getBinaryFormat()) {
214         case SPACED_HEX -> toSpacedHex(b);
215         case HEX -> toHex(b);
216         case BASE64 -> base64Encode(b);
217         default -> null;
218      };
219   }
220
221   @Override /* Overridden from SerializerSession */
222   protected SerializerPipe createPipe(Object output) {
223      return new SerializerPipe(output);
224   }
225
226   /**
227    * Binary output format.
228    *
229    * @see OutputStreamSerializer.Builder#binaryFormat(BinaryFormat)
230    * @return
231    *    The format to use for the {@link #serializeToString(Object)} method on stream-based serializers when converting byte arrays to strings.
232    */
233   protected final BinaryFormat getBinaryFormat() { return ctx.getBinaryFormat(); }
234}