Project

General

Profile

1 26600 sandro.lab
package eu.dnetlib.enabling.datasources;
2
3
import java.io.StringReader;
4 28070 michele.ar
import java.text.ParseException;
5
import java.util.Date;
6 50348 michele.ar
import java.util.HashMap;
7 26600 sandro.lab
import java.util.List;
8
import java.util.Map;
9 50043 michele.ar
import java.util.stream.Collectors;
10 43842 michele.ar
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 49890 michele.ar
import org.springframework.beans.factory.annotation.Autowired;
18 43842 michele.ar
import org.springframework.beans.factory.annotation.Required;
19
import org.springframework.core.io.ClassPathResource;
20
import org.springframework.core.io.Resource;
21 49890 michele.ar
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
22 43842 michele.ar
23 49890 michele.ar
import com.google.common.collect.ImmutableMap;
24 43842 michele.ar
25 50043 michele.ar
import eu.dnetlib.enabling.datasources.common.Api;
26
import eu.dnetlib.enabling.datasources.common.ApiParam;
27 49890 michele.ar
import eu.dnetlib.enabling.datasources.common.Datasource;
28 50251 michele.ar
import eu.dnetlib.enabling.datasources.common.DsmException;
29 49983 michele.ar
import eu.dnetlib.enabling.datasources.common.Identity;
30
import eu.dnetlib.enabling.datasources.common.Organization;
31 28070 michele.ar
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpDocumentNotFoundException;
32
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpException;
33 26600 sandro.lab
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService;
34
import eu.dnetlib.enabling.is.registry.rmi.ISRegistryService;
35 32789 michele.ar
import eu.dnetlib.enabling.locators.UniqueServiceLocator;
36 50509 sandro.lab
import org.springframework.transaction.annotation.Transactional;
37 26600 sandro.lab
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 49890 michele.ar
43 50596 claudio.at
	private static final Resource dsQuery = new ClassPathResource(LocalOpenaireDatasourceManagerImpl.QUERY_BASEDIR + "getDatasource.sql");
44
	private static final Resource dsIdentitiesQuery = new ClassPathResource(LocalOpenaireDatasourceManagerImpl.QUERY_BASEDIR + "dsIdentitiesQuery.sql");
45
	private static final Resource dsOrganizationsQuery = new ClassPathResource(LocalOpenaireDatasourceManagerImpl.QUERY_BASEDIR + "dsOrganizationsQuery.sql");
46
	private static final Resource listApisByDsId = new ClassPathResource(LocalOpenaireDatasourceManagerImpl.QUERY_BASEDIR + "listApisByDsId.sql");
47
	private static final Resource isDefinedParamQuery = new ClassPathResource(LocalOpenaireDatasourceManagerImpl.QUERY_BASEDIR + "isDefinedParam.sql");
48 49890 michele.ar
49
	private NamedParameterJdbcTemplate jdbcTemplate;
50
51
	public enum AfterSqlUpdate {
52
		DELETE_DS_PROFILE, UPDATE_DS_PROFILE, NONE
53
	}
54
55
	@Autowired
56 41364 claudio.at
	private UniqueServiceLocator serviceLocator;
57 26600 sandro.lab
58 50251 michele.ar
	public String findDatasourceId(final String profileId) throws DsmException {
59 26600 sandro.lab
		try {
60 32789 michele.ar
			return serviceLocator.getService(ISLookUpService.class).getResourceProfileByQuery(
61 26600 sandro.lab
					"/*[.//RESOURCE_IDENTIFIER/@value='" + profileId + "']//EXTRA_FIELDS/FIELD[./key='OpenAireDataSourceId']/value/text()");
62 43842 michele.ar
		} catch (final Exception e) {
63 32789 michele.ar
			log.error("Error finding dsId of profile " + profileId, e);
64 50251 michele.ar
			throw new DsmException(-1, "Error finding dsId of profile " + profileId, e);
65 26600 sandro.lab
		}
66
	}
67
68 50251 michele.ar
	public String getDatasourceProfile(final String dsId) throws DsmException {
69 26600 sandro.lab
		try {
70 32789 michele.ar
			return serviceLocator.getService(ISLookUpService.class)
71 33829 michele.ar
					.getResourceProfileByQuery(
72
							"collection('/db/DRIVER/RepositoryServiceResources/RepositoryServiceResourceType')/*[.//EXTRA_FIELDS/FIELD[./key='OpenAireDataSourceId']/value/text() = '"
73
									+ dsId + "']");
74 43842 michele.ar
		} catch (final Exception e) {
75 26600 sandro.lab
			return null;
76
		}
77
	}
78
79 50251 michele.ar
	public boolean deleteProfile(final String dsId) throws DsmException {
80 26600 sandro.lab
		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 32789 michele.ar
				serviceLocator.getService(ISRegistryService.class).deleteProfile(profId);
89 26600 sandro.lab
			}
90
			return true;
