Project

General

Profile

1
package eu.dnetlib.openaire.exporter;
2

    
3
import java.io.BufferedOutputStream;
4
import java.io.IOException;
5
import java.io.OutputStream;
6
import java.sql.SQLException;
7
import java.text.SimpleDateFormat;
8
import java.util.Arrays;
9
import java.util.Date;
10
import java.util.Map;
11
import java.util.zip.GZIPOutputStream;
12
import java.util.zip.ZipEntry;
13
import java.util.zip.ZipOutputStream;
14
import javax.servlet.ServletOutputStream;
15
import javax.servlet.ServletResponse;
16
import javax.servlet.http.HttpServletRequest;
17
import javax.servlet.http.HttpServletResponse;
18

    
19
import com.google.common.collect.Maps;
20
import com.google.common.xml.XmlEscapers;
21
import org.apache.commons.io.IOUtils;
22
import org.apache.commons.lang3.StringUtils;
23
import org.apache.commons.lang3.exception.ExceptionUtils;
24
import org.apache.commons.logging.Log;
25
import org.apache.commons.logging.LogFactory;
26
import org.springframework.beans.factory.annotation.Autowired;
27
import org.springframework.beans.factory.annotation.Value;
28
import org.springframework.core.io.Resource;
29
import org.springframework.http.HttpStatus;
30
import org.springframework.stereotype.Controller;
31
import org.springframework.web.bind.annotation.*;
32
import org.antlr.stringtemplate.StringTemplate;
33

    
34
@Controller
35
public class ProjectsController {
36

    
37
	private static final Log log = LogFactory.getLog(ProjectsController.class); // NOPMD by marko on 11/24/08 5:02 PM
38

    
39
	public final static String UTF8 = "UTF-8";
40

    
41
	@Value("${openaire.exporter.projectsfundings.sql.template}")
42
	private Resource projectsFundingQueryTemplate;
43

    
44
	@Value("${openaire.exporter.projects2tsv.sql.template}")
45
	private Resource projects2tsvQueryTemplate;
46

    
47
	@Value("${openaire.exporter.dspace.template.project}")
48
	private Resource dspaceTemplate;
49

    
50
	@Value("${openaire.exporter.dspace.template.head}")
51
	private Resource dspaceHeadTemplate;
52

    
53
	@Value("${openaire.exporter.dspace.template.tail}")
54
	private Resource dspaceTailTemplate;
55

    
56
	@Value("${openaire.exporter.eprints.template}")
57
	private Resource eprintsTemplate;
58

    
59
	@Value("${openaire.exporter.projectdetails.sql}")
60
	private Resource projectDetailsSql;
61

    
62
	@Autowired
63
	private JdbcApiDao dao;
64

    
65
	@Autowired
66
	private ProjectQueryParamsFactory projectQueryParamsFactory;
67

    
68
	@Deprecated
69
	/**
70
	 * @deprecated  we should use the codes returned by the yet to come service
71
	 */
72
	public enum Funding {
73
		FP7, WT, FCT, H2020, NHMRC, ARC, SFI, MZOS, HRZZ, NWO, MESTD, FWF, SNSF, RCUK
74
	}
75

    
76
	@RequestMapping(value = "/openaire/export/**/project/dspace.do")
77
	void processDspace(final HttpServletRequest request,
78
			final ServletResponse response,
79
			@RequestParam(value = "startFrom", required = false) final String startFrom,
80
			@RequestParam(value = "startUntil", required = false) final String startUntil,
81
			@RequestParam(value = "endFrom", required = false) final String endFrom,
82
			@RequestParam(value = "endUntil", required = false) final String endUntil) throws Exception {
83

    
84

    
85
		final ProjectQueryParams params = projectQueryParamsFactory.generateParams(request, startFrom, startUntil, endFrom, endUntil);
86
		final StringTemplate headSt = new StringTemplate(IOUtils.toString(dspaceHeadTemplate.getInputStream(), UTF8 ));
87

    
88
		headSt.setAttribute("fundingProgramme", params.getFundingProgramme());
89

    
90
		final StringTemplate tailSt = new StringTemplate(IOUtils.toString(dspaceTailTemplate.getInputStream(), UTF8));
91

    
92
		response.setContentType("text/xml");
93
		doProcess(response, params, headSt.toString(), dspaceTemplate, tailSt.toString(), s -> XmlEscapers.xmlContentEscaper().escape(oneLiner(s)));
94
	}
95

    
96
	@RequestMapping(value = "/openaire/export/**/project/eprints.do")
97
	void processEprints(final HttpServletRequest request,
98
			final ServletResponse response,
99
			@RequestParam(value = "startFrom", required = false) final String startFrom,
100
			@RequestParam(value = "startUntil", required = false) final String startUntil,
101
			@RequestParam(value = "endFrom", required = false) final String endFrom,
102
			@RequestParam(value = "endUntil", required = false) final String endUntil) throws Exception {
103

    
104
		final ProjectQueryParams params = projectQueryParamsFactory.generateParams(request, startFrom, startUntil, endFrom, endUntil);
105
		response.setContentType("text/html");
106
		doProcess(response, params, null, eprintsTemplate, null, s -> oneLiner(s));
107
	}
108

    
109
	private String oneLiner(final String s) {
110
		return StringUtils.isNotBlank(s) ? s.replaceAll("\\n", " ").trim() : "";
111
	}
112

    
113
	private void doProcess(
114
			final ServletResponse response,
115
			final ProjectQueryParams params,
116
			final String head, final Resource projectTemplate, final String tail,
117
			final ValueCleaner cleaner) throws IOException, SQLException {
118

    
119
		final StringTemplate st = new StringTemplate(IOUtils.toString(projectTemplate.getInputStream(), UTF8));
120
		dao.streamProjects(obtainQuery(params), response.getOutputStream(), head, st, tail, cleaner);
121
	}
122

    
123
	@RequestMapping(value = "/openaire/export/project2tsv.do")
124
	void processTsv(final HttpServletRequest request, final HttpServletResponse response,
125
			@RequestParam(value = "funding", required = true) final String funding,
126
			@RequestParam(value = "article293", required = false) final Boolean article293) throws Exception {
127

    
128
		final String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
129
		final String filename = "projects_" + funding + "_" + date + ".tsv";
130
		response.setContentType("text/tab-separated-values");
131
		response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + ".zip\"");
132

    
133
		final StringTemplate st = new StringTemplate(IOUtils.toString(projects2tsvQueryTemplate.getInputStream(), UTF8));
134
		Funding requestedFunding = Funding.valueOf(funding.toUpperCase());
135
		String fundingPrefix = getFundingPrefix(requestedFunding, null);
136
		log.debug("Setting fundingprefix to " + fundingPrefix);
137
		st.setAttribute("fundingprefix", fundingPrefix);
138
		st.setAttribute("filters", expandFilters(article293));
139

    
140
		final ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
141
		out.putNextEntry(new ZipEntry(filename));
142
		dao.streamProjectsTSV(st.toString(), out);
143
	}
