/*
 * ALMA - Atacama Large Millimeter Array
 * (c) Associated Universities Inc., 2007
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 */

/**
 * @author  srankin
 * @version $Id: TMCDBCommonQueries.java,v 1.8 2011/11/23 16:22:49 mmora Exp $
 * @since
 */

package alma.TMCDB.Query;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

import oracle.jdbc.pool.OracleDataSource;

import org.hsqldb.jdbc.JDBCDataSource;

import alma.TMCDB.legacy.TimeValue;
import alma.TmcdbGuiErrType.wrappers.AcsJTmcdbConnectionFailureEx;
import alma.TmcdbGuiErrType.wrappers.AcsJTmcdbDuplicateKeyEx;
import alma.TmcdbGuiErrType.wrappers.AcsJTmcdbGuiErrTypeEx;
import alma.TmcdbGuiErrType.wrappers.AcsJTmcdbInitializationFailureEx;
import alma.TmcdbGuiErrType.wrappers.AcsJTmcdbNoSuchRowEx;
import alma.TmcdbGuiErrType.wrappers.AcsJTmcdbSqlEx;
import alma.acs.logging.ClientLogManager;
import alma.archive.database.helpers.DBConfiguration;
import alma.archive.exceptions.general.DatabaseException;
import alma.archive.tmcdb.DAO.queries.QueryDAO;
import alma.archive.tmcdb.DAO.queries.QueryDAOImpl;
import alma.archive.tmcdb.DAO.queries.TimeValuePager;
import alma.archive.tmcdb.persistence.ComponentNameHelper;

public class TMCDBCommonQueries {

    private enum InitializationState {
        NotReady, Ready, Terminated
    };

    private InitializationState tmcdbState;

    protected DBConfiguration config;
    protected String dbUser;
    protected String dbPassword;
    protected String dbUrl;

    protected Connection conn;
    protected OracleDataSource ds;
    protected JDBCDataSource hds;

    protected String configurationName;
    protected int configurationId;

    protected List<Integer> assemblyIdList;
    protected List<String> assemblyTypeNameList;
    protected List<String> assemblySNList;

    protected List<Integer> componentIdList;
    protected List<Integer> componentTypeIdList;
    protected List<String> componentNameList;

    protected Map<String,List<String>> antennasToCompMap;
    protected Map<String,List<String>> antennasToAssemblyNameMap;


    protected final Logger logger;

    // is set, when connection is established (and at the same time dbConfig.properties is read)
    protected boolean useOracle=false;

    public TMCDBCommonQueries() {
        configurationName = "NONE";
        configurationId = 0;
        logger = ClientLogManager.getAcsLogManager().getLoggerForApplication(
                         "TMCDB", false);
	config = getDbConfiguration();

	antennasToAssemblyNameMap = new HashMap<String,List<String>>();
	antennasToCompMap = new HashMap<String,List<String>>();

        tmcdbState = InitializationState.NotReady;
    }

    public DBConfiguration getDbConfiguration() {
        try {
            return DBConfiguration.instance(logger);
        } catch (DatabaseException e) {
            logger.warning("Exception when reading dbConfig.properties: "
                                + e.toString());
            AcsJTmcdbInitializationFailureEx ex = new AcsJTmcdbInitializationFailureEx("Exception when reading dbConfig.properties",e);
            ex.printStackTrace();
        }
	return null;
    }

    public void connectToDB() {
        try {
            connectDB();
        } catch (AcsJTmcdbGuiErrTypeEx ex) {
            logger.severe(
                "Failed to connect to DB in TMCDBCommonQueries.connectToDB() - not recoverable - please report a bug.");
            ex.printStackTrace();
        }
    }

