text:
//******************************************************************************************************
//  Measurement.cs - Gbtc
//
//  Copyright © 2012, Grid Protection Alliance.  All Rights Reserved.
//
//  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
//  the NOTICE file distributed with this work for additional information regarding copyright ownership.
//  The GPA licenses this file to you under the MIT License (MIT), 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.opensource.org/licenses/MIT
//
//  Unless agreed to in writing, the subject software distributed under the License is distributed on an
//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
//  License for the specific language governing permissions and limitations.
//
//  Code Modification History:
//  ----------------------------------------------------------------------------------------------------
//  04/08/2011 - Magdiel Lorenzo
//       Generated original version of source code.
//  05/02/2011 - J. Ritchie Carroll
//       Updated for coding consistency.
//  05/03/2011 - Mehulbhai P Thakkar
//       Guid field related changes as well as static functions update.
//  05/05/2011 - Mehulbhai P Thakkar
//       Added NULL handling for Save() operation.
//  05/13/2011 - Aniket Salver
//       Modified the way Guid is retrieved from the Data Base.
//  05/13/2011 - Mehulbhai P Thakkar
//       Modified static methods to filter data by device.
//  12/20/2012 - Starlynn Danyelle Gilliam
//       Modified Header.
//
//******************************************************************************************************

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Data;
using System.Linq;
using GSF.Data;

namespace GSF.TimeSeries.UI.DataModels
{
    /// <summary>
    /// Represents a record of <see cref="Measurement"/> information as defined in the database.
    /// </summary>
    public class Measurement : DataModelBase
    {
        #region [ Members ]

        // Fields
        private Guid m_signalID;
        private int? m_historianID;
        private int m_pointID;
        private int? m_deviceID;
        private string m_pointTag;
        private string m_alternateTag;
        private int m_signalTypeID;
        private int? m_phasorSourceIndex;
        private string m_signalReference;
        private double m_adder;
        private double m_multiplier;
        private string m_description;
        private bool m_subscribed;
        private bool m_internal;
        private bool m_enabled;
        private string m_historianAcronym;
        private string m_deviceAcronym;
        private int? m_framesPerSecond;
        private string m_signalName;
        private string m_signalAcronym;
        private string m_signalSuffix;
        private string m_phasorLabel;
        private DateTime m_createdOn;
        private string m_createdBy;
        private DateTime m_updatedOn;
        private string m_updatedBy;
        private string m_id;
        private string m_companyAcronym;
        private string m_companyName;
        private bool m_selected;  //This is added for the SelectMeasurement user control to provide check boxes.

        #endregion

        #region [ Constructors ]

        /// <summary>
        /// Creates a new instance of the <see cref="Measurement"/> class.
        /// </summary>
        public Measurement()
        {
        }

        /// <summary>
        /// Creates a new instance of the <see cref="Measurement"/> class.
        /// </summary>
        /// <param name="loadDefaults">
        /// Determines whether to load default values into the properties using reflection.
        /// </param>
        public Measurement(bool loadDefaults)
            : base(loadDefaults, false)
        {
        }

        #endregion

        #region [ Properties ]

        /// <summary>
        /// Gets or sets the current <see cref="Measurement"/>'s Signal ID.
        /// </summary>
        public Guid SignalID
        {
            get
            {
                return m_signalID;
            }
            set
            {
                m_signalID = value;
                OnPropertyChanged("SignalID");
            }
        }

        /// <summary>
        /// Gets or sets the current <see cref="Measurement"/>'s Historian ID.
        /// </summary>
        // Because of database design, no validation attributes are applied
        public int? HistorianID
        {
            get
            {
                return m_historianID;
            }
            set
            {
                m_historianID = value;
                OnPropertyChanged("HistorianID");
            }
        }

        /// <summary>
        /// Gets or sets the current <see cref="Measurement"/>'s Point ID.
        /// </summary>
        // Field is populated by database via auto-increment and has no screen interaction, so no validation attributes are applied.
        public int PointID
        {
            get
            {
                return m_pointID;
            }
            set
            {
                m_pointID = value;
            }
        }

        /// <summary>
        /// Gets or sets the current <see cref="Measurement"/>'s Device ID.
        /// </summary>
        // Because of database design, no validation attributes are applied.
        public int? DeviceID
        {
            get
            {
                return m_deviceID;
            }
            set
            {
                m_deviceID = value;
                OnPropertyChanged("DeviceID");
            }
        }

        /// <summary>
        /// Gets or sets the current <see cref="Measurement"/>'s Point Tag.
        /// </summary>
        [Required(ErrorMessage = "Measurement point tag is a required field, please provide value.")]
        [StringLength(200, ErrorMessage = "Measurement point tag cannot exceed 200 characters.")]
        public string PointTag
        {
            get
            {
                return m_pointTag;
            }
            set
            {
                if ((object)value != null && value.Length > 200)
                    m_pointTag = value.Substring(0, 200);
                else
                    m_pointTag = value;
                OnPropertyChanged("PointTag");
            }
        }

        /// <summary>
        /// Gets or sets the current <see cref="Measurement"/>'s Alternate Tag.
        /// </summary>
        public string AlternateTag
        {
            get
            {
                return m_alternateTag;
            }
            set
            {
                m_alternateTag = value;
                OnPropertyChanged("AlternateTag");
            }
        }

        /// <summary>
        /// Gets or sets the current <see cref="Measurement"/>'s Signal Type ID.
        /// </summary>
        [Required(ErrorMessage = "Measurement signal type ID is a required field, please provide value.")]
        public int SignalTypeID
        {
            get
            {
                return m_signalTypeID;
            }
            set
            {
                m_signalTypeID = value;
                OnPropertyChanged("SignalTypeID");
            }
        }

        /// <summary>
        /// Gets or sets the current <see cref="Measurement"/>'s Phasor Source Index.
        /// </summary>
        // Because of database design, no validation attributes are applied
        public int? PhasorSourceIndex
        {
            get
            {
                return m_phasorSourceIndex;
            }
            set
            {
                m_phasorSourceIndex = value;
                OnPropertyChanged("PhasorSourceIndex");
            }
        }

        /// <summary>
        /// Gets or sets the current <see cref="Measurement"/>'s Signal Reference.
        /// </summary>
        [Required(ErrorMessage = "Measurement signal reference is a required field, please provide value.")]
        public string SignalReference
        {
            get
            {
                return m_signalReference;
            }
            set
            {
                m_signalReference = value;
                OnPropertyChanged("SignalReference");
            }
        }

        /// <summary>
        /// Gets or sets the current <see cref="Measurement"/>'s Adder.
        /// </summary>
        [DefaultValue(typeof(double), "0.0")]
        public double Adder
        {
            get
            {
                return m_adder;
            }
            set
            {
                m_adder = value;
                OnPropertyChanged("Adder");
            }
        }

        /// <summary>
        /// Gets or sets the current <see cref="Measurement"/>'s Multiplier.
        /// </summary>
        [DefaultValue(typeof(double), "1.0")]
        public double Multiplier
        {
            get
            {
                return m_multiplier;
            }
            set
            {
                m_multiplier = value;
                OnPropertyChanged("Multiplier");
            }
        }

        /// <summary>
        /// Gets or sets the current <see cref="Measurement"/>'s Description.
        /// </summary>
        // Because of database design, no validation attributes are applied
        public string Description
        {
            get
            {
                return m_description;
            }
            set
            {
                m_description = value;
                OnPropertyChanged("Description");
            }
        }

        /// <summary>
        /// Gets or sets whether the current <see cref="Measurement"/> is enabled.
        /// </summary>
        [DefaultValue(false)]
        public bool Subscribed
        {
            get
            {
                return m_subscribed;
            }
            set
            {
                m_subscribed = value;
                OnPropertyChanged("Subscribed");
            }
        }

        /// <summary>
        /// Gets or sets whether the current <see cref="Measurement"/> is enabled.
        /// </summary>
        [DefaultValue(true)]
        public bool Internal
        {
            get
            {
                return m_internal;
            }
            set
            {
                m_internal = value;
                OnPropertyChanged("Internal");
            }
        }

        /// <summary>
        /// Gets or sets whether the current <see cref="Measurement"/> is enabled.
        /// </summary>
        [DefaultValue(false)]
        public bool Enabled
        {
            get
            {
                return m_enabled;
            }
            set
            {
                m_enabled = value;
                OnPropertyChanged("Enabled");
            }
        }

        /// <summary>
        /// Gets the current <see cref="Measurement"/>'s Historian Acronym.
        /// </summary>
        // Because of database design, no validation attributes are supplied
        public string HistorianAcronym
        {
            get
            {
                return m_historianAcronym;
            }
        }

        /// <summary>
        /// Gets the current <see cref="Measurement"/>'s Device Acronym.
        /// </summary>
        // Because of database design, no validation attributes are supplied
        public string DeviceAcronym
        {
            get
            {
                return m_deviceAcronym;
            }
        }

        /// <summary>
        /// Gets the current <see cref="Measurement"/>'s Frames Per Second.
        /// </summary>
        // Because of database design, no validation attributes are supplied
        public int? FramesPerSecond
        {
            get
            {
                return m_framesPerSecond;
            }
        }

        /// <summary>
        /// Gets the current <see cref="Measurement"/>'s Signal Name.
        /// </summary>
        // Because of database design, no validation attributes are supplied
        public string SignalName
        {
            get
            {
                return m_signalName;
            }
        }

        /// <summary>
        /// Gets the current <see cref="Measurement"/>'s Signal Acronym.
        /// </summary>
        // Because of database design, no validation attributes are supplied
        public string SignalAcronym
        {
            get
            {
                return m_signalAcronym;
            }
        }

        /// <summary>
        /// Gets the current <see cref="Measurement"/>'s Signal Suffix.
        /// </summary>
        // Because of database design, no validation attributes are supplied
        public string SignalSuffix
        {
            get
            {
                return m_signalSuffix;
            }
        }