144

    
145
	@RequestMapping(value = "/openaire/export/streamProjectDetails.do")
146
	void streamProjectDetails(final HttpServletResponse response,
147
			@RequestParam(value = "format", required = true) final String format,
148
			@RequestParam(value = "compress", required = false) final Boolean compress) throws IOException, SQLException {
149
		final String sql = IOUtils.toString(projectDetailsSql.getInputStream(), UTF8);
150

    
151
		if (compress != null && compress) {
152
			response.setHeader("Content-Encoding", "gzip");
153
		}
154
		switch (format) {
155
		case "csv":
156
			response.setContentType("text/csv");
157
			break;
158
		case "json":
159
			response.setContentType("text/plain");
160
			break;
161
		default: throw new IllegalArgumentException("unsupported format: " + format);
162
		}
163

    
164
		final OutputStream outputStream = getOutputStream(response.getOutputStream(), compress);
165
		dao.streamProjectDetails(sql, outputStream, format);
166
	}
167

    
168
	private OutputStream getOutputStream(final ServletOutputStream outputStream, final Boolean compress) throws IOException {
169
		if (compress != null && compress) {
170
			return new GZIPOutputStream(outputStream);
171
		}
172
		return outputStream;
173
	}
174

    
175
	@ExceptionHandler({Exception.class, Throwable.class})
176
	@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
177
	public @ResponseBody ErrorMessage handleSqlException(final Exception e) {
178
		log.error(e.getMessage());
179
		return new ErrorMessage(e);
180
	}
181

    
182
	public class ErrorMessage {
183

    
184
		private final String message;
185
		private final String stacktrace;
186

    
187
		public ErrorMessage(final Exception e) {
188
			this(e.getMessage(), ExceptionUtils.getStackTrace(e));
189
		}
190

    
191
		public ErrorMessage(final String message, final String stacktrace) {
192
			this.message = message;
193
			this.stacktrace = stacktrace;
194
		}
195

    
196
		public String getMessage() {
197
			return this.message;
198
		}
199

    
200
		public String getStacktrace() {
201
			return this.stacktrace;
202
		}
203
	}
204

    
205

    
206
	private Map<String, String> expandFilters(final Boolean article293) {
207
		final Map<String, String> res = Maps.newHashMap();
208

    
209
		if (article293 != null) {
210
			res.put("ec_article29_3", String.valueOf(article293));
211
		}
212

    
213
		return res;
214
	}
