public class DirectoryZip {

	
	public static void zip(File directory, File zipfile) throws IOException {
	    URI base = directory.toURI();
	    Deque<File> queue = new LinkedList<File>();
	    queue.push(directory);
	    OutputStream out = new FileOutputStream(zipfile);
	    Closeable res = out;
	    try {
	      ZipOutputStream zout = new ZipOutputStream(out);
	      res = zout;
	      while (!queue.isEmpty()) {
	        directory = queue.pop();
	        for (File kid : directory.listFiles()) {
	          String name = base.relativize(kid.toURI()).getPath();
	          if (kid.isDirectory()) {
	            queue.push(kid);
	            name = name.endsWith("/") ? name : name + "/";
	            zout.putNextEntry(new ZipEntry(name));
	          } else {
	            zout.putNextEntry(new ZipEntry(name));
	            copy(kid, zout);
	            zout.closeEntry();
	          }
	        }
	      }
	    } finally {
	      res.close();
	    }
	  }
	
	
	 private static void copy(InputStream in, OutputStream out) throws IOException {
	    byte[] buffer = new byte[1024];
	    while (true) {
	      int readCount = in.read(buffer);
	      if (readCount < 0) {
	        break;
	      }
	      out.write(buffer, 0, readCount);
	    }
	  }
	
	 private static void copy(File file, OutputStream out) throws IOException {
	    InputStream in = new FileInputStream(file);
	    try {
	      copy(in, out);
	    } finally {
	      in.close();
	    }
	  }

