Project

General

Profile

1
package eu.dnetlib.data.mdstore.modular.postgres;
2

    
3
import java.io.IOException;
4
import java.io.InputStream;
5
import java.sql.Connection;
6
import java.sql.DatabaseMetaData;
7
import java.sql.PreparedStatement;
8
import java.sql.ResultSet;
9
import java.sql.SQLException;
10
import java.util.ArrayList;
11
import java.util.List;
12

    
13
import javax.sql.DataSource;
14

    
15
import org.antlr.stringtemplate.StringTemplate;
16
import org.apache.commons.io.IOUtils;
17
import org.apache.commons.lang.StringUtils;
18
import org.apache.commons.logging.Log;
19
import org.apache.commons.logging.LogFactory;
20
import org.springframework.beans.factory.annotation.Autowired;
21
import org.springframework.beans.factory.annotation.Required;
22
import org.springframework.core.io.Resource;
23

    
24
import eu.dnetlib.data.mdstore.MDStoreServiceException;
25
import eu.dnetlib.data.mdstore.modular.RecordParser;
26
import eu.dnetlib.data.mdstore.modular.connector.MDStore;
27
import eu.dnetlib.data.mdstore.modular.connector.MDStoreDao;
28

    
29
/**
30
 * The Class MDStoreDaoPostgresImpl.
31
 */