        /// <summary>
        /// Gets the current <see cref="Measurement"/>'s Phasor Label.
        /// </summary>
        // Because of database design, no validation attributes are supplied
        public string PhasorLabel
        {
            get
            {
                return m_phasorLabel;
            }
        }

        /// <summary>
        /// Gets or sets when the current <see cref="Measurement"/> was Created.
        /// </summary>
        // Field is populated by trigger and has no screen interaction, so no validation attributes are applied
        public DateTime CreatedOn
        {
            get
            {
                return m_createdOn;
            }
            set
            {
                m_createdOn = value;
            }
        }

        /// <summary>
        /// Gets or sets who the current <see cref="Measurement"/> was created by.
        /// </summary>
        // Field is populated by trigger and has no screen interaction, so no validation attributes are applied
        public string CreatedBy
        {
            get
            {
                return m_createdBy;
            }
            set
            {
                m_createdBy = value;
            }
        }

        /// <summary>
        /// Gets or sets when the current <see cref="Measurement"/> updated.
        /// </summary>
        // Field is populated by trigger and has no screen interaction, so no validation attributes are applied
        public DateTime UpdatedOn
        {
            get
            {
                return m_updatedOn;
            }
            set
            {
                m_updatedOn = value;
            }
        }

        /// <summary>
        /// Gets or sets who the current <see cref="Measurement"/> was updated by.
        /// </summary>
        // Field is populated by trigger and has no screen interaction, so no validation attributes are applied
        public string UpdatedBy
        {
            get
            {
                return m_updatedBy;
            }
            set
            {
                m_updatedBy = value;
            }
        }

        /// <summary>
        /// Gets ID of the <see cref="Measurement"/>.
        /// </summary>
        // Field is populated via view, so no validation attributes are applied.
        public string ID
        {
            get
            {
                return m_id;
            }
        }

        /// <summary>
        /// Gets <see cref="Measurement"/> company acronym.
        /// </summary>
        // Field is populated via view, so no validation attributes are applied.
        public string CompanyAcronym
        {
            get
            {
                return m_companyAcronym;
            }
        }

        /// <summary>
        /// Gets <see cref="Measurement"/> company name.
        /// </summary>
        // Field is populated via view, so no validation attributes are applied.
        public string CompanyName
        {
            get
            {
                return m_companyName;
            }
        }

        /// <summary>
        /// Gets or sets selected flag for <see cref="Measurement"/>.
        /// </summary>
        public bool Selected
        {
            get
            {
                return m_selected;
            }
            set
            {
                m_selected = value;
                OnPropertyChanged("Selected");
            }
        }

        #endregion

        #region [ Static ]

        /// <summary>
        /// Loads <see cref="Measurement"/> signal IDs as an <see cref="IList{T}"/>.
        /// </summary>
        /// <param name="database"><see cref="AdoDataConnection"/> to connection to database.</param>
        /// <param name="filterExpression">SQL expression by which to filter the data coming from the database.</param>
        /// <param name="sortMember">The field to sort by.</param>
        /// <param name="sortDirection"><c>ASC</c> or <c>DESC</c> for ascending or descending respectively.</param>
        /// <returns>Collection of <see cref="Guid"/>.</returns>
        /// <remarks>
        /// This method does not validate <paramref name="filterExpression"/> for SQL injection.
        /// Developers should validate their inputs before entering a filter expression.
        /// </remarks>
        public static List<Guid> LoadSignalIDs(AdoDataConnection database, string filterExpression = "", string sortMember = "", string sortDirection = "")
        {
            bool createdConnection = false;

            try
            {
                createdConnection = CreateConnection(ref database);

                List<Guid> signalIDList = new List<Guid>();
                DataTable measurementTable;

                string query;
                string sortClause = string.Empty;

                if (!string.IsNullOrEmpty(sortMember))
                    sortClause = string.Format("ORDER BY {0} {1}", sortMember, sortDirection);

                if (!string.IsNullOrEmpty(filterExpression))
                    query = string.Format("SELECT SignalID FROM MeasurementDetail WHERE ({0}) {1}", filterExpression, sortClause);
                else
                    query = string.Format("SELECT SignalID FROM MeasurementDetail {0}", sortClause);

                measurementTable = database.Connection.RetrieveData(database.AdapterType, query);

                foreach (DataRow row in measurementTable.Rows)
                {
                    signalIDList.Add(database.Guid(row, "SignalID"));
                }

                return signalIDList;
            }
            finally
            {
                if (createdConnection && database != null)
                    database.Dispose();
            }
        }

        /// <summary>
        /// Loads <see cref="Measurement"/> information as an <see cref="ObservableCollection{T}"/> style list.
        /// </summary>
        /// <param name="database"><see cref="AdoDataConnection"/> to connection to database.</param>
        /// <param name="keys">Keys of the measurements to be loaded from the database.</param>
        /// <returns>Collection of <see cref="Measurement"/>.</returns>
        public static ObservableCollection<Measurement> LoadFromKeys(AdoDataConnection database, List<Guid> keys)
        {
            bool createdConnection = false;

            try
            {
                createdConnection = CreateConnection(ref database);

                string query;
                string commaSeparatedKeys;

                Measurement[] measurementList = null;
                DataTable measurementTable;
                Guid signalID;

                if ((object)keys != null && keys.Count > 0)
                {
                    commaSeparatedKeys = keys.Select(key => "'" + key.ToString() + "'").Aggregate((str1, str2) => str1 + "," + str2);
                    query = string.Format("SELECT * FROM MeasurementDetail WHERE SignalID IN ({0})", commaSeparatedKeys);
                    measurementTable = database.Connection.RetrieveData(database.AdapterType, query);
                    measurementList = new Measurement[measurementTable.Rows.Count];

                    foreach (DataRow row in measurementTable.Rows)
                    {
                        signalID = database.Guid(row, "SignalID");

                        measurementList[keys.IndexOf(signalID)] = new Measurement(false)
                        {
                            SignalID = signalID,
                            HistorianID = row.ConvertNullableField<int>("HistorianID"),
                            PointID = row.ConvertField<int>("PointID"),
                            DeviceID = row.ConvertNullableField<int>("DeviceID"),
                            PointTag = row.Field<string>("PointTag"),
                            AlternateTag = row.Field<string>("AlternateTag"),
                            SignalTypeID = row.ConvertField<int>("SignalTypeID"),
                            PhasorSourceIndex = row.ConvertNullableField<int>("PhasorSourceIndex"),
                            SignalReference = row.Field<string>("SignalReference"),
                            Adder = row.ConvertField<double>("Adder"),
                            Multiplier = row.ConvertField<double>("Multiplier"),
                            Internal = Convert.ToBoolean(row.Field<object>("Internal")),
                            Subscribed = Convert.ToBoolean(row.Field<object>("Subscribed")),
                            Description = row.Field<string>("Description"),
                            Enabled = Convert.ToBoolean(row.Field<object>("Enabled")),
                            m_historianAcronym = row.Field<string>("HistorianAcronym"),
                            m_deviceAcronym = row.Field<object>("DeviceAcronym") == null ? string.Empty : row.Field<string>("DeviceAcronym"),
                            m_signalName = row.Field<string>("SignalName"),
                            m_signalAcronym = row.Field<string>("SignalAcronym"),
                            m_signalSuffix = row.Field<string>("SignalTypeSuffix"),
                            m_phasorLabel = row.Field<string>("PhasorLabel"),
                            m_framesPerSecond = Convert.ToInt32(row.Field<object>("FramesPerSecond") ?? 30),
                            m_id = row.Field<string>("ID"),
                            m_companyAcronym = row.Field<object>("CompanyAcronym") == null ? string.Empty : row.Field<string>("CompanyAcronym"),
                            m_companyName = row.Field<object>("CompanyName") == null ? string.Empty : row.Field<string>("CompanyName"),
                            Selected = false
                        };
                    }
                }

                return new ObservableCollection<Measurement>(measurementList ?? new Measurement[0]);
            }
            finally
            {
                if (createdConnection && database != null)
                    database.Dispose();
            }
        }