	  private static void copy(InputStream in, File file) throws IOException {
	    OutputStream out = new FileOutputStream(file);
	    try {
	      copy(in, out);
	    } finally {
	      out.close();
	    }
	  }
	
} public class TripPatternSerializer implements JsonSerializer<TripPattern>  {

		@Override
		public JsonElement serialize(TripPattern arg0, Type arg1, JsonSerializationContext arg2) 
		{
	    	JsonObject jsonObject = new JsonObject();
	    	
	    	    	
	    	jsonObject.addProperty("id", arg0.id);
	    	jsonObject.addProperty("headsign", arg0.headsign);
	    
	    	
	    	return jsonObject;
		}
} public class TripPatternShapeSerializer implements JsonSerializer<TripPattern>  {

		@Override
		public JsonElement serialize(TripPattern arg0, Type arg1, JsonSerializationContext arg2) 
		{
	    	JsonObject jsonObject = new JsonObject();
	    	
	    	    	
	    	jsonObject.addProperty("id", arg0.id);
	    	jsonObject.addProperty("name", arg0.name);
	    	jsonObject.addProperty("headsign", arg0.headsign);
	    	
	    	jsonObject.addProperty("color", arg0.route.agency.color);
	    	jsonObject.addProperty("gtfsAgencyId", arg0.route.agency.gtfsAgencyId);
	    	jsonObject.addProperty("routeShortName", arg0.route.routeShortName);
	    	jsonObject.addProperty("routeLongName", arg0.route.routeLongName);
	    	jsonObject.addProperty("routeDescription", arg0.route.routeDesc);
	    	jsonObject.addProperty("routeNotes", arg0.route.routeNotes);
	    	
	    	jsonObject.addProperty("headsign", arg0.headsign);
	    	
	    	JsonObject jsonBoundsObject = new JsonObject();
	    	
	    	jsonBoundsObject.addProperty("lat1", arg0.shape.shape.getEnvelopeInternal().getMaxY());
	    	jsonBoundsObject.addProperty("lon1", arg0.shape.shape.getEnvelopeInternal().getMaxX());

	    	jsonBoundsObject.addProperty("lat2", arg0.shape.shape.getEnvelopeInternal().getMinY());
	    	jsonBoundsObject.addProperty("lon2", arg0.shape.shape.getEnvelopeInternal().getMinX());
	    	
	    	jsonObject.add("bounds", jsonBoundsObject);
	    	

	    	JsonArray jsonArray = new JsonArray();
	    	
	    	List<TripPatternStop> tpStops = TripPatternStop.find("pattern = ? ORDER BY id", arg0).fetch();
	    	
	    	for(TripPatternStop tps : tpStops) {
	    		
	    		JsonObject jsonTpsObject = new JsonObject();
	    		
	    		jsonTpsObject.addProperty("lat", tps.stop.location.getY());
	    		jsonTpsObject.addProperty("lon", tps.stop.location.getX());
	    		jsonTpsObject.addProperty("board", tps.board);
	    		jsonTpsObject.addProperty("alight", tps.alight);
	    		jsonTpsObject.addProperty("travelTime", tps.defaultTravelTime);
	    		
	    		jsonArray.add(jsonTpsObject);
	    	}
	    	
	    	jsonObject.add("stops", jsonArray);
	    	
	    	EncodedPolylineBean polyline = PolylineEncoder.createEncodings(arg0.shape.shape);
	    	
	    	jsonObject.addProperty("shape", polyline.getPoints());
	    	
	    	return jsonObject;
		}
} public class ProcessGisExport extends Job {

	private List<Long> _patternIds;

	private String timestamp;
	
	public ProcessGisExport(List<Long> patternIds, String timestamp)
	{
		this._patternIds = patternIds;
		this.timestamp = timestamp;
	}
	
	public void doJob() throws InterruptedException {
    	
		File outputDirectory = new File(Play.configuration.getProperty("application.exportDataDirectory"), timestamp);
		File outputZipFile = new File(Play.configuration.getProperty("application.exportDataDirectory"), timestamp + ".zip");
		
        try
        {
        	if(!outputDirectory.exists())
        	{
        		outputDirectory.mkdir();
        	}

            if(outputZipFile.exists()) {
                outputZipFile.delete();
            }
        	
        	processStops(outputDirectory, timestamp);
        	processRoute(outputDirectory, timestamp);
    	
        	DirectoryZip.zip(outputDirectory, outputZipFile);
        	FileUtils.deleteDirectory(outputDirectory); 
        }
        catch(Exception e)
        {	
        	Logger.error("Unable to process GIS export: ", e.toString());
        	e.printStackTrace();
        } 
        
	}
	
	private void processStops(File outputDirectory, String exportName) throws Exception {
		
		File outputShapefile = new File(outputDirectory, exportName + "_stops.shp");
		
		ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
		
		Map<String, Serializable> params = new HashMap<String, Serializable>();
		params.put("url", outputShapefile.toURI().toURL());
		params.put("create spatial index", Boolean.TRUE);
		
		ShapefileDataStore dataStore = (ShapefileDataStore)dataStoreFactory.createNewDataStore(params);
		dataStore.forceSchemaCRS(DefaultGeographicCRS.WGS84);

    	SimpleFeatureType STOP_TYPE = DataUtilities.createType(
                "Stop",                 
                "location:Point:srid=4326," + 
                "id:String," +
                "routeId:String," +
                "sequence:Integer," +
                
                "travelTime:Integer," +
                "dwellTime:Integer," +
                
                "arrivalTime:Integer," +
                "departureTime:Integer," +
                
				"passengerAlightings:Integer," +
				"passengerBoardings:Integer"
                    
        );
    	
    	SimpleFeatureCollection collection = FeatureCollections.newCollection();

        SimpleFeatureBuilder featureBuilder = null;
        
    	dataStore.createSchema(STOP_TYPE);
    	featureBuilder = new SimpleFeatureBuilder(STOP_TYPE);

        for(Long patternId : this._patternIds) { 
    	
        	TripPattern tp = TripPattern.findById(patternId);
        	
    		List<TripPatternStop> patternStops = TripPatternStop.find("pattern = ? order by stopSequence", tp).fetch();
    		
    		Integer cumulativeTime = 0;
    		
    		for(TripPatternStop tps : patternStops)
        	{
        		featureBuilder.add(tps.stop.location);
        		
                featureBuilder.add(tps.stop.id.toString());
                featureBuilder.add(tp.id.toString());
                featureBuilder.add(tps.stopSequence);
                
                featureBuilder.add(tps.defaultTravelTime);
                featureBuilder.add(tps.defaultDwellTime);
                
                featureBuilder.add(tps.alight);
                featureBuilder.add(tps.board);
                
                if(tps.defaultTravelTime != null)
                cumulativeTime += tps.defaultTravelTime;
                featureBuilder.add(cumulativeTime);
                
                if(tps.defaultDwellTime != null)
                cumulativeTime += tps.defaultDwellTime;
                featureBuilder.add(cumulativeTime);
                
                SimpleFeature feature = featureBuilder.buildFeature(null);
                collection.add(feature);	
        	}
        }
    
        Transaction transaction = new DefaultTransaction("create");

        String typeName = dataStore.getTypeNames()[0];
        SimpleFeatureSource featureSource = dataStore.getFeatureSource(typeName);

        if (featureSource instanceof SimpleFeatureStore) 
        {
            SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;

            featureStore.setTransaction(transaction);
           
            featureStore.addFeatures(collection);
            transaction.commit();

            transaction.close();
        } 
        else 
        {
        	throw new Exception(typeName + " does not support read/write access");
        }      
	}
	
	private void processRoute(File outputDirectory, String exportName) throws Exception {
		
		File outputShapefile = new File(outputDirectory, exportName + "_route.shp");
		
		ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
		
		Map<String, Serializable> params = new HashMap<String, Serializable>();
		params.put("url", outputShapefile.toURI().toURL());
		params.put("create spatial index", Boolean.TRUE);
		
		ShapefileDataStore dataStore = (ShapefileDataStore)dataStoreFactory.createNewDataStore(params);
		dataStore.forceSchemaCRS(DefaultGeographicCRS.WGS84);

    	SimpleFeatureType ROUTE_TYPE = DataUtilities.createType(
                "Route",                   // <- the name for our feature type
                "route:LineString:srid=4326," +
                "id:String," +
                "name:String," +
                "desc:String," +
                "notes:String"
                     
        );
    	
    	SimpleFeatureCollection collection = FeatureCollections.newCollection();

        SimpleFeatureBuilder featureBuilder = null;
        
        dataStore.createSchema(ROUTE_TYPE);
       	
        featureBuilder = new SimpleFeatureBuilder(ROUTE_TYPE);
    	
        for(Long patternId : this._patternIds) {

           	TripPattern tp = TripPattern.findById(patternId);
    		
           	if(tp.shape == null)
    			return;
    	
    		featureBuilder.add(tp.shape.shape);
    		featureBuilder.add(tp.name);
    	    featureBuilder.add(tp.route.routeDesc);
    	    featureBuilder.add(tp.route.routeNotes);
    	      
            SimpleFeature feature = featureBuilder.buildFeature(null);
            collection.add(feature);	
        }
    	
        Transaction transaction = new DefaultTransaction("create");

        String typeName = dataStore.getTypeNames()[0];
        SimpleFeatureSource featureSource = dataStore.getFeatureSource(typeName);

        if (featureSource instanceof SimpleFeatureStore) 
        {
            SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;

            featureStore.setTransaction(transaction);
           
            featureStore.addFeatures(collection);
            transaction.commit();

            transaction.close();
        } 
        else 
        {
        	throw new Exception(typeName + " does not support read/write access");
        }
	}
} public static final class Upload extends
    com.google.protobuf.GeneratedMessageLite
    implements UploadOrBuilder {
  // Use Upload.newBuilder() to construct.
  private Upload(Builder builder) {
    super(builder);
  }
  private Upload(boolean noInit) {}
    
  private static final Upload defaultInstance;
  public static Upload getDefaultInstance() {
    return defaultInstance;
  }
    
  public Upload getDefaultInstanceForType() {
    return defaultInstance;
  }
    
  public interface RouteOrBuilder
      extends com.google.protobuf.MessageLiteOrBuilder {
      
    // required int64 start_time = 1;
    boolean hasStartTime();
    long getStartTime();
      
    // repeated .transitwand.Upload.Route.Point point = 2;
    java.util.List<com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point> 
        getPointList();
    com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point getPoint(int index);
    int getPointCount();
      
    // repeated .transitwand.Upload.Route.Stop stop = 3;
    java.util.List<com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop> 
        getStopList();
    com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop getStop(int index);
    int getStopCount();
      
    // optional string route_name = 4;
    boolean hasRouteName();
    String getRouteName();
      
    // optional string route_description = 5;
    boolean hasRouteDescription();
    String getRouteDescription();
      
    // optional string route_notes = 6;
    boolean hasRouteNotes();
    String getRouteNotes();
      
    // optional string vehicle_type = 7;
    boolean hasVehicleType();
    String getVehicleType();
      
    // optional string vehicle_capacity = 8;
    boolean hasVehicleCapacity();
    String getVehicleCapacity();
  }
  public static final class Route extends
      com.google.protobuf.GeneratedMessageLite
      implements RouteOrBuilder {
    // Use Route.newBuilder() to construct.
    private Route(Builder builder) {
      super(builder);
    }
    private Route(boolean noInit) {}
      
    private static final Route defaultInstance;
    public static Route getDefaultInstance() {
      return defaultInstance;
    }
      
    public Route getDefaultInstanceForType() {
      return defaultInstance;
    }
      
    public interface PointOrBuilder
        extends com.google.protobuf.MessageLiteOrBuilder {
        
      // required float lat = 1;
      boolean hasLat();
      float getLat();
        
      // required float lon = 2;
      boolean hasLon();
      float getLon();
        
      // optional int32 timeoffset = 3;
      boolean hasTimeoffset();
      int getTimeoffset();
    }
    public static final class Point extends
        com.google.protobuf.GeneratedMessageLite
        implements PointOrBuilder {
      // Use Point.newBuilder() to construct.
      private Point(Builder builder) {
        super(builder);
      }
      private Point(boolean noInit) {}
        
      private static final Point defaultInstance;
      public static Point getDefaultInstance() {
        return defaultInstance;
      }
        
      public Point getDefaultInstanceForType() {
        return defaultInstance;
      }
        
      private int bitField0_;
      // required float lat = 1;
      public static final int LAT_FIELD_NUMBER = 1;
      private float lat_;
      public boolean hasLat() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      public float getLat() {
        return lat_;
      }
        
      // required float lon = 2;
      public static final int LON_FIELD_NUMBER = 2;
      private float lon_;
      public boolean hasLon() {
        return ((bitField0_ & 0x00000002) == 0x00000002);
      }
      public float getLon() {
        return lon_;
      }
        
      // optional int32 timeoffset = 3;
      public static final int TIMEOFFSET_FIELD_NUMBER = 3;
      private int timeoffset_;
      public boolean hasTimeoffset() {
        return ((bitField0_ & 0x00000004) == 0x00000004);
      }
      public int getTimeoffset() {
        return timeoffset_;
      }
        
      private void initFields() {
        lat_ = 0F;
        lon_ = 0F;
        timeoffset_ = 0;
      }
      private byte memoizedIsInitialized = -1;
      public final boolean isInitialized() {
        byte isInitialized = memoizedIsInitialized;
        if (isInitialized != -1) return isInitialized == 1;
          
        if (!hasLat()) {
          memoizedIsInitialized = 0;
          return false;
        }
        if (!hasLon()) {
          memoizedIsInitialized = 0;
          return false;
        }
        memoizedIsInitialized = 1;
        return true;
      }
        
      public void writeTo(com.google.protobuf.CodedOutputStream output)
                          throws java.io.IOException {
        getSerializedSize();
        if (((bitField0_ & 0x00000001) == 0x00000001)) {
          output.writeFloat(1, lat_);
        }
        if (((bitField0_ & 0x00000002) == 0x00000002)) {
          output.writeFloat(2, lon_);
        }
        if (((bitField0_ & 0x00000004) == 0x00000004)) {
          output.writeInt32(3, timeoffset_);
        }
      }
        
      private int memoizedSerializedSize = -1;
      public int getSerializedSize() {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        
        size = 0;
        if (((bitField0_ & 0x00000001) == 0x00000001)) {
          size += com.google.protobuf.CodedOutputStream
            .computeFloatSize(1, lat_);
        }
        if (((bitField0_ & 0x00000002) == 0x00000002)) {
          size += com.google.protobuf.CodedOutputStream
            .computeFloatSize(2, lon_);
        }
        if (((bitField0_ & 0x00000004) == 0x00000004)) {
          size += com.google.protobuf.CodedOutputStream
            .computeInt32Size(3, timeoffset_);
        }
        memoizedSerializedSize = size;
        return size;
      }
        
      private static final long serialVersionUID = 0L;
      @java.lang.Override
      protected java.lang.Object writeReplace()
          throws java.io.ObjectStreamException {
        return super.writeReplace();
      }
        
      public static com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point parseFrom(
          com.google.protobuf.ByteString data)
          throws com.google.protobuf.InvalidProtocolBufferException {
        return newBuilder().mergeFrom(data).buildParsed();
      }
      public static com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point parseFrom(
          com.google.protobuf.ByteString data,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws com.google.protobuf.InvalidProtocolBufferException {
        return newBuilder().mergeFrom(data, extensionRegistry)
                 .buildParsed();
      }
      public static com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point parseFrom(byte[] data)
          throws com.google.protobuf.InvalidProtocolBufferException {
        return newBuilder().mergeFrom(data).buildParsed();
      }
      public static com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point parseFrom(
          byte[] data,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws com.google.protobuf.InvalidProtocolBufferException {
        return newBuilder().mergeFrom(data, extensionRegistry)
                 .buildParsed();
      }
      public static com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point parseFrom(java.io.InputStream input)
          throws java.io.IOException {
        return newBuilder().mergeFrom(input).buildParsed();
      }
      public static com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point parseFrom(
          java.io.InputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        return newBuilder().mergeFrom(input, extensionRegistry)
                 .buildParsed();
      }
      public static com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point parseDelimitedFrom(java.io.InputStream input)
          throws java.io.IOException {
        Builder builder = newBuilder();
        if (builder.mergeDelimitedFrom(input)) {
          return builder.buildParsed();
        } else {
          return null;
        }
      }
      public static com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point parseDelimitedFrom(
          java.io.InputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        Builder builder = newBuilder();
        if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
          return builder.buildParsed();
        } else {
          return null;
        }
      }
      public static com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point parseFrom(
          com.google.protobuf.CodedInputStream input)
          throws java.io.IOException {
        return newBuilder().mergeFrom(input).buildParsed();
      }
      public static com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point parseFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        return newBuilder().mergeFrom(input, extensionRegistry)
                 .buildParsed();
      }
        
      public static Builder newBuilder() { return Builder.create(); }
      public Builder newBuilderForType() { return newBuilder(); }
      public static Builder newBuilder(com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point prototype) {
        return newBuilder().mergeFrom(prototype);
      }
      public Builder toBuilder() { return newBuilder(this); }
        
      public static final class Builder extends
          com.google.protobuf.GeneratedMessageLite.Builder<
            com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point, Builder>
          implements com.conveyal.transitwand.TransitWandProtos.Upload.Route.PointOrBuilder {
        // Construct using com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point.newBuilder()
        private Builder() {
          maybeForceBuilderInitialization();
        }
          
        private void maybeForceBuilderInitialization() {
        }
        private static Builder create() {
          return new Builder();
        }
          
        public Builder clear() {
          super.clear();
          lat_ = 0F;
          bitField0_ = (bitField0_ & ~0x00000001);
          lon_ = 0F;
          bitField0_ = (bitField0_ & ~0x00000002);
          timeoffset_ = 0;
          bitField0_ = (bitField0_ & ~0x00000004);
          return this;
        }
          
        public Builder clone() {
          return create().mergeFrom(buildPartial());
        }
          
        public com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point getDefaultInstanceForType() {
          return com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point.getDefaultInstance();
        }
          
        public com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point build() {
          com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point result = buildPartial();
          if (!result.isInitialized()) {
            throw newUninitializedMessageException(result);
          }
          return result;
        }
          
        private com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point buildParsed()
            throws com.google.protobuf.InvalidProtocolBufferException {
          com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point result = buildPartial();
          if (!result.isInitialized()) {
            throw newUninitializedMessageException(
              result).asInvalidProtocolBufferException();
          }
          return result;
        }
          
        public com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point buildPartial() {
          com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point result = new com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point(this);
          int from_bitField0_ = bitField0_;
          int to_bitField0_ = 0;
          if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
            to_bitField0_ |= 0x00000001;
          }
          result.lat_ = lat_;
          if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
            to_bitField0_ |= 0x00000002;
          }
          result.lon_ = lon_;
          if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
            to_bitField0_ |= 0x00000004;
          }
          result.timeoffset_ = timeoffset_;
          result.bitField0_ = to_bitField0_;
          return result;
        }
          
        public Builder mergeFrom(com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point other) {
          if (other == com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point.getDefaultInstance()) return this;
          if (other.hasLat()) {
            setLat(other.getLat());
          }
          if (other.hasLon()) {
            setLon(other.getLon());
          }
          if (other.hasTimeoffset()) {
            setTimeoffset(other.getTimeoffset());
          }
          return this;
        }
          
        public final boolean isInitialized() {
          if (!hasLat()) {
              
            return false;
          }
          if (!hasLon()) {
              
            return false;
          }
          return true;
        }
          
        public Builder mergeFrom(
            com.google.protobuf.CodedInputStream input,
            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
            throws java.io.IOException {
          while (true) {
            int tag = input.readTag();
            switch (tag) {
              case 0:
                  
                return this;
              default: {
                if (!parseUnknownField(input, extensionRegistry, tag)) {
                    
                  return this;
                }
                break;
              }
              case 13: {
                bitField0_ |= 0x00000001;
                lat_ = input.readFloat();
                break;
              }
              case 21: {
                bitField0_ |= 0x00000002;
                lon_ = input.readFloat();
                break;
              }
              case 24: {
                bitField0_ |= 0x00000004;
                timeoffset_ = input.readInt32();
                break;
              }
            }
          }
        }
          
        private int bitField0_;
          
        // required float lat = 1;
        private float lat_ ;
        public boolean hasLat() {
          return ((bitField0_ & 0x00000001) == 0x00000001);
        }
        public float getLat() {
          return lat_;
        }
        public Builder setLat(float value) {
          bitField0_ |= 0x00000001;
          lat_ = value;
            
          return this;
        }
        public Builder clearLat() {
          bitField0_ = (bitField0_ & ~0x00000001);
          lat_ = 0F;
            
          return this;
        }
          
        // required float lon = 2;
        private float lon_ ;
        public boolean hasLon() {
          return ((bitField0_ & 0x00000002) == 0x00000002);
        }
        public float getLon() {
          return lon_;
        }
        public Builder setLon(float value) {
          bitField0_ |= 0x00000002;
          lon_ = value;
            
          return this;
        }
        public Builder clearLon() {
          bitField0_ = (bitField0_ & ~0x00000002);
          lon_ = 0F;
            
          return this;
        }
          
        // optional int32 timeoffset = 3;
        private int timeoffset_ ;
        public boolean hasTimeoffset() {
          return ((bitField0_ & 0x00000004) == 0x00000004);
        }
        public int getTimeoffset() {
          return timeoffset_;
        }
        public Builder setTimeoffset(int value) {
          bitField0_ |= 0x00000004;
          timeoffset_ = value;
            
          return this;
        }
        public Builder clearTimeoffset() {
          bitField0_ = (bitField0_ & ~0x00000004);
          timeoffset_ = 0;
            
          return this;
        }
          
        // @@protoc_insertion_point(builder_scope:transitwand.Upload.Route.Point)
      }
        
      static {
        defaultInstance = new Point(true);
        defaultInstance.initFields();
      }
        
      // @@protoc_insertion_point(class_scope:transitwand.Upload.Route.Point)
    }
      
    public interface StopOrBuilder
        extends com.google.protobuf.MessageLiteOrBuilder {
        
      // required float lat = 1;
      boolean hasLat();
      float getLat();
        
      // required float lon = 2;
      boolean hasLon();
      float getLon();
        
      // optional int32 arrivalTimeoffset = 3;
      boolean hasArrivalTimeoffset();
      int getArrivalTimeoffset();
        
      // optional int32 departureTimeoffset = 4;
      boolean hasDepartureTimeoffset();
      int getDepartureTimeoffset();
        
      // optional int32 board = 5;
      boolean hasBoard();
      int getBoard();
        
      // optional int32 alight = 6;
      boolean hasAlight();
      int getAlight();
    }
    public static final class Stop extends
        com.google.protobuf.GeneratedMessageLite
        implements StopOrBuilder {
      // Use Stop.newBuilder() to construct.
      private Stop(Builder builder) {
        super(builder);
      }
      private Stop(boolean noInit) {}
        
      private static final Stop defaultInstance;
      public static Stop getDefaultInstance() {
        return defaultInstance;
      }
        
      public Stop getDefaultInstanceForType() {
        return defaultInstance;
      }
        
      private int bitField0_;
      // required float lat = 1;
      public static final int LAT_FIELD_NUMBER = 1;
      private float lat_;
      public boolean hasLat() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      public float getLat() {
        return lat_;
      }
        
      // required float lon = 2;
      public static final int LON_FIELD_NUMBER = 2;
      private float lon_;
      public boolean hasLon() {
        return ((bitField0_ & 0x00000002) == 0x00000002);
      }
      public float getLon() {
        return lon_;
      }
        
      // optional int32 arrivalTimeoffset = 3;
      public static final int ARRIVALTIMEOFFSET_FIELD_NUMBER = 3;
      private int arrivalTimeoffset_;
      public boolean hasArrivalTimeoffset() {
        return ((bitField0_ & 0x00000004) == 0x00000004);
      }
      public int getArrivalTimeoffset() {
        return arrivalTimeoffset_;
      }
        
      // optional int32 departureTimeoffset = 4;
      public static final int DEPARTURETIMEOFFSET_FIELD_NUMBER = 4;
      private int departureTimeoffset_;
      public boolean hasDepartureTimeoffset() {
        return ((bitField0_ & 0x00000008) == 0x00000008);
      }
      public int getDepartureTimeoffset() {
        return departureTimeoffset_;
      }
        
      // optional int32 board = 5;
      public static final int BOARD_FIELD_NUMBER = 5;
      private int board_;
      public boolean hasBoard() {
        return ((bitField0_ & 0x00000010) == 0x00000010);
      }
      public int getBoard() {
        return board_;
      }
        
      // optional int32 alight = 6;
      public static final int ALIGHT_FIELD_NUMBER = 6;
      private int alight_;
      public boolean hasAlight() {
        return ((bitField0_ & 0x00000020) == 0x00000020);
      }
      public int getAlight() {
        return alight_;
      }
        
      private void initFields() {
        lat_ = 0F;
        lon_ = 0F;
        arrivalTimeoffset_ = 0;
        departureTimeoffset_ = 0;
        board_ = 0;
        alight_ = 0;
      }
      private byte memoizedIsInitialized = -1;
      public final boolean isInitialized() {
        byte isInitialized = memoizedIsInitialized;
        if (isInitialized != -1) return isInitialized == 1;
          
        if (!hasLat()) {
          memoizedIsInitialized = 0;
          return false;
        }
        if (!hasLon()) {
          memoizedIsInitialized = 0;
          return false;
        }
        memoizedIsInitialized = 1;
        return true;
      }
        
      public void writeTo(com.google.protobuf.CodedOutputStream output)
                          throws java.io.IOException {
        getSerializedSize();
        if (((bitField0_ & 0x00000001) == 0x00000001)) {
          output.writeFloat(1, lat_);
        }
        if (((bitField0_ & 0x00000002) == 0x00000002)) {
          output.writeFloat(2, lon_);
        }
        if (((bitField0_ & 0x00000004) == 0x00000004)) {
          output.writeInt32(3, arrivalTimeoffset_);
        }
        if (((bitField0_ & 0x00000008) == 0x00000008)) {
          output.writeInt32(4, departureTimeoffset_);
        }
        if (((bitField0_ & 0x00000010) == 0x00000010)) {
          output.writeInt32(5, board_);
        }
        if (((bitField0_ & 0x00000020) == 0x00000020)) {
          output.writeInt32(6, alight_);
        }
      }
        
      private int memoizedSerializedSize = -1;
      public int getSerializedSize() {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        
        size = 0;
        if (((bitField0_ & 0x00000001) == 0x00000001)) {
          size += com.google.protobuf.CodedOutputStream
            .computeFloatSize(1, lat_);
        }
        if (((bitField0_ & 0x00000002) == 0x00000002)) {
          size += com.google.protobuf.CodedOutputStream
            .computeFloatSize(2, lon_);
        }
        if (((bitField0_ & 0x00000004) == 0x00000004)) {
          size += com.google.protobuf.CodedOutputStream
            .computeInt32Size(3, arrivalTimeoffset_);
        }
        if (((bitField0_ & 0x00000008) == 0x00000008)) {
          size += com.google.protobuf.CodedOutputStream
            .computeInt32Size(4, departureTimeoffset_);
        }
        if (((bitField0_ & 0x00000010) == 0x00000010)) {
          size += com.google.protobuf.CodedOutputStream
            .computeInt32Size(5, board_);
        }
        if (((bitField0_ & 0x00000020) == 0x00000020)) {
          size += com.google.protobuf.CodedOutputStream
            .computeInt32Size(6, alight_);
        }
        memoizedSerializedSize = size;
        return size;
      }
        
      private static final long serialVersionUID = 0L;
      @java.lang.Override
      protected java.lang.Object writeReplace()
          throws java.io.ObjectStreamException {
        return super.writeReplace();
      }
        
      public static com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop parseFrom(
          com.google.protobuf.ByteString data)
          throws com.google.protobuf.InvalidProtocolBufferException {
        return newBuilder().mergeFrom(data).buildParsed();
      }
      public static com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop parseFrom(
          com.google.protobuf.ByteString data,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws com.google.protobuf.InvalidProtocolBufferException {
        return newBuilder().mergeFrom(data, extensionRegistry)
                 .buildParsed();
      }
      public static com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop parseFrom(byte[] data)
          throws com.google.protobuf.InvalidProtocolBufferException {
        return newBuilder().mergeFrom(data).buildParsed();
      }
      public static com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop parseFrom(
          byte[] data,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws com.google.protobuf.InvalidProtocolBufferException {
        return newBuilder().mergeFrom(data, extensionRegistry)
                 .buildParsed();
      }
      public static com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop parseFrom(java.io.InputStream input)
          throws java.io.IOException {
        return newBuilder().mergeFrom(input).buildParsed();
      }
      public static com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop parseFrom(
          java.io.InputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        return newBuilder().mergeFrom(input, extensionRegistry)
                 .buildParsed();
      }
      public static com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop parseDelimitedFrom(java.io.InputStream input)
          throws java.io.IOException {
        Builder builder = newBuilder();
        if (builder.mergeDelimitedFrom(input)) {
          return builder.buildParsed();
        } else {
          return null;
        }
      }
      public static com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop parseDelimitedFrom(
          java.io.InputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        Builder builder = newBuilder();
        if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
          return builder.buildParsed();
        } else {
          return null;
        }
      }
      public static com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop parseFrom(
          com.google.protobuf.CodedInputStream input)
          throws java.io.IOException {
        return newBuilder().mergeFrom(input).buildParsed();
      }
      public static com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop parseFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        return newBuilder().mergeFrom(input, extensionRegistry)
                 .buildParsed();
      }
        
      public static Builder newBuilder() { return Builder.create(); }
      public Builder newBuilderForType() { return newBuilder(); }
      public static Builder newBuilder(com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop prototype) {
        return newBuilder().mergeFrom(prototype);
      }
      public Builder toBuilder() { return newBuilder(this); }
        
      public static final class Builder extends
          com.google.protobuf.GeneratedMessageLite.Builder<
            com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop, Builder>
          implements com.conveyal.transitwand.TransitWandProtos.Upload.Route.StopOrBuilder {
        // Construct using com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop.newBuilder()
        private Builder() {
          maybeForceBuilderInitialization();
        }
          
        private void maybeForceBuilderInitialization() {
        }
        private static Builder create() {
          return new Builder();
        }
          
        public Builder clear() {
          super.clear();
          lat_ = 0F;
          bitField0_ = (bitField0_ & ~0x00000001);
          lon_ = 0F;
          bitField0_ = (bitField0_ & ~0x00000002);
          arrivalTimeoffset_ = 0;
          bitField0_ = (bitField0_ & ~0x00000004);
          departureTimeoffset_ = 0;
          bitField0_ = (bitField0_ & ~0x00000008);
          board_ = 0;
          bitField0_ = (bitField0_ & ~0x00000010);
          alight_ = 0;
          bitField0_ = (bitField0_ & ~0x00000020);
          return this;
        }
          
        public Builder clone() {
          return create().mergeFrom(buildPartial());
        }
          
        public com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop getDefaultInstanceForType() {
          return com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop.getDefaultInstance();
        }
          
        public com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop build() {
          com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop result = buildPartial();
          if (!result.isInitialized()) {
            throw newUninitializedMessageException(result);
          }
          return result;
        }
          
        private com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop buildParsed()
            throws com.google.protobuf.InvalidProtocolBufferException {
          com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop result = buildPartial();
          if (!result.isInitialized()) {
            throw newUninitializedMessageException(
              result).asInvalidProtocolBufferException();
          }
          return result;
        }
          
        public com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop buildPartial() {
          com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop result = new com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop(this);
          int from_bitField0_ = bitField0_;
          int to_bitField0_ = 0;
          if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
            to_bitField0_ |= 0x00000001;
          }
          result.lat_ = lat_;
          if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
            to_bitField0_ |= 0x00000002;
          }
          result.lon_ = lon_;
          if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
            to_bitField0_ |= 0x00000004;
          }
          result.arrivalTimeoffset_ = arrivalTimeoffset_;
          if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
            to_bitField0_ |= 0x00000008;
          }
          result.departureTimeoffset_ = departureTimeoffset_;
          if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
            to_bitField0_ |= 0x00000010;
          }
          result.board_ = board_;
          if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
            to_bitField0_ |= 0x00000020;
          }
          result.alight_ = alight_;
          result.bitField0_ = to_bitField0_;
          return result;
        }
          
        public Builder mergeFrom(com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop other) {
          if (other == com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop.getDefaultInstance()) return this;
          if (other.hasLat()) {
            setLat(other.getLat());
          }
          if (other.hasLon()) {
            setLon(other.getLon());
          }
          if (other.hasArrivalTimeoffset()) {
            setArrivalTimeoffset(other.getArrivalTimeoffset());
          }
          if (other.hasDepartureTimeoffset()) {
            setDepartureTimeoffset(other.getDepartureTimeoffset());
          }
          if (other.hasBoard()) {
            setBoard(other.getBoard());
          }
          if (other.hasAlight()) {
            setAlight(other.getAlight());
          }
          return this;
        }
          
        public final boolean isInitialized() {
          if (!hasLat()) {
              
            return false;
          }
          if (!hasLon()) {
              
            return false;
          }
          return true;
        }
          
        public Builder mergeFrom(
            com.google.protobuf.CodedInputStream input,
            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
            throws java.io.IOException {
          while (true) {
            int tag = input.readTag();
            switch (tag) {
              case 0:
                  
                return this;
              default: {
                if (!parseUnknownField(input, extensionRegistry, tag)) {
                    
                  return this;
                }
                break;
              }
              case 13: {
                bitField0_ |= 0x00000001;
                lat_ = input.readFloat();
                break;
              }
              case 21: {
                bitField0_ |= 0x00000002;
                lon_ = input.readFloat();
                break;
              }
              case 24: {
                bitField0_ |= 0x00000004;
                arrivalTimeoffset_ = input.readInt32();
                break;
              }
              case 32: {
                bitField0_ |= 0x00000008;
                departureTimeoffset_ = input.readInt32();
                break;
              }
              case 40: {
                bitField0_ |= 0x00000010;
                board_ = input.readInt32();
                break;
              }
              case 48: {
                bitField0_ |= 0x00000020;
                alight_ = input.readInt32();
                break;
              }
            }
          }
        }
          
        private int bitField0_;
          
        // required float lat = 1;
        private float lat_ ;
        public boolean hasLat() {
          return ((bitField0_ & 0x00000001) == 0x00000001);
        }
        public float getLat() {
          return lat_;
        }
        public Builder setLat(float value) {
          bitField0_ |= 0x00000001;
          lat_ = value;
            
          return this;
        }
        public Builder clearLat() {
          bitField0_ = (bitField0_ & ~0x00000001);
          lat_ = 0F;
            
          return this;
        }
          
        // required float lon = 2;
        private float lon_ ;
        public boolean hasLon() {
          return ((bitField0_ & 0x00000002) == 0x00000002);
        }
        public float getLon() {
          return lon_;
        }
        public Builder setLon(float value) {
          bitField0_ |= 0x00000002;
          lon_ = value;
            
          return this;
        }
        public Builder clearLon() {
          bitField0_ = (bitField0_ & ~0x00000002);
          lon_ = 0F;
            
          return this;
        }
          
        // optional int32 arrivalTimeoffset = 3;
        private int arrivalTimeoffset_ ;
        public boolean hasArrivalTimeoffset() {
          return ((bitField0_ & 0x00000004) == 0x00000004);
        }
        public int getArrivalTimeoffset() {
          return arrivalTimeoffset_;
        }
        public Builder setArrivalTimeoffset(int value) {
          bitField0_ |= 0x00000004;
          arrivalTimeoffset_ = value;
            
          return this;
        }
        public Builder clearArrivalTimeoffset() {
          bitField0_ = (bitField0_ & ~0x00000004);
          arrivalTimeoffset_ = 0;
            
          return this;
        }
          
        // optional int32 departureTimeoffset = 4;
        private int departureTimeoffset_ ;
        public boolean hasDepartureTimeoffset() {
          return ((bitField0_ & 0x00000008) == 0x00000008);
        }
        public int getDepartureTimeoffset() {
          return departureTimeoffset_;
        }
        public Builder setDepartureTimeoffset(int value) {
          bitField0_ |= 0x00000008;
          departureTimeoffset_ = value;
            
          return this;
        }
        public Builder clearDepartureTimeoffset() {
          bitField0_ = (bitField0_ & ~0x00000008);
          departureTimeoffset_ = 0;
            
          return this;
        }
          
        // optional int32 board = 5;
        private int board_ ;
        public boolean hasBoard() {
          return ((bitField0_ & 0x00000010) == 0x00000010);
        }
        public int getBoard() {
          return board_;
        }
        public Builder setBoard(int value) {
          bitField0_ |= 0x00000010;
          board_ = value;
            
          return this;
        }
        public Builder clearBoard() {
          bitField0_ = (bitField0_ & ~0x00000010);
          board_ = 0;
            
          return this;
        }
          
        // optional int32 alight = 6;
        private int alight_ ;
        public boolean hasAlight() {
          return ((bitField0_ & 0x00000020) == 0x00000020);
        }
        public int getAlight() {
          return alight_;
        }
        public Builder setAlight(int value) {
          bitField0_ |= 0x00000020;
          alight_ = value;
            
          return this;
        }
        public Builder clearAlight() {
          bitField0_ = (bitField0_ & ~0x00000020);
          alight_ = 0;
            
          return this;
        }
          
        // @@protoc_insertion_point(builder_scope:transitwand.Upload.Route.Stop)
      }
        
      static {
        defaultInstance = new Stop(true);
        defaultInstance.initFields();
      }
        
      // @@protoc_insertion_point(class_scope:transitwand.Upload.Route.Stop)
    }
      
    private int bitField0_;
    // required int64 start_time = 1;
    public static final int START_TIME_FIELD_NUMBER = 1;
    private long startTime_;
    public boolean hasStartTime() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    public long getStartTime() {
      return startTime_;
    }
      
    // repeated .transitwand.Upload.Route.Point point = 2;
    public static final int POINT_FIELD_NUMBER = 2;
    private java.util.List<com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point> point_;
    public java.util.List<com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point> getPointList() {
      return point_;
    }
    public java.util.List<? extends com.conveyal.transitwand.TransitWandProtos.Upload.Route.PointOrBuilder> 
        getPointOrBuilderList() {
      return point_;
    }
    public int getPointCount() {
      return point_.size();
    }
    public com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point getPoint(int index) {
      return point_.get(index);
    }
    public com.conveyal.transitwand.TransitWandProtos.Upload.Route.PointOrBuilder getPointOrBuilder(
        int index) {
      return point_.get(index);
    }
      
    // repeated .transitwand.Upload.Route.Stop stop = 3;
    public static final int STOP_FIELD_NUMBER = 3;
    private java.util.List<com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop> stop_;
    public java.util.List<com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop> getStopList() {
      return stop_;
    }
    public java.util.List<? extends com.conveyal.transitwand.TransitWandProtos.Upload.Route.StopOrBuilder> 
        getStopOrBuilderList() {
      return stop_;
    }
    public int getStopCount() {
      return stop_.size();
    }
    public com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop getStop(int index) {
      return stop_.get(index);
    }
    public com.conveyal.transitwand.TransitWandProtos.Upload.Route.StopOrBuilder getStopOrBuilder(
        int index) {
      return stop_.get(index);
    }
      
    // optional string route_name = 4;
    public static final int ROUTE_NAME_FIELD_NUMBER = 4;
    private java.lang.Object routeName_;
    public boolean hasRouteName() {
      return ((bitField0_ & 0x00000002) == 0x00000002);
    }
    public String getRouteName() {
      java.lang.Object ref = routeName_;
      if (ref instanceof String) {
        return (String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        String s = bs.toStringUtf8();
        if (com.google.protobuf.Internal.isValidUtf8(bs)) {
          routeName_ = s;
        }
        return s;
      }
    }
    private com.google.protobuf.ByteString getRouteNameBytes() {
      java.lang.Object ref = routeName_;
      if (ref instanceof String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8((String) ref);
        routeName_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }
      
    // optional string route_description = 5;
    public static final int ROUTE_DESCRIPTION_FIELD_NUMBER = 5;
    private java.lang.Object routeDescription_;
    public boolean hasRouteDescription() {
      return ((bitField0_ & 0x00000004) == 0x00000004);
    }
    public String getRouteDescription() {
      java.lang.Object ref = routeDescription_;
      if (ref instanceof String) {
        return (String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        String s = bs.toStringUtf8();
        if (com.google.protobuf.Internal.isValidUtf8(bs)) {
          routeDescription_ = s;
        }
        return s;
      }
    }
    private com.google.protobuf.ByteString getRouteDescriptionBytes() {
      java.lang.Object ref = routeDescription_;
      if (ref instanceof String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8((String) ref);
        routeDescription_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }
      
    // optional string route_notes = 6;
    public static final int ROUTE_NOTES_FIELD_NUMBER = 6;
    private java.lang.Object routeNotes_;
    public boolean hasRouteNotes() {
      return ((bitField0_ & 0x00000008) == 0x00000008);
    }
    public String getRouteNotes() {
      java.lang.Object ref = routeNotes_;
      if (ref instanceof String) {
        return (String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        String s = bs.toStringUtf8();
        if (com.google.protobuf.Internal.isValidUtf8(bs)) {
          routeNotes_ = s;
        }
        return s;
      }
    }
    private com.google.protobuf.ByteString getRouteNotesBytes() {
      java.lang.Object ref = routeNotes_;
      if (ref instanceof String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8((String) ref);
        routeNotes_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }
      
    // optional string vehicle_type = 7;
    public static final int VEHICLE_TYPE_FIELD_NUMBER = 7;
    private java.lang.Object vehicleType_;
    public boolean hasVehicleType() {
      return ((bitField0_ & 0x00000010) == 0x00000010);
    }
    public String getVehicleType() {
      java.lang.Object ref = vehicleType_;
      if (ref instanceof String) {
        return (String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        String s = bs.toStringUtf8();
        if (com.google.protobuf.Internal.isValidUtf8(bs)) {
          vehicleType_ = s;
        }
        return s;
      }
    }
    private com.google.protobuf.ByteString getVehicleTypeBytes() {
      java.lang.Object ref = vehicleType_;
      if (ref instanceof String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8((String) ref);
        vehicleType_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }
      
    // optional string vehicle_capacity = 8;
    public static final int VEHICLE_CAPACITY_FIELD_NUMBER = 8;
    private java.lang.Object vehicleCapacity_;
    public boolean hasVehicleCapacity() {
      return ((bitField0_ & 0x00000020) == 0x00000020);
    }
    public String getVehicleCapacity() {
      java.lang.Object ref = vehicleCapacity_;
      if (ref instanceof String) {
        return (String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        String s = bs.toStringUtf8();
        if (com.google.protobuf.Internal.isValidUtf8(bs)) {
          vehicleCapacity_ = s;
        }
        return s;
      }
    }
    private com.google.protobuf.ByteString getVehicleCapacityBytes() {
      java.lang.Object ref = vehicleCapacity_;
      if (ref instanceof String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8((String) ref);
        vehicleCapacity_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }
      
    private void initFields() {
      startTime_ = 0L;
      point_ = java.util.Collections.emptyList();
      stop_ = java.util.Collections.emptyList();
      routeName_ = "";
      routeDescription_ = "";
      routeNotes_ = "";
      vehicleType_ = "";
      vehicleCapacity_ = "";
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;
        
      if (!hasStartTime()) {
        memoizedIsInitialized = 0;
        return false;
      }
      for (int i = 0; i < getPointCount(); i++) {
        if (!getPoint(i).isInitialized()) {
          memoizedIsInitialized = 0;
          return false;
        }
      }
      for (int i = 0; i < getStopCount(); i++) {
        if (!getStop(i).isInitialized()) {
          memoizedIsInitialized = 0;
          return false;
        }
      }
      memoizedIsInitialized = 1;
      return true;
    }
      
    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        output.writeInt64(1, startTime_);
      }
      for (int i = 0; i < point_.size(); i++) {
        output.writeMessage(2, point_.get(i));
      }
      for (int i = 0; i < stop_.size(); i++) {
        output.writeMessage(3, stop_.get(i));
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        output.writeBytes(4, getRouteNameBytes());
      }
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        output.writeBytes(5, getRouteDescriptionBytes());
      }
      if (((bitField0_ & 0x00000008) == 0x00000008)) {
        output.writeBytes(6, getRouteNotesBytes());
      }
      if (((bitField0_ & 0x00000010) == 0x00000010)) {
        output.writeBytes(7, getVehicleTypeBytes());
      }
      if (((bitField0_ & 0x00000020) == 0x00000020)) {
        output.writeBytes(8, getVehicleCapacityBytes());
      }
    }
      
    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;
      
      size = 0;
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt64Size(1, startTime_);
      }
      for (int i = 0; i < point_.size(); i++) {
        size += com.google.protobuf.CodedOutputStream
          .computeMessageSize(2, point_.get(i));
      }
      for (int i = 0; i < stop_.size(); i++) {
        size += com.google.protobuf.CodedOutputStream
          .computeMessageSize(3, stop_.get(i));
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(4, getRouteNameBytes());
      }
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(5, getRouteDescriptionBytes());
      }
      if (((bitField0_ & 0x00000008) == 0x00000008)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(6, getRouteNotesBytes());
      }
      if (((bitField0_ & 0x00000010) == 0x00000010)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(7, getVehicleTypeBytes());
      }
      if (((bitField0_ & 0x00000020) == 0x00000020)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(8, getVehicleCapacityBytes());
      }
      memoizedSerializedSize = size;
      return size;
    }
      
    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }
      
    public static com.conveyal.transitwand.TransitWandProtos.Upload.Route parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return newBuilder().mergeFrom(data).buildParsed();
    }
    public static com.conveyal.transitwand.TransitWandProtos.Upload.Route parseFrom(
        com.google.protobuf.ByteString data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return newBuilder().mergeFrom(data, extensionRegistry)
               .buildParsed();
    }
    public static com.conveyal.transitwand.TransitWandProtos.Upload.Route parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return newBuilder().mergeFrom(data).buildParsed();
    }
    public static com.conveyal.transitwand.TransitWandProtos.Upload.Route parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return newBuilder().mergeFrom(data, extensionRegistry)
               .buildParsed();
    }
    public static com.conveyal.transitwand.TransitWandProtos.Upload.Route parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return newBuilder().mergeFrom(input).buildParsed();
    }
    public static com.conveyal.transitwand.TransitWandProtos.Upload.Route parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return newBuilder().mergeFrom(input, extensionRegistry)
               .buildParsed();
    }
    public static com.conveyal.transitwand.TransitWandProtos.Upload.Route parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      Builder builder = newBuilder();
      if (builder.mergeDelimitedFrom(input)) {
        return builder.buildParsed();
      } else {
        return null;
      }
    }
    public static com.conveyal.transitwand.TransitWandProtos.Upload.Route parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      Builder builder = newBuilder();
      if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
        return builder.buildParsed();
      } else {
        return null;
      }
    }
    public static com.conveyal.transitwand.TransitWandProtos.Upload.Route parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return newBuilder().mergeFrom(input).buildParsed();
    }
    public static com.conveyal.transitwand.TransitWandProtos.Upload.Route parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return newBuilder().mergeFrom(input, extensionRegistry)
               .buildParsed();
    }
      
    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(com.conveyal.transitwand.TransitWandProtos.Upload.Route prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }
      
    public static final class Builder extends
        com.google.protobuf.GeneratedMessageLite.Builder<
          com.conveyal.transitwand.TransitWandProtos.Upload.Route, Builder>
        implements com.conveyal.transitwand.TransitWandProtos.Upload.RouteOrBuilder {
      // Construct using com.conveyal.transitwand.TransitWandProtos.Upload.Route.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }
        
      private void maybeForceBuilderInitialization() {
      }
      private static Builder create() {
        return new Builder();
      }
        
      public Builder clear() {
        super.clear();
        startTime_ = 0L;
        bitField0_ = (bitField0_ & ~0x00000001);
        point_ = java.util.Collections.emptyList();
        bitField0_ = (bitField0_ & ~0x00000002);
        stop_ = java.util.Collections.emptyList();
        bitField0_ = (bitField0_ & ~0x00000004);
        routeName_ = "";
        bitField0_ = (bitField0_ & ~0x00000008);
        routeDescription_ = "";
        bitField0_ = (bitField0_ & ~0x00000010);
        routeNotes_ = "";
        bitField0_ = (bitField0_ & ~0x00000020);
        vehicleType_ = "";
        bitField0_ = (bitField0_ & ~0x00000040);
        vehicleCapacity_ = "";
        bitField0_ = (bitField0_ & ~0x00000080);
        return this;
      }
        
      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }
        
      public com.conveyal.transitwand.TransitWandProtos.Upload.Route getDefaultInstanceForType() {
        return com.conveyal.transitwand.TransitWandProtos.Upload.Route.getDefaultInstance();
      }
        
      public com.conveyal.transitwand.TransitWandProtos.Upload.Route build() {
        com.conveyal.transitwand.TransitWandProtos.Upload.Route result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }
        
      private com.conveyal.transitwand.TransitWandProtos.Upload.Route buildParsed()
          throws com.google.protobuf.InvalidProtocolBufferException {
        com.conveyal.transitwand.TransitWandProtos.Upload.Route result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(
            result).asInvalidProtocolBufferException();
        }
        return result;
      }
        
      public com.conveyal.transitwand.TransitWandProtos.Upload.Route buildPartial() {
        com.conveyal.transitwand.TransitWandProtos.Upload.Route result = new com.conveyal.transitwand.TransitWandProtos.Upload.Route(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        result.startTime_ = startTime_;
        if (((bitField0_ & 0x00000002) == 0x00000002)) {
          point_ = java.util.Collections.unmodifiableList(point_);
          bitField0_ = (bitField0_ & ~0x00000002);
        }
        result.point_ = point_;
        if (((bitField0_ & 0x00000004) == 0x00000004)) {
          stop_ = java.util.Collections.unmodifiableList(stop_);
          bitField0_ = (bitField0_ & ~0x00000004);
        }
        result.stop_ = stop_;
        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
          to_bitField0_ |= 0x00000002;
        }
        result.routeName_ = routeName_;
        if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
          to_bitField0_ |= 0x00000004;
        }
        result.routeDescription_ = routeDescription_;
        if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
          to_bitField0_ |= 0x00000008;
        }
        result.routeNotes_ = routeNotes_;
        if (((from_bitField0_ & 0x00000040) == 0x00000040)) {
          to_bitField0_ |= 0x00000010;
        }
        result.vehicleType_ = vehicleType_;
        if (((from_bitField0_ & 0x00000080) == 0x00000080)) {
          to_bitField0_ |= 0x00000020;
        }
        result.vehicleCapacity_ = vehicleCapacity_;
        result.bitField0_ = to_bitField0_;
        return result;
      }
        
      public Builder mergeFrom(com.conveyal.transitwand.TransitWandProtos.Upload.Route other) {
        if (other == com.conveyal.transitwand.TransitWandProtos.Upload.Route.getDefaultInstance()) return this;
        if (other.hasStartTime()) {
          setStartTime(other.getStartTime());
        }
        if (!other.point_.isEmpty()) {
          if (point_.isEmpty()) {
            point_ = other.point_;
            bitField0_ = (bitField0_ & ~0x00000002);
          } else {
            ensurePointIsMutable();
            point_.addAll(other.point_);
          }
            
        }
        if (!other.stop_.isEmpty()) {
          if (stop_.isEmpty()) {
            stop_ = other.stop_;
            bitField0_ = (bitField0_ & ~0x00000004);
          } else {
            ensureStopIsMutable();
            stop_.addAll(other.stop_);
          }
            
        }
        if (other.hasRouteName()) {
          setRouteName(other.getRouteName());
        }
        if (other.hasRouteDescription()) {
          setRouteDescription(other.getRouteDescription());
        }
        if (other.hasRouteNotes()) {
          setRouteNotes(other.getRouteNotes());
        }
        if (other.hasVehicleType()) {
          setVehicleType(other.getVehicleType());
        }
        if (other.hasVehicleCapacity()) {
          setVehicleCapacity(other.getVehicleCapacity());
        }
        return this;
      }
        
      public final boolean isInitialized() {
        if (!hasStartTime()) {
            
          return false;
        }
        for (int i = 0; i < getPointCount(); i++) {
          if (!getPoint(i).isInitialized()) {
              
            return false;
          }
        }
        for (int i = 0; i < getStopCount(); i++) {
          if (!getStop(i).isInitialized()) {
              
            return false;
          }
        }
        return true;
      }
        
      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        while (true) {
          int tag = input.readTag();
          switch (tag) {
            case 0:
                
              return this;
            default: {
              if (!parseUnknownField(input, extensionRegistry, tag)) {
                  
                return this;
              }
              break;
            }
            case 8: {
              bitField0_ |= 0x00000001;
              startTime_ = input.readInt64();
              break;
            }
            case 18: {
              com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point.Builder subBuilder = com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point.newBuilder();
              input.readMessage(subBuilder, extensionRegistry);
              addPoint(subBuilder.buildPartial());
              break;
            }
            case 26: {
              com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop.Builder subBuilder = com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop.newBuilder();
              input.readMessage(subBuilder, extensionRegistry);
              addStop(subBuilder.buildPartial());
              break;
            }
            case 34: {
              bitField0_ |= 0x00000008;
              routeName_ = input.readBytes();
              break;
            }
            case 42: {
              bitField0_ |= 0x00000010;
              routeDescription_ = input.readBytes();
              break;
            }
            case 50: {
              bitField0_ |= 0x00000020;
              routeNotes_ = input.readBytes();
              break;
            }
            case 58: {
              bitField0_ |= 0x00000040;
              vehicleType_ = input.readBytes();
              break;
            }
            case 66: {
              bitField0_ |= 0x00000080;
              vehicleCapacity_ = input.readBytes();
              break;
            }
          }
        }
      }
        
      private int bitField0_;
        
      // required int64 start_time = 1;
      private long startTime_ ;
      public boolean hasStartTime() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      public long getStartTime() {
        return startTime_;
      }
      public Builder setStartTime(long value) {
        bitField0_ |= 0x00000001;
        startTime_ = value;
          
        return this;
      }
      public Builder clearStartTime() {
        bitField0_ = (bitField0_ & ~0x00000001);
        startTime_ = 0L;
          
        return this;
      }
        
      // repeated .transitwand.Upload.Route.Point point = 2;
      private java.util.List<com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point> point_ =
        java.util.Collections.emptyList();
      private void ensurePointIsMutable() {
        if (!((bitField0_ & 0x00000002) == 0x00000002)) {
          point_ = new java.util.ArrayList<com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point>(point_);
          bitField0_ |= 0x00000002;
         }
      }
        
      public java.util.List<com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point> getPointList() {
        return java.util.Collections.unmodifiableList(point_);
      }
      public int getPointCount() {
        return point_.size();
      }
      public com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point getPoint(int index) {
        return point_.get(index);
      }
      public Builder setPoint(
          int index, com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point value) {
        if (value == null) {
          throw new NullPointerException();
        }
        ensurePointIsMutable();
        point_.set(index, value);
          
        return this;
      }
      public Builder setPoint(
          int index, com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point.Builder builderForValue) {
        ensurePointIsMutable();
        point_.set(index, builderForValue.build());
          
        return this;
      }
      public Builder addPoint(com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point value) {
        if (value == null) {
          throw new NullPointerException();
        }
        ensurePointIsMutable();
        point_.add(value);
          
        return this;
      }
      public Builder addPoint(
          int index, com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point value) {
        if (value == null) {
          throw new NullPointerException();
        }
        ensurePointIsMutable();
        point_.add(index, value);
          
        return this;
      }
      public Builder addPoint(
          com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point.Builder builderForValue) {
        ensurePointIsMutable();
        point_.add(builderForValue.build());
          
        return this;
      }
      public Builder addPoint(
          int index, com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point.Builder builderForValue) {
        ensurePointIsMutable();
        point_.add(index, builderForValue.build());
          
        return this;
      }
      public Builder addAllPoint(
          java.lang.Iterable<? extends com.conveyal.transitwand.TransitWandProtos.Upload.Route.Point> values) {
        ensurePointIsMutable();
        super.addAll(values, point_);
          
        return this;
      }
      public Builder clearPoint() {
        point_ = java.util.Collections.emptyList();
        bitField0_ = (bitField0_ & ~0x00000002);
          
        return this;
      }
      public Builder removePoint(int index) {
        ensurePointIsMutable();
        point_.remove(index);
          
        return this;
      }
        
      // repeated .transitwand.Upload.Route.Stop stop = 3;
      private java.util.List<com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop> stop_ =
        java.util.Collections.emptyList();
      private void ensureStopIsMutable() {
        if (!((bitField0_ & 0x00000004) == 0x00000004)) {
          stop_ = new java.util.ArrayList<com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop>(stop_);
          bitField0_ |= 0x00000004;
         }
      }
        
      public java.util.List<com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop> getStopList() {
        return java.util.Collections.unmodifiableList(stop_);
      }
      public int getStopCount() {
        return stop_.size();
      }
      public com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop getStop(int index) {
        return stop_.get(index);
      }
      public Builder setStop(
          int index, com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop value) {
        if (value == null) {
          throw new NullPointerException();
        }
        ensureStopIsMutable();
        stop_.set(index, value);
          
        return this;
      }
      public Builder setStop(
          int index, com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop.Builder builderForValue) {
        ensureStopIsMutable();
        stop_.set(index, builderForValue.build());
          
        return this;
      }
      public Builder addStop(com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop value) {
        if (value == null) {
          throw new NullPointerException();
        }
        ensureStopIsMutable();
        stop_.add(value);
          
        return this;
      }
      public Builder addStop(
          int index, com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop value) {
        if (value == null) {
          throw new NullPointerException();
        }
        ensureStopIsMutable();
        stop_.add(index, value);
          
        return this;
      }
      public Builder addStop(
          com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop.Builder builderForValue) {
        ensureStopIsMutable();
        stop_.add(builderForValue.build());
          
        return this;
      }
      public Builder addStop(
          int index, com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop.Builder builderForValue) {
        ensureStopIsMutable();
        stop_.add(index, builderForValue.build());
          
        return this;
      }
      public Builder addAllStop(
          java.lang.Iterable<? extends com.conveyal.transitwand.TransitWandProtos.Upload.Route.Stop> values) {
        ensureStopIsMutable();
        super.addAll(values, stop_);
          
        return this;
      }
      public Builder clearStop() {
        stop_ = java.util.Collections.emptyList();
        bitField0_ = (bitField0_ & ~0x00000004);
          
        return this;
      }
      public Builder removeStop(int index) {
        ensureStopIsMutable();
        stop_.remove(index);
          
        return this;
      }
        
      // optional string route_name = 4;
      private java.lang.Object routeName_ = "";
      public boolean hasRouteName() {
        return ((bitField0_ & 0x00000008) == 0x00000008);
      }
      public String getRouteName() {
        java.lang.Object ref = routeName_;
        if (!(ref instanceof String)) {
          String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
          routeName_ = s;
          return s;
        } else {
          return (String) ref;
        }
      }
      public Builder setRouteName(String value) {
        if (value == null) {
  throw new NullPointerException();
}
bitField0_ |= 0x00000008;
        routeName_ = value;
          
        return this;
      }
      public Builder clearRouteName() {
        bitField0_ = (bitField0_ & ~0x00000008);
        routeName_ = getDefaultInstance().getRouteName();
          
        return this;
      }
      void setRouteName(com.google.protobuf.ByteString value) {
        bitField0_ |= 0x00000008;
        routeName_ = value;
          
      }
        
      // optional string route_description = 5;
      private java.lang.Object routeDescription_ = "";
      public boolean hasRouteDescription() {
        return ((bitField0_ & 0x00000010) == 0x00000010);
      }
      public String getRouteDescription() {
        java.lang.Object ref = routeDescription_;
        if (!(ref instanceof String)) {
          String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
          routeDescription_ = s;
          return s;
        } else {
          return (String) ref;
        }
      }
      public Builder setRouteDescription(String value) {
        if (value == null) {
  throw new NullPointerException();
}
bitField0_ |= 0x00000010;
        routeDescription_ = value;
          
        return this;
      }
      public Builder clearRouteDescription() {
        bitField0_ = (bitField0_ & ~0x00000010);
        routeDescription_ = getDefaultInstance().getRouteDescription();
          
        return this;
      }
      void setRouteDescription(com.google.protobuf.ByteString value) {
        bitField0_ |= 0x00000010;
        routeDescription_ = value;
          
      }
        
      // optional string route_notes = 6;
      private java.lang.Object routeNotes_ = "";
      public boolean hasRouteNotes() {
        return ((bitField0_ & 0x00000020) == 0x00000020);
      }
      public String getRouteNotes() {
        java.lang.Object ref = routeNotes_;
        if (!(ref instanceof String)) {
          String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
          routeNotes_ = s;
          return s;
        } else {
          return (String) ref;
        }
      }
      public Builder setRouteNotes(String value) {
        if (value == null) {
  throw new NullPointerException();
}
bitField0_ |= 0x00000020;
        routeNotes_ = value;
          
        return this;
      }
      public Builder clearRouteNotes() {
        bitField0_ = (bitField0_ & ~0x00000020);
        routeNotes_ = getDefaultInstance().getRouteNotes();
          
        return this;
      }
      void setRouteNotes(com.google.protobuf.ByteString value) {
        bitField0_ |= 0x00000020;
        routeNotes_ = value;
          
      }
        
      // optional string vehicle_type = 7;
      private java.lang.Object vehicleType_ = "";
      public boolean hasVehicleType() {
        return ((bitField0_ & 0x00000040) == 0x00000040);
      }
      public String getVehicleType() {
        java.lang.Object ref = vehicleType_;
        if (!(ref instanceof String)) {
          String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
          vehicleType_ = s;
          return s;
        } else {
          return (String) ref;
        }
      }
      public Builder setVehicleType(String value) {
        if (value == null) {
  throw new NullPointerException();
}
bitField0_ |= 0x00000040;
        vehicleType_ = value;
          
        return this;
      }
      public Builder clearVehicleType() {
        bitField0_ = (bitField0_ & ~0x00000040);
        vehicleType_ = getDefaultInstance().getVehicleType();
          
        return this;
      }
      void setVehicleType(com.google.protobuf.ByteString value) {
        bitField0_ |= 0x00000040;
        vehicleType_ = value;
          
      }
        
      // optional string vehicle_capacity = 8;
      private java.lang.Object vehicleCapacity_ = "";
      public boolean hasVehicleCapacity() {
        return ((bitField0_ & 0x00000080) == 0x00000080);
      }
      public String getVehicleCapacity() {
        java.lang.Object ref = vehicleCapacity_;
        if (!(ref instanceof String)) {
          String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
          vehicleCapacity_ = s;
          return s;
        } else {
          return (String) ref;
        }
      }
      public Builder setVehicleCapacity(String value) {
        if (value == null) {
  throw new NullPointerException();
}
bitField0_ |= 0x00000080;
        vehicleCapacity_ = value;
          
        return this;
      }
      public Builder clearVehicleCapacity() {
        bitField0_ = (bitField0_ & ~0x00000080);
        vehicleCapacity_ = getDefaultInstance().getVehicleCapacity();
          
        return this;
      }
      void setVehicleCapacity(com.google.protobuf.ByteString value) {
        bitField0_ |= 0x00000080;
        vehicleCapacity_ = value;
          
      }
        
      // @@protoc_insertion_point(builder_scope:transitwand.Upload.Route)
    }
      
    static {
      defaultInstance = new Route(true);
      defaultInstance.initFields();
    }
      
    // @@protoc_insertion_point(class_scope:transitwand.Upload.Route)
  }
    
  private int bitField0_;
  // required int64 unit_id = 1;
  public static final int UNIT_ID_FIELD_NUMBER = 1;
  private long unitId_;
  public boolean hasUnitId() {
    return ((bitField0_ & 0x00000001) == 0x00000001);
  }
  public long getUnitId() {
    return unitId_;
  }
    
  // required int32 upload_id = 2;
  public static final int UPLOAD_ID_FIELD_NUMBER = 2;
  private int uploadId_;
  public boolean hasUploadId() {
    return ((bitField0_ & 0x00000002) == 0x00000002);
  }
  public int getUploadId() {
    return uploadId_;
  }
    
  // repeated .transitwand.Upload.Route route = 3;
  public static final int ROUTE_FIELD_NUMBER = 3;
  private java.util.List<com.conveyal.transitwand.TransitWandProtos.Upload.Route> route_;
  public java.util.List<com.conveyal.transitwand.TransitWandProtos.Upload.Route> getRouteList() {
    return route_;
  }
  public java.util.List<? extends com.conveyal.transitwand.TransitWandProtos.Upload.RouteOrBuilder> 
      getRouteOrBuilderList() {
    return route_;
  }
  public int getRouteCount() {
    return route_.size();
  }
  public com.conveyal.transitwand.TransitWandProtos.Upload.Route getRoute(int index) {
    return route_.get(index);
  }
  public com.conveyal.transitwand.TransitWandProtos.Upload.RouteOrBuilder getRouteOrBuilder(
      int index) {
    return route_.get(index);
  }
    
  private void initFields() {
    unitId_ = 0L;
    uploadId_ = 0;
    route_ = java.util.Collections.emptyList();
  }
  private byte memoizedIsInitialized = -1;
  public final boolean isInitialized() {
    byte isInitialized = memoizedIsInitialized;
    if (isInitialized != -1) return isInitialized == 1;
      
    if (!hasUnitId()) {
      memoizedIsInitialized = 0;
      return false;
    }
    if (!hasUploadId()) {
      memoizedIsInitialized = 0;
      return false;
    }
    for (int i = 0; i < getRouteCount(); i++) {
      if (!getRoute(i).isInitialized()) {
        memoizedIsInitialized = 0;
        return false;
      }
    }
    memoizedIsInitialized = 1;
    return true;
  }
    
  public void writeTo(com.google.protobuf.CodedOutputStream output)
                      throws java.io.IOException {
    getSerializedSize();
    if (((bitField0_ & 0x00000001) == 0x00000001)) {
      output.writeInt64(1, unitId_);
    }
    if (((bitField0_ & 0x00000002) == 0x00000002)) {
      output.writeInt32(2, uploadId_);
    }
    for (int i = 0; i < route_.size(); i++) {
      output.writeMessage(3, route_.get(i));
    }
  }
    
  private int memoizedSerializedSize = -1;
  public int getSerializedSize() {
    int size = memoizedSerializedSize;
    if (size != -1) return size;
    
    size = 0;
    if (((bitField0_ & 0x00000001) == 0x00000001)) {
      size += com.google.protobuf.CodedOutputStream
        .computeInt64Size(1, unitId_);
    }
    if (((bitField0_ & 0x00000002) == 0x00000002)) {
      size += com.google.protobuf.CodedOutputStream
        .computeInt32Size(2, uploadId_);
    }
    for (int i = 0; i < route_.size(); i++) {
      size += com.google.protobuf.CodedOutputStream
        .computeMessageSize(3, route_.get(i));
    }
    memoizedSerializedSize = size;
    return size;
  }
    
  private static final long serialVersionUID = 0L;
  @java.lang.Override
  protected java.lang.Object writeReplace()
      throws java.io.ObjectStreamException {
    return super.writeReplace();
  }
    
  public static com.conveyal.transitwand.TransitWandProtos.Upload parseFrom(
      com.google.protobuf.ByteString data)
      throws com.google.protobuf.InvalidProtocolBufferException {
    return newBuilder().mergeFrom(data).buildParsed();
  }
  public static com.conveyal.transitwand.TransitWandProtos.Upload parseFrom(
      com.google.protobuf.ByteString data,
      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
      throws com.google.protobuf.InvalidProtocolBufferException {
    return newBuilder().mergeFrom(data, extensionRegistry)
             .buildParsed();
  }
  public static com.conveyal.transitwand.TransitWandProtos.Upload parseFrom(byte[] data)
      throws com.google.protobuf.InvalidProtocolBufferException {
    return newBuilder().mergeFrom(data).buildParsed();
  }
  public static com.conveyal.transitwand.TransitWandProtos.Upload parseFrom(
      byte[] data,
      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
      throws com.google.protobuf.InvalidProtocolBufferException {
    return newBuilder().mergeFrom(data, extensionRegistry)
             .buildParsed();
  }
  public static com.conveyal.transitwand.TransitWandProtos.Upload parseFrom(java.io.InputStream input)
      throws java.io.IOException {
    return newBuilder().mergeFrom(input).buildParsed();
  }
  public static com.conveyal.transitwand.TransitWandProtos.Upload parseFrom(
      java.io.InputStream input,
      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
      throws java.io.IOException {
    return newBuilder().mergeFrom(input, extensionRegistry)
             .buildParsed();
  }
  public static com.conveyal.transitwand.TransitWandProtos.Upload parseDelimitedFrom(java.io.InputStream input)
      throws java.io.IOException {
    Builder builder = newBuilder();
    if (builder.mergeDelimitedFrom(input)) {
      return builder.buildParsed();
    } else {
      return null;
    }
  }
  public static com.conveyal.transitwand.TransitWandProtos.Upload parseDelimitedFrom(
      java.io.InputStream input,
      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
      throws java.io.IOException {
    Builder builder = newBuilder();
    if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
      return builder.buildParsed();
    } else {
      return null;
    }
  }
  public static com.conveyal.transitwand.TransitWandProtos.Upload parseFrom(
      com.google.protobuf.CodedInputStream input)
      throws java.io.IOException {
    return newBuilder().mergeFrom(input).buildParsed();
  }
  public static com.conveyal.transitwand.TransitWandProtos.Upload parseFrom(
      com.google.protobuf.CodedInputStream input,
      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
      throws java.io.IOException {
    return newBuilder().mergeFrom(input, extensionRegistry)
             .buildParsed();
  }
    
  public static Builder newBuilder() { return Builder.create(); }
  public Builder newBuilderForType() { return newBuilder(); }
  public static Builder newBuilder(com.conveyal.transitwand.TransitWandProtos.Upload prototype) {
    return newBuilder().mergeFrom(prototype);
  }
  public Builder toBuilder() { return newBuilder(this); }
    
  public static final class Builder extends
      com.google.protobuf.GeneratedMessageLite.Builder<
        com.conveyal.transitwand.TransitWandProtos.Upload, Builder>
      implements com.conveyal.transitwand.TransitWandProtos.UploadOrBuilder {
    // Construct using com.conveyal.transitwand.TransitWandProtos.Upload.newBuilder()
    private Builder() {
      maybeForceBuilderInitialization();
    }
      
    private void maybeForceBuilderInitialization() {
    }
    private static Builder create() {
      return new Builder();
    }
      
    public Builder clear() {
      super.clear();
      unitId_ = 0L;
      bitField0_ = (bitField0_ & ~0x00000001);
      uploadId_ = 0;
      bitField0_ = (bitField0_ & ~0x00000002);
      route_ = java.util.Collections.emptyList();
      bitField0_ = (bitField0_ & ~0x00000004);
      return this;
    }
      
    public Builder clone() {
      return create().mergeFrom(buildPartial());
    }
      
    public com.conveyal.transitwand.TransitWandProtos.Upload getDefaultInstanceForType() {
      return com.conveyal.transitwand.TransitWandProtos.Upload.getDefaultInstance();
    }
      
    public com.conveyal.transitwand.TransitWandProtos.Upload build() {
      com.conveyal.transitwand.TransitWandProtos.Upload result = buildPartial();
      if (!result.isInitialized()) {
        throw newUninitializedMessageException(result);
      }
      return result;
    }
      
    private com.conveyal.transitwand.TransitWandProtos.Upload buildParsed()
        throws com.google.protobuf.InvalidProtocolBufferException {
      com.conveyal.transitwand.TransitWandProtos.Upload result = buildPartial();
      if (!result.isInitialized()) {
        throw newUninitializedMessageException(
          result).asInvalidProtocolBufferException();
      }
      return result;
    }
      
    public com.conveyal.transitwand.TransitWandProtos.Upload buildPartial() {
      com.conveyal.transitwand.TransitWandProtos.Upload result = new com.conveyal.transitwand.TransitWandProtos.Upload(this);
      int from_bitField0_ = bitField0_;
      int to_bitField0_ = 0;
      if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
        to_bitField0_ |= 0x00000001;
      }
      result.unitId_ = unitId_;
      if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
        to_bitField0_ |= 0x00000002;
      }
      result.uploadId_ = uploadId_;
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        route_ = java.util.Collections.unmodifiableList(route_);
        bitField0_ = (bitField0_ & ~0x00000004);
      }
      result.route_ = route_;
      result.bitField0_ = to_bitField0_;
      return result;
    }
      
    public Builder mergeFrom(com.conveyal.transitwand.TransitWandProtos.Upload other) {
      if (other == com.conveyal.transitwand.TransitWandProtos.Upload.getDefaultInstance()) return this;
      if (other.hasUnitId()) {
        setUnitId(other.getUnitId());
      }
      if (other.hasUploadId()) {
        setUploadId(other.getUploadId());
      }
      if (!other.route_.isEmpty()) {
        if (route_.isEmpty()) {
          route_ = other.route_;
          bitField0_ = (bitField0_ & ~0x00000004);
        } else {
          ensureRouteIsMutable();
          route_.addAll(other.route_);
        }
          
      }
      return this;
    }
      
    public final boolean isInitialized() {
      if (!hasUnitId()) {
          
        return false;
      }
      if (!hasUploadId()) {
          
        return false;
      }
      for (int i = 0; i < getRouteCount(); i++) {
        if (!getRoute(i).isInitialized()) {
            
          return false;
        }
      }
      return true;
    }
      
    public Builder mergeFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      while (true) {
        int tag = input.readTag();
        switch (tag) {
          case 0:
              
            return this;
          default: {
            if (!parseUnknownField(input, extensionRegistry, tag)) {
                
              return this;
            }
            break;
          }
          case 8: {
            bitField0_ |= 0x00000001;
            unitId_ = input.readInt64();
            break;
          }
          case 16: {
            bitField0_ |= 0x00000002;
            uploadId_ = input.readInt32();
            break;
          }
          case 26: {
            com.conveyal.transitwand.TransitWandProtos.Upload.Route.Builder subBuilder = com.conveyal.transitwand.TransitWandProtos.Upload.Route.newBuilder();
            input.readMessage(subBuilder, extensionRegistry);
            addRoute(subBuilder.buildPartial());
            break;
          }
        }
      }
    }
      
    private int bitField0_;
      
    // required int64 unit_id = 1;
    private long unitId_ ;
    public boolean hasUnitId() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    public long getUnitId() {
      return unitId_;
    }
    public Builder setUnitId(long value) {
      bitField0_ |= 0x00000001;
      unitId_ = value;
        
      return this;
    }
    public Builder clearUnitId() {
      bitField0_ = (bitField0_ & ~0x00000001);
      unitId_ = 0L;
        
      return this;
    }
      
    // required int32 upload_id = 2;
    private int uploadId_ ;
    public boolean hasUploadId() {
      return ((bitField0_ & 0x00000002) == 0x00000002);
    }
    public int getUploadId() {
      return uploadId_;
    }
    public Builder setUploadId(int value) {
      bitField0_ |= 0x00000002;
      uploadId_ = value;
        
      return this;
    }
    public Builder clearUploadId() {
      bitField0_ = (bitField0_ & ~0x00000002);
      uploadId_ = 0;
        
      return this;
    }
      
    // repeated .transitwand.Upload.Route route = 3;
    private java.util.List<com.conveyal.transitwand.TransitWandProtos.Upload.Route> route_ =
      java.util.Collections.emptyList();
    private void ensureRouteIsMutable() {
      if (!((bitField0_ & 0x00000004) == 0x00000004)) {
        route_ = new java.util.ArrayList<com.conveyal.transitwand.TransitWandProtos.Upload.Route>(route_);
        bitField0_ |= 0x00000004;
       }
    }
      
    public java.util.List<com.conveyal.transitwand.TransitWandProtos.Upload.Route> getRouteList() {
      return java.util.Collections.unmodifiableList(route_);
    }
    public int getRouteCount() {
      return route_.size();
    }
    public com.conveyal.transitwand.TransitWandProtos.Upload.Route getRoute(int index) {
      return route_.get(index);
    }
    public Builder setRoute(
        int index, com.conveyal.transitwand.TransitWandProtos.Upload.Route value) {
      if (value == null) {
        throw new NullPointerException();
      }
      ensureRouteIsMutable();
      route_.set(index, value);
        
      return this;
    }
    public Builder setRoute(
        int index, com.conveyal.transitwand.TransitWandProtos.Upload.Route.Builder builderForValue) {
      ensureRouteIsMutable();
      route_.set(index, builderForValue.build());
        
      return this;
    }
    public Builder addRoute(com.conveyal.transitwand.TransitWandProtos.Upload.Route value) {
      if (value == null) {
        throw new NullPointerException();
      }
      ensureRouteIsMutable();
      route_.add(value);
        
      return this;
    }
    public Builder addRoute(
        int index, com.conveyal.transitwand.TransitWandProtos.Upload.Route value) {
      if (value == null) {
        throw new NullPointerException();
      }
      ensureRouteIsMutable();
      route_.add(index, value);
        
      return this;
    }
    public Builder addRoute(
        com.conveyal.transitwand.TransitWandProtos.Upload.Route.Builder builderForValue) {
      ensureRouteIsMutable();
      route_.add(builderForValue.build());
        
      return this;
    }
    public Builder addRoute(
        int index, com.conveyal.transitwand.TransitWandProtos.Upload.Route.Builder builderForValue) {
      ensureRouteIsMutable();
      route_.add(index, builderForValue.build());
        
      return this;
    }
    public Builder addAllRoute(
        java.lang.Iterable<? extends com.conveyal.transitwand.TransitWandProtos.Upload.Route> values) {
      ensureRouteIsMutable();
      super.addAll(values, route_);
        
      return this;
    }
    public Builder clearRoute() {
      route_ = java.util.Collections.emptyList();
      bitField0_ = (bitField0_ & ~0x00000004);
        
      return this;
    }
    public Builder removeRoute(int index) {
      ensureRouteIsMutable();
      route_.remove(index);
        
      return this;
    }
      
    // @@protoc_insertion_point(builder_scope:transitwand.Upload)
  }
    
  static {
    defaultInstance = new Upload(true);
    defaultInstance.initFields();
  }
    
  // @@protoc_insertion_point(class_scope:transitwand.Upload)
} @JsonIgnoreProperties({"entityId", "persistent"})
@Entity
public class Agency extends Model {
	
