public static bool doesConditionUseQuestion(XPathsPartEntry xppe, conditions conditions, condition c, string questionID)
        {
            //List<xpathsXpath> xpaths = ConditionsPartEntry.getXPathsUsedInCondition(c, xppe);
            List<xpathsXpath> xpaths = new List<xpathsXpath>();
            c.listXPaths(xpaths, conditions, xppe.getXPaths());

            foreach (xpathsXpath xpathObj in xpaths)
            {

                String xpathVal = xpathObj.dataBinding.xpath;

                if (xpathVal.StartsWith("/"))
                {
                    // simple
                    //System.out.println("question " + xpathObj.getQuestionID()
                    //        + " is in use via boolean condition " + conditionId);
                    if (xpathObj.questionID.Equals(questionID))
                    {
                        return true;
                    }

                }
                else if (xpathVal.Contains("position"))
                {
                    continue;
                }
                else
                {
                    //System.out.println(xpathVal);

                    String qid = xpathVal.Substring(
                        xpathVal.LastIndexOf("@id") + 5);
                    //						System.out.println("Got qid: " + qid);
                    qid = qid.Substring(0, qid.IndexOf("'"));
                    //						System.out.println("Got qid: " + qid);

                    //System.out.println("question " + qid
                    //        + " is in use via condition " + conditionId);

                    if (qid.Equals(questionID))
                    {
                        return true;
                    }

                }
            }
            return false;
        }
        public FormCondition(Word.ContentControl cc, ConditionsPartEntry cpe, condition existingCondition)
        {
            InitializeComponent();

            // NET 4 way; see http://msdn.microsoft.com/en-us/library/microsoft.office.tools.word.extensions.aspx
            FabDocxState fabDocxState = (FabDocxState)Globals.Factory.GetVstoObject(Globals.ThisAddIn.Application.ActiveDocument).Tag;

            // NET 3.5 way, which requires using Microsoft.Office.Tools.Word.Extensions
            //FabDocxState fabDocxState = (FabDocxState)Globals.ThisAddIn.Application.ActiveDocument.GetVstoObject(Globals.Factory).Tag;
            this.model = fabDocxState.model;
            xppe = new XPathsPartEntry(model);

            this.cc = cc;

            this.cpe = cpe;
            this.existingCondition = existingCondition;

            this.questionsPart = model.questionsPart;
            questionnaire = new questionnaire();
            questionnaire.Deserialize(questionsPart.XML, out questionnaire);

            questionListHelper = new Helpers.QuestionListHelperForConditionsForm(model, xppe, questionnaire, cc);
            questionListHelper.listBoxTypeFilter = listBoxTypeFilter;
            questionListHelper.listBoxQuestions = listBoxQuestions;
            questionListHelper.checkBoxScope = checkBoxScope;

            questionListHelper.comboBoxValues = comboBoxValues;
            questionListHelper.listBoxPredicate = listBoxPredicate;

            this.listBoxQuestions.SelectedIndexChanged += new System.EventHandler(questionListHelper.listBoxQuestions_SelectedIndexChanged);
            this.listBoxTypeFilter.SelectedIndexChanged += new System.EventHandler(questionListHelper.listBoxTypeFilter_SelectedIndexChanged);

            question existingQuestion = null;
            string matchResponse = null;
            if (existingCondition != null)
            {
                // Use the question associated with it, to pre-select
                // the correct entries in the dialog.

                // Re-label the window, so user can see what the condition was about
                this.Text = "Editing Condition:   " + cc.Title;

                //List<xpathsXpath> xpaths = ConditionsPartEntry.getXPathsUsedInCondition(existingCondition, xppe);
                List<xpathsXpath> xpaths = new List<xpathsXpath>();
                existingCondition.listXPaths(xpaths, cpe.conditions, xppe.getXPaths());

                if (xpaths.Count > 1)
                {
                    // TODO: use complex conditions editor
                }
                xpathsXpath xpathObj = xpaths[0];

                String xpathVal = xpathObj.dataBinding.xpath;

                if (xpathVal.StartsWith("/"))
                {
                    // simple
                    //System.out.println("question " + xpathObj.getQuestionID()
                    //        + " is in use via boolean condition " + conditionId);

                    existingQuestion = this.questionnaire.getQuestion(xpathObj.questionID);
                    matchResponse = xpathVal;
                }
                else if (xpathVal.Contains("position"))
                {
                    // TODO
                }
                else
                {
                    //System.out.println(xpathVal);

                    String qid = xpathVal.Substring(
                        xpathVal.LastIndexOf("@id") + 5);
                    //						System.out.println("Got qid: " + qid);
                    qid = qid.Substring(0, qid.IndexOf("'"));
                    //						System.out.println("Got qid: " + qid);

                    //System.out.println("question " + qid
                    //        + " is in use via condition " + conditionId);

                    existingQuestion = this.questionnaire.getQuestion(qid);
                    matchResponse = xpathVal;

                }

            }

            questionListHelper.populateTypeFilter(true);

            if (existingQuestion == null)
            {
                // for init, populate with all questions
                questionListHelper.populateQuestions(null);
            }
            else
            {
                // Just show the existing question
                listBoxQuestions.Items.Add(existingQuestion);
            }

            if (this.listBoxQuestions.Items.Count == 0) // Never happens if in a repeat, and nor do we want it to, since user might just want to use "repeat pos" stuff
            {
                // Try including out of scope
                this.checkBoxScope.Checked = true;
                questionListHelper.populateQuestions(null);
                if (this.listBoxQuestions.Items.Count == 0)
                {
                    MessageBox.Show("You can't define a condition until you have set up at least one question. Let's do that now. ");

                    FormQA formQA = new FormQA(cc, false);
                    formQA.ShowDialog();
                    formQA.Dispose();

                    // Refresh these
                    xppe = new XPathsPartEntry(model);
                    questionnaire.Deserialize(questionsPart.XML, out questionnaire);

                    questionListHelper.filterAction();

                    return;
                }
            }
            // value
            question q;
            if (existingQuestion == null)
            {
                // for init, populate with all questions
                q = (question)this.listBoxQuestions.Items[0];
            }
            else
            {
                q = existingQuestion;
            }

            this.listBoxQuestions.SelectedItem = q;
            if (q.response.Item is responseFixed)
            {
                questionListHelper.populateValues((responseFixed)q.response.Item, matchResponse);
            }

            // predicate =
            questionListHelper.populatePredicates(q);  // TODO: set this correctly in editing mode
        }
        public FormRepeat(Office.CustomXMLPart questionsPart,
            Office.CustomXMLPart answersPart,
            Model model,
            Word.ContentControl cc)
        {
            InitializeComponent();

            this.model = model;
            this.cc = cc;

            this.questionsPart = questionsPart;
            questionnaire = new questionnaire();
            questionnaire.Deserialize(questionsPart.XML, out questionnaire);

            this.answersPart = answersPart;

            Office.CustomXMLNodes answers = answersPart.SelectNodes("//oda:repeat");
            foreach (Office.CustomXMLNode answer in answers)
            {
                this.answerID.Add(CustomXMLNodeHelper.getAttribute(answer, "qref")); // ID
            }

            // Suggest ID .. the idea is that
            // the question ID = answer ID.
               // this.ID = generateId();

            xppe = new XPathsPartEntry(model);
            // List of repeat names, for re-use purposes
            // (we need a map from repeat name (shown in the UI) to repeat id,
            //  which is xppe.xpathId).
            // What is it that distinguishes a repeat from any other question?
            // Answer: The fact that the XPath pointing to it ends with oda:row

            // Only show repeats which are in scope (since this repeat is not allowed elsewhere)
            // - if no ancestor repeat, then top level repeats.
            // - if there is an ancestor repeat, then just those which are direct children of it.
            Word.ContentControl rptAncestor = RepeatHelper.getYoungestRepeatAncestor(cc);
            String scope = "/oda:answers";
            if (rptAncestor != null)
            {
                // find its XPath
                scope = xppe.getXPathByID(  (new TagData(rptAncestor.Tag)).getRepeatID() ).dataBinding.xpath;

            }

            repeatNameToIdMap = new Dictionary<string, string>();
            foreach (xpathsXpath xpath in xppe.getXPaths().xpath)
            {
                if (xpath.dataBinding.xpath.EndsWith("oda:row"))
                {
                    if (isRepeatInScope(scope, xpath.dataBinding.xpath)) {
                        // the repeat "name" is its question text.
                        // Get that.
                        question q = questionnaire.getQuestion(xpath.questionID);
                        repeatNameToIdMap.Add(q.text, xpath.id);
                    }
                }
            }
            // Populate the comboBox
            foreach(KeyValuePair<String,String> entry in repeatNameToIdMap)
            {
                this.comboBoxRepeatNames.Items.Add(entry.Key);
            }
        }
        private void injectLogicXPath(XPathsPartEntry targetXppe, xpathsXpath xp, string sourceAttr, string answersPartStoreID)
        {
            if (sourceAttr != null) xp.source = sourceAttr;

            if (answersPartStoreID != null)
            {
                xp.dataBinding.storeItemID = answersPartStoreID;
            }

            targetXppe.getXPaths().xpath.Add(xp);  // this is a HashSet, so we're overrwriting, not adding :-)
        }