Java tutorial
/** * 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(); } } } }