fr.certu.chouette.exchange.csv.importer.CSVImportLinePlugin.java Source code

Java tutorial

Introduction

Here is the source code for fr.certu.chouette.exchange.csv.importer.CSVImportLinePlugin.java

Source

/**
 * Projet CHOUETTE
 *
 * ce projet est sous license libre
 * voir LICENSE.txt pour plus de details
 *
 */
package fr.certu.chouette.exchange.csv.importer;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import lombok.Getter;
import lombok.Setter;

import org.apache.commons.io.FilenameUtils;
import org.apache.log4j.Logger;

import fr.certu.chouette.common.ChouetteException;
import fr.certu.chouette.exchange.csv.exception.ExchangeException;
import fr.certu.chouette.exchange.csv.exception.ExchangeExceptionCode;
import fr.certu.chouette.exchange.csv.importer.producer.CompanyProducer;
import fr.certu.chouette.exchange.csv.importer.producer.LineProducer;
import fr.certu.chouette.exchange.csv.importer.producer.PTNetworkProducer;
import fr.certu.chouette.exchange.csv.importer.producer.TimetableProducer;
import fr.certu.chouette.exchange.csv.importer.report.CSVReportItem;
import fr.certu.chouette.model.neptune.Company;
import fr.certu.chouette.model.neptune.JourneyPattern;
import fr.certu.chouette.model.neptune.Line;
import fr.certu.chouette.model.neptune.PTNetwork;
import fr.certu.chouette.model.neptune.Route;
import fr.certu.chouette.model.neptune.Timetable;
import fr.certu.chouette.model.neptune.VehicleJourney;
import fr.certu.chouette.plugin.exchange.FormatDescription;
import fr.certu.chouette.plugin.exchange.IImportPlugin;
import fr.certu.chouette.plugin.exchange.ParameterDescription;
import fr.certu.chouette.plugin.exchange.ParameterValue;
import fr.certu.chouette.plugin.exchange.SimpleParameterValue;
import fr.certu.chouette.plugin.exchange.report.ExchangeReport;
import fr.certu.chouette.plugin.exchange.report.ExchangeReportItem;
import fr.certu.chouette.plugin.report.Report;
import fr.certu.chouette.plugin.report.ReportHolder;
import fr.certu.chouette.plugin.report.ReportItem;
import fr.certu.chouette.service.geographic.IGeographicService;

/**
 * @author michel
 * 
 */
public class CSVImportLinePlugin implements IImportPlugin<Line> {

    private static final Logger logger = Logger.getLogger(CSVImportLinePlugin.class);

    private FormatDescription description;

    private List<String> allowedExtensions = Arrays.asList(new String[] { "csv" });

    @Getter
    @Setter
    private TimetableProducer timetableProducer;
    @Getter
    @Setter
    private PTNetworkProducer ptNetworkProducer;
    @Getter
    @Setter
    private CompanyProducer companyProducer;
    @Getter
    @Setter
    private LineProducer lineProducer;
    @Getter
    @Setter
    private String defaultObjectIdPrefix;

    @Setter
    private IGeographicService geographicService;

    /**
     * 
     */
    public CSVImportLinePlugin() {
        description = new FormatDescription(this.getClass().getName());
        description.setName("CSV");
        description.setUnzipAllowed(true);
        List<ParameterDescription> params = new ArrayList<ParameterDescription>();
        ParameterDescription param1 = new ParameterDescription("inputFile", ParameterDescription.TYPE.FILEPATH,
                false, true);
        param1.setAllowedExtensions(Arrays.asList(new String[] { "csv" }));
        params.add(param1);
        ParameterDescription param2 = new ParameterDescription("fileFormat", ParameterDescription.TYPE.STRING,
                false, "file extension");
        param2.setAllowedExtensions(Arrays.asList(new String[] { "csv" }));
        params.add(param2);
        ParameterDescription param3 = new ParameterDescription("objectIdPrefix", ParameterDescription.TYPE.STRING,
                false, defaultObjectIdPrefix);
        params.add(param3);
        ParameterDescription param4 = new ParameterDescription("srid", ParameterDescription.TYPE.STRING, false,
                false);
        params.add(param4);
        description.setParameterDescriptions(params);
    }

