Project

General

Profile

1 47423 michele.ar
package eu.dnetlib.msro.openaireplus.api.objects;
2
3
import java.text.SimpleDateFormat;
4 48139 alessia.ba
import java.util.*;
5 47423 michele.ar
import java.util.concurrent.TimeUnit;
6
7 48139 alessia.ba
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpException;
8
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService;
9
import eu.dnetlib.miscutils.datetime.DateUtils;
10
import eu.dnetlib.miscutils.functional.hash.Hashing;
11
import eu.dnetlib.msro.openaireplus.api.OpenAIRESubmitterUtils;
12
import eu.dnetlib.msro.rmi.MSROException;
13
import io.swagger.annotations.ApiModelProperty;
14 47423 michele.ar
import org.apache.commons.lang.StringUtils;
15
import org.apache.commons.logging.Log;
16
import org.apache.commons.logging.LogFactory;
17
import org.apache.velocity.app.VelocityEngine;
18
import org.apache.velocity.tools.generic.EscapeTool;
19
import org.springframework.ui.velocity.VelocityEngineUtils;
20
21
/**
22
 * Created by michele on 02/12/15.
23
 */
24
public class ResultEntry {
25
26 48139 alessia.ba
	private String openaireId;
27 47423 michele.ar
	private String originalId;
28
	private String title;
29
	private List<String> authors = new ArrayList<String>();
30
	private String publisher;
31
	private String description;
32
	private String language;
33
	private List<PidEntry> pids = new ArrayList<PidEntry>();
34
	private String licenseCode;
35
	private String embargoEndDate;
36
	private String type = "publication";
37
	private String resourceType;
38
	private String url;
39
	private String collectedFromId;
40
	private String hostedById;
41
42
	// String according to openaire guidelines:
43
	// info:eu-repo/grantAgreement/Funder/FundingProgram/ProjectID/[Jurisdiction]/[ProjectName]/[ProjectAcronym]
44
	private List<String> contexts = new ArrayList<String>();
45
46
	// String according to the EGI context profile, example: egi::classification::natsc::math
47
	private List<String> linksToProjects = new ArrayList<String>();
48
49
	private static long last_cache_update = 0;
50
	private static final Map<String, Map<String, String>> cached_vocabularies = new HashMap<String, Map<String, String>>();
51
	private static final Map<String, DatasourceEntry> cached_datasources = new HashMap<String, DatasourceEntry>();
52
	private static final Map<String, String> cached_contexts = new HashMap<String, String>();
53
54
	private static final Log log = LogFactory.getLog(ResultEntry.class);
55
56 48139 alessia.ba
	public ResultEntry() {
57
	}
58 47423 michele.ar
59 48139 alessia.ba
	public String getOpenaireId() {
60
		return openaireId;
61
	}
62
63
	public void setOpenaireId(String openaireId) {
64
		this.openaireId = openaireId;
65
	}
66
67 47423 michele.ar
	public String getOriginalId() {
68
		return originalId;
69
	}
70
71
	public void setOriginalId(final String originalId) {
72
		this.originalId = originalId;
73
	}
74
75 48139 alessia.ba
	@ApiModelProperty(required = true)
76 47423 michele.ar
	public String getTitle() {
77
		return title;
78
	}
79
80
	public void setTitle(final String title) {
81
		this.title = title;
82
	}
83
84
	public List<String> getAuthors() {
85
		return authors;
86
	}
87
88
	public void setAuthors(final List<String> authors) {
89
		this.authors = authors;
90
	}
91
92
	public String getPublisher() {
93
		return publisher;
94
	}
95
96
	public void setPublisher(final String publisher) {
97
		this.publisher = publisher;
98
	}
99
100
	public String getDescription() {
101
		return description;
102
	}
103
104
	public void setDescription(final String description) {
105
		this.description = description;
106
	}
107
108 48139 alessia.ba
	@ApiModelProperty(value = "ISO Alpha-3 code. E.g. 'eng', 'ita'")
109 47423 michele.ar
	public String getLanguage() {
110
		return language;
111
	}
112
113
	public void setLanguage(final String language) {
114
		this.language = language;
115
	}
116
117
	public List<PidEntry> getPids() {
118
		return pids;
119
	}
120
121
	public void setPids(final List<PidEntry> pids) {
122
		this.pids = pids;
123
	}
124
125 48139 alessia.ba
	@ApiModelProperty(required = true, allowableValues = "OPEN, CLOSED, RESTRICTED, EMBARGO, UNKNOWN, OTHER")
126 47423 michele.ar
	public String getLicenseCode() {
127
		return licenseCode;
128
	}
129
130
	public void setLicenseCode(final String licenseCode) {
131
		this.licenseCode = licenseCode;
132
	}
133
134 48139 alessia.ba
	@ApiModelProperty(required = true, value = "Use 001 for articles, 021 for datasets. See: http://api.openaire.eu/vocabularies/dnet:publication_resource.")
135 47423 michele.ar
	public String getResourceType() {
136
		return resourceType;
137
	}
138
139
	public void setResourceType(final String resourceType) {
140
		this.resourceType = resourceType;
141
	}
142
143 48139 alessia.ba
	@ApiModelProperty(required = true)
144 47423 michele.ar
	public String getUrl() {
145
		return url;
146
	}
147
148
	public void setUrl(final String url) {
149
		this.url = url;
150
	}
151
152 48139 alessia.ba
	@ApiModelProperty(required = true, value = "Use opendoar___::2659 for Zenodo Publications; re3data_____::r3d100010468 for Zenodo datasets; infrastruct::openaire for OpenAIRE portal.")
153 47423 michele.ar
	public String getCollectedFromId() {
154
		return collectedFromId;
155
	}
156
157
	public void setCollectedFromId(final String collectedFromId) {
158
		this.collectedFromId = collectedFromId;
159
	}
160
161
	public String getHostedById() {
162
		return hostedById;
163
	}
164
165
	public void setHostedById(final String hostedById) {
166
		this.hostedById = hostedById;
167
	}
168
169 48139 alessia.ba
	@ApiModelProperty(value = "E.g. fet, egi::classification::natsc::math::pure, egi::projects::EMI")
170 47423 michele.ar
	public List<String> getContexts() {
171
		return contexts;
172
	}
173
174
	public void setContexts(final List<String> contexts) {
175
		this.contexts = contexts;
176
	}
177 48139 alessia.ba
178
	@ApiModelProperty(value = "E.g. info:eu-repo/grantAgreement/EC/FP7/283595/EU//OpenAIREplus")
179 47423 michele.ar
	public List<String> getLinksToProjects() {
180
		return linksToProjects;
181
	}
182
183
	public void setLinksToProjects(final List<String> linksToProjects) {
184
		this.linksToProjects = linksToProjects;
185
	}
186
187 48139 alessia.ba
	@ApiModelProperty(allowableValues = "publication, dataset")
188 47423 michele.ar
	public String getType() {
189
		return type;
190
	}
191
192
	public void setType(final String type) {
193
		this.type = type;
194
	}
195
196
	public String getEmbargoEndDate() {
197
		return embargoEndDate;
198
	}
199
200
	public void setEmbargoEndDate(final String embargoEndDate) {
201
		this.embargoEndDate = embargoEndDate;
202
	}
203
204
	public String asOafRecord(final VelocityEngine ve,
205
			final ISLookUpService lookupService,
206
			final String oafSchemaLocation) throws Exception {
207
208 48139 alessia.ba
		if (StringUtils.isBlank(getOriginalId()) && StringUtils.isBlank(getOpenaireId())) {
209
			throw new MSROException("One of the following fields is required: originalId or openaireId");
210
		}
211
		if (StringUtils.isBlank(getTitle())) { throw new MSROException("A required field is missing: title"); }
212
		if (StringUtils.isBlank(getUrl())) { throw new MSROException("A required field is missing: url"); }
213
		if (StringUtils.isBlank(getLicenseCode())) { throw new MSROException("A required field is missing: licenseCode"); }
214
		if (StringUtils.isBlank(getResourceType())) { throw new MSROException("A required field is missing: resourceType"); }
215
		if (StringUtils.isBlank(getCollectedFromId())) { throw new MSROException("A required field is missing: collectedFromId"); }
216
		if (StringUtils.isBlank(getType())) { throw new MSROException("A required field is missing: type"); }
217
218 47423 michele.ar
		final DatasourceEntry collectedFromEntry = getDatasourceInfo(collectedFromId, lookupService);
219
		final DatasourceEntry hostedByEntry = getDatasourceInfo(hostedById, lookupService);
220
221 48139 alessia.ba
		if (StringUtils.isBlank(openaireId)) {
222
			setOpenaireId(calculateOpenaireId(originalId, collectedFromEntry));
223
		}
224 47423 michele.ar
225 48139 alessia.ba
		if (!openaireId.matches("^\\w{12}::\\w{32}$")) {
226
			throw new MSROException("Invalid openaireId: " + openaireId + " - regex ^\\w{12}::\\w{32}$ not matched");
227
		}
228
229 47423 michele.ar
		final Map<String, Object> model = new HashMap<String, Object>();
230
		model.put("esc", new EscapeTool());
231
		model.put("util", new OpenAIRESubmitterUtils());
232
		model.put("pub", this);
233 48139 alessia.ba
		model.put("objIdentifier", getOpenaireId());
234 47423 michele.ar
		model.put("oafSchemaLocation", oafSchemaLocation);
235
		model.put("resultTypes", getVocabulary("dnet:result_typologies", lookupService));
236
		model.put("licenses", getVocabulary("dnet:access_modes", lookupService));
237
		model.put("resourceTypes", getVocabulary("dnet:publication_resource", lookupService));
238
		model.put("pidTypes", getVocabulary("dnet:pid_types", lookupService));
239
		model.put("languages", getVocabulary("dnet:languages", lookupService));
240
		model.put("contexts", getContexts(lookupService));
241
		model.put("dateOfCollection", (new SimpleDateFormat("yyyy-MM-dd\'T\'hh:mm:ss\'Z\'")).format(new Date()));
242
		model.put("collectedFrom", collectedFromEntry);
243
		model.put("hostedBy", hostedByEntry);
244
245
		return VelocityEngineUtils.mergeTemplateIntoString(ve, "/eu/dnetlib/msro/openaireplus/api/indexRecord.xml.vm", "UTF-8", model);
246
	}
247
248 48139 alessia.ba
	private static String calculateOpenaireId(final String originalId, final DatasourceEntry collectedFromEntry) {
249 47423 michele.ar
		return collectedFromEntry.getPrefix() + "::" + Hashing.md5(originalId);
250
	}
251
252 48139 alessia.ba
	public static String calculateOpenaireId(final String originalId, final String collectedFromId, final ISLookUpService lookupService)
253
			throws ISLookUpException {
254
		return calculateOpenaireId(originalId, getDatasourceInfo(collectedFromId, lookupService));
255 47423 michele.ar
	}
256
257
	private synchronized static DatasourceEntry getDatasourceInfo(final String dsId, final ISLookUpService lookupService) throws ISLookUpException {
258
		if (StringUtils
259
				.isBlank(dsId)) { return new DatasourceEntry("openaire____::1256f046-bf1f-4afc-8b47-d0b147148b18", "Unknown Repository", "unknown_____"); }
260
261
		if (!cached_datasources.containsKey(dsId)) {
262
			final String query =
263
					"collection('/db/DRIVER/RepositoryServiceResources/RepositoryServiceResourceType')//CONFIGURATION[./DATASOURCE_ORIGINAL_ID='" + dsId
264
							+ "']/concat(./OFFICIAL_NAME, ' @@@ ', .//FIELD/value[../key='NamespacePrefix'])";
265
			final String s = lookupService.getResourceProfileByQuery(query);
266
			final String[] arr = s.split("@@@");
267
268
			final DatasourceEntry ds = new DatasourceEntry(dsId, arr[0].trim(), arr[1].trim());
269
270
			if (StringUtils.isBlank(ds.getName()) || StringUtils.isBlank(ds.getPrefix())) {
271
				log.error("Invalid datasource id: " + dsId);
272
				throw new ISLookUpException("Invalid datasource id: " + dsId);
273
			} else {
274
				cached_datasources.put(dsId, ds);
275
			}
276
		}
277
278
		return cached_datasources.get(dsId);
279
280
	}
281
282
	private synchronized static Map<String, String> getVocabulary(final String voc, final ISLookUpService lookupService) throws ISLookUpException {
283
284
		if (((DateUtils.now() - last_cache_update) < TimeUnit.MINUTES.toMillis(15)) && cached_vocabularies.containsKey(voc)) {
285
			return cached_vocabularies.get(voc);
286
		} else {
287
			final String query = "collection('/db/DRIVER/VocabularyDSResources/VocabularyDSResourceType')[.//VOCABULARY_NAME/@code='" + voc
288
					+ "']//TERM/concat(@code, ' @@@ ', @english_name)";
289
290
			final Map<String, String> map = new HashMap<String, String>();
291
			for (final String s : lookupService.quickSearchProfile(query)) {
292
				final String[] arr = s.split("@@@");
293
				map.put(arr[0].trim(), arr[1].trim());
294
			}
295
296
			cached_vocabularies.put(voc, map);
297
298
			last_cache_update = DateUtils.now();
299
300
			return map;
301
		}
302
	}
303
304
	private synchronized static Map<String, String> getContexts(final ISLookUpService lookupService) throws ISLookUpException {
305
		if (((DateUtils.now() - last_cache_update) > TimeUnit.MINUTES.toMillis(15)) || cached_contexts.isEmpty()) {
306
			final String query =
307
					"collection('/db/DRIVER/ContextDSResources/ContextDSResourceType')[.//context/@type='community']//*[name()='context' or name()='category' or name()='concept']/concat(@id, ' @@@ ', @label)";
308
309
			cached_contexts.clear();
310
			for (final String s : lookupService.quickSearchProfile(query)) {
311
				final String[] arr = s.split("@@@");
312
				cached_contexts.put(arr[0].trim(), arr[1].trim());
313
			}
314
			last_cache_update = DateUtils.now();
315
		}
316
		return cached_contexts;
317
	}
318
319 48139 alessia.ba
	@Override
320
	public String toString() {
321
		return StringUtils.isNotBlank(openaireId) ? openaireId : originalId;
322
	}
323
}