	public String gtfsAgencyId;
    public String name;
    public String url;
    public String timezone;
    public String lang;
    public String phone;
    
    public String color;
    
    public Boolean systemMap;
    
    @JsonCreator
    public static Agency factory(long id) {
      return Agency.findById(id);
    }

    @JsonCreator
    public static Agency factory(String id) {
      return Agency.findById(Long.parseLong(id));
    }
    
    public Agency(org.onebusaway.gtfs.model.Agency agency) {
        this.gtfsAgencyId = agency.getId();
        this.name = agency.getName();
        this.url = agency.getUrl();
        this.timezone = agency.getTimezone();
        this.lang = agency.getLang();
        this.phone = agency.getPhone();
    }
    
    public Agency(String gtfsAgencyId, String name, String url, String timezone, String lang, String phone) {
        this.gtfsAgencyId = gtfsAgencyId;
        this.name = name;
        this.url = url;
        this.timezone = timezone;
        this.lang = lang;
        this.phone = phone;
    }

} @JsonIgnoreProperties({"entityId", "persistent"})
@Entity
public class Route extends Model {

	public String gtfsRouteId;
    public String routeShortName;
    public String routeLongName;
    public String routeDesc;
    public String routeNotes;

    @Enumerated(EnumType.STRING)
    public RouteType routeType;