91 43842 michele.ar
		} catch (final Exception e) {
92 32789 michele.ar
			log.error("Error deleting profile", e);
93 50251 michele.ar
			throw new DsmException(-1, "Error deleting profile", e);
94 26600 sandro.lab
		}
95
	}
96
97 50251 michele.ar
	public boolean regenerateProfile(final String dsId) throws DsmException {
98 50628 claudio.at
		return regenerateProfile(dsId, serviceLocator.getService(ISRegistryService.class));
99
	}
100 26600 sandro.lab
101 50628 claudio.at
	public boolean regenerateProfile(final String dsId, final ISRegistryService registry) throws DsmException {
102
103 49983 michele.ar
		final Datasource<Organization<?>, Identity> ds = getDatasourceById(dsId);
104 50043 michele.ar
		final List<Api<ApiParam>> apis = getApis(dsId);
105 49890 michele.ar
106 26600 sandro.lab
		try {
107
108 49890 michele.ar
			final String oldProfile = getDatasourceProfile(dsId);
109 26600 sandro.lab
110 49890 michele.ar
			if (oldProfile != null) {
111
				final Document docOld = new SAXReader().read(new StringReader(oldProfile));
112 26600 sandro.lab
				final String profId = docOld.valueOf("//RESOURCE_IDENTIFIER/@value");
113 50043 michele.ar
				final String profile = DatasourceFunctions.dsToProfile(ds, apis, profId);
114 49890 michele.ar
				registry.updateProfile(profId, profile, REPOSITORY_SERVICE_RESOURCE_TYPE);
115 26600 sandro.lab
				log.info("Profile " + profId + " UPDATED for ds " + dsId);
116
			} else {
117 50043 michele.ar
				final String profile = DatasourceFunctions.dsToProfile(ds, apis, "");
118 49890 michele.ar
				final String profId = registry.registerProfile(profile);
119 33829 michele.ar
				log.info("Valid Profile " + profId + " REGISTERED for ds " + dsId);
120 26600 sandro.lab
			}
121
			return true;
122 43842 michele.ar
		} catch (final Exception e) {
123
			log.error("Error saving profile, id: " + dsId, e);
124 50251 michele.ar
			throw new DsmException(-1, "Error regenerating profile", e);
125 26600 sandro.lab
		}
126
	}
127
128 50509 sandro.lab
129
	@Transactional(readOnly = true)
130 50251 michele.ar
	public List<Map<String, Object>> searchSQL(final String sql, final Map<String, Object> sqlParams) throws DsmException {
131 41364 claudio.at
		try {
132 49890 michele.ar
			log.debug("Executing SQL: " + sql);
133
			return jdbcTemplate.queryForList(sql, sqlParams);
134
		} catch (final Exception e) {
135
			log.error("Error executing sql", e);
136 41364 claudio.at
137 50251 michele.ar
			throw new DsmException(-1, "Error obtaining datasources from db", e);
138 26600 sandro.lab
		}
139
	}
140
141 50509 sandro.lab
142
	@Transactional(readOnly = true)
143 50251 michele.ar
	public List<Map<String, Object>> searchSQL(final Resource sqlResource, final Map<String, Object> sqlParams) throws DsmException {
144 26600 sandro.lab
		try {
145 49890 michele.ar
			return searchSQL(IOUtils.toString(sqlResource.getInputStream()), sqlParams);
146 43842 michele.ar
		} catch (final Exception e) {
147 49890 michele.ar
			log.error("Error executing sql", e);
148 50251 michele.ar
			throw new DsmException(-1, "Error obtaining datasources from db", e);
149 26600 sandro.lab
		}
150
	}
151
152 50509 sandro.lab
153
	@Transactional
154 49983 michele.ar
	public void updateSQL(final String dsId, final String sql, final AfterSqlUpdate op, final Map<String, Object> sqlparams)
155 50251 michele.ar
			throws DsmException {
156 49890 michele.ar
		log.debug("Executing query SQL: " + sql);
157 26600 sandro.lab
158 49890 michele.ar
		jdbcTemplate.update(sql, sqlparams);
159 26600 sandro.lab
160 49890 michele.ar
		switch (op) {
161
		case DELETE_DS_PROFILE:
162
			deleteProfile(dsId);
163
			break;
164
		case UPDATE_DS_PROFILE:
165 50628 claudio.at
166
			regenerateProfile(dsId, serviceLocator.getService(ISRegistryService.class));
167 49890 michele.ar
			break;
168
		default:
169
			break;
170 26600 sandro.lab
		}
171 49890 michele.ar
172 26600 sandro.lab
	}
173 50509 sandro.lab
	@Transactional
174 49983 michele.ar
	public void updateSQL(final String dsId, final Resource sqlResource, final AfterSqlUpdate op, final Map<String, Object> sqlparams)
