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
		if (StringUtils.isBlank(ds.getAggregator())) {
103
			ds.setAggregator("OPENAIRE");
104
		}
105

    
106
		datasourceManagerClients.updateSQL(ds.getId(), addDs, AfterSqlUpdate.NONE, DatasourceFunctions.dsToMap(ds));
107

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

    
115
		datasourceManagerClients.regenerateProfile(ds.getId());
116
	}
117

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

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

    
128
	@Override
129
	public void regenerateProfiles() throws DsmException {
130
		datasourceManagerClients.regenerateProfiles();
131
	}
132

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

    
138
	@Override
139
	public void setManaged(final String dsId, final boolean managed) throws DsmException {
140
		final String id = fixDsId(dsId);
141

    
142
		final Map<String, Object> params = new HashMap<>();
143
		params.put("managed", managed);
144
		params.put("dsId", id);
145

    
146
		datasourceManagerClients.updateSQL(id, setManaged, AfterSqlUpdate.UPDATE_DS_PROFILE, params);
147

    
148
	}
149

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

    
156
	@Override
157
	public void setActive(final String dsId, final String apiId, final boolean active) throws DsmException {
158
		final String id = fixDsId(dsId);
159

    
160
		final Map<String, Object> params = new HashMap<>();
161
		params.put("active", active);
162
		params.put("apiId", apiId);
163
		params.put("dsId", id);
164

    
165
		datasourceManagerClients.updateSQL(id, setActive, AfterSqlUpdate.UPDATE_DS_PROFILE, params);
166
		if (!active) {
167
			setLastCollectionInfo(id, apiId, null, null, null);
168
			setLastAggregationInfo(id, apiId, null, null, null);
169
			setLastDownloadInfo(id, apiId, null, null, null);
170
		}
171
	}
172

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

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

    
185
	@Override
186
	public void updateCompliance(final String dsId, final String apiId, final String level, final boolean override) throws DsmException {
187
		final String id = fixDsId(dsId);
188

    
189
		if (!override) {
190
			datasourceManagerClients.updateSQL(id, setCompliance, AfterSqlUpdate.UPDATE_DS_PROFILE,
191
					ImmutableMap.of("level", level, "apiId", apiId, "dsId", id));
192
		} else if (level != null) {
193
			datasourceManagerClients.updateSQL(id, overrideCompliance, AfterSqlUpdate.UPDATE_DS_PROFILE,
194
					ImmutableMap.of("level", level, "apiId", apiId, "dsId", id));
195
		} else {
196
			datasourceManagerClients.updateSQL(id, resetCompliance, AfterSqlUpdate.UPDATE_DS_PROFILE, ImmutableMap.of("apiId", apiId, "dsId", id));
197
		}
198
	}
199

    
200
	@Override
201
	public void setLastCollectionInfo(final String dsId, final String apiId, final String mdId, final Integer size, final Date date)
202
			throws DsmException {
203
		setLastOperationInfo(setLastCollectionInfo, fixDsId(dsId), apiId, mdId, size, date);
204
	}
205

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

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

    
218
	private void setLastOperationInfo(final Resource sqlResource, final String dsId, final String apiId, final String mdId, final Integer size, final Date date)
219
			throws DsmException {
220
		final Map<String, Object> params = new HashMap<>();
221
		params.put("dsId", dsId);
222
		params.put("apiId", apiId);
223
		params.put("mdId", mdId);
224
		params.put("size", size);
225
		params.put("date", date);
226
		datasourceManagerClients.updateSQL(dsId, sqlResource, AfterSqlUpdate.UPDATE_DS_PROFILE, params);
227
	}
228

    
229
	@Override
230
	public void updateApiDetails(final String dsId,
231
			final String apiId,
232
			final String metadataIdentifierPath,
233
			final String baseUrl,
234
			final Map<String, String> params)