    private Connection connectDB() throws AcsJTmcdbInitializationFailureEx, AcsJTmcdbSqlEx, AcsJTmcdbConnectionFailureEx {
        String backend = config.get("archive.db.mode");
        String user = config.get("archive.tmcdb.user");
        String pwd = config.get("archive.tmcdb.passwd");
        String location = config.get("archive.tmcdb.location");

        if (backend==null) {
            throw new AcsJTmcdbInitializationFailureEx("No backend specified for TMCDB! Check property alma.tmcdb.backend in dbConfig.properties.");
        }
        if (backend.equalsIgnoreCase("operational")) {
            useOracle=true;
            //String service = config.get("archive.tmcdb.service");
            //String connectionString = "jdbc:oracle:thin:@//" + location + "/"
            //    + service;
            String connectionString = config.get("archive.tmcdb.connection");
            return connectOracle(user, pwd == null ? "alma$dba" : pwd, connectionString);
        } else {
            // we use HsqlDB
            useOracle=false;
            return connectHsqldb(user, pwd == null ? "" : pwd, location);
        }
    }

    private Connection connectOracle(String dbUser, String dbPassword, String dbUrl) throws AcsJTmcdbSqlEx {
        this.dbUser = dbUser;
        this.dbPassword = dbPassword;
        this.dbUrl = dbUrl;
        try {
            logger.info("Connecting to TMCDB in Oracle as " + dbUser + " with: "
                        + dbUrl);
            ds = new OracleDataSource();
            ds.setURL(dbUrl);
            conn = ds.getConnection(dbUser, dbPassword);
            conn.setAutoCommit(false);  // We have to commit explicitly.
        } catch (SQLException err) {
            throw new AcsJTmcdbSqlEx (err);
        }
        return conn;
    }

    private Connection connectHsqldb(String dbUser, String dbPassword, String dbUrl) throws AcsJTmcdbSqlEx, AcsJTmcdbConnectionFailureEx {
        this.dbUser = dbUser;
        this.dbPassword = dbPassword;
        this.dbUrl = dbUrl;
        try {
            logger.info("Connecting to TMCDB in HsqlDB as " + dbUser + " with: "
                        + dbUrl);
            Class.forName("org.hsqldb.jdbcDriver");
            hds = new JDBCDataSource();
            hds.setDatabase(dbUrl);
            conn = hds.getConnection(dbUser, dbPassword);
            conn.setAutoCommit(false);  // We have to commit explicitly.
        } catch (SQLException err) {
            throw new AcsJTmcdbSqlEx (err);
        } catch (ClassNotFoundException err) {
            throw new AcsJTmcdbConnectionFailureEx ("Can't load jdbc driver for HSQLDB.", err);
        }
        return conn;
    }

    public String readConfigName() {
        String configName = config.get("archive.tmcdb.configuration");
	return configName;
    }

    public void initialize(String config) throws AcsJTmcdbGuiErrTypeEx {
        setConfigurationName(config);
	getComponents(configurationId);
        tmcdbState = InitializationState.Ready;
    }

    public void setConfigurationName(String configName) throws AcsJTmcdbInitializationFailureEx, AcsJTmcdbNoSuchRowEx, AcsJTmcdbDuplicateKeyEx, AcsJTmcdbSqlEx {
        try {
            PreparedStatement getConfigurationAlt = conn.prepareStatement("SELECT ConfigurationId FROM Configuration WHERE ConfigurationName = '" + configName + "'");
            ResultSet result = getConfigurationAlt.executeQuery();
            if (result.next() == false)
                throw new AcsJTmcdbNoSuchRowEx("TMCDB: Database error: There are no rows in Configuration tables with key " +
                                               configName);
            configurationId = result.getInt(1);
            configurationName = configName;
	    System.out.println("configuration ID = " + configurationId);
	    System.out.println("configuration Name = " + configurationName);
            if (result.next())
                throw new AcsJTmcdbDuplicateKeyEx("TMCDB: Database error: Duplicate keys for Configuration table (key " +
                                                  configName + ")");
	    result.close();
	    getConfigurationAlt.close();
        } catch (SQLException err) {
            throw new AcsJTmcdbSqlEx(err);
        }
    }

    public void terminate() {
        tmcdbState = InitializationState.Terminated;
    }

    protected void finalize() throws Throwable {
	terminate();
    }