        /// <summary>
        /// Loads <see cref="Measurement"/> information as an <see cref="ObservableCollection{T}"/> style list.
        /// </summary>
        /// <param name="database"><see cref="AdoDataConnection"/> to connection to database.</param>
        /// <param name="deviceID">ID of the Device to filter data.</param>
        /// <param name="filterByInternalFlag">boolean flag to indicate if only non internal data requested.</param>
        /// <param name="includeInternal">boolean flag to indicate if internal measurements are included.</param>
        /// <returns>Collection of <see cref="Measurement"/>.</returns>
        public static ObservableCollection<Measurement> Load(AdoDataConnection database, int deviceID = 0, bool filterByInternalFlag = false, bool includeInternal = false)
        {
            bool createdConnection = false;

            try
            {
                createdConnection = CreateConnection(ref database);

                ObservableCollection<Measurement> measurementList = new ObservableCollection<Measurement>();
                DataTable measurementTable;
                string query;

                if (filterByInternalFlag)
                {
                    if (deviceID > 0)
                    {
                        if (includeInternal)
                        {
                            query = database.ParameterizedQueryString("SELECT * FROM MeasurementDetail WHERE DeviceID = {0} AND " +
                                "Subscribed = {1} ORDER BY PointID", "deviceID", "subscribed");

                            measurementTable = database.Connection.RetrieveData(database.AdapterType, query,
                                DefaultTimeout, deviceID, database.Bool(false));
                        }
                        else
                        {
                            query = database.ParameterizedQueryString("SELECT * FROM MeasurementDetail WHERE DeviceID = {0} AND Internal = {1} AND " +
                                "Subscribed = {2} ORDER BY PointID", "deviceID", "internal", "subscribed");

                            measurementTable = database.Connection.RetrieveData(database.AdapterType, query,
                                DefaultTimeout, deviceID, database.Bool(false), database.Bool(false));
                        }
                    }
                    else
                    {
                        if (includeInternal)
                        {
                            query = database.ParameterizedQueryString("SELECT * FROM MeasurementDetail WHERE " +
                                "Subscribed = {0} ORDER BY PointTag", "subscribed");

                            measurementTable = database.Connection.RetrieveData(database.AdapterType, query,
                                DefaultTimeout, database.Bool(false));
                        }
                        else
                        {
                            query = database.ParameterizedQueryString("SELECT * FROM MeasurementDetail WHERE Internal = {0} AND " +
                                "Subscribed = {1} ORDER BY PointTag", "internal", "subscribed");

                            measurementTable = database.Connection.RetrieveData(database.AdapterType, query,
                                DefaultTimeout, database.Bool(false), database.Bool(false));
                        }
                    }
                }
                else
                {
                    if (deviceID > 0)
                    {
                        query = database.ParameterizedQueryString("SELECT * FROM MeasurementDetail WHERE DeviceID = {0} ORDER BY PointID", "deviceID");
                        measurementTable = database.Connection.RetrieveData(database.AdapterType, query, DefaultTimeout, deviceID);
                    }
                    else
                    {
                        query = "SELECT * FROM MeasurementDetail ORDER BY PointTag";
                        measurementTable = database.Connection.RetrieveData(database.AdapterType, query);
                    }
                }

                foreach (DataRow row in measurementTable.Rows)
                {
                    measurementList.Add(new Measurement(false)
                    {
                        SignalID = database.Guid(row, "SignalID"),
                        HistorianID = row.ConvertNullableField<int>("HistorianID"),
                        PointID = row.ConvertField<int>("PointID"),
                        DeviceID = row.ConvertNullableField<int>("DeviceID"),
                        PointTag = row.Field<string>("PointTag"),
                        AlternateTag = row.Field<string>("AlternateTag"),
                        SignalTypeID = row.ConvertField<int>("SignalTypeID"),
                        PhasorSourceIndex = row.ConvertNullableField<int>("PhasorSourceIndex"),
                        SignalReference = row.Field<string>("SignalReference"),
                        Adder = row.ConvertField<double>("Adder"),
                        Multiplier = row.ConvertField<double>("Multiplier"),
                        Internal = Convert.ToBoolean(row.Field<object>("Internal")),
                        Subscribed = Convert.ToBoolean(row.Field<object>("Subscribed")),
                        Description = row.Field<string>("Description"),
                        Enabled = Convert.ToBoolean(row.Field<object>("Enabled")),
                        m_historianAcronym = row.Field<string>("HistorianAcronym"),
                        m_deviceAcronym = row.Field<object>("DeviceAcronym") == null ? string.Empty : row.Field<string>("DeviceAcronym"),
                        m_signalName = row.Field<string>("SignalName"),
                        m_signalAcronym = row.Field<string>("SignalAcronym"),
                        m_signalSuffix = row.Field<string>("SignalTypeSuffix"),
                        m_phasorLabel = row.Field<string>("PhasorLabel"),
                        m_framesPerSecond = Convert.ToInt32(row.Field<object>("FramesPerSecond") ?? 30),
                        m_id = row.Field<string>("ID"),
                        m_companyAcronym = row.Field<object>("CompanyAcronym") == null ? string.Empty : row.Field<string>("CompanyAcronym"),
                        m_companyName = row.Field<object>("CompanyName") == null ? string.Empty : row.Field<string>("CompanyName"),
                        Selected = false
                    });
                }

                return measurementList;
            }
            finally
            {
                if (createdConnection && database != null)
                    database.Dispose();
            }
        }

        /// <summary>
        /// Loads information about <see cref="Measurement"/> assigned to MeasurementGroup as <see cref="ObservableCollection{T}"/> style list.
        /// </summary>
        /// <param name="database"><see cref="AdoDataConnection"/> to connection to database.</param>
        /// <param name="measurementGroupID">ID of the MeasurementGroup to filter data.</param>
        /// <returns>Collection of <see cref="Measurement"/>.</returns>
        public static ObservableCollection<Measurement> GetMeasurementsByGroup(AdoDataConnection database, int measurementGroupID)
        {
            bool createdConnection = false;
            try
            {
                createdConnection = CreateConnection(ref database);

                if (measurementGroupID == 0)
                    return Load(database);

                ObservableCollection<Measurement> possibleMeasurements = new ObservableCollection<Measurement>();

                string query = database.ParameterizedQueryString("SELECT * FROM MeasurementDetail WHERE SignalID NOT IN " +
                    "(SELECT SignalID FROM MeasurementGroupMeasurement WHERE MeasurementGroupID = {0}) ORDER BY PointTag", "measurementGroupID");

                DataTable possibleMeasurementTable = database.Connection.RetrieveData(database.AdapterType, query, DefaultTimeout, measurementGroupID);

                foreach (DataRow row in possibleMeasurementTable.Rows)
                {
                    possibleMeasurements.Add(new Measurement
                    {
                        SignalID = database.Guid(row, "SignalID"),
                        HistorianID = row.ConvertNullableField<int>("HistorianID"),
                        PointID = row.ConvertField<int>("PointID"),
                        DeviceID = row.ConvertNullableField<int>("DeviceID"),
                        PointTag = row.Field<string>("PointTag"),
                        AlternateTag = row.Field<string>("AlternateTag"),
                        SignalTypeID = row.ConvertField<int>("SignalTypeID"),
                        PhasorSourceIndex = row.ConvertNullableField<int>("PhasorSourceIndex"),
                        SignalReference = row.Field<string>("SignalReference"),
                        Adder = row.ConvertField<double>("Adder"),
                        Multiplier = row.ConvertField<double>("Multiplier"),
                        Description = row.Field<string>("Description"),
                        Internal = Convert.ToBoolean(row.Field<object>("Internal")),
                        Subscribed = Convert.ToBoolean(row.Field<object>("Subscribed")),
                        Enabled = Convert.ToBoolean(row.Field<object>("Enabled")),
                        m_historianAcronym = row.Field<string>("HistorianAcronym"),
                        m_deviceAcronym = row.Field<object>("DeviceAcronym") == null ? string.Empty : row.Field<string>("DeviceAcronym"),
                        m_signalName = row.Field<string>("SignalName"),
                        m_signalAcronym = row.Field<string>("SignalAcronym"),
                        m_signalSuffix = row.Field<string>("SignalTypeSuffix"),
                        m_phasorLabel = row.Field<string>("PhasorLabel"),
                        m_id = row.Field<string>("ID"),
                        m_companyAcronym = row.Field<object>("CompanyAcronym") == null ? string.Empty : row.Field<string>("CompanyAcronym"),
                        m_companyName = row.Field<object>("CompanyName") == null ? string.Empty : row.Field<string>("CompanyName"),
                        Selected = false
                    });
                }

                return possibleMeasurements;
            }
            finally
            {
                if (createdConnection && database != null)
                    database.Dispose();
            }
        }

        /// <summary>
        /// Loads information about <see cref="Measurement"/> assigned to Subscriber as <see cref="ObservableCollection{T}"/> style list.
        /// </summary>
        /// <param name="database"><see cref="AdoDataConnection"/> to connection to database.</param>
        /// <param name="subscriberID">ID of the Subscriber to filter data.</param>
        /// <returns>Collection of <see cref="Measurement"/>.</returns>
        public static ObservableCollection<Measurement> GetMeasurementsBySubscriber(AdoDataConnection database, Guid subscriberID)
        {
            bool createdConnection = false;
            try
            {
                createdConnection = CreateConnection(ref database);

                if (subscriberID == Guid.Empty)
                    return Load(database);

                ObservableCollection<Measurement> possibleMeasurements = new ObservableCollection<Measurement>();

                string query = database.ParameterizedQueryString("SELECT * FROM MeasurementDetail WHERE SignalID NOT IN " +
                    "(SELECT SignalID FROM SubscriberMeasurement WHERE SubscriberID = {0}) ORDER BY PointTag", "subscriberID");

                DataTable possibleMeasurementTable = database.Connection.RetrieveData(database.AdapterType, query, DefaultTimeout, database.Guid(subscriberID));

                foreach (DataRow row in possibleMeasurementTable.Rows)
                {
                    possibleMeasurements.Add(new Measurement
                    {
                        SignalID = database.Guid(row, "SignalID"),
                        HistorianID = row.ConvertNullableField<int>("HistorianID"),
                        PointID = row.ConvertField<int>("PointID"),
                        DeviceID = row.ConvertNullableField<int>("DeviceID"),
                        PointTag = row.Field<string>("PointTag"),
                        AlternateTag = row.Field<string>("AlternateTag"),
                        SignalTypeID = row.ConvertField<int>("SignalTypeID"),
                        PhasorSourceIndex = row.ConvertNullableField<int>("PhasorSourceIndex"),
                        SignalReference = row.Field<string>("SignalReference"),
                        Adder = row.ConvertField<double>("Adder"),
                        Multiplier = row.ConvertField<double>("Multiplier"),
                        Internal = Convert.ToBoolean(row.Field<object>("Internal")),
                        Subscribed = Convert.ToBoolean(row.Field<object>("Subscribed")),
                        Description = row.Field<string>("Description"),
                        Enabled = Convert.ToBoolean(row.Field<object>("Enabled")),
                        m_historianAcronym = row.Field<string>("HistorianAcronym"),
                        m_deviceAcronym = row.Field<object>("DeviceAcronym") == null ? string.Empty : row.Field<string>("DeviceAcronym"),
                        m_signalName = row.Field<string>("SignalName"),
                        m_signalAcronym = row.Field<string>("SignalAcronym"),
                        m_signalSuffix = row.Field<string>("SignalTypeSuffix"),
                        m_phasorLabel = row.Field<string>("PhasorLabel"),
                        m_id = row.Field<string>("ID"),
                        m_companyAcronym = row.Field<object>("CompanyAcronym") == null ? string.Empty : row.Field<string>("CompanyAcronym"),
                        m_companyName = row.Field<object>("CompanyName") == null ? string.Empty : row.Field<string>("CompanyName"),
                        Selected = false
                    });
                }

                return possibleMeasurements;
            }
            finally
            {
                if (createdConnection && database != null)
                    database.Dispose();
            }
        }

