Project

General

Profile

1
package eu.dnetlib.enabling.datasources;
2

    
3
import java.io.StringReader;
4
import java.text.ParseException;
5
import java.util.Date;
6
import java.util.List;
7
import java.util.Map;
8
import java.util.stream.Collectors;
9

    
10
import org.apache.commons.io.IOUtils;
11
import org.apache.commons.logging.Log;
12
import org.apache.commons.logging.LogFactory;
13
import org.dom4j.Document;
14
import org.dom4j.io.SAXReader;
15
import org.quartz.CronExpression;
16
import org.springframework.beans.factory.annotation.Autowired;
17
import org.springframework.beans.factory.annotation.Required;
18
import org.springframework.core.io.ClassPathResource;
19
import org.springframework.core.io.Resource;
20
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
21

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

    
24
import eu.dnetlib.enabling.datasources.common.Api;
25
import eu.dnetlib.enabling.datasources.common.ApiParam;
26
import eu.dnetlib.enabling.datasources.common.Datasource;
27
import eu.dnetlib.enabling.datasources.common.DatasourceManagerException;
28
import eu.dnetlib.enabling.datasources.common.Identity;
29
import eu.dnetlib.enabling.datasources.common.Organization;
30
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpDocumentNotFoundException;
31
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpException;
32
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService;
33
import eu.dnetlib.enabling.is.registry.rmi.ISRegistryService;
34
import eu.dnetlib.enabling.locators.UniqueServiceLocator;
35

    
36
public class DatasourceManagerClients {
37

    
38
	private static final String REPOSITORY_SERVICE_RESOURCE_TYPE = "RepositoryServiceResourceType";
39
	private static final Log log = LogFactory.getLog(DatasourceManagerClients.class);
40

    
41
	private static final Resource isDefinedParamQuery = new ClassPathResource("/eu/dnetlib/enabling/datasources/queries/isDefinedParam.sql");
42
	private static final Resource dsQuery = new ClassPathResource("/eu/dnetlib/enabling/datasources/queries/getDatasource.sql");
43
	private static final Resource dsIdentitiesQuery = new ClassPathResource("/eu/dnetlib/enabling/datasources/queries/dsIdentitiesQuery.sql");
44
	private static final Resource dsOrganizationsQuery = new ClassPathResource("/eu/dnetlib/enabling/datasources/queries/dsOrganizationsQuery.sql");
45
	private static final Resource listApisByDsId = new ClassPathResource("/eu/dnetlib/enabling/datasources/queries/listApisByDsId.sql");
46

    
47
	private NamedParameterJdbcTemplate jdbcTemplate;
48

    
49
	public enum AfterSqlUpdate {
50
		DELETE_DS_PROFILE, UPDATE_DS_PROFILE, NONE
51
	}
52

    
53
	@Autowired
54
	private UniqueServiceLocator serviceLocator;
55

    
56
	public String findDatasourceId(final String profileId) throws DatasourceManagerException {
57
		try {
58
			return serviceLocator.getService(ISLookUpService.class).getResourceProfileByQuery(
59
					"/*[.//RESOURCE_IDENTIFIER/@value='" + profileId + "']//EXTRA_FIELDS/FIELD[./key='OpenAireDataSourceId']/value/text()");
60
		} catch (final Exception e) {
61
			log.error("Error finding dsId of profile " + profileId, e);
62
			throw new DatasourceManagerException(-1, "Error finding dsId of profile " + profileId, e);
63
		}
64
	}
65

    
66
	public String getDatasourceProfile(final String dsId) throws DatasourceManagerException {
67
		try {
68
			return serviceLocator.getService(ISLookUpService.class)
69
					.getResourceProfileByQuery(
70
							"collection('/db/DRIVER/RepositoryServiceResources/RepositoryServiceResourceType')/*[.//EXTRA_FIELDS/FIELD[./key='OpenAireDataSourceId']/value/text() = '"
71
									+ dsId + "']");
72
		} catch (final Exception e) {
73
			return null;
74
		}
75
	}
76

    
77
	public boolean deleteProfile(final String dsId) throws DatasourceManagerException {
78
		try {
79
			final SAXReader reader = new SAXReader();
80

    
81
			final String profile = getDatasourceProfile(dsId);
82

    
83
			if (profile != null) {
84
				final Document docOld = reader.read(new StringReader(profile));
85
				final String profId = docOld.valueOf("//RESOURCE_IDENTIFIER/@value");
86
				serviceLocator.getService(ISRegistryService.class).deleteProfile(profId);
87
			}
88
			return true;
89
		} catch (final Exception e) {
90
			log.error("Error deleting profile", e);
91
			throw new DatasourceManagerException(-1, "Error deleting profile", e);
92
		}
93
	}
94

    
95
	public boolean regenerateProfile(final String dsId) throws DatasourceManagerException {
96

    
97
		final Datasource<Organization<?>, Identity> ds = getDatasourceById(dsId);
98
		final List<Api<ApiParam>> apis = getApis(dsId);
99

    
100
		try {
101

    
102
			final ISRegistryService registry = serviceLocator.getService(ISRegistryService.class);
103

    
104
			final String oldProfile = getDatasourceProfile(dsId);
105

    
106
			if (oldProfile != null) {
107
				final Document docOld = new SAXReader().read(new StringReader(oldProfile));
108
				final String profId = docOld.valueOf("//RESOURCE_IDENTIFIER/@value");
109
				final String profile = DatasourceFunctions.dsToProfile(ds, apis, profId);
110
				registry.updateProfile(profId, profile, REPOSITORY_SERVICE_RESOURCE_TYPE);
111
				log.info("Profile " + profId + " UPDATED for ds " + dsId);
112
			} else {
113
				final String profile = DatasourceFunctions.dsToProfile(ds, apis, "");
114
				final String profId = registry.registerProfile(profile);
115
				log.info("Valid Profile " + profId + " REGISTERED for ds " + dsId);
116
			}
117
			return true;
118
		} catch (final Exception e) {
119
			log.error("Error saving profile, id: " + dsId, e);
120
			throw new DatasourceManagerException(-1, "Error regenerating profile", e);
121
		}
122
	}
123

    
124
	public List<Map<String, Object>> searchSQL(final String sql, final Map<String, Object> sqlParams) throws DatasourceManagerException {
125
		try {
126
			log.debug("Executing SQL: " + sql);
127
			return jdbcTemplate.queryForList(sql, sqlParams);
128
		} catch (final Exception e) {
129
			log.error("Error executing sql", e);
130

    
131
			throw new DatasourceManagerException(-1, "Error obtaining datasources from db", e);
132
		}
133
	}
134

    
135
	public List<Map<String, Object>> searchSQL(final Resource sqlResource, final Map<String, Object> sqlParams) throws DatasourceManagerException {
136
		try {
137
			return searchSQL(IOUtils.toString(sqlResource.getInputStream()), sqlParams);
138
		} catch (final Exception e) {
139
			log.error("Error executing sql", e);
140
			throw new DatasourceManagerException(-1, "Error obtaining datasources from db", e);
141
		}
142
	}
143

    
144
	public void updateSQL(final String dsId, final String sql, final AfterSqlUpdate op, final Map<String, Object> sqlparams)
145
			throws DatasourceManagerException {
146
		log.debug("Executing query SQL: " + sql);
147

    
148
		jdbcTemplate.update(sql, sqlparams);
149

    
150
		switch (op) {
151
		case DELETE_DS_PROFILE:
152
			deleteProfile(dsId);
153
			break;
154
		case UPDATE_DS_PROFILE:
155
			regenerateProfile(dsId);
156
			break;
157
		default:
158
			break;
159
		}
160

    
161
	}
162

    
163
	public void updateSQL(final String dsId, final Resource sqlResource, final AfterSqlUpdate op, final Map<String, Object> sqlparams)
164
			throws DatasourceManagerException {
165
		try {
166
			updateSQL(dsId, IOUtils.toString(sqlResource.getInputStream()), op, sqlparams);
167
		} catch (final Exception e) {
168
			log.error("Error in updateSQL", e);
169
			throw new DatasourceManagerException(-1, "Error in updateSQL", e);
170
		}
171
	}
172

    
173
	public Datasource<Organization<?>, Identity> getDatasourceById(final String id) throws DatasourceManagerException {
174
		final List<Map<String, Object>> list = searchSQL(dsQuery, ImmutableMap.of("dsId", id));
175

    
176
		if (list.size() != 1) { throw new DatasourceManagerException("Invalid number of ds with id: " + id); }
177

    
178
		final Datasource<Organization<?>, Identity> ds = DatasourceFunctions.mapToDatasource(list.get(0));
179
		ds.setIdentities(searchSQL(dsIdentitiesQuery, ImmutableMap.of("dsId", id))
180
				.stream()
181
				.map(DatasourceFunctions::mapToDsIdentity)
182
				.collect(Collectors.toSet()));
183
		ds.setOrganizations(searchSQL(dsOrganizationsQuery, ImmutableMap.of("dsId", id))
184
				.stream()
185
				.map(DatasourceFunctions::mapToDsOrganization)
186
				.collect(Collectors.toSet()));
187

    
188
		return ds;
189
	}
190

    
191
	public List<Api<ApiParam>> getApis(final String dsId) throws DatasourceManagerException {
192

    
193
		return searchSQL(listApisByDsId, ImmutableMap.of("dsId", dsId))
194
				.stream()
195
				.map(DatasourceFunctions::mapToApi)
196
				.collect(Collectors.toList());
197
	}
198

    
199
	public boolean isDefinedParam(final String apiId, final String param) throws DatasourceManagerException {
200
		return !searchSQL(isDefinedParamQuery, ImmutableMap.of("apiId", apiId, "param", param)).isEmpty();
201
	}
202

    
203
	public Date findNextScheduledExecution(final String dsId, final String ifaceId) throws DatasourceManagerException {
204
		final String xquery = "/*[.//DATAPROVIDER/@interface='" + ifaceId + "' and .//SCHEDULING/@enabled='true']//CRON/text()";
205
		try {
206
			final String cronExpression = serviceLocator.getService(ISLookUpService.class).getResourceProfileByQuery(xquery);
207
			final CronExpression cron = new CronExpression(cronExpression);
208
			return cron.getNextValidTimeAfter(new Date());
209
		} catch (final ISLookUpDocumentNotFoundException e) {
210
			// When the value is not found a null value must be returned
211
			return null;
212
		} catch (final ISLookUpException e) {
213
			log.error("Error in xquery: " + xquery, e);
214
			throw new DatasourceManagerException(-1, "Error in xquery: " + xquery, e);
215
		} catch (final ParseException e) {
216
			log.error("Error parsing cron expression", e);
217
			throw new DatasourceManagerException(-1, "Error parsing cron expression", e);
218
		}
219
	}
220

    
221
	public UniqueServiceLocator getServiceLocator() {
222
		return serviceLocator;
223
	}
224

    
225
	@Required
226
	public void setServiceLocator(final UniqueServiceLocator serviceLocator) {
227
		this.serviceLocator = serviceLocator;
228
	}
229

    
230
	public NamedParameterJdbcTemplate getJdbcTemplate() {
231
		return jdbcTemplate;
232
	}
233

    
234
	@Required
235
	public void setJdbcTemplate(final NamedParameterJdbcTemplate jdbcTemplate) {
236
		this.jdbcTemplate = jdbcTemplate;
237
	}
238

    
239
}
(2-2/4)