/*
 * Copyright 2016-2017 EMBL - European Bioinformatics Institute
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package uk.ac.ebi.eva.pipeline.io.readers;

import com.mongodb.BasicDBObject;
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DBObject;
import org.opencb.biodata.models.variant.Variant;
import org.opencb.opencga.storage.mongodb.variant.DBObjectToVariantConverter;
import org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.util.ClassUtils;

import uk.ac.ebi.eva.commons.models.converters.data.VariantSourceEntryToDBObjectConverter;
import uk.ac.ebi.eva.commons.models.converters.data.VariantToDBObjectConverter;
import uk.ac.ebi.eva.pipeline.model.VariantWrapper;

import javax.annotation.PostConstruct;

/**
 * Mongo variant reader using an ItemReader cursor based. This is speeding up
 * the reading of the variant in big collections. The
 * {@link org.springframework.batch.item.data.MongoItemReader} is using
 * pagination and it is slow with large collections
 */
public class NonAnnotatedVariantsMongoReader extends AbstractItemCountingItemStreamItemReader<VariantWrapper>
        implements InitializingBean {

    private MongoDbCursorItemReader delegateReader;

    private DBObjectToVariantConverter converter;

    private static final String STUDY_KEY = VariantToDBObjectConverter.FILES_FIELD + "."
            + VariantSourceEntryToDBObjectConverter.STUDYID_FIELD;

    /**
     * @param studyId Can be the empty string, meaning to bring all non-annotated variants in the collection. If the
     * studyId string is not empty, bring only non-annotated variants from that study. This parameter should not be null
     * in any case.
     */
    public NonAnnotatedVariantsMongoReader(MongoOperations template, String collectionsVariantsName, String studyId) {
        setName(ClassUtils.getShortName(NonAnnotatedVariantsMongoReader.class));
        if (studyId == null) {
            throw new IllegalArgumentException("NonAnnotatedVariantsMongoReader needs a non-null studyId " +
                    "(it can take a studyId or an empty string for reading every study)");
        }

        delegateReader = new MongoDbCursorItemReader();
        delegateReader.setTemplate(template);
        delegateReader.setCollection(collectionsVariantsName);

        BasicDBObjectBuilder queryBuilder = BasicDBObjectBuilder.start();
        if (!studyId.isEmpty()) {
            queryBuilder.add(STUDY_KEY, studyId);
        }
        DBObject query = queryBuilder.add("annot.ct.so", new BasicDBObject("$exists", false)).get();
        delegateReader.setQuery(query);

        String[] fields = {"chr", "start", "end", "ref", "alt"};
        delegateReader.setFields(fields);

        converter = new DBObjectToVariantConverter();
    }

    @PostConstruct
    @Override
    public void afterPropertiesSet() throws Exception {
        delegateReader.afterPropertiesSet();
    }

    @Override
    protected VariantWrapper doRead() throws Exception {
        DBObject dbObject = delegateReader.doRead();
        if (dbObject != null) {
            Variant variant = converter.convertToDataModelType(dbObject);
            return new VariantWrapper(variant);
        } else {
            return null;
        }
    }

    @Override
    protected void doOpen() throws Exception {
        delegateReader.doOpen();
    }

    @Override
    protected void doClose() throws Exception {
        delegateReader.doClose();
    }
}

@@ -941,56 +941,326 @@
 tem.
-support.AbstractItemCountingItemStreamItemReader
+ExecutionContext;%0Aimport org.springframework.batch.item.ItemStreamException;%0Aimport org.springframework.batch.item.ItemStreamReader;%0Aimport org.springframework.batch.item.NonTransientResourceException;%0Aimport org.springframework.batch.item.ParseException;%0Aimport org.springframework.batch.item.UnexpectedInputException
 ;%0Aim
@@ -1381,52 +1381,8 @@
 ons;
-%0Aimport org.springframework.util.ClassUtils;
 %0A%0Aim
@@ -1956,36 +1956,19 @@
 der 
-extend
+implement
 s 
-AbstractItemCounting
 Item
@@ -1973,20 +1973,16 @@
 emStream
-Item
 Reader%3CV
@@ -1999,27 +1999,9 @@
 per%3E
-%0A        implements
+,
  Ini
@@ -2675,89 +2675,8 @@
 ) %7B%0A
-        setName(ClassUtils.getShortName(NonAnnotatedVariantsMongoReader.class));%0A
     
@@ -3718,24 +3718,174 @@
 de%0A    p
-rotected
+ublic void open(ExecutionContext executionContext) throws ItemStreamException %7B%0A        delegateReader.open(executionContext);%0A    %7D%0A%0A    @Override%0A    public
  Variant
@@ -3892,24 +3892,34 @@
 Wrapper 
-doR
+r
 ead()
+%0A           
  throws 
@@ -3919,32 +3919,105 @@
 throws Exception
+, UnexpectedInputException, ParseException, NonTransientResourceException
  %7B%0A        DBObj
@@ -4050,11 +4050,9 @@
 der.
-doR
+r
 ead(
@@ -4290,38 +4290,78 @@
    p
-rotected void doOpen() throws 
+ublic void update(ExecutionContext executionContext) throws ItemStream
 Exce
@@ -4395,15 +4395,31 @@
 der.
-doOpen(
+update(executionContext
 );%0A 
@@ -4447,25 +4447,20 @@
    p
-rotected
+ublic
  void 
-doC
+c
 lose
@@ -4461,32 +4461,42 @@
  close() throws 
+ItemStream
 Exception %7B%0A    
@@ -4518,11 +4518,9 @@
 der.
-doC
+c
 lose

change inheritance design