package org.gcube.application.geoportal.service.engine.mongo; import com.fasterxml.jackson.core.JsonProcessingException; import com.mongodb.client.FindIterable; import com.mongodb.client.model.FindOneAndReplaceOptions; import com.mongodb.client.model.ReturnDocument; import lombok.extern.slf4j.Slf4j; import org.bson.Document; import org.bson.types.ObjectId; import org.gcube.application.cms.serialization.Serialization; import org.gcube.application.geoportal.common.model.useCaseDescriptor.UseCaseDescriptor; import org.gcube.application.geoportal.common.model.rest.ConfigurationException; import org.gcube.application.geoportal.common.model.rest.QueryRequest; import org.gcube.application.geoportal.common.utils.ContextUtils; import org.gcube.application.geoportal.service.model.internal.faults.RegistrationException; import javax.ws.rs.WebApplicationException; import java.util.NoSuchElementException; import java.util.concurrent.LinkedBlockingQueue; import java.util.function.Consumer; @Slf4j public class UCDMongoManager extends MongoManager implements UCDManagerI{ public UCDMongoManager() throws ConfigurationException { init("UCD_"+ContextUtils.getCurrentScope().replaceAll("/","_")); } public long deleteAll(){ return getCollection().deleteMany(new Document()).getDeletedCount(); } @Override protected String mongoIDFieldName() { return UseCaseDescriptor.MONGO_ID; } public UseCaseDescriptor insert(UseCaseDescriptor desc) throws RegistrationException { try { if (desc.getMongoId() != null) throw new RegistrationException("UCD has already a mongo ID"); //TODO validate ObjectId id = insertDoc(Serialization.asDocument(desc)); desc.setMongoId(id); return Serialization.convert(getDocById(id), UseCaseDescriptor.class); }catch(JsonProcessingException e){ log.error("Unexpected serialization exception ",e); throw new WebApplicationException("Unexpected exception ",e); } } @Override public UseCaseDescriptor put(UseCaseDescriptor desc) throws RegistrationException, ConfigurationException { log.debug("PUT UCD ID {} MONGO ID {}",desc.getId(),desc.getMongoId()); Document filter = new Document(UseCaseDescriptor.ID,desc.getId()); if(desc.getMongoId()!=null) // MONGO ID SHOULD MATCH IF PROVIDED filter.put(UseCaseDescriptor.MONGO_ID,desc.getMongoId()); try { UseCaseDescriptor toReturn = Serialization.convert(getCollection().findOneAndReplace( filter, Serialization.asDocument(desc), new FindOneAndReplaceOptions().returnDocument(ReturnDocument.AFTER)), UseCaseDescriptor.class); if(toReturn == null) { if (desc.getMongoId() != null) throw new RegistrationException("Illegal attempt to write to " + desc.getId() + " with unmatching mongo ID "); else { log.debug("Unable to update UCD {}. Inserting it..",desc.getId()); toReturn = insert(desc); } } log.info("Updated UCD in DB cache. ID {}, MONGO ID {}",toReturn.getId(),toReturn.getMongoId()); log.trace("Updated UCD is {} ", toReturn); return toReturn; }catch (RegistrationException e){ throw e; }catch(Throwable e){ log.error("Unable to update ",e); throw new RegistrationException("Invalid UCD provided "+e.getMessage()); } } @Override public Iterable query(QueryRequest queryRequest) { log.info("Searching UCD for {} ",queryRequest); LinkedBlockingQueue queue=new LinkedBlockingQueue(); FindIterable it=queryDoc(queryRequest); it.forEach( (Consumer) d ->{try{ queue.put(Serialization.convert(d,UseCaseDescriptor.class)); }catch(Throwable t){log.warn("Unable to translate "+d,t);}}); log.info("Returned {} elements ",queue.size()); return queue; } @Override public void deleteById(String id, boolean force) throws ConfigurationException { deleteDoc(getById(id).getMongoId()); } @Override public UseCaseDescriptor getById(String id) throws ConfigurationException { log.info("Getting UC by ID {} ",id); QueryRequest request=new QueryRequest(); request.setFilter(new Document(UseCaseDescriptor.ID,id)); try { return this.query(request).iterator().next(); }catch (NoSuchElementException e){return null;} } }