    /*
     * (non-Javadoc)
     * 
     * @see fr.certu.chouette.plugin.exchange.IExchangePlugin#getDescription()
     */
    @Override
    public FormatDescription getDescription() {
        return description;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * fr.certu.chouette.plugin.exchange.IImportPlugin#doImport(java.util.List,
     * fr.certu.chouette.plugin.report.ReportHolder)
     */
    @Override
    public List<Line> doImport(List<ParameterValue> parameters, ReportHolder importReport,
            ReportHolder validationReport) throws ChouetteException {
        Report iReport = null;
        if (importReport.getReport() != null) {
            iReport = importReport.getReport();
        } else {
            iReport = new ExchangeReport(ExchangeReport.KEY.IMPORT, description.getName());
            iReport.updateStatus(Report.STATE.UNCHECK);
            importReport.setReport(iReport);
        }
        // CSVReport report = new CSVReport(CSVReport.KEY.IMPORT);

        String filePath = null;
        String extension = "file extension";
        String objectIdPrefix = defaultObjectIdPrefix;
        String srid = null;
        for (ParameterValue value : parameters) {
            if (value instanceof SimpleParameterValue) {
                SimpleParameterValue svalue = (SimpleParameterValue) value;
                if (svalue.getName().equalsIgnoreCase("inputFile")) {
                    filePath = svalue.getFilepathValue();
                } else if (svalue.getName().equals("fileFormat")) {
                    extension = svalue.getStringValue().toLowerCase();
                } else if (svalue.getName().equalsIgnoreCase("objectIdPrefix")) {
                    objectIdPrefix = svalue.getStringValue();
                } else if (svalue.getName().equalsIgnoreCase("srid")) {
                    srid = svalue.getStringValue();
                } else {
                    throw new IllegalArgumentException("unexpected argument " + svalue.getName());
                }
            } else {
                throw new IllegalArgumentException("unexpected argument " + value.getName());
            }
        }
        if (filePath == null) {
            logger.error("missing argument inputFile");
            throw new IllegalArgumentException("inputFile required");
        }

        if (extension.equals("file extension")) {
            extension = FilenameUtils.getExtension(filePath).toLowerCase();
        }
        if (!allowedExtensions.contains(extension)) {
            logger.error("invalid argument inputFile " + filePath + ", allowed format : "
                    + Arrays.toString(allowedExtensions.toArray()));
            throw new IllegalArgumentException("invalid file type : " + extension);
        }

        List<Line> lines = null;

        // simple file processing
        logger.info("start import simple file " + filePath);
        lines = processImport(filePath, objectIdPrefix, srid, iReport);
        if (lines != null) {
            for (Line line : lines) {
                ReportItem importItem = new ExchangeReportItem(ExchangeReportItem.KEY.IMPORTED_LINE,
                        Report.STATE.OK);
                iReport.addItem(importItem);
                importItem.addMessageArgs(line.getName());
                line.complete();
                ExchangeReportItem countItem = new ExchangeReportItem(ExchangeReportItem.KEY.ROUTE_COUNT,
                        Report.STATE.OK, line.getRoutes().size());
                importItem.addItem(countItem);
                countItem = new ExchangeReportItem(ExchangeReportItem.KEY.JOURNEY_PATTERN_COUNT, Report.STATE.OK,
                        line.getJourneyPatterns().size());
                importItem.addItem(countItem);
                countItem = new ExchangeReportItem(ExchangeReportItem.KEY.VEHICLE_JOURNEY_COUNT, Report.STATE.OK,
                        line.getVehicleJourneys().size());
                importItem.addItem(countItem);
                countItem = new ExchangeReportItem(ExchangeReportItem.KEY.STOP_AREA_COUNT, Report.STATE.OK,
                        line.getStopAreas().size());
                importItem.addItem(countItem);
                countItem = new ExchangeReportItem(ExchangeReportItem.KEY.CONNECTION_LINK_COUNT, Report.STATE.OK,
                        line.getConnectionLinks().size());
                importItem.addItem(countItem);
                countItem = new ExchangeReportItem(ExchangeReportItem.KEY.ACCES_POINT_COUNT, Report.STATE.OK,
                        line.getAccessPoints().size());
                importItem.addItem(countItem);
                countItem = new ExchangeReportItem(ExchangeReportItem.KEY.TIME_TABLE_COUNT, Report.STATE.OK,
                        line.getTimetables().size());
                importItem.addItem(countItem);
            }
        }
        logger.info("import terminated");
        return lines;
    }

