biz.ganttproject.impex.csv.GanttCSVOpen.java Source code

Java tutorial

Introduction

Here is the source code for biz.ganttproject.impex.csv.GanttCSVOpen.java

Source

/*
Copyright 2012 GanttProject Team
    
This file is part of GanttProject, an opensource project management tool.
    
GanttProject is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
    
GanttProject is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with GanttProject.  If not, see <http://www.gnu.org/licenses/>.
 */
package biz.ganttproject.impex.csv;

import biz.ganttproject.core.time.TimeUnitStack;
import com.google.common.base.Function;
import com.google.common.base.Strings;
import com.google.common.base.Supplier;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import net.sourceforge.ganttproject.CustomPropertyClass;
import net.sourceforge.ganttproject.CustomPropertyManager;
import net.sourceforge.ganttproject.GPLogger;
import net.sourceforge.ganttproject.io.CSVOptions;
import net.sourceforge.ganttproject.language.GanttLanguage;
import net.sourceforge.ganttproject.resource.HumanResourceManager;
import net.sourceforge.ganttproject.roles.RoleManager;
import net.sourceforge.ganttproject.task.TaskManager;
import net.sourceforge.ganttproject.util.collect.Pair;
import org.apache.commons.csv.CSVFormat;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import static net.sourceforge.ganttproject.GPLogger.debug;
import static net.sourceforge.ganttproject.util.FileUtil.getExtension;

/**
 * Handles opening CSV and XLS files.
 */
public class GanttCSVOpen {
    static Collection<String> getFieldNames(Enum... fieldsEnum) {
        return Collections2.transform(Arrays.asList(fieldsEnum), new Function<Enum, String>() {
            @Override
            public String apply(Enum input) {
                return input.toString();
            }
        });
    }

    static final GanttLanguage language = GanttLanguage.getInstance();

    private final Supplier<InputStream> myInputSupplier;

    private final SpreadsheetFormat myFormat;

    private final List<RecordGroup> myRecordGroups;

    private int mySkippedLine;

    private CSVOptions myCsvOptions;

    public GanttCSVOpen(Supplier<InputStream> inputSupplier, SpreadsheetFormat format, RecordGroup... groups) {
        myInputSupplier = inputSupplier;
        myRecordGroups = Lists.newArrayList();
        for (RecordGroup group : groups) {
            if (group != null) {
                myRecordGroups.add(group);
            }
        }
        myFormat = format;
    }

    public GanttCSVOpen(Supplier<InputStream> inputSupplier, SpreadsheetFormat format,
            final TaskManager taskManager, final HumanResourceManager resourceManager, RoleManager roleManager,
            TimeUnitStack timeUnitStack) {
        this(inputSupplier, format, createTaskRecordGroup(taskManager, resourceManager, timeUnitStack),
                createResourceRecordGroup(resourceManager, roleManager));
    }

    public GanttCSVOpen(final File file, final TaskManager taskManager, final HumanResourceManager resourceManager,
            final RoleManager roleManager, TimeUnitStack timeUnitStack) {
        this(() -> {
            try {
                return new FileInputStream(file);
            } catch (FileNotFoundException e) {
                throw new RuntimeException(e);
            }
        }, createSpreadsheetFormat(file), taskManager, resourceManager, roleManager, timeUnitStack);
    }

    private static RecordGroup createTaskRecordGroup(final TaskManager taskManager,
            final HumanResourceManager resourceManager, TimeUnitStack timeUnitStack) {
        return new TaskRecords(taskManager, resourceManager, timeUnitStack);
    }

    protected static void createCustomProperties(Collection<String> customFields,
            CustomPropertyManager customPropertyManager) {
        for (String name : customFields) {
            customPropertyManager.createDefinition(name, CustomPropertyClass.TEXT.getID(), name, null);
        }
    }

    private static RecordGroup createResourceRecordGroup(HumanResourceManager resourceManager,
            RoleManager roleManager) {
        return resourceManager == null ? null : new ResourceRecords(resourceManager, roleManager);
    }

