<commit_before>package foodtruck.schedule;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.annotation.Nullable;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.gdata.client.calendar.CalendarQuery;
import com.google.gdata.client.calendar.CalendarService;
import com.google.gdata.data.DateTime;
import com.google.gdata.data.calendar.CalendarEventEntry;
import com.google.gdata.data.calendar.CalendarEventFeed;
import com.google.gdata.data.extensions.When;
import com.google.gdata.data.extensions.Where;
import com.google.gdata.util.ServiceException;
import com.google.inject.Inject;

import org.joda.time.DateTimeZone;
import org.joda.time.Interval;

import foodtruck.dao.TruckDAO;
import foodtruck.geolocation.GeoLocator;
import foodtruck.geolocation.GeolocationGranularity;
import foodtruck.model.Location;
import foodtruck.model.Truck;
import foodtruck.model.TruckStop;
import foodtruck.monitoring.Monitored;
import static foodtruck.schedule.TimeUtils.toJoda;

/**
 * Uses a google calendar feed to load a truck's schedule.
 * @author <EMAIL>
 * @since 8/27/11
 */
public class GoogleCalendar implements ScheduleStrategy {
  private static final Logger log = Logger.getLogger(GoogleCalendar.class.getName());
  private final static int MAX_TRIES = 3;
  private final CalendarService calendarService;
  private final CalendarQueryFactory queryFactory;
  private final DateTimeZone defaultZone;
  private final GeoLocator geolocator;
  private final TruckDAO truckDAO;
  private final AddressExtractor addressExtractor;

  @Inject
  public GoogleCalendar(CalendarService calendarService,
      CalendarQueryFactory queryFactory, DateTimeZone defaultZone, GeoLocator geolocator,
      TruckDAO truckDAO, AddressExtractor addressExtractor) {
    this.calendarService = calendarService;
    this.queryFactory = queryFactory;
    this.defaultZone = defaultZone;
    this.geolocator = geolocator;
    this.truckDAO = truckDAO;
    this.addressExtractor = addressExtractor;
  }

  // TODO: rewrite this...its awfully crappy
  @Override @Monitored
  public List<TruckStop> findForTime(Interval range, @Nullable Truck searchTruck) {
    CalendarQuery query = queryFactory.create();
    String truckId = searchTruck == null ? null : searchTruck.getId();
    log.info("Initiating calendar search " + truckId);
    List<TruckStop> stops = performTruckSearch(range, searchTruck, query, false);
    stops = Lists.newLinkedList(stops);
    if (searchTruck != null && !Strings.isNullOrEmpty(searchTruck.getCalendarUrl())) {
      customCalendarSearch(range, searchTruck, stops, searchTruck);
    } else if (searchTruck == null) {
      for (Truck truck : truckDAO.findTrucksWithCalendars()) {
        customCalendarSearch(range, truck, stops, truck);
      }
    }
    return stops;
  }

  private void customCalendarSearch(Interval range, Truck searchTruck, List<TruckStop> stops,
      Truck truck) {
    try {
      final String calendarUrl = truck.getCalendarUrl();
      if (calendarUrl == null || !calendarUrl.startsWith("http")) {
        return;
      }
      log.info("Custom calendar search: " + calendarUrl);
      stops.addAll(performTruckSearch(range, searchTruck,
          queryFactory.create(new URL(calendarUrl)), true));
    } catch (MalformedURLException e) {
      log.warning(e.getMessage());
    }
  }

