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.net.SocketException;
7
import java.nio.charset.Charset;
8
import java.sql.SQLException;
9
import java.text.SimpleDateFormat;
10
import java.util.Arrays;
11
import java.util.Date;
12
import java.util.List;
13
import java.util.Map;
14
import java.util.zip.GZIPOutputStream;
15
import java.util.zip.ZipEntry;
16
import java.util.zip.ZipOutputStream;
17
import javax.servlet.ServletOutputStream;
18
import javax.servlet.ServletResponse;
19
import javax.servlet.http.HttpServletRequest;
20
import javax.servlet.http.HttpServletResponse;
21

    
22
import com.google.common.base.Joiner;
23
import com.google.common.base.Splitter;
24
import com.google.common.collect.Lists;
25
import com.google.common.collect.Maps;
26
import com.google.common.xml.XmlEscapers;
27
import eu.dnetlib.openaire.exporter.model.Project;
28
import eu.dnetlib.openaire.exporter.model.ProjectDetail;
29
import org.antlr.stringtemplate.StringTemplate;
30
import org.apache.commons.io.IOUtils;
31
import org.apache.commons.lang.StringUtils;
32
import org.apache.commons.lang.exception.ExceptionUtils;
33
import org.apache.commons.logging.Log;
34
import org.apache.commons.logging.LogFactory;
35
import org.springframework.beans.factory.annotation.Autowired;
36
import org.springframework.beans.factory.annotation.Value;
37
import org.springframework.core.io.Resource;
38
import org.springframework.dao.DataAccessException;
39
import org.springframework.http.HttpStatus;
40
import org.springframework.stereotype.Controller;
41
import org.springframework.web.bind.annotation.*;
42

    
43
@Controller
44
public class ProjectsController {
45

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

    
48
	public static final Charset UTF8 = Charset.forName("UTF-8");
49

    
50
	@Value("${openaire.exporter.projectsfundings.sql.template}")
51
	private Resource projectsFundingQueryTemplate;
52

    
53
	@Value("${openaire.exporter.projects2tsv.sql.template}")
54
	private Resource projects2tsvQueryTemplate;
55

    
56
	@Value("${openaire.exporter.dspace.template.project}")
57
	private Resource dspaceTemplate;
58

    
59
	@Value("${openaire.exporter.dspace.template.head}")
60
	private Resource dspaceHeadTemplate;
61

    
62
	@Value("${openaire.exporter.dspace.template.tail}")
63
	private Resource dspaceTailTemplate;
64

    
65
	@Value("${openaire.exporter.eprints.template}")
66
	private Resource eprintsTemplate;
67

    
68
	@Value("${openaire.exporter.projectdetails.sql}")
69
	private Resource projectDetailsSql;
70

    
71
	@Autowired
72
	private JdbcApiDao dao;
73

    
74
	@Autowired
75
	private ProjectQueryParamsFactory projectQueryParamsFactory;
76

    
77
	public enum Funding {
78
		FP7, WT, FCT, H2020, NHMRC, ARC, SFI, MZOS, HRZZ, NWO
79
	}
80

    
81
	@RequestMapping(value = "/openaire/export/**/project/dspace.do")
82
	void processDspace(final HttpServletRequest request,
83
			final ServletResponse response,
84
			@RequestParam(value = "startFrom", required = false) final String startFrom,
85
			@RequestParam(value = "startUntil", required = false) final String startUntil,
86
			@RequestParam(value = "endFrom", required = false) final String endFrom,
87
			@RequestParam(value = "endUntil", required = false) final String endUntil) throws Exception {
88

    
89

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

    
92
		final StringTemplate headSt = new StringTemplate(IOUtils.toString(dspaceHeadTemplate.getInputStream()));
93
		headSt.setAttribute("fundingProgramme", params.getFundingProgramme());
94

    
95
		final StringTemplate tailSt = new StringTemplate(IOUtils.toString(dspaceTailTemplate.getInputStream()));
96

    
97
		response.setContentType("text/xml");
98
		doProcess(response, params, headSt.toString(), dspaceTemplate, tailSt.toString(), new ValueCleaner() {
99
			@Override
100
			public String clean(final String s) {
101
				return XmlEscapers.xmlContentEscaper().escape(oneLiner(s));
102
			}
103
		});
104
	}
105

    
106
	@RequestMapping(value = "/openaire/export/**/project/eprints.do")
107
	void processEprints(final HttpServletRequest request,
108
			final ServletResponse response,
109
			@RequestParam(value = "startFrom", required = false) final String startFrom,
110
			@RequestParam(value = "startUntil", required = false) final String startUntil,
111
			@RequestParam(value = "endFrom", required = false) final String endFrom,
112
			@RequestParam(value = "endUntil", required = false) final String endUntil) throws Exception {
113

    
114
		final ProjectQueryParams params = projectQueryParamsFactory.generateParams(request, startFrom, startUntil, endFrom, endUntil);
115
		response.setContentType("text/html");
116
		doProcess(response, params, null, eprintsTemplate, null, new ValueCleaner() {
117
			@Override
118
			public String clean(final String s) {
119
				return oneLiner(s);
120
			}
121
		});
122
	}
123

    
124
	private String oneLiner(final String s) {
125
		return StringUtils.isNotBlank(s) ? s.replaceAll("\\n", " ").trim() : "";
126
	}
127

    
128
	private void doProcess(
129
			final ServletResponse response,
130
			final ProjectQueryParams params,
131
			final String head, final Resource projectTemplate, final String tail,
132
			final ValueCleaner cleaner) throws IOException {
133

    
134
		final StringTemplate st = new StringTemplate(IOUtils.toString(projectTemplate.getInputStream()));
135
		dao.getProjects(obtainQuery(params), response.getOutputStream(), head, st, tail, cleaner);
136
	}
137

    
138
	@RequestMapping(value = "/openaire/export/project2tsv.do")
139
	void processTsv(final HttpServletRequest request, final HttpServletResponse response,
140
			@RequestParam(value = "funding", required = true) final String funding,
141
			@RequestParam(value = "article293", required = false) final Boolean article293) throws Exception {
142

    
143
		final String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
144
		final String filename = "projects_" + funding + "_" + date + ".tsv";
145
		response.setContentType("text/tab-separated-values");
146
		response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + ".zip\"");
147

    
148
		final StringTemplate st = new StringTemplate(IOUtils.toString(projects2tsvQueryTemplate.getInputStream()));
149
		Funding requestedFunding = Funding.valueOf(funding.toUpperCase());
150
		String fundingPrefix = getFundingPrefix(requestedFunding, null);
151
		log.debug("Setting fundingprefix to " + fundingPrefix);
152
		st.setAttribute("fundingprefix", fundingPrefix);
153
		st.setAttribute("filters", expandFilters(article293));
154

    
155
		final ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
156
		out.putNextEntry(new ZipEntry(filename));
157
		dao.streamProjectsTSV(st.toString(), out);
158
	}
