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.HashMap;
7
import java.util.List;
8
import java.util.Map;
9
import java.util.stream.Collectors;
10

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

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

    
25
import eu.dnetlib.enabling.datasources.common.Api;
26
import eu.dnetlib.enabling.datasources.common.ApiParam;
27
import eu.dnetlib.enabling.datasources.common.Datasource;
28
import eu.dnetlib.enabling.datasources.common.DsmException;
29
import eu.dnetlib.enabling.datasources.common.Identity;
30
import eu.dnetlib.enabling.datasources.common.Organization;
31
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpDocumentNotFoundException;
32
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpException;
33
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService;
34
import eu.dnetlib.enabling.is.registry.rmi.ISRegistryService;
35
import eu.dnetlib.enabling.locators.UniqueServiceLocator;
36
import org.springframework.transaction.annotation.Transactional;
37

    
38
public class DatasourceManagerClients {
39

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

    
43
	private static final Resource dsQuery = new ClassPathResource(LocalOpenaireDatasourceManager.QUERY_BASEDIR + "getDatasource.sql");
44
	private static final Resource dsIdentitiesQuery = new ClassPathResource(LocalOpenaireDatasourceManager.QUERY_BASEDIR + "dsIdentitiesQuery.sql");
45
	private static final Resource dsOrganizationsQuery = new ClassPathResource(LocalOpenaireDatasourceManager.QUERY_BASEDIR + "dsOrganizationsQuery.sql");
46
	private static final Resource listApisByDsId = new ClassPathResource(LocalOpenaireDatasourceManager.QUERY_BASEDIR + "listApisByDsId.sql");
47
	private static final Resource isDefinedParamQuery = new ClassPathResource(LocalOpenaireDatasourceManager.QUERY_BASEDIR + "isDefinedParam.sql");
48

    
49
	private NamedParameterJdbcTemplate jdbcTemplate;
50

    
51
	public enum AfterSqlUpdate {
52
		DELETE_DS_PROFILE, UPDATE_DS_PROFILE, NONE
53
	}
54

    
55
	@Autowired
56
	private UniqueServiceLocator serviceLocator;
57

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

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

    
79
	public boolean deleteProfile(final String dsId) throws DsmException {
80
		try {
81
			final SAXReader reader = new SAXReader();
82

    
83
			final String profile = getDatasourceProfile(dsId);
84

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

    
97
	public boolean regenerateProfile(final String dsId) throws DsmException {
98

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

    
102
		try {
103

    
104
			final ISRegistryService registry = serviceLocator.getService(ISRegistryService.class);
105

    
106
			final String oldProfile = getDatasourceProfile(dsId);
107

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

    
126

    
127
	@Transactional(readOnly = true)
128
	public List<Map<String, Object>> searchSQL(final String sql, final Map<String, Object> sqlParams) throws DsmException {
129
		try {
130
			log.debug("Executing SQL: " + sql);
131
			return jdbcTemplate.queryForList(sql, sqlParams);
132
		} catch (final Exception e) {
133
			log.error("Error executing sql", e);
134

    
135
			throw new DsmException(-1, "Error obtaining datasources from db", e);
136
		}
137
	}
138

    
139

    
140
	@Transactional(readOnly = true)
141
	public List<Map<String, Object>> searchSQL(final Resource sqlResource, final Map<String, Object> sqlParams) throws DsmException {
142
		try {
143
			return searchSQL(IOUtils.toString(sqlResource.getInputStream()), sqlParams);
144
		} catch (final Exception e) {
145
			log.error("Error executing sql", e);
146
			throw new DsmException(-1, "Error obtaining datasources from db", e);
147
		}
148
	}
149

    
150

    
151
	@Transactional
152
	public void updateSQL(final String dsId, final String sql, final AfterSqlUpdate op, final Map<String, Object> sqlparams)
153
			throws DsmException {
154
		log.debug("Executing query SQL: " + sql);
155

    
156
		jdbcTemplate.update(sql, sqlparams);
157

    
158
		switch (op) {
159
		case DELETE_DS_PROFILE:
160
			deleteProfile(dsId);
161
			break;
162
		case UPDATE_DS_PROFILE:
163
			regenerateProfile(dsId);
164
			break;
165
		default:
166
			break;
167
		}
168

    
169
	}
170
	@Transactional
171
	public void updateSQL(final String dsId, final Resource sqlResource, final AfterSqlUpdate op, final Map<String, Object> sqlparams)
172
			throws DsmException {
173
		try {
174
			updateSQL(dsId, IOUtils.toString(sqlResource.getInputStream()), op, sqlparams);
175
		} catch (final Exception e) {
176
			log.error("Error in updateSQL", e);
177
			throw new DsmException(-1, "Error in updateSQL", e);
178
		}
179
	}
180

    
181
	@Transactional(readOnly = true)
182
	public Datasource<Organization<?>, Identity> getDatasourceById(final String id) throws DsmException {
183
		final List<Map<String, Object>> list = searchSQL(dsQuery, ImmutableMap.of("dsId", id));
184

    
185
		if (list.size() != 1) { throw new DsmException("Invalid number of ds with id: " + id); }
186

    
187
		final Datasource<Organization<?>, Identity> ds = DatasourceFunctions.mapToDatasource(list.get(0));
188
		ds.setIdentities(searchSQL(dsIdentitiesQuery, ImmutableMap.of("dsId", id))
189
				.stream()
190
				.map(DatasourceFunctions::mapToDsIdentity)
191
				.collect(Collectors.toSet()));
192
		ds.setOrganizations(searchSQL(dsOrganizationsQuery, ImmutableMap.of("dsId", id))
193
				.stream()
194
				.map(DatasourceFunctions::mapToDsOrganization)
195
				.collect(Collectors.toSet()));
196

    
197
		return ds;
198
	}
199

    
200

    
201
	@Transactional(readOnly = true)
202
	public List<Api<ApiParam>> getApis(final String dsId) throws DsmException {
203

    
204
		return searchSQL(listApisByDsId, ImmutableMap.of("dsId", dsId))
205
				.stream()
206
				.map(DatasourceFunctions::mapToApi)
207
				.collect(Collectors.toList());
208
	}
209

    
210
	@Transactional(readOnly = true)
211
	public boolean isDefinedParam(final String apiId, final String param) throws DsmException {
212
		return !searchSQL(isDefinedParamQuery, ImmutableMap.of("apiId", apiId, "param", param)).isEmpty();
213
	}
214

    
215
	public Date findNextScheduledExecution(final String dsId, final String ifaceId) throws DsmException {
216
		final String xquery = "/*[.//DATAPROVIDER/@interface='" + ifaceId + "' and .//SCHEDULING/@enabled='true']//CRON/text()";
217
		try {
218
			final String cronExpression = serviceLocator.getService(ISLookUpService.class).getResourceProfileByQuery(xquery);
219
			final CronExpression cron = new CronExpression(cronExpression);
220
			return cron.getNextValidTimeAfter(new Date());
221
		} catch (final ISLookUpDocumentNotFoundException e) {
222
			// When the value is not found a null value must be returned
223
			return null;
224
		} catch (final ISLookUpException e) {
225
			log.error("Error in xquery: " + xquery, e);
226
			throw new DsmException(-1, "Error in xquery: " + xquery, e);
227
		} catch (final ParseException e) {
228
			log.error("Error parsing cron expression", e);
229
			throw new DsmException(-1, "Error parsing cron expression", e);
230
		}
231
	}
232

    
233
	@Transactional(readOnly = true)
234
	public void regenerateProfiles() throws DsmException {
235
		searchSQL("SELECT id FROM dsm_datasources", new HashMap<>()).stream()
236
				.map(m -> m.get("id").toString())
237
				.forEach(id -> {
238
					try {
239
						regenerateProfile(id);
240
					} catch (final DsmException e) {
241
						log.error("Error regeneating profile: " + id, e);
242
					}
243
				});
244
	}
245

    
246
	public NamedParameterJdbcTemplate getJdbcTemplate() {
247
		return jdbcTemplate;
248
	}
249

    
250
	@Required
251
	public void setJdbcTemplate(final NamedParameterJdbcTemplate jdbcTemplate) {
252
		this.jdbcTemplate = jdbcTemplate;
253
	}
254

    
255
}
(2-2/4)