    public String routeUrl;
    public String routeColor;
    public String routeTextColor;
    
    public String vehicleCapacity;
    public String vehicleType;
    
    public Date captureTime;

    // Custom Fields
    public Boolean airCon;
    public String comments;

    public Boolean weekday;
    public Boolean saturday;
    public Boolean sunday;

    @ManyToOne
    public Agency agency;
    
    @ManyToOne
    public Phone phone;


    @JsonCreator
    public static Route factory(long id) {
      return Route.findById(id);
    }

    @JsonCreator
    public static Route factory(String id) {
      return Route.findById(Long.parseLong(id));
    }

    public Route(org.onebusaway.gtfs.model.Route route,  Agency agency) {
        this.gtfsRouteId = route.getId().toString();
        this.routeShortName = route.getShortName();
        this.routeLongName = route.getLongName();
        this.routeDesc = route.getDesc();
        this.routeType = mapGtfsRouteType(route.getType());
        this.routeUrl = route.getUrl();
        this.routeColor = route.getColor();

        this.agency = agency;
    }


    public Route(String routeShortName, String routeLongName, RouteType routeType, String routeDescription,  Agency agency) {
        this.routeShortName = routeShortName;
        this.routeLongName = routeLongName;
        this.routeType = routeType;
        this.routeDesc = routeDescription;

        this.agency = agency;
    }

