Project

General

Profile

1
package eu.dnetlib.goldoa.service.dao;
2

    
3
import com.opencsv.CSVWriter;
4
import eu.dnetlib.goldoa.domain.BankAccount;
5
import eu.dnetlib.goldoa.domain.BankTransferReceipt;
6
import eu.dnetlib.goldoa.domain.Comment;
7
import eu.dnetlib.goldoa.domain.Currency;
8
import eu.dnetlib.goldoa.domain.Funder;
9
import eu.dnetlib.goldoa.domain.Person;
10
import eu.dnetlib.goldoa.domain.Request;
11
import eu.dnetlib.goldoa.domain.RequestCoFunder;
12
import eu.dnetlib.goldoa.domain.RequestFilter;
13
import eu.dnetlib.goldoa.domain.RequestPage;
14
import eu.dnetlib.goldoa.domain.RequestSort;
15
import eu.dnetlib.goldoa.domain.RequestSortOrder;
16
import org.apache.commons.codec.digest.DigestUtils;
17
import org.apache.commons.io.IOUtils;
18
import org.apache.commons.lang3.ArrayUtils;
19
import org.springframework.beans.factory.annotation.Autowired;
20
import org.springframework.dao.EmptyResultDataAccessException;
21
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
22
import org.springframework.jdbc.core.JdbcTemplate;
23
import org.springframework.jdbc.core.PreparedStatementSetter;
24
import org.springframework.jdbc.core.RowMapper;
25

    
26
import javax.sql.DataSource;
27
import java.io.ByteArrayOutputStream;
28
import java.io.IOException;
29
import java.io.InputStream;
30
import java.io.StringWriter;
31
import java.sql.PreparedStatement;
32
import java.sql.ResultSet;
33
import java.sql.SQLException;
34
import java.sql.Types;
35
import java.text.SimpleDateFormat;
36
import java.util.ArrayList;
37
import java.util.Date;
38
import java.util.HashMap;
39
import java.util.List;
40
import java.util.Map;
41

    
42
/**
43
 * Created by antleb on 3/30/15.
44
 */