        /// <summary>
        /// Gets a <see cref="Dictionary{T1,T2}"/> style list of <see cref="Measurement"/> information.
        /// </summary>
        /// <param name="database"><see cref="AdoDataConnection"/> to connection to database.</param>
        /// <param name="isOptional">Indicates if selection on UI is optional for this collection.</param>
        /// <param name="subscribedOnly">boolean flag to indicate if only subscribed measurements to be returned.</param>
        /// <returns><see cref="Dictionary{T1,T2}"/> containing PointID and SignalID of measurements defined in the database.</returns>
        public static Dictionary<Guid, string> GetLookupList(AdoDataConnection database, bool isOptional = false, bool subscribedOnly = false)
        {
            bool createdConnection = false;

            try
            {
                createdConnection = CreateConnection(ref database);

                Dictionary<Guid, string> measurementList = new Dictionary<Guid, string>();
                if (isOptional)
                    measurementList.Add(Guid.Empty, "Select Measurement");

                DataTable measurementTable;
                string query;

                if (subscribedOnly)
                {
                    // If subscribedOnly is set then return only those measurements which are not internal and subscribed flag is set to true.
                    query = database.ParameterizedQueryString("SELECT SignalID, PointTag FROM MeasurementDetail WHERE " +
                        "NodeID = {0} AND Internal = {1} AND Subscribed = {2} ORDER BY PointID", "nodeID", "internal", "subscribed");

                    measurementTable = database.Connection.RetrieveData(database.AdapterType, query,
                        DefaultTimeout, database.CurrentNodeID(), database.Bool(false), database.Bool(true));
                }
                else
                {
                    query = database.ParameterizedQueryString("SELECT SignalID, PointTag FROM MeasurementDetail WHERE NodeID = {0} ORDER BY PointID", "nodeID");
                    measurementTable = database.Connection.RetrieveData(database.AdapterType, query, DefaultTimeout, database.CurrentNodeID());
                }

                foreach (DataRow row in measurementTable.Rows)
                    measurementList[database.Guid(row, "SignalID")] = row.Field<string>("PointTag");

                return measurementList;
            }
            finally
            {
                if (createdConnection && database != null)
                    database.Dispose();
            }
        }

        /// <summary>
        /// Retrieves only subscribed <see cref="Measurement"/> collection.
        /// </summary>
        /// <param name="database"><see cref="AdoDataConnection"/> to connection to database.</param>
        /// <returns><see cref="ObservableCollection{T1}"/> type list of <see cref="Measurement"/>.</returns>
        public static ObservableCollection<Measurement> GetSubscribedMeasurements(AdoDataConnection database)
        {
            bool createdConnection = false;

            try
            {
                createdConnection = CreateConnection(ref database);

                ObservableCollection<Measurement> measurementList = new ObservableCollection<Measurement>();
                DataTable measurementTable;
                string query;

                query = database.ParameterizedQueryString("SELECT * FROM MeasurementDetail WHERE " +
                    "Subscribed = {0} ORDER BY PointTag", "subscribed");

                measurementTable = database.Connection.RetrieveData(database.AdapterType, query, DefaultTimeout, database.Bool(true));

                foreach (DataRow row in measurementTable.Rows)
                {
                    measurementList.Add(new Measurement
                    {
                        SignalID = database.Guid(row, "SignalID"),
                        HistorianID = row.ConvertNullableField<int>("HistorianID"),
                        PointID = row.ConvertField<int>("PointID"),
                        DeviceID = row.ConvertNullableField<int>("DeviceID"),
                        PointTag = row.Field<string>("PointTag"),
                        AlternateTag = row.Field<string>("AlternateTag"),
                        SignalTypeID = row.ConvertField<int>("SignalTypeID"),
                        PhasorSourceIndex = row.ConvertNullableField<int>("PhasorSourceIndex"),
                        SignalReference = row.Field<string>("SignalReference"),
                        Adder = row.ConvertField<double>("Adder"),
                        Multiplier = row.ConvertField<double>("Multiplier"),
                        Internal = Convert.ToBoolean(row.Field<object>("Internal")),
                        Subscribed = Convert.ToBoolean(row.Field<object>("Subscribed")),
                        Description = row.Field<string>("Description"),
                        Enabled = Convert.ToBoolean(row.Field<object>("Enabled")),
                        m_historianAcronym = row.Field<string>("HistorianAcronym"),
                        m_deviceAcronym = row.Field<object>("DeviceAcronym") == null ? string.Empty : row.Field<string>("DeviceAcronym"),
                        m_signalName = row.Field<string>("SignalName"),
                        m_signalAcronym = row.Field<string>("SignalAcronym"),
                        m_signalSuffix = row.Field<string>("SignalTypeSuffix"),
                        m_phasorLabel = row.Field<string>("PhasorLabel"),
                        m_framesPerSecond = Convert.ToInt32(row.Field<object>("FramesPerSecond") ?? 30),
                        m_id = row.Field<string>("ID"),
                        m_companyAcronym = row.Field<object>("CompanyAcronym") == null ? string.Empty : row.Field<string>("CompanyAcronym"),
                        m_companyName = row.Field<object>("CompanyName") == null ? string.Empty : row.Field<string>("CompanyName"),
                        Selected = false
                    });
                }

                return measurementList;
            }
            finally
            {
                if (createdConnection && database != null)
                    database.Dispose();
            }
        }

        /// <summary>
        /// Saves <see cref="Measurement"/> information to database.
        /// </summary>
        /// <param name="database"><see cref="AdoDataConnection"/> to connection to database.</param>
        /// <param name="measurement">Information about <see cref="Measurement"/>.</param>
        /// <returns>String, for display use, indicating success.</returns>
        public static string Save(AdoDataConnection database, Measurement measurement)
        {
            bool createdConnection = false;
            string query;

            try
            {
                createdConnection = CreateConnection(ref database);

                if (measurement.PointID == 0)
                {
                    query = database.ParameterizedQueryString("INSERT INTO Measurement (HistorianID, DeviceID, PointTag, AlternateTag, SignalTypeID, PhasorSourceIndex, " +
                        "SignalReference, Adder, Multiplier, Subscribed, Internal, Description, Enabled, UpdatedBy, UpdatedOn, CreatedBy, CreatedOn) VALUES ({0}, {1}, {2}, " +
                        "{3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {12}, {13}, {14}, {15}, {16})", "historianID", "deviceID", "pointTag", "alternateTag", "signalTypeID",
                        "phasorSourceIndex", "signalReference", "adder", "multiplier", "subscribed", "internal", "description", "enabled", "updatedBy", "updatedOn",
                        "createdBy", "createdOn");

                    database.Connection.ExecuteNonQuery(query, DefaultTimeout, measurement.HistorianID.ToNotNull(), measurement.DeviceID.ToNotNull(), measurement.PointTag,
                        measurement.AlternateTag.ToNotNull(), measurement.SignalTypeID, measurement.PhasorSourceIndex ?? measurement.PhasorSourceIndex.ToNotNull(), measurement.SignalReference,
                        measurement.Adder, measurement.Multiplier, database.Bool(measurement.Subscribed), database.Bool(measurement.Internal), measurement.Description.ToNotNull(),
                        database.Bool(measurement.Enabled), CommonFunctions.CurrentUser, database.UtcNow, CommonFunctions.CurrentUser, database.UtcNow);
                }
                else
                {
                    query = database.ParameterizedQueryString("UPDATE Measurement SET HistorianID = {0}, DeviceID = {1}, PointTag = {2}, AlternateTag = {3}, " +
                        "SignalTypeID = {4}, PhasorSourceIndex = {5}, SignalReference = {6}, Adder = {7}, Multiplier = {8}, Description = {9}, Subscribed = {10}, " +
                        "Internal = {11}, Enabled = {12}, UpdatedBy = {13}, UpdatedOn = {14} WHERE PointID = {15}", "historianID", "deviceID", "pointTag",
                        "alternateTag", "signalTypeID", "phasorSourceINdex", "signalReference", "adder", "multiplier", "description", "subscribed", "internal",
                        "enabled", "updatedBy", "updatedOn", "pointID");

                    database.Connection.ExecuteNonQuery(query, DefaultTimeout, measurement.HistorianID.ToNotNull(), measurement.DeviceID.ToNotNull(), measurement.PointTag,
                        measurement.AlternateTag.ToNotNull(), measurement.SignalTypeID, measurement.PhasorSourceIndex ?? measurement.PhasorSourceIndex.ToNotNull(), measurement.SignalReference,
                        measurement.Adder, measurement.Multiplier, measurement.Description.ToNotNull(), database.Bool(measurement.Subscribed), database.Bool(measurement.Internal),
                        database.Bool(measurement.Enabled), CommonFunctions.CurrentUser, database.UtcNow, measurement.PointID);
                }

                return "Measurement information saved successfully";
            }
            finally
            {
                if (createdConnection && database != null)
                    database.Dispose();
            }
        }

        /// <summary>
        /// Deletes specified <see cref="Measurement"/> record from database.
        /// </summary>
        /// <param name="database"><see cref="AdoDataConnection"/> to connection to database.</param>
        /// <param name="signalID">ID of the record to be deleted.</param>
        /// <returns>String, for display use, indicating success.</returns>
        public static string Delete(AdoDataConnection database, Guid signalID)
        {
            bool createdConnection = false;

            try
            {
                createdConnection = CreateConnection(ref database);

                // Setup current user context for any delete triggers
                CommonFunctions.SetCurrentUserContext(database);

                database.Connection.ExecuteNonQuery(database.ParameterizedQueryString("DELETE FROM Measurement WHERE SignalID = {0}", "signalID"), DefaultTimeout, database.Guid(signalID));

                return "Measurement deleted successfully";
            }
            finally
            {
                if (createdConnection && database != null)
                    database.Dispose();
            }
        }

