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.antlr.stringtemplate.StringTemplate;
22
import org.apache.commons.io.IOUtils;
23
import org.apache.commons.lang.StringUtils;
24
import org.apache.commons.lang.exception.ExceptionUtils;
25
import org.apache.commons.logging.Log;
26
import org.apache.commons.logging.LogFactory;
27
import org.springframework.beans.factory.annotation.Autowired;
28
import org.springframework.beans.factory.annotation.Value;
29
import org.springframework.core.io.Resource;
30
import org.springframework.http.HttpStatus;
31
import org.springframework.stereotype.Controller;
32
import org.springframework.web.bind.annotation.*;
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
	@Value("${openaire.exporter.projectsfundings.sql.template}")
40
	private Resource projectsFundingQueryTemplate;
41

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

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

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

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

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

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

    
60
	@Autowired
61
	private JdbcApiDao dao;
62

    
63
	@Autowired
64
	private ProjectQueryParamsFactory projectQueryParamsFactory;
65

    
66
	public enum Funding {
67
		FP7, WT, FCT, H2020, NHMRC, ARC, SFI, MZOS, HRZZ, NWO, MESTD, FWF, SNSF
68
	}
69

    
70
	@RequestMapping(value = "/openaire/export/**/project/dspace.do")
71
	void processDspace(final HttpServletRequest request,
72
			final ServletResponse response,
73
			@RequestParam(value = "startFrom", required = false) final String startFrom,
74
			@RequestParam(value = "startUntil", required = false) final String startUntil,
75
			@RequestParam(value = "endFrom", required = false) final String endFrom,
76
			@RequestParam(value = "endUntil", required = false) final String endUntil) throws Exception {
77

    
78

    
79
		final ProjectQueryParams params = projectQueryParamsFactory.generateParams(request, startFrom, startUntil, endFrom, endUntil);
80

    
81
		final StringTemplate headSt = new StringTemplate(IOUtils.toString(dspaceHeadTemplate.getInputStream()));
82
		headSt.setAttribute("fundingProgramme", params.getFundingProgramme());
83

    
84
		final StringTemplate tailSt = new StringTemplate(IOUtils.toString(dspaceTailTemplate.getInputStream()));
85

    
86
		response.setContentType("text/xml");
87
		doProcess(response, params, headSt.toString(), dspaceTemplate, tailSt.toString(), new ValueCleaner() {
88
			@Override
89
			public String clean(final String s) {
90
				return XmlEscapers.xmlContentEscaper().escape(oneLiner(s));
91
			}
92
		});
93
	}
94

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

    
103
		final ProjectQueryParams params = projectQueryParamsFactory.generateParams(request, startFrom, startUntil, endFrom, endUntil);
104
		response.setContentType("text/html");
105
		doProcess(response, params, null, eprintsTemplate, null, new ValueCleaner() {
106
			@Override
107
			public String clean(final String s) {
108
				return oneLiner(s);
109
			}
110
		});
111
	}
112

    
113
	private String oneLiner(final String s) {
114
		return StringUtils.isNotBlank(s) ? s.replaceAll("\\n", " ").trim() : "";
115
	}
116

    
117
	private void doProcess(
118
			final ServletResponse response,
119
			final ProjectQueryParams params,
120
			final String head, final Resource projectTemplate, final String tail,
121
			final ValueCleaner cleaner) throws IOException, SQLException {
122

    
123
		final StringTemplate st = new StringTemplate(IOUtils.toString(projectTemplate.getInputStream()));
124
		dao.streamProjects(obtainQuery(params), response.getOutputStream(), head, st, tail, cleaner);
125
	}
126

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

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

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

    
144
		final ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
145
		out.putNextEntry(new ZipEntry(filename));
146
		dao.streamProjectsTSV(st.toString(), out);
147
	}
148

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

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

    
168
		final OutputStream outputStream = getOutputStream(response.getOutputStream(), compress);
169
		dao.streamProjectDetails(sql, outputStream, format);
170
	}
171

    
172
	private OutputStream getOutputStream(final ServletOutputStream outputStream, final Boolean compress) throws IOException {
173
		if (compress != null && compress) {
174
			return new GZIPOutputStream(outputStream);
175
		}
176
		return outputStream;
177
	}
178

    
179
	@ExceptionHandler({Exception.class, Throwable.class})
180
	@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
181
	public @ResponseBody ErrorMessage handleSqlException(final Exception e) {
182
		log.error(e.getMessage());
183
		return new ErrorMessage(e);
184
	}
185

    
186
	public class ErrorMessage {
187

    
188
		private final String message;
189
		private final String stacktrace;
190

    
191
		public ErrorMessage(final Exception e) {
192
			this(e.getMessage(), ExceptionUtils.getStackTrace(e));
193
		}
194

    
195
		public ErrorMessage(final String message, final String stacktrace) {
196
			this.message = message;
197
			this.stacktrace = stacktrace;
198
		}
199

    
200
		public String getMessage() {
201
			return this.message;
202
		}
203

    
204
		public String getStacktrace() {
205
			return this.stacktrace;
206
		}
207
	}
208

    
209

    
210
	private Map<String, String> expandFilters(final Boolean article293) {
211
		final Map<String, String> res = Maps.newHashMap();
212

    
213
		if (article293 != null) {
214
			res.put("ec_article29_3", String.valueOf(article293));
215
		}
216

    
217
		return res;
218
	}
219

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

    
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
		default:
286
			throw new IllegalArgumentException("Invalid funding " + funding + " (valid are: " + Arrays.asList(Funding.values()) + ") ");
287
		}
288
	}
289

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

    
307
	public void setProjectsFundingQueryTemplate(final Resource projectsFundingQueryTemplate) {
308
		this.projectsFundingQueryTemplate = projectsFundingQueryTemplate;
309
	}
310

    
311
}
(4-4/5)