diff --git a/chouette-command/pom.xml b/chouette-command/pom.xml index b5e5496b5..eee6b9cfa 100644 --- a/chouette-command/pom.xml +++ b/chouette-command/pom.xml @@ -1,165 +1,165 @@ - - 4.0.0 - - chouette - fr.certu.chouette - 2.0.1 - - fr.certu.chouette - chouette-command - Chouette Command - 2.0.1 - - - - org.projectlombok - lombok - - - fr.certu.chouette - chouette-exchange-neptune - - - fr.certu.chouette - chouette-exchange-csv - - - fr.certu.chouette - chouette-exchange-gtfs - - - fr.certu.chouette - chouette-export-geoportail - - - fr.certu.chouette.schema - chouette-castor-neptune - - - fr.certu.chouette - chouette-core - - - fr.certu.chouette - chouette-hibernate-dao - - - fr.certu.chouette - chouette-validation - - - fr.certu.chouette - chouette-jdbc-dao - - - - org.springframework - spring-core - - - - postgresql - postgresql - - - log4j - log4j - - - - org.testng - testng - - - - - - - src/main/java/ - - **/*.properties - - - - ${basedir}/src/main/resources - - filtered/** - - false - - - true - src/main/scripts - - *.bat - *.sh - - ${project.build.directory} - - - - ../config/dev - false - ${project.build.directory} - - - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - prepare-package - - copy-dependencies - - - - - ${project.build.directory}/lib - - - - org.apache.maven.plugins - maven-jar-plugin - - - - lib/ - true - fr.certu.chouette.command.Command - - - . - - - - - - maven-assembly-plugin - - chouette-cmd_${project.version} - false - - src/main/resources/assemblies/cbc.xml - - - - - make-assembly - package - - single - - - - - - - - + + 4.0.0 + + chouette + fr.certu.chouette + 2.0.1 + + fr.certu.chouette + chouette-command + Chouette Command + 2.0.1 + + + + org.projectlombok + lombok + + + fr.certu.chouette + chouette-exchange-neptune + + + fr.certu.chouette + chouette-exchange-csv + + + fr.certu.chouette + chouette-exchange-gtfs + + + fr.certu.chouette + chouette-export-geoportail + + + fr.certu.chouette.schema + chouette-castor-neptune + + + fr.certu.chouette + chouette-core + + + fr.certu.chouette + chouette-hibernate-dao + + + fr.certu.chouette + chouette-validation + + + fr.certu.chouette + chouette-jdbc-dao + + + + org.springframework + spring-core + + + + postgresql + postgresql + + + log4j + log4j + + + + org.testng + testng + + + + + + + src/main/java/ + + **/*.properties + + + + ${basedir}/src/main/resources + + filtered/** + + false + + + true + src/main/scripts + + *.bat + *.sh + + ${project.build.directory} + + + + ../config/dev + false + ${project.build.directory} + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + prepare-package + + copy-dependencies + + + + + ${project.build.directory}/lib + + + + org.apache.maven.plugins + maven-jar-plugin + + + + lib/ + true + fr.certu.chouette.command.Command + + + . + + + + + + maven-assembly-plugin + + chouette-cmd_${project.version} + false + + src/main/resources/assemblies/cbc.xml + + + + + make-assembly + package + + single + + + + + + + + diff --git a/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/CommercialStopGenerator.java b/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/CommercialStopGenerator.java index 518097bf2..00756a2ee 100644 --- a/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/CommercialStopGenerator.java +++ b/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/CommercialStopGenerator.java @@ -1,266 +1,266 @@ -package fr.certu.chouette.exchange.gtfs.importer; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.log4j.Logger; - -import fr.certu.chouette.model.neptune.AreaCentroid; -import fr.certu.chouette.model.neptune.StopArea; -import fr.certu.chouette.model.neptune.type.ChouetteAreaEnum; -import fr.certu.chouette.model.neptune.type.LongLatTypeEnum; - -public class CommercialStopGenerator extends AbstractGenerator -{ - private static final Logger logger = Logger.getLogger(CommercialStopGenerator.class); - - - - /** - * create and associate commercial stop points for boarding positions - * - * @param boardingPositions list of input boarding positions - * @return commercial stop points created - */ - public List createCommercialStopPoints(List boardingPositions,double distanceMax, boolean ignoreLastWord, int ignoreEndCharacters) - { - Map areaMap = new HashMap(); - - Set keys = new HashSet(); - for (StopArea stop : boardingPositions) - { - String key = stop.getName(); - if (ignoreLastWord) - { - String[] token = key.split(" "); - if (token.length > 0 && token[token.length -1].length() < ignoreEndCharacters) - { - key = key.substring(0, key.lastIndexOf(" "+token[token.length -1])); - } - } - else if (key.length() > ignoreEndCharacters) - { - key = key.substring(0,key.length()-ignoreEndCharacters); - } - keys.add(key); - } - - for (StopArea stop : boardingPositions) - { - - String mergeKey = stop.getName(); - for (String key : keys) - { - if (mergeKey.startsWith(key)) - { - mergeKey = key; - break; - } - } - - StopArea area = areaMap.get(mergeKey); - if (area == null) - { - area = new StopArea(); - initArea(area,stop); - areaMap.put(mergeKey, area); - } - area.addContainedStopArea(stop); - stop.setParent(area); - - } - - // check distance to explode areas - List dividedAreas = new ArrayList(); - for (StopArea area : areaMap.values()) - { - explodeArea(dividedAreas, area, 1,area.getObjectId(),distanceMax); - } - - // save area - List areas = new ArrayList(); - areas.addAll(areaMap.values()); - areas.addAll(dividedAreas); - - for (StopArea stopArea : areas) - { - String basename = stopArea.getName(); - for (StopArea boarding : stopArea.getContainedStopAreas()) - { - String name = boarding.getName(); - while (!name.contains(basename)) - { - basename = basename.substring(0, basename.length() -1); - if (basename.isEmpty()) break; - } - } - if (!basename.isEmpty()) stopArea.setName(basename.trim()); - } - - logger.debug(""+areas.size()+" commercial stops created"); - return areas; - - } - - /** - * Commercial stop point initialization with first boarding position values - * - * @param area commercial stop point - * @param stop boarding position - */ - private void initArea(StopArea area, StopArea stop) - { - Calendar now = Calendar.getInstance(); - area.setName(stop.getName()); - String[] token = stop.getObjectId().split(":"); - String objectId = token[0]+":"+token[1]+":COM_"+token[2]; - area.setObjectId(objectId); - area.setObjectVersion(stop.getObjectVersion()); - area.setCreationTime(now.getTime()); - area.setAreaType(ChouetteAreaEnum.COMMERCIALSTOPPOINT); - AreaCentroid areaCentroid = new AreaCentroid(); - areaCentroid.setName(area.getName()); - areaCentroid.setObjectId(objectId.replace(StopArea.STOPAREA_KEY, AreaCentroid.AREACENTROID_KEY)); - areaCentroid.setObjectVersion(stop.getObjectVersion()); - areaCentroid.setCreationTime(now.getTime()); - area.setAreaCentroid(areaCentroid); - areaCentroid.setContainedInStopArea(area); - - } - - /** - * divide commercial stop point into smaller ones if boarding positions are too far - *
recursive method - * - * @param dividedAreas divided area container - * @param area area to check - * @param rank rank of subdivision - */ - private void explodeArea(List dividedAreas, StopArea area,int rank,String baseId,double distanceMax) - { - if (!checkDistance(area,distanceMax)) - { - if (rank == 1) - { - logger.warn(area.getName()+" has long distance boarding positions , divided"); - } - List excludedList = excludeLongDistanceStops(area,distanceMax); - StopArea areaExcluded = new StopArea(); - initArea(areaExcluded, excludedList.get(0)); - // patch object id for non confusion - areaExcluded.setObjectId(baseId+"_"+rank); - areaExcluded.getAreaCentroid().setObjectId(areaExcluded.getObjectId().replace(StopArea.STOPAREA_KEY,AreaCentroid.AREACENTROID_KEY)); - for (StopArea excluded : excludedList) - { - areaExcluded.addContainedStopArea(excluded); - excluded.setParent(areaExcluded); - } - dividedAreas.add(areaExcluded); - explodeArea(dividedAreas,areaExcluded,rank+1,baseId,distanceMax); - } - } - - - /** - * remove boarding positions to far from others. - * - * @param area the commercial stop point to check - * @return a list of removed boarding positions - */ - private List excludeLongDistanceStops(StopArea area,double distanceMax) - { - List excludedStops = new ArrayList(); - - // remove stop most away from area while distance id invalid - while (!checkDistance(area,distanceMax)) - { - double distanceMaxInArea = 0; - StopArea excluded = null; - List stops = area.getContainedStopAreas(); - for (StopArea stop : stops) - { - - double distance = distance(area.getAreaCentroid().getLongitude().doubleValue(), - area.getAreaCentroid().getLatitude().doubleValue(), - stop.getAreaCentroid().getLongitude().doubleValue(), - stop.getAreaCentroid().getLatitude().doubleValue()); - if (distance > distanceMaxInArea) - { - distanceMaxInArea = distance; - excluded = stop; - } - } - if (excluded != null) - { - area.removeContainedStopArea(excluded); - excluded.setParent(null); - excludedStops.add(excluded); - } - } - return excludedStops; - } - - - /** - * compute centroid for the commercial stop point's boarding positions - * - * @param area - */ - private void buildCentroid(StopArea area) - { - - double sigmaLong = 0; - double sigmaLat = 0; - - for (StopArea stop : area.getContainedStopAreas()) - { - sigmaLong += stop.getAreaCentroid().getLongitude().doubleValue(); - sigmaLat += stop.getAreaCentroid().getLatitude().doubleValue(); - } - double areaLong = sigmaLong / area.getContainedStopAreas().size(); - double areaLat = sigmaLat / area.getContainedStopAreas().size(); - area.getAreaCentroid().setLongitude(new BigDecimal(areaLong)); - area.getAreaCentroid().setLatitude(new BigDecimal(areaLat)); - area.getAreaCentroid().setLongLatType(LongLatTypeEnum.WGS84); - } - - /** - * check every pair of stop to see if they are all in the distance - * - * @return - */ - private boolean checkDistance(StopArea area,double distanceMax) - { - buildCentroid(area); - // - List stops = area.getContainedStopAreas(); - for (int i = 0; i < stops.size() -1; i++) - { - StopArea first = stops.get(i); - for (int j = i+1; j < stops.size(); j++) - { - StopArea next = stops.get(j); - double distance = distance(first.getAreaCentroid().getLongitude().doubleValue(), - first.getAreaCentroid().getLatitude().doubleValue(), - next.getAreaCentroid().getLongitude().doubleValue(), - next.getAreaCentroid().getLatitude().doubleValue()); - if (distance > distanceMax) - { - // logger.debug("BP : "+first.getName()+" (pos="+first.getAreaCentroid().getLatitude()+","+first.getAreaCentroid().getLongitude()); - // logger.debug("BP : "+next.getName()+" (pos="+next.getAreaCentroid().getLatitude()+","+next.getAreaCentroid().getLongitude()); - // logger.debug("distance = "+distance); - return false; - } - } - } - return true; - } - - -} +package fr.certu.chouette.exchange.gtfs.importer; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.log4j.Logger; + +import fr.certu.chouette.model.neptune.AreaCentroid; +import fr.certu.chouette.model.neptune.StopArea; +import fr.certu.chouette.model.neptune.type.ChouetteAreaEnum; +import fr.certu.chouette.model.neptune.type.LongLatTypeEnum; + +public class CommercialStopGenerator extends AbstractGenerator +{ + private static final Logger logger = Logger.getLogger(CommercialStopGenerator.class); + + + + /** + * create and associate commercial stop points for boarding positions + * + * @param boardingPositions list of input boarding positions + * @return commercial stop points created + */ + public List createCommercialStopPoints(List boardingPositions,double distanceMax, boolean ignoreLastWord, int ignoreEndCharacters) + { + Map areaMap = new HashMap(); + + Set keys = new HashSet(); + for (StopArea stop : boardingPositions) + { + String key = stop.getName(); + if (ignoreLastWord) + { + String[] token = key.split(" "); + if (token.length > 0 && token[token.length -1].length() < ignoreEndCharacters) + { + key = key.substring(0, key.lastIndexOf(" "+token[token.length -1])); + } + } + else if (key.length() > ignoreEndCharacters) + { + key = key.substring(0,key.length()-ignoreEndCharacters); + } + keys.add(key); + } + + for (StopArea stop : boardingPositions) + { + + String mergeKey = stop.getName(); + for (String key : keys) + { + if (mergeKey.startsWith(key)) + { + mergeKey = key; + break; + } + } + + StopArea area = areaMap.get(mergeKey); + if (area == null) + { + area = new StopArea(); + initArea(area,stop); + areaMap.put(mergeKey, area); + } + area.addContainedStopArea(stop); + stop.setParent(area); + + } + + // check distance to explode areas + List dividedAreas = new ArrayList(); + for (StopArea area : areaMap.values()) + { + explodeArea(dividedAreas, area, 1,area.getObjectId(),distanceMax); + } + + // save area + List areas = new ArrayList(); + areas.addAll(areaMap.values()); + areas.addAll(dividedAreas); + + for (StopArea stopArea : areas) + { + String basename = stopArea.getName(); + for (StopArea boarding : stopArea.getContainedStopAreas()) + { + String name = boarding.getName(); + while (!name.contains(basename)) + { + basename = basename.substring(0, basename.length() -1); + if (basename.isEmpty()) break; + } + } + if (!basename.isEmpty()) stopArea.setName(basename.trim()); + } + + logger.debug(""+areas.size()+" commercial stops created"); + return areas; + + } + + /** + * Commercial stop point initialization with first boarding position values + * + * @param area commercial stop point + * @param stop boarding position + */ + private void initArea(StopArea area, StopArea stop) + { + Calendar now = Calendar.getInstance(); + area.setName(stop.getName()); + String[] token = stop.getObjectId().split(":"); + String objectId = token[0]+":"+token[1]+":COM_"+token[2]; + area.setObjectId(objectId); + area.setObjectVersion(stop.getObjectVersion()); + area.setCreationTime(now.getTime()); + area.setAreaType(ChouetteAreaEnum.COMMERCIALSTOPPOINT); + AreaCentroid areaCentroid = new AreaCentroid(); + areaCentroid.setName(area.getName()); + areaCentroid.setObjectId(objectId.replace(StopArea.STOPAREA_KEY, AreaCentroid.AREACENTROID_KEY)); + areaCentroid.setObjectVersion(stop.getObjectVersion()); + areaCentroid.setCreationTime(now.getTime()); + area.setAreaCentroid(areaCentroid); + areaCentroid.setContainedInStopArea(area); + + } + + /** + * divide commercial stop point into smaller ones if boarding positions are too far + *
recursive method + * + * @param dividedAreas divided area container + * @param area area to check + * @param rank rank of subdivision + */ + private void explodeArea(List dividedAreas, StopArea area,int rank,String baseId,double distanceMax) + { + if (!checkDistance(area,distanceMax)) + { + if (rank == 1) + { + logger.warn(area.getName()+" has long distance boarding positions , divided"); + } + List excludedList = excludeLongDistanceStops(area,distanceMax); + StopArea areaExcluded = new StopArea(); + initArea(areaExcluded, excludedList.get(0)); + // patch object id for non confusion + areaExcluded.setObjectId(baseId+"_"+rank); + areaExcluded.getAreaCentroid().setObjectId(areaExcluded.getObjectId().replace(StopArea.STOPAREA_KEY,AreaCentroid.AREACENTROID_KEY)); + for (StopArea excluded : excludedList) + { + areaExcluded.addContainedStopArea(excluded); + excluded.setParent(areaExcluded); + } + dividedAreas.add(areaExcluded); + explodeArea(dividedAreas,areaExcluded,rank+1,baseId,distanceMax); + } + } + + + /** + * remove boarding positions to far from others. + * + * @param area the commercial stop point to check + * @return a list of removed boarding positions + */ + private List excludeLongDistanceStops(StopArea area,double distanceMax) + { + List excludedStops = new ArrayList(); + + // remove stop most away from area while distance id invalid + while (!checkDistance(area,distanceMax)) + { + double distanceMaxInArea = 0; + StopArea excluded = null; + List stops = area.getContainedStopAreas(); + for (StopArea stop : stops) + { + + double distance = distance(area.getAreaCentroid().getLongitude().doubleValue(), + area.getAreaCentroid().getLatitude().doubleValue(), + stop.getAreaCentroid().getLongitude().doubleValue(), + stop.getAreaCentroid().getLatitude().doubleValue()); + if (distance > distanceMaxInArea) + { + distanceMaxInArea = distance; + excluded = stop; + } + } + if (excluded != null) + { + area.removeContainedStopArea(excluded); + excluded.setParent(null); + excludedStops.add(excluded); + } + } + return excludedStops; + } + + + /** + * compute centroid for the commercial stop point's boarding positions + * + * @param area + */ + private void buildCentroid(StopArea area) + { + + double sigmaLong = 0; + double sigmaLat = 0; + + for (StopArea stop : area.getContainedStopAreas()) + { + sigmaLong += stop.getAreaCentroid().getLongitude().doubleValue(); + sigmaLat += stop.getAreaCentroid().getLatitude().doubleValue(); + } + double areaLong = sigmaLong / area.getContainedStopAreas().size(); + double areaLat = sigmaLat / area.getContainedStopAreas().size(); + area.getAreaCentroid().setLongitude(new BigDecimal(areaLong)); + area.getAreaCentroid().setLatitude(new BigDecimal(areaLat)); + area.getAreaCentroid().setLongLatType(LongLatTypeEnum.WGS84); + } + + /** + * check every pair of stop to see if they are all in the distance + * + * @return + */ + private boolean checkDistance(StopArea area,double distanceMax) + { + buildCentroid(area); + // + List stops = area.getContainedStopAreas(); + for (int i = 0; i < stops.size() -1; i++) + { + StopArea first = stops.get(i); + for (int j = i+1; j < stops.size(); j++) + { + StopArea next = stops.get(j); + double distance = distance(first.getAreaCentroid().getLongitude().doubleValue(), + first.getAreaCentroid().getLatitude().doubleValue(), + next.getAreaCentroid().getLongitude().doubleValue(), + next.getAreaCentroid().getLatitude().doubleValue()); + if (distance > distanceMax) + { + // logger.debug("BP : "+first.getName()+" (pos="+first.getAreaCentroid().getLatitude()+","+first.getAreaCentroid().getLongitude()); + // logger.debug("BP : "+next.getName()+" (pos="+next.getAreaCentroid().getLatitude()+","+next.getAreaCentroid().getLongitude()); + // logger.debug("distance = "+distance); + return false; + } + } + } + return true; + } + + +} diff --git a/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/GtfsImportLinePlugin_fr.properties b/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/GtfsImportLinePlugin_fr.properties index f80d702f2..d833d81b8 100644 --- a/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/GtfsImportLinePlugin_fr.properties +++ b/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/GtfsImportLinePlugin_fr.properties @@ -1,11 +1,11 @@ GTFS=import de lignes au format GTFS inputFile=chemin du fichier Zip GTFS objectIdPrefix=pr\u00E9fixe des identifiants Neptune -incremental=mode incremental\: indice d'incr\u00E9ment -mergeRouteByShortName=fusionne les routes GTFS \u00E0 nom court identiques +incremental=mode incremental\: indice d'incr\u00E9ment +mergeRouteByShortName=fusionne les routes GTFS \u00E0 nom court identiques maxDistanceForCommercial=distance maximale en m\u00E8tres pour regrouper les arr\u00EAts homonymes en arr\u00EAt commerciaux ignoreLastWord=ignorer le dernier mot des noms des arr\u00EAts pour le regroupement ignoreEndChars=ignorer la fin du nom des arr\u00EAts pour le regroupement -maxDistanceForConnectionLink=distance maximale en m\u00E8tres pour la cr\u00E9ation des correspondances -colorFile=fichier de sauvegarde des couleurs pour futur export KML -optimizeMemory=optimise les ressources m\u00E9moire au d\u00E9triment du temps +maxDistanceForConnectionLink=distance maximale en m\u00E8tres pour la cr\u00E9ation des correspondances +colorFile=fichier de sauvegarde des couleurs pour futur export KML +optimizeMemory=optimise les ressources m\u00E9moire au d\u00E9triment du temps diff --git a/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/NeptuneConverter.java b/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/NeptuneConverter.java index 4af54a52f..d2abbe6d5 100644 --- a/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/NeptuneConverter.java +++ b/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/NeptuneConverter.java @@ -1,770 +1,770 @@ -/** - * Projet CHOUETTE - * - * ce projet est sous license libre - * voir LICENSE.txt pour plus de details - * - */ -package fr.certu.chouette.exchange.gtfs.importer; - -import java.lang.reflect.InvocationTargetException; -import java.sql.Time; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import lombok.Setter; - -import org.apache.commons.beanutils.BeanUtils; -import org.apache.log4j.Logger; - -import fr.certu.chouette.exchange.gtfs.importer.producer.AbstractModelProducer; -import fr.certu.chouette.exchange.gtfs.importer.producer.CompanyProducer; -import fr.certu.chouette.exchange.gtfs.importer.producer.ConnectionLinkProducer; -import fr.certu.chouette.exchange.gtfs.importer.producer.LineProducer; -import fr.certu.chouette.exchange.gtfs.importer.producer.PTNetworkProducer; -import fr.certu.chouette.exchange.gtfs.importer.producer.RouteProducer; -import fr.certu.chouette.exchange.gtfs.importer.producer.StopAreaProducer; -import fr.certu.chouette.exchange.gtfs.importer.producer.TimetableProducer; -import fr.certu.chouette.exchange.gtfs.importer.producer.VehicleJourneyAtStopProducer; -import fr.certu.chouette.exchange.gtfs.importer.producer.VehicleJourneyProducer; -import fr.certu.chouette.exchange.gtfs.model.GtfsAgency; -import fr.certu.chouette.exchange.gtfs.model.GtfsCalendar; -import fr.certu.chouette.exchange.gtfs.model.GtfsCalendarDate; -import fr.certu.chouette.exchange.gtfs.model.GtfsFrequency; -import fr.certu.chouette.exchange.gtfs.model.GtfsRoute; -import fr.certu.chouette.exchange.gtfs.model.GtfsStop; -import fr.certu.chouette.exchange.gtfs.model.GtfsStopTime; -import fr.certu.chouette.exchange.gtfs.model.GtfsTransfer; -import fr.certu.chouette.exchange.gtfs.model.GtfsTrip; -import fr.certu.chouette.exchange.gtfs.model.neptune.DbVehicleJourneyFactory; -import fr.certu.chouette.model.neptune.Company; -import fr.certu.chouette.model.neptune.ConnectionLink; -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.StopArea; -import fr.certu.chouette.model.neptune.StopPoint; -import fr.certu.chouette.model.neptune.Timetable; -import fr.certu.chouette.model.neptune.VehicleJourney; -import fr.certu.chouette.model.neptune.VehicleJourneyAtStop; -import fr.certu.chouette.plugin.report.ReportItem; - -/** - * convert GTFS raw data structure to Chouette internal one - * - */ -public class NeptuneConverter -{ - private static Logger logger = Logger.getLogger(NeptuneConverter.class); - - /** - * Line producer from GtfsRoute - */ - @Setter - private LineProducer lineProducer; - /** - * Route producer from GtfsRoute - */ - @Setter - private RouteProducer routeProducer; - /** - * PTNetwork producer from base name - */ - @Setter - private PTNetworkProducer networkProducer; - /** - * Company producer from GtfsAgency - */ - @Setter - private CompanyProducer companyProducer; - /** - * VehicleJourney producer from GtfsTrip - */ - @Setter - private VehicleJourneyProducer vehicleJourneyProducer; - /** - * VehicleJourneyAtStop producer from GtfsStopTime - */ - @Setter - private VehicleJourneyAtStopProducer vehicleJourneyAtStopProducer; - /** - * StopArea (BoardingPosition) producer from GtfsStop - */ - @Setter - private StopAreaProducer stopAreaProducer; - /** - * Timetable producer from GtfsCalendar and CtfsCalendarDate - */ - @Setter - private TimetableProducer timetableProducer; - - /** - * Connection producer from GtfsTransfer - */ - @Setter private ConnectionLinkProducer connectionLinkProducer ; - - /** - * CommercialStopPoint generator - */ - @Setter - private CommercialStopGenerator commercialStopGenerator; - /** - * ConnectionLink generator - */ - @Setter - private ConnectionLinkGenerator connectionLinkGenerator; - - /** - * convert Gfts model to Chouette model - * - * @param prefix - * objectId prefix - * @param data - * Gtfs data - * @param maxDistanceForCommercialStop - * maximum distance in meter to merge same named BoardingPosition - * in one CommercialStop - * @param ignoreLastWord - * ignore last word for BoardingPosition name comparison - * @param ignoreEndCharacters - * ignore last characters for BoardingPosition name comparison - * @param maxDistanceForConnectionLink - * maximum distance in meter to connect CommercialStops with a - * ConnectionLink - * @return a Chouette internal model nearly connected - */ - public ModelAssembler convert(boolean optimizeMemory, String prefix, String incrementalPrefix, GtfsData data, double maxDistanceForCommercialStop, - boolean ignoreLastWord, int ignoreEndCharacters, double maxDistanceForConnectionLink, boolean mergeRouteByShortName) - { - DbVehicleJourneyFactory vjFactory = new DbVehicleJourneyFactory(prefix,optimizeMemory); - vehicleJourneyProducer.setFactory(vjFactory); - ModelAssembler assembler = new ModelAssembler(); - ReportItem report = null; - AbstractModelProducer.setPrefix(prefix); - AbstractModelProducer.setIncrementalPrefix(incrementalPrefix); - - // PTnetwork - PTNetwork network = networkProducer.produce(data.getNetwork(), report); - assembler.setPtNetwork(network); - - // Companies - List companies = new ArrayList(); - for (GtfsAgency gtfsAgency : data.getAgencies().getAll()) - // for (Iterator iterator = data.getAgencies().iterator(); iterator.hasNext();) - { - Company company = companyProducer.produce(gtfsAgency, report); - companies.add(company); - // iterator.remove(); - } - data.getAgencies().clear(); - assembler.setCompanies(companies); - - // lines, routes - List lines = new ArrayList(); - List routes = new ArrayList(); - Map mapLineByRouteName = new HashMap(); - Map mapRouteByRouteId = new HashMap(); - logger.info("process routes :" + data.getRoutes().size()); - Map mapRouteExtensionByRouteId = new HashMap(); - - for (GtfsRoute gtfsRoute : data.getRoutes().getAll()) - // for (Iterator iterator = data.getRoutes().iterator(); iterator.hasNext();) - { - // GtfsRoute gtfsRoute = iterator.next(); - // must produce 2 routes : one for each direction; - // at end of processing, empty route will be destroyed - String routeName = mergeRouteByShortName?gtfsRoute.getRouteShortName():gtfsRoute.getRouteId(); - Line line = mapLineByRouteName.get(routeName); - if (line == null) - { - line = lineProducer.produce(gtfsRoute, report); - mapLineByRouteName.put(routeName, line); - lines.add(line); - } - Route route0 = routeProducer.produce(gtfsRoute, report); - Route route1 = new Route(); - route1.setName(route0.getName()); - route1.setPublishedName(route0.getPublishedName()); - route1.setComment(route0.getComment()); - route1.setObjectId(route0.getObjectId()+"_1"); - route0.setObjectId(route0.getObjectId()+"_0"); - route0.setLine(line); - route1.setWayBackRouteId(route0.getObjectId()); - route0.setWayBackRouteId(route1.getObjectId()); - mapRouteByRouteId.put(gtfsRoute.getRouteId()+"_0", route0); - line.addRoute(route0); - routes.add(route0); - mapRouteExtensionByRouteId.put(route0.getObjectId(), Integer.valueOf(1)); - route1.setLine(line); - mapRouteByRouteId.put(gtfsRoute.getRouteId()+"_1", route1); - line.addRoute(route1); - routes.add(route1); - mapRouteExtensionByRouteId.put(route1.getObjectId(), Integer.valueOf(1)); - // iterator.remove(); - } - // System.gc(); - logger.debug("free memory = "+Runtime.getRuntime().freeMemory()); - logger.debug("max memory = "+Runtime.getRuntime().maxMemory()); - logger.debug("total memory = "+Runtime.getRuntime().totalMemory()); - assembler.setLines(lines); - assembler.setRoutes(routes); - - // stopareas - List areas = new ArrayList(); - Map mapStopAreasByStopId = new HashMap(); - logger.info("process stopArea :" + data.getStops().size()); - for (GtfsStop gtfsStop : data.getStops().getAll()) - // for (Iterator iterator = data.getStops().iterator(); iterator.hasNext();) - { - // GtfsStop gtfsStop = iterator.next(); - // iterator.remove(); - StopArea area = stopAreaProducer.produce(gtfsStop, report); - areas.add(area); - mapStopAreasByStopId.put(gtfsStop.getStopId(), area); - } - data.getStops().clear(); - // System.gc(); - logger.debug("free memory = "+Runtime.getRuntime().freeMemory()); - logger.debug("max memory = "+Runtime.getRuntime().maxMemory()); - logger.debug("total memory = "+Runtime.getRuntime().totalMemory()); - List commercials = commercialStopGenerator.createCommercialStopPoints(areas, - maxDistanceForCommercialStop, ignoreLastWord, ignoreEndCharacters); - areas.addAll(commercials); - assembler.setStopAreas(areas); - - // Timetables - List timetables = new ArrayList(); - Map mapTimetableByServiceId = new HashMap(); - - logger.info("process timetables :" + data.getCalendars().size()); - for (GtfsCalendar gtfsCalendar : data.getCalendars().getAll()) - // for (Iterator iterator = data.getCalendars().iterator(); iterator.hasNext();) - { - // GtfsCalendar gtfsCalendar = iterator.next(); - // iterator.remove(); - - List dates = data.getCalendarDates().getAllFromParent(gtfsCalendar.getServiceId()); - for (GtfsCalendarDate date : dates) - { - gtfsCalendar.addCalendarDate(date); - } - - Timetable timetable = timetableProducer.produce(gtfsCalendar, report); - - timetables.add(timetable); - mapTimetableByServiceId.put(gtfsCalendar.getServiceId(), timetable); - } - - logger.debug("timetables mapped : "+mapTimetableByServiceId.size()); - // System.gc(); - logger.debug("free memory = "+Runtime.getRuntime().freeMemory()); - logger.debug("max memory = "+Runtime.getRuntime().maxMemory()); - logger.debug("total memory = "+Runtime.getRuntime().totalMemory()); - assembler.setTimetables(timetables); - - // vehicleJourneys , vehicleJourneyAtStops, JourneyPatterns and StopPoints - // build in to steps : - // first dispatch stopTimes to trips - // next match stoptimes sequence of each trip to a journey pattern; - // and identify stops to be affected to routes - - // Map> mapStopTimesByTrip = new HashMap>(); - // logger.info("process stopTimes :" + data.getStopTimes().size()); - // - // { - // List stopTimesOfATrip = null; - // String previousTrip = null; - // int count = 0; - // for (GtfsStopTime gtfsStopTime: data.getStopTimes()) - // { - // if (!gtfsStopTime.getTripId().equals(previousTrip)) - // { - // stopTimesOfATrip = mapStopTimesByTrip.get(gtfsStopTime.getTripId()); - // previousTrip = gtfsStopTime.getTripId(); - // count++; - // if (count % 1000 == 0) logger.debug("stops in trips count = "+count); - // - // } - // if (stopTimesOfATrip == null) - // { - // stopTimesOfATrip = new ArrayList(); - // mapStopTimesByTrip.put(gtfsStopTime.getTripId(), stopTimesOfATrip); - // } - // - // stopTimesOfATrip.add(gtfsStopTime); - // } - // } - // data.getStopTimes().clear(); - - List journeyPatterns = new ArrayList(); - List stopPoints = new ArrayList(); - List vehicleJourneys = new ArrayList(); - Map mapVehicleJourneyByTripId = new HashMap(); - Map mapJourneyPatternByStopSequence = new HashMap(); - Map mapStopPointbyJourneyPatternRank = new HashMap(); - - logger.info("process vehicleJourneys :" + data.getTrips().size()); - int count = 0; - for (GtfsTrip gtfsTrip : data.getTrips().getAll()) - //for (Iterator iterator = data.getTrips().iterator(); iterator.hasNext();) - { - // GtfsTrip gtfsTrip = iterator.next(); - // iterator.remove(); - count++; - if (count % 1000 == 0) - { - logger.debug("process "+count+" vehicleJourneys ..."); - logger.debug("free memory = "+Runtime.getRuntime().freeMemory()); - logger.debug("max memory = "+Runtime.getRuntime().maxMemory()); - logger.debug("total memory = "+Runtime.getRuntime().totalMemory()); - } - - VehicleJourney vehicleJourney = vehicleJourneyProducer.produce(gtfsTrip, report); - Timetable timetable = mapTimetableByServiceId.get(gtfsTrip.getServiceId()); - if (timetable == null) - { - logger.warn("service "+gtfsTrip.getServiceId()+" not found for trip "+gtfsTrip.getTripId()); - } - else - { - vehicleJourney.addTimetable(timetable); - timetable.addVehicleJourney(vehicleJourney); - } - vehicleJourneys.add(vehicleJourney); - String routeId = gtfsTrip.getRouteId()+"_"+gtfsTrip.getDirectionId(); - Route route = mapRouteByRouteId.get(routeId); - mapVehicleJourneyByTripId.put(gtfsTrip.getTripId(), vehicleJourney); - // stopSequence - // List stopTimesOfATrip = mapStopTimesByTrip.get(gtfsTrip.getTripId()); - // mapStopTimesByTrip.remove(gtfsTrip.getTripId()); - List stopTimesOfATrip = data.getStopTimes().getAllFromParent(gtfsTrip.getTripId()); - Collections.sort(stopTimesOfATrip); - String journeyKey = routeId; - for (GtfsStopTime gtfsStopTime : stopTimesOfATrip) - { - journeyKey += "," + gtfsStopTime.getStopId(); - } - JourneyPattern journeyPattern = mapJourneyPatternByStopSequence.get(journeyKey); - if (journeyPattern == null) - { - // logger.debug("creating new journeyPattern"); - journeyPattern = new JourneyPattern(); - if (route.getJourneyPatterns() != null && !route.getJourneyPatterns().isEmpty()) - { - // wayback relations will be lost - route = cloneRoute(route, mapRouteExtensionByRouteId); - routes.add(route); - // logger.debug("cloning route " + route.getObjectId()); - } - journeyPattern.setRoute(route); - route.addJourneyPattern(journeyPattern); - journeyPattern.setObjectId(route.getObjectId().replace(Route.ROUTE_KEY, JourneyPattern.JOURNEYPATTERN_KEY) - + "a" + route.getJourneyPatterns().size()); - // compare stops - // logger.debug("affect journeypattern " + journeyPattern.getObjectId() + " to route " + route.getObjectId()); - List jpStopPoints = buildStopPoint(route.getObjectId(), stopTimesOfATrip, mapStopAreasByStopId); - route.setStopPoints(jpStopPoints); - stopPoints.addAll(jpStopPoints); - for (int i = 0; i < jpStopPoints.size(); i++) - { - mapStopPointbyJourneyPatternRank.put(journeyKey + "a" + (i + 1), jpStopPoints.get(i)); - } - journeyPattern.setStopPoints(jpStopPoints); - // map journey pattern - mapJourneyPatternByStopSequence.put(journeyKey, journeyPattern); - journeyPatterns.add(journeyPattern); - - } - route = journeyPattern.getRoute(); - vehicleJourney.setRoute(route); - vehicleJourney.setRouteId(route.getObjectId()); - route.setWayBack(gtfsTrip.getDirectionId() == 0 ? "A" : "R"); - vehicleJourney.setJourneyPattern(journeyPattern); - vehicleJourney.setJourneyPatternId(journeyPattern.getObjectId()); - journeyPattern.addVehicleJourney(vehicleJourney); - // vehicleJourneyAtStop - int stRank = 1; - for (GtfsStopTime gtfsStopTime : stopTimesOfATrip) - { - VehicleJourneyAtStop vjas = vehicleJourneyAtStopProducer.produce(gtfsStopTime, report); - vjas.setVehicleJourney(vehicleJourney); - vehicleJourney.addVehicleJourneyAtStop(vjas); - String stopKey = journeyKey + "a" + stRank; - vjas.setOrder(stRank); - StopPoint spor = mapStopPointbyJourneyPatternRank.get(stopKey); - if (spor == null) - { - logger.error("StopPoint " + stopKey + " not found"); - } - vjas.setStopPoint(spor); - stRank++; - - } - stopTimesOfATrip.clear(); - // apply frequencies - for (GtfsFrequency frequency : data.getFrequencies().getAllFromParent(gtfsTrip.getTripId())) - { - baseVehicleJourneyToTime(vehicleJourney, frequency.getStartTime().getTime().getTime()); - try - { - if (!frequency.getStartTime().isTomorrow() && frequency.getEndTime().isTomorrow()) - { - - copyVehicleJourney(vjFactory,vehicleJourney, frequency.getEndTime().getTime().getTime() + 24 * 3600 * 1000, - frequency.getHeadwaySecs() * 1000); - } - else - { - copyVehicleJourney(vjFactory,vehicleJourney, frequency.getEndTime().getTime().getTime(), frequency.getHeadwaySecs() * 1000); - } - } - catch (Exception e) - { - logger.error("cannot apply frequency ", e); - } - } - - vjFactory.flush(vehicleJourney); - // System.gc(); - } - logger.debug("process "+count+" vehicleJourneys ..."); - logger.debug("free memory = "+Runtime.getRuntime().freeMemory()); - logger.debug("max memory = "+Runtime.getRuntime().maxMemory()); - logger.debug("total memory = "+Runtime.getRuntime().totalMemory()); - - // free some unused maps - // mapStopTimesByTrip.clear(); - data.getTrips().clear(); - data.getStopTimes().clear(); - vjFactory.flush(); - // System.gc(); - logger.debug("free memory = "+Runtime.getRuntime().freeMemory()); - logger.debug("max memory = "+Runtime.getRuntime().maxMemory()); - logger.debug("total memory = "+Runtime.getRuntime().totalMemory()); - // fix spor objectids and clean empty routes - - for (Iterator iterator = routes.iterator(); iterator.hasNext();) - { - Route route = iterator.next(); - if (route.getStopPoints() == null || route.getStopPoints().isEmpty()) - { - // dettach route - route.getLine().removeRoute(route); - if (route.getWayBackRouteId() != null) - { - Route wayback = mapRouteByRouteId.get(route.getWayBackRouteId().split(":")[2]); - if (wayback == null) - { - logger.error("route to remove "+route.getObjectId()+" : opposite route "+route.getWayBackRouteId()+" not found"); - } - else - { - wayback.setWayBackRouteId(null); - } - } - iterator.remove(); - } - else - { - int rank = 0; - for (StopPoint spor : route.getStopPoints()) - { - spor.setPosition(rank++); - spor.setRoute(route); - } - // force rebuild ptlinks - route.rebuildPTLinks(); - } - } - - // clone vehicleJourneys by frequency - // for (GtfsFrequency frequency : data.getFrequencies().getAll()) - // { - // DbVehicleJourney vj = mapVehicleJourneyByTripId.get(frequency.getTripId()); - // if (vj != null) - // { - // baseVehicleJourneyToTime(vj, frequency.getStartTime().getTime().getTime()); - // try - // { - // if (!frequency.getStartTime().isTomorrow() && frequency.getEndTime().isTomorrow()) - // { - // - // copyVehicleJourney(vj, frequency.getEndTime().getTime().getTime() + 24 * 3600 * 1000, - // frequency.getHeadwaySecs() * 1000); - // } - // else - // { - // copyVehicleJourney(vj, frequency.getEndTime().getTime().getTime(), frequency.getHeadwaySecs() * 1000); - // } - // } - // catch (Exception e) - // { - // logger.error("cannot apply frequency ", e); - // } - // } - // } - - // merge identical vehicleJourneys with different timetables - // vehicleJourneys.clear(); - // for (JourneyPattern jp : journeyPatterns) - // { - // List vjs = new ArrayList(jp.getVehicleJourneys()); - // for (int i = 0; i < vjs.size(); i++) - // { - // VehicleJourney vj1 = vjs.get(i); - // if (vj1.getObjectId() == null) - // continue; - // for (int j = i + 1; j < vjs.size(); j++) - // { - // VehicleJourney vj2 = vjs.get(j); - // if (vj2.getObjectId() == null) - // continue; - // if (compareTimes(vj1, vj2)) - // { - // // merge - // String id = vj2.getObjectId().split(":")[2]; - // vj1.setObjectId(vj1.getObjectId() + "_" + id); - // for (Timetable tm : vj2.getTimetables()) - // { - // tm.removeVehicleJourney(vj2); - // tm.addVehicleJourney(vj1); - // vj1.addTimetable(tm); - // } - // jp.removeVehicleJourney(vj2); - // vj2.setObjectId(null); // to ignore in further iterations - // } - // } - // vehicleJourneys.add(vj1); - // } - // } - - assembler.setVehicleJourneys(vehicleJourneys); - assembler.setStopPoints(stopPoints); - assembler.setJourneyPatterns(journeyPatterns); - - // ConnectionLinks - List links = new ArrayList(); - List excludedLinks = new ArrayList(); - - for (GtfsTransfer transfer : data.getTransfers().getAll()) - { - ConnectionLink link = connectionLinkProducer.produce(transfer, report); - link.setStartOfLink(mapStopAreasByStopId.get(link.getStartOfLinkId())); - link.setEndOfLink(mapStopAreasByStopId.get(link.getEndOfLinkId())); - if (link.getStartOfLink() == null || link.getEndOfLink() == null) - { - logger.error("line "+transfer.getFileLineNumber()+" invalid transfer : form or to stop unknown"); - } - link.setStartOfLinkId(link.getStartOfLink().getObjectId()); - link.setEndOfLinkId(link.getEndOfLink().getObjectId()); - - if ("FORBIDDEN".equals(link.getName())) - { - excludedLinks.add(link); - } - else - { - link.setName("from "+link.getStartOfLink().getName()+" to "+link.getEndOfLink().getName()); - links.add(link); - } - } - - if (maxDistanceForConnectionLink > 0.) - { - links.addAll(connectionLinkGenerator.createConnectionLinks(commercials, - maxDistanceForConnectionLink,links,excludedLinks)); - assembler.setConnectionLinks(links); - } - - return assembler; - } - - /** - * compare VehicleJourneys on vehicleJourneyAtStops departure and arrival - * times - * - * @param vj1 - * @param vj2 - * @return - */ - private boolean compareTimes2(VehicleJourney vj1, VehicleJourney vj2) - { - List vjass1 = vj1.getVehicleJourneyAtStops(); - List vjass2 = vj2.getVehicleJourneyAtStops(); - - for (int i = 0; i < vjass1.size(); i++) - { - if (vjass1.get(i).getArrivalTime() != vjass2.get(i).getArrivalTime()) - return false; - if (vjass1.get(i).getDepartureTime() != vjass2.get(i).getDepartureTime()) - return false; - } - return true; - } - - /** - * create a copy of a route - * - * @param route - * route to copy - * @param mapRouteExtensionByRouteId - * next rank for objectId build - * @return new route builded by copy - */ - private Route cloneRoute(Route route, Map mapRouteExtensionByRouteId) - { - Route clone = new Route(); - clone.setLine(route.getLine()); - route.getLine().addRoute(clone); - Integer rank = mapRouteExtensionByRouteId.get(route.getObjectId()); - clone.setObjectId(route.getObjectId() + "_" + rank); - mapRouteExtensionByRouteId.put(route.getObjectId(), rank + 1); - clone.setName(route.getName()); - clone.setPublishedName(route.getPublishedName()); - clone.setComment(route.getComment()); - - return clone; - } - - /** - * build stopPoints for Route - * - * @param routeId - * route objectId - * @param stopTimesOfATrip - * first trip's ordered GTFS StopTimes - * @param mapStopAreasByStopId - * stopAreas to attach created StopPoints (parent relationship) - * @return - */ - private List buildStopPoint(String routeId, List stopTimesOfATrip, - Map mapStopAreasByStopId) - { - List stopPoints = new ArrayList(); - Set stopPointKeys = new HashSet(); - - for (GtfsStopTime gtfsStopTime : stopTimesOfATrip) - { - String stopKey = routeId.replace(Route.ROUTE_KEY, StopPoint.STOPPOINT_KEY) + "a" + gtfsStopTime.getStopId(); - if (stopPointKeys.contains(stopKey)) - stopKey = stopKey + "_1"; - stopPointKeys.add(stopKey); - StopPoint spor = new StopPoint(); - spor.setObjectId(stopKey); - StopArea area = mapStopAreasByStopId.get(gtfsStopTime.getStopId()); - area.addContainedStopPoint(spor); - spor.setContainedInStopArea(area); - spor.setName(area.getName()); - spor.setLatitude(area.getAreaCentroid().getLatitude()); - spor.setLongitude(area.getAreaCentroid().getLongitude()); - spor.setLongLatType(area.getAreaCentroid().getLongLatType()); - stopPoints.add(spor); - - } - return stopPoints; - - } - - /** - * shift vehicleJourney times to start vehicleJourney at a specific time - * - * @param vj - * vehicleJourney to shift - * @param t - * start time (first StopPoint's departureTime) - */ - private void baseVehicleJourneyToTime(VehicleJourney vj, long t) - { - VehicleJourneyAtStop first = vj.getVehicleJourneyAtStops().get(0); - long depOffset = t - first.getDepartureTime().getTime(); - long arrOffset = t - first.getArrivalTime().getTime(); - - for (VehicleJourneyAtStop vjas : vj.getVehicleJourneyAtStops()) - { - vjas.setArrivalTime(shiftTime(vjas.getArrivalTime(), arrOffset)); - vjas.setDepartureTime(shiftTime(vjas.getDepartureTime(), depOffset)); - } - } - - /** - * shift a time on and offset - * - * @param t - * time to shift - * @param offset - * offset (seconds) - * @return time shifted (new instance) - */ - private Time shiftTime(Time t, long offset) - { - return new Time((t.getTime() + offset) % (24 * 3600 * 1000)); - } - - /** - * shift several times a vehicleJourney to match frequency on scheduled - * vehicleJourneys - *

- * vehicleJourneys are added to journeyPattern - * - * @param vj - * vehicleJourney to shift - * @param end - * last StartTime in milliseconds - * @param headway - * gap between each new vehicleJourneys - * @throws IllegalAccessException - * @throws InstantiationException - * @throws InvocationTargetException - * @throws NoSuchMethodException - */ - private void copyVehicleJourney(DbVehicleJourneyFactory factory, VehicleJourney vj, long end, long headway) throws IllegalAccessException, - InstantiationException, InvocationTargetException, NoSuchMethodException - { - VehicleJourneyAtStop first = vj.getVehicleJourneyAtStops().get(0); - long start = first.getDepartureTime().getTime(); - long stop = end - start; - int iter = 1; - - long offset = headway; - while (offset <= stop) - { - VehicleJourney nvj = factory.getNewVehicleJourney(); - nvj.setObjectId(vj.getObjectId() + "a" + iter); - iter++; - for (Timetable timetable : nvj.getTimetables()) - { - timetable.addVehicleJourney(nvj); - } - List vjass = vj.getVehicleJourneyAtStops(); - for (VehicleJourneyAtStop vjas : vjass) - { - VehicleJourneyAtStop nvjas = (VehicleJourneyAtStop) BeanUtils.cloneBean(vjas); - nvjas.setVehicleJourney(nvj); - nvjas.setArrivalTime(shiftTime(nvjas.getArrivalTime(), offset)); - nvjas.setDepartureTime(shiftTime(nvjas.getDepartureTime(), offset)); - nvj.addVehicleJourneyAtStop(nvjas); - } - nvj.setRoute(vj.getRoute()); - nvj.setRouteId(vj.getRouteId()); - nvj.setJourneyPattern(vj.getJourneyPattern()); - nvj.setJourneyPatternId(vj.getJourneyPatternId()); - nvj.getJourneyPattern().addVehicleJourney(nvj); - for (Timetable tm : vj.getTimetables()) - { - nvj.addTimetable(tm); - tm.addVehicleJourney(nvj); - } - factory.flush(nvj); - offset += headway; - } - return; - } - -} +/** + * Projet CHOUETTE + * + * ce projet est sous license libre + * voir LICENSE.txt pour plus de details + * + */ +package fr.certu.chouette.exchange.gtfs.importer; + +import java.lang.reflect.InvocationTargetException; +import java.sql.Time; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import lombok.Setter; + +import org.apache.commons.beanutils.BeanUtils; +import org.apache.log4j.Logger; + +import fr.certu.chouette.exchange.gtfs.importer.producer.AbstractModelProducer; +import fr.certu.chouette.exchange.gtfs.importer.producer.CompanyProducer; +import fr.certu.chouette.exchange.gtfs.importer.producer.ConnectionLinkProducer; +import fr.certu.chouette.exchange.gtfs.importer.producer.LineProducer; +import fr.certu.chouette.exchange.gtfs.importer.producer.PTNetworkProducer; +import fr.certu.chouette.exchange.gtfs.importer.producer.RouteProducer; +import fr.certu.chouette.exchange.gtfs.importer.producer.StopAreaProducer; +import fr.certu.chouette.exchange.gtfs.importer.producer.TimetableProducer; +import fr.certu.chouette.exchange.gtfs.importer.producer.VehicleJourneyAtStopProducer; +import fr.certu.chouette.exchange.gtfs.importer.producer.VehicleJourneyProducer; +import fr.certu.chouette.exchange.gtfs.model.GtfsAgency; +import fr.certu.chouette.exchange.gtfs.model.GtfsCalendar; +import fr.certu.chouette.exchange.gtfs.model.GtfsCalendarDate; +import fr.certu.chouette.exchange.gtfs.model.GtfsFrequency; +import fr.certu.chouette.exchange.gtfs.model.GtfsRoute; +import fr.certu.chouette.exchange.gtfs.model.GtfsStop; +import fr.certu.chouette.exchange.gtfs.model.GtfsStopTime; +import fr.certu.chouette.exchange.gtfs.model.GtfsTransfer; +import fr.certu.chouette.exchange.gtfs.model.GtfsTrip; +import fr.certu.chouette.exchange.gtfs.model.neptune.DbVehicleJourneyFactory; +import fr.certu.chouette.model.neptune.Company; +import fr.certu.chouette.model.neptune.ConnectionLink; +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.StopArea; +import fr.certu.chouette.model.neptune.StopPoint; +import fr.certu.chouette.model.neptune.Timetable; +import fr.certu.chouette.model.neptune.VehicleJourney; +import fr.certu.chouette.model.neptune.VehicleJourneyAtStop; +import fr.certu.chouette.plugin.report.ReportItem; + +/** + * convert GTFS raw data structure to Chouette internal one + * + */ +public class NeptuneConverter +{ + private static Logger logger = Logger.getLogger(NeptuneConverter.class); + + /** + * Line producer from GtfsRoute + */ + @Setter + private LineProducer lineProducer; + /** + * Route producer from GtfsRoute + */ + @Setter + private RouteProducer routeProducer; + /** + * PTNetwork producer from base name + */ + @Setter + private PTNetworkProducer networkProducer; + /** + * Company producer from GtfsAgency + */ + @Setter + private CompanyProducer companyProducer; + /** + * VehicleJourney producer from GtfsTrip + */ + @Setter + private VehicleJourneyProducer vehicleJourneyProducer; + /** + * VehicleJourneyAtStop producer from GtfsStopTime + */ + @Setter + private VehicleJourneyAtStopProducer vehicleJourneyAtStopProducer; + /** + * StopArea (BoardingPosition) producer from GtfsStop + */ + @Setter + private StopAreaProducer stopAreaProducer; + /** + * Timetable producer from GtfsCalendar and CtfsCalendarDate + */ + @Setter + private TimetableProducer timetableProducer; + + /** + * Connection producer from GtfsTransfer + */ + @Setter private ConnectionLinkProducer connectionLinkProducer ; + + /** + * CommercialStopPoint generator + */ + @Setter + private CommercialStopGenerator commercialStopGenerator; + /** + * ConnectionLink generator + */ + @Setter + private ConnectionLinkGenerator connectionLinkGenerator; + + /** + * convert Gfts model to Chouette model + * + * @param prefix + * objectId prefix + * @param data + * Gtfs data + * @param maxDistanceForCommercialStop + * maximum distance in meter to merge same named BoardingPosition + * in one CommercialStop + * @param ignoreLastWord + * ignore last word for BoardingPosition name comparison + * @param ignoreEndCharacters + * ignore last characters for BoardingPosition name comparison + * @param maxDistanceForConnectionLink + * maximum distance in meter to connect CommercialStops with a + * ConnectionLink + * @return a Chouette internal model nearly connected + */ + public ModelAssembler convert(boolean optimizeMemory, String prefix, String incrementalPrefix, GtfsData data, double maxDistanceForCommercialStop, + boolean ignoreLastWord, int ignoreEndCharacters, double maxDistanceForConnectionLink, boolean mergeRouteByShortName) + { + DbVehicleJourneyFactory vjFactory = new DbVehicleJourneyFactory(prefix,optimizeMemory); + vehicleJourneyProducer.setFactory(vjFactory); + ModelAssembler assembler = new ModelAssembler(); + ReportItem report = null; + AbstractModelProducer.setPrefix(prefix); + AbstractModelProducer.setIncrementalPrefix(incrementalPrefix); + + // PTnetwork + PTNetwork network = networkProducer.produce(data.getNetwork(), report); + assembler.setPtNetwork(network); + + // Companies + List companies = new ArrayList(); + for (GtfsAgency gtfsAgency : data.getAgencies().getAll()) + // for (Iterator iterator = data.getAgencies().iterator(); iterator.hasNext();) + { + Company company = companyProducer.produce(gtfsAgency, report); + companies.add(company); + // iterator.remove(); + } + data.getAgencies().clear(); + assembler.setCompanies(companies); + + // lines, routes + List lines = new ArrayList(); + List routes = new ArrayList(); + Map mapLineByRouteName = new HashMap(); + Map mapRouteByRouteId = new HashMap(); + logger.info("process routes :" + data.getRoutes().size()); + Map mapRouteExtensionByRouteId = new HashMap(); + + for (GtfsRoute gtfsRoute : data.getRoutes().getAll()) + // for (Iterator iterator = data.getRoutes().iterator(); iterator.hasNext();) + { + // GtfsRoute gtfsRoute = iterator.next(); + // must produce 2 routes : one for each direction; + // at end of processing, empty route will be destroyed + String routeName = mergeRouteByShortName?gtfsRoute.getRouteShortName():gtfsRoute.getRouteId(); + Line line = mapLineByRouteName.get(routeName); + if (line == null) + { + line = lineProducer.produce(gtfsRoute, report); + mapLineByRouteName.put(routeName, line); + lines.add(line); + } + Route route0 = routeProducer.produce(gtfsRoute, report); + Route route1 = new Route(); + route1.setName(route0.getName()); + route1.setPublishedName(route0.getPublishedName()); + route1.setComment(route0.getComment()); + route1.setObjectId(route0.getObjectId()+"_1"); + route0.setObjectId(route0.getObjectId()+"_0"); + route0.setLine(line); + route1.setWayBackRouteId(route0.getObjectId()); + route0.setWayBackRouteId(route1.getObjectId()); + mapRouteByRouteId.put(gtfsRoute.getRouteId()+"_0", route0); + line.addRoute(route0); + routes.add(route0); + mapRouteExtensionByRouteId.put(route0.getObjectId(), Integer.valueOf(1)); + route1.setLine(line); + mapRouteByRouteId.put(gtfsRoute.getRouteId()+"_1", route1); + line.addRoute(route1); + routes.add(route1); + mapRouteExtensionByRouteId.put(route1.getObjectId(), Integer.valueOf(1)); + // iterator.remove(); + } + // System.gc(); + logger.debug("free memory = "+Runtime.getRuntime().freeMemory()); + logger.debug("max memory = "+Runtime.getRuntime().maxMemory()); + logger.debug("total memory = "+Runtime.getRuntime().totalMemory()); + assembler.setLines(lines); + assembler.setRoutes(routes); + + // stopareas + List areas = new ArrayList(); + Map mapStopAreasByStopId = new HashMap(); + logger.info("process stopArea :" + data.getStops().size()); + for (GtfsStop gtfsStop : data.getStops().getAll()) + // for (Iterator iterator = data.getStops().iterator(); iterator.hasNext();) + { + // GtfsStop gtfsStop = iterator.next(); + // iterator.remove(); + StopArea area = stopAreaProducer.produce(gtfsStop, report); + areas.add(area); + mapStopAreasByStopId.put(gtfsStop.getStopId(), area); + } + data.getStops().clear(); + // System.gc(); + logger.debug("free memory = "+Runtime.getRuntime().freeMemory()); + logger.debug("max memory = "+Runtime.getRuntime().maxMemory()); + logger.debug("total memory = "+Runtime.getRuntime().totalMemory()); + List commercials = commercialStopGenerator.createCommercialStopPoints(areas, + maxDistanceForCommercialStop, ignoreLastWord, ignoreEndCharacters); + areas.addAll(commercials); + assembler.setStopAreas(areas); + + // Timetables + List timetables = new ArrayList(); + Map mapTimetableByServiceId = new HashMap(); + + logger.info("process timetables :" + data.getCalendars().size()); + for (GtfsCalendar gtfsCalendar : data.getCalendars().getAll()) + // for (Iterator iterator = data.getCalendars().iterator(); iterator.hasNext();) + { + // GtfsCalendar gtfsCalendar = iterator.next(); + // iterator.remove(); + + List dates = data.getCalendarDates().getAllFromParent(gtfsCalendar.getServiceId()); + for (GtfsCalendarDate date : dates) + { + gtfsCalendar.addCalendarDate(date); + } + + Timetable timetable = timetableProducer.produce(gtfsCalendar, report); + + timetables.add(timetable); + mapTimetableByServiceId.put(gtfsCalendar.getServiceId(), timetable); + } + + logger.debug("timetables mapped : "+mapTimetableByServiceId.size()); + // System.gc(); + logger.debug("free memory = "+Runtime.getRuntime().freeMemory()); + logger.debug("max memory = "+Runtime.getRuntime().maxMemory()); + logger.debug("total memory = "+Runtime.getRuntime().totalMemory()); + assembler.setTimetables(timetables); + + // vehicleJourneys , vehicleJourneyAtStops, JourneyPatterns and StopPoints + // build in to steps : + // first dispatch stopTimes to trips + // next match stoptimes sequence of each trip to a journey pattern; + // and identify stops to be affected to routes + + // Map> mapStopTimesByTrip = new HashMap>(); + // logger.info("process stopTimes :" + data.getStopTimes().size()); + // + // { + // List stopTimesOfATrip = null; + // String previousTrip = null; + // int count = 0; + // for (GtfsStopTime gtfsStopTime: data.getStopTimes()) + // { + // if (!gtfsStopTime.getTripId().equals(previousTrip)) + // { + // stopTimesOfATrip = mapStopTimesByTrip.get(gtfsStopTime.getTripId()); + // previousTrip = gtfsStopTime.getTripId(); + // count++; + // if (count % 1000 == 0) logger.debug("stops in trips count = "+count); + // + // } + // if (stopTimesOfATrip == null) + // { + // stopTimesOfATrip = new ArrayList(); + // mapStopTimesByTrip.put(gtfsStopTime.getTripId(), stopTimesOfATrip); + // } + // + // stopTimesOfATrip.add(gtfsStopTime); + // } + // } + // data.getStopTimes().clear(); + + List journeyPatterns = new ArrayList(); + List stopPoints = new ArrayList(); + List vehicleJourneys = new ArrayList(); + Map mapVehicleJourneyByTripId = new HashMap(); + Map mapJourneyPatternByStopSequence = new HashMap(); + Map mapStopPointbyJourneyPatternRank = new HashMap(); + + logger.info("process vehicleJourneys :" + data.getTrips().size()); + int count = 0; + for (GtfsTrip gtfsTrip : data.getTrips().getAll()) + //for (Iterator iterator = data.getTrips().iterator(); iterator.hasNext();) + { + // GtfsTrip gtfsTrip = iterator.next(); + // iterator.remove(); + count++; + if (count % 1000 == 0) + { + logger.debug("process "+count+" vehicleJourneys ..."); + logger.debug("free memory = "+Runtime.getRuntime().freeMemory()); + logger.debug("max memory = "+Runtime.getRuntime().maxMemory()); + logger.debug("total memory = "+Runtime.getRuntime().totalMemory()); + } + + VehicleJourney vehicleJourney = vehicleJourneyProducer.produce(gtfsTrip, report); + Timetable timetable = mapTimetableByServiceId.get(gtfsTrip.getServiceId()); + if (timetable == null) + { + logger.warn("service "+gtfsTrip.getServiceId()+" not found for trip "+gtfsTrip.getTripId()); + } + else + { + vehicleJourney.addTimetable(timetable); + timetable.addVehicleJourney(vehicleJourney); + } + vehicleJourneys.add(vehicleJourney); + String routeId = gtfsTrip.getRouteId()+"_"+gtfsTrip.getDirectionId(); + Route route = mapRouteByRouteId.get(routeId); + mapVehicleJourneyByTripId.put(gtfsTrip.getTripId(), vehicleJourney); + // stopSequence + // List stopTimesOfATrip = mapStopTimesByTrip.get(gtfsTrip.getTripId()); + // mapStopTimesByTrip.remove(gtfsTrip.getTripId()); + List stopTimesOfATrip = data.getStopTimes().getAllFromParent(gtfsTrip.getTripId()); + Collections.sort(stopTimesOfATrip); + String journeyKey = routeId; + for (GtfsStopTime gtfsStopTime : stopTimesOfATrip) + { + journeyKey += "," + gtfsStopTime.getStopId(); + } + JourneyPattern journeyPattern = mapJourneyPatternByStopSequence.get(journeyKey); + if (journeyPattern == null) + { + // logger.debug("creating new journeyPattern"); + journeyPattern = new JourneyPattern(); + if (route.getJourneyPatterns() != null && !route.getJourneyPatterns().isEmpty()) + { + // wayback relations will be lost + route = cloneRoute(route, mapRouteExtensionByRouteId); + routes.add(route); + // logger.debug("cloning route " + route.getObjectId()); + } + journeyPattern.setRoute(route); + route.addJourneyPattern(journeyPattern); + journeyPattern.setObjectId(route.getObjectId().replace(Route.ROUTE_KEY, JourneyPattern.JOURNEYPATTERN_KEY) + + "a" + route.getJourneyPatterns().size()); + // compare stops + // logger.debug("affect journeypattern " + journeyPattern.getObjectId() + " to route " + route.getObjectId()); + List jpStopPoints = buildStopPoint(route.getObjectId(), stopTimesOfATrip, mapStopAreasByStopId); + route.setStopPoints(jpStopPoints); + stopPoints.addAll(jpStopPoints); + for (int i = 0; i < jpStopPoints.size(); i++) + { + mapStopPointbyJourneyPatternRank.put(journeyKey + "a" + (i + 1), jpStopPoints.get(i)); + } + journeyPattern.setStopPoints(jpStopPoints); + // map journey pattern + mapJourneyPatternByStopSequence.put(journeyKey, journeyPattern); + journeyPatterns.add(journeyPattern); + + } + route = journeyPattern.getRoute(); + vehicleJourney.setRoute(route); + vehicleJourney.setRouteId(route.getObjectId()); + route.setWayBack(gtfsTrip.getDirectionId() == 0 ? "A" : "R"); + vehicleJourney.setJourneyPattern(journeyPattern); + vehicleJourney.setJourneyPatternId(journeyPattern.getObjectId()); + journeyPattern.addVehicleJourney(vehicleJourney); + // vehicleJourneyAtStop + int stRank = 1; + for (GtfsStopTime gtfsStopTime : stopTimesOfATrip) + { + VehicleJourneyAtStop vjas = vehicleJourneyAtStopProducer.produce(gtfsStopTime, report); + vjas.setVehicleJourney(vehicleJourney); + vehicleJourney.addVehicleJourneyAtStop(vjas); + String stopKey = journeyKey + "a" + stRank; + vjas.setOrder(stRank); + StopPoint spor = mapStopPointbyJourneyPatternRank.get(stopKey); + if (spor == null) + { + logger.error("StopPoint " + stopKey + " not found"); + } + vjas.setStopPoint(spor); + stRank++; + + } + stopTimesOfATrip.clear(); + // apply frequencies + for (GtfsFrequency frequency : data.getFrequencies().getAllFromParent(gtfsTrip.getTripId())) + { + baseVehicleJourneyToTime(vehicleJourney, frequency.getStartTime().getTime().getTime()); + try + { + if (!frequency.getStartTime().isTomorrow() && frequency.getEndTime().isTomorrow()) + { + + copyVehicleJourney(vjFactory,vehicleJourney, frequency.getEndTime().getTime().getTime() + 24 * 3600 * 1000, + frequency.getHeadwaySecs() * 1000); + } + else + { + copyVehicleJourney(vjFactory,vehicleJourney, frequency.getEndTime().getTime().getTime(), frequency.getHeadwaySecs() * 1000); + } + } + catch (Exception e) + { + logger.error("cannot apply frequency ", e); + } + } + + vjFactory.flush(vehicleJourney); + // System.gc(); + } + logger.debug("process "+count+" vehicleJourneys ..."); + logger.debug("free memory = "+Runtime.getRuntime().freeMemory()); + logger.debug("max memory = "+Runtime.getRuntime().maxMemory()); + logger.debug("total memory = "+Runtime.getRuntime().totalMemory()); + + // free some unused maps + // mapStopTimesByTrip.clear(); + data.getTrips().clear(); + data.getStopTimes().clear(); + vjFactory.flush(); + // System.gc(); + logger.debug("free memory = "+Runtime.getRuntime().freeMemory()); + logger.debug("max memory = "+Runtime.getRuntime().maxMemory()); + logger.debug("total memory = "+Runtime.getRuntime().totalMemory()); + // fix spor objectids and clean empty routes + + for (Iterator iterator = routes.iterator(); iterator.hasNext();) + { + Route route = iterator.next(); + if (route.getStopPoints() == null || route.getStopPoints().isEmpty()) + { + // dettach route + route.getLine().removeRoute(route); + if (route.getWayBackRouteId() != null) + { + Route wayback = mapRouteByRouteId.get(route.getWayBackRouteId().split(":")[2]); + if (wayback == null) + { + logger.error("route to remove "+route.getObjectId()+" : opposite route "+route.getWayBackRouteId()+" not found"); + } + else + { + wayback.setWayBackRouteId(null); + } + } + iterator.remove(); + } + else + { + int rank = 0; + for (StopPoint spor : route.getStopPoints()) + { + spor.setPosition(rank++); + spor.setRoute(route); + } + // force rebuild ptlinks + route.rebuildPTLinks(); + } + } + + // clone vehicleJourneys by frequency + // for (GtfsFrequency frequency : data.getFrequencies().getAll()) + // { + // DbVehicleJourney vj = mapVehicleJourneyByTripId.get(frequency.getTripId()); + // if (vj != null) + // { + // baseVehicleJourneyToTime(vj, frequency.getStartTime().getTime().getTime()); + // try + // { + // if (!frequency.getStartTime().isTomorrow() && frequency.getEndTime().isTomorrow()) + // { + // + // copyVehicleJourney(vj, frequency.getEndTime().getTime().getTime() + 24 * 3600 * 1000, + // frequency.getHeadwaySecs() * 1000); + // } + // else + // { + // copyVehicleJourney(vj, frequency.getEndTime().getTime().getTime(), frequency.getHeadwaySecs() * 1000); + // } + // } + // catch (Exception e) + // { + // logger.error("cannot apply frequency ", e); + // } + // } + // } + + // merge identical vehicleJourneys with different timetables + // vehicleJourneys.clear(); + // for (JourneyPattern jp : journeyPatterns) + // { + // List vjs = new ArrayList(jp.getVehicleJourneys()); + // for (int i = 0; i < vjs.size(); i++) + // { + // VehicleJourney vj1 = vjs.get(i); + // if (vj1.getObjectId() == null) + // continue; + // for (int j = i + 1; j < vjs.size(); j++) + // { + // VehicleJourney vj2 = vjs.get(j); + // if (vj2.getObjectId() == null) + // continue; + // if (compareTimes(vj1, vj2)) + // { + // // merge + // String id = vj2.getObjectId().split(":")[2]; + // vj1.setObjectId(vj1.getObjectId() + "_" + id); + // for (Timetable tm : vj2.getTimetables()) + // { + // tm.removeVehicleJourney(vj2); + // tm.addVehicleJourney(vj1); + // vj1.addTimetable(tm); + // } + // jp.removeVehicleJourney(vj2); + // vj2.setObjectId(null); // to ignore in further iterations + // } + // } + // vehicleJourneys.add(vj1); + // } + // } + + assembler.setVehicleJourneys(vehicleJourneys); + assembler.setStopPoints(stopPoints); + assembler.setJourneyPatterns(journeyPatterns); + + // ConnectionLinks + List links = new ArrayList(); + List excludedLinks = new ArrayList(); + + for (GtfsTransfer transfer : data.getTransfers().getAll()) + { + ConnectionLink link = connectionLinkProducer.produce(transfer, report); + link.setStartOfLink(mapStopAreasByStopId.get(link.getStartOfLinkId())); + link.setEndOfLink(mapStopAreasByStopId.get(link.getEndOfLinkId())); + if (link.getStartOfLink() == null || link.getEndOfLink() == null) + { + logger.error("line "+transfer.getFileLineNumber()+" invalid transfer : form or to stop unknown"); + } + link.setStartOfLinkId(link.getStartOfLink().getObjectId()); + link.setEndOfLinkId(link.getEndOfLink().getObjectId()); + + if ("FORBIDDEN".equals(link.getName())) + { + excludedLinks.add(link); + } + else + { + link.setName("from "+link.getStartOfLink().getName()+" to "+link.getEndOfLink().getName()); + links.add(link); + } + } + + if (maxDistanceForConnectionLink > 0.) + { + links.addAll(connectionLinkGenerator.createConnectionLinks(commercials, + maxDistanceForConnectionLink,links,excludedLinks)); + assembler.setConnectionLinks(links); + } + + return assembler; + } + + /** + * compare VehicleJourneys on vehicleJourneyAtStops departure and arrival + * times + * + * @param vj1 + * @param vj2 + * @return + */ + private boolean compareTimes2(VehicleJourney vj1, VehicleJourney vj2) + { + List vjass1 = vj1.getVehicleJourneyAtStops(); + List vjass2 = vj2.getVehicleJourneyAtStops(); + + for (int i = 0; i < vjass1.size(); i++) + { + if (vjass1.get(i).getArrivalTime() != vjass2.get(i).getArrivalTime()) + return false; + if (vjass1.get(i).getDepartureTime() != vjass2.get(i).getDepartureTime()) + return false; + } + return true; + } + + /** + * create a copy of a route + * + * @param route + * route to copy + * @param mapRouteExtensionByRouteId + * next rank for objectId build + * @return new route builded by copy + */ + private Route cloneRoute(Route route, Map mapRouteExtensionByRouteId) + { + Route clone = new Route(); + clone.setLine(route.getLine()); + route.getLine().addRoute(clone); + Integer rank = mapRouteExtensionByRouteId.get(route.getObjectId()); + clone.setObjectId(route.getObjectId() + "_" + rank); + mapRouteExtensionByRouteId.put(route.getObjectId(), rank + 1); + clone.setName(route.getName()); + clone.setPublishedName(route.getPublishedName()); + clone.setComment(route.getComment()); + + return clone; + } + + /** + * build stopPoints for Route + * + * @param routeId + * route objectId + * @param stopTimesOfATrip + * first trip's ordered GTFS StopTimes + * @param mapStopAreasByStopId + * stopAreas to attach created StopPoints (parent relationship) + * @return + */ + private List buildStopPoint(String routeId, List stopTimesOfATrip, + Map mapStopAreasByStopId) + { + List stopPoints = new ArrayList(); + Set stopPointKeys = new HashSet(); + + for (GtfsStopTime gtfsStopTime : stopTimesOfATrip) + { + String stopKey = routeId.replace(Route.ROUTE_KEY, StopPoint.STOPPOINT_KEY) + "a" + gtfsStopTime.getStopId(); + if (stopPointKeys.contains(stopKey)) + stopKey = stopKey + "_1"; + stopPointKeys.add(stopKey); + StopPoint spor = new StopPoint(); + spor.setObjectId(stopKey); + StopArea area = mapStopAreasByStopId.get(gtfsStopTime.getStopId()); + area.addContainedStopPoint(spor); + spor.setContainedInStopArea(area); + spor.setName(area.getName()); + spor.setLatitude(area.getAreaCentroid().getLatitude()); + spor.setLongitude(area.getAreaCentroid().getLongitude()); + spor.setLongLatType(area.getAreaCentroid().getLongLatType()); + stopPoints.add(spor); + + } + return stopPoints; + + } + + /** + * shift vehicleJourney times to start vehicleJourney at a specific time + * + * @param vj + * vehicleJourney to shift + * @param t + * start time (first StopPoint's departureTime) + */ + private void baseVehicleJourneyToTime(VehicleJourney vj, long t) + { + VehicleJourneyAtStop first = vj.getVehicleJourneyAtStops().get(0); + long depOffset = t - first.getDepartureTime().getTime(); + long arrOffset = t - first.getArrivalTime().getTime(); + + for (VehicleJourneyAtStop vjas : vj.getVehicleJourneyAtStops()) + { + vjas.setArrivalTime(shiftTime(vjas.getArrivalTime(), arrOffset)); + vjas.setDepartureTime(shiftTime(vjas.getDepartureTime(), depOffset)); + } + } + + /** + * shift a time on and offset + * + * @param t + * time to shift + * @param offset + * offset (seconds) + * @return time shifted (new instance) + */ + private Time shiftTime(Time t, long offset) + { + return new Time((t.getTime() + offset) % (24 * 3600 * 1000)); + } + + /** + * shift several times a vehicleJourney to match frequency on scheduled + * vehicleJourneys + *

+ * vehicleJourneys are added to journeyPattern + * + * @param vj + * vehicleJourney to shift + * @param end + * last StartTime in milliseconds + * @param headway + * gap between each new vehicleJourneys + * @throws IllegalAccessException + * @throws InstantiationException + * @throws InvocationTargetException + * @throws NoSuchMethodException + */ + private void copyVehicleJourney(DbVehicleJourneyFactory factory, VehicleJourney vj, long end, long headway) throws IllegalAccessException, + InstantiationException, InvocationTargetException, NoSuchMethodException + { + VehicleJourneyAtStop first = vj.getVehicleJourneyAtStops().get(0); + long start = first.getDepartureTime().getTime(); + long stop = end - start; + int iter = 1; + + long offset = headway; + while (offset <= stop) + { + VehicleJourney nvj = factory.getNewVehicleJourney(); + nvj.setObjectId(vj.getObjectId() + "a" + iter); + iter++; + for (Timetable timetable : nvj.getTimetables()) + { + timetable.addVehicleJourney(nvj); + } + List vjass = vj.getVehicleJourneyAtStops(); + for (VehicleJourneyAtStop vjas : vjass) + { + VehicleJourneyAtStop nvjas = (VehicleJourneyAtStop) BeanUtils.cloneBean(vjas); + nvjas.setVehicleJourney(nvj); + nvjas.setArrivalTime(shiftTime(nvjas.getArrivalTime(), offset)); + nvjas.setDepartureTime(shiftTime(nvjas.getDepartureTime(), offset)); + nvj.addVehicleJourneyAtStop(nvjas); + } + nvj.setRoute(vj.getRoute()); + nvj.setRouteId(vj.getRouteId()); + nvj.setJourneyPattern(vj.getJourneyPattern()); + nvj.setJourneyPatternId(vj.getJourneyPatternId()); + nvj.getJourneyPattern().addVehicleJourney(nvj); + for (Timetable tm : vj.getTimetables()) + { + nvj.addTimetable(tm); + tm.addVehicleJourney(nvj); + } + factory.flush(nvj); + offset += headway; + } + return; + } + +} diff --git a/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/producer/AbstractModelProducer.java b/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/producer/AbstractModelProducer.java index f8bc91f4c..fafcfd967 100644 --- a/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/producer/AbstractModelProducer.java +++ b/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/producer/AbstractModelProducer.java @@ -1,53 +1,53 @@ -package fr.certu.chouette.exchange.gtfs.importer.producer; - -import org.apache.log4j.Logger; - -import fr.certu.chouette.exchange.gtfs.model.GtfsBean; -import fr.certu.chouette.model.neptune.NeptuneObject; - -public abstract class AbstractModelProducer extends AbstractProducer implements IModelProducer -{ - - private static String prefix; - private static String incremental = ""; - private static int nullIdCount = 0; - public String composeObjectId(String type, String id, Logger logger) - { - if (id == null) - { - logger.error("id null for "+type); - id="NULL_"+nullIdCount; - nullIdCount++; - } - return prefix+":"+type+":"+id.trim().replaceAll(" ", "_").replaceAll("\\(", "_").replaceAll("\\)", "_").replaceAll("/", "_"); - } - - public String composeIncrementalObjectId(String type, String id, Logger logger) - { - if (id == null) - { - logger.error("id null for "+type); - id="NULL_"+nullIdCount; - nullIdCount++; - } - return prefix+":"+type+":"+incremental+id.trim().replaceAll(" ", "_").replaceAll("\\(", "_").replaceAll("\\)", "_").replaceAll("/", "_"); - } - - public static void setIncrementalPrefix(String value) - { - incremental = value; - } - public static String getIncrementalPrefix() - { - return incremental ; - } - public static void setPrefix(String value) - { - prefix = value; - } - public static String getPrefix() - { - return prefix ; - } - -} +package fr.certu.chouette.exchange.gtfs.importer.producer; + +import org.apache.log4j.Logger; + +import fr.certu.chouette.exchange.gtfs.model.GtfsBean; +import fr.certu.chouette.model.neptune.NeptuneObject; + +public abstract class AbstractModelProducer extends AbstractProducer implements IModelProducer +{ + + private static String prefix; + private static String incremental = ""; + private static int nullIdCount = 0; + public String composeObjectId(String type, String id, Logger logger) + { + if (id == null) + { + logger.error("id null for "+type); + id="NULL_"+nullIdCount; + nullIdCount++; + } + return prefix+":"+type+":"+id.trim().replaceAll(" ", "_").replaceAll("\\(", "_").replaceAll("\\)", "_").replaceAll("/", "_"); + } + + public String composeIncrementalObjectId(String type, String id, Logger logger) + { + if (id == null) + { + logger.error("id null for "+type); + id="NULL_"+nullIdCount; + nullIdCount++; + } + return prefix+":"+type+":"+incremental+id.trim().replaceAll(" ", "_").replaceAll("\\(", "_").replaceAll("\\)", "_").replaceAll("/", "_"); + } + + public static void setIncrementalPrefix(String value) + { + incremental = value; + } + public static String getIncrementalPrefix() + { + return incremental ; + } + public static void setPrefix(String value) + { + prefix = value; + } + public static String getPrefix() + { + return prefix ; + } + +} diff --git a/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/producer/AbstractProducer.java b/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/producer/AbstractProducer.java index 1e3563d76..811b0def2 100644 --- a/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/producer/AbstractProducer.java +++ b/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/producer/AbstractProducer.java @@ -1,38 +1,38 @@ -package fr.certu.chouette.exchange.gtfs.importer.producer; - -import java.sql.Time; - -import fr.certu.chouette.exchange.gtfs.model.GtfsTime; - - -public abstract class AbstractProducer -{ - - /** - * @param source - * @return - */ - protected String getNonEmptyTrimedString(String source) - { - if (source == null) return null; - String target = source.trim(); - return (target.length() ==0? null: target); - } - - - - /** - * @param gtfsTime - * @return - */ - protected Time getTime(GtfsTime gtfsTime) - { - if(gtfsTime == null) return null; - - Time time = gtfsTime.getTime(); - return time; - } - - - -} +package fr.certu.chouette.exchange.gtfs.importer.producer; + +import java.sql.Time; + +import fr.certu.chouette.exchange.gtfs.model.GtfsTime; + + +public abstract class AbstractProducer +{ + + /** + * @param source + * @return + */ + protected String getNonEmptyTrimedString(String source) + { + if (source == null) return null; + String target = source.trim(); + return (target.length() ==0? null: target); + } + + + + /** + * @param gtfsTime + * @return + */ + protected Time getTime(GtfsTime gtfsTime) + { + if(gtfsTime == null) return null; + + Time time = gtfsTime.getTime(); + return time; + } + + + +} diff --git a/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/producer/LineProducer.java b/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/producer/LineProducer.java index b0ef6af44..600967163 100644 --- a/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/producer/LineProducer.java +++ b/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/producer/LineProducer.java @@ -1,58 +1,58 @@ -package fr.certu.chouette.exchange.gtfs.importer.producer; - -import org.apache.log4j.Logger; - -import fr.certu.chouette.exchange.gtfs.model.GtfsRoute; -import fr.certu.chouette.model.neptune.Company; -import fr.certu.chouette.model.neptune.Line; -import fr.certu.chouette.model.neptune.type.TransportModeNameEnum; -import fr.certu.chouette.plugin.report.ReportItem; - -public class LineProducer extends AbstractModelProducer -{ - private static Logger logger = Logger.getLogger(LineProducer.class); - - public Line produce(GtfsRoute gtfsLine,ReportItem report) - { - Line line = new Line(); - - line.setObjectId(composeObjectId( Line.LINE_KEY, gtfsLine.getRouteId() ,logger)); - - // Name optional - line.setName(getNonEmptyTrimedString(gtfsLine.getRouteShortName())); - if (line.getName() == null) - line.setName(getNonEmptyTrimedString(gtfsLine.getRouteLongName())); - - // Number optional - line.setNumber(getNonEmptyTrimedString(gtfsLine.getRouteShortName())); - - // PublishedName optional - line.setPublishedName(getNonEmptyTrimedString(gtfsLine.getRouteLongName())); - - // TransportModeName optional - switch (gtfsLine.getRouteType()) - { - case 0 : line.setTransportModeName(TransportModeNameEnum.BUS); break; - case 1 : line.setTransportModeName(TransportModeNameEnum.METRO); break; - case 2 : line.setTransportModeName(TransportModeNameEnum.LONGDISTANCETRAIN); break; - case 3 : line.setTransportModeName(TransportModeNameEnum.COACH); break; - case 4 : line.setTransportModeName(TransportModeNameEnum.FERRY); break; - case 5 : line.setTransportModeName(TransportModeNameEnum.TRAMWAY); break; - default : line.setTransportModeName(TransportModeNameEnum.OTHER); break; - - } - - // Registration optional - line.setRegistrationNumber(gtfsLine.getRouteShortName()); - - // Comment optional : refers to company - line.setComment(getNonEmptyTrimedString(composeObjectId( Company.COMPANY_KEY,gtfsLine.getAgencyId(),logger))); - - if (line.getComment() != null && line.getComment().length() > 255) - line.setComment(line.getComment().substring(0,255)); - return line; - } - - - -} +package fr.certu.chouette.exchange.gtfs.importer.producer; + +import org.apache.log4j.Logger; + +import fr.certu.chouette.exchange.gtfs.model.GtfsRoute; +import fr.certu.chouette.model.neptune.Company; +import fr.certu.chouette.model.neptune.Line; +import fr.certu.chouette.model.neptune.type.TransportModeNameEnum; +import fr.certu.chouette.plugin.report.ReportItem; + +public class LineProducer extends AbstractModelProducer +{ + private static Logger logger = Logger.getLogger(LineProducer.class); + + public Line produce(GtfsRoute gtfsLine,ReportItem report) + { + Line line = new Line(); + + line.setObjectId(composeObjectId( Line.LINE_KEY, gtfsLine.getRouteId() ,logger)); + + // Name optional + line.setName(getNonEmptyTrimedString(gtfsLine.getRouteShortName())); + if (line.getName() == null) + line.setName(getNonEmptyTrimedString(gtfsLine.getRouteLongName())); + + // Number optional + line.setNumber(getNonEmptyTrimedString(gtfsLine.getRouteShortName())); + + // PublishedName optional + line.setPublishedName(getNonEmptyTrimedString(gtfsLine.getRouteLongName())); + + // TransportModeName optional + switch (gtfsLine.getRouteType()) + { + case 0 : line.setTransportModeName(TransportModeNameEnum.BUS); break; + case 1 : line.setTransportModeName(TransportModeNameEnum.METRO); break; + case 2 : line.setTransportModeName(TransportModeNameEnum.LONGDISTANCETRAIN); break; + case 3 : line.setTransportModeName(TransportModeNameEnum.COACH); break; + case 4 : line.setTransportModeName(TransportModeNameEnum.FERRY); break; + case 5 : line.setTransportModeName(TransportModeNameEnum.TRAMWAY); break; + default : line.setTransportModeName(TransportModeNameEnum.OTHER); break; + + } + + // Registration optional + line.setRegistrationNumber(gtfsLine.getRouteShortName()); + + // Comment optional : refers to company + line.setComment(getNonEmptyTrimedString(composeObjectId( Company.COMPANY_KEY,gtfsLine.getAgencyId(),logger))); + + if (line.getComment() != null && line.getComment().length() > 255) + line.setComment(line.getComment().substring(0,255)); + return line; + } + + + +} diff --git a/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/producer/StopAreaProducer.java b/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/producer/StopAreaProducer.java index c1867b891..d37d17ec7 100644 --- a/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/producer/StopAreaProducer.java +++ b/chouette-exchange-gtfs/src/main/java/fr/certu/chouette/exchange/gtfs/importer/producer/StopAreaProducer.java @@ -1,53 +1,53 @@ -package fr.certu.chouette.exchange.gtfs.importer.producer; - -import org.apache.log4j.Logger; - -import fr.certu.chouette.exchange.gtfs.model.GtfsStop; -import fr.certu.chouette.model.neptune.AreaCentroid; -import fr.certu.chouette.model.neptune.StopArea; -import fr.certu.chouette.model.neptune.type.ChouetteAreaEnum; -import fr.certu.chouette.model.neptune.type.LongLatTypeEnum; -import fr.certu.chouette.plugin.report.ReportItem; - -public class StopAreaProducer extends AbstractModelProducer -{ - private static Logger logger = Logger.getLogger(StopAreaProducer.class); - @Override - public StopArea produce(GtfsStop gtfsStop,ReportItem report) - { - StopArea stopArea = new StopArea(); - - // objectId, objectVersion, creatorId, creationTime - stopArea.setObjectId(composeObjectId( StopArea.STOPAREA_KEY, gtfsStop.getStopId(),logger)); - - // AreaCentroid optional - AreaCentroid centroid = new AreaCentroid(); - centroid.setObjectId(composeObjectId( AreaCentroid.AREACENTROID_KEY, gtfsStop.getStopId(),logger)); - centroid.setName(getNonEmptyTrimedString(gtfsStop.getStopName())); - centroid.setLatitude(gtfsStop.getStopLat()); - centroid.setLongitude(gtfsStop.getStopLon()); - centroid.setLongLatType(LongLatTypeEnum.WGS84); - - stopArea.setAreaCentroid(centroid); - centroid.setContainedInStopArea(stopArea); - - // Name optional - stopArea.setName(getNonEmptyTrimedString(gtfsStop.getStopName())); - - // Comment optional - stopArea.setComment(getNonEmptyTrimedString(gtfsStop.getStopDesc())); - if (stopArea.getComment() != null && stopArea.getComment().length() > 255) - stopArea.setComment(stopArea.getComment().substring(0,255)); - - // farecode - stopArea.setFareCode(0); - - stopArea.setAreaType(ChouetteAreaEnum.BOARDINGPOSITION); - - // RegistrationNumber optional - stopArea.setRegistrationNumber(gtfsStop.getStopCode()); - - return stopArea; - } - -} +package fr.certu.chouette.exchange.gtfs.importer.producer; + +import org.apache.log4j.Logger; + +import fr.certu.chouette.exchange.gtfs.model.GtfsStop; +import fr.certu.chouette.model.neptune.AreaCentroid; +import fr.certu.chouette.model.neptune.StopArea; +import fr.certu.chouette.model.neptune.type.ChouetteAreaEnum; +import fr.certu.chouette.model.neptune.type.LongLatTypeEnum; +import fr.certu.chouette.plugin.report.ReportItem; + +public class StopAreaProducer extends AbstractModelProducer +{ + private static Logger logger = Logger.getLogger(StopAreaProducer.class); + @Override + public StopArea produce(GtfsStop gtfsStop,ReportItem report) + { + StopArea stopArea = new StopArea(); + + // objectId, objectVersion, creatorId, creationTime + stopArea.setObjectId(composeObjectId( StopArea.STOPAREA_KEY, gtfsStop.getStopId(),logger)); + + // AreaCentroid optional + AreaCentroid centroid = new AreaCentroid(); + centroid.setObjectId(composeObjectId( AreaCentroid.AREACENTROID_KEY, gtfsStop.getStopId(),logger)); + centroid.setName(getNonEmptyTrimedString(gtfsStop.getStopName())); + centroid.setLatitude(gtfsStop.getStopLat()); + centroid.setLongitude(gtfsStop.getStopLon()); + centroid.setLongLatType(LongLatTypeEnum.WGS84); + + stopArea.setAreaCentroid(centroid); + centroid.setContainedInStopArea(stopArea); + + // Name optional + stopArea.setName(getNonEmptyTrimedString(gtfsStop.getStopName())); + + // Comment optional + stopArea.setComment(getNonEmptyTrimedString(gtfsStop.getStopDesc())); + if (stopArea.getComment() != null && stopArea.getComment().length() > 255) + stopArea.setComment(stopArea.getComment().substring(0,255)); + + // farecode + stopArea.setFareCode(0); + + stopArea.setAreaType(ChouetteAreaEnum.BOARDINGPOSITION); + + // RegistrationNumber optional + stopArea.setRegistrationNumber(gtfsStop.getStopCode()); + + return stopArea; + } + +} diff --git a/chouette-exchange-gtfs/src/main/resources/chouetteContext.xml b/chouette-exchange-gtfs/src/main/resources/chouetteContext.xml index 24c05f30d..3497567d5 100644 --- a/chouette-exchange-gtfs/src/main/resources/chouetteContext.xml +++ b/chouette-exchange-gtfs/src/main/resources/chouetteContext.xml @@ -1,27 +1,27 @@ + default-init-method="init"> - - - - - - - - - - - - + + + + + + + + + + + + - + - + \ No newline at end of file