    public static RouteType mapGtfsRouteType(Integer routeType)
    {
    	switch(routeType)
    	{
    		case 0:
    			return RouteType.TRAM;
    		case 1:
    			return RouteType.SUBWAY;
    		case 2:
    			return RouteType.RAIL;
    		case 3:
    			return RouteType.BUS;
    		case 4:
    			return RouteType.FERRY;
    		case 5:
    			return RouteType.CABLECAR;
    		case 6:
    			return RouteType.GONDOLA;
    		case 7:
    			return RouteType.FUNICULAR;
    		default:
    			return null;

    	}
    }

    public static Integer mapGtfsRouteType(RouteType routeType)
    {
    	switch(routeType)
    	{
    		case TRAM:
    			return 0;
    		case SUBWAY:
    			return 1;
    		case RAIL:
    			return 2;
    		case BUS:
    			return 3;
    		case FERRY:
    			return 4;
    		case CABLECAR:
    			return 5;
    		case GONDOLA:
    			return 6;
    		case FUNICULAR:
    			return 7;
    		default:
    			return null;

    	}
    }

    public static BigInteger nativeInsert(EntityManager em, org.onebusaway.gtfs.model.Route gtfsRoute, BigInteger agencyId)
    {
    	Query idQuery = em().createNativeQuery("SELECT NEXTVAL('hibernate_sequence');");
    	BigInteger nextId = (BigInteger)idQuery.getSingleResult();

        em.createNativeQuery("INSERT INTO route (id, routecolor, routedesc, gtfsrouteid, routelongname, routeshortname, routetextcolor, routetype, routeurl, agency_id)" +
        	"  VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?);")
          .setParameter(1,  nextId)
          .setParameter(2,  gtfsRoute.getColor())
          .setParameter(3,  gtfsRoute.getDesc())
          .setParameter(4,  gtfsRoute.getId().toString())
          .setParameter(5,  gtfsRoute.getLongName())
          .setParameter(6,  gtfsRoute.getShortName())
          .setParameter(7,  gtfsRoute.getTextColor())
          .setParameter(8,  mapGtfsRouteType(gtfsRoute.getType()).name())
          .setParameter(9,  gtfsRoute.getUrl())
          .setParameter(10, agencyId)
          .executeUpdate();

        return nextId;
    }

} @JsonIgnoreProperties({"entityId", "persistent"})
@Entity
public class RoutePoint extends Model {

