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 43782 claudio.at
import java.net.SocketException;
7 43755 claudio.at
import java.nio.charset.Charset;
8 43779 claudio.at
import java.sql.SQLException;
9 34239 michele.ar
import java.text.SimpleDateFormat;
10 40912 alessia.ba
import java.util.Arrays;
11 34239 michele.ar
import java.util.Date;
12
import java.util.List;
13 39128 claudio.at
import java.util.Map;
14 43779 claudio.at
import java.util.zip.GZIPOutputStream;
15 43755 claudio.at
import java.util.zip.ZipEntry;
16
import java.util.zip.ZipOutputStream;
17 43779 claudio.at
import javax.servlet.ServletOutputStream;
18 28340 alessia.ba
import javax.servlet.ServletResponse;
19
import javax.servlet.http.HttpServletRequest;
20 34239 michele.ar
import javax.servlet.http.HttpServletResponse;
21 28340 alessia.ba
22 40139 alessia.ba
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 43807 claudio.at
import com.google.common.xml.XmlEscapers;
27 43779 claudio.at
import eu.dnetlib.openaire.exporter.model.Project;
28
import eu.dnetlib.openaire.exporter.model.ProjectDetail;
29 34253 michele.ar
import org.antlr.stringtemplate.StringTemplate;
30 28340 alessia.ba
import org.apache.commons.io.IOUtils;
31 33397 alessia.ba
import org.apache.commons.lang.StringUtils;
32 43779 claudio.at
import org.apache.commons.lang.exception.ExceptionUtils;
33 28340 alessia.ba
import org.apache.commons.logging.Log;
34
import org.apache.commons.logging.LogFactory;
35 28386 alessia.ba
import org.springframework.beans.factory.annotation.Autowired;
36
import org.springframework.beans.factory.annotation.Value;
37 28340 alessia.ba
import org.springframework.core.io.Resource;
38 43779 claudio.at
import org.springframework.dao.DataAccessException;
39
import org.springframework.http.HttpStatus;
40 28386 alessia.ba
import org.springframework.stereotype.Controller;
41 43779 claudio.at
import org.springframework.web.bind.annotation.*;
42 28340 alessia.ba
43 28386 alessia.ba
@Controller
44 28340 alessia.ba
public class ProjectsController {
45
46 41363 alessia.ba
	private static final Log log = LogFactory.getLog(ProjectsController.class); // NOPMD by marko on 11/24/08 5:02 PM
47 28386 alessia.ba
48 43755 claudio.at
	public static final Charset UTF8 = Charset.forName("UTF-8");
49
50 35906 alessia.ba
	@Value("${openaire.exporter.projectsfundings.sql.template}")
51
	private Resource projectsFundingQueryTemplate;
52 43755 claudio.at
53 34253 michele.ar
	@Value("${openaire.exporter.projects2tsv.sql.template}")
54
	private Resource projects2tsvQueryTemplate;
55 43755 claudio.at
56 43807 claudio.at
	@Value("${openaire.exporter.dspace.template.project}")
57 43755 claudio.at
	private Resource dspaceTemplate;
58
59 43807 claudio.at
	@Value("${openaire.exporter.dspace.template.head}")
60
	private Resource dspaceHeadTemplate;
61
62
	@Value("${openaire.exporter.dspace.template.tail}")
63
	private Resource dspaceTailTemplate;
64
65 43755 claudio.at
	@Value("${openaire.exporter.eprints.template}")
66
	private Resource eprintsTemplate;
67
68 43779 claudio.at
	@Value("${openaire.exporter.projectdetails.sql}")
69
	private Resource projectDetailsSql;
70
71 28386 alessia.ba
	@Autowired
72 43755 claudio.at
	private JdbcApiDao dao;
73
74 28386 alessia.ba
	@Autowired
75 28340 alessia.ba
	private ProjectQueryParamsFactory projectQueryParamsFactory;
76
77 43755 claudio.at
	public enum Funding {
78
		FP7, WT, FCT, H2020, NHMRC, ARC, SFI, MZOS, HRZZ, NWO
79
	}
80
81 28340 alessia.ba
	@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 43826 claudio.at
90 43807 claudio.at
		final ProjectQueryParams params = projectQueryParamsFactory.generateParams(request, startFrom, startUntil, endFrom, endUntil);
91 28340 alessia.ba
92 43807 claudio.at
		final StringTemplate headSt = new StringTemplate(IOUtils.toString(dspaceHeadTemplate.getInputStream()));
93
		headSt.setAttribute("fundingProgramme", params.getFundingProgramme());
94 28340 alessia.ba
95 43807 claudio.at
		final StringTemplate tailSt = new StringTemplate(IOUtils.toString(dspaceTailTemplate.getInputStream()));
96
97 43826 claudio.at
		response.setContentType("text/xml");
98 43807 claudio.at
		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 28340 alessia.ba
	}
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 29218 alessia.ba
114 43807 claudio.at
		final ProjectQueryParams params = projectQueryParamsFactory.generateParams(request, startFrom, startUntil, endFrom, endUntil);
115 43826 claudio.at
		response.setContentType("text/html");
116 43807 claudio.at
		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 43755 claudio.at
124 43807 claudio.at
	private String oneLiner(final String s) {
125
		return StringUtils.isNotBlank(s) ? s.replaceAll("\\n", " ").trim() : "";
126 28340 alessia.ba
	}
127
128 43807 claudio.at
	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 34239 michele.ar
	@RequestMapping(value = "/openaire/export/project2tsv.do")
139 39128 claudio.at
	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 34253 michele.ar
143 34239 michele.ar
		final String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
144 43755 claudio.at
		final String filename = "projects_" + funding + "_" + date + ".tsv";
