/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.opentripplanner.routing.core; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * A set of traverse modes -- typically, one non-transit mode (walking, biking, car) and zero or * more transit modes (bus, tram, etc). This class allows efficiently adding or removing modes * from a set. * @author novalis * */ public class TraverseModeSet implements Cloneable, Serializable { private static final long serialVersionUID = -1640048158419762255L; private static final int MODE_BICYCLE = 1; private static final int MODE_WALK = 2; private static final int MODE_CAR = 4; private static final int MODE_BUS = 16; private static final int MODE_TRAM = 32; private static final int MODE_SUBWAY = 64; private static final int MODE_RAIL = 128; private static final int MODE_FERRY = 256; private static final int MODE_CABLE_CAR = 512; private static final int MODE_GONDOLA = 1024; private static final int MODE_FUNICULAR = 2048; private static final int MODE_CUSTOM_MOTOR_VEHICLE = 4096; private static final int MODE_TRAINISH = MODE_TRAM | MODE_RAIL | MODE_SUBWAY | MODE_FUNICULAR | MODE_GONDOLA; private static final int MODE_BUSISH = MODE_CABLE_CAR | MODE_BUS; private static final int MODE_TRANSIT = MODE_TRAINISH | MODE_BUSISH | MODE_FERRY; private static final int MODE_DRIVING = MODE_CAR | MODE_CUSTOM_MOTOR_VEHICLE; private static final int MODE_ALL = MODE_TRANSIT | MODE_DRIVING | MODE_WALK | MODE_BICYCLE; private int modes = 0; public TraverseModeSet(String modelist) { modes = 0; for (String modeStr : modelist.split(",")) { if (modeStr.length() == 0) { continue; } setMode(TraverseMode.valueOf(modeStr), true); } } public TraverseModeSet(TraverseMode... modes) { for (TraverseMode mode : modes) { this.modes |= getMaskForMode(mode); } } /** * Returns a mode set containing all modes. * * @return */ public static TraverseModeSet allModes() { TraverseModeSet modes = new TraverseModeSet(); modes.modes = MODE_ALL; return modes; } private final int getMaskForMode(TraverseMode mode) { switch (mode) { case BICYCLE: return MODE_BICYCLE; case WALK: return MODE_WALK; case CAR: return MODE_CAR; case CUSTOM_MOTOR_VEHICLE: return MODE_CUSTOM_MOTOR_VEHICLE; case BUS: return MODE_BUS; case TRAM: return MODE_TRAM; case CABLE_CAR: return MODE_CABLE_CAR; case GONDOLA: return MODE_GONDOLA; case FERRY: return MODE_FERRY; case FUNICULAR: return MODE_FUNICULAR; case SUBWAY: return MODE_SUBWAY; case RAIL: return MODE_RAIL; case TRAINISH: return MODE_TRAINISH; case BUSISH: return MODE_BUSISH; case TRANSIT: return MODE_TRANSIT; } return 0; } public TraverseModeSet(Collection<TraverseMode> modeList) { this(modeList.toArray(new TraverseMode[0])); } public int getMask() { return modes; } public void setMode(TraverseMode mode, boolean value) { int mask = getMaskForMode(mode); if (value) { modes |= mask; } else { modes &= ~mask; } } public boolean getBicycle() { return (modes & MODE_BICYCLE) != 0; } public boolean getWalk() { return (modes & MODE_WALK) != 0; } public boolean getCar() { return (modes & MODE_CAR) != 0; } public boolean getCustomMotorVehicle() { return (modes & MODE_CUSTOM_MOTOR_VEHICLE) != 0; } public boolean getDriving() { return (modes & MODE_DRIVING) != 0; } public boolean getTram() { return (modes & MODE_TRAM) != 0; } public boolean getTrainish() { return (modes & MODE_TRAINISH) != 0; } public boolean getBusish() { return (modes & MODE_BUSISH) != 0; } public boolean getBus() { return (modes & MODE_BUS) != 0; } public boolean getGondola() { return (modes & MODE_GONDOLA) != 0; } public boolean getFerry() { return (modes & MODE_FERRY) != 0; } public boolean getCableCar() { return (modes & MODE_CABLE_CAR) != 0; } public boolean getFunicular() { return (modes & MODE_FUNICULAR) != 0; } public boolean getRail() { return (modes & MODE_RAIL) != 0; } public boolean getSubway() { return (modes & MODE_SUBWAY) != 0; } public void setBicycle(boolean bicycle) { if (bicycle) { modes |= MODE_BICYCLE; } else { modes &= ~MODE_BICYCLE; } } public void setWalk(boolean walk) { if (walk) { modes |= MODE_WALK; } else { modes &= ~MODE_WALK; } } public void setCar(boolean car) { if (car) { modes |= MODE_CAR; } else { modes &= ~MODE_CAR; } } public void setCustomMotorVehicle(boolean cmv) { if (cmv) { modes |= MODE_CUSTOM_MOTOR_VEHICLE; } else { modes &= ~MODE_CUSTOM_MOTOR_VEHICLE; } } public void setDriving(boolean driving) { if (driving) { modes |= MODE_DRIVING; } else { modes &= ~MODE_DRIVING; } } public void setTram(boolean tram) { if (tram) { modes |= MODE_TRAM; } else { modes &= ~MODE_TRAM; } } public void setTrainish(boolean trainish) { if (trainish) { modes |= MODE_TRAINISH; } else { modes &= ~MODE_TRAINISH; } } public void setBus(boolean bus) { if (bus) { modes |= MODE_BUS; } else { modes &= ~MODE_BUS; } } public void setBusish(boolean busish) { if (busish) { modes |= MODE_BUSISH; } else { modes &= ~MODE_BUSISH; } } public void setFerry(boolean ferry) { if (ferry) { modes |= MODE_FERRY; } else { modes &= ~MODE_FERRY; } } public void setCableCar(boolean cableCar) { if (cableCar) { modes |= MODE_CABLE_CAR; } else { modes &= ~MODE_CABLE_CAR; } } public void setGondola(boolean gondola) { if (gondola) { modes |= MODE_GONDOLA; } else { modes &= ~MODE_GONDOLA; } } public void setFunicular(boolean funicular) { if (funicular) { modes |= MODE_FUNICULAR; } else { modes &= ~MODE_FUNICULAR; } } public void setSubway(boolean subway) { if (subway) { modes |= MODE_SUBWAY; } else { modes &= ~MODE_SUBWAY; } } public void setRail(boolean rail) { if (rail) { modes |= MODE_RAIL; } else { modes &= ~MODE_RAIL; } } /** Returns true if the trip may use some transit mode */ public boolean isTransit() { return (modes & (MODE_TRANSIT)) != 0; } public void setTransit(boolean transit) { if (transit) { modes |= MODE_TRANSIT; } else { modes &= ~MODE_TRANSIT; } } /** Returns a TraverseModeSet containing only the non-transit modes set. */ public TraverseModeSet getNonTransitSet() { TraverseModeSet retval = new TraverseModeSet(); retval.modes = modes; retval.setTransit(false); return retval; } /** Returns true if any the trip may use some train-like (train, subway, tram) mode */ public boolean getTraininsh() { return (modes & (MODE_TRAINISH)) != 0; } public List<TraverseMode> getModes() { ArrayList<TraverseMode> modeList = new ArrayList<TraverseMode>(); for (TraverseMode mode : TraverseMode.values()) { if ((modes & getMaskForMode(mode)) != 0) { modeList.add(mode); } } return modeList; } public boolean isValid() { return modes != 0; } public boolean contains(TraverseMode mode) { return (modes & getMaskForMode(mode)) != 0; } public boolean get(int modeMask) { return (modes & modeMask) != 0; } public String toString() { StringBuilder out = new StringBuilder(); for (TraverseMode mode : TraverseMode.values()) { int mask = getMaskForMode(mode); if (mask != 0 && (modes & mask) == mask) { if (out.length() != 0) { out.append(", "); } out.append(mode); } } return "TraverseMode (" + out + ")"; } public String getAsStr() { String retVal = null; for (TraverseMode m : getModes()) { if (retVal == null) retVal = ""; else retVal += ", "; retVal += m; } return retVal; } @Override public TraverseModeSet clone() { try { return (TraverseModeSet) super.clone(); } catch (CloneNotSupportedException e) { /* this will never happen since our super is the cloneable object */ throw new RuntimeException(e); } } /** * Clear the mode set so that no modes are included. */ public void clear() { modes = 0; } /** * @param restrictedModes A set of restricted modes * @return false If *at least one* of the non-transit mode is not restricted. */ public boolean isRestricted(TraverseModeSet restrictedModes) { // For each non-transit mode, test if it's set and not restricted. // If so, then the traverse mode set is not restricted. if (getWalk() && !restrictedModes.contains(TraverseMode.WALK)) return false; if (getBicycle() && !restrictedModes.contains(TraverseMode.BICYCLE)) return false; if (getCar() && !restrictedModes.contains(TraverseMode.CAR)) return false; if (getCustomMotorVehicle() && !restrictedModes.contains(TraverseMode.CUSTOM_MOTOR_VEHICLE)) return false; return true; } public int hashCode() { return modes; } public boolean equals(Object other) { if (other instanceof TraverseModeSet) { return modes == ((TraverseModeSet)other).modes; } return false; } }