    @ManyToOne
    public Route route;
    
    public Double lat;
    public Double lon;
    
    public Integer sequence;
    
    public Integer timeOffset;
    
    
    
    public static void addRoutePoint(Upload.Route.Point p, Long routeId, Integer sequence)
    {
    	Query idQuery = RoutePoint.em().createNativeQuery("SELECT NEXTVAL('hibernate_sequence');");
    	BigInteger routePointId = (BigInteger)idQuery.getSingleResult();

	
		Query q = RoutePoint.em().createNativeQuery("INSERT INTO routepoint (id, route_id, sequence, lat, lon, timeoffset)" +
	    	"  VALUES(?, ?, ?, ?, ?, ?);");
		
		q.setParameter(1, routePointId.longValue())
		 .setParameter(2, routeId)
		 .setParameter(3, sequence)
		 .setParameter(4, p.getLat())
		 .setParameter(5, p.getLon())
		 .setParameter(6, p.getTimeoffset());

		q.executeUpdate();

    }
} public enum RouteType {
	TRAM,
	SUBWAY,
	RAIL, 
	BUS, 
	FERRY,
	JEEPNEY,
	CABLECAR,
	GONDOLA,
	FUNICULAR;
} @JsonIgnoreProperties({"entityId", "persistent"})
@Entity
public class Stop extends Model {