    /**
     * @param objectIdPrefix
     * @param srid
     * @param report
     * @param rootObject
     * @param validate
     * @param report
     * @param entryName
     * @return
     * @throws ExchangeException
     */
    private List<Line> processImport(String filePath, String objectIdPrefix, String srid, Report report)
            throws ExchangeException {
        ChouetteCsvReader csvReader = null;
        Map<String, Timetable> timetableMap = new HashMap<String, Timetable>();
        PTNetwork ptNetwork = null;
        Company company = null;
        List<Line> lines = new ArrayList<Line>();

        lineProducer.clean();
        ReportItem fileReportItem = null;
        try {
            File input = new File(filePath);
            fileReportItem = new ExchangeReportItem(ExchangeReportItem.KEY.FILE, Report.STATE.OK, input.getName());
            report.addItem(fileReportItem);
            FileInputStream stream = new FileInputStream(input);
            csvReader = new ChouetteCsvReader(new InputStreamReader(stream, "UTF-8"), ';');
        } catch (FileNotFoundException e) {
            ReportItem errorItem = new ExchangeReportItem(ExchangeReportItem.KEY.FILE_ERROR, Report.STATE.ERROR,
                    e.getLocalizedMessage());
            fileReportItem.addItem(errorItem);
            throw new ExchangeException(ExchangeExceptionCode.FILE_NOT_FOUND, filePath);
        } catch (UnsupportedEncodingException e) {
            ReportItem errorItem = new ExchangeReportItem(ExchangeReportItem.KEY.FILE_ERROR, Report.STATE.ERROR,
                    e.getLocalizedMessage());
            fileReportItem.addItem(errorItem);
            throw new ExchangeException(ExchangeExceptionCode.INVALID_CSV_FILE, filePath);
        }

        String[] currentLine;
        try {
            currentLine = csvReader.readNext();
            // check if firstLine is correct (detect oldfashion format)
            if ((currentLine.length < TimetableProducer.TITLE_COLUMN + 2)
                    || currentLine[TimetableProducer.TITLE_COLUMN].isEmpty()
                    || currentLine[TimetableProducer.TITLE_COLUMN + 1].isEmpty()) {
                CSVReportItem reportItem = new CSVReportItem(CSVReportItem.KEY.FILE_FORMAT, Report.STATE.ERROR);
                report.addItem(reportItem);
                return null;
            }
        } catch (IOException e) {
            ReportItem errorItem = new ExchangeReportItem(ExchangeReportItem.KEY.FILE_ERROR, Report.STATE.ERROR,
                    e.getLocalizedMessage());
            fileReportItem.addItem(errorItem);
            throw new ExchangeException(ExchangeExceptionCode.INVALID_CSV_FILE, filePath);
        }

        CSVReportItem timetableCountReport = new CSVReportItem(CSVReportItem.KEY.TIMETABLE_COUNT, Report.STATE.OK);
        while (currentLine[TimetableProducer.TITLE_COLUMN].equals(TimetableProducer.TIMETABLE_LABEL_TITLE)) {
            Timetable timetable = timetableProducer.produce(csvReader, currentLine, objectIdPrefix, srid,
                    timetableCountReport);
            if (timetable != null) {
                logger.debug("timetable \n" + timetable.toString());
                timetableMap.put(timetable.getObjectId().split(":")[2], timetable);
            }

            currentLine = getStartOfNextBloc(filePath, report, csvReader, true);
            if (currentLine == null)
                break;
        }

        if (currentLine == null)
            return null;
        ptNetwork = ptNetworkProducer.produce(csvReader, currentLine, objectIdPrefix, srid, report);
        if (ptNetwork == null)
            return null;

        logger.debug("network \n" + ptNetwork);
        currentLine = getStartOfNextBloc(filePath, report, csvReader, true);
        if (currentLine == null)
            return null;

        company = companyProducer.produce(csvReader, currentLine, objectIdPrefix, srid, report);
        if (company == null)
            return null;
        logger.debug("company \n" + company.toString());
        currentLine = getStartOfNextBloc(filePath, report, csvReader, true);
        if (currentLine == null)
            return null;

        CSVReportItem lineCountReport = new CSVReportItem(CSVReportItem.KEY.LINE_COUNT, Report.STATE.OK);
        while (currentLine[LineProducer.TITLE_COLUMN].equals(LineProducer.LINE_NAME_TITLE)) {
            logger.debug("lines");
            Line line = lineProducer.produce(csvReader, currentLine, objectIdPrefix, srid, lineCountReport);
            if (line != null) {
                line.setCompany(company);
                line.setPtNetwork(ptNetwork);
                assemble(line, timetableMap, report);
                logger.debug("line \n" + line.toString());
                if (line.getRoutes().isEmpty()) {
                    logger.error("empty line removed :" + line.getNumber());
                    CSVReportItem reportItem = new CSVReportItem(CSVReportItem.KEY.INVALID_LINE, Report.STATE.ERROR,
                            line.getName());
                    report.addItem(reportItem);
                } else {
                    CSVReportItem reportItem = new CSVReportItem(CSVReportItem.KEY.OK_LINE, Report.STATE.OK,
                            line.getName());
                    report.addItem(reportItem);
                    lines.add(line);
                }
            }
            try {
                currentLine = csvReader.readNext();
                if (currentLine == null)
                    break;
            } catch (IOException e) {
                ReportItem errorItem = new ExchangeReportItem(ExchangeReportItem.KEY.FILE_ERROR, Report.STATE.ERROR,
                        e.getLocalizedMessage());
                fileReportItem.addItem(errorItem);
                throw new ExchangeException(ExchangeExceptionCode.INVALID_CSV_FILE, filePath);
            }
        }
        // compute barycenters
        if (!lineProducer.getCommercials().isEmpty()) {
            geographicService.computeBarycentre(lineProducer.getCommercials().values());
        }

        // warns unused Timetables
        int tmCount = timetableMap.size();
        for (Timetable tm : timetableMap.values()) {
            if (tm.getVehicleJourneys() == null || tm.getVehicleJourneys().isEmpty()) {
                CSVReportItem unused = new CSVReportItem(CSVReportItem.KEY.UNUSED_TIMETABLE, Report.STATE.WARNING,
                        tm.getComment(), tm.getObjectId());
                timetableCountReport.addItem(unused);
                tmCount--;
            }
        }
        timetableCountReport.addMessageArgs(Integer.toString(tmCount));
        report.addItem(timetableCountReport);

        lineCountReport.addMessageArgs(Integer.toString(lines.size()));
        report.addItem(lineCountReport);

        return lines;
    }