    private int doLoad(SpreadsheetReader reader, int numGroup, int linesToSkip) {
        final Logger logger = GPLogger.getLogger(GanttCSVOpen.class);
        int lineCounter = 0;
        RecordGroup currentGroup = myRecordGroups.get(numGroup);
        boolean searchHeader = currentGroup.getHeader() == null;
        if (searchHeader) {
            debug(logger, "[CSV] Searching for a header of %s", currentGroup);
        } else {
            debug(logger, "[CSV] Expecting to read records of group %s", currentGroup);
            numGroup++;
        }

        for (Iterator<SpreadsheetRecord> it = reader.iterator(); it.hasNext();) {
            SpreadsheetRecord record = it.next();
            lineCounter++;
            if (linesToSkip-- > 0) {
                continue;
            }
            if (record.size() == 0 || record.size() == 1 && Strings.isNullOrEmpty(record.get(0))) {
                // If line is empty then current record group is probably finished.
                // Let's search for the next group header.
                searchHeader = true;
                continue;
            }
            if (searchHeader) {
                if (numGroup < myRecordGroups.size()) {
                    debug(logger, "%s\n", record);
                    RecordGroup nextGroup = myRecordGroups.get(numGroup);
                    // Record is not empty and we're searching for header.
                    if (nextGroup.isHeader(record)) {
                        debug(logger, "[CSV] ^^^ This seems to be a header");

                        nextGroup.setHeader(Lists.newArrayList(record.iterator()));
                        return lineCounter;
                    }
                }
            }
            if (currentGroup.doProcess(record)) {
                searchHeader = false;
            } else {
                mySkippedLine++;
            }
        }
        return 0;
    }

    /**
     * Create tasks from file.
     *
     * @throws IOException on parse error or input read-failure
     */
    public List<Pair<Level, String>> load() throws IOException {
        final List<Pair<Level, String>> errors = Lists.newArrayList();
        for (RecordGroup group : myRecordGroups) {
            group.setErrorOutput(errors);
        }
        int idxCurrentGroup = 0;
        int idxNextGroup;
        int skipHeadLines = 0;
        List<String> headers;
        do {
            idxNextGroup = idxCurrentGroup;
            RecordGroup currentGroup = myRecordGroups.get(idxCurrentGroup);
            headers = currentGroup.getHeader();
            if (headers != null) {
                idxNextGroup++;
            }
            try (SpreadsheetReader reader = createReader(myInputSupplier.get(), headers)) {
                skipHeadLines = doLoad(reader, idxCurrentGroup, skipHeadLines);
            }
            idxCurrentGroup = idxNextGroup;
        } while (skipHeadLines > 0);
        for (RecordGroup group : myRecordGroups) {
            group.postProcess();
        }
        return errors;
    }

    int getSkippedLineCount() {
        return mySkippedLine;
    }

    public void setOptions(CSVOptions csvOptions) {
        myCsvOptions = csvOptions;
    }

    private SpreadsheetReader createReader(InputStream is, List<String> headers) throws IOException {
        switch (myFormat) {
        case CSV:
            return new CsvReaderImpl(is, createCSVFormat(headers));
        case XLS:
            return new XlsReaderImpl(is, headers);
        default:
            throw new IllegalArgumentException("Unsupported format: " + myFormat);
        }
    }

    private CSVFormat createCSVFormat(List<String> headers) {
        CSVFormat format = CSVFormat.DEFAULT.withIgnoreEmptyLines(false).withIgnoreSurroundingSpaces(true);
        if (myCsvOptions != null) {
            format = format.withDelimiter(myCsvOptions.sSeparatedChar.charAt(0))
                    .withQuote(myCsvOptions.sSeparatedTextChar.charAt(0));
        }
        if (headers != null) {
            format = format.withHeader(headers.toArray(new String[0]));
        }
        return format;
    }

    private static SpreadsheetFormat createSpreadsheetFormat(File file) {
        String extension = getExtension(file);
        if (extension.isEmpty()) {
            throw new IllegalArgumentException("No file extension!");
        }
        return SpreadsheetFormat.getSpreadsheetFormat(extension);
    }
}