    public String gtfsStopId;
    public String stopCode;
    public String stopName;
    public String stopDesc;
    public String zoneId;
    public String stopUrl;
    
    public Integer board;
    public Integer alight;

    @ManyToOne
    public Agency agency;

    @Enumerated(EnumType.STRING)
    public LocationType locationType;

    public String parentStation;
    
    // Major stop is a custom field; it has no corralary in the GTFS.
    public Boolean majorStop;

    @JsonCreator
    public static Stop factory(long id) {
      return Stop.findById(id);
    }

    @JsonCreator
    public static Stop factory(String id) {
      return Stop.findById(Long.parseLong(id));
    }
   
    @Type(type = "org.hibernatespatial.GeometryUserType")
    public Point location;


    public void setLocation(Hashtable<String, Double> loc) {
        GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), 4326);
        this.location = geometryFactory.createPoint(new Coordinate(loc.get("lng"), loc.get("lat")));;
    }

    public Stop(org.onebusaway.gtfs.model.Stop stop, GeometryFactory geometryFactory) {

        this.gtfsStopId = stop.getId().toString();
        this.stopCode = stop.getCode();
        this.stopName = stop.getName();
        this.stopDesc = stop.getDesc();
        this.zoneId = stop.getZoneId();
        this.stopUrl = stop.getUrl();
        this.locationType = stop.getLocationType() == 1 ? LocationType.STATION : LocationType.STOP;
        this.parentStation = stop.getParentStation();

        this.location  =  geometryFactory.createPoint(new Coordinate(stop.getLat(),stop.getLon()));
    }

    public Stop(Agency agency,String stopName,  String stopCode,  String stopUrl, String stopDesc, Double lat, Double lon) {
        this.agency = agency;
        this.stopCode = stopCode;
        this.stopName = stopName;
        this.stopDesc = stopDesc;
        this.stopUrl = stopUrl;
        this.locationType = LocationType.STOP;

        GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), 4326);

        this.location = geometryFactory.createPoint(new Coordinate(lon, lat));;
    }


    public static BigInteger nativeInsert(EntityManager em, org.onebusaway.gtfs.model.Stop gtfsStop)
    {
        Query idQuery = em.createNativeQuery("SELECT NEXTVAL('hibernate_sequence');");
        BigInteger nextId = (BigInteger)idQuery.getSingleResult();

        em.createNativeQuery("INSERT INTO stop (id, locationtype, parentstation, stopcode, stopdesc, gtfsstopid, stopname, stopurl, zoneid, location)" +
            "  VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ST_GeomFromText( ? , 4326));")
          .setParameter(1,  nextId)
          .setParameter(2,  gtfsStop.getLocationType() == 1 ? LocationType.STATION.name() : LocationType.STOP.name())
          .setParameter(3,  gtfsStop.getParentStation())
          .setParameter(4,  gtfsStop.getCode())
          .setParameter(5,  gtfsStop.getDesc())
          .setParameter(6,  gtfsStop.getId().toString())
          .setParameter(7,  gtfsStop.getName())
          .setParameter(8,  gtfsStop.getUrl())
          .setParameter(9,  gtfsStop.getZoneId())
          .setParameter(10,  "POINT(" + gtfsStop.getLon() + " " + gtfsStop.getLat() + ")")
          .executeUpdate();

        return nextId;
    }
    
    public static BigInteger nativeInsert(EntityManager em, Upload.Route.Stop stop)
    {
        Query idQuery = em.createNativeQuery("SELECT NEXTVAL('hibernate_sequence');");
        BigInteger nextId = (BigInteger)idQuery.getSingleResult();

        em.createNativeQuery("INSERT INTO stop (id, location, board, alight)" +
            "  VALUES(?, ST_GeomFromText( ? , 4326), ?, ?);")
          .setParameter(1,  nextId)
          .setParameter(2,  "POINT(" + stop.getLon() + " " + stop.getLat() + ")")
          .setParameter(3,  stop.getBoard())
          .setParameter(4,  stop.getAlight())
          .executeUpdate();

        return nextId;
    }

    public Set<Route> routesServed()
    {
        List<TripPatternStop> stops = TripPatternStop.find("stop = ?", this).fetch();
        HashSet<Route> routes = new HashSet<Route>();

        for(TripPatternStop patternStop : stops)
        {
            if(patternStop.pattern == null)
                continue;

            if(patternStop.pattern.longest != null && patternStop.pattern.longest == true)
                routes.add(patternStop.pattern.route);
        }

        return routes;
    }

    public Set<TripPattern> tripPatternsServed(Boolean weekday, Boolean saturday, Boolean sunday)
    {
        List<TripPatternStop> stops = TripPatternStop.find("stop = ?", this).fetch();
        HashSet<TripPattern> patterns = new HashSet<TripPattern>();

        for(TripPatternStop patternStop : stops)
        {
            if(patternStop.pattern == null)
                continue;

            if(patternStop.pattern.longest == true)
            {
                if((weekday && patternStop.pattern.weekday) || (saturday && patternStop.pattern.saturday) || (sunday && patternStop.pattern.sunday))
                    patterns.add(patternStop.pattern);
            }
        }

        return patterns;
    }
} @JsonIgnoreProperties({"entityId", "persistent"})
@Entity
public class TripPattern extends Model {