175 50251 michele.ar
			throws DsmException {
176 26600 sandro.lab
		try {
177 49890 michele.ar
			updateSQL(dsId, IOUtils.toString(sqlResource.getInputStream()), op, sqlparams);
178 43842 michele.ar
		} catch (final Exception e) {
179 49890 michele.ar
			log.error("Error in updateSQL", e);
180 50251 michele.ar
			throw new DsmException(-1, "Error in updateSQL", e);
181 26600 sandro.lab
		}
182
	}
183
184 50509 sandro.lab
	@Transactional(readOnly = true)
185 50251 michele.ar
	public Datasource<Organization<?>, Identity> getDatasourceById(final String id) throws DsmException {
186 49983 michele.ar
		final List<Map<String, Object>> list = searchSQL(dsQuery, ImmutableMap.of("dsId", id));
187 26600 sandro.lab
188 50251 michele.ar
		if (list.size() != 1) { throw new DsmException("Invalid number of ds with id: " + id); }
189 26600 sandro.lab
190 50154 michele.ar
		final Datasource<Organization<?>, Identity> ds = DatasourceFunctions.mapToDatasource(list.get(0));
191
		ds.setIdentities(searchSQL(dsIdentitiesQuery, ImmutableMap.of("dsId", id))
192
				.stream()
193
				.map(DatasourceFunctions::mapToDsIdentity)
194
				.collect(Collectors.toSet()));
195
		ds.setOrganizations(searchSQL(dsOrganizationsQuery, ImmutableMap.of("dsId", id))
196
				.stream()
197
				.map(DatasourceFunctions::mapToDsOrganization)
198
				.collect(Collectors.toSet()));
199
200
		return ds;
201 26600 sandro.lab
	}
202
203 50509 sandro.lab
204
	@Transactional(readOnly = true)
205 50251 michele.ar
	public List<Api<ApiParam>> getApis(final String dsId) throws DsmException {
206 50043 michele.ar
207
		return searchSQL(listApisByDsId, ImmutableMap.of("dsId", dsId))
208
				.stream()
209
				.map(DatasourceFunctions::mapToApi)
210
				.collect(Collectors.toList());
211
	}
212
213 50509 sandro.lab
	@Transactional(readOnly = true)
214 50251 michele.ar
	public boolean isDefinedParam(final String apiId, final String param) throws DsmException {
215 49890 michele.ar
		return !searchSQL(isDefinedParamQuery, ImmutableMap.of("apiId", apiId, "param", param)).isEmpty();
216 26600 sandro.lab
	}
217 32789 michele.ar
218 50251 michele.ar
	public Date findNextScheduledExecution(final String dsId, final String ifaceId) throws DsmException {
219 28070 michele.ar
		final String xquery = "/*[.//DATAPROVIDER/@interface='" + ifaceId + "' and .//SCHEDULING/@enabled='true']//CRON/text()";
220
		try {
221 32789 michele.ar
			final String cronExpression = serviceLocator.getService(ISLookUpService.class).getResourceProfileByQuery(xquery);
222 28070 michele.ar
			final CronExpression cron = new CronExpression(cronExpression);
223
			return cron.getNextValidTimeAfter(new Date());
224 43842 michele.ar
		} catch (final ISLookUpDocumentNotFoundException e) {
225 28070 michele.ar
			// When the value is not found a null value must be returned
226
			return null;
227 43842 michele.ar
		} catch (final ISLookUpException e) {
228 32789 michele.ar
			log.error("Error in xquery: " + xquery, e);
229 50251 michele.ar
			throw new DsmException(-1, "Error in xquery: " + xquery, e);
230 43842 michele.ar
		} catch (final ParseException e) {
231 32789 michele.ar
			log.error("Error parsing cron expression", e);
232 50251 michele.ar
			throw new DsmException(-1, "Error parsing cron expression", e);
233 28070 michele.ar
		}
234
	}
235 26600 sandro.lab
236 50509 sandro.lab
	@Transactional(readOnly = true)
237 50348 michele.ar
	public void regenerateProfiles() throws DsmException {
238 50628 claudio.at
		final ISRegistryService registry = serviceLocator.getService(ISRegistryService.class);
239 50348 michele.ar
		searchSQL("SELECT id FROM dsm_datasources", new HashMap<>()).stream()
240
				.map(m -> m.get("id").toString())
241
				.forEach(id -> {
242
					try {
243 50628 claudio.at
						regenerateProfile(id, registry);
244 50348 michele.ar
					} catch (final DsmException e) {
245
						log.error("Error regeneating profile: " + id, e);
246
					}
247
				});
248
	}
249
250 49890 michele.ar
	public NamedParameterJdbcTemplate getJdbcTemplate() {
251
		return jdbcTemplate;
252 26600 sandro.lab
	}
253
254
	@Required
255 49983 michele.ar
	public void setJdbcTemplate(final NamedParameterJdbcTemplate jdbcTemplate) {
256 49890 michele.ar
		this.jdbcTemplate = jdbcTemplate;
257 26600 sandro.lab
	}
258
259
}