Ejemplo n.º 1
0
  @Transactional(readOnly = true)
  public Object doWork(Session s, ServiceFactory sf) {

    if (q == null) {
      return null;
    }

    final Class<?> cls = values.onlyTypes.get(0);
    FullTextSession session = Search.createFullTextSession(s);
    Criteria criteria = criteria(session);
    if (criteria == null) {
      return null; // EARLY EXIT. See criteria method.
    }

    final String ticket975 =
        "ticket:975 - Wrong return type: %s instead of %s\n"
            + "Under some circumstances, byFullText and related methods \n"
            + "like bySomeMustNone can return instances of the wrong \n"
            + "types. One known case is the use of onlyAnnotatedWith(). \n"
            + "If you are recieving this error, please try using the \n"
            + "intersection/union methods to achieve the same results.";

    // Main query
    FullTextQuery ftQuery = session.createFullTextQuery(this.q, cls);
    initializeQuery(ftQuery);
    List<?> result = ftQuery.list();
    int totalSize = ftQuery.getResultSize();

    if (result.size() == 0) {
      // EARLY EXIT
      return result; // of wrong type but with generics it doesn't matter
    }

    final Map<Long, Integer> order = new HashMap<Long, Integer>();
    final Map<Long, Float> scores = new HashMap<Long, Float>();
    final Map<Long, Object[]> projections = new HashMap<Long, Object[]>();
    for (int i = 0; i < result.size(); i++) {
      Object[] parts = (Object[]) result.get(i);
      scores.put((Long) parts[1], (Float) parts[0]);
      order.put((Long) parts[1], i);
      projections.put((Long) parts[1], parts);
    }

    // TODO Could add a performance optimization here on returnUnloaded

    final LinkedList<Long> ids = new LinkedList<Long>(scores.keySet());
    final List<IObject> check975 = new ArrayList<IObject>();

    while (ids.size() > 0) {
      final List<Long> page = new ArrayList<Long>();
      for (int i = 0; i < 1000 && ids.size() > 0; i++) {
        page.add(ids.removeFirst());
      }
      if (criteria == null) {
        criteria = criteria(session);
      }
      criteria.add(Restrictions.in("id", page));
      check975.addAll(criteria.list());
      criteria = null;
    }

    for (IObject object : check975) {
      // TODO This is now all but impossible. Remove
      if (!cls.isAssignableFrom(object.getClass())) {
        throw new ApiUsageException(String.format(ticket975, object.getClass(), cls));
      } else {
        object.putAt(TOTAL_SIZE, totalSize);
        object.putAt(ProjectionConstants.SCORE, scores.get(object.getId()));
        object.putAt(ALL_PROJECTIONS, projections.get(object.getId()));
      }
    }

    // Order return value based on the original ordering

    final Comparator cmp =
        new Comparator() {
          public int compare(Object obj1, Object obj2) {
            IObject o1 = (IObject) obj1;
            IObject o2 = (IObject) obj2;
            Long id1 = o1.getId();
            Long id2 = o2.getId();
            Integer idx1 = order.get(id1);
            Integer idx2 = order.get(id2);
            return idx1.compareTo(idx2);
          }
        };
    Collections.sort(check975, cmp);
    return check975;
  }