    private void getComponents (int configId) throws AcsJTmcdbNoSuchRowEx, AcsJTmcdbSqlEx {
        try {
	    PreparedStatement getComponentsByConfigId = conn.prepareStatement("SELECT ComponentId, ComponentTypeId, ComponentName, Path FROM Component WHERE ConfigurationId = '" + configId + "'");
	    ResultSet result = getComponentsByConfigId.executeQuery();
            if (result.next() == false)
                throw new AcsJTmcdbNoSuchRowEx("TMCDB: Database error: There are no components for current configuration " + configurationName);

	    componentIdList = new ArrayList<Integer>();
	    componentTypeIdList = new ArrayList<Integer>();
	    componentNameList = new ArrayList<String>();
	    do {
		componentIdList.add(result.getInt(1));
		componentTypeIdList.add(result.getInt(2));
		componentNameList.add(result.getString(4) + "/" + result.getString(3));
	    } while (result.next() != false);
	    System.out.println("number of components for current config = " + componentIdList.size());
	    result.close();
	    getComponentsByConfigId.close();
        } catch (SQLException err) {
            throw new AcsJTmcdbSqlEx(err);
        }
    }

    private String getAssemblyTypeName (String componentName) {
	String assemblyTypeName = "";
	System.out.println("component name = " + componentName);
        String tokens[] = ComponentNameHelper.getPathAndName(componentName);
	try {
	    PreparedStatement statement = conn.prepareStatement("SELECT dc.AssemblyTypeName " +
								"FROM DefaultComponent dc, Component c " +
								"WHERE dc.ComponentTypeId = c.ComponentTypeId " +
								"AND c.ComponentName = '" + tokens[1] + "' " +
                                                                "AND c.Path = '" + tokens[0] + "' " +
								"AND c.ConfigurationId = " + configurationId);
	    ResultSet result = statement.executeQuery();
            if (result.next() == false)
                logger.warning("TMCDB: Database error: There is no assemblytype name known for component " + componentName);
	    assemblyTypeName = result.getString(1);
	    if (result.next() != false)
                logger.warning("TMCDB: Database error: There were more than one assemblytype name known for component " + componentName);
	    result.close();
	    statement.close();
        } catch (SQLException err) {
            err.printStackTrace();
	}
	return assemblyTypeName;
    }

    private List<String> getComponentNames() {
	System.out.println("getComponentNames() called");
	return componentNameList;
    }

    public List<String> getAntennaNames() {

        List<String> antennaNames = new ArrayList<String>();
        List<String> componentNames = getComponentNames();

        for (String componentName : componentNames) {
            String antennaName = getAntennaFromCompName(componentName);
	    List<String> compsInAnt = antennasToCompMap.get(antennaName);
	    if (compsInAnt != null){
		compsInAnt.add(componentName);
	    } else {
                antennaNames.add(antennaName);
		List<String> aux = new ArrayList<String>();
		aux.add(componentName);
		antennasToCompMap.put(antennaName,aux);
	    }
        }
	System.out.println("Number of antennas = " + antennasToCompMap.size());
        return antennaNames;
    }

    private String getAntennaFromCompName(String componentName) {
        int antennaNameIndex = 1;
        if (componentName.startsWith("CORR"))
        {
            antennaNameIndex = 0;
        }
        String[] strParts = componentName.split("/");
        try {
            return strParts[antennaNameIndex];
        } catch (ArrayIndexOutOfBoundsException err) {
	    err.printStackTrace();
            return "";
        }
    }

    public List<String> getAssemblyNames(String antennaName) {
	List<String> compNames = antennasToCompMap.get(antennaName);

	List<String> assemblyNames = new ArrayList<String>();

        for (String compName : compNames) {
	    assemblyNames.add(getAssemblyFromCompName(compName));
	}
	antennasToAssemblyNameMap.put(antennaName,assemblyNames);
        return assemblyNames;
    }

    private String getAssemblyFromCompName(String compName) {
        int assemblyNameIndex = 2;
        String[] strParts;

	if (compName.contains("FrontEnd")||compName.contains("PhotonicReference"))
	    strParts = compName.split("/",3);
        else if (compName.contains("Mount")) {
            strParts = compName.split("/");
            if (strParts[1].contains("DV")) {
                strParts[2] = "MountVertex";
            } else if (strParts[1].contains("PM")) {
                strParts[2] = "MountACA";
            } else {
                strParts[2] = "MountAEM";
            }

	} else
	    strParts = compName.split("/");

        try {
            if (compName.startsWith("CORR"))
            {
                return strParts[assemblyNameIndex - 1];
            }

            return strParts[assemblyNameIndex];
        } catch (ArrayIndexOutOfBoundsException err) {
            return "";
        }
    }