        /// <summary>
        /// Retrieves a <see cref="Measurement"/> information from the database based on the signal ID of the measurement.
        /// </summary>
        /// <param name="database"><see cref="AdoDataConnection"/> to connection to database.</param>
        /// <param name="signalID">Signal ID of the measurement.</param>
        /// <returns><see cref="Measurement"/> information.</returns>
        public static Measurement GetMeasurement(AdoDataConnection database, Guid signalID)
        {
            bool createdConnection = false;
            DataTable measurementTable;
            DataRow row;

            try
            {
                createdConnection = CreateConnection(ref database);
                measurementTable = database.RetrieveData(DefaultTimeout, "SELECT * FROM MeasurementDetail WHERE SignalID = {0}", signalID);

                if (measurementTable.Rows.Count == 0)
                    return null;

                row = measurementTable.Rows[0];

                Measurement measurement = new Measurement()
                {
                    SignalID = database.Guid(row, "SignalID"),
                    HistorianID = row.ConvertNullableField<int>("HistorianID"),
                    PointID = row.ConvertField<int>("PointID"),
                    DeviceID = row.ConvertNullableField<int>("DeviceID"),
                    PointTag = row.Field<string>("PointTag"),
                    AlternateTag = row.Field<string>("AlternateTag"),
                    SignalTypeID = row.ConvertField<int>("SignalTypeID"),
                    PhasorSourceIndex = row.ConvertNullableField<int>("PhasorSourceIndex"),
                    SignalReference = row.Field<string>("SignalReference"),
                    Adder = row.ConvertField<double>("Adder"),
                    Multiplier = row.ConvertField<double>("Multiplier"),
                    Description = row.Field<string>("Description"),
                    Enabled = Convert.ToBoolean(row.Field<object>("Enabled")),
                    m_historianAcronym = row.Field<string>("HistorianAcronym"),
                    m_deviceAcronym = row.Field<object>("DeviceAcronym") == null ? string.Empty : row.Field<string>("DeviceAcronym"),
                    m_signalName = row.Field<string>("SignalName"),
                    m_signalAcronym = row.Field<string>("SignalAcronym"),
                    m_signalSuffix = row.Field<string>("SignalTypeSuffix"),
                    m_phasorLabel = row.Field<string>("PhasorLabel"),
                    m_framesPerSecond = Convert.ToInt32(row.Field<object>("FramesPerSecond") ?? 30),
                    m_id = row.Field<string>("ID"),
                    m_companyAcronym = row.Field<object>("CompanyAcronym") == null ? string.Empty : row.Field<string>("CompanyAcronym"),
                    m_companyName = row.Field<object>("CompanyName") == null ? string.Empty : row.Field<string>("CompanyName"),
                    Selected = false
                };

                return measurement;
            }
            finally
            {
                if (createdConnection && database != null)
                    database.Dispose();
            }
        }

        /// <summary>
        /// Retrieves a <see cref="Measurement"/> information from the database based on query string filter.
        /// </summary>
        /// <param name="database"><see cref="AdoDataConnection"/> to connection to database.</param>
        /// <param name="whereClause"><see cref="AdoDataConnection"/> to connection to database.</param>
        /// <returns><see cref="Measurement"/> information.</returns>
        public static Measurement GetMeasurement(AdoDataConnection database, string whereClause)
        {
            bool createdConnection = false;
            DataTable measurementTable;
            DataRow row;

            try
            {
                createdConnection = CreateConnection(ref database);
                measurementTable = database.Connection.RetrieveData(database.AdapterType, "SELECT * FROM MeasurementDetail " + whereClause);

                if (measurementTable.Rows.Count == 0)
                    return null;

                row = measurementTable.Rows[0];

                Measurement measurement = new Measurement
                {
                    SignalID = database.Guid(row, "SignalID"),
                    HistorianID = row.ConvertNullableField<int>("HistorianID"),
                    PointID = row.ConvertField<int>("PointID"),
                    DeviceID = row.ConvertNullableField<int>("DeviceID"),
                    PointTag = row.Field<string>("PointTag"),
                    AlternateTag = row.Field<string>("AlternateTag"),
                    SignalTypeID = row.ConvertField<int>("SignalTypeID"),
                    PhasorSourceIndex = row.ConvertNullableField<int>("PhasorSourceIndex"),
                    SignalReference = row.Field<string>("SignalReference"),
                    Adder = row.ConvertField<double>("Adder"),
                    Multiplier = row.ConvertField<double>("Multiplier"),
                    Description = row.Field<string>("Description"),
                    Enabled = Convert.ToBoolean(row.Field<object>("Enabled")),
                    m_historianAcronym = row.Field<string>("HistorianAcronym"),
                    m_deviceAcronym = row.Field<object>("DeviceAcronym") == null ? string.Empty : row.Field<string>("DeviceAcronym"),
                    m_signalName = row.Field<string>("SignalName"),
                    m_signalAcronym = row.Field<string>("SignalAcronym"),
                    m_signalSuffix = row.Field<string>("SignalTypeSuffix"),
                    m_phasorLabel = row.Field<string>("PhasorLabel"),
                    m_framesPerSecond = Convert.ToInt32(row.Field<object>("FramesPerSecond") ?? 30),
                    m_id = row.Field<string>("ID"),
                    m_companyAcronym = row.Field<object>("CompanyAcronym") == null ? string.Empty : row.Field<string>("CompanyAcronym"),
                    m_companyName = row.Field<object>("CompanyName") == null ? string.Empty : row.Field<string>("CompanyName"),
                    Selected = false
                };

                return measurement;
            }
            finally
            {
                if (createdConnection && database != null)
                    database.Dispose();
            }
        }

        /// <summary>
        /// Retrieves <see cref="ObservableCollection{T}"/> of <see cref="Measurement"/> based on the whereClause.
        /// </summary>
        /// <param name="database"><see cref="AdoDataConnection"/> to connection to database.</param>
        /// <param name="whereClause"><see cref="AdoDataConnection"/> to connection to database.</param>
        /// <returns><see cref="ObservableCollection{T}"/> type collection of <see cref="Measurement"/>.</returns>
        public static ObservableCollection<Measurement> GetMeasurements(AdoDataConnection database, string whereClause)
        {
            bool createdConnection = false;

            try
            {
                createdConnection = CreateConnection(ref database);
                ObservableCollection<Measurement> measurementList = new ObservableCollection<Measurement>();
                DataTable measurementTable = database.Connection.RetrieveData(database.AdapterType, "SELECT * FROM MeasurementDetail " + whereClause);
                foreach (DataRow row in measurementTable.Rows)
                {
                    measurementList.Add(new Measurement
                    {
                        SignalID = database.Guid(row, "SignalID"),
                        HistorianID = row.ConvertNullableField<int>("HistorianID"),
                        PointID = row.ConvertField<int>("PointID"),
                        DeviceID = row.ConvertNullableField<int>("DeviceID"),
                        PointTag = row.Field<string>("PointTag"),
                        AlternateTag = row.Field<string>("AlternateTag"),
                        SignalTypeID = row.ConvertField<int>("SignalTypeID"),
                        PhasorSourceIndex = row.ConvertNullableField<int>("PhasorSourceIndex"),
                        SignalReference = row.Field<string>("SignalReference"),
                        Adder = row.ConvertField<double>("Adder"),
                        Multiplier = row.ConvertField<double>("Multiplier"),
                        Internal = Convert.ToBoolean(row.Field<object>("Internal")),
                        Subscribed = Convert.ToBoolean(row.Field<object>("Subscribed")),
                        Description = row.Field<string>("Description"),
                        Enabled = Convert.ToBoolean(row.Field<object>("Enabled")),
                        m_historianAcronym = row.Field<string>("HistorianAcronym"),
                        m_deviceAcronym = row.Field<object>("DeviceAcronym") == null ? string.Empty : row.Field<string>("DeviceAcronym"),
                        m_signalName = row.Field<string>("SignalName"),
                        m_signalAcronym = row.Field<string>("SignalAcronym"),
                        m_signalSuffix = row.Field<string>("SignalTypeSuffix"),
                        m_phasorLabel = row.Field<string>("PhasorLabel"),
                        m_framesPerSecond = Convert.ToInt32(row.Field<object>("FramesPerSecond") ?? 30),
                        m_id = row.Field<string>("ID"),
                        m_companyAcronym = row.Field<object>("CompanyAcronym") == null ? string.Empty : row.Field<string>("CompanyAcronym"),
                        m_companyName = row.Field<object>("CompanyName") == null ? string.Empty : row.Field<string>("CompanyName"),
                        Selected = false
                    });
                }

                return measurementList;
            }
            finally
            {
                if (createdConnection && database != null)
                    database.Dispose();
            }
        }

