Java tutorial
/* * Copyright (c) 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 javax.batch.api.BatchProperty; import javax.inject.Inject; import javax.naming.InitialContext; import com.fasterxml.jackson.dataformat.csv.CsvFactory; import com.fasterxml.jackson.dataformat.csv.CsvMapper; import com.fasterxml.jackson.dataformat.csv.CsvSchema; /** * The base class for {@link JacksonCsvItemReader} and {@link JacksonCsvItemWriter}. * * @see JacksonCsvItemReader * @see JacksonCsvItemWriter * @since 1.1.0 */ public abstract class JacksonCsvItemReaderWriterBase extends JsonItemReaderWriterBase { /** * For {@code ItemReader}, it's the java type that each data item should be converted to; for {@code ItemWriter}, * it's the java type for each incoming data item. In either case, the valid values are: * <p/> * <ul> * <li>a custom java type that represents data item and serves as the CSV schema class * <li>{@code java.util.Map} * <li>{@code java.util.List} * <li>{@code java.lang.String[]} * <li>{@code com.fasterxml.jackson.databind.JsonNode} * </ul> * <p> * When using {@code java.util.List} or {@code java.lang.String[]} for reading, it is deemed raw access, and CSV * schema will not be configured and any schema-related properties are ignored. Specifically, CSV header and * comment lines are read as raw access content. */ @Inject @BatchProperty protected Class beanType; /** * Specifies CSV schema in one of the 2 ways: * <p/> * <ul> * <li>columns = "<fully-qualified class name>":<br> * CSV schema is defined in the named POJO class, which typically has class-level annotation * {@code com.fasterxml.jackson.annotation.JsonPropertyOrder} to define property order corresponding to * CSV column order.</li> * <p/> * <li>columns = "<comma-separated list of column names, each of which may be followed by a space and column type>":<br> * use the value to manually build CSV schema. Valid column types are defined in * {@code com.fasterxml.jackson.dataformat.csv.CsvSchema.ColumnType}, including: * <ul> * <li>STRING * <li>STRING_OR_LITERAL * <li>NUMBER * <li>NUMBER_OR_STRING * <li>BOOLEAN * <li>ARRAY * </ul> * For complete list and descriptioin, see {@code com.fasterxml.jackson.dataformat.csv.CsvSchema.ColumnType} javadoc. * </li> * </ul> * <p/> * For example, * <pre> * columns = "org.jberet.support.io.StockTrade" * columns = "firstName STRING, lastName STRING, age NUMBER" * </pre> * In {@link JacksonCsvItemReader}, if this property is not defined and {@link #useHeader} is true * (CSV input has a header), the header is used to create CSV schema. However, when {@link #beanType} is * {@code java.util.List} or {@code java.lang.String[]}, the reader is considered raw access, and all schema-related * properties are ignored. * <p/> * This property is optional for reader and required for writer class. * * @see "com.fasterxml.jackson.dataformat.csv.CsvSchema" */ @Inject @BatchProperty protected String columns; /** * whether the first line of physical document defines column names (true) or not (false): * if enabled, parser will take first-line values to define column names; and generator will output column names as * the first line. Optional property. * <p> * For {@link JacksonCsvItemReader}, if {@link #beanType} is {@code java.util.List} or {@code java.lang.String[]}, * it is considered raw access, {@code useHeader} property is ignored and no CSV schema is used. * <p> * valid values are {@code true} or {@code false}, and the default is {@code false}. * * @see "com.fasterxml.jackson.dataformat.csv.CsvSchema" */ @Inject @BatchProperty protected boolean useHeader; /** * Character used for quoting values that contain quote characters or linefeeds. * Optional property and defaults to " (double-quote character). * * @see "com.fasterxml.jackson.dataformat.csv.CsvSchema" */ @Inject @BatchProperty protected String quoteChar; /** * Character used to separate values. * <p/> * Optional property and defaults to , (comma character). * Other commonly used values include tab ('\t') and pipe ('|') * * @see "com.fasterxml.jackson.dataformat.csv.CsvSchema" */ @Inject @BatchProperty protected String columnSeparator; /** * When asked to write Java `null`, this String value will be used instead. * Optional property and defaults to empty string. * * @see "com.fasterxml.jackson.dataformat.csv.CsvSchema" */ @Inject @BatchProperty protected String nullValue; protected CsvMapper csvMapper; protected void init() throws Exception { initJsonFactoryAndObjectMapper(); csvMapper = (CsvMapper) objectMapper; } @Override protected void initJsonFactory() throws Exception { if (jsonFactoryLookup != null) { jsonFactory = InitialContext.doLookup(jsonFactoryLookup); } else { jsonFactory = new CsvFactory(new CsvMapper()); } } protected CsvSchema buildCsvSchema(CsvSchema schema) throws Exception { if (schema == null) { columns = columns.trim(); if (columns.indexOf(',') < 0 && columns.indexOf(' ') < 0) { //no comma and no space, assume it's java class name for schema schema = csvMapper.schemaFor(getClass().getClassLoader().loadClass(columns)); } else { //manually build CsvSchema final String[] cols = columns.split(","); final CsvSchema.Builder builder = new CsvSchema.Builder(); for (String e : cols) { e = e.trim(); final int lastSpace = e.lastIndexOf(' '); if (lastSpace > 0) { final String e1 = e.substring(0, lastSpace).trim(); final String e2 = e.substring(lastSpace + 1); builder.addColumn(e1, CsvSchema.ColumnType.valueOf(e2)); } else { builder.addColumn(e); } } schema = builder.build(); } } schema = useHeader ? schema.withHeader() : schema.withoutHeader(); if (columnSeparator != null) { schema = schema.withColumnSeparator(columnSeparator.charAt(0)); } if (quoteChar != null) { schema = schema.withQuoteChar(quoteChar.charAt(0)); } if (nullValue != null) { schema = schema.withNullValue(nullValue); } //to allow comments like "# this is comments". //comments can be enabled or disabled with com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_YAML_COMMENTS //which corresponds to batch property jsonParserFeatures return schema.withComments(); } }