jp.terasoluna.fw.file.dao.standard.VariableFileLineIterator.java Source code

Java tutorial

Introduction

Here is the source code for jp.terasoluna.fw.file.dao.standard.VariableFileLineIterator.java

Source

/*
 * Copyright (c) 2007 NTT DATA Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package jp.terasoluna.fw.file.dao.standard;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import jp.terasoluna.fw.file.annotation.FileFormat;
import jp.terasoluna.fw.file.dao.FileException;

/**
 * ??(?)
 * <p>
 * ?????1?? ??<br>
 * CSV???????????? ?????
 * </p>
 * <b>??</b><br>
 * @{@link FileFormat}?<br>
 * <div align="center">
 * <table width="90%" border="1" bgcolor="#FFFFFF">
 * <tr>
 * <td><b>???</b></td>
 * <td><b>???</b></td>
 * <td><b></b></td>
 * <td><b></b></td>
 * </tr>
 * <tr>
 * <td> <code></code></td>
 * <td> <code>lineFeedChar</code></td>
 * <td> <code>?</code></td>
 * <td> <code></code></td>
 * </tr>
 * <tr>
 * <td> <code></code></td>
 * <td> <code>delimiter</code></td>
 * <td> <code>','</code></td>
 * <td> <code></code></td>
 * </tr>
 * <tr>
 * <td> <code>?</code></td>
 * <td> <code>encloseChar</code></td>
 * <td> <code>??('\u0000')</code></td>
 * <td> <code></code></td>
 * </tr>
 * <tr>
 * <td> <code></code></td>
 * <td> <code>fileEncodeing</code></td>
 * <td> <code>?</code></td>
 * <td> <code></code></td>
 * </tr>
 * <tr>
 * <td> <code></code></td>
 * <td> <code>headerLineCount</code></td>
 * <td> <code>0</code></td>
 * <td> <code></code></td>
 * </tr>
 * <tr>
 * <td> <code></code></td>
 * <td> <code>trailerLineCount</code></td>
 * <td> <code>0</code></td>
 * <td> <code></code></td>
 * </tr>
 * </table>
 * </div> <br>
 * @{@link jp.terasoluna.fw.file.annotation.InputFileColumn}?@{@link jp.terasoluna.fw.file.annotation.OutputFileColumn}?<br>
 * <div align="center">
 * <table width="90%" border="1" bgcolor="#FFFFFF">
 * <tr>
 * <td><b>???</b></td>
 * <td><b>???</b></td>
 * <td><b></b></td>
 * <td><b></b></td>
 * </tr>
 * <tr>
 * <td> <code></code></td>
 * <td> <code>columnIndex</code></td>
 * <td>-</td>
 * <td> <code></code></td>
 * </tr>
 * <tr>
 * <td> <code></code></td>
 * <td> <code>columnFormat</code></td>
 * <td> <code>""</code></td>
 * <td> <code></code></td>
 * </tr>
 * <tr>
 * <td> <code>?</code></td>
 * <td> <code>bytes</code></td>
 * <td> <code>-1</code></td>
 * <td> <code></code></td>
 * </tr>
 * <tr>
 * <td> <code></code></td>
 * <td> <code>paddingType</code></td>
 * <td> <code>??</code></td>
 * <td> <code></code></td>
 * </tr>
 * <tr>
 * <td> <code></code></td>
 * <td> <code>paddingChar</code></td>
 * <td> <code>' '</code></td>
 * <td> <code></code></td>
 * </tr>
 * <tr>
 * <td> <code></code></td>
 * <td> <code>trimType</code></td>
 * <td> <code>??</code></td>
 * <td> <code></code></td>
 * </tr>
 * <tr>
 * <td> <code></code></td>
 * <td> <code>trimChar</code></td>
 * <td> <code>' '</code></td>
 * <td> <code></code></td>
 * </tr>
 * <tr>
 * <td> <code>?</code></td>
 * <td> <code>stringConverter</code></td>
 * <td> <code>NullStringConverter.class</code></td>
 * <td> <code></code></td>
 * </tr>
 * </table>
 * </div> <br>
 * <b>?</b><br>
 * <ul>
 * 
 * <li>?Caracter.MIN_VALUE???????()</li>
 * </ul>
 * @param <T> 
 */
