Project

General

Profile

1 28340 alessia.ba
package eu.dnetlib.openaire.exporter;
2
3 43755 claudio.at
import java.io.BufferedOutputStream;
4 28340 alessia.ba
import java.io.IOException;
5
import java.io.OutputStream;
6 43834 claudio.at
import java.sql.SQLException;
7 34239 michele.ar
import java.text.SimpleDateFormat;
8 40912 alessia.ba
import java.util.Arrays;
9 34239 michele.ar
import java.util.Date;
10 39128 claudio.at
import java.util.Map;
11 43779 claudio.at
import java.util.zip.GZIPOutputStream;
12 43755 claudio.at
import java.util.zip.ZipEntry;
13
import java.util.zip.ZipOutputStream;
14 43779 claudio.at
import javax.servlet.ServletOutputStream;
15 28340 alessia.ba
import javax.servlet.ServletResponse;
16
import javax.servlet.http.HttpServletRequest;
17 34239 michele.ar
import javax.servlet.http.HttpServletResponse;
18 28340 alessia.ba
19 40139 alessia.ba
import com.google.common.collect.Maps;
20 43807 claudio.at
import com.google.common.xml.XmlEscapers;
21 34253 michele.ar
import org.antlr.stringtemplate.StringTemplate;
22 28340 alessia.ba
import org.apache.commons.io.IOUtils;
23 33397 alessia.ba
import org.apache.commons.lang.StringUtils;
24 43779 claudio.at
import org.apache.commons.lang.exception.ExceptionUtils;
25 28340 alessia.ba
import org.apache.commons.logging.Log;
26
import org.apache.commons.logging.LogFactory;
27 28386 alessia.ba
import org.springframework.beans.factory.annotation.Autowired;
28
import org.springframework.beans.factory.annotation.Value;
29 28340 alessia.ba
import org.springframework.core.io.Resource;
30 43779 claudio.at
import org.springframework.http.HttpStatus;
31 28386 alessia.ba
import org.springframework.stereotype.Controller;
32 43779 claudio.at
import org.springframework.web.bind.annotation.*;
33 28340 alessia.ba
34 28386 alessia.ba
@Controller
35 28340 alessia.ba
public class ProjectsController {
36
37 41363 alessia.ba
	private static final Log log = LogFactory.getLog(ProjectsController.class); // NOPMD by marko on 11/24/08 5:02 PM
38 28386 alessia.ba
39 35906 alessia.ba
	@Value("${openaire.exporter.projectsfundings.sql.template}")
40
	private Resource projectsFundingQueryTemplate;
41 43755 claudio.at
42 34253 michele.ar
	@Value("${openaire.exporter.projects2tsv.sql.template}")
43
	private Resource projects2tsvQueryTemplate;
44 43755 claudio.at
45 43807 claudio.at
	@Value("${openaire.exporter.dspace.template.project}")
46 43755 claudio.at
	private Resource dspaceTemplate;
47
48 43807 claudio.at
	@Value("${openaire.exporter.dspace.template.head}")
49
	private Resource dspaceHeadTemplate;
50
51
	@Value("${openaire.exporter.dspace.template.tail}")
52
	private Resource dspaceTailTemplate;
53
54 43755 claudio.at
	@Value("${openaire.exporter.eprints.template}")
55
	private Resource eprintsTemplate;
56
57 43779 claudio.at
	@Value("${openaire.exporter.projectdetails.sql}")
58
	private Resource projectDetailsSql;
59
60 28386 alessia.ba
	@Autowired
61 43755 claudio.at
	private JdbcApiDao dao;
62
63 28386 alessia.ba
	@Autowired
64 28340 alessia.ba
	private ProjectQueryParamsFactory projectQueryParamsFactory;
65
66 43755 claudio.at
	public enum Funding {
67 45369 alessia.ba
		FP7, WT, FCT, H2020, NHMRC, ARC, SFI, MZOS, HRZZ, NWO, MESTD, FWF, SNSF
68 43755 claudio.at
	}
69
70 28340 alessia.ba
	@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 43826 claudio.at
79 43807 claudio.at
		final ProjectQueryParams params = projectQueryParamsFactory.generateParams(request, startFrom, startUntil, endFrom, endUntil);
80 28340 alessia.ba
81 43807 claudio.at
		final StringTemplate headSt = new StringTemplate(IOUtils.toString(dspaceHeadTemplate.getInputStream()));
82
		headSt.setAttribute("fundingProgramme", params.getFundingProgramme());
83 28340 alessia.ba
84 43807 claudio.at
		final StringTemplate tailSt = new StringTemplate(IOUtils.toString(dspaceTailTemplate.getInputStream()));
85
86 43826 claudio.at
		response.setContentType("text/xml");
87 43807 claudio.at
		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 28340 alessia.ba
	}
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 29218 alessia.ba
103 43807 claudio.at
		final ProjectQueryParams params = projectQueryParamsFactory.generateParams(request, startFrom, startUntil, endFrom, endUntil);
