Package org.onebusaway.transit_data_federation.bundle.tasks

Source Code of org.onebusaway.transit_data_federation.bundle.tasks.GtfsMultiReaderImpl$EntityCounter

/**
* Copyright (C) 2011 Brian Ferris <bdferris@onebusaway.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*         http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onebusaway.transit_data_federation.bundle.tasks;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.onebusaway.collections.Counter;
import org.onebusaway.csv_entities.EntityHandler;
import org.onebusaway.gtfs.impl.GenericMutableDaoWrapper;
import org.onebusaway.gtfs.model.Agency;
import org.onebusaway.gtfs.model.IdentityBean;
import org.onebusaway.gtfs.model.ShapePoint;
import org.onebusaway.gtfs.serialization.GtfsReader;
import org.onebusaway.gtfs.services.GenericMutableDao;
import org.onebusaway.transit_data_federation.bundle.services.EntityReplacementStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Supports reading from multiple {@link GtfsReader} instances sequentially with
* respect to GTFS entity classes. That is to say, given three readers A, B, and
* C, all {@link Agency} entities will be read from A, B, and C in turn, and
* then all {@link ShapePoint} entities will be read from A, B, and C in turn,
* and so forth. This sequential reading scheme allows for cases where two
* separate feeds may have cross-feed references (ex. StopTime => Stop) as
* facilitated by the use of an {@link EntityReplacementStrategy}.
*
* @author bdferris
* @see EntityReplacementStrategy
* @see GtfsReader
* @see GtfsReadingSupport
*/
public class GtfsMultiReaderImpl implements Runnable {

  private final Logger _log = LoggerFactory.getLogger(GtfsMultiReaderImpl.class);

  private List<GtfsReader> _readers = new ArrayList<GtfsReader>();

  private GenericMutableDao _store;

  private EntityReplacementStrategy _entityReplacementStrategy = new EntityReplacementStrategyImpl();

  public void setStore(GenericMutableDao store) {
    _store = store;
  }

  public void setEntityReplacementStrategy(EntityReplacementStrategy strategy) {
    _entityReplacementStrategy = strategy;
  }

  public void addGtfsReader(GtfsReader reader) {
    _readers.add(reader);
  }

  public void addGtfsReaderFromInputLocation(File inputLocation)
      throws IOException {
    GtfsReader reader = new GtfsReader();
    reader.setInputLocation(inputLocation);
    addGtfsReader(reader);
  }

  @Override
  public void run() {

    if (_readers.isEmpty())
      return;

    try {

      StoreImpl store = new StoreImpl(_store);

      for (GtfsReader reader : _readers) {
        reader.setEntityStore(store);
        reader.addEntityHandler(new EntityCounter());
      }

      store.open();

      List<Agency> agencies = new ArrayList<Agency>();
      List<Class<?>> entityClasses = _readers.get(0).getEntityClasses();

      for (Class<?> entityClass : entityClasses) {
        _log.info("reading entities: " + entityClass.getName());

        for (GtfsReader reader : _readers) {

          // Pre-load the agencies, since one agency can be mentioned across
          // multiple feeds
          if (entityClass.equals(Agency.class))
            reader.setAgencies(agencies);

          reader.readEntities(entityClass);

          if (entityClass.equals(Agency.class))
            agencies = new ArrayList<Agency>(reader.getAgencies());

          store.flush();
        }
      }

      store.close();

    } catch (IOException ex) {
      ex.printStackTrace();
    }
  }

  /****
   * Private Methods
   ****/
 
  /**
   * Custom {@link GenericMutableDao} instance that intercepts methods so that
   * the entity replacement strategy can be applied.
   */
  private class StoreImpl extends GenericMutableDaoWrapper {

    public StoreImpl(GenericMutableDao source) {
      super(source);
    }

    @Override
    public <T> T getEntityForId(Class<T> type, Serializable id) {

      Serializable replacementId = _entityReplacementStrategy.getReplacementEntityId(
          type, id);

      if (replacementId != null) {

        T entity = super.getEntityForId(type, replacementId);

        if (entity != null)
          return entity;

        _log.warn("error replacing entity: type=" + type.getName() + " fromId="
            + id + " toId=" + replacementId + " - replacement not found");
      }
      return super.getEntityForId(type, id);
    }

    @Override
    public void saveEntity(Object entity) {

      Class<? extends Object> entityType = entity.getClass();
      if (entity instanceof IdentityBean<?>
          && _entityReplacementStrategy.hasReplacementEntities(entityType)) {
        IdentityBean<?> bean = (IdentityBean<?>) entity;
        Serializable id = bean.getId();
        if (_entityReplacementStrategy.hasReplacementEntity(entityType, id))
          return;
      }

      super.saveEntity(entity);
    }
  }

  private static class EntityCounter implements EntityHandler {

    private Counter<String> _counter = new Counter<String>();

    private Map<String, Long> _startTime = new HashMap<String, Long>();

    public void handleEntity(Object bean) {
      String name = bean.getClass().getName();
      int index = name.lastIndexOf('.');
      if (index != -1)
        name = name.substring(index + 1);
      increment(name);
    }

    private void increment(String key) {
      _counter.increment(key);
      int c = _counter.getCount(key);
      if (c % 1000 == 0) {
        double ellapsedTime = (System.currentTimeMillis() - getStartTimeForKey(key)) / 1000.0;
        System.out.println(key + " = " + c + " rate="
            + ((long) (c / ellapsedTime)));
      }
    }

    private long getStartTimeForKey(String key) {
      Long value = _startTime.get(key);
      if (value == null) {
        value = System.currentTimeMillis();
        _startTime.put(key, value);
      }
      return value;
    }
  }
}
TOP

Related Classes of org.onebusaway.transit_data_federation.bundle.tasks.GtfsMultiReaderImpl$EntityCounter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.