Project

General

Profile

1
package eu.dnetlib.enabling.datasources;
2

    
3
import java.io.StringWriter;
4
import java.util.ArrayList;
5
import java.util.Date;
6
import java.util.HashMap;
7
import java.util.List;
8
import java.util.Map;
9
import java.util.Optional;
10
import java.util.stream.Collectors;
11

    
12
import org.apache.commons.io.IOUtils;
13
import org.apache.commons.lang.StringUtils;
14
import org.apache.commons.lang.math.NumberUtils;
15
import org.apache.commons.logging.Log;
16
import org.apache.commons.logging.LogFactory;
17
import org.springframework.beans.factory.annotation.Required;
18
import org.springframework.core.io.ClassPathResource;
19
import org.springframework.core.io.Resource;
20

    
21
import com.google.common.collect.ImmutableMap;
22

    
23
import eu.dnetlib.enabling.datasources.DatasourceManagerClients.AfterSqlUpdate;
24
import eu.dnetlib.enabling.datasources.common.Api;
25
import eu.dnetlib.enabling.datasources.common.ApiParam;
26
import eu.dnetlib.enabling.datasources.common.BrowsableField;
27
import eu.dnetlib.enabling.datasources.common.BrowseTerm;
28
import eu.dnetlib.enabling.datasources.common.BrowseTermImpl;
29
import eu.dnetlib.enabling.datasources.common.Datasource;
30
import eu.dnetlib.enabling.datasources.common.DsmException;
31
import eu.dnetlib.enabling.datasources.common.Identity;
32
import eu.dnetlib.enabling.datasources.common.LocalDatasourceManager;
33
import eu.dnetlib.enabling.datasources.common.Organization;
34
import eu.dnetlib.enabling.datasources.common.SearchApisEntry;
35
import eu.dnetlib.enabling.datasources.common.SimpleDatasource;
36

    
37
public class LocalOpenaireDatasourceManager implements LocalDatasourceManager<Datasource<Organization<?>, Identity>, Api<ApiParam>> {
38

    
39
	private DatasourceManagerClients datasourceManagerClients;
40

    
41
	private List<DbBrowsableField> browsableFields;
42

    
43
	public static final String QUERY_BASEDIR = "/eu/dnetlib/enabling/datasources/queries/";
44

    
45
	private static final Resource searchDsByType = new ClassPathResource(QUERY_BASEDIR + "searchDsByType.sql");
46
	private static final Resource searchApis = new ClassPathResource(QUERY_BASEDIR + "searchApisNormal.sql");
47
	private static final Resource searchApisUsingField = new ClassPathResource(QUERY_BASEDIR + "searchApisUsingField.sql");
48
	private static final Resource addDs = new ClassPathResource(QUERY_BASEDIR + "addDatasource.sql");
49
	private static final Resource addOrg = new ClassPathResource(QUERY_BASEDIR + "addOrganization.sql");
50
	private static final Resource deleteDs = new ClassPathResource(QUERY_BASEDIR + "deleteDatasource.sql");
51
	private static final Resource setActive = new ClassPathResource(QUERY_BASEDIR + "setActive.sql");
52
	private static final Resource setManaged = new ClassPathResource(QUERY_BASEDIR + "setManaged.sql");
53
	private static final Resource setCompliance = new ClassPathResource(QUERY_BASEDIR + "setCompliance.sql");
54
	private static final Resource overrideCompliance = new ClassPathResource(QUERY_BASEDIR + "overrideCompliance.sql");
55
	private static final Resource resetCompliance = new ClassPathResource(QUERY_BASEDIR + "resetCompliance.sql");
56
	private static final Resource setLastCollectionInfo = new ClassPathResource(QUERY_BASEDIR + "setLastCollectionInfo.sql");
57
	private static final Resource setLastAggregationInfo = new ClassPathResource(QUERY_BASEDIR + "setLastAggregationInfo.sql");
58
	private static final Resource setLastDownloadInfo = new ClassPathResource(QUERY_BASEDIR + "setLastDownloadInfo.sql");
59
	private static final Resource insertApiParam = new ClassPathResource(QUERY_BASEDIR + "insertApiParam.sql");
60
	private static final Resource insertApi = new ClassPathResource(QUERY_BASEDIR + "insertApi.sql");
61

    
62
	private static final Log log = LogFactory.getLog(LocalOpenaireDatasourceManager.class);
63

    
64
	private static final String REPO_PROFILEID_SUFFIX = "_UmVwb3NpdG9yeVNlcnZpY2VSZXNvdXJjZXMvUmVwb3NpdG9yeVNlcnZpY2VSZXNvdXJjZVR5cGU=";
65

    
66
	@Override
67
	public List<SimpleDatasource> searchDatasourcesByType(final String type) throws DsmException {
68
		return datasourceManagerClients.searchSQL(searchDsByType, ImmutableMap.of("type", type))
69
				.stream()
70
				.map(DatasourceFunctions::mapToSimpleDs)
71
				.collect(Collectors.toList());
72
	}
73

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

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

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

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

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

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

    
107
		ds.setManaged(true);
108

    
109
		datasourceManagerClients.updateSQL(ds.getId(), addDs, AfterSqlUpdate.NONE, DatasourceFunctions.dsToMap(ds));
110

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

    
118
		datasourceManagerClients.regenerateProfile(ds.getId());
119
	}
