package org.intermine.bio.dataconversion;

/*
 * Copyright (C) 2002-2010 FlyMine
 *
 * This code may be freely distributed and modified under the
 * terms of the GNU Lesser General Public Licence.  This should
 * be distributed with the code.  See the LICENSE file for more
 * information or http://www.gnu.org/copyleft/lesser.html.
 *
 */

import java.io.Reader;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.apache.log4j.Logger;
import org.intermine.dataconversion.ItemWriter;
import org.intermine.metadata.Model;
import org.intermine.util.FormattedTextParser;
import org.intermine.xml.full.Item;


/**
 *
 * @author Julie Sullivan
 */
public class MgiIdentifiersConverter extends BioFileConverter
{
    protected static final Logger LOG = Logger.getLogger(MgiIdentifiersConverter.class);
    private static final String DATASET_TITLE = "MGI identifiers";
    private static final String DATA_SOURCE_NAME = "MGI";
    private static final String NULL_STRING = "null";

    /**
     * Constructor
     * @param writer the ItemWriter used to handle the resultant items
     * @param model the Model
     */
    public MgiIdentifiersConverter(ItemWriter writer, Model model) {
        super(writer, model, DATA_SOURCE_NAME, DATASET_TITLE);
    }

    /**
     *
     *
     * {@inheritDoc}
     */
    public void process(Reader reader) throws Exception {
        Iterator lineIter = FormattedTextParser.parseTabDelimitedReader(reader);

        Item organism = createItem("Organism");
        organism.setAttribute("taxonId", "10090");
        store(organism);

        Set<String> identifiers = new HashSet<String>();
        Set<String> seenEnsembl = new HashSet<String>();
        Set<String> seenEntrez = new HashSet<String>();

        Set<String> duplicateEntrez = new HashSet<String>();
        Set<String> duplicateEnsembl = new HashSet<String>();

        Set<GeneRecord> records = new HashSet<GeneRecord>();

        // Read all lines into gene records
        while (lineIter.hasNext()) {
            String[] line = (String[]) lineIter.next();

            if (line.length < 16) {
                continue;
            }

            String type = line[1];
            if (!"Gene".equals(type)) {
                continue;
            }

            String identifier = line[0];    // MGI
            String symbol = line[2];
            String name = line[3];
            String entrez = line[10];
            String ensembl = line[15];

            if (!identifier.equals(NULL_STRING) && identifiers.contains(identifier)) {
                throw new RuntimeException("duplicate MGI identifier");
            }

            if (!symbol.equals(NULL_STRING) && identifiers.contains(symbol)) {
                throw new RuntimeException("duplicate symbol " + symbol + " for gene "
                        + identifier);
            } else {
                identifiers.add(identifier);
                identifiers.add(symbol);

                if (!entrez.equals(NULL_STRING)) {
                    if (seenEntrez.contains(entrez)) {
                        duplicateEntrez.add(entrez);
                    }
                    seenEntrez.add(entrez);
                }

                if (!ensembl.equals(NULL_STRING)) {
                    if (seenEnsembl.contains(ensembl)) {
                        duplicateEnsembl.add(ensembl);
                    }
                    seenEnsembl.add(ensembl);
                }
                records.add(new GeneRecord(identifier, symbol, name, entrez, ensembl));
            }
        }
        if (!duplicateEnsembl.isEmpty()) {
            LOG.warn("Found " + duplicateEnsembl.size() + " duplicate ensembl ids, not using "
                    + " duplicates for primaryIdentifier: " + duplicateEnsembl);
        }

        if (!duplicateEntrez.isEmpty()) {
            LOG.warn("Found " + duplicateEntrez.size() + " duplicate entrez ids, not using "
                    + " duplicates for ncbiGeneNumber: " + duplicateEntrez);
        }

        // store genes and synonyms, avoid setting duplicate ensembl and entrez ids
        for (GeneRecord record : records) {
            Set<Item> synonyms = new HashSet<Item>();
            Item gene = createItem("Gene");
            gene.setReference("organism", organism);
            if (!NULL_STRING.equals(record.identifier)) {
                gene.setAttribute("secondaryIdentifier", record.identifier);
            }
            if (!NULL_STRING.equals(record.symbol)) {
                gene.setAttribute("symbol", record.symbol);
            }
            if (!NULL_STRING.equals(record.name)) {
                gene.setAttribute("name", record.name);
            }

            if (!NULL_STRING.equals(record.entrez)) {
                if (!duplicateEntrez.contains(record.entrez)) {
                    gene.setAttribute("ncbiGeneNumber", record.entrez);
                } else {
                    Item syn = createSynonym(gene, record.entrez, false);
                    if (syn != null) {
                        synonyms.add(syn);
                    } else {
                        throw new RuntimeException("duplicate id " + record.entrez
                                + " for gene " + record.identifier);
                    }
                }
            }
            if (!NULL_STRING.equals(record.ensembl)) {
                if (!duplicateEnsembl.contains(record.ensembl)) {
                    gene.setAttribute("primaryIdentifier", record.ensembl);
                } else {
                    Item syn = createSynonym(gene, record.ensembl, false);
                    if (syn != null) {
                        synonyms.add(syn);
                    } else {
                        throw new RuntimeException("duplicate id " + record.ensembl
                                + " for gene " + record.identifier);
                    }
                }
            }
            store(gene);
            for (Item item : synonyms) {
                store(item);
            }
        }
    }

    private class GeneRecord
    {
        protected String identifier, symbol, name, entrez, ensembl;

        public GeneRecord(String identifier, String symbol, String name, String entrez,
                String ensembl) {
            this.identifier = identifier;
            this.symbol = symbol;
            this.name = name;
            this.entrez = entrez;
            this.ensembl = ensembl;

        }
    }
}

@@ -433,16 +433,60 @@
 l.Set;%0A%0A
+import org.apache.commons.lang.StringUtils;%0A
 import o
@@ -2529,16 +2529,160 @@
 e%5B15%5D;%0A%0A
+            if (StringUtils.isEmpty(identifier)) %7B%0A                throw new RuntimeException(%22null MGI identifier: %22 + symbol);%0A            %7D%0A%0A
         

throw an exception if MGI identifier is null