/// <summary>
    ///  Process one load specification.
    /// </summary>
    /// <param name="handler">The data loader that constructs OPL elements.</param>
    /// <param name="tuple">The load specification.</param>
    private void loadSpec(OplDataHandler handler, ITuple tuple)
    {
        // Get the connection string
        // In the SimpleData implementation we don't use that string.
        // If you create a data source that is backed up by a file or
        // by a database, then this string can be used to specify
        // locations and/or credentials.
        string connection = tuple.GetStringValue(CONN_FIELD);

        connection = Interpolate(connection, handler);

        string connectionType = tryLoadField(tuple, TYPE_FIELD, "SimpleData");

        connectionType = Interpolate(connectionType, handler);
        IDataProvider provider = null;

        if (connectionType.Equals("SimpleData"))
        {
            provider = new SimpleData(connection);
        }
        else if (connectionType.Equals("SQLite"))
        {
            provider = new SQLiteData(connection);
        }
        else
        {
            provider = new GenericData(connectionType, connection);
        }

        // Process each of load specifications and load the respective
        // element.
        using (provider)
        {
            ISymbolSet  data = tuple.GetSymbolSetValue(DATA_FIELD);
            IEnumerator e    = data.GetEnumerator();
            while (e.MoveNext())
            {
                // Split specification into element name and
                // initialiation string (statement).
                string s    = Interpolate(e.Current.ToString().Trim(), handler);
                int    eq   = s.IndexOf('=');
                string name = s.Substring(0, eq).Trim();
                string stmt = s.Substring(eq + 1).Trim();

                // Inspect the type of the element and populate it.
                OplElement          elem = handler.getElement(name);
                OplElementType.Type type = elem.ElementType;
                using (IEnumerator <IRow> rows = provider.getRows(stmt))
                {
                    // (collections of) integers
                    if (type == OplElementType.Type.INT)
                    {
                        loadPrimitive(handler, name, rows, SET_INT);
                    }
                    else if (type == OplElementType.Type.SET_INT)
                    {
                        loadPrimitiveCollection(handler, name, rows, START_SET, END_SET, SET_INT);
                    }
                    else if (type == OplElementType.Type.MAP_INT)
                    {
                        loadPrimitiveCollection(handler, name, rows, START_ARRAY, END_ARRAY, SET_INT);
                    }

                    // (collections of) floating point values
                    else if (type == OplElementType.Type.NUM)
                    {
                        loadPrimitive(handler, name, rows, SET_FLOAT);
                    }
                    else if (type == OplElementType.Type.SET_NUM)
                    {
                        loadPrimitiveCollection(handler, name, rows, START_SET, END_SET, SET_FLOAT);
                    }
                    else if (type == OplElementType.Type.MAP_NUM)
                    {
                        loadPrimitiveCollection(handler, name, rows, START_ARRAY, END_ARRAY, SET_FLOAT);
                    }

                    // (collections of) tuples
                    else if (type == OplElementType.Type.STRING)
                    {
                        loadPrimitive(handler, name, rows, SET_STRING);
                    }
                    else if (type == OplElementType.Type.SET_SYMBOL)
                    {
                        loadPrimitiveCollection(handler, name, rows, START_SET, END_SET, SET_STRING);
                    }
                    else if (type == OplElementType.Type.MAP_SYMBOL)
                    {
                        loadPrimitiveCollection(handler, name, rows, START_ARRAY, END_ARRAY, SET_STRING);
                    }

                    else if (type == OplElementType.Type.TUPLE)
                    {
                        loadTuple(handler, name, rows);
                    }
                    else if (type == OplElementType.Type.SET_TUPLE)
                    {
                        loadTupleCollection(handler, name, rows, elem.AsTupleSet().Schema, START_SET, END_SET);
                    }
                    else if (type == OplElementType.Type.MAP_TUPLE)
                    {
                        loadTupleCollection(handler, name, rows, elem.AsTupleMap().Schema, START_ARRAY, END_ARRAY);
                    }
                    else
                    {
                        throw new NotImplementedException("element type " + type + " not implemented");
                    }
                }
            }
        }
    }