        /// <summary>
        /// Retrieves unassigned measurements for output stream.
        /// </summary>
        /// <param name="database"><see cref="AdoDataConnection"/> to connection to database.</param>
        /// <param name="outputStreamID">ID of the output stream to filter data.</param>
        /// <returns><see cref="ObservableCollection{T}"/> type collection of Measurements.</returns>
        public static ObservableCollection<Measurement> GetNewOutputStreamMeasurements(AdoDataConnection database, int outputStreamID)
        {
            bool createdConnection = false;

            try
            {
                createdConnection = CreateConnection(ref database);
                ObservableCollection<Measurement> measurementList = new ObservableCollection<Measurement>();
                string query = database.ParameterizedQueryString("SELECT * FROM MeasurementDetail WHERE NodeID = {0} AND PointID NOT IN (SELECT PointID FROM OutputStreamMeasurement WHERE AdapterID = {1}) " +
                    "ORDER BY SignalReference", "nodeID", "outputStreamID");
                DataTable measurementTable = database.Connection.RetrieveData(database.AdapterType, query, DefaultTimeout, database.CurrentNodeID(), outputStreamID);

                foreach (DataRow row in measurementTable.Rows)
                {
                    if (row.Field<string>("SignalAcronym") != "STAT")
                    {
                        measurementList.Add(new Measurement
                        {
                            SignalID = database.Guid(row, "SignalID"),
                            HistorianID = row.ConvertNullableField<int>("HistorianID"),
                            PointID = row.ConvertField<int>("PointID"),
                            DeviceID = row.ConvertNullableField<int>("DeviceID"),
                            PointTag = row.Field<string>("PointTag"),
                            AlternateTag = row.Field<string>("AlternateTag"),
                            SignalTypeID = row.ConvertField<int>("SignalTypeID"),
                            PhasorSourceIndex = row.ConvertNullableField<int>("PhasorSourceIndex"),
                            SignalReference = row.Field<string>("SignalReference"),
                            Adder = row.ConvertField<double>("Adder"),
                            Multiplier = row.ConvertField<double>("Multiplier"),
                            Internal = Convert.ToBoolean(row.Field<object>("Internal")),
                            Subscribed = Convert.ToBoolean(row.Field<object>("Subscribed")),
                            Description = row.Field<string>("Description"),
                            Enabled = row.ConvertField<bool>("Enabled"),
                            m_historianAcronym = row.Field<string>("HistorianAcronym"),
                            m_deviceAcronym = row.Field<object>("DeviceAcronym") == null ? string.Empty : row.Field<string>("DeviceAcronym"),
                            m_signalName = row.Field<string>("SignalName"),
                            m_signalAcronym = row.Field<string>("SignalAcronym"),
                            m_signalSuffix = row.Field<string>("SignalTypeSuffix"),
                            m_phasorLabel = row.Field<string>("PhasorLabel"),
                            m_framesPerSecond = Convert.ToInt32(row.Field<object>("FramesPerSecond") ?? 30),
                            m_id = row.Field<string>("ID"),
                            m_companyAcronym = row.Field<object>("CompanyAcronym") == null ? string.Empty : row.Field<string>("CompanyAcronym"),
                            m_companyName = row.Field<object>("CompanyName") == null ? string.Empty : row.Field<string>("CompanyName"),
                            Selected = false
                        });
                    }
                }

                return measurementList;
            }
            finally
            {
                if (createdConnection && database != null)
                    database.Dispose();
            }
        }

        /// <summary>
        /// Retrieves statistic measurements for a device.
        /// </summary>
        /// <param name="database"><see cref="AdoDataConnection"/> to connection to database.</param>
        /// <param name="deviceID">ID of the device to filter data.</param>
        /// <returns><see cref="ObservableCollection{T}"/> type collection of Measurement.</returns>
        public static ObservableCollection<Measurement> GetInputStatisticMeasurements(AdoDataConnection database, int deviceID)
        {
            bool createdConnection = false;

            try
            {
                createdConnection = CreateConnection(ref database);
                ObservableCollection<Measurement> measurementList = new ObservableCollection<Measurement>();
                string query;
                DataTable measurementTable;

                if (deviceID == 0)
                {
                    query = database.ParameterizedQueryString("SELECT * FROM StatisticMeasurement WHERE NodeID = {0} AND DeviceID > 0 ORDER BY SignalReference", "nodeID");
                    measurementTable = database.Connection.RetrieveData(database.AdapterType, query, DefaultTimeout, database.CurrentNodeID());
                }
                else
                {
                    query = database.ParameterizedQueryString("SELECT * FROM StatisticMeasurement WHERE NodeID = {0} AND DeviceID = {1} ORDER BY SignalReference", "nodeID", "deviceID");
                    measurementTable = database.Connection.RetrieveData(database.AdapterType, query, DefaultTimeout, database.CurrentNodeID(), deviceID);
                }

                foreach (DataRow row in measurementTable.Rows)
                {
                    if (row.Field<string>("SignalAcronym") == "STAT") // Just one more filter.
                    {
                        measurementList.Add(new Measurement
                            {
                                SignalID = database.Guid(row, "SignalID"),
                                HistorianID = row.ConvertNullableField<int>("HistorianID"),
                                PointID = row.ConvertField<int>("PointID"),
                                DeviceID = row.ConvertNullableField<int>("DeviceID"),
                                PointTag = row.Field<string>("PointTag"),
                                AlternateTag = row.Field<string>("AlternateTag"),
                                SignalTypeID = row.ConvertField<int>("SignalTypeID"),
                                PhasorSourceIndex = row.ConvertNullableField<int>("PhasorSourceIndex"),
                                SignalReference = row.Field<string>("SignalReference"),
                                Adder = row.ConvertField<double>("Adder"),
                                Multiplier = row.ConvertField<double>("Multiplier"),
                                Internal = Convert.ToBoolean(row.Field<object>("Internal")),
                                Subscribed = Convert.ToBoolean(row.Field<object>("Subscribed")),
                                Description = row.Field<string>("Description"),
                                Enabled = row.ConvertField<bool>("Enabled"),
                                m_historianAcronym = row.Field<string>("HistorianAcronym"),
                                m_deviceAcronym = row.Field<object>("DeviceAcronym") == null ? string.Empty : row.Field<string>("DeviceAcronym"),
                                m_signalName = row.Field<string>("SignalName"),
                                m_signalAcronym = row.Field<string>("SignalAcronym"),
                                m_signalSuffix = row.Field<string>("SignalTypeSuffix"),
                                m_phasorLabel = row.Field<string>("PhasorLabel"),
                                m_framesPerSecond = Convert.ToInt32(row.Field<object>("FramesPerSecond") ?? 30),
                                m_id = row.Field<string>("ID"),
                                m_companyAcronym = row.Field<object>("CompanyAcronym") == null ? string.Empty : row.Field<string>("CompanyAcronym"),
                                m_companyName = row.Field<object>("CompanyName") == null ? string.Empty : row.Field<string>("CompanyName"),
                                Selected = false
                            });
                    }
                }

                return measurementList;
            }
            finally
            {
                if (createdConnection && database != null)
                    database.Dispose();
            }
        }

        /// <summary>
        /// Retrieves statistic measurements for output stream.
        /// </summary>
        /// <param name="database"><see cref="AdoDataConnection"/> to connection to database.</param>
        /// <param name="outputStreamAcronym">Acronym of the output stream to filter data.</param>
        /// <returns><see cref="ObservableCollection{T}"/> type collection of Measurement.</returns>
        public static ObservableCollection<Measurement> GetOutputStatisticMeasurements(AdoDataConnection database, string outputStreamAcronym)
        {
            bool createdConnection = false;

            try
            {
                createdConnection = CreateConnection(ref database);
                ObservableCollection<Measurement> measurementList = new ObservableCollection<Measurement>();

                string query = database.ParameterizedQueryString("SELECT * FROM StatisticMeasurement WHERE NodeID = {0} AND DeviceID IS NULL ORDER BY SignalReference", "nodeID");
                DataTable measurementTable = database.Connection.RetrieveData(database.AdapterType, query, DefaultTimeout, database.CurrentNodeID());

                foreach (DataRow row in measurementTable.Rows)
                {
                    if (row.Field<string>("SignalAcronym") == "STAT") // Just one more filter.
                    {
                        bool continueProcess = false;

                        if (!string.IsNullOrEmpty(outputStreamAcronym))
                        {
                            if (row.Field<string>("SignalReference").StartsWith(outputStreamAcronym + "!OS"))
                                continueProcess = true;
                        }
                        else
                        {
                            continueProcess = true;
                        }

                        if (continueProcess)
                        {
                            measurementList.Add(new Measurement
                            {
                                SignalID = database.Guid(row, "SignalID"),
                                HistorianID = row.ConvertNullableField<int>("HistorianID"),
                                PointID = row.ConvertField<int>("PointID"),
                                DeviceID = row.ConvertNullableField<int>("DeviceID"),
                                PointTag = row.Field<string>("PointTag"),
                                AlternateTag = row.Field<string>("AlternateTag"),
                                SignalTypeID = row.ConvertField<int>("SignalTypeID"),
                                PhasorSourceIndex = row.ConvertNullableField<int>("PhasorSourceIndex"),
                                SignalReference = row.Field<string>("SignalReference"),
                                Adder = row.ConvertField<double>("Adder"),
                                Multiplier = row.ConvertField<double>("Multiplier"),
                                Internal = Convert.ToBoolean(row.Field<object>("Internal")),
                                Subscribed = Convert.ToBoolean(row.Field<object>("Subscribed")),
                                Description = row.Field<string>("Description"),
                                Enabled = row.ConvertField<bool>("Enabled"),
                                m_historianAcronym = row.Field<string>("HistorianAcronym"),
                                m_deviceAcronym = row.Field<object>("DeviceAcronym") == null ? string.Empty : row.Field<string>("DeviceAcronym"),
                                m_signalName = row.Field<string>("SignalName"),
                                m_signalAcronym = row.Field<string>("SignalAcronym"),
                                m_signalSuffix = row.Field<string>("SignalTypeSuffix"),
                                m_phasorLabel = row.Field<string>("PhasorLabel"),
                                m_framesPerSecond = Convert.ToInt32(row.Field<object>("FramesPerSecond") ?? 30),
                                m_id = row.Field<string>("ID"),
                                m_companyAcronym = row.Field<object>("CompanyAcronym") == null ? string.Empty : row.Field<string>("CompanyAcronym"),
                                m_companyName = row.Field<object>("CompanyName") == null ? string.Empty : row.Field<string>("CompanyName"),
                                Selected = false
                            });
                        }
                    }
                }

                return measurementList;
            }
            finally
            {
                if (createdConnection && database != null)
                    database.Dispose();
            }
        }

        #endregion
    }
}


