Project

General

Profile

1
package eu.dnetlib.enabling.datasources;
2

    
3
import java.io.StringWriter;
4
import java.util.*;
5
import java.util.stream.Collectors;
6

    
7
import com.google.common.collect.ImmutableMap;
8
import eu.dnetlib.enabling.datasources.DatasourceManagerClients.AfterSqlUpdate;
9
import eu.dnetlib.enabling.datasources.common.*;
10
import org.apache.commons.io.IOUtils;
11
import org.apache.commons.lang3.StringUtils;
12
import org.apache.commons.lang3.math.NumberUtils;
13
import org.apache.commons.logging.Log;
14
import org.apache.commons.logging.LogFactory;
15
import org.springframework.beans.factory.annotation.Required;
16
import org.springframework.core.io.ClassPathResource;
17
import org.springframework.core.io.Resource;
18
import org.springframework.transaction.annotation.Transactional;
19

    
20
public class LocalOpenaireDatasourceManagerImpl implements LocalOpenaireDatasourceManager {
21

    
22
	private DatasourceManagerClients datasourceManagerClients;
23

    
24
	private List<DbBrowsableField> browsableFields;
25

    
26
	public static final String QUERY_BASEDIR = "/eu/dnetlib/enabling/datasources/queries/";
27

    
28
	private static final Resource searchDsByType = new ClassPathResource(QUERY_BASEDIR + "searchDsByType.sql");
29
	private static final Resource searchApis = new ClassPathResource(QUERY_BASEDIR + "searchApisNormal.sql");
30
	private static final Resource searchApisUsingField = new ClassPathResource(QUERY_BASEDIR + "searchApisUsingField.sql");
31
	private static final Resource addDs = new ClassPathResource(QUERY_BASEDIR + "addDatasource.sql");
32
	private static final Resource addOrg = new ClassPathResource(QUERY_BASEDIR + "addOrganization.sql");
33
	private static final Resource deleteDs = new ClassPathResource(QUERY_BASEDIR + "deleteDatasource.sql");
34
	private static final Resource setActive = new ClassPathResource(QUERY_BASEDIR + "setActive.sql");
35
	private static final Resource setManaged = new ClassPathResource(QUERY_BASEDIR + "setManaged.sql");
36
	private static final Resource setCompliance = new ClassPathResource(QUERY_BASEDIR + "setCompliance.sql");
37
	private static final Resource overrideCompliance = new ClassPathResource(QUERY_BASEDIR + "overrideCompliance.sql");
38
	private static final Resource resetCompliance = new ClassPathResource(QUERY_BASEDIR + "resetCompliance.sql");
39
	private static final Resource setLastCollectionInfo = new ClassPathResource(QUERY_BASEDIR + "setLastCollectionInfo.sql");
40
	private static final Resource setLastAggregationInfo = new ClassPathResource(QUERY_BASEDIR + "setLastAggregationInfo.sql");
41
	private static final Resource setLastDownloadInfo = new ClassPathResource(QUERY_BASEDIR + "setLastDownloadInfo.sql");
42
	private static final Resource setLastValidationJob = new ClassPathResource(QUERY_BASEDIR + "setLastValidationJob.sql");
43
	private static final Resource resetLastOperationsInfo = new ClassPathResource(QUERY_BASEDIR + "resetLastOperationsInfo.sql");
44
	private static final Resource insertApiParam = new ClassPathResource(QUERY_BASEDIR + "insertApiParam.sql");
45
	private static final Resource insertApi = new ClassPathResource(QUERY_BASEDIR + "insertApi.sql");
46

    
47
	private static final Log log = LogFactory.getLog(LocalOpenaireDatasourceManagerImpl.class);
48

    
49
	private static final String REPO_PROFILEID_SUFFIX = "_UmVwb3NpdG9yeVNlcnZpY2VSZXNvdXJjZXMvUmVwb3NpdG9yeVNlcnZpY2VSZXNvdXJjZVR5cGU=";
50

    
51
	@Override
52
	@Transactional(readOnly = true)
53
	public Set<String> listManagedDatasourceIds() throws DsmRuntimeException {
54
		try {
55
			return datasourceManagerClients.searchSQL("SELECT id FROM dsm_datasources WHERE managed = true", new HashMap<>())
56
					.stream()
57
					.map(m -> (String) m.get("id"))
58
					.collect(Collectors.toCollection(HashSet::new));
59
		} catch (final DsmException e) {
60
			throw new DsmRuntimeException(e);
61
		}
62
	}
63

    
64
	@Override
65
	@Transactional(readOnly = true)
66
	public List<SimpleDatasource> searchDatasourcesByType(final String type) throws DsmException {
67

    
68
		return datasourceManagerClients.searchSQL(searchDsByType, ImmutableMap.of("type", type))
69
				.stream()
70
				.map(DatasourceFunctions::mapToSimpleDs)
71
				.collect(Collectors.toList());
72
	}
73

    
74
	@Override
75
	@Transactional(readOnly = true)
76
	public List<? extends SearchApisEntry> searchApis(final String field, final Object value) throws DsmException {
77
		try {
78
			final StringWriter sql = new StringWriter();
79

    
80
			if (field.equalsIgnoreCase("__search__")) {
81
				sql.append(IOUtils.toString(searchApis.getInputStream()));
82
			} else {
83
				sql.append(IOUtils.toString(searchApisUsingField.getInputStream()));
84
				sql.append(field);
85
				sql.append("::text = ");
86
				sql.append(":value");
87
			}
88

    
89
			return datasourceManagerClients
90
					.searchSQL(sql.toString(), ImmutableMap.of("value", field.equalsIgnoreCase("__search__") ? "%" + value + "%" : value))
91
					.stream()
92
					.map(DatasourceFunctions::mapToSearchApisEntry)
93
					.collect(Collectors.toList());
94

    
95
		} catch (final Exception e) {
96
			log.error("Error searching field " + field + " - value: " + value, e);
97
		}
98
		return new ArrayList<>();
99
	}
100

    
101
	@Override
102
	@Transactional
103
	public void saveDs(final Datasource<Organization<?>, Identity> ds) throws DsmException {
104

    
105
		if (StringUtils.isBlank(ds.getAggregator())) {
106
			ds.setAggregator("OPENAIRE");
107
		}
108

    
109
		ds.setManaged(true);
110

    
111
		datasourceManagerClients.updateSQL(ds.getId(), addDs, AfterSqlUpdate.NONE, DatasourceFunctions.dsToMap(ds));
112

    
113
		if (ds.getOrganizations() != null) {
114
			for (final Organization<?> org : ds.getOrganizations()) {
115
				final Map<String, Object> orgParams = DatasourceFunctions.orgToMap(ds.getId(), org);
116
				datasourceManagerClients.updateSQL(ds.getId(), addOrg, AfterSqlUpdate.NONE, orgParams);
117
			}
118
		}
119

    
120
		datasourceManagerClients.regenerateProfile(ds.getId());
121
	}
122

    
123
	@Override
124
	@Transactional
125
	public void deleteDs(final String dsId) throws DsmException {
126
		datasourceManagerClients.updateSQL(fixDsId(dsId), deleteDs, AfterSqlUpdate.DELETE_DS_PROFILE, ImmutableMap.of("dsId", dsId));
127
	}
128

    
129
	@Override
130
	public Datasource<Organization<?>, Identity> getDs(final String dsId) throws DsmException {
131
		return datasourceManagerClients.getDatasourceById(fixDsId(dsId));
132
	}
133

    
134
	@Override
135
	public void regenerateProfiles() throws DsmException {
136
		datasourceManagerClients.regenerateProfiles();
137
	}
138

    
139
	@Override
140
	public List<Api<ApiParam>> getApis(final String dsId) throws DsmException {
141
		return datasourceManagerClients.getApis(fixDsId(dsId));
142
	}
143

    
144
	@Override
145
	public void setManaged(final String dsId, final boolean managed) throws DsmException {
146
		final String id = fixDsId(dsId);
147

    
148
		final Map<String, Object> params = new HashMap<>();
149
		params.put("managed", managed);
150
		params.put("dsId", id);
151

    
152
		datasourceManagerClients.updateSQL(id, setManaged, AfterSqlUpdate.UPDATE_DS_PROFILE, params);
153

    
154
	}
155

    
156
	@Override
157
	public boolean isManaged(final String dsId) throws DsmException {
158
		final String q = "SELECT * from dsm_datasources WHERE id = :dsId AND managed = true";
159
		return !datasourceManagerClients.searchSQL(q, ImmutableMap.of("dsId", fixDsId(dsId))).isEmpty();
160
	}
161

    
162
	@Override
163
	@Transactional
164
	public void setActive(final String dsId, final String apiId, final boolean active) throws DsmException {
165
		final String id = fixDsId(dsId);
166

    
167
		final Map<String, Object> params = new HashMap<>();
168
		params.put("active", active);
169
		params.put("apiId", apiId);
170
		params.put("dsId", id);
171

    
172
		datasourceManagerClients.updateSQL(id, setActive, AfterSqlUpdate.NONE, params);
173
		if (!active) {
174
			datasourceManagerClients.updateSQL(dsId, resetLastOperationsInfo, AfterSqlUpdate.NONE, params);
175
		}
176

    
177
		setManaged(id, true); // It also update the IS profile
178
	}
179

    
180
	@Override
181
	@Transactional(readOnly = true)
182
	public boolean isActive(final String dsId, final String apiId) throws DsmException {
183
		final String q = "SELECT * from dsm_api WHERE id = :apiId AND datasource = :dsId AND active = true";
184
		return !datasourceManagerClients.searchSQL(q, ImmutableMap.of("dsId", fixDsId(dsId), "apiId", apiId)).isEmpty();
185
	}
186

    
187
	@Override
188
	@Transactional(readOnly = true)
189
	public boolean isRemovable(final String dsId, final String apiId) throws DsmException {
190
		final String q = "SELECT * from dsm_api WHERE id = :apiId AND datasource = :dsId AND active != true AND removable = true";
191
		return !datasourceManagerClients.searchSQL(q, ImmutableMap.of("dsId", fixDsId(dsId), "apiId", apiId)).isEmpty();
192
	}
193

    
194
	@Override
195
	@Transactional
196
	public void updateCompliance(final String dsId, final String apiId, final String level, final boolean override) throws DsmException {
197
		final String id = fixDsId(dsId);
198

    
199
		if (!override) {
200
			datasourceManagerClients.updateSQL(id, setCompliance, AfterSqlUpdate.NONE, ImmutableMap.of("level", level, "apiId", apiId, "dsId", id));
201
		} else if (level != null) {
202
			datasourceManagerClients.updateSQL(id, overrideCompliance, AfterSqlUpdate.NONE, ImmutableMap.of("level", level, "apiId", apiId, "dsId", id));
203
		} else {
204
			datasourceManagerClients.updateSQL(id, resetCompliance, AfterSqlUpdate.NONE, ImmutableMap.of("apiId", apiId, "dsId", id));
205
		}
206

    
207
		setManaged(id, true); // It also update the IS profile
208
	}
209

    
210
	@Override
211

    
212
	public void setLastCollectionInfo(final String dsId, final String apiId, final String mdId, final Integer size, final Date date)
213
			throws DsmException {
214
		setLastOperationInfo(setLastCollectionInfo, fixDsId(dsId), apiId, mdId, size, date);
215
	}
216

    
217
	@Override
218
	public void setLastAggregationInfo(final String dsId, final String apiId, final String mdId, final Integer size, final Date date)
219
			throws DsmException {
220
		setLastOperationInfo(setLastAggregationInfo, fixDsId(dsId), apiId, mdId, size, date);
221
	}
222

    
223
	@Override
224
	public void setLastDownloadInfo(final String dsId, final String apiId, final String objId, final Integer size, final Date date)
225
			throws DsmException {
226
		setLastOperationInfo(setLastDownloadInfo, fixDsId(dsId), apiId, objId, size, date);
227
	}
228

    
229
	@Override
230
	public void setLastValidationJob(String dsId, String apiId, String jobId) throws DsmException {
231
		final Map<String, Object> params = new HashMap<>();
232
		params.put("dsId", dsId);
233
		params.put("apiId", apiId);
234
		params.put("jobId", jobId);
235

    
236
		datasourceManagerClients.updateSQL(dsId, setLastValidationJob, AfterSqlUpdate.NONE, params);
237
		setManaged(dsId, true); // It also update the IS profile
238
	}
239

    
240
	@Transactional
241
	protected void setLastOperationInfo(final Resource sqlResource, final String dsId, final String apiId, final String mdId, final Integer size, final Date date)
242
			throws DsmException {
243
		final Map<String, Object> params = new HashMap<>();
244
		params.put("dsId", dsId);
245
		params.put("apiId", apiId);
246
		params.put("mdId", mdId);
247
		params.put("total", size);
248
		if (date != null) {
249
			params.put("date", new java.sql.Timestamp(date.getTime()));
250
		}
251

    
252
		datasourceManagerClients.updateSQL(dsId, sqlResource, AfterSqlUpdate.NONE, params);
253

    
254
		setManaged(dsId, true); // It also update the IS profile
255
	}
256

    
257
	@Override
258
	@Transactional
259
	public void updateApiDetails(final String dsId,
260
			final String apiId,
261
			final String metadataIdentifierPath,
262
			final String baseUrl,
263
			final Map<String, String> params)
264
			throws DsmException {
265

    
266
		final String id = fixDsId(dsId);
267

    
268
		// Delete old params
269
		datasourceManagerClients.updateSQL(id, "DELETE FROM dsm_apiparams WHERE api = :api", AfterSqlUpdate.NONE, ImmutableMap.of("api", apiId));
270

    
271
		// Insert new params
272
		for (final Map.Entry<String, String> e : params.entrySet()) {
273
			final Map<String, Object> sqlParams = ImmutableMap.of("param", e.getKey(), "value", e.getValue(), "api", apiId);
274
			datasourceManagerClients.updateSQL(id, insertApiParam, AfterSqlUpdate.NONE, sqlParams);
275
		}
276

    
277
		// Update the BaseURL
278
		datasourceManagerClients.updateSQL(id,
279
				"UPDATE dsm_api SET baseurl = :baseurl WHERE id = :api",
280
				AfterSqlUpdate.NONE,
281
				ImmutableMap.of("baseurl", baseUrl, "api", apiId));
282

    
283
		// Update the metadata_identifier_path
284
		datasourceManagerClients.updateSQL(id,
285
				"UPDATE dsm_api SET metadata_identifier_path = :path WHERE id = :api",
286
				AfterSqlUpdate.NONE,
287
				ImmutableMap.of("path", metadataIdentifierPath, "api", apiId));
288

    
289
		setManaged(id, true); // It also update the IS profile
290
	}
291

    
292
	@Override
293
	public List<? extends BrowsableField> listBrowsableFields() throws DsmException {
294
		return getBrowsableFields();
295
	}
296

    
297
	@Override
298
	public List<BrowseTerm> browseField(final String field) throws DsmException {
299
		final Optional<DbBrowsableField> bf = getBrowsableFields()
300
				.stream()
301
				.filter(f -> f.getId().equals(field))
302
				.findFirst();
303

    
304
		if (bf.isPresent()) {
305
			return datasourceManagerClients.searchSQL(bf.get().getSql(), new HashMap<>())
306
					.stream()
307
					.filter(m -> m.get("term") != null)
308
					.filter(m -> m.get("count") != null)
309
					.filter(m -> StringUtils.isNotBlank(m.get("term").toString()))
310
					.map(m -> new BrowseTermImpl(m.get("term").toString(), NumberUtils.toInt(m.get("count").toString(), 0)))
311
					.collect(Collectors.toList());
312
		} else {
313
			log.error("Not browsable field:" + field);
314
			throw new DsmException("Not browsable field:" + field);
315
		}
316
	}
317

    
318
	@Override
319
	@Transactional
320
	public void addApi(final Api<ApiParam> api) throws DsmException {
321

    
322
		datasourceManagerClients.updateSQL(api.getDatasource(), insertApi, AfterSqlUpdate.NONE, DatasourceFunctions.apiToMap(api));
323

    
324
		if (api.getApiParams() != null) {
325
			api.getApiParams().forEach(p -> {
326
				final ImmutableMap<String, Object> sqlParams = ImmutableMap.of("param", p.getParam(), "value", p.getValue(), "api", api.getId());
327
				try {
328
					datasourceManagerClients.updateSQL(api.getDatasource(), insertApiParam, AfterSqlUpdate.NONE, sqlParams);
329
				} catch (final DsmException e) {
330
					throw new RuntimeException(e);
331
				}
332
			});
333
		}
334

    
335
		setManaged(api.getDatasource(), true); // It also update the IS profile
336
	}
337

    
338
	@Override
339
	@Transactional
340
	public void deleteApi(final String dsId, final String apiId) throws DsmException {
341
		if (!isRemovable(dsId, apiId)) { throw new DsmException("The api " + apiId + " can't be deleted"); }
342

    
343
		datasourceManagerClients.updateSQL(dsId, "DELETE FROM dsm_apiparams WHERE api = :api", AfterSqlUpdate.NONE, ImmutableMap.of("api", apiId));
344
		datasourceManagerClients.updateSQL(dsId, "DELETE FROM dsm_api WHERE id = :api", AfterSqlUpdate.NONE, ImmutableMap.of("api", apiId));
345

    
346
		setManaged(dsId, true); // It also update the IS profile
347
	}
348

    
349
	public DatasourceManagerClients getDatasourceManagerClients() {
350
		return datasourceManagerClients;
351
	}
352

    
353
	private String fixDsId(final String dsId) throws DsmException {
354
		return dsId.endsWith(REPO_PROFILEID_SUFFIX) ? datasourceManagerClients.findDatasourceId(dsId) : dsId;
355
	}
356

    
357
	@Required
358
	public void setDatasourceManagerClients(final DatasourceManagerClients datasourceManagerClients) {
359
		this.datasourceManagerClients = datasourceManagerClients;
360
	}
361

    
362
	public List<DbBrowsableField> getBrowsableFields() {
363
		return browsableFields;
364
	}
365

    
366
	@Required
367
	public void setBrowsableFields(final List<DbBrowsableField> browsableFields) {
368
		this.browsableFields = browsableFields;
369
	}
370

    
371
}
(5-5/5)