001/*
002 * SPDX-FileCopyrightText: none
003 * SPDX-License-Identifier: CC0-1.0
004 */
005
006package dev.metaschema.databind.io.json;
007
008import com.fasterxml.jackson.core.JsonFactory;
009import com.fasterxml.jackson.core.JsonGenerator;
010import com.fasterxml.jackson.core.JsonParser;
011import com.fasterxml.jackson.databind.ObjectMapper;
012
013import edu.umd.cs.findbugs.annotations.NonNull;
014
015/**
016 * A factory for creating and configuring {@link JsonFactory} instances with
017 * standard Metaschema settings.
018 * <p>
019 * This class provides a singleton factory instance configured for optimal use
020 * with Metaschema data binding operations. The factory is configured to not
021 * auto-close streams and includes a default codec.
022 */
023public final class JsonFactoryFactory {
024  @NonNull
025  private static final JsonFactory SINGLETON = newJsonFactoryInstance();
026
027  /**
028   * Private constructor to prevent instantiation.
029   */
030  private JsonFactoryFactory() {
031    // disable construction
032  }
033
034  /**
035   * Create a new {@link JsonFactory}.
036   *
037   * @return the factory
038   */
039  @NonNull
040  private static JsonFactory newJsonFactoryInstance() {
041    JsonFactory retval = new JsonFactory();
042    configureJsonFactory(retval);
043    return retval;
044  }
045
046  /**
047   * Get the cached {@link JsonFactory} instance.
048   *
049   * @return the factory
050   */
051  @NonNull
052  public static JsonFactory instance() {
053    return SINGLETON;
054  }
055
056  /**
057   * Apply a standard configuration to the provided JSON {@code factory}.
058   *
059   * @param factory
060   *          the factory to configure
061   */
062  public static void configureJsonFactory(@NonNull JsonFactory factory) {
063    // avoid automatically closing parsing streams not owned by the reader
064    factory.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE);
065    // avoid automatically closing generation streams not owned by the reader
066    factory.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
067    // ensure there is a default codec
068    factory.setCodec(new ObjectMapper(factory));
069  }
070}