package restx.jongo.specs.tests;
import com.google.common.base.Optional;
import com.google.common.base.Splitter;
import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.UnmodifiableIterator;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import org.bson.types.ObjectId;
import org.jongo.Jongo;
import org.jongo.Mapper;
import org.jongo.MongoCollection;
import org.jongo.ObjectIdUpdater;
import org.jongo.marshall.Marshaller;
import org.jongo.marshall.Unmarshaller;
import org.jongo.query.QueryFactory;
import restx.factory.*;
import restx.jongo.JongoCollection;
import restx.specs.mongo.GivenJongoCollection;
import restx.tests.GivenCleaner;
import restx.tests.GivenRunner;
import java.lang.reflect.Field;
import java.net.UnknownHostException;
import static com.google.common.base.Preconditions.checkNotNull;
import static restx.factory.Factory.LocalMachines.contextLocal;
import static restx.factory.Factory.LocalMachines.threadLocal;
import static restx.specs.WhenHttpRequest.CONTEXT_NAME;
import static restx.specs.mongo.GivenJongoCollection.DB_URI;
@Component
public class GivenJongoCollectionRunner implements GivenRunner<GivenJongoCollection> {
@Override
public Class<GivenJongoCollection> getGivenClass() {
return GivenJongoCollection.class;
}
public GivenCleaner run(final GivenJongoCollection given, final ImmutableMap<String, String> params) {
try {
MongoClientURI mongoClientURI = new MongoClientURI(
checkNotNull(params.get(DB_URI),
DB_URI + " param is required"));
Jongo jongo = new Jongo(new MongoClient(mongoClientURI).getDB(mongoClientURI.getDatabase()));
try {
Stopwatch stopwatch = Stopwatch.createStarted();
MongoCollection collection = jongo.getCollection(given.getCollection());
Iterable<String> items = Splitter.on("\n").trimResults().omitEmptyStrings().split(given.getData());
int count = 0;
for (String item : items) {
collection.insert(item);
count++;
}
System.out.printf("imported %s[%d] -- %s%n", given.getCollection(), count, stopwatch.stop().toString());
} finally {
jongo.getDatabase().getMongo().close();
}
final UnmodifiableIterator<String> it = given.getSequence().iterator();
final CollectionSequence iteratingSequence = new CollectionSequence() {
@Override
public Optional<String> next() {
return it.hasNext() ? Optional.of(it.next()) : Optional.<String>absent();
}
};
final SingleNameFactoryMachine<ComponentCustomizerEngine> customizerMachine =
new SingleNameFactoryMachine<>(0, new StdMachineEngine<ComponentCustomizerEngine>(
Name.of(ComponentCustomizerEngine.class, "JongoCollectionSequenceSupplierOf"
+ given.getCollection()),
BoundlessComponentBox.FACTORY) {
@Override
public BillOfMaterials getBillOfMaterial() {
return BillOfMaterials.of();
}
@Override
protected ComponentCustomizerEngine doNewComponent(final SatisfiedBOM satisfiedBOM) {
return new SingleComponentNameCustomizerEngine<JongoCollection>(
0, Name.of(JongoCollection.class, given.getCollection())) {
@Override
public NamedComponent<JongoCollection> customize(NamedComponent<JongoCollection> namedComponent) {
if (namedComponent.getName().getName().equals(given.getCollection())) {
return new NamedComponent<>(namedComponent.getName(),
new SequencedJongoCollection(namedComponent.getComponent(),iteratingSequence));
} else {
return namedComponent;
}
}
};
}
});
final Factory.LocalMachines localMachines = threadLocal();
localMachines.addMachine(customizerMachine);
return new GivenCleaner() {
@Override
public void cleanUp() {
try {
localMachines.removeMachine(customizerMachine);
MongoClientURI mongoClientURI = new MongoClientURI(
checkNotNull(params.get(DB_URI),
DB_URI + " param is required"));
Jongo jongo = new Jongo(new MongoClient(mongoClientURI).getDB(mongoClientURI.getDatabase()));
Stopwatch stopwatch = Stopwatch.createStarted();
jongo.getCollection(given.getCollection()).drop();
System.out.printf("dropped %s -- %s%n", given.getCollection(), stopwatch.stop().toString());
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
}
};
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
}
public static interface CollectionSequence {
Optional<String> next();
}
private class SequencedJongoCollection implements JongoCollection {
private final JongoCollection collection;
private final CollectionSequence iteratingSequence;
public SequencedJongoCollection(JongoCollection collection, CollectionSequence iteratingSequence) {
this.collection = collection;
this.iteratingSequence = iteratingSequence;
}
@Override
public String getName() {
return collection.getName();
}
@Override
public MongoCollection get() {
final Mapper mapper = getMapper();
MongoCollection mongoCollection = new MongoCollection(
collection.get().getDBCollection(),
new Mapper() {
@Override
public Marshaller getMarshaller() {
return mapper.getMarshaller();
}
@Override
public Unmarshaller getUnmarshaller() {
return mapper.getUnmarshaller();
}
@Override
public ObjectIdUpdater getObjectIdUpdater() {
return new ObjectIdUpdater() {
@Override
public boolean mustGenerateObjectId(Object pojo) {
return mapper.getObjectIdUpdater().mustGenerateObjectId(pojo);
}
@Override
public Object getId(Object pojo) {
return mapper.getObjectIdUpdater().getId(pojo);
}
@Override
public void setObjectId(Object target, ObjectId id) {
mapper.getObjectIdUpdater().setObjectId(target,
new ObjectId(iteratingSequence.next().or(id.toString())));
}
};
}
@Override
public QueryFactory getQueryFactory() {
return mapper.getQueryFactory();
}
});
return mongoCollection;
}
protected Mapper getMapper() {
try {
Field mapperField = MongoCollection.class.getDeclaredField("mapper");
mapperField.setAccessible(true);
return (Mapper) mapperField.get(collection.get());
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
}