    public List<String> getPropertyNames(String assemblyName) {

        List<String> propertyNames = new ArrayList<String>();

	System.out.println("assemblyName: " + assemblyName);

        Collection c = antennasToAssemblyNameMap.values();
	Set<String> k = antennasToAssemblyNameMap.keySet();
	Collection comps = antennasToCompMap.values();
	Iterator itr = c.iterator();
	Iterator itr2 = k.iterator();
	while(itr.hasNext()) {
	    List<String> aux = (List<String>) itr.next();
	    String antName = (String) itr2.next();
	    if (aux.contains(assemblyName)) {
		String compName =  antennasToCompMap.get(antName).get(aux.indexOf(assemblyName));
		System.out.println("assemblyName: " + assemblyName + " at position: " + aux.indexOf(assemblyName));
		System.out.println("Antenna: " + antName + " Comp Name: " + compName);
		try {
                    String tokens[] = ComponentNameHelper.getPathAndName(compName);
		    PreparedStatement getPropertiesByCompName = conn.prepareStatement("SELECT m.MonitorPointName " + 
										      "FROM MonitorPoint m, BaciProperty b, Component c " +
										      "WHERE m.BaciPropertyId = b.BaciPropertyId " + 
										      "AND b.ComponentId = c.ComponentId " +
										      "AND c.ConfigurationId = " + configurationId + " " +
										      "AND c.ComponentName = '" + tokens[1] + "' " +
                                                                                      "AND c.path = '" + tokens[0] + "'");
		
		    ResultSet result = getPropertiesByCompName.executeQuery();
		    if (result.next() == false){
			logger.warning("TMCDB: Database error: There are no properties for this component " + compName);
		    } else {
			do {
			    propertyNames.add(result.getString(1));
			} while (result.next());
		    }
		    result.close();
		    getPropertiesByCompName.close();
		    return propertyNames;
		} catch (SQLException err) {
		    logger.warning("Caught SQLException in alma.TMCDB.Query.TMCDBCommonQueries.getPropertyNames(" + assemblyName + ") "
				   + err.toString());
		    err.printStackTrace();
		}
	    }
        }
        return propertyNames;
    }

    private int getMonitorPointId(String componentName, String assemblyTypeName, String propertyName) {
	int mpId = -1;
	try {
	    System.out.println("configuration id = " + configurationId + " component name = " + componentName + " assembly type name = " + assemblyTypeName + " property name = " + propertyName);
            String tokens[] = ComponentNameHelper.getPathAndName(componentName);
	    PreparedStatement getMonitorPointIdFromCompName = conn.prepareStatement("SELECT m.MonitorPointId " +
										    "FROM MonitorPoint m, BaciProperty b, Component c, Assembly a " +
										    "WHERE m.BaciPropertyId = b.BaciPropertyId " +
										    "AND b.ComponentId = c.ComponentId " +
										    "AND c.ConfigurationId = a.ConfigurationId " +
										    "AND m.AssemblyId = a.AssemblyId " +
										    "AND a.ConfigurationId = " + configurationId + " " +
										    "AND a.AssemblyTypeName = '" + assemblyTypeName + "' " +
										    "AND c.ComponentName = '" + tokens[1] + "' " +
										    "AND c.Path = '" + tokens[0] + "' " +
										    "AND m.MonitorPointName = '" + propertyName + "'");
	    ResultSet result = getMonitorPointIdFromCompName.executeQuery();
	    if (result.next() == false)
		logger.warning("TMCDB: Database error: There are no properties for component " + componentName + " named " + propertyName);
	    mpId = result.getInt(1);
	    if (result.next() != false)
		logger.warning("TMCDB: Database error: Found more than one property for " + componentName + " named " + propertyName);
	    result.close();
	    getMonitorPointIdFromCompName.close();
	} catch (SQLException err) {
	    logger.warning("Caught SQLException in alma.TMCDB.Query.TMCDBCommonQueries.getMonitorPointId"
			   + err.toString());
	    err.printStackTrace();
	}
	return mpId;
    }