Ferrari driver calls European GP win one of the highlights of his career but says more work needed in pursuit of title.
Fernando Alonso's emotional comeback win at the European Grand Prix last Sunday has finally set one driver apart from the pack in the most tightly contested Formula One season in history.
Alonso steered his Ferrari from an 11th-place start to a dramatic victory at Valencia to become the first driver to win two races this year, opening up a 20-point gap over his nearest challenger, Red Bull's Mark Webber.
Now the Spaniard and his team are trying to focus on the British GP on July 8, when Alonso will seek to repeat his triumph at Silverstone last season.
"These 25 points will definitely not go to our heads,'' says Ferrari team principal Stefano Domenicali.
Alonso called the win in front of his home fans that featured a display of daring driving to pass various front-runners on the notoriously hard-to-overtake street circuit one of the best of his 29-win career. And becoming the sole driver with two victories in a season that saw seven different winners in the first seven races also gave him a commanding lead over the other major candidates for the title.
While Alonso collected the 25 points for the win, Lewis Hamilton and Sebastian Vettel failed to finish the race. After eight races Alonso has a 23-point lead over Hamilton, with Vettel a further three points behind the English driver.
Even so, the two-time champion was hesitant to claim he has taken control of the championship race.
!I think we always need to be cautious and we always need to be honest with ourselves first and with our supporters, saying that we will fight, will work day and night to be competitive and to fight for the title which is the ultimate goal for Ferrari,'' Alonso said.
Alonso's unexpected victory underscored why he is considered one of F1's best ever, but he reminded his followers - and team - that only managing 11th in Saturday's qualifying showed this year's Ferrari still needs improvement.
His teammate Felipe Massa struggled all weekend, qualifying 13th and then sliding to a 16th-place finish in the race.
"We were in 11th and 13th place, so we need to work,'' said Alonso.
If Ferrari still had doubts following its driver's big win, then McLaren and Red Bull had even larger ones.
Hamilton was heading for a decent points haul at Valencia, hanging onto third place, when Williams driver Pastor Maldonado bumped him off the track and out of the race on the penultimate lap. The incident overshadowed McLaren's own troubles that included fading pace down the stretch due to spent tires and a botched pit stop that cost Hamilton valuable seconds and positions.
"(It) was just a bad day in the office, but that's motor racing, and I'm already looking forward to the next grand prix, my home race at Silverstone,'' said Hamilton, who had gone into the Spanish race at the top of the points standings.
Vettel's concerns are surely deeper as the two-time defending champion looked set to claim his third straight win at the European GP after starting from pole and opening up a huge lead, but his Red Bull suddenly stalled midway through the race.
Just a few laps later Romain Grosjean's Lotus suffered a similar shutdown, robbing the young French pilot of a chance to finish on the podium.
Both cars are powered by Renault engines, suggesting a common cause.
"It was a bitterly disappointing race for Sebastian who had done everything right,'' said Red Bull team principal Christian Horner.
Red Bull leads the constructors title race with 176 points. McLaren has 137, Lotus 126 and Ferrari 122.


Women of Reform Judaism's Wilkenfeld International Women's Leadership Seminar is a leadership training program for women in Reform/Progressive congregations around the world who have been identified as potential emerging leaders. The 2018 seminar took place at the Saltz Center in Jerusalem. Participants had the opportunity to cultivate leadership skills, learned about the Reform/Progressive Movement across the globe at a deeper level, and established relationships with one another, with WRJ and with the World Union for Progressive Judaism. The group was comprised of 18 – 25 women, with representatives from a variety of the WUPJ regions, reflecting the diverse make-up of progressive Jewish congregations.
Learned the "why" and "how" of leadership.
Met Reform and Progressive Jewish women from around the world.
Developed skills that can be used in your own community.
Learn more about the 2018 Wilkenfeld Seminar participants.
This seminar was presented by Women of Reform Judaism (WRJ) in cooperation with the World Union for Progressive Judaism (WUPJ). The Israel Movement for Progressive Judaism (IMPJ) biennial conference took place immediately following the Wilkenfeld seminar and participants were encouraged to attend.
"I have already recommended it to a number of people…, this seminar provided me with an insight into the rest of the Jewish world, giving me a sense of connectivity that is vital to providing ongoing motivation and inspiration. … I cannot overstate how powerful and moving it was to be in a room full of other Jewish women. Seeing that we all have shared aims and empowering each other to continue forward was an experience that I will never forget."
"Hearing the other women speak about their leadership visions and about their communities (was the best) The organizing group consisted of very nice and very capable people. It was a pleasure to get to know them, and the seminar participants. I felt like I was in good hands."
"It was nice to meet with women from different countries with whom I was united by common challenges"
"All in all, I have understood the importance of developing my own clear, personal vision and goals, and the way to work together with others to achieve this and other project."
"[I would recommend this seminar to my friends] because it is great leadership training and I am convinced that such experience is very valuable for everyone who is in the leadership of the community."


We are delighted to offer for rent this well presented & deceptively spacious two bedroom end terrace property situated in the popular village of Byers Green. Enjoying off-road parking, the property is warmed by gas central heating and is double glazed throughout providing the perfect home within superb village location for a range of occupants. Internal viewing will reveal contemporary accommodation comprising of: Lounge, Dining Room & Kitchen with integrated cooking appliances to the Ground Floor. To the First Floor are Two Double Bedrooms and Family Bathroom with corner bath and separate shower cubicle. Externally there is a Yard to the Rear with gated access providing off-road parking.


This test tube jointed vase is perfect for the botanist in you. An elegant vessel for fresh cut flower or new sprouts not quite ready to pot! Makes a stunning centerpiece for your table or special occasion.


I am dealing with lmdb and lmdb is really fast . But one problem with it is lmdb isn't distributed . Everytime i need to do some maintenance , lmdb has to taken down and sites is unavailable for few hours . I researching on making lmdb a distributed one , implementing replication capabilites . So far the closest i have been close to it a dynomite code base by netflix .
I am out of clue how to approach it from lmdb perspective in python world , since code has to be written in python bindings also .
Any help will be greatly appreciated .
LMDB is meant to only be an embedded DB engine. Distribution/replication belong to a higher layer. You could use HyperDex with the LMDB backend, for example. https://github.com/hyc/HyperDex/tree/lmdb. There's also memcachedb built on LMDB, and ardb or ledisdb for redis-compatible servers running on top of LMDB.
So you could use them with dynomite if you want.
You can drop LMDB (embeded in ARDB) to replace Redis in Dynomite to make LMDB a distributed system. We have done a POC on this and they worked.
Not the answer you're looking for? Browse other questions tagged python distributed-database lmdb or ask your own question.
How to start at a specific step in a script?
How does one talk about comparing positions of characters in a string?
What is special about internal design of LMDB?


