public static void renamePatterns(Collection<Pattern> patterns, Map<String, Stop> stopById) {
        LOG.info("Generating unique names for patterns");

        Map<String, PatternNamingInfo> namingInfoForRoute = new HashMap<>();

        for (Pattern pattern : patterns) {
            if (pattern.associatedTrips.isEmpty() || pattern.orderedStops.isEmpty()) continue;

            // Each pattern within a route has a unique name (within that route, not across the entire feed)

            PatternNamingInfo namingInfo = namingInfoForRoute.get(pattern.route_id);
            if (namingInfo == null) {
                namingInfo = new PatternNamingInfo();
                namingInfoForRoute.put(pattern.route_id, namingInfo);
            }

            // Pattern names are built using stop names rather than stop IDs.
            // Stop names, unlike IDs, are not guaranteed to be unique.
            // Therefore we must track used names carefully to avoid duplicates.

            String fromName = stopById.get(pattern.orderedStops.get(0)).stop_name;
            String toName = stopById.get(pattern.orderedStops.get(pattern.orderedStops.size() - 1)).stop_name;

            namingInfo.fromStops.put(fromName, pattern);
            namingInfo.toStops.put(toName, pattern);

            for (String stopId : pattern.orderedStops) {
                Stop stop = stopById.get(stopId);
                if (fromName.equals(stop.stop_name) || toName.equals(stop.stop_name)) continue;
                namingInfo.vias.put(stop.stop_name, pattern);
            }
            namingInfo.patternsOnRoute.add(pattern);
        }

        // name the patterns on each route
        for (PatternNamingInfo info : namingInfoForRoute.values()) {
            for (Pattern pattern : info.patternsOnRoute) {
                pattern.name = null; // clear this now so we don't get confused later on
                String fromName = stopById.get(pattern.orderedStops.get(0)).stop_name;
                String toName = stopById.get(pattern.orderedStops.get(pattern.orderedStops.size() - 1)).stop_name;

                // check if combination from, to is unique
                Set<Pattern> intersection = new HashSet<>(info.fromStops.get(fromName));
                intersection.retainAll(info.toStops.get(toName));

                if (intersection.size() == 1) {
                    pattern.name = String.format(Locale.US, "from %s to %s", fromName, toName);
                    continue;
                }

                // check for unique via stop
                pattern.orderedStops.stream().map(stopById::get).forEach(stop -> {
                    Set<Pattern> viaIntersection = new HashSet<>(intersection);
                    viaIntersection.retainAll(info.vias.get(stop.stop_name));

                    if (viaIntersection.size() == 1) {
                        pattern.name = String.format(Locale.US, "from %s to %s via %s", fromName, toName, stop.stop_name);
                    }
                });

                if (pattern.name == null) {
                    // no unique via, one pattern is subset of other.
                    if (intersection.size() == 2) {
                        Iterator<Pattern> it = intersection.iterator();
                        Pattern p0 = it.next();
                        Pattern p1 = it.next();
                        if (p0.orderedStops.size() > p1.orderedStops.size()) {
                            p1.name = String.format(Locale.US, "from %s to %s express", fromName, toName);
                            p0.name = String.format(Locale.US, "from %s to %s local", fromName, toName);
                        } else if (p1.orderedStops.size() > p0.orderedStops.size()){
                            p0.name = String.format(Locale.US, "from %s to %s express", fromName, toName);
                            p1.name = String.format(Locale.US, "from %s to %s local", fromName, toName);
                        }
                    }
                }

                if (pattern.name == null) {
                    // give up
                    pattern.name = String.format(Locale.US, "from %s to %s like trip %s", fromName, toName, pattern.associatedTrips.get(0));
                }
            }

            // attach a stop and trip count to each
            for (Pattern pattern : info.patternsOnRoute) {
                pattern.name = String.format(Locale.US, "%s stops %s (%s trips)",
                        pattern.orderedStops.size(), pattern.name, pattern.associatedTrips.size());
            }
        }
    }