    private String getComponentName(String antennaName, String assemblyName) {
	List<String> assemblyNameList = antennasToAssemblyNameMap.get(antennaName);
	List<String> compList = antennasToCompMap.get(antennaName);
	String compName =  compList.get(assemblyNameList.indexOf(assemblyName));
	return compName;
    }

    public TimeValue getLastMonitorData(String antennaName,
					String assemblyName, 
					String propertyName) {
	System.out.println("getLastMonitorData => entering: antennaName = " + antennaName + ", assemblyName = " + assemblyName + ", propertyName = " + propertyName);
        TimeValue monitorData = null;

	String componentName = getComponentName(antennaName, assemblyName);
	String assemblyTypeName = getAssemblyTypeName(componentName);
	int monitorPointId = getMonitorPointId(componentName, assemblyTypeName, propertyName);

        try {
            monitorData = getLastMonitorDataPoint(monitorPointId);
        } catch (AcsJTmcdbGuiErrTypeEx err) {
            logger.warning(
                "Caught AcsJTmcdbGuiErrTypeEx in alma.TMCDB.Query.TMCDBCommonQueries.getLastMonitorData) "
                + err.toString());
        }
        return monitorData;
    }

    private TimeValue getLastMonitorDataPoint(int monitorPointId) throws AcsJTmcdbSqlEx {

        try {
            PreparedStatement lastMonitorDataTime = conn.prepareStatement("SELECT MAX(MonitorTS) FROM MonitorData  WHERE MonitorPointId = " + monitorPointId);
            ResultSet timeStampResults = lastMonitorDataTime.executeQuery();
            if (timeStampResults.next() == false)
                return null;
            Timestamp lastTimeStamp = timeStampResults.getTimestamp(1);
            PreparedStatement lastMonitorDataValue = conn.prepareStatement("SELECT MeanStat FROM MonitorData " + 
									   "WHERE MonitorPointId = " + monitorPointId + 
									   " AND MonitorTS = ?");
	    lastMonitorDataValue.setTimestamp(1,lastTimeStamp);
            ResultSet valueResults = lastMonitorDataValue.executeQuery();
            if (valueResults.next() == false) {
                logger.warning(
                    "Did not find Value data matching time stamp in alma.TMCDB.Query.TMCDBCommonQueries.getLastMonitorDataPoint()");
                return null;
            }

            String lastValue = valueResults.getString(1);
            if (valueResults.next() != false) {
                logger.warning(
                    "Found more than one Value data matching time stamp in alma.TMCDB.Query.TMCDBCommonQueries.getLastMonitorDataPoint()");
            }
	    timeStampResults.close();
	    lastMonitorDataTime.close();
	    valueResults.close();
	    lastMonitorDataValue.close();

            TimeValue result = new TimeValue(lastTimeStamp.getTime() * 10000L + 122192928000000000L, lastValue);
            return result;

        } catch (SQLException err) {
            err.printStackTrace();
            throw new AcsJTmcdbSqlEx(err);
        }
    }

    public TimeValuePager getMonitorData(String antennaName, String assemblyName,
					 String propertyName, long begin, 
					 long end, long pageNum) {
	System.out.println("getMonitorData => entering: antennaName = " + antennaName + ", assemblyName = " + assemblyName + ", propertyName = " + propertyName);
        TimeValue[] monitorData = new TimeValue[0];
	String componentName = getComponentName(antennaName, assemblyName);
	String assemblyTypeName = getAssemblyTypeName(componentName);
        int monitorPointId = getMonitorPointId(componentName, assemblyTypeName, propertyName);

        TimeValuePager tvp = null;
        QueryDAO queryDAO = new QueryDAOImpl(logger);
        // converts from acstime to system time
        Timestamp begin_ts = new Timestamp((begin - 122192928000000000L) / 10000L);
        Timestamp end_ts = new Timestamp((end - 122192928000000000L) / 10000L);

        try {
            tvp = queryDAO.getMonitorData(monitorPointId,begin_ts,end_ts);
        }catch(javax.persistence.NoResultException nre){
            logger.warning("Caught NoResultException in alma.TMCDB.Query.TMCDBCommonQueries.getMonitorData) "
			   + nre.toString());
        }
        return tvp;
    }

