org.jberet.support.io.JsonItemWriter.java Source code

Java tutorial

Introduction

Here is the source code for org.jberet.support.io.JsonItemWriter.java

Source

/*
 * Copyright (c) 2014-2015 Red Hat, Inc. and/or its affiliates.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * Cheng Fang - Initial API and implementation
 */

package org.jberet.support.io;

import java.io.OutputStream;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import javax.batch.api.BatchProperty;
import javax.batch.api.chunk.ItemWriter;
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import javax.inject.Named;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.PrettyPrinter;
import com.fasterxml.jackson.core.io.OutputDecorator;
import org.jberet.support._private.SupportLogger;
import org.jberet.support._private.SupportMessages;

/**
 * An implementation of {@code javax.batch.api.chunk.ItemWriter} that writes a list of same-typed objects to Json resource.
 * Each object is written as part of the root Json array.
 *
 * @see JsonItemReader
 * @see JsonItemReaderWriterBase
 * @since 1.0.2
 */
@Named
@Dependent
public class JsonItemWriter extends JsonItemReaderWriterBase implements ItemWriter {
    /**
     * Instructs this class, when the target Json resource already exists, whether to append to, or overwrite
     * the existing resource, or fail. Valid values are {@code append}, {@code overwrite}, and {@code failIfExists}.
     * Optional property, and defaults to {@code append}.
     */
    @Inject
    @BatchProperty
    protected String writeMode;

    /**
     * A comma-separated list of key-value pairs that specify {@code com.fasterxml.jackson.core.JsonGenerator} features.
     * Optional property and defaults to null. Keys and values must be defined in
     * {@code com.fasterxml.jackson.core.JsonGenerator.Feature}. For example,
     * <p/>
     * <pre>
     * WRITE_BIGDECIMAL_AS_PLAIN=true, WRITE_NUMBERS_AS_STRINGS=true, QUOTE_NON_NUMERIC_NUMBERS=false
     * </pre>
     *
     * @see "com.fasterxml.jackson.core.JsonGenerator.Feature"
     */
    @Inject
    @BatchProperty
    protected Map<String, String> jsonGeneratorFeatures;

    /**
     * Fully-qualified name of a class that implements {@code com.fasterxml.jackson.core.PrettyPrinter}, which
     * implements pretty printer functionality, such as indentation. Optional property and defaults to null (the
     * system default pretty printer is used). For example,
     * <p/>
     * <pre>
     * com.fasterxml.jackson.core.util.MinimalPrettyPrinter
     * </pre>
     *
     * @see "com.fasterxml.jackson.core.PrettyPrinter"
     * @see "com.fasterxml.jackson.core.JsonGenerator#setPrettyPrinter(com.fasterxml.jackson.core.PrettyPrinter)"
     */
    @Inject
    @BatchProperty
    protected Class prettyPrinter;

    /**
     * Fully-qualified name of a class that implements {@code com.fasterxml.jackson.core.io.OutputDecorator}, which
     * can be used to decorate output destinations. Typical use is to use a filter abstraction (filtered output stream,
     * writer) around original output destination, and apply additional processing during write operations.
     * Optional property and defaults to null. For example,
     * <p/>
     * <pre>
     * org.jberet.support.io.JsonItemReaderTest$NoopOutputDecorator
     * </pre>
     *
     * @see "com.fasterxml.jackson.core.io.OutputDecorator"
     * @see "com.fasterxml.jackson.core.JsonFactory#setOutputDecorator(com.fasterxml.jackson.core.io.OutputDecorator)"
     */
    @Inject
    @BatchProperty
    protected Class outputDecorator;

    protected JsonGenerator jsonGenerator;

    @Override
    public void open(final Serializable checkpoint) throws Exception {
        SupportLogger.LOGGER.tracef(
                "Open JsonItemWriter with checkpoint %s, which is ignored for JsonItemWriter.%n", checkpoint);
        initJsonFactoryAndObjectMapper();

        jsonGenerator = configureJsonGenerator(jsonFactory, getOutputStream(writeMode), outputDecorator,
                jsonGeneratorFeatures);
        SupportLogger.LOGGER.openingResource(resource, this.getClass());

        if (prettyPrinter == null) {
            jsonGenerator.useDefaultPrettyPrinter();
        } else {
            jsonGenerator.setPrettyPrinter((PrettyPrinter) prettyPrinter.newInstance());
        }

        //write { regardless of the value of skipWritingHeader, since any existing content already ends with }
        jsonGenerator.writeStartArray();
    }

    @Override
    public void writeItems(final List<Object> items) throws Exception {
        for (final Object o : items) {
            jsonGenerator.writeObject(o);
        }
        jsonGenerator.flush();
    }

    @Override
    public Serializable checkpointInfo() throws Exception {
        return null;
    }

    @Override
    public void close() throws Exception {
        if (jsonGenerator != null) {
            SupportLogger.LOGGER.closingResource(resource, this.getClass());
            jsonGenerator.close();
            jsonGenerator = null;
        }
    }

    protected static JsonGenerator configureJsonGenerator(final JsonFactory jsonFactory,
            final OutputStream outputStream, final Class<?> outputDecorator,
            final Map<String, String> jsonGeneratorFeatures) throws Exception {
        if (outputDecorator != null) {
            jsonFactory.setOutputDecorator((OutputDecorator) outputDecorator.newInstance());
        }
        final JsonGenerator jsonGenerator = jsonFactory.createGenerator(outputStream);

        if (jsonGeneratorFeatures != null) {
            for (final Map.Entry<String, String> e : jsonGeneratorFeatures.entrySet()) {
                final String key = e.getKey();
                final String value = e.getValue();
                final JsonGenerator.Feature feature;
                try {
                    feature = JsonGenerator.Feature.valueOf(key);
                } catch (final Exception e1) {
                    throw SupportMessages.MESSAGES.unrecognizedReaderWriterProperty(key, value);
                }
                if ("true".equals(value)) {
                    if (!feature.enabledByDefault()) {
                        jsonGenerator.configure(feature, true);
                    }
                } else if ("false".equals(value)) {
                    if (feature.enabledByDefault()) {
                        jsonGenerator.configure(feature, false);
                    }
                } else {
                    throw SupportMessages.MESSAGES.invalidReaderWriterProperty(null, value, key);
                }
            }
        }

        return jsonGenerator;
    }
}