public MultiSourceSelect(
     Map<QualifiedName, AnalyzedRelation> sources,
     List<OutputName> outputNames,
     QuerySpec querySpec) {
   assert sources.size() > 1 : "MultiSourceSelect requires at least 2 relations";
   this.querySpec = querySpec;
   this.sources = new LinkedHashMap<>(sources.size());
   this.splitter = initSources(sources);
   assert outputNames.size() == querySpec.outputs().size()
       : "size of outputNames and outputSymbols must match";
   fields = new ArrayList<>(outputNames.size());
   for (int i = 0; i < outputNames.size(); i++) {
     fields.add(new Field(this, outputNames.get(i), querySpec.outputs().get(i).valueType()));
   }
 }
 private boolean queueQuery(QuerySpec queryData) {
   queryData.searchQuery = mSearchQuery;
   Boolean queuedQuery;
   synchronized (mQueryQueue) {
     queuedQuery = false;
     Boolean doQueryNow = mQueryQueue.isEmpty();
     mQueryQueue.add(queryData);
     queuedQuery = true;
     if (doQueryNow) {
       doQuery(queryData);
     }
   }
   return queuedQuery;
 }
Example #3
0
  /** {@inheritDoc} */
  public java.util.List<Object> query(QuerySpec qs) {
    java.util.List<Object> ret = null;
    java.util.List<Object> list = _list;

    if (isDerived() && !isActive()) {
      list = deriveContent();
    }

    synchronized (list) {
      // If no max items set, or list size is smaller than the max
      // size, and the style is normal, then just copy
      if ((qs.getMaxItems() == 0 || qs.getMaxItems() >= list.size())
          && qs.getStyle() == Style.Normal) {
        ret = new java.util.ArrayList<Object>(list);
      } else {
        int start = 0;
        int end = list.size();

        if (qs.getMaxItems() > 0 && qs.getMaxItems() <= list.size()) {
          if (qs.getTruncate() == Truncate.End) {
            end = qs.getMaxItems();
          } else {
            start = list.size() - qs.getMaxItems();
          }
        }

        ret = new java.util.ArrayList<Object>();

        if (qs.getStyle() == Style.Reversed) {
          for (int i = end - 1; i >= start; i--) {
            ret.add(list.get(i));
          }
        } else {
          for (int i = start; i < end; i++) {
            ret.add(list.get(i));
          }
        }
      }
    }

    return (ret);
  }
 private boolean queueQuery(
     int start, int end, Time goToTime, String searchQuery, int queryType, long id) {
   QuerySpec queryData = new QuerySpec(queryType);
   queryData.goToTime = new Time(goToTime); // Creates a new time reference per QuerySpec.
   queryData.start = start;
   queryData.end = end;
   queryData.searchQuery = searchQuery;
   queryData.id = id;
   return queueQuery(queryData);
 }
 public void normalize(EvaluatingNormalizer normalizer) {
   querySpec.normalize(normalizer);
 }
    @Override
    protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
      if (DEBUGLOG) {
        Log.d(TAG, "(+)onQueryComplete");
      }
      QuerySpec data = (QuerySpec) cookie;

      if (cursor == null) {
        if (mAgendaListView != null && mAgendaListView.getContext() instanceof Activity) {
          ((Activity) mAgendaListView.getContext()).finish();
        }
        return;
      }

      if (BASICLOG) {
        long queryEndMillis = System.nanoTime();
        Log.e(
            TAG,
            "Query time(ms): "
                + (queryEndMillis - data.queryStartMillis) / 1000000
                + " Count: "
                + cursor.getCount());
      }

      if (data.queryType == QUERY_TYPE_CLEAN) {
        mCleanQueryInitiated = false;
      }

      if (mShuttingDown) {
        cursor.close();
        return;
      }

      // Notify Listview of changes and update position
      int cursorSize = cursor.getCount();
      if (cursorSize > 0 || mAdapterInfos.isEmpty() || data.queryType == QUERY_TYPE_CLEAN) {
        final int listPositionOffset = processNewCursor(data, cursor);
        int newPosition = -1;
        if (data.goToTime == null) { // Typical Scrolling type query
          notifyDataSetChanged();
          if (listPositionOffset != 0) {
            mAgendaListView.shiftSelection(listPositionOffset);
          }
        } else { // refresh() called. Go to the designated position
          final Time goToTime = data.goToTime;
          notifyDataSetChanged();
          newPosition = findEventPositionNearestTime(goToTime, data.id);
          if (newPosition >= 0) {
            if (mListViewScrollState == OnScrollListener.SCROLL_STATE_FLING) {
              mAgendaListView.smoothScrollBy(0, 0);
            }
            mAgendaListView.setSelectionFromTop(newPosition + OFF_BY_ONE_BUG, mStickyHeaderSize);
            Time actualTime = new Time(mTimeZone);
            actualTime.set(goToTime);
            if (DEBUGLOG) {
              Log.d(TAG, "onQueryComplete: Updating title...");
            }
            CalendarController.getInstance(mContext)
                .sendEvent(
                    this, EventType.UPDATE_TITLE, actualTime, actualTime, -1, ViewType.CURRENT);
          }
          if (DEBUGLOG) {
            Log.e(
                TAG,
                "Setting listview to "
                    + "findEventPositionNearestTime: "
                    + (newPosition + OFF_BY_ONE_BUG));
          }
        }

        // Make sure we change the selected instance Id only on a clean query and we
        // do not have one set already
        if (mSelectedInstanceId == -1 && newPosition != -1 && data.queryType == QUERY_TYPE_CLEAN) {
          if (data.id != -1 || data.goToTime != null) {
            mSelectedInstanceId = findInstanceIdFromPosition(newPosition);
          }
        }

        // size == 1 means a fresh query. Possibly after the data changed.
        // Let's check whether mSelectedInstanceId is still valid.
        if (mAdapterInfos.size() == 1 && mSelectedInstanceId != -1) {
          boolean found = false;
          cursor.moveToPosition(-1);
          while (cursor.moveToNext()) {
            if (mSelectedInstanceId == cursor.getLong(AgendaWindowAdapter.INDEX_INSTANCE_ID)) {
              found = true;
              break;
            }
          }
          ;

          if (!found) {
            mSelectedInstanceId = -1;
          }
        }

        // Show the requested event
        if (mShowEventOnStart && data.queryType == QUERY_TYPE_CLEAN) {
          Cursor tempCursor = null;
          int tempCursorPosition = -1;

          // If no valid event is selected , just pick the first one
          if (mSelectedInstanceId == -1) {
            if (cursor.moveToFirst()) {
              mSelectedInstanceId = cursor.getLong(AgendaWindowAdapter.INDEX_INSTANCE_ID);
              // Set up a dummy view holder so we have the right all day
              // info when the view is created.
              // TODO determine the full set of what might be useful to
              // know about the selected view and fill it in.
              mSelectedVH = new AgendaAdapter.ViewHolder();
              mSelectedVH.allDay = cursor.getInt(AgendaWindowAdapter.INDEX_ALL_DAY) != 0;
              tempCursor = cursor;
            }
          } else if (newPosition != -1) {
            tempCursor = getCursorByPosition(newPosition);
            tempCursorPosition = getCursorPositionByPosition(newPosition);
          }
          if (tempCursor != null) {
            AgendaItem item = buildAgendaItemFromCursor(tempCursor, tempCursorPosition, false);
            long selectedTime = findStartTimeFromPosition(newPosition);
            if (DEBUGLOG) {
              Log.d(TAG, "onQueryComplete: Sending View Event...");
            }
            sendViewEvent(item, selectedTime);
          }
        }
      } else {
        cursor.close();
      }

      // Update header and footer
      if (!mDoneSettingUpHeaderFooter) {
        OnClickListener headerFooterOnClickListener =
            new OnClickListener() {
              public void onClick(View v) {
                if (v == mHeaderView) {
                  queueQuery(new QuerySpec(QUERY_TYPE_OLDER));
                } else {
                  queueQuery(new QuerySpec(QUERY_TYPE_NEWER));
                }
              }
            };
        mHeaderView.setOnClickListener(headerFooterOnClickListener);
        mFooterView.setOnClickListener(headerFooterOnClickListener);
        mAgendaListView.addFooterView(mFooterView);
        mDoneSettingUpHeaderFooter = true;
      }
      synchronized (mQueryQueue) {
        int totalAgendaRangeStart = -1;
        int totalAgendaRangeEnd = -1;

        if (cursorSize != 0) {
          // Remove the query that just completed
          QuerySpec x = mQueryQueue.poll();
          if (BASICLOG && !x.equals(data)) {
            Log.e(TAG, "onQueryComplete - cookie != head of queue");
          }
          mEmptyCursorCount = 0;
          if (data.queryType == QUERY_TYPE_NEWER) {
            mNewerRequestsProcessed++;
          } else if (data.queryType == QUERY_TYPE_OLDER) {
            mOlderRequestsProcessed++;
          }

          totalAgendaRangeStart = mAdapterInfos.getFirst().start;
          totalAgendaRangeEnd = mAdapterInfos.getLast().end;
        } else { // CursorSize == 0
          QuerySpec querySpec = mQueryQueue.peek();

          // Update Adapter Info with new start and end date range
          if (!mAdapterInfos.isEmpty()) {
            DayAdapterInfo first = mAdapterInfos.getFirst();
            DayAdapterInfo last = mAdapterInfos.getLast();

            if (first.start - 1 <= querySpec.end && querySpec.start < first.start) {
              first.start = querySpec.start;
            }

            if (querySpec.start <= last.end + 1 && last.end < querySpec.end) {
              last.end = querySpec.end;
            }

            totalAgendaRangeStart = first.start;
            totalAgendaRangeEnd = last.end;
          } else {
            totalAgendaRangeStart = querySpec.start;
            totalAgendaRangeEnd = querySpec.end;
          }

          // Update query specification with expanded search range
          // and maybe rerun query
          switch (querySpec.queryType) {
            case QUERY_TYPE_OLDER:
              totalAgendaRangeStart = querySpec.start;
              querySpec.start -= MAX_QUERY_DURATION;
              break;
            case QUERY_TYPE_NEWER:
              totalAgendaRangeEnd = querySpec.end;
              querySpec.end += MAX_QUERY_DURATION;
              break;
            case QUERY_TYPE_CLEAN:
              totalAgendaRangeStart = querySpec.start;
              totalAgendaRangeEnd = querySpec.end;
              querySpec.start -= MAX_QUERY_DURATION / 2;
              querySpec.end += MAX_QUERY_DURATION / 2;
              break;
          }

          if (++mEmptyCursorCount > RETRIES_ON_NO_DATA) {
            // Nothing in the cursor again. Dropping query
            mQueryQueue.poll();
          }
        }

        updateHeaderFooter(totalAgendaRangeStart, totalAgendaRangeEnd);

        // Go over the events and mark the first day after yesterday
        // that has events in it
        // If the range of adapters doesn't include yesterday, skip marking it since it will
        // mark the first day in the adapters.
        synchronized (mAdapterInfos) {
          DayAdapterInfo info = mAdapterInfos.getFirst();
          Time time = new Time(mTimeZone);
          long now = System.currentTimeMillis();
          time.set(now);
          int JulianToday = Time.getJulianDay(now, time.gmtoff);
          if (info != null
              && JulianToday >= info.start
              && JulianToday <= mAdapterInfos.getLast().end) {
            Iterator<DayAdapterInfo> iter = mAdapterInfos.iterator();
            boolean foundDay = false;
            while (iter.hasNext() && !foundDay) {
              info = iter.next();
              for (int i = 0; i < info.size; i++) {
                if (info.dayAdapter.findJulianDayFromPosition(i) >= JulianToday) {
                  info.dayAdapter.setAsFirstDayAfterYesterday(i);
                  foundDay = true;
                  break;
                }
              }
            }
          }
        }

        // Fire off the next query if any
        Iterator<QuerySpec> it = mQueryQueue.iterator();
        while (it.hasNext()) {
          QuerySpec queryData = it.next();
          if (queryData.queryType == QUERY_TYPE_CLEAN
              || !isInRange(queryData.start, queryData.end)) {
            // Query accepted
            if (DEBUGLOG) Log.e(TAG, "Query accepted. QueueSize:" + mQueryQueue.size());
            doQuery(queryData);
            break;
          } else {
            // Query rejected
            it.remove();
            if (DEBUGLOG) Log.e(TAG, "Query rejected. QueueSize:" + mQueryQueue.size());
          }
        }
      }
      if (BASICLOG) {
        for (DayAdapterInfo info3 : mAdapterInfos) {
          Log.e(TAG, "> " + info3.toString());
        }
      }
    }
  private void doQuery(QuerySpec queryData) {
    if (!mAdapterInfos.isEmpty()) {
      int start = mAdapterInfos.getFirst().start;
      int end = mAdapterInfos.getLast().end;
      int queryDuration = calculateQueryDuration(start, end);
      switch (queryData.queryType) {
        case QUERY_TYPE_OLDER:
          queryData.end = start - 1;
          queryData.start = queryData.end - queryDuration;
          break;
        case QUERY_TYPE_NEWER:
          queryData.start = end + 1;
          queryData.end = queryData.start + queryDuration;
          break;
      }

      // By "compacting" cursors, this fixes the disco/ping-pong problem
      // b/5311977
      if (mRowCount < 20 && queryData.queryType != QUERY_TYPE_CLEAN) {
        if (DEBUGLOG) {
          Log.e(
              TAG,
              "Compacting cursor: mRowCount="
                  + mRowCount
                  + " totalStart:"
                  + start
                  + " totalEnd:"
                  + end
                  + " query.start:"
                  + queryData.start
                  + " query.end:"
                  + queryData.end);
        }

        queryData.queryType = QUERY_TYPE_CLEAN;

        if (queryData.start > start) {
          queryData.start = start;
        }
        if (queryData.end < end) {
          queryData.end = end;
        }
      }
    }

    if (BASICLOG) {
      Time time = new Time(mTimeZone);
      time.setJulianDay(queryData.start);
      Time time2 = new Time(mTimeZone);
      time2.setJulianDay(queryData.end);
      Log.v(
          TAG,
          "startQuery: "
              + time.toString()
              + " to "
              + time2.toString()
              + " then go to "
              + queryData.goToTime);
    }

    mQueryHandler.cancelOperation(0);
    if (BASICLOG) queryData.queryStartMillis = System.nanoTime();

    Uri queryUri = buildQueryUri(queryData.start, queryData.end, queryData.searchQuery);
    mQueryHandler.startQuery(
        0, queryData, queryUri, PROJECTION, buildQuerySelection(), null, AGENDA_SORT_ORDER);
  }