235
			throws DsmException {
236

    
237
		final String id = fixDsId(dsId);
238

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

    
242
		// Insert new params
243
		for (final Map.Entry<String, String> e : params.entrySet()) {
244
			final Map<String, Object> sqlParams = ImmutableMap.of("param", e.getKey(), "value", e.getValue(), "api", apiId);
245
			datasourceManagerClients.updateSQL(id, insertApiParam, AfterSqlUpdate.NONE, sqlParams);
246
		}
247

    
248
		// Update the BaseURL
249
		datasourceManagerClients.updateSQL(id,
250
				"UPDATE dsm_api SET baseurl = :baseurl WHERE id = :api",
251
				AfterSqlUpdate.NONE,
252
				ImmutableMap.of("baseurl", baseUrl, "api", apiId));
253

    
254
		// Update the metadata_identifier_path
255
		datasourceManagerClients.updateSQL(id,
256
				"UPDATE dsm_api SET metadata_identifier_path = :path WHERE id = :api",
257
				AfterSqlUpdate.NONE,
258
				ImmutableMap.of("path", metadataIdentifierPath, "api", apiId));
259

    
260
		// Update the IS profile
261
		datasourceManagerClients.regenerateProfile(id);
262
	}
263

    
264
	@Override
265
	public List<? extends BrowsableField> listBrowsableFields() throws DsmException {
266
		return getBrowsableFields();
267
	}
268

    
269
	@Override
270
	public List<BrowseTerm> browseField(final String field) throws DsmException {
271
		final Optional<DbBrowsableField> bf = getBrowsableFields()
272
				.stream()
273
				.filter(f -> f.getId().equals(field))
274
				.findFirst();
275

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

    
290
	@Override
291
	public void addApi(final Api<ApiParam> api) throws DsmException {
292

    
293
		datasourceManagerClients.updateSQL(api.getDatasource(), insertApi, AfterSqlUpdate.NONE, DatasourceFunctions.apiToMap(api));
294

    
295
		api.getApiParams().forEach(p -> {
296
			final ImmutableMap<String, Object> sqlParams = ImmutableMap.of("param", p.getParam(), "value", p.getValue(), "api", api.getId());
297
			try {
298
				datasourceManagerClients.updateSQL(api.getDatasource(), insertApiParam, AfterSqlUpdate.NONE, sqlParams);
299
			} catch (final DsmException e) {
300
				throw new RuntimeException(e);
301
			}
302
		});
303

    
304
		datasourceManagerClients.regenerateProfile(api.getDatasource());
305
	}
306

    
307
	@Override
308
	public void deleteApi(final String dsId, final String apiId) throws DsmException {
309
		if (!isRemovable(dsId, apiId)) { throw new DsmException("The api " + apiId + " can't be deleted"); }
310

    
311
		datasourceManagerClients.updateSQL(dsId, "DELETE FROM dsm_apiparams WHERE api = :api", AfterSqlUpdate.NONE, ImmutableMap.of("api", apiId));
312
		datasourceManagerClients.updateSQL(dsId, "DELETE FROM dsm_api WHERE id = :api", AfterSqlUpdate.UPDATE_DS_PROFILE, ImmutableMap.of("api", apiId));
313
	}
314

    
315
	public DatasourceManagerClients getDatasourceManagerClients() {
316
		return datasourceManagerClients;
317
	}
318

    
319
	private String fixDsId(final String dsId) throws DsmException {
320
		return dsId.endsWith(REPO_PROFILEID_SUFFIX) ? datasourceManagerClients.findDatasourceId(dsId) : dsId;
321
	}
322

    
323
	@Required
324
	public void setDatasourceManagerClients(final DatasourceManagerClients datasourceManagerClients) {
325
		this.datasourceManagerClients = datasourceManagerClients;
326
	}
327

    
328
	public List<DbBrowsableField> getBrowsableFields() {
329
		return browsableFields;
330
	}
331

    
332
	@Required
333
	public void setBrowsableFields(final List<DbBrowsableField> browsableFields) {
334
		this.browsableFields = browsableFields;
335
	}
336

    
337
}
(4-4/4)