    public String name;
    public String headsign;

    @ManyToOne
    public TripShape shape;

    @ManyToOne
    public Route route;

    @JsonManagedReference
    @OneToMany(cascade = CascadeType.ALL)
    public List<TripPatternStop> patternStops;

    public Boolean longest;

    public Boolean weekday;
    public Boolean saturday;
    public Boolean sunday;

    public Boolean useFrequency;

    public Integer startTime;
    public Integer endTime;

    public Integer headway;

    @JsonCreator
    public static TripPattern factory(long id) {
      return TripPattern.findById(id);
    }

    @JsonCreator
    public static TripPattern factory(String id) {
      return TripPattern.findById(Long.parseLong(id));
    }

    public TripPattern()
    {

    }

    public TripPattern(String name, String headsign, TripShape shape, Route route)
    {
    	this.name = name;
    	this.headsign = headsign;
    	this.shape = shape;
    	this.route = route;
    }

    public static BigInteger createFromTrip(EntityManager em, BigInteger tripId)
    {
    	Trip trip = Trip.findById(tripId.longValue());

    	Query idQuery = em.createNativeQuery("SELECT NEXTVAL('hibernate_sequence');");
		BigInteger tripPatternId = (BigInteger)idQuery.getSingleResult();

		Query q;

		if(trip.shape != null)
			q = em.createNativeQuery("INSERT INTO trippattern (id, name, route_id, headsign, shape_id)" +
	    	"  VALUES(?, ?, ?, ?, ?);");
		else
			q = em.createNativeQuery("INSERT INTO trippattern (id, name, route_id, headsign)" +
			    	"  VALUES(?, ?, ?, ?);");

	      q.setParameter(1,  tripPatternId.longValue())
	      .setParameter(2,  trip.route.routeShortName + " (" + trip.tripHeadsign + ")")
	      .setParameter(3,  trip.route.id)
	      .setParameter(4,  trip.tripHeadsign);

	      if(trip.shape != null)
	       q.setParameter(5,  trip.shape.id);

	      q.executeUpdate();


    	ArrayList<StopTime> stopTimes = trip.getStopTimes();

    	Integer previousDepartureTime = 0;
    	Double previousDistance = new Double(0);

    	Boolean firstStop = true;

    	for(StopTime stopTime : stopTimes)
    	{
    		BigInteger tripPatternStopId = (BigInteger)idQuery.getSingleResult();

    		q = em.createNativeQuery("INSERT INTO trippatternstop (id, pattern_id, stop_id, stopsequence, defaultdwelltime, defaultdistance, defaulttraveltime)" +
	    	"  VALUES(?, ?, ?, ?, ?, ?, ?);");

    		q.setParameter(1,  tripPatternStopId.longValue());
    		q.setParameter(2,  tripPatternId.longValue());
    		q.setParameter(3,  stopTime.stop.id);
    		q.setParameter(4,  stopTime.stopSequence);
    		q.setParameter(5,  stopTime.departureTime - stopTime.arrivalTime);

    		if(firstStop)
    		{
    			previousDepartureTime = stopTime.departureTime;

    			q.setParameter(6,  new Double(0));
    			q.setParameter(7,  0);

    			firstStop = false;
    		}
    		else
    		{
    			q.setParameter(6,  stopTime.shapeDistTraveled - previousDistance);
    			q.setParameter(7,  stopTime.arrivalTime - previousDepartureTime);

    			previousDepartureTime = stopTime.departureTime;
    			previousDistance = stopTime.shapeDistTraveled;
    		}

    		q.executeUpdate();
    	}

    	Logger.info("Adding trip pattern: " + trip.route.routeShortName + " (" + trip.tripHeadsign + ")");

    	return tripPatternId;
    }
} @JsonIgnoreProperties({"entityId", "persistent"})
@Entity
public class TripPatternStop extends Model {

	@JsonBackReference
	@ManyToOne
    public TripPattern pattern;

	@ManyToOne
    public Stop stop;

	public Integer stopSequence;

	public Double defaultDistance;

	public Integer defaultTravelTime;
	public Integer defaultDwellTime;

	public Integer board;
	public Integer alight;
	

	public TripPatternStop()
	{

	}

	public TripPatternStop(TripPattern pattern, Stop stop,  Integer stopSequence, Integer defaultTravelTime)
	{
		this.pattern = pattern;
		this.stop = stop;
		this.stopSequence = stopSequence;
		this.defaultTravelTime = defaultTravelTime;

		this.defaultDistance = 0.0;
	}
} @Entity
public class TripShape extends Model {
	
    public String gtfsShapeId;
    public String description;
    
    public Double describedDistance;
    
    @ManyToOne
    public Agency agency;
    
    @Type(type = "org.hibernatespatial.GeometryUserType") 
    public LineString shape;
    
    @Type(type = "org.hibernatespatial.GeometryUserType") 
    public LineString simpleShape;
    
    
    public static BigInteger nativeInsert(EntityManager em, String shapeId, String shape, Double distance)
    {
    	Query idQuery = em.createNativeQuery("SELECT NEXTVAL('hibernate_sequence');");
    	BigInteger nextId = (BigInteger)idQuery.getSingleResult();
    	
        em.createNativeQuery("INSERT INTO tripshape (id, gtfsshapeid, shape, describeddistance)" +
        	"  VALUES(?, ?, ST_Simplify(ST_GeomFromText( ?, 4326), 0.0001), ?);")
          .setParameter(1,  nextId)
          .setParameter(2,  shapeId)	            
          .setParameter(3,  shape)
          .setParameter(4,  distance)
          .executeUpdate();
        
        return nextId;
    }
   
}
import play.*;
import play.mvc.*;
import utils.DirectoryZip;
import utils.TripPatternSerializer;
import utils.TripPatternShapeSerializer;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.persistence.EntityManager;
import jobs.ProcessGisExport;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import au.com.bytecode.opencsv.CSVWriter;
import com.conveyal.transitwand.TransitWandProtos.Upload;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import models.*;
import models.transit.Agency;
import models.transit.Route;
import models.transit.RoutePoint;
import models.transit.RouteType;
import models.transit.Stop;
import models.transit.TripPattern;
import models.transit.TripPatternStop;
import models.transit.TripShape;
package controllers;









public class Application extends Controller {

	
    public static void index(Boolean invalid) {
        render(invalid);
    }
    
    public static void export(String unitId) throws InterruptedException {

        Phone p = Phone.find("unitId = ?", unitId).first();

        List<TripPattern> tripPatterns =  TripPattern.find("route.phone = ?", p).fetch();