public static void renamePatterns(Collection<Pattern> patterns, Map<String, Stop> stopById) {
        LOG.info("Generating unique names for patterns");

        Map<String, PatternNamingInfo> namingInfoForRoute = new HashMap<>();

        for (Pattern pattern : patterns) {
            if (pattern.associatedTrips.isEmpty() || pattern.orderedStops.isEmpty()) continue;

            

            PatternNamingInfo namingInfo = namingInfoForRoute.get(pattern.route_id);
            if (namingInfo == null) {
                namingInfo = new PatternNamingInfo();
                namingInfoForRoute.put(pattern.route_id, namingInfo);
            }

            
            
            

            String fromName = stopById.get(pattern.orderedStops.get(0)).stop_name;
            String toName = stopById.get(pattern.orderedStops.get(pattern.orderedStops.size() - 1)).stop_name;

            namingInfo.fromStops.put(fromName, pattern);
            namingInfo.toStops.put(toName, pattern);

            for (String stopId : pattern.orderedStops) {
                Stop stop = stopById.get(stopId);
                if (fromName.equals(stop.stop_name) || toName.equals(stop.stop_name)) continue;
                namingInfo.vias.put(stop.stop_name, pattern);
            }
            namingInfo.patternsOnRoute.add(pattern);
        }

        
        for (PatternNamingInfo info : namingInfoForRoute.values()) {
            for (Pattern pattern : info.patternsOnRoute) {
                pattern.name = null; 
                String fromName = stopById.get(pattern.orderedStops.get(0)).stop_name;
                String toName = stopById.get(pattern.orderedStops.get(pattern.orderedStops.size() - 1)).stop_name;

                
                Set<Pattern> intersection = new HashSet<>(info.fromStops.get(fromName));
                intersection.retainAll(info.toStops.get(toName));

                if (intersection.size() == 1) {
                    pattern.name = String.format(Locale.US, "from %s to %s", fromName, toName);
                    continue;
                }

                
                pattern.orderedStops.stream().map(stopById::get).forEach(stop -> {
                    Set<Pattern> viaIntersection = new HashSet<>(intersection);
                    viaIntersection.retainAll(info.vias.get(stop.stop_name));

                    if (viaIntersection.size() == 1) {
                        pattern.name = String.format(Locale.US, "from %s to %s via %s", fromName, toName, stop.stop_name);
                    }
                });

                if (pattern.name == null) {
                    
                    if (intersection.size() == 2) {
                        Iterator<Pattern> it = intersection.iterator();
                        Pattern p0 = it.next();
                        Pattern p1 = it.next();
                        if (p0.orderedStops.size() > p1.orderedStops.size()) {
                            p1.name = String.format(Locale.US, "from %s to %s express", fromName, toName);
                            p0.name = String.format(Locale.US, "from %s to %s local", fromName, toName);
                        } else if (p1.orderedStops.size() > p0.orderedStops.size()){
                            p0.name = String.format(Locale.US, "from %s to %s express", fromName, toName);
                            p1.name = String.format(Locale.US, "from %s to %s local", fromName, toName);
                        }
                    }
                }

                if (pattern.name == null) {
                    
                    pattern.name = String.format(Locale.US, "from %s to %s like trip %s", fromName, toName, pattern.associatedTrips.get(0));
                }
            }

            
            for (Pattern pattern : info.patternsOnRoute) {
                pattern.name = String.format(Locale.US, "%s stops %s (%s trips)",
                        pattern.orderedStops.size(), pattern.name, pattern.associatedTrips.size());
            }
        }
    }
