@SuppressWarnings("unchecked") private AnnotationView buildAnnotationView(Annotation annotation, boolean loadAllReplies) { Object values[]; try { values = (Object[]) hibernateTemplate .findByCriteria( DetachedCriteria.forClass(Article.class) .add(Restrictions.eq("ID", annotation.getArticleID())) .setProjection( Projections.projectionList() .add(Projections.property("doi")) .add(Projections.property("title"))), 0, 1) .get(0); } catch (IndexOutOfBoundsException e) { // this should never happen throw new IllegalStateException( "Annotation " + annotation.getID() + " pointed to an article that didn't exist;" + " articleID: " + annotation.getArticleID()); } String articleDoi = (String) values[0]; String articleTitle = (String) values[1]; return buildAnnotationView(annotation, articleDoi, articleTitle, loadAllReplies); }
/** * Build up a map of id, and replies to that id so we can initialize the reply tree * * @param articleId * @return */ @SuppressWarnings("unchecked") private Map<Long, List<Annotation>> buildReplyMap(Long articleId) { Map<Long, List<Annotation>> fullReplyMap = new HashMap<Long, List<Annotation>>(); List<Annotation> allReplies = hibernateTemplate.findByCriteria( DetachedCriteria.forClass(Annotation.class) .add(Restrictions.eq("articleID", articleId)) .add(Restrictions.eq("type", AnnotationType.REPLY))); for (Annotation reply : allReplies) { // parent id should never be null on a reply if (reply.getParentID() == null) { log.warn("Found a reply with null parent id. Reply id: " + reply.getID()); } else { if (!fullReplyMap.containsKey(reply.getParentID())) { fullReplyMap.put(reply.getParentID(), new ArrayList<Annotation>()); } fullReplyMap.get(reply.getParentID()).add(reply); } } return Collections.unmodifiableMap(fullReplyMap); }
/** * Get a list of all annotations satisfying the given criteria. * * @param startDate search for annotation after start date. * @param endDate is the date to search until. If null, search until present date * @param annotTypes List of annotation types * @param maxResults the maximum number of results to return, or 0 for no limit * @param journal journalName * @return the (possibly empty) list of article annotations. * @throws ParseException if any of the dates or query could not be parsed * @throws URISyntaxException if an element of annotType cannot be parsed as a URI */ @Override @Transactional(readOnly = true) @SuppressWarnings("unchecked") public List<AnnotationView> getAnnotations( final Date startDate, final Date endDate, final Set<String> annotTypes, final int maxResults, final String journal) throws ParseException, URISyntaxException { /** * * There may be a more efficient way to do this other than querying the database twice, at * some point in time we might improve how hibernate does the object mappings * * <p>This execute returns annotationIDs, article DOIs and titles, which are needed to * construction the annotionView object */ Map<Long, String[]> results = (Map<Long, String[]>) hibernateTemplate.execute( new HibernateCallback() { @Override public Object doInHibernate(Session session) throws HibernateException, SQLException { /** * URIGen We have to do this with SQL because of how the mappings are currently * defined And hence, there is no way to unit test this */ StringBuilder sqlQuery = new StringBuilder(); Map<String, Object> params = new HashMap<String, Object>(3); sqlQuery.append("select ann.annotationID, art.doi, art.title "); sqlQuery.append("from annotation ann "); sqlQuery.append("join article art on art.articleID = ann.articleID "); sqlQuery.append("join journal j on art.eIssn = j.eIssn "); sqlQuery.append("where j.journalKey = :journal "); params.put("journal", journal); if (startDate != null) { sqlQuery.append(" and ann.created > :startDate"); params.put("startDate", startDate); } if (endDate != null) { sqlQuery.append(" and ann.created < :endDate"); params.put("endDate", endDate); } if (annotTypes != null) { sqlQuery.append(" and ann.type in (:annotTypes)"); params.put("annotTypes", annotTypes); } sqlQuery.append(" order by ann.created desc"); SQLQuery query = session.createSQLQuery(sqlQuery.toString()); query.setProperties(params); if (maxResults > 0) { query.setMaxResults(maxResults); } List<Object[]> tempResults = query.list(); Map<Long, String[]> results = new HashMap<Long, String[]>(tempResults.size()); for (Object[] obj : tempResults) { // This forces this method to return Long values and not BigInteger results.put( (((Number) obj[0]).longValue()), new String[] {(String) obj[1], (String) obj[2]}); } return results; } }); // The previous query puts annotationID and doi into the map. annotationID is key // I do this to avoid extra doi lookups later in the code. if (results.size() > 0) { DetachedCriteria criteria = DetachedCriteria.forClass(Annotation.class) .add(Restrictions.in("ID", results.keySet())) .addOrder(Order.desc("created")) .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); List<Annotation> annotations = hibernateTemplate.findByCriteria(criteria); List<AnnotationView> views = new ArrayList<AnnotationView>(annotations.size()); for (Annotation ann : annotations) { String articleDoi = results.get(ann.getID())[0]; String articleTitle = results.get(ann.getID())[1]; views.add(buildAnnotationView(ann, articleDoi, articleTitle, false)); } return views; } else { return new ArrayList<AnnotationView>(); } }