104 43826 claudio.at
		response.setContentType("text/html");
105 43807 claudio.at
		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 43755 claudio.at
113 43807 claudio.at
	private String oneLiner(final String s) {
114
		return StringUtils.isNotBlank(s) ? s.replaceAll("\\n", " ").trim() : "";
115 28340 alessia.ba
	}
116
117 43807 claudio.at
	private void doProcess(
118
			final ServletResponse response,
119
			final ProjectQueryParams params,
120
			final String head, final Resource projectTemplate, final String tail,
121 43834 claudio.at
			final ValueCleaner cleaner) throws IOException, SQLException {
122 43807 claudio.at
123
		final StringTemplate st = new StringTemplate(IOUtils.toString(projectTemplate.getInputStream()));
124 43827 alessia.ba
		dao.streamProjects(obtainQuery(params), response.getOutputStream(), head, st, tail, cleaner);
125 43807 claudio.at
	}
126
127 34239 michele.ar
	@RequestMapping(value = "/openaire/export/project2tsv.do")
128 39128 claudio.at
	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 34253 michele.ar
132 34239 michele.ar
		final String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
133 43755 claudio.at
		final String filename = "projects_" + funding + "_" + date + ".tsv";
134 34239 michele.ar
		response.setContentType("text/tab-separated-values");
135 43755 claudio.at
		response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + ".zip\"");
136 34253 michele.ar
137
		final StringTemplate st = new StringTemplate(IOUtils.toString(projects2tsvQueryTemplate.getInputStream()));
138 35906 alessia.ba
		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 39128 claudio.at
		st.setAttribute("filters", expandFilters(article293));
143 43755 claudio.at
144
		final ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
145
		out.putNextEntry(new ZipEntry(filename));
146 43826 claudio.at
		dao.streamProjectsTSV(st.toString(), out);
147 34239 michele.ar
	}
148
149 43779 claudio.at
	@RequestMapping(value = "/openaire/export/streamProjectDetails.do")
