/// <summary>
        /// Add the condition to the conditions part.
        /// </summary>
        /// <param name="model"></param>
        /// <param name="cxpId"></param>
        /// <param name="strXPath"></param>
        /// <param name="prefixMappings"></param>
        public condition setup(xpathsXpath xpath)
        {
            condition result = null;

            //////////////////////////
            // Second, create and add the condition

            // If the Condition is already defined in our Condition part, don't do it again.
            // Also need this for ID generation.


            Dictionary <string, string> conditionsById = new Dictionary <string, string>();

            foreach (condition xx in conditions.condition)
            {
                conditionsById.Add(xx.id, "");
                if (xx.Item is xpathref)
                {
                    xpathref ex = (xpathref)xx.Item;

                    if (ex.id.Equals(xpath.id))
                    {
                        result = xx;
                        log.Info("This Condition is already setup, with ID: " + xx.id);
                        break;
                    }
                }
            }



            if (result == null) // not already defined
            {
                // Add the new condition
                result = new condition();
                //result.id = IdGenerator.generateIdForXPath(conditionsById, null, null, xpath.dataBinding.xpath);
                result.id = IdHelper.GenerateShortID(5);

                xpathref xpathref = new xpathref();
                xpathref.id = xpath.id;

                result.Item = xpathref;

                conditions.condition.Add(result);

                // Save the conditions in docx
                string ser = conditions.Serialize();
                log.Info(ser);
                CustomXmlUtilities.replaceXmlDoc(model.conditionsPart, ser);
            }

            // Set this
            conditionId = result.id;

            log.Debug("Condition written!");

            return(result);
        }
        public static void editXPath(Word.ContentControl cc)
        {
            Word.Document document = Globals.ThisAddIn.Application.ActiveDocument;
            object        missing  = System.Type.Missing;

            // First, work out whether this is a condition or a repeat or a plain bind
            bool isCondition = false;
            bool isRepeat    = false;
            bool isBind      = false;

            if ((cc.Title != null && cc.Title.StartsWith("Condition")) ||
                (cc.Tag != null && cc.Tag.Contains("od:condition")))
            {
                isCondition = true;
            }
            else if ((cc.Title != null && cc.Title.StartsWith("Repeat")) ||
                     (cc.Tag != null && cc.Tag.Contains("od:repeat")))
            {
                isRepeat = true;
            }
            else if ((cc.Title != null && cc.Title.StartsWith("Data")) ||
                     (cc.Tag != null && cc.Tag.Contains("od:xpath")) ||
                     cc.XMLMapping.IsMapped
                     )
            {
                isBind = true;
            }
            else
            {
                // Ask user
                using (Forms.ConditionOrRepeat cor = new Forms.ConditionOrRepeat())
                {
                    if (cor.ShowDialog() == DialogResult.OK)
                    {
                        isCondition = cor.radioButtonCondition.Checked;
                        isRepeat    = cor.radioButtonRepeat.Checked;
                        isBind      = cor.radioButtonBind.Checked;
                    }
                    else
                    {
                        // They cancelled
                        return;
                    }
                }
            }

            // OK, now we know whether its a condition or a repeat or a bind
            // Is it already mapped to something?
            TagData td    = new TagData(cc.Tag);
            Model   model = Model.ModelFactory(document);

            string strXPath = "";

            // In order to get Id and prefix mappings for current part
            CustomTaskPane ctpPaneForThisWindow = Utilities.FindTaskPaneForCurrentWindow();

            Controls.ControlMain ccm = (Controls.ControlMain)ctpPaneForThisWindow.Control;

            string cxpId          = ccm.CurrentPart.Id;
            string prefixMappings = ""; // TODO GetPrefixMappings(ccm.CurrentPart.NamespaceManager);

            log.Debug("default prefixMappings: " + prefixMappings);

            XPathsPartEntry     xppe = null;
            ConditionsPartEntry cpe  = null;

            if (isCondition &&
                td.get("od:condition") != null)
            {
                string conditionId = td.get("od:condition");
                cpe = new ConditionsPartEntry(model);
                condition c = cpe.getConditionByID(conditionId);

                string xpathid = null;
                if (c != null &&
                    c.Item is xpathref)
                {
                    xpathref ex = (xpathref)c.Item;
                    xpathid = ex.id;

                    // Now fetch the XPath
                    xppe = new XPathsPartEntry(model);

                    xpathsXpath xx = xppe.getXPathByID(xpathid);

                    if (xx != null)
                    {
                        strXPath       = xx.dataBinding.xpath;
                        cxpId          = xx.dataBinding.storeItemID;
                        prefixMappings = xx.dataBinding.prefixMappings;
                    }
                }
            }
            else if (isRepeat &&
                     td.get("od:repeat") != null)
            {
                string repeatId = td.get("od:repeat");

                // Now fetch the XPath
                xppe = new XPathsPartEntry(model);

                xpathsXpath xx = xppe.getXPathByID(repeatId);

                if (xx != null)
                {
                    strXPath       = xx.dataBinding.xpath;
                    cxpId          = xx.dataBinding.storeItemID;
                    prefixMappings = xx.dataBinding.prefixMappings;
                }
            }
            else if (isBind)
            {
                if (cc.XMLMapping.IsMapped)
                {
                    // Prefer this, if for some reason it contradicts od:xpath
                    strXPath       = cc.XMLMapping.XPath;
                    cxpId          = cc.XMLMapping.CustomXMLPart.Id;
                    prefixMappings = cc.XMLMapping.PrefixMappings;
                }
                else if (td.get("od:xpath") != null)
                {
                    string xpathId = td.get("od:xpath");

                    // Now fetch the XPath
                    xppe = new XPathsPartEntry(model);

                    xpathsXpath xx = xppe.getXPathByID(xpathId);

                    if (xx != null)
                    {
                        strXPath       = xx.dataBinding.xpath;
                        cxpId          = xx.dataBinding.storeItemID;
                        prefixMappings = xx.dataBinding.prefixMappings;
                    }
                }
            }

            // Now we can present the form
            using (Forms.XPathEditor xpe = new Forms.XPathEditor())
            {
                xpe.textBox1.Text = strXPath;
                if (xpe.ShowDialog() == DialogResult.OK)
                {
                    strXPath = xpe.textBox1.Text;
                }
                else
                {
                    // They cancelled
                    return;
                }
            }

            // Now give effect to it
            td = new TagData("");
            if (isCondition)
            {
                // Create the new condition. Doesn't attempt to delete
                // the old one (if any)
                if (cpe == null)
                {
                    cpe = new ConditionsPartEntry(model);
                }
                cpe.setup(cxpId, strXPath, prefixMappings, true);
                cpe.save();

                cc.Title = "Conditional: " + cpe.conditionId;
                // Write tag
                td.set("od:condition", cpe.conditionId);
                cc.Tag = td.asQueryString();
            }
            else if (isRepeat)
            {
                // Create the new repeat. Doesn't attempt to delete
                // the old one (if any)
                if (xppe == null)
                {
                    xppe = new XPathsPartEntry(model);
                }

                xppe.setup("rpt", cxpId, strXPath, prefixMappings, false);
                xppe.save();

                cc.Title = "Repeat: " + xppe.xpathId;
                // Write tag
                td.set("od:repeat", xppe.xpathId);
                cc.Tag = td.asQueryString();
            }
            else if (isBind)
            {
                // Create the new bind. Doesn't attempt to delete
                // the old one (if any)
                if (xppe == null)
                {
                    xppe = new XPathsPartEntry(model);
                }

                Word.XMLMapping bind     = cc.XMLMapping;
                bool            mappable = false;
                try
                {
                    mappable = bind.SetMapping(strXPath, prefixMappings,
                                               CustomXmlUtilities.getPartById(document, cxpId));
                }
                catch (COMException ce)
                {
                    if (ce.Message.Contains("Data bindings cannot be created for rich text content controls"))
                    {
                        // TODO: editing a rich text control
                        // TODO manually check whether it is mappable
                        // So for now,
                        cc.Delete(true);
                        cc = document.ContentControls.Add(
                            Word.WdContentControlType.wdContentControlText, ref missing);
                        mappable = cc.XMLMapping.SetMapping(strXPath, prefixMappings,
                                                            CustomXmlUtilities.getPartById(document, cxpId));
                    }
                    else
                    {
                        log.Error(ce);
                        //What to do??
                    }
                }
                if (mappable)
                {
                    // What does the XPath point to?
                    string val = cc.XMLMapping.CustomXMLNode.Text;

                    cc.Title = "Data value: " + xppe.xpathId;

                    if (ContentDetection.IsBase64Encoded(val))
                    {
                        // Force picture content control ...
                        // cc.Type = Word.WdContentControlType.wdContentControlPicture;
                        // from wdContentControlText (or wdContentControlRichText for that matter)
                        // doesn't work (you get "inappropriate range for applying this
                        // content control type").

                        cc.Delete(true);

                        // Now add a new cc
                        Globals.ThisAddIn.Application.Selection.Collapse(ref missing);

                        bool   _PictureContentControlsReplace = true;
                        String picSetting = System.Configuration.ConfigurationManager.AppSettings["ContentControl.Picture.RichText.Override"];
                        if (picSetting != null)
                        {
                            Boolean.TryParse(picSetting, out _PictureContentControlsReplace);
                        }

                        if (_PictureContentControlsReplace)
                        {
                            // Use a rich text control instead
                            cc = document.ContentControls.Add(
                                Word.WdContentControlType.wdContentControlRichText, ref missing);

                            PictureUtils.setPictureHandler(td);
                            cc.Title = "Image: " + xppe.xpathId;

                            PictureUtils.pastePictureIntoCC(cc, Convert.FromBase64String(val));
                        }
                        else
                        {
                            cc = document.ContentControls.Add(
                                Word.WdContentControlType.wdContentControlPicture, ref missing);

                            cc.XMLMapping.SetMapping(strXPath, prefixMappings,
                                                     CustomXmlUtilities.getPartById(document, cxpId));
                        }
                    }
                    else if (ContentDetection.IsFlatOPCContent(val))
                    {
                        // <?mso-application progid="Word.Document"?>
                        // <pkg:package xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage">

                        td.set("od:progid", "Word.Document");
                        cc.Tag = td.asQueryString();

                        cc.XMLMapping.Delete();
                        cc.Type  = Word.WdContentControlType.wdContentControlRichText;
                        cc.Title = "Word: " + xppe.xpathId;
                        //cc.Range.Text = val; // don't escape it

                        Inline2Block i2b = new Inline2Block();
                        cc = i2b.convertToBlockLevel(cc, false, true);

                        if (cc == null)
                        {
                            MessageBox.Show("Problems inserting block level WordML at this location.");
                            return;
                        }

                        cc.Range.InsertXML(val, ref missing);
                    }
                    else if (ContentDetection.IsXHTMLContent(val))
                    {
                        td.set("od:ContentType", "application/xhtml+xml");
                        cc.Tag = td.asQueryString();

                        cc.XMLMapping.Delete();
                        cc.Type  = Word.WdContentControlType.wdContentControlRichText;
                        cc.Title = "XHTML: " + xppe.xpathId;

                        if (Inline2Block.containsBlockLevelContent(val))
                        {
                            Inline2Block i2b = new Inline2Block();
                            cc = i2b.convertToBlockLevel(cc, true, true);

                            if (cc == null)
                            {
                                MessageBox.Show("Problems inserting block level XHTML at this location.");
                                return;
                            }
                        }
                    }

                    xppe.setup(null, cxpId, strXPath, prefixMappings, true);
                    xppe.save();

                    td.set("od:xpath", xppe.xpathId);

                    cc.Tag = td.asQueryString();
                }
                else
                {
                    xppe.setup(null, cxpId, strXPath, prefixMappings, true);
                    xppe.save();

                    td.set("od:xpath", xppe.xpathId);

                    cc.Title = "Data value: " + xppe.xpathId;
                    cc.Tag   = td.asQueryString();

                    // FIXME TODO handle pictures/FlatOPC/XHTML in this case

                    log.Warn(" XPath \n\r " + strXPath
                             + "\n\r does not return an element. The OpenDoPE pre-processor will attempt to evaluate it, but Word will never update the result. ");
                    bind.Delete();
                    MessageBox.Show(" XPath \n\r " + strXPath
                                    + "\n\r does not return an element. Check this is what you want? ");
                }
            }
        }