  private List<TruckStop> performTruckSearch(Interval range, Truck searchTruck,
      CalendarQuery query, boolean customCalendar) {
    query.setMinimumStartTime(new DateTime(range.getStart().toDate(),
        defaultZone.toTimeZone()));
    query.setMaximumStartTime(new DateTime(range.getEnd().toDate(),
        defaultZone.toTimeZone()));
    query.setMaxResults(1000);
    if (searchTruck != null && !customCalendar) {
      query.setFullTextQuery(searchTruck.getId());
    }
    query.setStringCustomParameter("singleevents", "true");
    ImmutableList.Builder<TruckStop> builder = ImmutableList.builder();
    try {
      CalendarEventFeed resultFeed = calendarQuery(query);
      for (CalendarEventEntry entry : resultFeed.getEntries()) {
        final String titleText = entry.getTitle().getPlainText();
        Truck truck = (searchTruck != null) ? searchTruck :
            truckDAO.findById(titleText);
        if (truck == null) {
          continue;
        }
        Where where = Iterables.getFirst(entry.getLocations(), null);
        if (where == null) {
          throw new IllegalStateException("No location specified");<commit_msg>Blank title was causing calendar recache to blow out<commit_after>package foodtruck.schedule;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.annotation.Nullable;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.gdata.client.calendar.CalendarQuery;
import com.google.gdata.client.calendar.CalendarService;
import com.google.gdata.data.DateTime;
import com.google.gdata.data.Link;
import com.google.gdata.data.calendar.CalendarEventEntry;
import com.google.gdata.data.calendar.CalendarEventFeed;
import com.google.gdata.data.extensions.When;
import com.google.gdata.data.extensions.Where;
import com.google.gdata.util.ServiceException;
import com.google.inject.Inject;

import org.joda.time.DateTimeZone;
import org.joda.time.Interval;

import foodtruck.dao.TruckDAO;
import foodtruck.geolocation.GeoLocator;
import foodtruck.geolocation.GeolocationGranularity;
import foodtruck.model.Location;
import foodtruck.model.Truck;
import foodtruck.model.TruckStop;
import foodtruck.monitoring.Monitored;
import static foodtruck.schedule.TimeUtils.toJoda;

/**
 * Uses a google calendar feed to load a truck's schedule.
 * @author <EMAIL>
 * @since 8/27/11
 */
public class GoogleCalendar implements ScheduleStrategy {
  private static final Logger log = Logger.getLogger(GoogleCalendar.class.getName());
  private final static int MAX_TRIES = 3;
  private final CalendarService calendarService;
  private final CalendarQueryFactory queryFactory;
  private final DateTimeZone defaultZone;
  private final GeoLocator geolocator;
  private final TruckDAO truckDAO;
  private final AddressExtractor addressExtractor;

  @Inject
  public GoogleCalendar(CalendarService calendarService,
      CalendarQueryFactory queryFactory, DateTimeZone defaultZone, GeoLocator geolocator,
      TruckDAO truckDAO, AddressExtractor addressExtractor) {
    this.calendarService = calendarService;
    this.queryFactory = queryFactory;
    this.defaultZone = defaultZone;
    this.geolocator = geolocator;
    this.truckDAO = truckDAO;
    this.addressExtractor = addressExtractor;
  }

  // TODO: rewrite this...its awfully crappy
  @Override @Monitored
  public List<TruckStop> findForTime(Interval range, @Nullable Truck searchTruck) {
    CalendarQuery query = queryFactory.create();
    String truckId = searchTruck == null ? null : searchTruck.getId();
    log.info("Initiating calendar search " + truckId);
    List<TruckStop> stops = performTruckSearch(range, searchTruck, query, false);
    stops = Lists.newLinkedList(stops);
    if (searchTruck != null && !Strings.isNullOrEmpty(searchTruck.getCalendarUrl())) {
      customCalendarSearch(range, searchTruck, stops, searchTruck);
    } else if (searchTruck == null) {
      for (Truck truck : truckDAO.findTrucksWithCalendars()) {
        customCalendarSearch(range, truck, stops, truck);
      }
    }
    return stops;
  }

  private void customCalendarSearch(Interval range, Truck searchTruck, List<TruckStop> stops,
      Truck truck) {
    try {
      final String calendarUrl = truck.getCalendarUrl();
      if (calendarUrl == null || !calendarUrl.startsWith("http")) {
        return;
      }
      log.info("Custom calendar search: " + calendarUrl);
      stops.addAll(performTruckSearch(range, searchTruck,
          queryFactory.create(new URL(calendarUrl)), true));
    } catch (MalformedURLException e) {
      log.warning(e.getMessage());
    }
  }

  private List<TruckStop> performTruckSearch(Interval range, Truck searchTruck,
      CalendarQuery query, boolean customCalendar) {
    query.setMinimumStartTime(new DateTime(range.getStart().toDate(),
        defaultZone.toTimeZone()));
    query.setMaximumStartTime(new DateTime(range.getEnd().toDate(),
        defaultZone.toTimeZone()));
    query.setMaxResults(1000);
    if (searchTruck != null && !customCalendar) {
      query.setFullTextQuery(searchTruck.getId());
    }
    query.setStringCustomParameter("singleevents", "true");
    ImmutableList.Builder<TruckStop> builder = ImmutableList.builder();
    try {
      CalendarEventFeed resultFeed = calendarQuery(query);
      for (CalendarEventEntry entry : resultFeed.getEntries()) {
        final String titleText = entry.getTitle().getPlainText();
        if (Strings.isNullOrEmpty(titleText) && searchTruck == null) {
          Link htmlLink = entry.getHtmlLink();
          String entryString = (htmlLink == null) ? entry.getId() : htmlLink.getHref();
          log.log(Level.WARNING, "Could not find title text for {0}", new Object[] { entryString });
        }
        Truck truck = (searchTruck != null || Strings.isNullOrEmpty(titleText)) ? searchTruck :
            truckDAO.findById(titleText);
        if (truck == null) {
          continue;
        }
        Where where = Iterables.getFirst(entry.getLocations(), null);
        if (where == null) {
          throw new IllegalStateException("No location specified");
{'fraction_non_alphanumeric': 0.10313539671337836, 'fraction_numerical': 0.002117148906139732, 'mean_word_length': 4.2737905369484315, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1211956', 'n_tokens_mistral': 2957, 'n_tokens_neox': 2858, 'n_words': 624}