package org.juxtasoftware.dao.impl; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.juxtasoftware.dao.UserAnnotationDao; import org.juxtasoftware.model.ComparisonSet; import org.juxtasoftware.model.UserAnnotation; import org.juxtasoftware.model.UserAnnotation.Data; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.stereotype.Repository; import eu.interedition.text.Range; @Repository public class UserAnnotationDaoImpl implements UserAnnotationDao, InitializingBean { private static final String MAIN_TABLE = "juxta_user_note"; private static final String DATA_TABLE = "juxta_user_note_data"; protected SimpleJdbcInsert insert; @Autowired private JdbcTemplate jdbcTemplate; @Override public void afterPropertiesSet() throws Exception { this.insert = new SimpleJdbcInsert(jdbcTemplate).withTableName(MAIN_TABLE).usingGeneratedKeyColumns("id"); } @Override public Long create(UserAnnotation ua) { final MapSqlParameterSource ps = new MapSqlParameterSource(); ps.addValue("set_id", ua.getSetId()); ps.addValue("group_id", ua.getGroupId()); ps.addValue("base_id", ua.getBaseId()); ps.addValue("range_start", ua.getBaseRange().getStart()); ps.addValue("range_End", ua.getBaseRange().getEnd()); Long id = this.insert.executeAndReturnKey(ps).longValue(); addNotes(id, ua.getNotes()); ua.setId(id); return id; } private void addNotes(Long id, Set<Data> notes) { final String sql = "insert into "+DATA_TABLE+" (note_id,is_group,witness_id,note) values (?,?,?,?)"; for ( UserAnnotation.Data noteData : notes ) { this.jdbcTemplate.update(sql, id, noteData.isGroup(), noteData.getWitnessId(), noteData.getText()); } } @Override public Long findGroupId(ComparisonSet set, Long baseId, Range r) { StringBuilder sql = new StringBuilder("select group_id from "); sql.append(MAIN_TABLE); sql.append(" where set_id=? and base_id=?"); sql.append(" and range_start=? and range_end=? and group_id IS NOT NULL"); return this.jdbcTemplate.queryForLong(sql.toString(), set.getId(), baseId, r.getStart(), r.getEnd() ); } @Override public UserAnnotation find(ComparisonSet set, Long baseId, Range r) { StringBuilder sql = getFindSql(); sql.append(" where set_id=? and base_id=?"); sql.append(" and range_start >= ? and range_end <= ?"); Extractor rse = new Extractor(); List<UserAnnotation> hits = this.jdbcTemplate.query(sql.toString(), rse, set.getId(), baseId, r.getStart(), r.getEnd() ); if ( hits.size() == 0 ) { return null; } if ( hits.size() == 1 ) { return hits.get(0); } UserAnnotation anno = null; for ( UserAnnotation a : hits ) { if ( anno == null ) { anno = a; } else { if (anno.getGroupId() == null ) { anno.setGroupId(a.getGroupId()); } anno.addNotes(a.getNotes()); } } return anno; } @Override public List<UserAnnotation> list(ComparisonSet set, Long baseId) { Extractor rse = new Extractor(); StringBuilder sql = getFindSql(); sql.append(" where set_id=? and base_id=?"); return this.jdbcTemplate.query(sql.toString(), rse, set.getId(), baseId ); } private StringBuilder getFindSql() { StringBuilder sql = new StringBuilder(); sql.append("select n.id as n_id,set_id,base_id,range_start,range_end,group_id,d.id as d_id,is_group,witness_id,note from "); sql.append(MAIN_TABLE).append(" n"); sql.append(" inner join ").append(DATA_TABLE).append(" d"); sql.append(" on n.id = note_id "); return sql; } @Override public List<Long> getGroupWitnesses(Long groupId) { String sql= "select witness_id from juxta_user_note_data where note_id in (select id from juxta_user_note where group_id = ?)"; return this.jdbcTemplate.queryForList(sql, Long.class, groupId); } @Override public void updateGroupId(UserAnnotation ua, Long groupId) { String sql="update "+MAIN_TABLE+" set group_id=? where id=?"; this.jdbcTemplate.update(sql, groupId, ua.getId()); } @Override public void deleteWitnessNote(Long noteId) { String sql = "select note_id from "+DATA_TABLE+" where id=?"; Long id = this.jdbcTemplate.queryForLong(sql, noteId); sql = "delete from "+DATA_TABLE+" where id=?"; this.jdbcTemplate.update(sql, noteId); sql = "select count(*) as cnt from "+DATA_TABLE+" where note_id=?"; int cnt = this.jdbcTemplate.queryForInt(sql,id); if ( cnt == 0 ) { sql = "delete from "+MAIN_TABLE+" where id=?"; this.jdbcTemplate.update(sql, id); } } @Override public void addWitnessNote(UserAnnotation ua, Long witId, String text) { StringBuilder sql = new StringBuilder("select id from "); sql.append(MAIN_TABLE); sql.append(" where set_id=? and base_id=?"); sql.append(" and range_start=? and range_end=? and group_id is null "); Long noteId = this.jdbcTemplate.queryForLong(sql.toString(), ua.getSetId(), ua.getBaseId(), ua.getBaseRange().getStart(), ua.getBaseRange().getEnd()); String s = "insert into "+DATA_TABLE+" (note_id,witness_id,note) values (?,?,?)"; this.jdbcTemplate.update(s, noteId, witId, text); } @Override public void updateWitnessNote(Long noteId, String text) { String sql = "update juxta_user_note_data set note=? where id=?"; this.jdbcTemplate.update(sql, text, noteId); } @Override public void updateGroupNote(Long groupId, String newNote) { String sql = "update juxta_user_note_data set note=? where note_id in (select id from juxta_user_note where group_id=?) "; this.jdbcTemplate.update(sql, newNote, groupId); } @Override public void deleteGroupNote(ComparisonSet set, Long groupId) { final String sql = "delete from "+MAIN_TABLE+" where set_id=? and group_id=?"; this.jdbcTemplate.update(sql, set.getId(), groupId ); } @Override public void delete(ComparisonSet set, Long baseId, Range r) { if ( baseId == null ) { final String sql = "delete from "+MAIN_TABLE+" where set_id=?"; this.jdbcTemplate.update(sql, set.getId() ); return; } if ( r == null ) { final String sql = "delete from "+MAIN_TABLE+" where set_id=? and base_id=?"; this.jdbcTemplate.update(sql, set.getId(), baseId ); return; } final String sql = "delete from "+MAIN_TABLE+" where set_id=? and base_id=? and range_start>=? and range_end<=?"; this.jdbcTemplate.update(sql, set.getId(), baseId, r.getStart(), r.getEnd()); } @Override public boolean hasUserAnnotations(ComparisonSet set, Long baseId) { String sql = "select count(*) as cnt from "+MAIN_TABLE+" where base_id=? and set_id=?"; return (this.jdbcTemplate.queryForInt(sql, baseId, set.getId())>0); } @Override public int count(ComparisonSet set, Long baseId) { String sql = "select count(*) as cnt from "+MAIN_TABLE+" where base_id=? and set_id=?"; return this.jdbcTemplate.queryForInt(sql, baseId, set.getId()); } /** * Mapper to convert raw sql data into user annotation class */ private static class Extractor implements ResultSetExtractor< List<UserAnnotation> > { @Override public List<UserAnnotation> extractData(ResultSet rs) throws SQLException, DataAccessException { Map<Long, UserAnnotation> map = new HashMap<Long, UserAnnotation>(); while ( rs.next() ) { Long id = rs.getLong("n_id"); UserAnnotation ua = map.get(id); if ( ua == null ) { ua = new UserAnnotation(); ua.setId(id); ua.setBaseId( rs.getLong("base_id") ); ua.setSetId( rs.getLong("set_id") ); Object gid = rs.getObject("group_id"); if ( gid != null ) { ua.setGroupId(rs.getLong("group_id")); } ua.setBaseRange( new Range( rs.getLong("range_start"), rs.getLong("range_end") ) ); map.put(id, ua); } UserAnnotation.Data note = new UserAnnotation.Data(rs.getLong("witness_id"), rs.getString("note")); note.setId(rs.getLong("d_id")); note.setGroup(rs.getBoolean("is_group")); ua.addNote(note); } List<UserAnnotation> out = new ArrayList<UserAnnotation>(map.values()); Collections.sort(out); return out; } } }