/**
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 *
 * Copyright (C)
 * <a href="http://www.inab.org">Spanish National Institute of Bioinformatics (INB)</a>
 * <a href="http://www.bsc.es">Barcelona Supercomputing Center (BSC)</a>
 * <a href="http://inb.bsc.es">Computational Node 6</a>
 */

package org.inb.biomoby.shared.message;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlElementRefs;
import javax.xml.bind.annotation.XmlRootElement;

/**
 * @author Dmitry Repchevsky
 */

@XmlRootElement
public class MobyData implements Serializable
{
    private String queryID;
    private List<MobyDataElement> data;
    private ArrayList<MobyParameter> parameters;
    
    public MobyData() {}

    public MobyData(String queryID)
    {
        this.queryID = queryID;
    }

    public MobyData(MobySimple mobySimple, String queryID)
    {
        this.queryID = queryID;
        addMobyDataElement(mobySimple);
    }

    public MobyData(MobyCollection mobyColection, String queryID)
    {
        this.queryID = queryID;
        addMobyDataElement(mobyColection);
        
    }

    @XmlAttribute(name="queryID", namespace="")
    public String getQueryID()
    {
        return queryID;
    }

    public void setQueryID(String queryID)
    {
        this.queryID = queryID;
    }

    // hack around Moby specification bug where it allows attributes with or without namespaces
    // this leads to two attributes in xml schema... these accessors are for JAXB only because
    // they are unaccessible from a client

    @XmlAttribute(name="queryID", namespace="http://www.biomoby.org/moby")
    void setFixedQueryID(String queryID)
    {
        this.queryID = queryID;
    }
    
    String getFixedQueryID()
    {
        return null; // always return null (we do not want to put it twice)
    }

    /**
     *
     * 
     * @return could be either List<MobySimple> or List<MobyCollection>
     */
    @XmlElementRefs({
      @XmlElementRef(type=MobySimple.class),
      @XmlElementRef(type=MobyCollection.class)})
    public List<MobyDataElement> getMobyDataElements()
    {
        if (data == null)
        {
            data = new ArrayList<MobyDataElement>();
        }
        
        return data;
    }
    
    public void addMobyDataElement(MobyDataElement element)
    {
        getMobyDataElements().add(element);
    }
        
    @XmlElement(name="Parameter")
    public List<MobyParameter> getParameters()
    {
        if (parameters == null)
        {
            parameters = new ArrayList<MobyParameter>();
        }
        
        return parameters;
    }
    
    public Map<String, String> getParameterMap()
    {
        if (parameters == null || parameters.isEmpty())
        {
            return Collections.emptyMap();
        }
        
        Map map = new TreeMap<String, String>();
        
        for(MobyParameter param : parameters)
        {
            String articleName = param.getArticleName();
            
            if (articleName != null && articleName.length() > 0)
            {
                map.put(articleName, param.getValue());
            }
        }
        
        return map;
    }
    
    public void addParameter(MobyParameter parameter)
    {
        getParameters().add(parameter);
    }

    public <T extends MobyDataElement> T getData(String articleName)
    {
        for (MobyDataElement element : data)
        {
            if (articleName.equals(element.getArticleName()))
            {
                try
                {
                    return (T)element;
                }
                catch(ClassCastException ex)
                {
                    return null;
                }
            }
        }
        
        return null;
    }
}