text:
Reading Jack Temple Kirby's "Media-Made Dixie" (1986)
Foster Dickson
Historian Jack Temple Kirby's 1986 book Media-Made Dixie focuses on how the overall image of the South, including the South's own understanding of itself, was created, to some extent, by portrayals in fiction, drama, film, television, music, and other popular media. The cover features the family photo from the TV show The Waltons – who could forget John Boy? – which aired from 1972 to 1981 and showed us the lives of a rural Virginia family during the Depression. Though the most of the book covers time periods that precede the scope of this project, reviewing those earlier images do lead to a better understanding of how modern myths and narratives since the 1970s are undergirded by images that already existed.
Kirby's subtitle here is "The South in the American Imagination," and his approach to the subject is different from the approach of Nobody's Home, which considers beliefs, myths, and narratives not as the products of scholarship but as the result of multitudinous everyday conversations among ordinary people— folklore. Kirby explains in his preface:
Pervading scholarship is an assumption that once the generation involved in an event has passed on, scholars control communication and understanding about the event. These historians have constructed without serious reflection or criticism a pyramidal model representing the transmission of historical knowledge: At prestigious history departments hypothesizing dons develop research and publish monographs and syntheses that break interpretive barriers.
I am more interested in how beliefs and narratives come from a constant, ongoing bottom-up reification of ideas, which inevitably includes evolutionary changes. Kirby describes more of a top-down endeavor, in which university-level scholars take up the mantle by interpreting events from those who leave them behind. The purpose then is crafting the understanding that gets perpetuated. Kirby and I might be arriving in the same place via different roads.
It is also important to share another section of Kirby's preface, where he informs us clearly of what he'll be covering:
. . . the main object of inquiry— popular historical images of the South since the advent of feature movies and annual bestseller lists. The object of this study is first simply to survey this imagery in mass communication media: films, bestselling fiction, documentary books and films, popular (i.e. nonacademic) histories, school texts, music, and television. Some attention is also given to radio, drama, sports, and to advertising through the printed and television media.
This seems cut-and-dried, though a massive subject for a relatively small book. But there is one extra thing to be aware of, as one begins reading: "by South," he writes, "I mean the white majority. " Because he is dealing with popular conceptions, not actual realities, the book will take that primary focus since "Americans typically intend southerner as descriptive of whites only." (Remember, this was 1986.)
Chapter one begins – where else? – with DW Griffith, the maker of Birth of a Nation and the son of a Confederate veteran, and we also meet a man less familiar in modern circles: Columbia University professor William A Dunning, a "northern man of southern sentiments who believed that an objective, 'balanced' history of the Civil War era required the southern white point of view." The way Kirby handles these two men, both were brilliant in their respective fields in addition to being pro-Southern, conservative, and racist. Griffith's film and Dunning's scholarship set up the model for interpreting the Civil War this way: "North-South reconciliation at the expense of blacks" and "Dixie as a superior breeding ground for physical courage." This kind of Lost Cause mythology prevailed for a long time but is currently the target of many scholars, activists, and leaders who prefer a more well-rounded, fact-based approach.
Next, we meet Claude Bowers, who "never went to college but wrote a shelf full of histories." According to Kirby, "more than anyone he educated Americans on their early national period," yet was one of many such writers who "rewrote" the history that they believed had been written to serve Northern economic and cultural interests. Bowers was a guy who "shared with his white contemporaries a swelling generosity towards Dixie" and who believed that we should "overcome bitterness, recognize the manly heroism of the rebels, and celebrate the new nationalism forged by the war and its aftermath."
With Griffith, Dunning, and Bowers in the rearview mirror, Kirby then moves into a three-pronged examination of the early to mid-20th century South: "The Embarrassing New South" in chapter three, "The Grand Old South" in chapter four, and "The Visceral South" in chapter five. The first of the three sees a marked shift in portrayals of the region, after a relative dry spell: "From 1916 through 1928, not a single book on a southern subject appeared on annual best seller lists." What emerged from that drought was a not a continued canonization of cavaliers and belles, but a degraded people worn down by poverty and moral destitution. The discussion includes the book-turned-film Cabin in the Cotton, as well as the novels of William Faulkner and Erskine Caldwell. Kirby then moves his attention, in chapter four, to another version of the South:
The quasi-Marxist, liberal-chic intellectualism of the late twenties and thirties, then, reinforced the embarrassing New South-grand Old South dichotomy. The mass-media managers, especially moviemakers, experimented as usual with genre, and discovered for themselves the cash power of that grand Old South.
This was the South of Gone with the Wind— the money-making image of the South in film and fiction, which required a disposal of the harsher realities to focus on carefree happiness and/or deeply involved drama. Finally, in chapter five, Kirby examines a third perspective. Here, he steps outside of the dichotomy to discuss WJ Cash's The Mind of the South, the country music of the Carter Family and Jimmie Rogers, and the plays of Tennessee Williams— all counterbalances to outsiders' notions of a "southern 'laziness'" that produces "happiness and at least the species of peace that lobotomies bring."
Chapter six, then, moves solidly into the middle 20th century with a collection of examples and ideas that involve portrayals of race and African Americans. We learn about the movie industry's connection to images of the South: "Thirty percent of American movie houses were located in the south, and Hollywood business people believed the 'southern market' could make or break a movie." This fact is built into a discussions of race relations, demagoguery, and "negrophobia," and reading it, I thought about how Hollywood maintained its imagery for the same reason that 19th- and early 20th-century Democrats let slavery and then Jim Crow go on unabated— you'll lose Southern support if you make an issue of it, so let it be and keep their support. Here, Kirby discusses the movies Pinky and Carmen Jones before moving on to novelists Frank Yerby and Harper Lee.
Next, in "The Devilish South," we see the Civil Rights era through a different lens. Kirby opens by mentioning race-focused historical and sociological publications by Gunnar Myrdal, C. Vann Woodward, and Kenneth Stampp as an introduction. But most people weren't reading those works, they were seeing movies, and . . .
Hollywood, in the meantime, moved very slowly toward a development of the neoabolitionist genre. The break with the Old South sentimentalist tradition which had sold so many movie tickets was difficult.
But 1950s Hollywood did produce films that moved beyond Gone with the Wind stereotypes: Band of Angels, Mandingo, and The Defiant Ones. These stories may have provoked more questions than they provided answers, but it was a shift in what Hollywood was showing to America, which pointed the way to movies Nothing but a Man and Slaves in the 1960s. To end the chapter, Kirby spends a good bit of space on white novelist William Styron's Confessions of Nat Turner, which was based on a real man from a 1830s slave revolt. Styron's heavily psychological narrative both uses historical facts and makes big assumptions about what this man would have been thinking and feeling. His approach, coupled with the time the novel was published, led to a great deal of controversy— some calling it a thought-provoking work that encouraged "soul-searching" among white people, others deriding it as wrongheaded and downright racist.
By the last two chapters, eight and nine, Kirby has moved into the time period covered by Nobody's Home. Chapter eight, titled "Dixie Redux and Demise," finds the South in the post-Civil Rights 1970s, when yet another type of imagery will become associated with it: advertising that used Southern imagery as symbolism for what is down-home and relaxing. This is a far cry from what Americans had just seen on TV for more than a decade, with racist whites using firehoses, dogs, beatings, lynchings, and bombs to combat racial equality. Yet, Kirby writes, "the message about the region was clear: the white South represents home, family, good old values." Instead of Bull Connor or Selma, think Kentucky Fried Chicken or Andy Griffith.
According to Kirby, many blacks also bought into this image and this idea that things had changed. He writes about a Gallup poll that found about half of American blacks and about two-thirds of Southern blacks believed that "the South is better for blacks." Attitudes among white Americans (including some Southerners) about the truths of history were changing, certainly, but not into a complete regard for the truth. Kirby refers to a 1974 book titled Time on the Cross that showed how most Southern whites now believed that slavery was simply an economic system whose negative effects on enslaved people was an unfortunate side-effect. Other myths that were commonly held included a denial that sexual exploitation of enslaved women was commonplace and an insistence that enslaved men were respected as heads of household in nuclear families.
On TV and in film, these mixed messages thrived. On the one hand, there were The Waltons, The Beverly Hillbillies, and The Andy Griffith Show, which showed the South as a harmless, albeit quirky place where tensions were mild. On the other hand, there were movies like Sounder, tick . . . tick . . . tick . . . , and The Liberation of Lord Byron Jones that showed inequality, racism, injustice, and hate in clear terms. Yet neither of those groupings would contain other people and works that Kirby mentions: the violent revenge film Walking Tall, the enlightened-white Conrack, and the often-unorthodox stylings of non-Nashville, often hippie-inspired country acts like Kris Kristofferson and David Allen Coe. If those example aren't enough to give a someone socio-historical whiplash, the chapter closes with brief discussions of the movies Nashville (a "three-hour-long bore") and Deliverance, which is of course famous for its homosexual rape scene. In the chapter's final paragraph, Kirby calls the South:
a media colony, an elsewhere for the American majority's amusement or negative example. Some Southerners have capitalized upon the imagery, reifying at times the most outrageous stereotypes. Yet colonials they remained, along with those of us who chafed and snarled at imperial manipulations.
He closes by stating that, when the North finally accepted the South as its own region, which occurred at least in part due to this stream of imagery, then the South "died" . . . but not completely.
Chapter nine gives Kirby's answer to question, If it died, then what? Remembering that the book was published thirty-six years ago, Kirby somewhat-dated summation is that modern mass media, now deeply ingrained in American culture, now has a full bag from which to pull images and tropes that viewers and readers will recognize and accept. He begins with the Dukes of Hazzard, which he tells us is a comedic combination of Tobacco Road and Thunder Road. In discussing Roots, he puts it in a context of how research and marketing have to meet in the middle to turn something true into something palatable. Later, he refers to President Jimmy Carter as "John-Boy Walton all grown up. Or better – considering his political partnership with blacks – he was a magisterial 'Conrack.""
But now, in the mid-1980s, we're still in that place where wildly disparate images form a whole variety of myths and beliefs about the South, even within the South itself. In Atlanta, there's the big shot Ted Turner who has produced a distinctly Southern television network. At the movies, we could see an Army sergeant face off with a corrupt small-town sheriff in Tank or a desperate farming family's struggle against nature in Places in the Heart. At the chapter ends, Kirby gives space the farming-focused Country and The River, neither of which has maintained its popularity, and finally, The Color Purple, which he defends vigorously. Ultimately, there is this:
This is, I believe, the emerging message of the South in the eighties: reconciliation within and without, between regions, races, and sexes. Reconciliation does not mean bland homogeneity, amalgamization, or passionless androgyny. It is merely a sure step towards every sane person's goal on this earth. Heaven, it has been said, can wait.
You can also read the editor's blog on another of Jack Temple Kirby's books, The Countercultural South.
Old Cloverdale, Montgomery, AL 36106, USA
This entry was posted in 1980s, Books, History, Society and tagged film, History, imagery, Jack Temple Kirby, Music, popular media, TV. Bookmark the permalink.
One thought on "Reading Jack Temple Kirby's "Media-Made Dixie" (1986)"
Pingback: The Editor's Reading List: Thirteen Done, Thirteen to Go – Nobody's Home

redpajama_set_name: RedPajamaCommonCrawl


The Nuffield Farming Conference was recently held in Newcastle Upon Tyne. Presenting his findings on "Alternatives to Antibiotics in Agriculture" was Aled Rhys Davies of Pruex.
Delegates learned of the issues of Antimicrobial Resistance (AMR), that have arisen from human misuse, but could well be blamed on agriculture unless the industry develop strategies to ensure prudent as opposed to excessive use of antibiotics. Aled stated that "We have evolved in line with bacteria, around 50% of a humans' body is made up of bacterial cells, so, we can't live without bacteria."
Cows with bad bacteria in their udders and high somatic cell counts.
Herd Screen is a product that forms part of a programme that ensures prudent use of antibiotics.


text:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="true"
          android:state_pressed="false" >
        <shape>
			<gradient android:startColor="#00c4f8" android:endColor="#00c4f8"/>
			<stroke android:width="2dp" android:color="#00333333" />
			<padding android:left="5dp" android:top="5dp"
				android:bottom="5dp" android:right="5dp"/>
		</shape>
    </item>
    <item android:state_focused="true"
          android:state_pressed="true">
        <shape>
	        <gradient android:startColor="#00c4f8" android:endColor="#00c4f8" />
	        <stroke android:width="2dp" android:color="#00000000" />
	        <padding android:left="5dp" android:top="5dp"
	            android:bottom="5dp" android:right="5dp"/>
	    </shape>
    </item>
    <item android:state_focused="false"
          android:state_pressed="true">
        <shape>
	        <gradient android:startColor="#00c4f8" android:endColor="#00c4f8" />
	        <stroke android:width="2dp" android:color="#00000000" />
	        <padding android:left="5dp" android:top="5dp"
	            android:bottom="5dp" android:right="5dp"/>
	    </shape>
    </item>
    <item android:state_selected="true">
        <shape>
	        <gradient android:startColor="#00c4f8" android:endColor="#00c4f8" />
	        <stroke android:width="2dp" android:color="#00000000" />
	        <padding android:left="5dp" android:top="5dp"
	            android:bottom="5dp" android:right="5dp"/>
	    </shape>
    </item>
    <item >
        <shape>
	        <gradient android:startColor="#00000000" android:endColor="#00000000" />
	        <stroke android:width="2dp" android:color="#00000000" />
	        <padding android:left="5dp" android:top="5dp"
	            android:bottom="5dp" android:right="5dp"/>
	    </shape>
    </item>
</selector>

redpajama_set_name: RedPajamaGithub