159

    
160
	@RequestMapping(value = "/openaire/export/streamProjectDetails.do")
161
	void streamProjectDetails(final HttpServletResponse response,
162
			@RequestParam(value = "format", required = true) final String format,
163
			@RequestParam(value = "compress", required = false) final Boolean compress) throws IOException {
164
		final String sql = IOUtils.toString(projectDetailsSql.getInputStream());
165

    
166
		if (compress != null && compress) {
167
			response.setHeader("Content-Encoding", "gzip");
168
		}
169
		switch (format) {
170
		case "csv":
171
			response.setContentType("text/csv");
172
			break;
173
		case "json":
174
			response.setContentType("text/plain");
175
			break;
176
		default: throw new IllegalArgumentException("unsupported format: " + format);
177
		}
178

    
179
		final OutputStream outputStream = getOutputStream(response.getOutputStream(), compress);
180
		dao.streamProjectDetails(sql, outputStream, format);
181
	}
182

    
183
	private OutputStream getOutputStream(final ServletOutputStream outputStream, final Boolean compress) throws IOException {
184
		if (compress != null && compress) {
185
			return new GZIPOutputStream(outputStream);
186
		}
187
		return outputStream;
188
	}
189

    
190
	@ExceptionHandler({Exception.class, Throwable.class})
191
	@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
192
	public @ResponseBody ErrorMessage handleSqlException(final Exception e) {
193
		log.error(e.getMessage());
194
		return new ErrorMessage(e);
195
	}