    public String getPropertyDataType(String propertyName) {
        String dataType = "";
        try {
	    PreparedStatement propertyDataTypeFromPropertyNameQuery = conn
		.prepareStatement("SELECT DataType FROM MonitorPoint WHERE MonitorPointName = ?");

            propertyDataTypeFromPropertyNameQuery.setString(1, propertyName);
            ResultSet result = propertyDataTypeFromPropertyNameQuery
                    .executeQuery();
            // This should give 0 or 1 results.
            if (result.next())
                dataType = result.getString("DataType");
	    result.close();
	    propertyDataTypeFromPropertyNameQuery.close();
        } catch (SQLException err) {
            logger.warning(
                "Caught SQLException in alma.TMCDB.Query.TMCDBCommonQueries.getPropertyDataType(" + propertyName + ") "
                + err.toString());
        }
	//System.out.println("dataType = " + dataType);
        return dataType;
    }

    public int getAssemblyIDforSN(String serialNumber) {
//System.out.println("getAssemblyIDforSN() => serialNumber = " + serialNumber);
        List<Integer> ids = new ArrayList<Integer>();
        try {
            PreparedStatement assemblyIdFromCompNameQuery = conn
                    .prepareStatement("SELECT AssemblyId from Monitorpoint, Baciproperty, Component WHERE Component.ComponentName = ? AND Component.Path = ? AND MonitorPoint.BaciPropertyId = BaciProperty.BaciPropertyId AND BaciProperty.ComponentId = Component.ComponentId AND ROWNUM = 1");
            String tokens[] = ComponentNameHelper.getPathAndName(serialNumber);
            assemblyIdFromCompNameQuery.setString(1, tokens[1]);
            assemblyIdFromCompNameQuery.setString(2, tokens[0]);
            ResultSet result = assemblyIdFromCompNameQuery.executeQuery();
            //assemblyIdFromAssemblySNQuery.setString(2, serialNumber);
            //ResultSet result = assemblyIdFromAssemblySNQuery.executeQuery();
            while (result.next())
                ids.add(result.getInt("AssemblyId"));
	    result.close();
	    assemblyIdFromCompNameQuery.close();
        } catch (SQLException err) {
            logger.warning(
                "SQLException in alma.TMCDB.Query.TMCDBCommonQueries.getAssembyIds() - please report a bug.");
        }
        if (ids.size() == 0)
            return 0;
        if (ids.size() == 1)
            return ids.get(0);
        logger.warning(
            "Found more than 1 assembly ID for assembly serial number in alma.TMCDB.Query.TMCDBCommonQueries.getAssemblyIDforSN(serialNumber) - possible TMCDB issue or bug in this method.");
        return ids.get(0);
    }

    public String getAssemblyName(int assemblyId) {

        List<String> names = new ArrayList<String>();
        try {
            PreparedStatement assemblyNameFromAssemblyIdQuery = conn
                    .prepareStatement("SELECT AssemblyTypeName FROM Assembly WHERE AssemblyId = ?");

            assemblyNameFromAssemblyIdQuery.setInt(1, assemblyId);
            ResultSet result = assemblyNameFromAssemblyIdQuery.executeQuery();
            while (result.next()) {
                names.add(result.getString("AssemblyName"));
            }
	    result.close();
	    assemblyNameFromAssemblyIdQuery.close();
        } catch (SQLException err) {
            logger.warning(
                "Caught SQLException in alma.TMCDB.Query.TMCDBCommonQueries.getAssemblyName(assemblyId) "
                + err.toString());
        }
        if (names.size() == 0)
            return "";
        else if (names.size() == 1)
            return names.get(0);
        else {
            logger.warning(
                "alma.TMCDB.Query.TMCDBCommonQueries.getAssemblyName(assemblyId) found more than one name for assemblyId: "
                + assemblyId
                + ", returning the fist name found.");
            return names.get(0);
        }
    }

} // class

//O_o
