Project

General

Profile

1
package eu.dnetlib.data.search.web.api;
2

    
3
import com.google.common.collect.Iterables;
4
import eu.dnetlib.data.search.app.SearchServiceImpl;
5
import eu.dnetlib.data.search.utils.vocabulary.VocabularyManager;
6
import eu.dnetlib.domain.data.FormattedSearchResult;
7
import org.apache.commons.collections.ListUtils;
8
import org.apache.commons.io.IOUtils;
9
import org.apache.commons.lang.IncompleteArgumentException;
10
import org.apache.commons.lang.StringEscapeUtils;
11
import org.apache.log4j.Logger;
12
import org.springframework.beans.factory.annotation.Autowired;
13
import org.springframework.stereotype.Controller;
14
import org.springframework.ui.ModelMap;
15
import org.springframework.web.bind.annotation.RequestMapping;
16
import org.springframework.web.bind.annotation.RequestMethod;
17

    
18
import javax.annotation.Resource;
19
import javax.servlet.http.HttpServletRequest;
20
import javax.servlet.http.HttpServletResponse;
21
import java.io.PrintWriter;
22
import java.text.SimpleDateFormat;
23
import java.util.*;
24

    
25
@Controller
26
public class SearchRequestController {
27

    
28
	@Autowired
29
	private SearchServiceImpl searchService = null;
30
	@Autowired
31
	private VocabularyManager vocabularyManager = null;
32

    
33
	@Resource
34
	private String maxResults = null;
35

    
36
	@Resource
37
	private String maxSize = null;
38

    
39
	private static Logger logger = Logger.getLogger(SearchRequestController.class);
40

    
41
	private static final String XML_CONTENT_TYPE = "application/xml;charset=UTF-8";
42
	private static final String JSON_CONTENT_TYPE = "application/json;charset=UTF-8;";
43
    private static final String CSV_CONTENT_TYPE = "text/csv;charset=UTF-8;";
44
    private static final String TSV_CONTENT_TYPE = "text/tab-separated-values;charset=UTF-8;";
45
    private static final String HTML_CONTENT_TYPE = "text/html;charset=UTF-8;";
46

    
47
    private static final String PUBLICATION_BASIC_QUERY = "(oaftype exact result) and (resulttypeid exact publication)";
48
    private static final String DATASET_BASIC_QUERY = "(oaftype exact result) and (resulttypeid exact dataset)";
49
    private static final String PROJECT_BASIC_QUERY = "(oaftype exact project)";
50

    
51
    private static final List<String> GLOBAL_PARAMETERS = Arrays.asList("page", "size", "format", "sortBy");
52

    
53
    private static final List<String> PUB_N_DATA_COMMON_PARAMETERS = Arrays.asList("author", "doi", "FP7ProjectID", "FP7scientificArea",
54
            "fromDateAccepted", "funder", "fundingStream", "hasECFunding", "hasProject", "hasWTFunding", "keywords",
55
            "model", "OA", "openaireAuthorID", "openaireProjectID", "openaireProviderID", "projectID", "title", "toDateAccepted");
56

    
57
    private static final List<String> PUB_PARAMETERS = Arrays.asList("openairePublicationID");
58
    private static final List<String> DATA_PARAMETERS = Arrays.asList("openaireDatasetID");
59

    
60
    private static final List<String> PUB_N_DATASET_MODELS = Arrays.asList("dc", "openaire", "sygma");
61
    private static final List<String> PUB_N_DATASET_FORMATS = Arrays.asList("json", "rss", "xml", "csv", "tsv", "html");
62

    
63
    private static final List<String> PROJECT_PARAMETERS = Arrays.asList("acronym", "callID", "endYear", "FP7scientificArea",
64
            "funder", "fundingStream", "grantID", "hasECFunding", "hasWTFunding", "keywords", "name",
65
            "participantAcronyms", "participantCountries", "startYear", "sc39", "openaireParticipantID", "openaireProjectID");
66
    private static final List<String> PROJECT_FORMATS = Arrays.asList("xml", "json", "csv", "tsv", "html");
67

    
68
	@RequestMapping(value = "/search", method = RequestMethod.GET)
69
	public void search(HttpServletRequest request, HttpServletResponse response) {
70

    
71
		PrintWriter writer = null;
72
		FormattedSearchResult formattedSearchResult = null;
73

    
74
		String action = request.getParameter("action");
75
		if (action == null) {
76
			throw new UnsupportedOperationException("Undefined action.");
77
		}
78

    
79
		String query = request.getParameter("query");
80
		if (query == null) {
81
			throw new IncompleteArgumentException("Undefined query. Search request");
82
		}
83

    
84
		String format = (request.getParameter("format") != null) ? request.getParameter("format") : "xml";
85
        createResponseMeta(response, format, "UTF-8");
86

    
87
		String locale = request.getParameter("locale");
88

    
89
		int page = readParameter(request, "page", 1);
90
		int size = readParameter(request, "size", 10);
91

    
92
		if (size > Integer.parseInt(maxSize)) {
93
			throw new IllegalArgumentException("Size argument have exceeded the maximum allowed number.");
94
		}
95

    
96
		String sTransformer = request.getParameter("sTransformer");
97
		String rTransformer = request.getParameter("rTransformer");
98

    
99
		Collection<String> fields = readParameter(request, "fields");
100

    
101

    
102
		try {
103
			writer = response.getWriter();
104
			if (action.equals("search")) {
105
				if (sTransformer == null) {
106
					throw new IncompleteArgumentException(
107
							"Undefined search transformer. Search request");
108
				}
109

    
110
				formattedSearchResult = searchService.search(query,
111
						sTransformer, format, locale, page, size);
112

    
113
			} else if (action.equals("refine")) {
114
				if (rTransformer == null) {
115
					throw new IncompleteArgumentException(
116
							"Undefined refine transformer. Refine request");
117
				}
118

    
119
				if (fields == null) {
120
					throw new IncompleteArgumentException(
121
							"Undefined refine fields. Refine request");
122
				}
123

    
124
				formattedSearchResult = searchService.refine(query,
125
						rTransformer, format, locale, fields);
126

    
127
			} else if (action.equals("searchNrefine")) {
128

    
129
				if (sTransformer == null) {
130
					throw new IncompleteArgumentException(
131
							"Undefined search transformer. Search and Refine request");
132
				}
133

    
134
				if (rTransformer == null) {
135
					throw new IncompleteArgumentException(
136
							"Undefined refine transformer. Search and Refine request");
137
				}
138

    
139
				if (fields == null) {
140
					throw new IncompleteArgumentException(
141
							"Undefined refine fields. Search and Refine request");
142
				}
143

    
144
				formattedSearchResult = searchService.searchNrefine(query,
145
						sTransformer, rTransformer, format, locale, page, size,
146
						fields);
147

    
148
			} else {
149
				throw new UnsupportedOperationException("The action " + action
150
						+ " is not supported. Please try one of {search, refine, searchNrefine}.");
151
			}
152

    
153
			writer.append(formattedSearchResult.getFormattedResult());
154

    
155
		} catch (Exception e) {
156
			logger.error("Fail to execute search.", e);
157
			createXmlErrorPage(writer, e);
158

    
159
		} finally {
160
            if (writer != null) {
161
                writer.close();
162
            }
163
		}
164
	}
165

    
166
	
167
    @RequestMapping(value="/search/openSearchDescriptor", method = RequestMethod.GET)
168
    public String printOpenSearchDescriptor(ModelMap model) {
169
        return "openSearchDescriptor";
170
    }
171

    
172
	@RequestMapping(value = "/api/publications", method = RequestMethod.GET)
173
	public void searchPublications(HttpServletRequest request, HttpServletResponse response) {
174

    
175
		PrintWriter writer = null;
176

    
177
        try {
178
            writer = response.getWriter();
179

    
180
            checkParameters(ListUtils.union(PUB_N_DATA_COMMON_PARAMETERS, PUB_PARAMETERS),request.getParameterMap());
181

    
182
            int page = readParameter(request, "page", 1);
183
            int size = readParameter(request, "size", 10);
184
            checkRequestSize(page, size);
185

    
186
            String format = (request.getParameter("format") != null) ? request.getParameter("format") : "xml";
187
            checkFormatParameter(PUB_N_DATASET_FORMATS, format);
188
            createResponseMeta(response, format, "UTF-8");
189

    
190
            String locale = request.getParameter("locale");
191

    
192
            String model = request.getParameter("model");
193
            checkModelParameter(PUB_N_DATASET_MODELS, model);
194
            String sTransformer = defineTransformer(model,format);
195

    
196
            Collection<String> referrers = readParameter(request,"referrer");
197
            String newFormat = defineFormatter(model, format, true, referrers);
198
            logger.debug("FORMATTER " + newFormat);
199

    
200
            StringBuilder queryBuilder = new StringBuilder();
201
            queryBuilder.append(PUBLICATION_BASIC_QUERY);
202

    
203
			QueryEnhancer.enhanceQueryWithFundingLevelParams(queryBuilder, request, vocabularyManager, isModelSygma(model));
204
            QueryEnhancer.enhanceQueryWithOpenAIREIds(queryBuilder, request);
205
            QueryEnhancer.enhanceQueryWithMetadataKeywords(queryBuilder, request);
206
            QueryEnhancer.enhanceQueryWithFundingParams(queryBuilder, request);
207
            QueryEnhancer.enhanceQueryWithRelProjectParams(queryBuilder, request);
208
            QueryEnhancer.enhanceQueryWithAccessRights(queryBuilder, request);
209
            QueryEnhancer.enhanceQueryWithDate(queryBuilder, request);
210
            QueryEnhancer.enhanceQueryWithDoi(queryBuilder, request);
211

    
212
            QueryEnhancer.enhanceQueryWithResultsSortParameters(queryBuilder, request);
213

    
214
			FormattedSearchResult formattedSearchResult = searchService.search(queryBuilder.toString(),sTransformer, (newFormat!=null)?newFormat:format, locale, page, size);
215
			writer.append(formattedSearchResult.getFormattedResult());
216

    
217
		} catch (Exception e) {
218
			logger.error("Fail to execute search.", e);
219
			createXmlErrorPage(writer, e);
220

    
221
		} finally {
222
            if (writer != null) {
223
                IOUtils.closeQuietly(writer);
224
            }
225
		}
226
	}
227

    
228
	@RequestMapping(value = "/api/datasets", method = RequestMethod.GET)
229
	public void searchData(HttpServletRequest request, HttpServletResponse response) {
230

    
231
		PrintWriter writer = null;
232

    
233
        try {
234
            writer = response.getWriter();
235

    
236
            checkParameters(ListUtils.union(PUB_N_DATA_COMMON_PARAMETERS, DATA_PARAMETERS),request.getParameterMap());
237

    
238
            int page = readParameter(request, "page", 1);
239
            int size = readParameter(request, "size", 10);
240
            checkRequestSize(page, size);
241

    
242
            String format = (request.getParameter("format") != null) ? request.getParameter("format") : "xml";
243
            createResponseMeta(response, format, "UTF-8");
244

    
245
            checkFormatParameter(PUB_N_DATASET_FORMATS, format);
246

    
247
            String model = request.getParameter("model");
248
            checkModelParameter(PUB_N_DATASET_MODELS, model);
249
            String sTransformer = defineTransformer(model,format);
250

    
251
            Collection<String> referrers = readParameter(request,"referrer");
252
            String newFormat = defineFormatter(model, format, false, referrers);
253

    
254
            String locale = request.getParameter("locale");
255

    
256
            StringBuilder queryBuilder = new StringBuilder();
257
            queryBuilder.append(DATASET_BASIC_QUERY);
258

    
259
            QueryEnhancer.enhanceQueryWithFundingLevelParams(queryBuilder, request, vocabularyManager, isModelSygma(model));
260
            QueryEnhancer.enhanceQueryWithOpenAIREIds(queryBuilder, request);
261
            QueryEnhancer.enhanceQueryWithMetadataKeywords(queryBuilder, request);
262
            QueryEnhancer.enhanceQueryWithFundingParams(queryBuilder, request);
263
            QueryEnhancer.enhanceQueryWithRelProjectParams(queryBuilder, request);
264
            QueryEnhancer.enhanceQueryWithAccessRights(queryBuilder, request);
265
            QueryEnhancer.enhanceQueryWithDate(queryBuilder, request);
266
            QueryEnhancer.enhanceQueryWithDoi(queryBuilder, request);
267

    
268
            QueryEnhancer.enhanceQueryWithResultsSortParameters(queryBuilder, request);
269

    
270
			FormattedSearchResult formattedSearchResult =  searchService.search(queryBuilder.toString(),sTransformer, (newFormat!=null)?newFormat:format, locale, page, size);
271
			writer.append(formattedSearchResult.getFormattedResult());
272

    
273
		} catch (Exception e) {
274
			logger.error("Fail to execute search.", e);
275
			createXmlErrorPage(writer, e);
276

    
277
		} finally {
278
            if (writer != null) {
279
                IOUtils.closeQuietly(writer);
280
            }
281
		}
282

    
283
	}
284

    
285
	@RequestMapping(value = "/api/projects", method = RequestMethod.GET)
286
	public void searchProjects(HttpServletRequest request, HttpServletResponse response)  {
287

    
288
		PrintWriter writer = null;
289

    
290
        try {
291
            writer = response.getWriter();
292

    
293
            checkParameters(PROJECT_PARAMETERS, request.getParameterMap());
294

    
295
            int page = readParameter(request, "page", 1);
296
            int size = readParameter(request, "size", 10);
297
            checkRequestSize(page, size);
298

    
299
            StringBuilder queryBuilder = new StringBuilder();
300
            queryBuilder.append(PROJECT_BASIC_QUERY);
301
            String locale = request.getParameter("locale");
302

    
303
            String format = (request.getParameter("format") != null) ? request.getParameter("format") : "xml";
304
            checkFormatParameter(PROJECT_FORMATS, format);
305
            createResponseMeta(response, format, "UTF-8");
306

    
307
            format = finalFormat(format);
308

    
309

    
310
            String sTransformer = request.getParameter("sTransformer");
311

    
312
            FormattedSearchResult formattedSearchResult = null;
313

    
314
            QueryEnhancer.enhanceProjectQueryWithOpenAIREIds(queryBuilder, request);
315
            QueryEnhancer.enhanceQueryWithProjectMetadataKeywords(queryBuilder, request);
316
            QueryEnhancer.enhanceQueryWithProjectFundingParams(queryBuilder, request);
317
            QueryEnhancer.enhanceProjectQueryWithFundingLevelParams(queryBuilder, request, vocabularyManager);
318
            QueryEnhancer.enhanceQueryWithParticipantsInfoParams(queryBuilder, request);
319
            QueryEnhancer.enhanceQueryWithYearParams(queryBuilder, request);
320
            QueryEnhancer.enhanceQueryWithSC39Params(queryBuilder, request);
321

    
322
            QueryEnhancer.enhanceQueryWithProjectSortParameters(queryBuilder, request);
323

    
324
			formattedSearchResult = searchService.search(queryBuilder.toString(),sTransformer, format, locale, page, size);
325
			writer.append(formattedSearchResult.getFormattedResult());
326

    
327
		} catch (Exception e) {
328
			logger.error("Fail to execute search.", e);
329
            createXmlErrorPage(writer, e);
330

    
331
		} finally {
332
            if (writer != null) {
333
                IOUtils.closeQuietly(writer);
334
            }
335
		}
336
	}
337

    
338
    private String finalFormat(String format) {
339
        if (format.equals("tsv")){
340
            return "project_tsv";
341

    
342
        } else if (format.equals("csv")) {
343
            return "project_csv";
344

    
345
        } else if (format.equals("html")) {
346
            return "project_html";
347
        }
348

    
349
        return format;
350
    }
351

    
352
    private String finalFormat(String format, String referrer) {
353
        if (referrer == null || referrer.isEmpty() || !referrer.equals("joomla")) {
354
            return finalFormat(format);
355
        }
356

    
357
        if (format.equals("tsv")){
358
            return "publication_tsv_notitle";
359

    
360
        } else if (format.equals("csv")) {
361
            return "publication_csv_notitle";
362

    
363
        }
364

    
365
        return format;
366
    }
367

    
368
    /**
369
     * Based on the given model the transformer to be used is defined
370
     * @param model
371
     * @return
372
     */
373
    private String defineTransformer(String model) {
374
        if (model!=null && !model.trim().isEmpty()) {
375
            if (model.equals("openaire")) {
376
                return null;
377

    
378
            } else if (model.equals("sygma")) {
379
                return "results_openaire";
380
            }
381
            else if (model.equals("dc")) {
382
                return "dc";
383
            }
384

    
385
            throw new IllegalArgumentException("model '" + model + "' is not supported.");
386

    
387
        } else {
388
            return null;
389
        }
390
    }
391

    
392
 private String defineTransformer(String model, String format) {
393
   if (model!=null && !model.trim().isEmpty()) {
394
            if (model.equals("openaire")) {
395
                return null;
396

    
397
            } else if (model.equals("sygma")) {
398
                return "results_openaire";
399
            }
400
            else if (model.equals("dc")) {
401
                return "dc";
402
            }
403

    
404
            throw new IllegalArgumentException("model '" + model + "' is not supported.");
405

    
406
        } else if (format!=null && !format.trim().isEmpty()){
407
            if (format.equals("rss") || format.equals("csv") || format.equals("tsv") || format.equals("html")){
408
			return "results_openaire";
409
		}
410
        } 
411
		return null;
412
	
413
    }
414

    
415
    private String defineFormatter(String model, String format, boolean isPublications, Collection<String> referrers) {
416
        if( model != null && !model.trim().isEmpty() ) {
417
            if (model.equals("sygma")) {
418

    
419
                if (isPublications) {
420
                    return "sygma_publication";
421
                }
422
                return "sygma_dataset";
423
            }
424
        } else {
425
            if (referrers != null && !referrers.isEmpty() && Iterables.get(referrers, 0) != null && !Iterables.get(referrers, 0).isEmpty()) {
426
                return finalFormat(format, Iterables.get(referrers, 0));
427
            } else {
428
                format = finalFormat(format);
429
            }
430
        }
431

    
432
        return null;
433
    }
434

    
435
    private void createXmlErrorPage(PrintWriter writer, Exception e) {
436
		writer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
437
		writer.append("<error>");
438
		writer.append("<exception>")
439
				.append(StringEscapeUtils.escapeXml(e.getClass().getName()))
440
				.append("</exception>");
441
		if (e.getMessage() != null) {
442
			writer.append("<message>")
443
					.append(StringEscapeUtils.escapeXml(e.getMessage()))
444
					.append("</message>");
445
		}
446
		if (e.getCause() != null) {
447
			writer.append("<cause>")
448
					.append(StringEscapeUtils.escapeXml(e.getCause()
449
							.toString())).append("</cause>");
450
		}
451

    
452
		StackTraceElement[] trace = e.getStackTrace();
453
		writer.append("<trace>");
454
		for (int i = 0; i < trace.length; i++) {
455
			writer.append(StringEscapeUtils.escapeXml(trace[i].toString()))
456
					.append("\n");
457
		}
458
		writer.append("</trace>");
459

    
460
		writer.append("</error>");
461
	}
462

    
463
    // Reading parameters from url and adding default values
464
    public int readParameter(HttpServletRequest request, String parameterName, int defaultValue) {
465
        String param = request.getParameter(parameterName);
466
        return (param != null && !param.isEmpty()) ? Integer.parseInt(param) : defaultValue;
467
    }
468

    
469
    private Collection<String> readParameter(HttpServletRequest request, String parameterName) {
470
        Collection<String> fields = null;
471
        String[] paramfields = request.getParameterValues(parameterName);
472
        if (paramfields != null) {
473
            fields = new ArrayList<String>();
474
            for (int i = 0; i < paramfields.length; i++)
475
                fields.add(paramfields[i]);
476
        }
477
        return fields;
478
    }
479

    
480
    /**
481
	 * Checks if the requested result size exceeds the maximum allowed numbers of returned results
482
	 * @param page the page parameter
483
	 * @param size the size parameter
484
	 */
485
	private void checkRequestSize(int page, int size) {
486
		int total = page*size;
487
		if (total > Integer.parseInt(maxResults)) {
488
			throw new IllegalArgumentException("Size and page arguments have exceeded the maximum number of returned results.");
489
		}
490
	}
491

    
492
	private String defineContentType(String format) {
493
		if (format != null) {
494
			if (format.equalsIgnoreCase("xml")) {
495
				return XML_CONTENT_TYPE;
496

    
497
			} else if (format.equalsIgnoreCase("json")) {
498
				return JSON_CONTENT_TYPE;
499

    
500
			} else if (format.equalsIgnoreCase("csv")) {
501
                return CSV_CONTENT_TYPE;
502

    
503
            } else if (format.equalsIgnoreCase("tsv")) {
504
                return TSV_CONTENT_TYPE;
505

    
506
            } else if (format.equalsIgnoreCase("html")){
507
                return HTML_CONTENT_TYPE;
508
            }
509
		}
510

    
511
		return XML_CONTENT_TYPE;
512

    
513
	}
514

    
515
    /**
516
     * Checks if the parameters given are allowed. The given parameters are checked against the allowed parameter
517
     * and the GLOBAL_PARAMETERS.
518
     * @param allowedParameters the allowed parameters
519
     * @param currentParameters the given parameters
520
     */
521
    private void checkParameters(List<String> allowedParameters, Map<String, String[]> currentParameters){
522
        if(currentParameters != null) {
523
            for (String parameter : currentParameters.keySet()) {
524
                if (!allowedParameters.contains(parameter) && !GLOBAL_PARAMETERS.contains(parameter) && !parameter.equals("referrer")) {
525
                    throw new IllegalArgumentException("Parameter " + parameter + " is not supported. The supported parameters are: " +
526
                            allowedParameters.toString().replace("[","").replace("]", ", ") + GLOBAL_PARAMETERS.toString().substring(1,GLOBAL_PARAMETERS.toString().length()-1));
527
                }
528
            }
529
        }
530
    }
531

    
532
    private void checkFormatParameter(List<String> allowedFormats, String requestedFormat) {
533
        if (requestedFormat!= null && !allowedFormats.contains(requestedFormat)) {
534
            throw new IllegalArgumentException("The requested format \'"+ requestedFormat +"\' is not supported. The supported formats are: " + allowedFormats);
535
        }
536
    }
537

    
538
    private static void checkModelParameter(List<String> allowedModels, String requestedModel) {
539
        if (requestedModel!= null && !allowedModels.contains(requestedModel)) {
540
            throw new IllegalArgumentException("The requested model \'"+ allowedModels +"\' is not supported. The supported formats are: " + allowedModels);
541
        }
542
    }
543

    
544
    private static boolean isModelSygma(String model) {
545
        logger.debug("MODEL: " + model);
546
        if (model == null || model.isEmpty()) { return false; }
547

    
548
        if (model != null && !model.isEmpty() && !model.equals("sygma")) {
549
            return  false;
550
        }
551

    
552
        return true;
553
    }
554

    
555
    private void createResponseMeta( HttpServletResponse response, String format, String encoding) {
556
        response.setContentType(defineContentType(format));
557
        response.setCharacterEncoding("UTF-8");
558

    
559
        if (!format.equals("xml") || !format.equals("json")) {
560

    
561
            SimpleDateFormat sdf = new SimpleDateFormat("ddMMyyyy");
562
            String date = sdf.format(new Date());
563

    
564
            if (format.equals("csv")) {
565
                response.setHeader("Content-Disposition", "filename="+date+".csv");
566

    
567
            } else if (format.equals("csv")) {
568
                response.setHeader("Content-Disposition", "filename="+date+".tsv");
569

    
570
            } else if (format.equals("html")) {
571
                response.setHeader("Content-Disposition", "filename="+date+".html");
572
            }
573
        }
574
    }
575
}
(7-7/8)