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

Java tutorial

Introduction

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

Source

/*
 * Copyright (c) 2014 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.Serializable;
import java.util.List;
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 javax.xml.stream.XMLStreamWriter;

import com.fasterxml.jackson.core.PrettyPrinter;
import com.fasterxml.jackson.core.io.OutputDecorator;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule;
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
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 XML resource.
 * Each object is written as a sub-element of the target XML resource. The XML root element is specified with the
 * injected batch artifact properties {@link #rootElementName}, {@link #rootElementNamespaceURI}, and
 * {@link #rootElementPrefix}.
 *
 * @see     XmlItemReader
 * @see     XmlItemReaderWriterBase
 * @since   1.0.2
 */
@Named
@Dependent
public class XmlItemWriter extends XmlItemReaderWriterBase implements ItemWriter {
    /**
     * Instructs this class, when the target XML 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;

    /**
     * Whether use wrapper for indexed (List, array) properties or not, if there are no explicit annotations.
     * Optional property, valid values are "true" and "false", and defaults to "true".
     *
     * @see "com.fasterxml.jackson.dataformat.xml.JacksonXmlModule#setDefaultUseWrapper(boolean)"
     * @see "com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper"
     */
    @Inject
    @BatchProperty
    protected String defaultUseWrapper;

    /**
     * Local name of the output XML root element. Required property.
     *
     * @see "javax.xml.stream.XMLStreamWriter#writeStartElement"
     */
    @Inject
    @BatchProperty
    protected String rootElementName;

    /**
     * The prefix of the XML root element tag. Optional property and defaults to null.
     *
     * @see "javax.xml.stream.XMLStreamWriter#writeStartElement(java.lang.String, java.lang.String, java.lang.String)"
     */
    @Inject
    @BatchProperty
    protected String rootElementPrefix;

    /**
     * The namespaceURI of the prefix to use. Optional property and defaults to null.
     * @see "javax.xml.stream.XMLStreamWriter#writeStartElement(java.lang.String, java.lang.String, java.lang.String)"
     * @see "javax.xml.stream.XMLStreamWriter#writeStartElement(java.lang.String, java.lang.String)"
     */
    @Inject
    @BatchProperty
    protected String rootElementNamespaceURI;

    /**
     * The fully-qualified name of a class implementing {@code com.fasterxml.jackson.core.PrettyPrinter}, which implements
     * pretty printer functionality, such as indentation. Optional property and defaults to null (default pretty printer
     * is used).
     *
     * @see "com.fasterxml.jackson.core.PrettyPrinter"
     * @see "com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator#setPrettyPrinter(com.fasterxml.jackson.core.PrettyPrinter)"
     */
    @Inject
    @BatchProperty
    protected Class prettyPrinter;

    /**
     * The fully-qualified name of a class implementing {@code com.fasterxml.jackson.core.io.OutputDecorator}, which
     * can be used to decorate output destinations. Optional property and defaults to null.
     *
     * @see "com.fasterxml.jackson.core.JsonFactory#setOutputDecorator(com.fasterxml.jackson.core.io.OutputDecorator)"
     * @see "com.fasterxml.jackson.core.io.OutputDecorator"
     */
    @Inject
    @BatchProperty
    protected Class outputDecorator;

    protected ToXmlGenerator toXmlGenerator;
    private XMLStreamWriter staxWriter;

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

        if (outputDecorator != null) {
            xmlFactory.setOutputDecorator((OutputDecorator) outputDecorator.newInstance());
        }
        xmlMapper.configure(SerializationFeature.WRAP_ROOT_VALUE, false);

        toXmlGenerator = xmlFactory.createGenerator(getOutputStream(writeMode));
        SupportLogger.LOGGER.openingResource(resource, this.getClass());

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

        staxWriter = toXmlGenerator.getStaxWriter();
        if (!this.skipWritingHeader) {
            staxWriter.writeStartDocument();
        }
        staxWriter.writeCharacters(NEW_LINE);
        if (rootElementName == null || rootElementName.isEmpty()) {
            throw SupportMessages.MESSAGES.invalidReaderWriterProperty(null, rootElementName, "rootElementName");
        }
        if (rootElementPrefix == null || rootElementPrefix.isEmpty()) {
            if (rootElementNamespaceURI == null || rootElementNamespaceURI.isEmpty()) {
                staxWriter.writeStartElement(rootElementName);
            } else {
                staxWriter.writeStartElement(rootElementNamespaceURI, rootElementName);
            }
        } else {
            if (rootElementNamespaceURI == null || rootElementNamespaceURI.isEmpty()) {
                throw SupportMessages.MESSAGES.invalidReaderWriterProperty(null, rootElementNamespaceURI,
                        "rootElementNamespaceURI");
            } else {
                staxWriter.writeStartElement(rootElementPrefix, rootElementName, rootElementNamespaceURI);
            }
        }
    }

    @Override
    public void writeItems(final List<Object> items) throws Exception {
        for (final Object o : items) {
            staxWriter.writeCharacters(NEW_LINE);
            toXmlGenerator.writeObject(o);

        }
        toXmlGenerator.flush();
    }

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

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

    @Override
    protected void initXmlModule() {
        if (defaultUseWrapper != null) {
            if (defaultUseWrapper.equals("false")) {
                xmlModule = new JacksonXmlModule();
                xmlModule.setDefaultUseWrapper(false);
            } else if (defaultUseWrapper.equals("true")) {
                //default value is already true, so nothing to do
            } else {
                throw SupportMessages.MESSAGES.invalidReaderWriterProperty(null, defaultUseWrapper,
                        "defaultUseWrapper");
            }
        }
    }
}