45
public class RequestDAO {
46

    
47
	@Autowired
48
	private DataSource dataSource;
49

    
50
	private final static String GET_FOR_PROJECT = "select id, \"user\", date, researcher, organization, project, publication, journal, publisher, publisher_email, budget, invoice, apc, discount, projectparticipation, fundingrequested, currency, status, bank_name, bank_address, bank_code, bank_holder, bank_iban, apc_paid, transfer_cost, other_cost, date_paid, submissiondate, approvaldate from request where project=?";
51

    
52
	private final static String GET_BY_ID = "select id, \"user\", date, researcher, organization, project, publication, journal, publisher_email, publisher, budget, invoice, apc, discount, projectparticipation, fundingrequested, currency, status, bank_name, bank_address, bank_code, bank_holder, bank_iban, apc_paid, transfer_cost, other_cost, date_paid, submissiondate, approvaldate from request where id=?";
53

    
54
	private final static String UPDATE_REQUEST = "update request set \"user\"=?, date=?, researcher=?, organization=?, project=?, publication=?, journal=?, publisher=?, publisher_email=?, budget=?, invoice = ?, apc=?, discount=?, projectparticipation=?, fundingrequested=?, currency=?, status=?, bank_name=?, bank_address=?, bank_code=?, bank_holder=?, bank_iban=?, apc_paid=?, transfer_cost=?, other_cost=?, date_paid=?, submissiondate=?, approvaldate=? where id = ?";
55

    
56
	private final static String INSERT_REQUEST = "insert into request (\"user\", date, researcher, organization, project, publication, journal, publisher, publisher_email, budget, invoice, apc, discount, projectparticipation, fundingrequested, currency, status, bank_name, bank_address, bank_code, bank_holder, bank_iban, apc_paid, transfer_cost, other_cost, date_paid, submissiondate, approvaldate, id) values (?, ?, ?, ?, ?, ? ,? ,? ,? ,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
57

    
58
	private final static String APPROVE_REQUEST = "update request set status = (status & ~" + (Request.RequestStatus.REJECTED.getCode() | Request.RequestStatus.CONDITIONALLY_APPROVED.getCode()) + ") | " + Request.RequestStatus.APPROVED.getCode() + ", approvaldate=now() where id=?";
59

    
60
	private final static String CONDITIONALLY_APPROVE_REQUEST = "update request set status = (status & ~" + (Request.RequestStatus.REJECTED.getCode() | Request.RequestStatus.APPROVED.getCode()) + ") | " + Request.RequestStatus.CONDITIONALLY_APPROVED.getCode() + " where id=?";
61

    
62
	private final static String REJECT_REQUEST = "update request set status = (status & ~" + (Request.RequestStatus.APPROVED.getCode() | Request.RequestStatus.CONDITIONALLY_APPROVED.getCode()) + ") | " + Request.RequestStatus.REJECTED.getCode() + " where id=?";
63

    
64
	private final static String PAID_REQUEST = "update request set status = (status & ~" + (Request.RequestStatus.ACCOUNTING_ON_HOLD.getCode() | Request.RequestStatus.ACCOUNTING_DENIED.getCode() | Request.RequestStatus.ACCOUNTING_PROCESSING.getCode()) + ") | " + Request.RequestStatus.ACCOUNTING_PAID.getCode() + ", apc_paid=?, transfer_cost=?, other_cost=?, date_paid=? where id=?";
65

    
66
	private final static String ONHOLD_REQUEST = "update request set status = (status & ~" + (Request.RequestStatus.ACCOUNTING_PAID.getCode() | Request.RequestStatus.ACCOUNTING_DENIED.getCode() | Request.RequestStatus.ACCOUNTING_PROCESSING.getCode()) + ") | " + Request.RequestStatus.ACCOUNTING_ON_HOLD.getCode() + " where id=?";
67

    
68
	private final static String PROCESSING_REQUEST = "update request set status = (status & ~" + (Request.RequestStatus.ACCOUNTING_PAID.getCode() | Request.RequestStatus.ACCOUNTING_DENIED.getCode() | Request.RequestStatus.ACCOUNTING_ON_HOLD.getCode()) + ") | " + Request.RequestStatus.ACCOUNTING_PROCESSING.getCode() + " where id=?";
69

    
70
	private final static String DENIED_REQUEST = "update request set status = (status & ~" + (Request.RequestStatus.ACCOUNTING_ON_HOLD.getCode() | Request.RequestStatus.ACCOUNTING_PAID.getCode() | Request.RequestStatus.ACCOUNTING_PROCESSING.getCode()) + ") | " + Request.RequestStatus.ACCOUNTING_DENIED.getCode() + " where id=?";
71

    
72
	private final static String INVOICE_UPLOADED = "update request set invoice=?, status = status | " + Request.RequestStatus.INVOICE_UPLOADED.getCode() + " where id=?";
73

    
74
	private RowMapper<Request> requestRowMapper = new RowMapper<Request>() {
75
		@Override
76
		public Request mapRow(ResultSet rs, int rowNum) throws SQLException {
77
			BankAccount bankAccount = new BankAccount(rs.getString("bank_name"), rs.getString("bank_address"), rs.getString("bank_code"), rs.getString("bank_holder"), rs.getString("bank_iban"));
78

    
79
			Request request = new Request(
80
					rs.getString("id"), rs.getString("user"), rs.getTimestamp("date"), rs.getString("researcher"), rs.getString("organization"),
81
					rs.getString("project"), rs.getString("publication"), rs.getString("journal"), rs.getString("publisher"), rs.getString("publisher_email"),
82
					rs.getString("budget"), rs.getString("invoice"), rs.getFloat("apc"), rs.getFloat("discount"), rs.getFloat("projectparticipation"),
83
					rs.getFloat("fundingrequested"), null, bankAccount, new ArrayList<RequestCoFunder>(), rs.getFloat("apc_paid"), rs.getFloat("transfer_cost"),
84
					rs.getFloat("other_cost"), rs.getTimestamp("date_paid"), rs.getInt("status"), rs.getDate("submissiondate"), rs.getDate("approvaldate"));
85

    
86
			String currency = rs.getString("currency");
87
			if (rs.wasNull())
88
				request.setCurrency(null);
89
			else
90
				request.setCurrency(Currency.valueOf(currency));
91

    
92
			rs.getFloat("apc");
93
			if (rs.wasNull())
94
				request.setApc(null);
95
			rs.getFloat("discount");
96
			if (rs.wasNull())
97
				request.setDiscount(null);
98
			rs.getFloat("projectparticipation");
99
			if (rs.wasNull())
100
				request.setProjectParticipation(null);
101
			rs.getFloat("fundingrequested");
102
			if (rs.wasNull())
103
				request.setFundingRequested(null);
104
			rs.getFloat("apc_paid");
105
			if (rs.wasNull())
106
				request.setApc_paid(null);
107
			rs.getFloat("transfer_cost");
108
			if (rs.wasNull())
109
				request.setTransfer_cost(null);
110
			rs.getFloat("other_cost");
111
			if (rs.wasNull())
112
				request.setOther_cost(null);
113

    
114
			return request;
115
		}
116
	};
117

    
118

    
119
	public void saveRequest(final Request request) {
120
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
121
		Object[] args;
122
		int[] types = new int[]{Types.VARCHAR, Types.TIMESTAMP, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
123
				Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.REAL, Types.REAL, Types.REAL,
124
				Types.REAL, Types.VARCHAR, Types.INTEGER, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
125
				Types.VARCHAR, Types.REAL, Types.REAL, Types.REAL, Types.TIMESTAMP, Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR};
126

    
127
		String currency = request.getCurrency() != null ? request.getCurrency().name() : null;
128

    
129
		if (request.getBankAccount() != null) {
130
			args = new Object[]{request.getUser(), request.getDate(), request.getResearcher(), request.getOrganization(), request.getProject(),
131
					request.getPublication(), request.getJournal(), request.getPublisher(), request.getPublisherEmail(), request.getBudget(), request.getInvoice(),
132
					request.getApc(), request.getDiscount(), request.getProjectParticipation(), request.getFundingRequested(), currency,
133
					request.getStatus(), request.getBankAccount().getBankName(), request.getBankAccount().getBankAddress(), request.getBankAccount().getBankCode(), request.getBankAccount().getAccountHolder(),
134
					request.getBankAccount().getIban(), request.getApc_paid(), request.getTransfer_cost(), request.getOther_cost(), request.getDate_paid(), request.getSubmissionDate(), request.getApprovalDate(), request.getId()};
135
		} else {
136
			args = new Object[]{request.getUser(), request.getDate(), request.getResearcher(), request.getOrganization(), request.getProject(),
137
					request.getPublication(), request.getJournal(), request.getPublisher(), request.getPublisherEmail(), request.getBudget(), request.getInvoice(),
138
					request.getApc(), request.getDiscount(), request.getProjectParticipation(), request.getFundingRequested(), currency, request.getStatus(), null, null, null, null, null,
139
					request.getApc_paid(), request.getTransfer_cost(), request.getOther_cost(), request.getDate_paid(), request.getSubmissionDate(), request.getApprovalDate(), request.getId()};
140
		}
141

    
142
		if (jdbcTemplate.update(UPDATE_REQUEST, args, types) == 0) {
143
			jdbcTemplate.update(INSERT_REQUEST, args, types);
144
		}
145
	}
146

    
147
	public void saveCoFunders(final Request request) {
148
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
149
		jdbcTemplate.update("delete from request_cofunder where request=?", new String[]{request.getId()}, new int[]{Types.VARCHAR});
150
		jdbcTemplate.batchUpdate("insert into request_cofunder (request, funder, percentage) values (?,?,?)", new BatchPreparedStatementSetter() {
151

    
152
			@Override
153
			public void setValues(PreparedStatement ps, int i) throws SQLException {
154
				ps.setString(1, request.getId());
155
				ps.setString(2, request.getCoFunders().get(i).getFunder().getId());
156
				ps.setFloat(3, request.getCoFunders().get(i).getPercentage());
157
			}
158

    
159
			@Override
160
			public int getBatchSize() {
161
				if (request.getCoFunders() != null)
162
					return request.getCoFunders().size();
163
				else
164
					return 0;
165
			}
166
		});
167
	}
168

    
169
	public List<RequestCoFunder> getCoFunders(final Request request) {
170
		return new JdbcTemplate(dataSource).query("select rf.percentage, f.id, f.name, f.url, f.source from request_cofunder rf join funder f on rf.funder=f.id where rf.request=?", new String[]{request.getId()}, new int[]{Types.VARCHAR}, new RowMapper<RequestCoFunder>() {
171
			@Override
172
			public RequestCoFunder mapRow(ResultSet rs, int rowNum) throws SQLException {
173
				Funder funder = new Funder(rs.getString("id"), rs.getString("name"), rs.getString("url"), rs.getString("source"));
174

    
175
				return new RequestCoFunder(request, funder, rs.getFloat("percentage"));
176
			}
177
		});
178
	}
179

    
180
	public Request getRequest(String requestId) {
181
		return new JdbcTemplate(dataSource).queryForObject(GET_BY_ID, new String[]{requestId}, new int[]{
182
				Types.VARCHAR}, requestRowMapper);
183
	}
184

    
185
	public RequestPage getForUser(String personId, Date fromDate, Date toDate, RequestSort requestSortBy, RequestSortOrder order, RequestFilter requestFilter, String term, Request.RequestStatus[] statusFilter, int from, int to) {
186
		return this.getRequestPage(personId, null, null, requestSortBy, order, requestFilter, term, getStatusFilter(statusFilter), from, to);
187
	}
188

    
189
	public RequestPage getForOrganization(List<String> organizationIds, Date fromDate, Date toDate, RequestSort requestSortBy, RequestSortOrder order, RequestFilter requestFilter, String term, Request.RequestStatus[] statusFilter, int from, int to) {
190
		return this.getRequestPage(null, organizationIds, null, requestSortBy, order, requestFilter, term, getStatusFilter(statusFilter), from, to);
191
	}
192

    
193
	public RequestPage getForPublisher(String publisherId, Date fromDate, Date toDate, RequestSort requestSortBy, RequestSortOrder order, RequestFilter requestFilter, String term, Request.RequestStatus[] statusFilter, int from, int to) {
194
		return this.getRequestPage(null, null, publisherId, requestSortBy, order, requestFilter, term, getStatusFilter(statusFilter), from, to);
195
	}
196

    
197
	public List<Request> getForProject(String projectId) {
198
		return new JdbcTemplate(dataSource).query(GET_FOR_PROJECT, new String[]{projectId}, new int[]{
199
				Types.VARCHAR}, requestRowMapper);
200
	}
201

    
202
	public RequestPage getRequests(Date fromDate, Date toDate, RequestSort requestSortBy, RequestSortOrder order, RequestFilter requestFilter, String term, Request.RequestStatus[] statusFilter, int from, int to) {
203
		return this.getRequestPage(null, null, null, requestSortBy, order, requestFilter, term, getStatusFilter(statusFilter), from, to);
204
	}
205

    
206
	public RequestPage getRequests(Date fromDate, Date toDate, RequestSort requestSortBy, RequestSortOrder order, RequestFilter requestFilter, String term, Integer[] statusFilter, int from, int to) {
207
		return this.getRequestPage(null, null, null, requestSortBy, order, requestFilter, term, statusFilter, from, to);
208
	}
209

    
210
	public void approveRequest(String requestId, String personId, String comment) {
211
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
212

    
213
		jdbcTemplate.update(APPROVE_REQUEST, new String[]{requestId}, new int[]{Types.VARCHAR});
214

    
215
		if (comment != null && !comment.isEmpty()) {
216
			saveComment(requestId, personId, comment);
217
		}
218
	}
219

    
220
	public void conditionallyApproveRequest(String requestId, String personId, String comment) {
221
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
222

    
223
		jdbcTemplate.update(CONDITIONALLY_APPROVE_REQUEST, new String[]{requestId}, new int[]{Types.VARCHAR});
224

    
225
		if (comment != null && !comment.isEmpty()) {
226
			saveComment(requestId, personId, comment);
227
		}
228
	}
229

    
230
	private void saveComment(String requestId, String personId, String comment) {
231
		String commentId = "portal::" + DigestUtils.md5Hex(comment + new Date());
232

    
233
		new JdbcTemplate(dataSource).update("with comm as ( insert into comment (id, person, comment, date) values (?, ?, ?, ?) returning id) insert into request_comment (request, comment) select ?, comm.id from comm",
234
				new Object[]{commentId, personId, comment, new Date(), requestId}, new int[]{Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.TIMESTAMP, Types.VARCHAR});
235
	}
236

    
237
	public void rejectRequest(String requestId, String personId, String comment) {
238
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
239

    
240
		jdbcTemplate.update(REJECT_REQUEST, new String[]{requestId}, new int[]{Types.VARCHAR});
241

    
242
		if (comment != null && !comment.isEmpty()) {
243
			saveComment(requestId, personId, comment);
244
		}
245
	}
246

    
247
	public void processingRequest(String requestId, String personId, String comment) {
248
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
249

    
250
		jdbcTemplate.update(PROCESSING_REQUEST, new String[]{requestId}, new int[]{Types.VARCHAR});
251

    
252
		if (comment != null && !comment.isEmpty()) {
253
			saveComment(requestId, personId, comment);
254
		}
255
	}
256

    
257
	public void paidRequest(String requestId, String personId, String comment, float apc_paid, float transfer_cost, float other_cost, Date datePaid) {
258
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
259

    
260
		jdbcTemplate.update(PAID_REQUEST, new Object[]{apc_paid, transfer_cost, other_cost, datePaid, requestId}, new int[]{Types.REAL, Types.REAL, Types.REAL, Types.TIMESTAMP, Types.VARCHAR});
261

    
262
		if (comment != null && !comment.isEmpty()) {
263
			saveComment(requestId, personId, comment);
264
		}
265
	}
266

    
267
	public void onHoldRequest(String requestId, String personId, String comment) {
268
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
269

    
270
		jdbcTemplate.update(ONHOLD_REQUEST, new String[]{requestId}, new int[]{Types.VARCHAR});
271

    
272
		if (comment != null && !comment.isEmpty()) {
273
			saveComment(requestId, personId, comment);
274
		}
275
	}
276

    
277
	public void deniedRequest(String requestId, String personId, String comment) {
278
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
279

    
280
		jdbcTemplate.update(DENIED_REQUEST, new String[]{requestId}, new int[]{Types.VARCHAR});
281

    
282
		if (comment != null && !comment.isEmpty()) {
283
			saveComment(requestId, personId, comment);
284
		}
285
	}
286

    
287
	public void invoiceUploaded(String requestId, String invoiceId) {
288
		new JdbcTemplate(dataSource).update(INVOICE_UPLOADED, new String[]{invoiceId, requestId}, new int[]{Types.VARCHAR, Types.VARCHAR});
289
	}
290

    
291
	public int getRequestId() {
292
		return new JdbcTemplate(dataSource).queryForObject("select nextval('request_id_seq') as id", new RowMapper<Integer>() {
293
			@Override
294
			public Integer mapRow(ResultSet rs, int rowNum) throws SQLException {
295
				return rs.getInt("id");
296
			}
297
		});
298
	}
299

    
300
	public String getCSV(RequestSort requestSortBy, RequestSortOrder order, RequestFilter requestFilter, String term, Integer[] statuses) throws IOException {
301
		List<Object> args = new ArrayList<Object>();
302
		List<Integer> types = new ArrayList<Integer>();
303
		String requestQuery = this.getQuery(null, null, null, requestSortBy, order, requestFilter, term, statuses, args, types);
304
		String query = "select r.id, r.status, r.date::date, u.firstname, u.lastname, p.acronym, pub.title, pub.type, r.date_paid::date, r.apc_paid, r.transfer_cost, r.other_cost, j.title as journal, (case when jp.id is not null then jp.name else mp.name end) as publisher, r.apc as apc, r.approvaldate as approvaldate, r.currency as currency from (" + requestQuery + ") r left join person u on r.researcher = u.id left join project p on r.project=p.id left join publication pub on r.publication=pub.id left join journal j on j.id=r.journal left join publisher jp on j.publisher=jp.id left join publisher mp on mp.id=r.publisher";
305

    
306
		List<String[]> requests = new JdbcTemplate(dataSource).query(query, args.toArray(), ArrayUtils.toPrimitive(types.toArray(new Integer[0])), new RowMapper<String[]>() {
307
			@Override
308
			public String[] mapRow(ResultSet rs, int rowNum) throws SQLException {
309
				String[] objs = new String[17];
310

    
311
				objs[0] = rs.getString("id");
312
				objs[1] = Request.RequestStatus.forStatus(rs.getInt("status")).getValue();
313
				objs[2] = new SimpleDateFormat("yyyy/MM/dd").format(rs.getDate("date"));
314
				objs[3] = rs.getString("firstname");
315
				objs[4] = rs.getString("lastname");
316
				objs[5] = rs.getString("acronym");
317
				objs[6] = rs.getString("title");
318
				objs[7] = rs.getString("type");
319
				objs[8] = rs.getString("journal");
320
				objs[9] = rs.getString("publisher");
321
				objs[10] = rs.getDate("approvaldate") != null?new SimpleDateFormat("yyyy/MM/dd").format(rs.getDate("approvaldate")):null;
322
				objs[11] = Float.toString(rs.getFloat("apc"));
323
				objs[12] = rs.getString("currency");
324
				objs[13] = rs.getDate("date_paid")!=null?new SimpleDateFormat("yyyy/MM/dd").format(rs.getDate("date_paid")):null;
325
				objs[14] = rs.getFloat("apc_paid") +"";
326
				objs[15] = rs.getFloat("transfer_cost") + "";
327
				objs[16] = rs.getFloat("other_cost") + "";
328

    
329
				return objs;
330
			}
331
		});
332

    
333
		StringWriter sw = new StringWriter();
334
		CSVWriter csvWriter = new CSVWriter(sw);
335

    
336
			csvWriter.writeNext(new String[]{"id", "Status", "Submission Date", "Firstname", "Lastname", "Project", "Title", "Type", "Journal", "Publisher", "Date Approved", "APC requested", "Currency", "Date Paid", "APC paid", "Transfer Cost", "Other Expenses"}, false);
337
		csvWriter.writeAll(requests, false);
338

    
339
		csvWriter.close();
340
		sw.close();
341

    
342
		return sw.toString();
343
	}
344

    
345
	private RequestPage getRequestPage(String personId, List<String> organizationIds, String publisherId, RequestSort requestSortBy, RequestSortOrder order, RequestFilter requestFilter, String term, Integer[] statusFilterCodes, int from, int to) {
346
		RequestPage page = new RequestPage();
347
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
348
		List<Object> args = new ArrayList<Object>();
349
		List<Integer> types = new ArrayList<Integer>();
350
		String query = getQuery(personId, organizationIds, publisherId, requestSortBy, order, requestFilter, term, statusFilterCodes, args, types);
351

    
352

    
353
		page.setRequests(jdbcTemplate.query(applyPaging(query, from, to), args.toArray(), ArrayUtils.toPrimitive(types.toArray(new Integer[0])), requestRowMapper));
354
		page.setTotal(jdbcTemplate.queryForObject(getCountQuery(query), args.toArray(), ArrayUtils.toPrimitive(types.toArray(new Integer[0])), Integer.class));
355
		page.setFrom(from);
356
		page.setTo(to);
357

    
358
		return page;
359
	}
360

    
361
	private String getCountQuery(String query) {
362
		StringBuilder sb = new StringBuilder();
363

    
364
		sb.append("select count(*) from (").append(query).append(") foo");
365

    
366
		return sb.toString();
367
	}
368

    
369
	private String getQuery(String personId, List<String> organizationIds, String publisherId, RequestSort requestSortBy, RequestSortOrder order, RequestFilter requestFilter, String term, Integer[] statusFilterCodes, List<Object> args, List<Integer> types) {
370
		Map<String, String> joins = new HashMap<String, String>();
371
		List<String> whereClauses = new ArrayList<String>();
372
		List<Object> whereArgs = new ArrayList<Object>();
373
		List<Integer> whereTypes = new ArrayList<Integer>();
374

    
375
		String orderBy = null;
376

    
377
		if (term != null) {
378
			if (requestFilter != null) {
379
				switch (requestFilter) {
380
					case ID:
381
						whereClauses.add("(r.id like ? )");
382
						whereArgs.add("%" + term + "%");
383
						types.add(Types.VARCHAR);
384
						break;
385
					case USER:
386
						joins.put("user", " join person u on u.id=r.user and (lower(u.firstname) like lower(?) or lower(u.initials) like lower(?) or lower(u.lastname) like lower(?)) ");
387
						args.add("%" + term + "%");
388
						args.add("%" + term + "%");
389
						args.add("%" + term + "%");
390
						types.add(Types.VARCHAR);
391
						types.add(Types.VARCHAR);
392
						types.add(Types.VARCHAR);
393
						break;
394
					case RESEARCHER:
395
						joins.put("researcher", " join person res on res.id=r.researcher and (lower(res.firstname) like lower(?) or lower(res.initials) like lower(?) or lower(res.lastname) like lower(?)) ");
396
						args.add("%" + term + "%");
397
						args.add("%" + term + "%");
398
						args.add("%" + term + "%");
399
						types.add(Types.VARCHAR);
400
						types.add(Types.VARCHAR);
401
						types.add(Types.VARCHAR);
402
						break;
403
					case PROJECT:
404
						joins.put("project", " join project proj on proj.id=r.project and (lower(proj.acronym) like lower(?) or lower(proj.title) like lower(?) or lower(proj.grant) like lower(?)) ");
405
						args.add("%" + term + "%");
406
						args.add("%" + term + "%");
407
						args.add("%" + term + "%");
408
						types.add(Types.VARCHAR);
409
						types.add(Types.VARCHAR);
410
						types.add(Types.VARCHAR);
411
						break;
412
					case PUBLICATION:
413
						joins.put("publication", " join publication pub on pub.id=r.publication and (lower(pub.title) like lower(?)) ");
414
						args.add("%" + term + "%");
415
						types.add(Types.VARCHAR);
416
						break;
417
					case JOURNAL:
418
						joins.put("journal", " join journal j on j.id=r.journal and (lower(j.title) like lower(?)) ");
419
						args.add("%" + term + "%");
420
						types.add(Types.VARCHAR);
421
						break;
422
					case PUBLISHER:
423
						joins.put("publisher", " join publisher publ on publ.id=r.publisher and (lower(publ.name) like lower(?)) ");
424
						args.add("%" + term + "%");
425
						types.add(Types.VARCHAR);
426
						break;
427
				}
428
			} else {
429
				whereClauses.add("(r.id like ? )");
430
				whereArgs.add("%" + term + "%");
431
				types.add(Types.VARCHAR);
432

    
433
				joins.put("user", " left join person u on u.id=r.user ");
434
				whereClauses.add("(lower(u.firstname) like lower(?) or lower(u.initials) like lower(?) or lower(u.lastname) like lower(?))");
435
				whereArgs.add("%" + term + "%");
436
				whereArgs.add("%" + term + "%");
437
				whereArgs.add("%" + term + "%");
438
				whereTypes.add(Types.VARCHAR);
439
				whereTypes.add(Types.VARCHAR);
440
				whereTypes.add(Types.VARCHAR);
441
				joins.put("researcher", " left join person res on res.id=r.researcher ");
442
				whereClauses.add("(lower(res.firstname) like lower(?) or lower(res.initials) like lower(?) or lower(res.lastname) like lower(?))");
443
				whereArgs.add("%" + term + "%");
444
				whereArgs.add("%" + term + "%");
445
				whereArgs.add("%" + term + "%");
446
				whereTypes.add(Types.VARCHAR);
447
				whereTypes.add(Types.VARCHAR);
448
				whereTypes.add(Types.VARCHAR);
449
				joins.put("project", " left join project proj on proj.id=r.project ");
450
				whereClauses.add("(lower(proj.acronym) like lower(?) or lower(proj.title) like lower(?) or lower(proj.grant) like lower(?))");
451
				whereArgs.add("%" + term + "%");
452
				whereArgs.add("%" + term + "%");
453
				whereArgs.add("%" + term + "%");
454
				whereTypes.add(Types.VARCHAR);
455
				whereTypes.add(Types.VARCHAR);
456
				whereTypes.add(Types.VARCHAR);
457
				joins.put("publication", " left join publication pub on pub.id=r.publication ");
458
				whereClauses.add("(lower(pub.title) like lower(?))");
459
				whereArgs.add("%" + term + "%");
460
				whereTypes.add(Types.VARCHAR);
461
				joins.put("journal", " left join journal j on j.id=r.journal ");
462
				whereClauses.add("(lower(j.title) like lower(?))");
463
				whereArgs.add("%" + term + "%");
464
				whereTypes.add(Types.VARCHAR);
465
				joins.put("publisher", " left join publisher publ on publ.id=r.publisher ");
466
				whereClauses.add("(lower(publ.name) like lower(?))");
467
				whereArgs.add("%" + term + "%");
468
				whereTypes.add(Types.VARCHAR);
469
			}
470

    
471
		}
472

    
473
		if (requestSortBy != null) {
474
			switch (requestSortBy) {
475
				case DATE:
476
					orderBy = " r.date ";
477
					break;
478
				case FUNDING_REQUESTED:
479
					orderBy = " r.fundingrequested ";
480
					break;
481
				case USER:
482
					if (joins.get("user") == null)
483
						joins.put("user", " left join person u on u.id=r.user ");
484

    
485
					orderBy = " u.firstname, u.initials, u.lastname ";
486
					break;
487
				case PUBLICATION:
488
					if (joins.get("publication") == null)
489
						joins.put("publication", " left join publication pub on r.publication=pub.id ");
490

    
491
					orderBy = " pub.title ";
492
					break;
493
				case RESEARCHER:
494
					if (joins.get("researcher") == null)
495
						joins.put("researcher", " left join person res on res.id=r.researcher ");
496

    
497
					orderBy = " res.firstname, res.initials, res.lastname ";
498
					break;
499
				case PROJECT:
500
					if (joins.get("project") == null)
501
						joins.put("project", " left join project proj on proj.id=r.project ");
502

    
503
					orderBy = " proj.acronym ";
504
					break;
505
				case JOURNAL:
506
					if (joins.get("journal") == null)
507
						joins.put("journal", " left join journal j on j.id=r.journal ");
508

    
509
					orderBy = " j.title ";
510
					break;
511
				case PUBLISHER:
512
					if (joins.get("publisher") == null)
513
						joins.put("publisher", " left join publisher publ on publ.id=r.publisher ");
514

    
515
					orderBy = " publ.name ";
516
					break;
517
				case STATUS:
518
				default:
519
					orderBy = " r.status ";
520
					break;
521
			}
522
		}
523

    
524
		StringBuilder sb = new StringBuilder("select r.id, r.\"user\", r.date, r.researcher, r.organization, r.project, r.publication, r.journal, r.publisher, r.publisher_email, r.budget, r.invoice, r.apc, r.discount, r.projectparticipation, r.fundingrequested, r.currency, r.bank_name, r.bank_address, r.bank_code, r.bank_holder, r.bank_iban, r.apc_paid, r.transfer_cost, r.other_cost, r.date_paid, r.submissiondate, r.approvaldate, r.status from request r ");
525

    
526
		for (String join : joins.values())
527
			sb.append(" ").append(join).append(" ");
528

    
529

    
530
		sb.append(" where ");
531

    
532
		if (personId != null) {
533
			sb.append("r.\"user\"=? ");
534

    
535
			args.add(personId);
536
			types.add(Types.VARCHAR);
537
		} else if (organizationIds != null) {
538
			sb.append("(");
539

    
540
			for (int i = 0; i < organizationIds.size(); i++) {
541
				if (i > 0)
542
					sb.append(" or ");
543

    
544
				sb.append(" r.organization=? ");
545

    
546
				args.add(organizationIds.get(i));
547
				types.add(Types.VARCHAR);
548
			}
549

    
550
			sb.append(")");
551

    
552
		} else if (publisherId != null) {
553

    
554
			if (joins.get("journal") == null) {
555
				sb.delete(sb.lastIndexOf("where"), sb.length());
556
				sb.append(" left join journal j on j.id=r.journal ");
557
				sb.append(" where ");
558
			}
559

    
560
			sb.append("(r.publisher=? or j.publisher=?)");
561

    
562
			args.add(publisherId);
563
			types.add(Types.VARCHAR);
564
			args.add(publisherId);
565
			types.add(Types.VARCHAR);
566
		}
567

    
568
		if (statusFilterCodes != null) {
569
			StringBuilder ssb = new StringBuilder();
570

    
571
			for (Integer code:statusFilterCodes) {
572
				String clause;
573

    
574
				switch (code) {
575
					case 0:
576
						clause = " r.status&" + Request.RequestStatus.SUBMITTED.getCode() + "=0";
577
						break;
578
					default:
579
						clause = " (r.status&" + code + " = " + code + " and r.status < " + (code<<1) + ")";
580
						break;
581
				}
582

    
583
				ssb.append(ssb.length()==0?clause:" or " + clause);
584
			}
585

    
586
			if (sb.toString().trim().endsWith("where"))
587
				sb.append("(").append(ssb.toString()).append(")");
588
			else
589
				sb.append(" and ").append("(").append(ssb.toString()).append(")");
590
		}
591

    
592
		if (whereClauses.size() > 0) {
593
			if (!sb.toString().trim().endsWith("where"))
594
				sb.append(" and ");
595
			sb.append("(");
596

    
597
			for (String clause : whereClauses) {
598
				sb.append(clause);
599
				sb.append(" or ");
600
			}
601

    
602
			sb.delete(sb.lastIndexOf("or"), sb.length());
603
			sb.append(") ");
604

    
605
			args.addAll(whereArgs);
606
			types.addAll(whereTypes);
607
		}
608

    
609
		if (sb.toString().trim().endsWith("where"))
610
			sb.delete(sb.lastIndexOf("where"), sb.length());
611

    
612
		if (orderBy != null) {
613
			sb.append(" order by ").append(orderBy);
614

    
615
			if (order == RequestSortOrder.ASCENDING)
616
				sb.append(" asc");
617
			else
618
				sb.append(" desc");
619
		}
620

    
621
		return sb.toString();
622
	}
623

    
624
	private String applyPaging(String query, int from, int to) {
625
		StringBuilder sb = new StringBuilder(query);
626

    
627
		if (from > 0 || to > 0) {
628
			sb.append(" limit ").append(to - from + 1);
629
			sb.append(" offset ").append(from);
630
		}
631

    
632
		return sb.toString();
633
	}
634

    
635
	private Integer[] getStatusFilter(Request.RequestStatus[] statuses) {
636
		if (statuses == null)
637
			return null;
638
		else {
639
			Integer[] res = new Integer[statuses.length];
640

    
641
			for (int i = 0; i < statuses.length; i++)
642
				res[i] = statuses[i].getCode();
643

    
644
			return res;
645
		}
646
	}
647

    
648
	public List<Comment> getComments(String id) {
649
		try {
650
			return new JdbcTemplate(dataSource).query("select c.comment, c.date, c.person from comment c join request_comment rc on rc.comment=c.id and rc.request=? order by date",
651
					new String[]{id}, new int[]{Types.VARCHAR}, new RowMapper<Comment>() {
652
						@Override
653
						public Comment mapRow(ResultSet rs, int rowNum) throws SQLException {
654
							return new Comment(new Person(rs.getString("person")), rs.getTimestamp("date"), rs.getString("comment"));
655
						}
656
					});
657
		} catch (EmptyResultDataAccessException e) {
658
			return null;
659
		}
660
	}
661

    
662
	public void uploadBankTransferReceipt(final String requestid, final String contentType, InputStream inputStream) {
663
		try {
664
			final ByteArrayOutputStream baos = new ByteArrayOutputStream();
665
			final JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
666

    
667
			IOUtils.copy(inputStream, baos);
668
			IOUtils.closeQuietly(baos);
669

    
670
			final PreparedStatementSetter pss = new PreparedStatementSetter() {
671
				@Override
672
				public void setValues(PreparedStatement ps) throws SQLException {
673
					ps.setString(1, contentType);
674
					ps.setBytes(2, baos.toByteArray());
675
					ps.setString(3, requestid);
676
				}
677
			};
678

    
679
			jdbcTemplate.update("update request set bank_receipt_contenttype=?, bank_receipt=? where id=?", pss);
680

    
681
		} catch (Exception e) {
682
			e.printStackTrace();
683
		}
684
	}
685

    
686
	public BankTransferReceipt downloadBankTransferReceipt(String requestId) {
687
		return new JdbcTemplate(dataSource).queryForObject("select bank_receipt_contenttype, bank_receipt from request where id=?", new String[]{requestId}, new int[]{Types.VARCHAR}, new RowMapper<BankTransferReceipt>() {
688
			@Override
689
			public BankTransferReceipt mapRow(ResultSet rs, int rowNum) throws SQLException {
690
				return new BankTransferReceipt(rs.getString("bank_receipt_contenttype"), rs.getBytes("bank_receipt"));
691
			}
692
		});
693
	}
694
}
(9-9/9)