Project

General

Profile

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

    
3
import eu.dnetlib.goldoa.domain.Request;
4
import eu.dnetlib.goldoa.domain.stats.Browse;
5
import eu.dnetlib.goldoa.domain.stats.DateSeries;
6
import eu.dnetlib.goldoa.domain.stats.MapData;
7
import eu.dnetlib.goldoa.domain.stats.Numbers;
8
import eu.dnetlib.goldoa.domain.stats.Quadruple;
9
import eu.dnetlib.goldoa.domain.stats.Series;
10
import eu.dnetlib.goldoa.domain.stats.Triple;
11
import org.springframework.beans.factory.annotation.Autowired;
12
import org.springframework.jdbc.core.JdbcTemplate;
13
import org.springframework.jdbc.core.RowMapper;
14
import org.springframework.transaction.annotation.Transactional;
15

    
16
import javax.sql.DataSource;
17
import java.sql.ResultSet;
18
import java.sql.SQLException;
19
import java.text.SimpleDateFormat;
20
import java.util.ArrayList;
21
import java.util.Date;
22
import java.util.HashMap;
23
import java.util.List;
24
import java.util.Map;
25

    
26
/**
27
 * Created by antleb on 11/19/15.
28
 */
29
@Transactional(readOnly = true)
30
public class StatsManagerImpl implements StatsManager {
31

    
32
	public static final String NUMBERS_REQUESTS = "select count(*) from request r where r.status in (" + Request.RequestStatus.APPROVED.getCode() + ", " + Request.RequestStatus.ACCOUNTING_PROCESSING.getCode() + ", " + Request.RequestStatus.ACCOUNTING_PAID.getCode() + ", " + Request.RequestStatus.CONDITIONALLY_APPROVED.getCode() + ", " + Request.RequestStatus.ACCOUNTING_ON_HOLD.getCode() + ")" ;
33
	public static final String NUMBERS_PAID_REQUESTS = "select count(*) from request r where r.status in (" + Request.RequestStatus.ACCOUNTING_PAID.getCode() + ")" ;
34
	public static final String NUMBERS_PROJECTS = "select count(distinct project) from request r where r.status in (" + Request.RequestStatus.APPROVED.getCode() + ", " + Request.RequestStatus.ACCOUNTING_PROCESSING.getCode() + ", " + Request.RequestStatus.ACCOUNTING_PAID.getCode() + ", " + Request.RequestStatus.CONDITIONALLY_APPROVED.getCode() + ", " + Request.RequestStatus.ACCOUNTING_ON_HOLD.getCode() + ")";
35
	public static final String NUMBERS_TOTAL_AMOUNT = "select sum(apc_paid) from request r";
36
	public static final String NUMBERS_AVERAGE_AMOUNT = "select avg(apc_paid)::INTEGER from request r";
37
	public static final String NUMBERS_AVERAGE_PER_ARTICLE = "select avg(apc_paid)::INTEGER from request r join publication p on r.publication=p.id where p.type='ARTICLE'";
38
	public static final String NUMBERS_AVERAGE_PER_MONOGRAPH = "select avg(apc_paid)::INTEGER from request r join publication p on r.publication=p.id where p.type='MONOGRAPH'";
39
	public static final String NUMBERS_AVERAGE_PER_BOOK_CHAPTER = "select avg(apc_paid)::INTEGER from request r join publication p on r.publication=p.id where p.type='BOOK_CHAPTER'";
40
	public static final String NUMBERS_PAID_REQUESTS_WITH_DOI = "select count(*) from request r join publication p on r.publication=p.id where p.doi is not null and r.status=" + Request.RequestStatus.ACCOUNTING_PAID;
41
	public static final String NUMBERS_APPROVED_REQUESTS_WITH_DOI = "select count(*) from request r join publication p on r.publication=p.id where p.doi is not null and r.status in (" + Request.RequestStatus.APPROVED.getCode() + ", " + Request.RequestStatus.ACCOUNTING_PROCESSING.getCode() + ", " + Request.RequestStatus.ACCOUNTING_PAID.getCode() + ", " + Request.RequestStatus.CONDITIONALLY_APPROVED.getCode() + ", " + Request.RequestStatus.ACCOUNTING_ON_HOLD.getCode() + ", " + Request.RequestStatus.CONDITIONALLY_APPROVED.getCode() + ")";
42

    
43
	public static final String SERIES_COUNTRY = "select c.name as category, count(r.id) as count, sum(apc_paid) as apc, avg(apc_paid) as avgapc from request r join organisation o on r.organization=o.id join country c on c.id=o.country %WHERE% group by c.name";
44
	public static final String SERIES_STATUS = "select r.status as category, count(r.id) as count, sum(apc_paid) as apc, avg(apc_paid) as avgapc from request r %WHERE% group by r.status";
45
	public static final String SERIES_TYPE = "select p.type as category, count(r.id) as count, sum(apc_paid) as apc, avg(apc_paid) as avgapc from request r join publication p on p.id=r.publication %WHERE% group by p.type";
46
	public static final String SERIES_ORGANIZATION = "select o.name as category, count(r.id) as count, sum(apc_paid) as apc, avg(apc_paid) as avgapc from request r join organisation o on r.organization=o.id %WHERE% group by o.shortname, o.name";
47
	public static final String SERIES_PUBLISHER = "select p.name as category, count(r.id) as count, sum(apc_paid) as apc, avg(apc_paid) as avgapc from (select r.id, r.status, r.apc_paid, j.publisher, 'j' from request r join journal j on r.journal=j.id where j.publisher is not null union select r.id, r.status, r.apc_paid, p.id, 'p' from request r join publisher p on r.publisher=p.id) as r join publisher p on r.publisher=p.id %WHERE% group by p.name";
48

    
49
	public static final String BROWSE_SCIENTIFIC_AREA = "select distinct p.scientificarea as id, p.scientificarea as category, count(r.id) as count from request r join project p on r.project=p.id group by p.scientificarea order by category";
50
	public static final String BROWSE_COUNTRY = "select c.id as id, c.name as category, count(r.id) as count from request r join organisation o on r.organization=o.id join country c on c.id=o.country group by c.name, c.id order by category";
51
	public static final String BROWSE_ORGANIZATION = "select o.id as id, case when o.shortname is not null then o.shortname else o.name end  as category, count(r.id) as count from request r join organisation o on o.id=r.organization group by o.shortname, o.name, o.id order by category";
52
	public static final String BROWSE_PUBLISHER = "select p.id as id, p.name as category, count(r.id) as count from (select r.id, r.status, j.publisher, 'j' from request r join journal j on r.journal=j.id where j.publisher is not null union select r.id, r.status, p.id, 'p' from request r join publisher p on r.publisher=p.id) as r join publisher p on r.publisher=p.id group by p.name, p.id order by category";
53
	public static final String BROWSE_STATUS = "select r.status as id, r.status as category, count(r.id) as count from request r group by status";
54

    
55
	@Autowired
56
	private DataSource dataSource;
57

    
58
	@Override
59
	public Numbers getNumbers(Numbers.Category[] categories) {
60
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
61
		Map<Numbers.Category, Integer> map = new HashMap<Numbers.Category, Integer>();
62

    
63
		for (Numbers.Category category:categories) {
64
			switch (category) {
65
				case REQUESTS:
66
					map.put(Numbers.Category.REQUESTS, jdbcTemplate.queryForObject(NUMBERS_REQUESTS, Integer.class));
67
					break;
68
				case PAID_REQUESTS:
69
					map.put(Numbers.Category.PAID_REQUESTS, jdbcTemplate.queryForObject(NUMBERS_PAID_REQUESTS, Integer.class));
70
					break;
71
				case PROJECTS:
72
					map.put(Numbers.Category.PROJECTS, jdbcTemplate.queryForObject(NUMBERS_PROJECTS, Integer.class));
73
					break;
74
				case TOTAL_AMOUNT:
75
					map.put(Numbers.Category.TOTAL_AMOUNT, jdbcTemplate.queryForObject(NUMBERS_TOTAL_AMOUNT, Integer.class));
76
					break;
77
				case AVERAGE_AMOUNT:
78
					map.put(Numbers.Category.AVERAGE_AMOUNT, jdbcTemplate.queryForObject(NUMBERS_AVERAGE_AMOUNT, Integer.class));
79
					break;
80
				case AVERAGE_PER_ARTICLE:
81
					map.put(Numbers.Category.AVERAGE_PER_ARTICLE, jdbcTemplate.queryForObject(NUMBERS_AVERAGE_PER_ARTICLE, Integer.class));
82
					break;
83
				case AVERAGE_PER_MONOGRAPH:
84
					map.put(Numbers.Category.AVERAGE_PER_MONOGRAPH, jdbcTemplate.queryForObject(NUMBERS_AVERAGE_PER_MONOGRAPH, Integer.class));
85
					break;
86
				case AVERAGE_PER_BOOK_CHAPTER:
87
					map.put(Numbers.Category.AVERAGE_PER_BOOK_CHAPTER, jdbcTemplate.queryForObject(NUMBERS_AVERAGE_PER_BOOK_CHAPTER, Integer.class));
88
					break;
89
				case PAID_REQUESTS_WITH_DOI:
90
					map.put(Numbers.Category.PAID_REQUESTS_WITH_DOI, jdbcTemplate.queryForObject(NUMBERS_PAID_REQUESTS_WITH_DOI, Integer.class));
91
					break;
92
				case APPROVED_REQUESTS_WITH_DOI:
93
					map.put(Numbers.Category.APPROVED_REQUESTS_WITH_DOI, jdbcTemplate.queryForObject(NUMBERS_APPROVED_REQUESTS_WITH_DOI, Integer.class));
94
					break;
95
			}
96
		}
97

    
98
		return new Numbers(map);
99
	}
100

    
101
	@Override
102
	public Series getSeries(Series.Category[] categories, Request.RequestStatus[] statuses) {
103
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
104
		Map<Series.Category, List<Quadruple<String, Integer, Float, Float>>> map = new HashMap<Series.Category, List<Quadruple<String, Integer, Float, Float>>>();
105

    
106
		for (final Series.Category category:categories) {
107
			String query = null;
108

    
109
			switch (category) {
110
				case COUNTRY:
111
					query = SERIES_COUNTRY;
112
					break;
113
				case ORGANIZATION:
114
					query = SERIES_ORGANIZATION;
115
					break;
116
				case PUBLISHER:
117
					query = SERIES_PUBLISHER;
118
					break;
119
				case STATUS:
120
					query = SERIES_STATUS;
121
					break;
122
				case PUBLICATION_TYPE:
123
					query = SERIES_TYPE;
124
			}
125

    
126
			if (statuses != null) {
127
				StringBuilder ssb = new StringBuilder();
128

    
129
				for (Request.RequestStatus status:statuses) {
130
					String clause;
131
					int code = status.getCode();
132

    
133
					switch (code) {
134
						case 0:
135
							clause = " r.status=0";
136
							break;
137
						default:
138
							clause = " (r.status = " + code + ")";
139
							break;
140
					}
141

    
142
					ssb.append(ssb.length()==0?clause:" or " + clause);
143
				}
144

    
145
				query = query.replace("%WHERE%", " where " + ssb.toString());
146
			} else {
147
				query = query.replace("%WHERE%", "");
148
			}
149

    
150
			map.put(category, jdbcTemplate.query(query, new RowMapper<Quadruple<String, Integer, Float, Float>>() {
151
				@Override
152
				public Quadruple<String, Integer, Float, Float> mapRow(ResultSet rs, int rowNum) throws SQLException {
153
					if (category != Series.Category.STATUS)
154
						return new Quadruple<String, Integer, Float, Float>(rs.getString("category"), rs.getInt("count"), rs.getFloat("apc"), rs.getFloat("avgapc"));
155
					else
156
						return new Quadruple<String, Integer, Float, Float>(Request.RequestStatus.forStatus(rs.getInt("category")).getValue(), rs.getInt("count"), rs.getFloat("apc"), rs.getFloat("avgapc"));
157
				}
158
			}));
159
		}
160

    
161
		return new Series(map);
162
	}
163

    
164
	@Override
165
	public DateSeries getDateSeries(DateSeries.Over over, boolean cumulative, Date from, Date to, String[] publishers, String[] organizations, String[] countries, String[] scientificAreas) {
166

    
167
		StringBuilder sb = new StringBuilder();
168
		String dateColumn = null;
169
		String windowKeyword ;
170
		List<String> clauses = new ArrayList<String>();
171

    
172
		switch (over) {
173
			case DAY:
174
				dateColumn = "date_trunc('day', submissiondate)";
175
				break;
176
			case MONTH:
177
				dateColumn = "date_trunc('month', submissiondate)";
178
				break;
179
			case YEAR:
180
				dateColumn = "date_trunc('year', submissiondate)";
181
				break;
182
		}
183

    
184
		if (cumulative)
185
			windowKeyword = "order";
186
		else
187
			windowKeyword = "partition";
188

    
189
		if (from != null) {
190
			clauses.add(" r.submissiondate >= '" + new SimpleDateFormat("yyyy-MM-dd").format(from) + "' ");
191
		}
192
		if (to != null) {
193
			clauses.add(" r.submissiondate <= '" + new SimpleDateFormat("yyyy-MM-dd").format(to) + "' ");
194
		}
195

    
196
		if (publishers != null && publishers.length > 0) {
197
			String clause = "pub.id in (";
198

    
199
			for (int i = 0; i < publishers.length; i++) {
200
				if (i > 0)
201
					clause += ", ";
202

    
203
				clause += "'" + publishers[i] + "'";
204
			}
205

    
206
			clause += ")";
207

    
208
			clauses.add(clause);
209
		}
210

    
211
		if (organizations != null && organizations.length > 0) {
212
			String clause = "o.id in (";
213

    
214
			for (int i = 0; i < organizations.length; i++) {
215
				if (i > 0)
216
					clause += ", ";
217

    
218
				clause += "'" + organizations[i] + "'";
219
			}
220

    
221
			clause += ")";
222

    
223
			clauses.add(clause);
224
		}
225

    
226
		if (countries != null && countries.length > 0) {
227
			String clause = "c.id in (";
228

    
229
			for (int i = 0; i < countries.length; i++) {
230
				if (i > 0)
231
					clause += ", ";
232

    
233
				clause += "'" + countries[i] + "'";
234
			}
235

    
236
			clause += ")";
237

    
238
			clauses.add(clause);
239
		}
240

    
241
		if (scientificAreas != null && scientificAreas.length > 0) {
242
			String clause = "p.scientificarea in (";
243

    
244
			for (int i = 0; i < scientificAreas.length; i++) {
245
				if (i > 0)
246
					clause += ", ";
247

    
248
				clause += "'" + scientificAreas[i] + "'";
249
			}
250

    
251
			clause += ")";
252

    
253
			clauses.add(clause);
254
		}
255

    
256
		sb.append("select distinct ").append(dateColumn).append(" as date, count(r.id) over (").append(windowKeyword).append(" by ").append(dateColumn).append(") as count, sum(apc_paid) over (").append(windowKeyword).append(" by ").append(dateColumn).append(") as apc ");
257
		sb.append("from request r left join project p on r.project=p.id left join organisation o on r.organization=o.id left join country c on c.id=o.country left join (select r.id as rid,  p.id, p.name from request r join journal j on r.journal=j.id join publisher p on p.id=j.publisher  union select r.id, p.id, p.name from request r join publisher p on r.publisher=p.id) as pub on pub.rid=r.id");
258

    
259
		if (clauses.size() > 0)
260
			sb.append(" where ");
261

    
262
		for (int i = 0; i < clauses.size(); i++) {
263
			if (i > 0)
264
				sb.append(" and ");
265

    
266
			sb.append(" (").append(clauses.get(i)).append(") ");
267
		}
268

    
269
		sb.append(" order by ").append(dateColumn);
270

    
271
//		System.out.println(sb.toString());return null;
272

    
273
		return new DateSeries(new JdbcTemplate(dataSource).query(sb.toString(), new RowMapper<Triple<Date, Integer, Float>>() {
274
			@Override
275
			public Triple<Date, Integer, Float> mapRow(ResultSet rs, int rowNum) throws SQLException {
276
				return new Triple<Date, Integer, Float>(rs.getDate("date"), rs.getInt("count"), rs.getFloat("apc"));
277
			}
278
		}));
279
	}
280

    
281
	public static void main(String[] args) {
282
		System.out.println(new StatsManagerImpl().getDateSeries(DateSeries.Over.DAY, true, null,null,null,null,null,null));
283
	}
284

    
285
	@Override
286
	public Browse browse(Browse.Category[] categories) {
287
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
288
		Map<Browse.Category, List<Triple<String, String, Integer>>> map = new HashMap<Browse.Category, List<Triple<String, String, Integer>>>();
289

    
290
		for (final Browse.Category category:categories) {
291
			String query = null;
292

    
293
			switch (category) {
294
				case COUNTRY:
295
					query = BROWSE_COUNTRY;
296
					break;
297
				case ORGANIZATION:
298
					query = BROWSE_ORGANIZATION;
299
					break;
300
				case PUBLISHER:
301
					query = BROWSE_PUBLISHER;
302
					break;
303
				case SCIENTIFIC_AREA:
304
					query = BROWSE_SCIENTIFIC_AREA;
305
					break;
306
				case STATUS:
307
					query =  BROWSE_STATUS;
308
					break;
309
			}
310

    
311
			map.put(category, jdbcTemplate.query(query, new RowMapper<Triple<String, String, Integer>>() {
312
				@Override
313
				public Triple<String, String, Integer> mapRow(ResultSet rs, int rowNum) throws SQLException {
314
					if (category != Browse.Category.STATUS)
315
						return new Triple<String, String, Integer>(rs.getString("id"), rs.getString("category"), rs.getInt("count"));
316
					else
317
						return new Triple<String, String, Integer>(Request.RequestStatus.forStatus(rs.getInt("id")).name(), Request.RequestStatus.forStatus(rs.getInt("category")).getValue(), rs.getInt("count"));
318
				}
319
			}));
320
		}
321

    
322
		return new Browse(map);
323
	}
324

    
325
	@Override
326
	public MapData getMapData() {
327
		return null;
328
	}
329
}
(2-2/2)