public class VariableFileLineIterator<T> extends AbstractFileLineIterator<T> {

    /**
     * 
     */
    private char delimiter = ',';

    /**
     * ?
     */
    private char encloseChar = Character.MIN_VALUE;

    /**
     * 
     * @param fileName ??
     * @param clazz 
     * @param columnParserMap 
     */
    public VariableFileLineIterator(String fileName, Class<T> clazz, Map<String, ColumnParser> columnParserMap) {

        super(fileName, clazz, columnParserMap);

        FileFormat fileFormat = clazz.getAnnotation(FileFormat.class);

        // ?Character.MIN_VALUE????
        if (fileFormat.delimiter() == Character.MIN_VALUE) {
            throw new FileException("Delimiter can not use '\\u0000'.", new IllegalStateException(), fileName);
        }

        // ?????????
        if (fileFormat.lineFeedChar().indexOf(fileFormat.delimiter()) >= 0) {
            throw new FileException("delimiter is the same as lineFeedChar and is no use.",
                    new IllegalStateException(), fileName);
        }

        // ??
        this.encloseChar = fileFormat.encloseChar();

        // ?
        this.delimiter = fileFormat.delimiter();

        // ???
        super.init();
    }

    /**
     * ????? ???? ????<br>
     * <code>fileLineString</code>?<code>null</code>???? ?????????<code>String</code>????
     * @param fileLineString ??1?
     * @return ?
     */
    @Override
    protected String[] separateColumns(String fileLineString) {

        if (fileLineString == null || "".equals(fileLineString)) {
            return new String[0];
        }

        // 1???
        StringBuilder columnBuilder = new StringBuilder();

        // ????
        char previousChar = Character.MIN_VALUE;

        // ??????
        List<String> columnList = new ArrayList<String>();

        boolean isEnclosed = true;
        boolean isEscaped = false;

        int fieldCount = 0;
        char[] columnEncloseChar = getColumnEncloseChar();

        if (!isEnclosed()) {
            return StringUtils.splitByWholeSeparatorPreserveAllTokens(fileLineString,
                    Character.toString(delimiter));
        } else {
            for (char currentChar : fileLineString.toCharArray()) {
                if (previousChar == Character.MIN_VALUE) {
                    previousChar = currentChar;
                }
                if (previousChar == getEncloseCharcter(columnEncloseChar, fieldCount)) {
                    if (isEnclosed) {
                        if (currentChar == getEncloseCharcter(columnEncloseChar, fieldCount)) {
                            isEnclosed = false;
                        }
                    } else {
                        if (currentChar == getEncloseCharcter(columnEncloseChar, fieldCount)) {
                            if (isEscaped) {
                                columnBuilder.append(currentChar);
                                isEscaped = false;
                            } else {
                                isEscaped = true;
                            }
                        } else if (currentChar == getDelimiter()) {
                            if (isEscaped) {
                                columnList.add(columnBuilder.toString());
                                previousChar = Character.MIN_VALUE;
                                columnBuilder.delete(0, columnBuilder.length());
                                isEnclosed = true;
                                isEscaped = false;
                                fieldCount++;
                            } else {
                                columnBuilder.append(currentChar);
                                isEscaped = false;
                            }
                        } else {
                            columnBuilder.append(currentChar);
                        }
                    }
                } else {
                    if (currentChar != getDelimiter()) {
                        columnBuilder.append(currentChar);
                    } else {
                        columnList.add(columnBuilder.toString());
                        previousChar = Character.MIN_VALUE;
                        columnBuilder.delete(0, columnBuilder.length());
                        fieldCount++;
                    }
                }
            }
            columnList.add(columnBuilder.toString());
            return columnList.toArray(new String[columnList.size()]);
        }
    }

    /**
     * ?????
     * @param index ?
     * @return ?
     */
    private char getEncloseCharcter(char[] columnEncloseChar, int index) {
        if (columnEncloseChar.length == 0 || index >= columnEncloseChar.length) {
            return this.encloseChar;
        } else {
            return columnEncloseChar[index];
        }
    }

    /**
     * ??
     * @return 
     */
    @Override
    public char getDelimiter() {

        return delimiter;
    }

    /**
     * ???
     * @return ?
     */
    @Override
    public char getEncloseChar() {

        return encloseChar;
    }
}