/// <summary>
        /// Clears any existing relations when deleting a node with a PickerRelations datatype
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="umbraco.cms.businesslogic.DeleteEventArgs"/> instance containing the event data.</param>
        private void BeforeDelete(Content sender, DeleteEventArgs e)
        {
            Guid pickerRelationsId = new Guid(DataTypeGuids.PickerRelationsId);

            // Clean up any relations

            // For each PickerRelations datatype
            foreach (Property pickerRelationsProperty in from property in sender.GenericProperties
                     where property.PropertyType.DataTypeDefinition.DataType.Id == pickerRelationsId
                     select property)
            {
                // used to identify this datatype instance - relations created are marked with this in the comment field
                string instanceIdentifier = "[\"PropertyTypeId\":" + pickerRelationsProperty.PropertyType.Id.ToString() + "]";

                // get configuration options for datatype
                PickerRelationsOptions options = ((PickerRelationsPreValueEditor)pickerRelationsProperty.PropertyType.DataTypeDefinition.DataType.PrevalueEditor).Options;

                // get relationType from options
                RelationType relationType = RelationType.GetById(options.RelationTypeId);

                if (relationType != null)
                {
                    // clear all exisitng relations
                    DeleteRelations(relationType, sender.Id, options.ReverseIndexing, instanceIdentifier);
                }
            }
        }
        /////// NOT CURRENTLY USED, BUT MIGHT BE USEFUL TO MARK BIDIRECTIONAL RELATIONS
        /////// <summary>
        /////// string to identify a particular instance of this datatype
        /////// </summary>
        ////private string InstanceIdentifier
        ////{
        ////    get
        ////    {
        ////        Property pickerRelationsProperty = new Property(((DefaultData)this.data).PropertyId);
        ////        return "[" + pickerRelationsProperty.PropertyType.Id.ToString() + "]";
        ////    }
        ////}

        /// <summary>
        /// Initializes a new instance of PickerRelationsDataEditor
        /// </summary>
        /// <param name="data">data stored by this instance of this datatype (not currently used)</param>
        /// <param name="options">configuration options for this datatype as set by the PreValueEditor</param>
        internal PickerRelationsDataEditor(IData data, PickerRelationsOptions options)
        {
            this.data = data;
            this.options = options;
        }
        /// <summary>
        /// Event after all properties have been saved
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AfterSave(Content sender, SaveEventArgs e)
        {
            Guid pickerRelationsId = new Guid(DataTypeGuids.PickerRelationsId);

            // For each PickerRelations datatype
            foreach (Property pickerRelationsProperty in from property in sender.GenericProperties
                     where property.PropertyType.DataTypeDefinition.DataType.Id == pickerRelationsId
                     select property)
            {
                // used to identify this datatype instance - relations created are marked with this in the comment field
                string instanceIdentifier = "[\"PropertyTypeId\":" + pickerRelationsProperty.PropertyType.Id.ToString() + "]";

                // get configuration options for datatype
                PickerRelationsOptions options = ((PickerRelationsPreValueEditor)pickerRelationsProperty.PropertyType.DataTypeDefinition.DataType.PrevalueEditor).Options;

                // find Picker source propertyAlias field on sender
                Property pickerProperty = sender.getProperty(options.PropertyAlias);

                if (pickerProperty != null)
                {
                    // get relationType from options
                    RelationType relationType = RelationType.GetById(options.RelationTypeId);

                    if (relationType != null)
                    {
                        // validate: 1) check current type of sender matches that expected by the relationType, validation method is in the DataEditor
                        uQuery.UmbracoObjectType contextObjectType = uQuery.UmbracoObjectType.Unknown;
                        switch (sender.GetType().ToString())
                        {
                        case "umbraco.cms.businesslogic.web.Document": contextObjectType = uQuery.UmbracoObjectType.Document; break;

                        case "umbraco.cms.businesslogic.media.Media": contextObjectType = uQuery.UmbracoObjectType.Media; break;

                        case "umbraco.cms.businesslogic.member.Member": contextObjectType = uQuery.UmbracoObjectType.Member; break;
                        }

                        if (((PickerRelationsDataEditor)pickerRelationsProperty.PropertyType.DataTypeDefinition.DataType.DataEditor)
                            .IsContextUmbracoObjectTypeValid(contextObjectType, relationType))
                        {
                            uQuery.UmbracoObjectType pickerUmbracoObjectType = uQuery.UmbracoObjectType.Unknown;

                            // Get the object type expected by the associated relation type and if this datatype has been configures as a rever index
                            pickerUmbracoObjectType = ((PickerRelationsDataEditor)pickerRelationsProperty.PropertyType.DataTypeDefinition.DataType.DataEditor)
                                                      .GetPickerUmbracoObjectType(relationType);


                            // clear all exisitng relations (or look to see previous verion of sender to delete changes ?)
                            DeleteRelations(relationType, sender.Id, options.ReverseIndexing, instanceIdentifier);

                            string pickerPropertyValue = pickerProperty.Value.ToString();

                            var pickerStorageFormat = PickerStorageFormat.Csv;                             // Assume default of csv

                            if (xmlHelper.CouldItBeXml(pickerPropertyValue))
                            {
                                pickerStorageFormat = PickerStorageFormat.Xml;
                            }

                            // Creating instances of Documents / Media / Members ensures the IDs are of a valid type - be quicker to check with GetUmbracoObjectType(int)
                            Dictionary <int, string> pickerItems = null;
                            switch (pickerUmbracoObjectType)
                            {
                            case uQuery.UmbracoObjectType.Document:
                                switch (pickerStorageFormat)
                                {
                                case PickerStorageFormat.Csv:
                                    pickerItems = uQuery.GetDocumentsByCsv(pickerPropertyValue).ToNameIds();
                                    break;

                                case PickerStorageFormat.Xml:
                                    pickerItems = uQuery.GetDocumentsByXml(pickerPropertyValue).ToNameIds();
                                    break;
                                }

                                break;

                            case uQuery.UmbracoObjectType.Media:
                                switch (pickerStorageFormat)
                                {
                                case PickerStorageFormat.Csv:
                                    pickerItems = uQuery.GetMediaByCsv(pickerPropertyValue).ToNameIds();
                                    break;

                                case PickerStorageFormat.Xml:
                                    pickerItems = uQuery.GetMediaByXml(pickerPropertyValue).ToNameIds();
                                    break;
                                }
                                break;

                            case uQuery.UmbracoObjectType.Member:
                                switch (pickerStorageFormat)
                                {
                                case PickerStorageFormat.Csv:
                                    pickerItems = uQuery.GetMembersByCsv(pickerPropertyValue).ToNameIds();
                                    break;

                                case PickerStorageFormat.Xml:
                                    pickerItems = uQuery.GetMembersByXml(pickerPropertyValue).ToNameIds();
                                    break;
                                }
                                break;
                            }
                            if (pickerItems != null)
                            {
                                foreach (KeyValuePair <int, string> pickerItem in pickerItems)
                                {
                                    CreateRelation(relationType, sender.Id, pickerItem.Key, options.ReverseIndexing, instanceIdentifier);
                                }
                            }
                        }
                        else
                        {
                            // Error: content object type invalid with relation type
                        }
                    }
                    else
                    {
                        // Error: relation type is null
                    }
                }
                else
                {
                    // Error: pickerProperty alias not found
                }
            }
        }
        /////// NOT CURRENTLY USED, BUT MIGHT BE USEFUL TO MARK BIDIRECTIONAL RELATIONS
        /////// <summary>
        /////// string to identify a particular instance of this datatype
        /////// </summary>
        ////private string InstanceIdentifier
        ////{
        ////    get
        ////    {
        ////        Property pickerRelationsProperty = new Property(((DefaultData)this.data).PropertyId);
        ////        return "[" + pickerRelationsProperty.PropertyType.Id.ToString() + "]";
        ////    }
        ////}

        /// <summary>
        /// Initializes a new instance of PickerRelationsDataEditor
        /// </summary>
        /// <param name="data">data stored by this instance of this datatype (not currently used)</param>
        /// <param name="options">configuration options for this datatype as set by the PreValueEditor</param>
        internal PickerRelationsDataEditor(IData data, PickerRelationsOptions options)
        {
            this.data    = data;
            this.options = options;
        }