Project

General

Profile

1
package eu.dnetlib.oai.mongo;
2

    
3
import java.util.List;
4
import java.util.stream.Collectors;
5
import javax.annotation.Resource;
6

    
7
import com.mongodb.BasicDBObjectBuilder;
8
import com.mongodb.DBObject;
9
import com.mongodb.MongoClient;
10
import com.mongodb.client.FindIterable;
11
import com.mongodb.client.MongoCollection;
12
import com.mongodb.client.MongoDatabase;
13
import com.mongodb.client.model.Filters;
14
import eu.dnetlib.cql.CqlTranslator;
15
import eu.dnetlib.enabling.tools.DnetStreamSupport;
16
import eu.dnetlib.oai.PublisherStoreDAO;
17
import eu.dnetlib.oai.RecordChangeDetector;
18
import eu.dnetlib.oai.conf.OAIConfigurationReader;
19
import eu.dnetlib.oai.sets.MongoSetCollection;
20
import eu.dnetlib.rmi.provision.MDFInfo;
21
import eu.dnetlib.rmi.provision.OaiPublisherException;
22
import eu.dnetlib.rmi.provision.OaiPublisherRuntimeException;
23
import net.sf.ehcache.Cache;
24
import net.sf.ehcache.Element;
25
import org.apache.commons.logging.Log;
26
import org.apache.commons.logging.LogFactory;
27
import org.springframework.beans.factory.annotation.Autowired;
28
import org.springframework.beans.factory.annotation.Required;
29

    
30
public class MongoPublisherStoreDAO implements PublisherStoreDAO<MongoPublisherStore, DNetOAIMongoCursor> {
31

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

    
34
	@Autowired
35
	private MongoClient publisherMongoClient;
36

    
37
	/**
38
	 * Name of the collection with information about the OAI stores.
39
	 **/
40
	private String metadataCollection;
41

    
42
	@Autowired
43
	private RecordInfoGenerator recordInfoGenerator;
44
	@Autowired
45
	private MetadataExtractor metadataExtractor;
46
	@Autowired
47
	private CqlTranslator cqlTranslator;
48
	@Resource(name = "oaiConfigurationExistReader")
49
	private OAIConfigurationReader configuration;
50
	@Autowired
51
	private RecordChangeDetector recordChangeDetector;
52
	@Autowired
53
	private MongoSetCollection mongoSetCollection;
54

    
55
	/**
56
	 * Cache for oaistores. Keys are dbName-storeId, values are objects of type MongoPublisherStore.
57
	 */
58
	private Cache mongoOaistoreCache;
59

    
60
	/**
61
	 * Cache for oaistores. Keys is OAI metadata prefixes, values are objects of type MongoPublisherStore.
62
	 */
63
	private Cache mongoOaistoreCacheByMdPrefix;
64

    
65
	private boolean alwaysNewRecord;
66

    
67
	protected MongoDatabase getDB(final String dbName) {
68
		return this.publisherMongoClient.getDatabase(dbName);
69
	}
70

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

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

    
86
	@Override
87
	public MongoPublisherStore getStore(final String mdfName, final String mdfInterpretation, final String mdfLayout, final String dbName) {
88
		return this.getStore(this.generateStoreId(mdfName, mdfInterpretation, mdfLayout), dbName);
89
	}
90

    
91
	@Override
92
	public MongoPublisherStore getStoreFor(final String targetMetadataPrefix, final String dbName) {
93

    
94
		final Element elem = this.mongoOaistoreCacheByMdPrefix.get(targetMetadataPrefix);
95

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

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

    
117
	}
118

    
119
	@Override
120
	public boolean deleteStore(final String storeId, final String dbName) {
121

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

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

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

    
156
	@Override
157
	public boolean deleteStore(final String mdfName, final String mdfInterpretation, final String mdfLayout, final String dbName) {
158
		return this.deleteStore(this.generateStoreId(mdfName, mdfInterpretation, mdfLayout), dbName);
159
	}
160

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

    
165
			@Override
166
			public void run() {
167
				store.ensureIndices();
168
			}
169
		};
170
		t.start();
171
	}
172

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

    
179
	}
180

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

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

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

    
213
	}
214

    
215
	private String generateStoreId(final String mdfName, final String mdfInterpretation, final String mdfLayout) {
216
		return mdfName + "-" + mdfLayout + "-" + mdfInterpretation;
217
	}
218

    
219
	public String getMetadataCollection() {
220
		return this.metadataCollection;
221
	}
222

    
223
	@Required
224
	public void setMetadataCollection(final String metadataCollection) {
225
		this.metadataCollection = metadataCollection;
226
	}
227

    
228
	public OAIConfigurationReader getConfiguration() {
229
		return this.configuration;
230
	}
231

    
232
	public void setConfiguration(final OAIConfigurationReader configuration) {
233
		this.configuration = configuration;
234
	}
235

    
236
	public RecordInfoGenerator getRecordInfoGenerator() {
237
		return this.recordInfoGenerator;
238
	}
239

    
240
	public void setRecordInfoGenerator(final RecordInfoGenerator recordInfoGenerator) {
241
		this.recordInfoGenerator = recordInfoGenerator;
242
	}
243

    
244
	public MetadataExtractor getMetadataExtractor() {
245
		return this.metadataExtractor;
246
	}
247

    
248
	public void setMetadataExtractor(final MetadataExtractor metadataExtractor) {
249
		this.metadataExtractor = metadataExtractor;
250
	}
251

    
252
	public RecordChangeDetector getRecordChangeDetector() {
253
		return this.recordChangeDetector;
254
	}
255

    
256
	public void setRecordChangeDetector(final RecordChangeDetector recordChangeDetector) {
257
		this.recordChangeDetector = recordChangeDetector;
258
	}
259

    
260
	public MongoSetCollection getMongoSetCollection() {
261
		return this.mongoSetCollection;
262
	}
263

    
264
	public void setMongoSetCollection(final MongoSetCollection mongoSetCollection) {
265
		this.mongoSetCollection = mongoSetCollection;
266
	}
267

    
268
	public boolean isAlwaysNewRecord() {
269
		return this.alwaysNewRecord;
270
	}
271

    
272
	public void setAlwaysNewRecord(final boolean alwaysNewRecord) {
273
		this.alwaysNewRecord = alwaysNewRecord;
274
	}
275

    
276
	public Cache getMongoOaistoreCache() {
277
		return this.mongoOaistoreCache;
278
	}
279

    
280
	@Required
281
	public void setMongoOaistoreCache(final Cache mongoOaistoreCache) {
282
		this.mongoOaistoreCache = mongoOaistoreCache;
283
	}
284

    
285
	public Cache getMongoOaistoreCacheByMdPrefix() {
286
		return this.mongoOaistoreCacheByMdPrefix;
287
	}
288

    
289
	@Required
290
	public void setMongoOaistoreCacheByMdPrefix(final Cache mongoOaistoreCacheByMdPrefix) {
291
		this.mongoOaistoreCacheByMdPrefix = mongoOaistoreCacheByMdPrefix;
292
	}
293

    
294
	public CqlTranslator getCqlTranslator() {
295
		return cqlTranslator;
296
	}
297

    
298
	public void setCqlTranslator(final CqlTranslator cqlTranslator) {
299
		this.cqlTranslator = cqlTranslator;
300
	}
301

    
302
}
(4-4/6)