<commit_before>package io.core9.plugin.database.mongodb.repository;

import io.core9.plugin.database.mongodb.MongoDatabase;
import io.core9.plugin.database.repository.Collection;
import io.core9.plugin.database.repository.CrudEntity;
import io.core9.plugin.database.repository.CrudRepository;
import io.core9.plugin.database.repository.DataUtils;
import io.core9.plugin.database.repository.NoCollectionNamePresentException;
import io.core9.plugin.database.repository.ObservableCrudRepository;
import io.core9.plugin.database.repository.RepositoryFactory;
import io.core9.plugin.server.VirtualHost;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.xeoh.plugins.base.annotations.PluginImplementation;
import net.xeoh.plugins.base.annotations.injections.InjectPlugin;

import org.mongojack.DBQuery;
import org.mongojack.JacksonDBCollection;
import org.mongojack.internal.MongoJackModule;

import rx.Observable;
import rx.Observable.OnSubscribe;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.BasicDBObject;
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DBCollection;

@PluginImplementation
public class RepositoryFactoryImpl implements RepositoryFactory {
	
	@InjectPlugin
	private MongoDatabase mongo;

	@Override
	public <T extends CrudEntity> CrudRepository<T> getRepository(final Class<T> type) throws NoCollectionNamePresentException {
		
		final Collection classColl = type.getAnnotation(Collection.class);
		if(classColl == null) {
			throw new NoCollectionNamePresentException();
		}
		
		final ObjectMapper mapper = new ObjectMapper();
		MongoJackModule.configure(mapper);
		mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		
		return new CrudRepository<T>(){
			String collectionName = classColl.value();
			
			@Override
			public T create(VirtualHost vhost, T entity) {
				return create((String) vhost.getContext("database"), (String) vhost.getContext("prefix"), entity);
			}
			
			@Override
			public T create(String database, String prefix, T entity) {
				DBCollection collection = mongo.getCollection(database, prefix + collectionName);
				JacksonDBCollection<T, String> coll = JacksonDBCollection.wrap(collection, type, String.class, mapper);
				return coll.insert(entity).getSavedObject();
			}

			@Override
			public T read(VirtualHost vhost, String id) {
				return read((String) vhost.getContext("database"), (String) vhost.getContext("prefix"), id);
			}
			
			@Override
			public T read(String database, String prefix, String id) {
				DBCollection collection = mongo.getCollection(database, prefix + collectionName);
				JacksonDBCollection<T, String> coll = JacksonDBCollection.wrap(collection, type, String.class, mapper);
				return coll.findOneById(id);
			}

			@Override
			public T update(VirtualHost vhost, T entity) {
				return update((String) vhost.getContext("database"), (String) vhost.getContext("prefix"), entity);
			}
			
			@Override
			public T update(VirtualHost vhost, String id, T entity) {
				return update((String) vhost.getContext("database"), (String) vhost.getContext("prefix"), id, entity);
			}
			
			@Override
			public T update(String database, String prefix, T entity) {
				DBCollection collection = mongo.getCollection(database, prefix + collectionName);
				JacksonDBCollection<T, String> coll = JacksonDBCollection.wrap(collection, type, String.class, mapper);
				int n = coll.updateById(entity.getId(), entity).getN();
				if(n == 1) {
					return entity;
				}
				return null;
			}
			
			@Override
			public T update(String database, String prefix, String id, T entity) {
				DBCollection collection = mongo.getCollection(database, prefix + collectionName);
				JacksonDBCollection<T, String> coll = JacksonDBCollection.wrap(collection, type, String.class, mapper);
				int n = coll.updateById(id, entity).getN();
				if(n == 1) {
					return entity;
				}
				return null;
			}
			
			@Override
			public T updateFields(VirtualHost vhost, T entity) {
				return updateFields((String) vhost.getContext("database"), (String) vhost.getContext("prefix"), entity);
			}
			
			@Override
			public T updateFields(String database, String prefix, T entity) {
				DBCollection collection = mongo.getCollection(database, prefix + collectionName);
				JacksonDBCollection<T, String> coll = JacksonDBCollection.wrap(collection, type, String.class, mapper);
				int n = coll.update(new BasicDBObject("_id", entity.getId()), new BasicDBObject("$set", DataUtils.toMap(entity)), true, false).getN();
				if(n == 1) {
					return entity;
				}
				return null;
			}
			
			@Override
			public T upsert(VirtualHost vhost, T entity) {
				return upsert((String) vhost.getContext("database"), (String) vhost.getContext("prefix"), entity);
			}

			@Override
			public T upsert(String database, String prefix, T entity) {
				DBCollection collection = mongo.getCollection(database, prefix + collectionName);
				JacksonDBCollection<T, String> coll = JacksonDBCollection.wrap(collection, type, String.class, mapper);
				int n = coll.update(DBQuery.is("_id", entity.getId()), entity, true, false).getN();
				if(n == 1) {
					return entity;
				}

				return null;
			}

			@Override
			public void delete(VirtualHost vhost, T entity) {
				delete((String) vhost.getContext("database"), (String) vhost.getContext("prefix"), entity);
			}
			
			@Override
			public void delete(String database, String prefix, T entity) {
				DBCollection collection = mongo.getCollection(database, prefix + collectionName);
				JacksonDBCollection<T, String> coll = JacksonDBCollection.wrap(collection, type, String.class, mapper);
				coll.removeById(entity.getId());
			}
			
			@Override
			public void delete(VirtualHost vhost, String id) {
				delete((String) vhost.getContext("database"), (String) vhost.getContext("prefix"), id);
			}
			
			@Override
			public void delete(String database, String prefix, String id) {
				DBCollection collection = mongo.getCollection(database, prefix + collectionName);
				JacksonDBCollection<T, String> coll = JacksonDBCollection.wrap(collection, type, String.class, mapper);
				coll.removeById(id);
			}
			
			@Override
			public List<T> getAll(VirtualHost vhost) {
				return getAll((String) vhost.getContext("database"), (String) vhost.getContext("prefix"));
			}
			
			@Override
			public List<T> getAll(String database, String prefix) {
				return query(database, prefix, null);
			}

			@Override
			public List<T> query(VirtualHost vhost, Map<String, Object> query) {
				return query((String) vhost.getContext("database"), (String) vhost.getContext("prefix"), query);
			}
			
			@Override
			public List<T> query(String database, String prefix, Map<String, Object> query) {
				try {<commit_msg>Acknowlegde from replicas before write continues<commit_after>package io.core9.plugin.database.mongodb.repository;

import io.core9.plugin.database.mongodb.MongoDatabase;
import io.core9.plugin.database.repository.Collection;
import io.core9.plugin.database.repository.CrudEntity;
import io.core9.plugin.database.repository.CrudRepository;
import io.core9.plugin.database.repository.DataUtils;
import io.core9.plugin.database.repository.NoCollectionNamePresentException;
import io.core9.plugin.database.repository.ObservableCrudRepository;
import io.core9.plugin.database.repository.RepositoryFactory;
import io.core9.plugin.server.VirtualHost;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.xeoh.plugins.base.annotations.PluginImplementation;
import net.xeoh.plugins.base.annotations.injections.InjectPlugin;

import org.mongojack.DBQuery;
import org.mongojack.JacksonDBCollection;
import org.mongojack.internal.MongoJackModule;

import rx.Observable;
import rx.Observable.OnSubscribe;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.BasicDBObject;
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DBCollection;
import com.mongodb.WriteConcern;

@PluginImplementation
public class RepositoryFactoryImpl implements RepositoryFactory {
	
	@InjectPlugin
	private MongoDatabase mongo;

	@Override
	public <T extends CrudEntity> CrudRepository<T> getRepository(final Class<T> type) throws NoCollectionNamePresentException {
		
		final Collection classColl = type.getAnnotation(Collection.class);
		if(classColl == null) {
			throw new NoCollectionNamePresentException();
		}
		
		final ObjectMapper mapper = new ObjectMapper();
		MongoJackModule.configure(mapper);
		mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		
		return new CrudRepository<T>(){
			String collectionName = classColl.value();
			
			@Override
			public T create(VirtualHost vhost, T entity) {
				return create((String) vhost.getContext("database"), (String) vhost.getContext("prefix"), entity);
			}
			
			@Override
			public T create(String database, String prefix, T entity) {
				DBCollection collection = mongo.getCollection(database, prefix + collectionName);
				JacksonDBCollection<T, String> coll = JacksonDBCollection.wrap(collection, type, String.class, mapper);
				coll.setWriteConcern(WriteConcern.REPLICA_ACKNOWLEDGED);
				return coll.insert(entity).getSavedObject();
			}

			@Override
			public T read(VirtualHost vhost, String id) {
				return read((String) vhost.getContext("database"), (String) vhost.getContext("prefix"), id);
			}
			
			@Override
			public T read(String database, String prefix, String id) {
				DBCollection collection = mongo.getCollection(database, prefix + collectionName);
				JacksonDBCollection<T, String> coll = JacksonDBCollection.wrap(collection, type, String.class, mapper);
				return coll.findOneById(id);
			}

			@Override
			public T update(VirtualHost vhost, T entity) {
				return update((String) vhost.getContext("database"), (String) vhost.getContext("prefix"), entity);
			}
			
			@Override
			public T update(VirtualHost vhost, String id, T entity) {
				return update((String) vhost.getContext("database"), (String) vhost.getContext("prefix"), id, entity);
			}
			
			@Override
			public T update(String database, String prefix, T entity) {
				DBCollection collection = mongo.getCollection(database, prefix + collectionName);
				JacksonDBCollection<T, String> coll = JacksonDBCollection.wrap(collection, type, String.class, mapper);
				coll.setWriteConcern(WriteConcern.REPLICA_ACKNOWLEDGED);
				int n = coll.updateById(entity.getId(), entity).getN();
				if(n == 1) {
					return entity;
				}
				return null;
			}
			
			@Override
			public T update(String database, String prefix, String id, T entity) {
				DBCollection collection = mongo.getCollection(database, prefix + collectionName);
				JacksonDBCollection<T, String> coll = JacksonDBCollection.wrap(collection, type, String.class, mapper);
				coll.setWriteConcern(WriteConcern.REPLICA_ACKNOWLEDGED);
				int n = coll.updateById(id, entity).getN();
				if(n == 1) {
					return entity;
				}
				return null;
			}
			
			@Override
			public T updateFields(VirtualHost vhost, T entity) {
				return updateFields((String) vhost.getContext("database"), (String) vhost.getContext("prefix"), entity);
			}
			
			@Override
			public T updateFields(String database, String prefix, T entity) {
				DBCollection collection = mongo.getCollection(database, prefix + collectionName);
				JacksonDBCollection<T, String> coll = JacksonDBCollection.wrap(collection, type, String.class, mapper);
				coll.setWriteConcern(WriteConcern.REPLICA_ACKNOWLEDGED);
				int n = coll.update(new BasicDBObject("_id", entity.getId()), new BasicDBObject("$set", DataUtils.toMap(entity)), true, false).getN();
				if(n == 1) {
					return entity;
				}
				return null;
			}
			
			@Override
			public T upsert(VirtualHost vhost, T entity) {
				return upsert((String) vhost.getContext("database"), (String) vhost.getContext("prefix"), entity);
			}

			@Override
			public T upsert(String database, String prefix, T entity) {
				DBCollection collection = mongo.getCollection(database, prefix + collectionName);
				JacksonDBCollection<T, String> coll = JacksonDBCollection.wrap(collection, type, String.class, mapper);
				coll.setWriteConcern(WriteConcern.REPLICA_ACKNOWLEDGED);
				int n = coll.update(DBQuery.is("_id", entity.getId()), entity, true, false).getN();
				if(n == 1) {
					return entity;
				}

				return null;
			}

			@Override
			public void delete(VirtualHost vhost, T entity) {
				delete((String) vhost.getContext("database"), (String) vhost.getContext("prefix"), entity);
			}
			
			@Override
			public void delete(String database, String prefix, T entity) {
				DBCollection collection = mongo.getCollection(database, prefix + collectionName);
				JacksonDBCollection<T, String> coll = JacksonDBCollection.wrap(collection, type, String.class, mapper);
				coll.setWriteConcern(WriteConcern.REPLICA_ACKNOWLEDGED);
				coll.removeById(entity.getId());
			}
			
			@Override
			public void delete(VirtualHost vhost, String id) {
				delete((String) vhost.getContext("database"), (String) vhost.getContext("prefix"), id);
			}
			
			@Override
			public void delete(String database, String prefix, String id) {
				DBCollection collection = mongo.getCollection(database, prefix + collectionName);
				JacksonDBCollection<T, String> coll = JacksonDBCollection.wrap(collection, type, String.class, mapper);
				coll.setWriteConcern(WriteConcern.REPLICA_ACKNOWLEDGED);
				coll.removeById(id);
			}
			
			@Override
			public List<T> getAll(VirtualHost vhost) {
				return getAll((String) vhost.getContext("database"), (String) vhost.getContext("prefix"));
			}
			
			@Override
			public List<T> getAll(String database, String prefix) {
				return query(database, prefix, null);
			}

			@Override
			public List<T> query(VirtualHost vhost, Map<String, Object> query) {
				return query((String) vhost.getContext("database"), (String) vhost.getContext("prefix"), query);
			}
			
			@Override
			public List<T> query(String database, String prefix, Map<String, Object> query) {
				try {
{'fraction_non_alphanumeric': 0.11329528640879306, 'fraction_numerical': 0.0019728034946804762, 'mean_word_length': 4.707277844792923, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7324837', 'n_tokens_mistral': 4850, 'n_tokens_neox': 4089, 'n_words': 954}