32
public class MDStoreDaoPostgresImpl implements MDStoreDao {
33

    
34
	/** The datasource. */
35
	@javax.annotation.Resource(name = "mdstoreDataSource")
36
	private DataSource datasource;
37

    
38
	/** The metadata table. */
39
	private static String METADATA_TABLE = "metadata";
40

    
41
	/** The MDID column name. */
42
	private static String MDIDColumnName = "mdid";
43

    
44
	/** The template metadata. */
45
	private Resource templateMetadata;
46

    
47
	/** The template collection. */
48
	private Resource templateCollection;
49

    
50
	/** The record parser. */
51
	@Autowired
52
	private RecordParser recordParser;
53

    
54
	@Autowired
55
	private PostgresTransactionManagerImpl transactionManager;
56

    
57
	/** The Constant log. */
58
	private static final Log log = LogFactory.getLog(MDStoreDaoPostgresImpl.class);
59

    
60
	/**
61
	 * Verify if Exists a particular table.
62
	 *
63
	 * @param tableName
64
	 *            the table name
65
	 * @param conn
66
	 *            the conn
67
	 * @return true, if successful
68
	 * @throws SQLException
69
	 *             the SQL exception
70
	 */
71
	private boolean existsTable(final String tableName, final Connection conn) throws SQLException {
72
		DatabaseMetaData md = conn.getMetaData();
73
		ResultSet rs = md.getTables(null, null, tableName, null);
74
		while (rs.next()) {
75
			String tName = rs.getString(3);
76
			if (tableName.equals(tName)) return true;
77
		}
78
		return false;
79
	}
80

    
81
	/*
82
	 * (non-Javadoc)
83
	 * 
84
	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreDao#getMDStore(java.lang.String)
85
	 */
86
	@Override
87
	public MDStore getMDStore(final String mdId) throws MDStoreServiceException {
88
		Connection conn = null;
89
		try {
90
			conn = datasource.getConnection();
91
			verifyConsistency(conn);
92
			String mdProfileID = transactionManager.getMDStoreForTransaction(mdId);
93
			String sql = String.format("select * from %s where %s = ? or current_table= ?", METADATA_TABLE, MDIDColumnName);
94
			if (mdProfileID != null) {
95
				sql = String.format("select * from %s where %s = ?", METADATA_TABLE, MDIDColumnName);
96
			}
97
			PreparedStatement ps = conn.prepareStatement(sql);
98
			if (mdProfileID != null) {
99
				ps.setString(1, mdProfileID);
100
			} else {
101
				ps.setString(1, mdId);
102
				ps.setString(2, mdId);
103
			}
104
			ResultSet rs = ps.executeQuery();
105
			if (!rs.next()) throw new MDStoreServiceException("Collection not found for MDStoreID :" + (mdProfileID != null ? mdProfileID : mdId));
106
			String tableName = mdProfileID != null ? mdId : rs.getString("current_table");
107
			String format = rs.getString("format");
108
			String layout = rs.getString("layout");
109
			String interpretation = rs.getString("interpretation");
110
			int size = rs.getInt("size");
111
			if (!existsTable(tableName, conn))
112
				throw new MDStoreServiceException("Error the current MDstore of: " + mdId + " with id " + tableName + " not exist!");
113
			return new PostgresMDStore(tableName, format, layout, interpretation, this.datasource, true, recordParser, size, mdProfileID != null ? mdProfileID
114
					: mdId);
115
		} catch (Exception e) {
116
			log.error("Error on get mdstore", e);
117
			throw new MDStoreServiceException(e);
118
		} finally {
119
			if (conn != null) {
120
				try {
121
					conn.close();
122
				} catch (SQLException e) {
123
					log.error("Error on close connection", e);
124
					throw new MDStoreServiceException(e);
125
				}
126
			}
127
		}
128
	}
129

    
130
	/**
131
	 * Initialize tables.
132
	 *
133
	 * @param connection
134
	 *            the connection
135
	 * @throws IOException
136
	 *             Signals that an I/O exception has occurred.
137
	 * @throws SQLException
138
	 *             the SQL exception
139
	 */
140
	private void initializeTables(final Connection connection) throws IOException, SQLException {
141
		InputStream is = getTemplateMetadata().getInputStream();
142
		String createTableQuery = IOUtils.toString(is);
143
		PreparedStatement ps = connection.prepareStatement(createTableQuery);
144
		ps.executeUpdate();
145
	}
146

    
147
	/**
148
	 * Verify consistency.
149
	 *
150
	 * @param conn
151
	 *            the conn
152
	 * @throws SQLException
153
	 *             the SQL exception
154
	 * @throws IOException
155
	 *             Signals that an I/O exception has occurred.
156
	 */
157
	private void verifyConsistency(final Connection conn) throws SQLException, IOException {
158
		if (existsTable(METADATA_TABLE, conn)) return;
159
		initializeTables(conn);
160
	}
161

    
162
	/*
163
	 * (non-Javadoc)
164
	 * 
165
	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreDao#listMDStores()
166
	 */
167
	@Override
168
	public List<String> listMDStores() throws MDStoreServiceException {
169
		Connection conn = null;
170
		try {
171
			conn = datasource.getConnection();
172
			verifyConsistency(conn);
173
			String query = "select  " + MDIDColumnName + "  from metadata";
174
			PreparedStatement st = conn.prepareStatement(query);
175
			ResultSet rs = st.executeQuery();
176
			List<String> ids = new ArrayList<String>();
177
			while (rs.next()) {
178
				ids.add(rs.getString(MDIDColumnName));
179
			}
180
			return ids;
181
		} catch (Exception e) {
182
			log.error("Error on listing mdstore", e);
183
			throw new MDStoreServiceException(e);
184
		} finally {
185
			if (conn != null) {
186
				try {
187
					conn.close();
188
				} catch (SQLException e) {
189
					log.error("Error on close connection", e);
190
					throw new MDStoreServiceException(e);
191
				}
192
			}
193
		}
194
	}
195

    
196
	/*
197
	 * (non-Javadoc)
198
	 * 
199
	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreDao#listMDStores(java.lang.String, java.lang.String, java.lang.String)
200
	 */
201
	@Override
202
	public List<String> listMDStores(final String format, final String layout, final String interpretation) throws MDStoreServiceException {
203
		Connection conn = null;
204
		try {
205
			conn = datasource.getConnection();
206
			verifyConsistency(conn);
207
			String query = "select  " + MDIDColumnName + "  from metadata where lower(format) = ? and lower(layout) = ? and lower(interpretation) = ?";
208
			PreparedStatement st = conn.prepareStatement(query);
209
			st.setString(1, format.toLowerCase());
210
			st.setString(2, layout.toLowerCase());
211
			st.setString(3, interpretation.toLowerCase());
212
			ResultSet rs = st.executeQuery();
213
			List<String> ids = new ArrayList<String>();
214
			while (rs.next()) {
215
				ids.add(rs.getString(MDIDColumnName));
216
			}
217
			return ids;
218
		} catch (Exception e) {
219
			log.error("Error on listing mdstore", e);
220
			throw new MDStoreServiceException(e);
221
		} finally {
222
			if (conn != null) {
223
				try {
224
					conn.close();
225
				} catch (SQLException e) {
226
					log.error("Error on close connection", e);
227
					throw new MDStoreServiceException(e);
228
				}
229
			}
230
		}
231
	}
232

    
233
	/*
234
	 * (non-Javadoc)
235
	 * 
236
	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreDao#createMDStore(java.lang.String, java.lang.String, java.lang.String,
237
	 * java.lang.String)
238
	 */
239
	@Override
240
	public void createMDStore(final String mdId, final String format, final String interpretation, final String layout) throws MDStoreServiceException {
241

    
242
		Connection conn = null;
243
		try {
244
			conn = datasource.getConnection();
245
			verifyConsistency(conn);
246
			String query = "insert into  " + METADATA_TABLE + "  values (?,?,?,?,?,?,?)";
247
			PreparedStatement st = conn.prepareStatement(query);
248
			st.setString(1, mdId);
249
			st.setString(2, format);
250
			st.setString(3, layout);
251
			st.setString(4, interpretation);
252

    
253
			String idName = mdId;
254
			if (mdId.contains("_")) {
255
				idName = StringUtils.substringBefore(mdId, "_");
256
			}
257

    
258
			st.setString(5, "mdstore_" + idName.replace("-", "_"));
259
			st.setInt(6, 0);
260
			st.setInt(7, 0);
261
			log.debug(st.toString());
262
			st.executeUpdate();
263
			final StringTemplate templateCollection = new StringTemplate(IOUtils.toString(getTemplateCollection().getInputStream()));
264
			templateCollection.setAttribute("name", "mdstore_" + idName.replace("-", "_"));
265
			st = conn.prepareStatement(templateCollection.toString());
266
			st.executeUpdate();
267

    
268
		} catch (Exception e) {
269
			log.error("Error on inserting mdstore", e);
270
			throw new MDStoreServiceException(e);
271
		} finally {
272
			if (conn != null) {
273
				try {
274
					conn.close();
275
				} catch (SQLException e) {
276
					log.error("Error on close connection", e);
277
					throw new MDStoreServiceException(e);
278
				}
279
			}
280
		}
281
	}
282

    
283
	/*
284
	 * (non-Javadoc)
285
	 * 
286
	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreDao#deleteMDStore(java.lang.String)
287
	 */
288
	@Override
289
	public void deleteMDStore(final String mdId) throws MDStoreServiceException {
290
		Connection conn = null;
291
		try {
292
			conn = datasource.getConnection();
293
			verifyConsistency(conn);
294
			// RETREIVE THE CURRENT USED TABLE ON METADATA
295
			String sql = String.format("select * from %s where %s = ?", METADATA_TABLE, MDIDColumnName);
296
			PreparedStatement ps = conn.prepareStatement(sql);
297
			ps.setString(1, mdId);
298
			ResultSet rs = ps.executeQuery();
299
			if (rs.next() == false) throw new MDStoreServiceException("Error on deleting mdstore: " + mdId + " not found in metadata");
300
			String tableName = rs.getString("current_table");
301
			// DELETE THE RELATIVE FIELDS TABLE
302
			sql = String.format("drop table %s_fields", tableName);
303
			ps = conn.prepareStatement(sql);
304
			ps.executeUpdate();
305
			// DELETE THE RELATIVE TABLE
306
			sql = String.format("drop table %s", tableName);
307
			ps = conn.prepareStatement(sql);
308
			ps.executeUpdate();
309
			// DELETE THE DISCARDED TABLE
310
			sql = String.format("drop table %s_discarded", tableName);
311
			ps = conn.prepareStatement(sql);
312
			ps.executeUpdate();
313
			sql = String.format("delete from %s where lower(%s) = ? ", METADATA_TABLE, MDIDColumnName);
314
			ps = conn.prepareStatement(sql);
315
			ps.setString(1, mdId.toLowerCase());
316
			ps.executeUpdate();
317

    
318
		} catch (Exception e) {
319
			log.error("Error on deleting mdstore", e);
320
			throw new MDStoreServiceException(e);
321
		} finally {
322
			if (conn != null) {
323
				try {
324
					conn.close();
325
				} catch (SQLException e) {
326
					log.error("Error on close connection", e);
327
					throw new MDStoreServiceException(e);
328
				}
329
			}
330
		}
331

    
332
	}
333

    
334
	/**
335
	 * Gets the template metadata.
336
	 *
337
	 * @return the template metadata
338
	 */
339
	public Resource getTemplateMetadata() {
340
		return templateMetadata;
341
	}
342

    
343
	/**
344
	 * Sets the template metadata.
345
	 *
346
	 * @param templateMetadata
347
	 *            the new template metadata
348
	 */
349
	@Required
350
	public void setTemplateMetadata(final Resource templateMetadata) {
351
		this.templateMetadata = templateMetadata;
352
	}
353

    
354
	/**
355
	 * Gets the template collection.
356
	 *
357
	 * @return the template collection
358
	 */
359
	public Resource getTemplateCollection() {
360
		return templateCollection;
361
	}
362

    
363
	/**
364
	 * Sets the template collection.
365
	 *
366
	 * @param templateCollection
367
	 *            the new template collection
368
	 */
369
	@Required
370
	public void setTemplateCollection(final Resource templateCollection) {
371
		this.templateCollection = templateCollection;
372
	}
373

    
374
}
(1-1/7)