public static void renamePatterns ( Collection < Pattern > patterns , Map < String , Stop > stopById ) { LOG . info ( "Generating unique names for patterns" ) ; Map < String , PatternNamingInfo > namingInfoForRoute = new HashMap <> ( ) ; for ( Pattern pattern : patterns ) { if ( pattern . associatedTrips . isEmpty ( ) || pattern . orderedStops . isEmpty ( ) ) continue ; // Each pattern within a route has a unique name (within that route, not across the entire feed) PatternNamingInfo namingInfo = namingInfoForRoute . get ( pattern . route_id ) ; if ( namingInfo == null ) { namingInfo = new PatternNamingInfo ( ) ; namingInfoForRoute . put ( pattern . route_id , namingInfo ) ; } // Pattern names are built using stop names rather than stop IDs. // Stop names, unlike IDs, are not guaranteed to be unique. // Therefore we must track used names carefully to avoid duplicates. String fromName = stopById . get ( pattern . orderedStops . get ( 0 ) ) . stop_name ; String toName = stopById . get ( pattern . orderedStops . get ( pattern . orderedStops . size ( ) - 1 ) ) . stop_name ; namingInfo . fromStops . put ( fromName , pattern ) ; namingInfo . toStops . put ( toName , pattern ) ; for ( String stopId : pattern . orderedStops ) { Stop stop = stopById . get ( stopId ) ; if ( fromName . equals ( stop . stop_name ) || toName . equals ( stop . stop_name ) ) continue ; namingInfo . vias . put ( stop . stop_name , pattern ) ; } namingInfo . patternsOnRoute . add ( pattern ) ; } // name the patterns on each route for ( PatternNamingInfo info : namingInfoForRoute . values ( ) ) { for ( Pattern pattern : info . patternsOnRoute ) { pattern . name = null ; // clear this now so we don't get confused later on String fromName = stopById . get ( pattern . orderedStops . get ( 0 ) ) . stop_name ; String toName = stopById . get ( pattern . orderedStops . get ( pattern . orderedStops . size ( ) - 1 ) ) . stop_name ; // check if combination from, to is unique Set < Pattern > intersection = new HashSet <> ( info . fromStops . get ( fromName ) ) ; intersection . retainAll ( info . toStops . get ( toName ) ) ; if ( intersection . size ( ) == 1 ) { pattern . name = String . format ( Locale . US , "from %s to %s" , fromName , toName ) ; continue ; } // check for unique via stop pattern . orderedStops . stream ( ) . map ( stopById :: get ) . forEach ( stop -> { Set < Pattern > viaIntersection = new HashSet <> ( intersection ) ; viaIntersection . retainAll ( info . vias . get ( stop . stop_name ) ) ; if ( viaIntersection . size ( ) == 1 ) { pattern . name = String . format ( Locale . US , "from %s to %s via %s" , fromName , toName , stop . stop_name ) ; } } ) ; if ( pattern . name == null ) { // no unique via, one pattern is subset of other. if ( intersection . size ( ) == 2 ) { Iterator < Pattern > it = intersection . iterator ( ) ; Pattern p0 = it . next ( ) ; Pattern p1 = it . next ( ) ; if ( p0 . orderedStops . size ( ) > p1 . orderedStops . size ( ) ) { p1 . name = String . format ( Locale . US , "from %s to %s express" , fromName , toName ) ; p0 . name = String . format ( Locale . US , "from %s to %s local" , fromName , toName ) ; } else if ( p1 . orderedStops . size ( ) > p0 . orderedStops . size ( ) ) { p0 . name = String . format ( Locale . US , "from %s to %s express" , fromName , toName ) ; p1 . name = String . format ( Locale . US , "from %s to %s local" , fromName , toName ) ; } } } if ( pattern . name == null ) { // give up pattern . name = String . format ( Locale . US , "from %s to %s like trip %s" , fromName , toName , pattern . associatedTrips . get ( 0 ) ) ; } } // attach a stop and trip count to each for ( Pattern pattern : info . patternsOnRoute ) { pattern . name = String . format ( Locale . US , "%s stops %s (%s trips)" , pattern . orderedStops . size ( ) , pattern . name , pattern . associatedTrips . size ( ) ) ; } } }
Destructively rename the supplied collection of patterns.
This process requires access to all the stops in the feed.
Some validators already cache a map of all the stops. There's probably a cleaner way to do this.
Destructively rename the supplied collection of patterns . This process requires access to all the stops in the feed . Some validators already cache a map of all the stops . There s probably a cleaner way to do this .