215

    
216
	/**
217
	 * Creates the query on the fundingProgramme specified in the given parameters.
218
	 *
219
	 * @param params
220
	 *            request parameters
221
	 * @return the query string
222
	 * @throws IllegalArgumentException
223
	 *             if the funding program is not recognized
224
	 * @throws IOException
225
	 *             if there are problem loading the query temlate
226
	 * @throws IllegalArgumentException
227
	 *             if the funding program is not recognized
228
	 */
229
	protected String obtainQuery(final ProjectQueryParams params) throws IllegalArgumentException, IOException {
230
		String funding = params.getFundingProgramme();
231
		String suffix = params.getFundingPath();
232
		String fundingPrefix = getFundingPrefix(Funding.valueOf(funding.toUpperCase()), suffix);
233
		final StringTemplate st = new StringTemplate(IOUtils.toString(projectsFundingQueryTemplate.getInputStream(), UTF8));
234
		st.setAttribute("fundingprefix", fundingPrefix);
235
		String theQuery = setDateParameters(st.toString(), params);
236
		log.debug("Generated query: " + theQuery);
237
		return theQuery;
238
	}
239

    
240
	/**
241
	 * @deprecated call the yet to come service that returns the funding prefix given a funding code
242
	 */
243
	@Deprecated
244
	private String getFundingPrefix(final Funding funding, final String suffix) throws IllegalArgumentException {
245
		switch (funding) {
246
		case FCT:
247
			if (StringUtils.isBlank(suffix)) return "fct_________::FCT";
248
			else return "fct_________::FCT::" + suffix;
249
		case WT:
250
			if (StringUtils.isBlank(suffix)) return "wt__________::WT";
251
			else return "wt__________::WT::" + suffix;
252
		case FP7:
253
			if (StringUtils.isBlank(suffix)) return "ec__________::EC::FP7";
254
			else return "ec__________::EC::FP7::" + suffix;
255
		case H2020:
256
			if (StringUtils.isBlank(suffix)) return "ec__________::EC::H2020";
257
			else return "ec__________::EC::H2020" + suffix;
258
		case NHMRC:
259
			if (StringUtils.isBlank(suffix)) return "nhmrc_______::NHMRC";
260
			else return "nhmrc_______::NHMRC::" + suffix;
261
		case ARC:
262
			if (StringUtils.isBlank(suffix)) return "arc_________::ARC";
263
			else return "arc_________::ARC::" + suffix;
264
		case SFI:
265
			if (StringUtils.isBlank(suffix)) return "sfi_________::SFI";
266
			else return "sfi_________::SFI::" + suffix;
267
		case MZOS:
268
			if (StringUtils.isBlank(suffix)) return "irb_hr______::MZOS";
269
			else return "irb_hr______::MZOS::" + suffix;
270
		case HRZZ:
271
			if (StringUtils.isBlank(suffix)) return "irb_hr______::HRZZ";
272
			else return "irb_hr______::HRZZ::" + suffix;
273
		case NWO:
274
			if (StringUtils.isBlank(suffix)) return "nwo_________::NWO";
275
			else return "nwo_________::NWO::" + suffix;
276
		case MESTD:
277
			if (StringUtils.isBlank(suffix)) return "mestd_______::MESTD";
278
			else return "mestd_______::MESTD::" + suffix;
279
		case FWF:
280
			if (StringUtils.isBlank(suffix)) return "fwf_________::FWF";
281
			else return "fwf_________::FWF::" + suffix;
282
		case SNSF:
283
			if (StringUtils.isBlank(suffix)) return "snsf________::SNSF";
284
			else return "snsf________::SNSF::" + suffix;
285
		case RCUK:
286
			if (StringUtils.isBlank(suffix)) return "rcuk________::RCUK";
287
			else return "rcuk________::RCUK::" + suffix;
288
		default:
289
			throw new IllegalArgumentException("Invalid funding " + funding + " (valid are: " + Arrays.asList(Funding.values()) + ") ");
290
		}
291
	}
292

    
293
	private String setDateParameters(final String query, final ProjectQueryParams params) {
294
		String queryWithDates = query;
295
		if (params.getStartFrom() != null) {
296
			queryWithDates += " AND startdate >= '" + params.getStartFrom() + "'";
297
		}
298
		if (params.getStartUntil() != null) {
299
			queryWithDates += " AND startdate <= '" + params.getStartUntil() + "'";
300
		}
301
		if (params.getEndFrom() != null) {
302
			queryWithDates += " AND enddate >= '" + params.getEndFrom() + "'";
303
		}
304
		if (params.getEndUntil() != null) {
305
			queryWithDates += " AND enddate <= '" + params.getEndUntil() + "'";
306
		}
307
		return queryWithDates;
308
	}
309

    
310
	public void setProjectsFundingQueryTemplate(final Resource projectsFundingQueryTemplate) {
311
		this.projectsFundingQueryTemplate = projectsFundingQueryTemplate;
312
	}
313

    
314
}
(4-4/5)