145 34239 michele.ar
		response.setContentType("text/tab-separated-values");
146 43755 claudio.at
		response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + ".zip\"");
147 34253 michele.ar
148
		final StringTemplate st = new StringTemplate(IOUtils.toString(projects2tsvQueryTemplate.getInputStream()));
149 35906 alessia.ba
		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 39128 claudio.at
		st.setAttribute("filters", expandFilters(article293));
154 43755 claudio.at
155
		final ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
156
		out.putNextEntry(new ZipEntry(filename));
157 43826 claudio.at
		dao.streamProjectsTSV(st.toString(), out);
158 34239 michele.ar
	}
159
160 43779 claudio.at
	@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 43826 claudio.at
	@ExceptionHandler({Exception.class, Throwable.class})
191 43779 claudio.at
	@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
192
	public @ResponseBody ErrorMessage handleSqlException(final Exception e) {
193 43782 claudio.at
		log.error(e.getMessage());
194 43779 claudio.at
		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 39128 claudio.at
	private Map<String, String> expandFilters(final Boolean article293) {
222
		final Map<String, String> res = Maps.newHashMap();
223
224
		if (article293 != null) {
225 43755 claudio.at
			res.put("ec_article29_3", String.valueOf(article293));
226 39128 claudio.at
		}
227
228
		return res;
229
	}
230
231 28360 alessia.ba
	/**
232
	 * Creates the query on the fundingProgramme specified in the given parameters.
233 39107 claudio.at
	 *
234 28360 alessia.ba
	 * @param params
235
	 *            request parameters
236
	 * @return the query string
237
	 * @throws IllegalArgumentException
238 35906 alessia.ba
	 *             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 28360 alessia.ba
	 */
244 35906 alessia.ba
	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 36356 alessia.ba
		String theQuery = setDateParameters(st.toString(), params);
251
		log.debug("Generated query: " + theQuery);
252
		return theQuery;
253 35906 alessia.ba
	}
254
255
	private String getFundingPrefix(final Funding funding, final String suffix) throws IllegalArgumentException {
256
		switch (funding) {
257
		case FCT:
258 37854 alessia.ba
			if (StringUtils.isBlank(suffix)) return "fct_________::FCT::";
259
			else return "fct_________::FCT::" + suffix;
260 35906 alessia.ba
		case WT:
261
			if (StringUtils.isBlank(suffix)) return "wt__________::WT::";
262
			else return "wt__________::WT::" + suffix;
263 28360 alessia.ba
		case FP7:
264 37854 alessia.ba
			if (StringUtils.isBlank(suffix)) return "ec__________::EC::FP7::";
265
			else return "ec__________::EC::FP7::" + suffix;
266 35906 alessia.ba
		case H2020:
267 39107 claudio.at
			if (StringUtils.isBlank(suffix)) return "ec__________::EC::H2020";
268
			else return "ec__________::EC::H2020" + suffix;
269 37858 alessia.ba
		case NHMRC:
270 37867 alessia.ba
			if (StringUtils.isBlank(suffix)) return "nhmrc_______::NHMRC::";
271
			else return "nhmrc_______::NHMRC::" + suffix;
272 37858 alessia.ba
		case ARC:
273
			if (StringUtils.isBlank(suffix)) return "arc_________::ARC::";
274
			else return "arc_________::ARC::" + suffix;
275 40139 alessia.ba
		case SFI:
276
			if (StringUtils.isBlank(suffix)) return "sfi_________::SFI::";
277
			else return "sfi_________::SFI::" + suffix;
278 43177 alessia.ba
		case MZOS:
279 43181 alessia.ba
			if (StringUtils.isBlank(suffix)) return "irb_hr______::MZOS";
280 43177 alessia.ba
			else return "irb_hr______::MZOS::" + suffix;
281
		case HRZZ:
282 43181 alessia.ba
			if (StringUtils.isBlank(suffix)) return "irb_hr______::HRZZ";
283 43177 alessia.ba
			else return "irb_hr______::HRZZ::" + suffix;
284 42994 alessia.ba
		case NWO:
285
			if (StringUtils.isBlank(suffix)) return "nwo_________::NWO";
286
			else return "nwo_________::NWO::" + suffix;
287 28360 alessia.ba
		default:
288 40912 alessia.ba
			throw new IllegalArgumentException("Invalid funding " + funding + " (valid are: " + Arrays.asList(Funding.values()) + ") ");
289 28360 alessia.ba
		}
290
	}
291
292
	private String setDateParameters(final String query, final ProjectQueryParams params) {
293
		String queryWithDates = query;
294
		if (params.getStartFrom() != null) {
295 43755 claudio.at
			queryWithDates += " AND startdate >= '" + params.getStartFrom() + "'";
296 28360 alessia.ba
		}
297
		if (params.getStartUntil() != null) {
298 43755 claudio.at
			queryWithDates += " AND startdate <= '" + params.getStartUntil() + "'";
299 28360 alessia.ba
		}
300
		if (params.getEndFrom() != null) {
301 43755 claudio.at
			queryWithDates += " AND enddate >= '" + params.getEndFrom() + "'";
302 28360 alessia.ba
		}
303
		if (params.getEndUntil() != null) {
304 43755 claudio.at
			queryWithDates += " AND enddate <= '" + params.getEndUntil() + "'";
305 28360 alessia.ba
		}
306
		return queryWithDates;
307
	}
308
309 35906 alessia.ba
	public void setProjectsFundingQueryTemplate(final Resource projectsFundingQueryTemplate) {
310
		this.projectsFundingQueryTemplate = projectsFundingQueryTemplate;
311
	}
312
313 28340 alessia.ba
}