196

    
197
	public class ErrorMessage {
198

    
199
		private final String message;
200
		private final String stacktrace;
201

    
202
		public ErrorMessage(final Exception e) {
203
			this(e.getMessage(), ExceptionUtils.getStackTrace(e));
204
		}
205

    
206
		public ErrorMessage(final String message, final String stacktrace) {
207
			this.message = message;
208
			this.stacktrace = stacktrace;
209
		}
210

    
211
		public String getMessage() {
212
			return this.message;
213
		}
214

    
215
		public String getStacktrace() {
216
			return this.stacktrace;
217
		}
218
	}
219

    
220

    
221
	private Map<String, String> expandFilters(final Boolean article293) {
222
		final Map<String, String> res = Maps.newHashMap();
223

    
224
		if (article293 != null) {
225
			res.put("ec_article29_3", String.valueOf(article293));
226
		}
227

    
228
		return res;
229
	}
230

    
231
	/**
232
	 * Creates the query on the fundingProgramme specified in the given parameters.
233
	 *
234
	 * @param params
235
	 *            request parameters
236
	 * @return the query string
237
	 * @throws IllegalArgumentException
238
	 *             if the funding program is not recognized
239
	 * @throws IOException
240
	 *             if there are problem loading the query temlate
241
	 * @throws IllegalArgumentException
242
	 *             if the funding program is not recognized
243
	 */
244
	protected String obtainQuery(final ProjectQueryParams params) throws IllegalArgumentException, IOException {
245
		String funding = params.getFundingProgramme();
246
		String suffix = params.getFundingPath();
247
		String fundingPrefix = getFundingPrefix(Funding.valueOf(funding.toUpperCase()), suffix);
248
		final StringTemplate st = new StringTemplate(IOUtils.toString(projectsFundingQueryTemplate.getInputStream()));
249
		st.setAttribute("fundingprefix", fundingPrefix);
250
		String theQuery = setDateParameters(st.toString(), params);
251
		log.debug("Generated query: " + theQuery);
252
		return theQuery;
253
	}
254

    
255
	private String getFundingPrefix(final Funding funding, final String suffix) throws IllegalArgumentException {
256
		switch (funding) {
257
		case FCT:
258
			if (StringUtils.isBlank(suffix)) return "fct_________::FCT::";
259
			else return "fct_________::FCT::" + suffix;
260
		case WT:
261
			if (StringUtils.isBlank(suffix)) return "wt__________::WT::";
262
			else return "wt__________::WT::" + suffix;
263
		case FP7:
264
			if (StringUtils.isBlank(suffix)) return "ec__________::EC::FP7::";
265
			else return "ec__________::EC::FP7::" + suffix;
266
		case H2020:
267
			if (StringUtils.isBlank(suffix)) return "ec__________::EC::H2020";
268
			else return "ec__________::EC::H2020" + suffix;
269
		case NHMRC:
270
			if (StringUtils.isBlank(suffix)) return "nhmrc_______::NHMRC::";
271
			else return "nhmrc_______::NHMRC::" + suffix;
272
		case ARC:
273
			if (StringUtils.isBlank(suffix)) return "arc_________::ARC::";
274
			else return "arc_________::ARC::" + suffix;
275
		case SFI:
276
			if (StringUtils.isBlank(suffix)) return "sfi_________::SFI::";
277
			else return "sfi_________::SFI::" + suffix;
278
		case MZOS:
279
			if (StringUtils.isBlank(suffix)) return "irb_hr______::MZOS";
280
			else return "irb_hr______::MZOS::" + suffix;
281
		case HRZZ:
282
			if (StringUtils.isBlank(suffix)) return "irb_hr______::HRZZ";
283
			else return "irb_hr______::HRZZ::" + suffix;
284
		case NWO:
285
			if (StringUtils.isBlank(suffix)) return "nwo_________::NWO";
286
			else return "nwo_________::NWO::" + suffix;
287
		default:
288
			throw new IllegalArgumentException("Invalid funding " + funding + " (valid are: " + Arrays.asList(Funding.values()) + ") ");
289
		}
290
	}
291

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

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

    
313
}
(4-4/5)