150
	void streamProjectDetails(final HttpServletResponse response,
151
			@RequestParam(value = "format", required = true) final String format,
152 43834 claudio.at
			@RequestParam(value = "compress", required = false) final Boolean compress) throws IOException, SQLException {
153 43779 claudio.at
		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 43826 claudio.at
	@ExceptionHandler({Exception.class, Throwable.class})
180 43779 claudio.at
	@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
181
	public @ResponseBody ErrorMessage handleSqlException(final Exception e) {
182 43782 claudio.at
		log.error(e.getMessage());
183 43779 claudio.at
		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 39128 claudio.at
	private Map<String, String> expandFilters(final Boolean article293) {
211
		final Map<String, String> res = Maps.newHashMap();
212
213
		if (article293 != null) {
214 43755 claudio.at
			res.put("ec_article29_3", String.valueOf(article293));
215 39128 claudio.at
		}
216
217
		return res;
218
	}
219
220 28360 alessia.ba
	/**
221
	 * Creates the query on the fundingProgramme specified in the given parameters.
222 39107 claudio.at
	 *
223 28360 alessia.ba
	 * @param params
224
	 *            request parameters
225
	 * @return the query string
226
	 * @throws IllegalArgumentException
227 35906 alessia.ba
	 *             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 28360 alessia.ba
	 */
233 35906 alessia.ba
	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 36356 alessia.ba
		String theQuery = setDateParameters(st.toString(), params);
240
		log.debug("Generated query: " + theQuery);
241
		return theQuery;
242 35906 alessia.ba
	}
243
244
	private String getFundingPrefix(final Funding funding, final String suffix) throws IllegalArgumentException {
245
		switch (funding) {
246
		case FCT:
247 45369 alessia.ba
			if (StringUtils.isBlank(suffix)) return "fct_________::FCT";
248 37854 alessia.ba
			else return "fct_________::FCT::" + suffix;
249 35906 alessia.ba
		case WT:
250 45369 alessia.ba
			if (StringUtils.isBlank(suffix)) return "wt__________::WT";
251 35906 alessia.ba
			else return "wt__________::WT::" + suffix;
252 28360 alessia.ba
		case FP7:
253 45369 alessia.ba
			if (StringUtils.isBlank(suffix)) return "ec__________::EC::FP7";
254 37854 alessia.ba
			else return "ec__________::EC::FP7::" + suffix;
255 35906 alessia.ba
		case H2020:
256 39107 claudio.at
			if (StringUtils.isBlank(suffix)) return "ec__________::EC::H2020";
257
			else return "ec__________::EC::H2020" + suffix;
258 37858 alessia.ba
		case NHMRC:
259 45369 alessia.ba
			if (StringUtils.isBlank(suffix)) return "nhmrc_______::NHMRC";
260 37867 alessia.ba
			else return "nhmrc_______::NHMRC::" + suffix;
261 37858 alessia.ba
		case ARC:
262 45369 alessia.ba
			if (StringUtils.isBlank(suffix)) return "arc_________::ARC";
263 37858 alessia.ba
			else return "arc_________::ARC::" + suffix;
264 40139 alessia.ba
		case SFI:
265 45369 alessia.ba
			if (StringUtils.isBlank(suffix)) return "sfi_________::SFI";
266 40139 alessia.ba
			else return "sfi_________::SFI::" + suffix;
267 43177 alessia.ba
		case MZOS:
268 43181 alessia.ba
			if (StringUtils.isBlank(suffix)) return "irb_hr______::MZOS";
269 43177 alessia.ba
			else return "irb_hr______::MZOS::" + suffix;
270
		case HRZZ:
271 43181 alessia.ba
			if (StringUtils.isBlank(suffix)) return "irb_hr______::HRZZ";
272 43177 alessia.ba
			else return "irb_hr______::HRZZ::" + suffix;
273 42994 alessia.ba
		case NWO:
274
			if (StringUtils.isBlank(suffix)) return "nwo_________::NWO";
275
			else return "nwo_________::NWO::" + suffix;
276 44074 alessia.ba
		case MESTD:
277
			if (StringUtils.isBlank(suffix)) return "mestd_______::MESTD";
278
			else return "mestd_______::MESTD::" + suffix;
279 44251 alessia.ba
		case FWF:
280
			if (StringUtils.isBlank(suffix)) return "fwf_________::FWF";
281
			else return "fwf_________::FWF::" + suffix;
282 45369 alessia.ba
		case SNSF:
283
			if (StringUtils.isBlank(suffix)) return "snsf________::SNSF";
284
			else return "snsf________::SNSF::" + suffix;
285 28360 alessia.ba
		default:
286 40912 alessia.ba
			throw new IllegalArgumentException("Invalid funding " + funding + " (valid are: " + Arrays.asList(Funding.values()) + ") ");
287 28360 alessia.ba
		}
288
	}
289
290
	private String setDateParameters(final String query, final ProjectQueryParams params) {
291
		String queryWithDates = query;
292
		if (params.getStartFrom() != null) {
293 43755 claudio.at
			queryWithDates += " AND startdate >= '" + params.getStartFrom() + "'";
294 28360 alessia.ba
		}
295
		if (params.getStartUntil() != null) {
296 43755 claudio.at
			queryWithDates += " AND startdate <= '" + params.getStartUntil() + "'";
297 28360 alessia.ba
		}
298
		if (params.getEndFrom() != null) {
299 43755 claudio.at
			queryWithDates += " AND enddate >= '" + params.getEndFrom() + "'";
300 28360 alessia.ba
		}
301
		if (params.getEndUntil() != null) {
302 43755 claudio.at
			queryWithDates += " AND enddate <= '" + params.getEndUntil() + "'";
303 28360 alessia.ba
		}
304
		return queryWithDates;
305
	}
306
307 35906 alessia.ba
	public void setProjectsFundingQueryTemplate(final Resource projectsFundingQueryTemplate) {
308
		this.projectsFundingQueryTemplate = projectsFundingQueryTemplate;
309
	}
310
311 28340 alessia.ba
}