    /**
     * @param filePath
     * @param report
     * @param csvReader
     * @param currentLine
     * @return
     * @throws ExchangeException
     */
    private String[] getStartOfNextBloc(String filePath, Report report, ChouetteCsvReader csvReader,
            boolean reportEOF) throws ExchangeException {
        try {
            String[] currentLine = csvReader.readNext();
            if (currentLine == null) {
                if (reportEOF) {
                    CSVReportItem reportItem = new CSVReportItem(CSVReportItem.KEY.END_OF_FILE, Report.STATE.ERROR);
                    report.addItem(reportItem);
                }
                return null;
            }
            // if line not empty, maybe previous block wasn't completely parsed
            while (!timetableProducer.checkLine(currentLine)) {
                currentLine = csvReader.readNext();
                if (currentLine == null) {
                    if (reportEOF) {
                        CSVReportItem reportItem = new CSVReportItem(CSVReportItem.KEY.END_OF_FILE,
                                Report.STATE.ERROR);
                        report.addItem(reportItem);
                    }
                    return null;
                }
            }
            // skip empty line bloc
            while (timetableProducer.checkLine(currentLine)) {
                currentLine = csvReader.readNext();
                if (currentLine == null) {
                    if (reportEOF) {
                        CSVReportItem reportItem = new CSVReportItem(CSVReportItem.KEY.END_OF_FILE,
                                Report.STATE.ERROR);
                        report.addItem(reportItem);
                    }
                    return null;
                }
            }

            return currentLine;
        } catch (IOException e) {
            throw new ExchangeException(ExchangeExceptionCode.INVALID_CSV_FILE, filePath);
        }
    }

    /**
     * @param line
     * @param timetableMap
     * @throws ExchangeException
     */
    private void assemble(Line line, Map<String, Timetable> timetableMap, Report report) throws ExchangeException {
        for (Iterator<Route> iterator = line.getRoutes().iterator(); iterator.hasNext();) {
            Route route = iterator.next();
            for (Iterator<JourneyPattern> iterator2 = route.getJourneyPatterns().iterator(); iterator2.hasNext();) {
                JourneyPattern journey = iterator2.next();
                for (Iterator<VehicleJourney> iterator3 = journey.getVehicleJourneys().iterator(); iterator3
                        .hasNext();) {
                    VehicleJourney vj = iterator3.next();
                    String keys = vj.getComment();
                    vj.setComment(null);
                    String[] ttid = keys.split(",");
                    for (String key : ttid) {
                        Timetable t = timetableMap.get(key);
                        if (t == null) {
                            logger.error(
                                    "missing timetable " + key + " vehicleJourney removed :" + vj.getObjectId());
                            CSVReportItem reportItem = new CSVReportItem(CSVReportItem.KEY.VJ_MISSING_TIMETABLE,
                                    Report.STATE.WARNING, vj.getName());
                            report.addItem(reportItem);
                            iterator3.remove();
                        } else {
                            vj.addTimetable(t);
                            t.addVehicleJourney(vj);
                        }
                    }
                }
                if (journey.getVehicleJourneys().isEmpty()) {
                    logger.error("empty journeyPattern removed :" + journey.getObjectId());
                    iterator2.remove();
                }
            }
            if (route.getJourneyPatterns().isEmpty()) {
                logger.error("empty route removed :" + route.getObjectId());
                iterator.remove();
            }
        }

    }

}