120

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

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

    
131
	@Override
132
	public void regenerateProfiles() throws DsmException {
133
		datasourceManagerClients.regenerateProfiles();
134
	}
135

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

    
141
	@Override
142
	public void setManaged(final String dsId, final boolean managed) throws DsmException {
143
		final String id = fixDsId(dsId);
144

    
145
		final Map<String, Object> params = new HashMap<>();
146
		params.put("managed", managed);
147
		params.put("dsId", id);
148

    
149
		datasourceManagerClients.updateSQL(id, setManaged, AfterSqlUpdate.UPDATE_DS_PROFILE, params);
150

    
151
	}
152

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

    
159
	@Override
160
	public void setActive(final String dsId, final String apiId, final boolean active) throws DsmException {
161
		final String id = fixDsId(dsId);
162

    
163
		final Map<String, Object> params = new HashMap<>();
164
		params.put("active", active);
165
		params.put("apiId", apiId);
166
		params.put("dsId", id);
167

    
168
		datasourceManagerClients.updateSQL(id, setActive, AfterSqlUpdate.NONE, params);
169
		if (!active) {
170
			setLastCollectionInfo(id, apiId, null, null, null);
171
			setLastAggregationInfo(id, apiId, null, null, null);
172
			setLastDownloadInfo(id, apiId, null, null, null);
173
		}
174

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

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

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

    
190
	@Override
191
	public void updateCompliance(final String dsId, final String apiId, final String level, final boolean override) throws DsmException {
192
		final String id = fixDsId(dsId);
193

    
194
		if (!override) {
195
			datasourceManagerClients.updateSQL(id, setCompliance, AfterSqlUpdate.NONE, ImmutableMap.of("level", level, "apiId", apiId, "dsId", id));
196
		} else if (level != null) {
197
			datasourceManagerClients.updateSQL(id, overrideCompliance, AfterSqlUpdate.NONE, ImmutableMap.of("level", level, "apiId", apiId, "dsId", id));
198
		} else {
199
			datasourceManagerClients.updateSQL(id, resetCompliance, AfterSqlUpdate.NONE, ImmutableMap.of("apiId", apiId, "dsId", id));
200
		}
201

    
202
		setManaged(id, true); // It also update the IS profile
203
	}
204

    
205
	@Override
206
	public void setLastCollectionInfo(final String dsId, final String apiId, final String mdId, final Integer size, final Date date)
207
			throws DsmException {
208
		setLastOperationInfo(setLastCollectionInfo, fixDsId(dsId), apiId, mdId, size, date);
209
	}
210

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

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

    
223
	private void setLastOperationInfo(final Resource sqlResource, final String dsId, final String apiId, final String mdId, final Integer size, final Date date)
224
			throws DsmException {
225
		final Map<String, Object> params = new HashMap<>();
226
		params.put("dsId", dsId);
227
		params.put("apiId", apiId);
228
		params.put("mdId", mdId);
229
		params.put("total", size);
230
		params.put("date", new java.sql.Timestamp(date.getTime()));
231

    
232
		datasourceManagerClients.updateSQL(dsId, sqlResource, AfterSqlUpdate.NONE, params);
233

    
234
		setManaged(dsId, true); // It also update the IS profile
235
	}
236

    
237
	@Override
238
	public void updateApiDetails(final String dsId,
239
			final String apiId,
240
			final String metadataIdentifierPath,
241
			final String baseUrl,
242
			final Map<String, String> params)
243
			throws DsmException {
244

    
245
		final String id = fixDsId(dsId);
246

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

    
250
		// Insert new params
251
		for (final Map.Entry<String, String> e : params.entrySet()) {
252
			final Map<String, Object> sqlParams = ImmutableMap.of("param", e.getKey(), "value", e.getValue(), "api", apiId);
253
			datasourceManagerClients.updateSQL(id, insertApiParam, AfterSqlUpdate.NONE, sqlParams);
254
		}
255

    
256
		// Update the BaseURL
257
		datasourceManagerClients.updateSQL(id,
258
				"UPDATE dsm_api SET baseurl = :baseurl WHERE id = :api",
259
				AfterSqlUpdate.NONE,
260
				ImmutableMap.of("baseurl", baseUrl, "api", apiId));
261

    
262
		// Update the metadata_identifier_path
263
		datasourceManagerClients.updateSQL(id,
264
				"UPDATE dsm_api SET metadata_identifier_path = :path WHERE id = :api",
265
				AfterSqlUpdate.NONE,
266
				ImmutableMap.of("path", metadataIdentifierPath, "api", apiId));
267

    
268
		setManaged(id, true); // It also update the IS profile
269
	}
270

    
271
	@Override
272
	public List<? extends BrowsableField> listBrowsableFields() throws DsmException {
273
		return getBrowsableFields();
274
	}
275

    
276
	@Override
277
	public List<BrowseTerm> browseField(final String field) throws DsmException {
278
		final Optional<DbBrowsableField> bf = getBrowsableFields()
279
				.stream()
280
				.filter(f -> f.getId().equals(field))
281
				.findFirst();
282

    
283
		if (bf.isPresent()) {
284
			return datasourceManagerClients.searchSQL(bf.get().getSql(), new HashMap<>())
285
					.stream()
286
					.filter(m -> m.get("term") != null)
287
					.filter(m -> m.get("count") != null)
288
					.filter(m -> StringUtils.isNotBlank(m.get("term").toString()))
289
					.map(m -> new BrowseTermImpl(m.get("term").toString(), NumberUtils.toInt(m.get("count").toString(), 0)))
290
					.collect(Collectors.toList());
291
		} else {
292
			log.error("Not browsable field:" + field);
293
			throw new DsmException("Not browsable field:" + field);
294
		}
295
	}
296

    
297
	@Override
298
	public void addApi(final Api<ApiParam> api) throws DsmException {
299

    
300
		datasourceManagerClients.updateSQL(api.getDatasource(), insertApi, AfterSqlUpdate.NONE, DatasourceFunctions.apiToMap(api));
301

    
302
		api.getApiParams().forEach(p -> {
303
			final ImmutableMap<String, Object> sqlParams = ImmutableMap.of("param", p.getParam(), "value", p.getValue(), "api", api.getId());
304
			try {
305
				datasourceManagerClients.updateSQL(api.getDatasource(), insertApiParam, AfterSqlUpdate.NONE, sqlParams);
306
			} catch (final DsmException e) {
307
				throw new RuntimeException(e);
308
			}
309
		});
310

    
311
		setManaged(api.getDatasource(), true); // It also update the IS profile
312
	}
313

    
314
	@Override
315
	public void deleteApi(final String dsId, final String apiId) throws DsmException {
316
		if (!isRemovable(dsId, apiId)) { throw new DsmException("The api " + apiId + " can't be deleted"); }
317

    
318
		datasourceManagerClients.updateSQL(dsId, "DELETE FROM dsm_apiparams WHERE api = :api", AfterSqlUpdate.NONE, ImmutableMap.of("api", apiId));
319
		datasourceManagerClients.updateSQL(dsId, "DELETE FROM dsm_api WHERE id = :api", AfterSqlUpdate.NONE, ImmutableMap.of("api", apiId));
320

    
321
		setManaged(dsId, true); // It also update the IS profile
322
	}
323

    
324
	public DatasourceManagerClients getDatasourceManagerClients() {
325
		return datasourceManagerClients;
326
	}
327

    
328
	private String fixDsId(final String dsId) throws DsmException {
329
		return dsId.endsWith(REPO_PROFILEID_SUFFIX) ? datasourceManagerClients.findDatasourceId(dsId) : dsId;
330
	}
331

    
332
	@Required
333
	public void setDatasourceManagerClients(final DatasourceManagerClients datasourceManagerClients) {
334
		this.datasourceManagerClients = datasourceManagerClients;
335
	}
336

    
337
	public List<DbBrowsableField> getBrowsableFields() {
338
		return browsableFields;
339
	}
340

    
341
	@Required
342
	public void setBrowsableFields(final List<DbBrowsableField> browsableFields) {
343
		this.browsableFields = browsableFields;
344
	}
345

    
346
}
(4-4/4)