Project

General

Profile

1
package eu.dnetlib.oai.mongo;
2

    
3
import java.util.List;
4
import java.util.stream.Collectors;
5

    
6
import javax.annotation.Resource;
7

    
8
import org.apache.commons.logging.Log;
9
import org.apache.commons.logging.LogFactory;
10
import org.springframework.beans.factory.annotation.Autowired;
11
import org.springframework.beans.factory.annotation.Required;
12

    
13
import com.mongodb.BasicDBObjectBuilder;
14
import com.mongodb.DBObject;
15
import com.mongodb.MongoClient;
16
import com.mongodb.client.FindIterable;
17
import com.mongodb.client.MongoCollection;
18
import com.mongodb.client.MongoDatabase;
19
import com.mongodb.client.model.Filters;
20

    
21
import eu.dnetlib.enabling.tools.DnetStreamSupport;
22
import eu.dnetlib.oai.PublisherStoreDAO;
23
import eu.dnetlib.oai.RecordChangeDetector;
24
import eu.dnetlib.oai.conf.OAIConfigurationReader;
25
import eu.dnetlib.oai.parser.MongoQueryParser;
26
import eu.dnetlib.oai.sets.MongoSetCollection;
27
import eu.dnetlib.rmi.provision.MDFInfo;
28
import eu.dnetlib.rmi.provision.OaiPublisherException;
29
import eu.dnetlib.rmi.provision.OaiPublisherRuntimeException;
30
import net.sf.ehcache.Cache;
31
import net.sf.ehcache.Element;
32

    
33
public class MongoPublisherStoreDAO implements PublisherStoreDAO<MongoPublisherStore, DNetOAIMongoCursor> {
34

    
35
	private static final Log log = LogFactory.getLog(MongoPublisherStoreDAO.class); // NOPMD by marko on 11/24/08 5:02 PM
36

    
37
	@Autowired
38
	private MongoClient publisherMongoClient;
39

    
40
	/**
41
	 * Name of the collection with information about the OAI stores.
42
	 **/
43
	private String metadataCollection;
44

    
45
	@Resource
46
	private RecordInfoGenerator recordInfoGenerator;
47
	@Resource
48
	private MetadataExtractor metadataExtractor;
49
	@Resource
50
	private MongoQueryParser queryParser;
51
	@Resource(name = "oaiConfigurationExistReader")
52
	private OAIConfigurationReader configuration;
53
	@Resource
54
	private RecordChangeDetector recordChangeDetector;
55
	@Resource
56
	private MongoSetCollection mongoSetCollection;
57

    
58
	/**
59
	 * Cache for oaistores. Keys are dbName-storeId, values are objects of type MongoPublisherStore.
60
	 */
61
	private Cache mongoOaistoreCache;
62

    
63
	/**
64
	 * Cache for oaistores. Keys is OAI metadata prefixes, values are objects of type MongoPublisherStore.
65
	 */
66
	private Cache mongoOaistoreCacheByMdPrefix;
67

    
68
	private boolean alwaysNewRecord;
69

    
70
	protected MongoDatabase getDB(final String dbName) {
71
		return this.publisherMongoClient.getDatabase(dbName);
72
	}
73

    
74
	@Override
75
	public List<MongoPublisherStore> listPublisherStores(final String dbName) {
76
		final MongoDatabase db = getDB(dbName);
77
		final FindIterable<DBObject> stores = db.getCollection(this.metadataCollection, DBObject.class).find();
78
		return DnetStreamSupport.generateStreamFromIterator(stores.iterator())
79
				.map(storeInfo -> createFromDBObject(storeInfo, db))
80
				.collect(Collectors.toList());
81
	}
82

    
83
	@Override
84
	public MongoPublisherStore getStore(final String storeId, final String dbName) {
85
		final DBObject storeInfo = getDB(dbName).getCollection(this.metadataCollection, DBObject.class).find(Filters.eq("id", storeId)).first();
86
		return this.createFromDBObject(storeInfo, getDB(dbName));
87
	}
88

    
89
	@Override
90
	public MongoPublisherStore getStore(final String mdfName, final String mdfInterpretation, final String mdfLayout, final String dbName) {
91
		return this.getStore(this.generateStoreId(mdfName, mdfInterpretation, mdfLayout), dbName);
92
	}
93

    
94
	@Override
95
	public MongoPublisherStore getStoreFor(final String targetMetadataPrefix, final String dbName) {
96

    
97
		final Element elem = this.mongoOaistoreCacheByMdPrefix.get(targetMetadataPrefix);
98

    
99
		if (elem != null) {
100
			return (MongoPublisherStore) elem.getObjectValue();
101
		} else {
102
			final MDFInfo info = this.configuration.getMetadataFormatInfo(targetMetadataPrefix);
103
			final MongoPublisherStore store =
104
					this.getStore(info.getSourceFormatName(), info.getSourceFormatInterpretation(), info.getSourceFormatLayout(), dbName);
105
			this.mongoOaistoreCacheByMdPrefix.put(new Element(targetMetadataPrefix, store));
106
			return store;
107
		}
108
	}
109

    
110
	@Override
111
	public MongoPublisherStore createStore(final String mdfName, final String mdfInterpretation, final String mdfLayout, final String dbName)
112
			throws OaiPublisherException {
113
		final MongoDatabase db = getDB(dbName);
114
		final DBObject store = createMetadataEntry(mdfName, mdfInterpretation, mdfLayout);
115
		final MongoCollection<DBObject> metadata = db.getCollection(this.metadataCollection, DBObject.class);
116
		metadata.insertOne(store);
117
		final MongoPublisherStore theStore = this.createFromDBObject(store, db);
118
		return theStore;
119

    
120
	}
121

    
122
	@Override
123
	public boolean deleteStore(final String storeId, final String dbName) {
124

    
125
		final MongoDatabase db = getDB(dbName);
126
		final MongoCollection<DBObject> metadata = db.getCollection(this.metadataCollection, DBObject.class);
127
		final DBObject storeDeleted = metadata.findOneAndDelete(Filters.eq("id", storeId));
128
		if (storeDeleted == null) {
129
			return false;
130
		} else {
131
			db.getCollection(storeId).drop();
132
			// TODO: should drop entries related to mdPrefix served by the store we are deleting, not all of them.
133
			this.mongoSetCollection.dropOAISets(dbName);
134
			log.debug("Deleted oaistore " + storeId + ", db: " + dbName);
135
			return true;
136
		}
137
	}
138

    
139
	@Override
140
	public boolean deleteFromStore(final String storeId, final String dbName, final String set) {
141
		final MongoDatabase db = getDB(dbName);
142
		final MongoCollection<DBObject> metadata = db.getCollection(this.metadataCollection, DBObject.class);
143
		final DBObject storeInfo = metadata.find(Filters.eq("id", storeId)).first();
144
		if (storeInfo == null) {
145
			return false;
146
		} else {
147
			db.getCollection(storeId).deleteOne(Filters.eq(OAIConfigurationReader.SET_FIELD, set));
148
			this.mongoSetCollection.dropSet(dbName, set);
149
			log.debug("Deleted set " + set + " from oaistore " + storeId + ", db: " + dbName);
150
			return true;
151
		}
152
	}
153

    
154
	@Override
155
	public boolean deleteFromStore(final String mdfName, final String mdfInterpretation, final String mdfLayout, final String dbName, final String set) {
156
		return this.deleteFromStore(this.generateStoreId(mdfName, mdfInterpretation, mdfLayout), dbName, set);
157
	}
158

    
159
	@Override
160
	public boolean deleteStore(final String mdfName, final String mdfInterpretation, final String mdfLayout, final String dbName) {
161
		return this.deleteStore(this.generateStoreId(mdfName, mdfInterpretation, mdfLayout), dbName);
162
	}
163

    
164
	public void ensureIndex(final MongoPublisherStore store) {
165
		if (store == null) { throw new OaiPublisherRuntimeException("Can't ensure index on null store"); }
166
		final Thread t = new Thread() {
167

    
168
			@Override
169
			public void run() {
170
				store.ensureIndices();
171
			}
172
		};
173
		t.start();
174
	}
175

    
176
	public void ensureIndex(final String dbName) {
177
		final List<MongoPublisherStore> stores = this.listPublisherStores(dbName);
178
		for (final MongoPublisherStore s : stores) {
179
			s.ensureIndices();
180
		}
181

    
182
	}
183

    
184
	private MongoPublisherStore createFromDBObject(final DBObject storeInfo, final MongoDatabase db) {
185
		if (storeInfo == null) { return null; }
186
		final String storeId = (String) storeInfo.get("id");
187
		final String mdFormat = (String) storeInfo.get("metadataFormat");
188
		final String mdInterpreation = (String) storeInfo.get("interpretation");
189
		final String mdLayout = (String) storeInfo.get("layout");
190
		final String k = db.getName() + "-" + storeId;
191

    
192
		final Element elem = this.mongoOaistoreCache.get(k);
193
		if (elem != null) {
194
			log.debug("Store retreived from cache and alwaysNewRecord is" + this.alwaysNewRecord);
195
			final MongoPublisherStore store = (MongoPublisherStore) elem.getObjectValue();
196
			store.setAlwaysNewRecord(this.alwaysNewRecord);
197
			return store;
198
		} else {
199
			log.debug("Store retreived, cache miss,  alwaysNewRecord is" + this.alwaysNewRecord);
200
			log.fatal("Not using cache to create oaistore from dbObject: " + k);
201
			final MongoPublisherStore store = new MongoPublisherStore(storeId, mdFormat, mdInterpreation, mdLayout, db.getCollection(storeId, DBObject.class),
202
					this.configuration.getFields(mdFormat, mdInterpreation, mdLayout), this.queryParser, this.recordInfoGenerator,
203
					this.configuration.getIdScheme(),
204
					this.configuration.getIdNamespace(), this.metadataExtractor, this.recordChangeDetector, this.alwaysNewRecord, db);
205
			store.setMongoSetCollection(this.mongoSetCollection);
206
			this.mongoOaistoreCache.put(new Element(k, store));
207
			return store;
208
		}
209
	}
210

    
211
	private DBObject createMetadataEntry(final String mdfName, final String mdfInterpretation, final String mdfLayout) {
212
		final DBObject info = BasicDBObjectBuilder.start("id", generateStoreId(mdfName, mdfInterpretation, mdfLayout)).append("metadataFormat", mdfName)
213
				.append("interpretation", mdfInterpretation).append("layout", mdfLayout).get();
214
		return info;
215

    
216
	}
217

    
218
	private String generateStoreId(final String mdfName, final String mdfInterpretation, final String mdfLayout) {
219
		return mdfName + "-" + mdfLayout + "-" + mdfInterpretation;
220
	}
221

    
222
	public String getMetadataCollection() {
223
		return this.metadataCollection;
224
	}
225

    
226
	@Required
227
	public void setMetadataCollection(final String metadataCollection) {
228
		this.metadataCollection = metadataCollection;
229
	}
230

    
231
	public MongoQueryParser getQueryParser() {
232
		return this.queryParser;
233
	}
234

    
235
	public void setQueryParser(final MongoQueryParser queryParser) {
236
		this.queryParser = queryParser;
237
	}
238

    
239
	public OAIConfigurationReader getConfiguration() {
240
		return this.configuration;
241
	}
242

    
243
	public void setConfiguration(final OAIConfigurationReader configuration) {
244
		this.configuration = configuration;
245
	}
246

    
247
	public RecordInfoGenerator getRecordInfoGenerator() {
248
		return this.recordInfoGenerator;
249
	}
250

    
251
	public void setRecordInfoGenerator(final RecordInfoGenerator recordInfoGenerator) {
252
		this.recordInfoGenerator = recordInfoGenerator;
253
	}
254

    
255
	public MetadataExtractor getMetadataExtractor() {
256
		return this.metadataExtractor;
257
	}
258

    
259
	public void setMetadataExtractor(final MetadataExtractor metadataExtractor) {
260
		this.metadataExtractor = metadataExtractor;
261
	}
262

    
263
	public RecordChangeDetector getRecordChangeDetector() {
264
		return this.recordChangeDetector;
265
	}
266

    
267
	public void setRecordChangeDetector(final RecordChangeDetector recordChangeDetector) {
268
		this.recordChangeDetector = recordChangeDetector;
269
	}
270

    
271
	public MongoSetCollection getMongoSetCollection() {
272
		return this.mongoSetCollection;
273
	}
274

    
275
	public void setMongoSetCollection(final MongoSetCollection mongoSetCollection) {
276
		this.mongoSetCollection = mongoSetCollection;
277
	}
278

    
279
	public boolean isAlwaysNewRecord() {
280
		return this.alwaysNewRecord;
281
	}
282

    
283
	public void setAlwaysNewRecord(final boolean alwaysNewRecord) {
284
		this.alwaysNewRecord = alwaysNewRecord;
285
	}
286

    
287
	public Cache getMongoOaistoreCache() {
288
		return this.mongoOaistoreCache;
289
	}
290

    
291
	@Required
292
	public void setMongoOaistoreCache(final Cache mongoOaistoreCache) {
293
		this.mongoOaistoreCache = mongoOaistoreCache;
294
	}
295

    
296
	public Cache getMongoOaistoreCacheByMdPrefix() {
297
		return this.mongoOaistoreCacheByMdPrefix;
298
	}
299

    
300
	@Required
301
	public void setMongoOaistoreCacheByMdPrefix(final Cache mongoOaistoreCacheByMdPrefix) {
302
		this.mongoOaistoreCacheByMdPrefix = mongoOaistoreCacheByMdPrefix;
303
	}
304

    
305
}
(4-4/6)