<commit_before>/**
 *  Copyright (C) 2006 Orbeon, Inc.
 *
 *  This program is free software; you can redistribute it and/or modify it under the terms of the
 *  GNU Lesser General Public License as published by the Free Software Foundation; either version
 *  2.1 of the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *  See the GNU Lesser General Public License for more details.
 *
 *  The full text of the license is available at http://www.gnu.org/copyleft/lesser.html
 */
package org.orbeon.oxf.xforms;

import org.dom4j.Attribute;
import org.dom4j.Element;
import org.dom4j.Node;
import org.orbeon.oxf.pipeline.api.PipelineContext;
import org.orbeon.oxf.xforms.control.controls.RepeatIterationControl;
import org.orbeon.oxf.xforms.control.XFormsControl;
import org.orbeon.oxf.xforms.control.controls.XFormsRepeatControl;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Utilities related to xforms:switch.
 */
public class XFormsSwitchUtils {

    public static boolean prepareSwitches(PipelineContext pipelineContext, XFormsControls xformsControls) {
        // Store temporary switch information into appropriate nodes
        boolean found = false;
        for (Iterator i = xformsControls.getCurrentControlsState().getSwitchIdToSelectedCaseIdMap().entrySet().iterator(); i.hasNext();) {
            final Map.Entry entry = (Map.Entry) i.next();
            final String switchId = (String) entry.getKey();

//            System.out.println("xxx 1: switch id: " + switchId);

            if (switchId.indexOf(XFormsConstants.REPEAT_HIERARCHY_SEPARATOR_1) != -1) {
                // This switch id may be affected by this insertion

//                System.out.println("xxx 1: has separator");

                final XFormsControl switchXFormsControl = (XFormsControl) xformsControls.getObjectById(switchId);
                XFormsControl parent = switchXFormsControl;
                while ((parent = parent.getParent()) != null) {
                    if (parent instanceof RepeatIterationControl) {
                        // Found closest enclosing repeat iteration

                        final RepeatIterationControl repeatIterationInfo = (RepeatIterationControl) parent;
                        final XFormsRepeatControl repeatControlInfo = (XFormsRepeatControl) repeatIterationInfo.getParent();

                        final List currentNodeset = repeatControlInfo.getBindingContext().getNodeset();

                        final Node node = (Node) currentNodeset.get(repeatIterationInfo.getIteration() - 1);
                        final InstanceData instanceData = XFormsUtils.getLocalInstanceData(node);

                        // Store an original case id instead of an effective case id
                        final String caseId = (String) entry.getValue();
                        instanceData.addSwitchIdToCaseId(switchXFormsControl.getOriginalId(), caseId.substring(0, caseId.indexOf(XFormsConstants.REPEAT_HIERARCHY_SEPARATOR_1)));

//                        System.out.println("xxx 1: adding case id " + switchControlInfo.getOriginalId() + " " + entry.getValue());

                        found = true;

                        break;
                    }
                }
            }
        }
        return found;
    }

    public static void prepareSwitches(PipelineContext pipelineContext, XFormsControls xformsControls, Node sourceElement, Node clonedElement) {
        final boolean found = prepareSwitches(pipelineContext, xformsControls);
        if (found) {
            // Propagate temporary switch information to new nodes
            copySwitchInfo(sourceElement, clonedElement);
        }
    }

    private static void copySwitchInfo(Node sourceNode, Node destNode) {

        final InstanceData sourceInstanceData = XFormsUtils.getLocalInstanceData(sourceNode);
        final InstanceData destInstanceData = XFormsUtils.getLocalInstanceData(destNode);
        destInstanceData.setSwitchIdsToCaseIds(sourceInstanceData.getSwitchIdsToCaseIds());

        if (sourceNode instanceof Element) {
            final Element sourceElement = (Element) sourceNode;
            final Element destElement = (Element) destNode;
            // Recurse over attributes
            {
                final Iterator j = destElement.attributes().iterator();
                for (Iterator i = sourceElement.attributes().iterator(); i.hasNext();) {
                    final Attribute sourceAttribute = (Attribute) i.next();
                    final Attribute destAttribute = (Attribute) j.next();

                    final InstanceData sourceAttributeInstanceData = XFormsUtils.getLocalInstanceData(sourceAttribute);
                    final InstanceData destAttributeInstanceData = XFormsUtils.getLocalInstanceData(destAttribute);

                    destAttributeInstanceData.setSwitchIdsToCaseIds(sourceAttributeInstanceData.getSwitchIdsToCaseIds());
                }
            }
            // Recurse over children elements
            {
                final Iterator j = destElement.elements().iterator();
                for (Iterator i = sourceElement.elements().iterator(); i.hasNext();) {
                    final Element sourceChild = (Element) i.next();
                    final Element destChild = (Element) j.next();
                    copySwitchInfo(sourceChild, destChild);
                }
            }
        }
    }

    public static void updateSwitches(PipelineContext pipelineContext, XFormsControls xformsControls) {
        for (Iterator i = xformsControls.getCurrentControlsState().getSwitchIdToSelectedCaseIdMap().entrySet().iterator(); i.hasNext();) {
            final Map.Entry entry = (Map.Entry) i.next();
            final String switchId = (String) entry.getKey();

//            System.out.println("xxx 2: switch id: " + switchId);

            if (switchId.indexOf(XFormsConstants.REPEAT_HIERARCHY_SEPARATOR_1) != -1) {
                // This switch id may be affected by this insertion

//                System.out.println("xxx 2: has separator");

                final XFormsControl switchXFormsControl = (XFormsControl) xformsControls.getObjectById(switchId);
                XFormsControl parent = switchXFormsControl;
                while ((parent = parent.getParent()) != null) {
                    if (parent instanceof RepeatIterationControl) {
                        // Found closest enclosing repeat iteration

                        final RepeatIterationControl repeatIterationInfo = (RepeatIterationControl) parent;
                        final XFormsRepeatControl repeatControlInfo = (XFormsRepeatControl) repeatIterationInfo.getParent();

                        final List currentNodeset = repeatControlInfo.getBindingContext().getNodeset();

                        final Node node = (Node) currentNodeset.get(repeatIterationInfo.getIteration() - 1);
                        final InstanceData instanceData = XFormsUtils.getLocalInstanceData(node);

                        final String caseId = instanceData.getCasedIdForSwitchId(switchXFormsControl.getOriginalId());

//                        System.out.println("xxx 2: found case id " + caseId);

                        if (caseId != null) {
                            // Set effective case id
                            final String effectiveCaseId = caseId + switchId.substring(switchId.indexOf(XFormsConstants.REPEAT_HIERARCHY_SEPARATOR_1));
//                            System.out.println("xxx 2: setting case id " + effectiveCaseId);
                            entry.setValue(effectiveCaseId);
                        }

                        break;
                    }
                }
            }
        }
    }
}<commit_msg>Fixed ClassCastException when using switch in repeat.<commit_after>/**
 *  Copyright (C) 2006 Orbeon, Inc.
 *
 *  This program is free software; you can redistribute it and/or modify it under the terms of the
 *  GNU Lesser General Public License as published by the Free Software Foundation; either version
 *  2.1 of the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *  See the GNU Lesser General Public License for more details.
 *
 *  The full text of the license is available at http://www.gnu.org/copyleft/lesser.html
 */
package org.orbeon.oxf.xforms;

import org.dom4j.Attribute;
import org.dom4j.Element;
import org.dom4j.Node;
import org.orbeon.oxf.pipeline.api.PipelineContext;
import org.orbeon.oxf.xforms.control.XFormsControl;
import org.orbeon.oxf.xforms.control.controls.RepeatIterationControl;
import org.orbeon.oxf.xforms.control.controls.XFormsRepeatControl;
import org.orbeon.saxon.om.NodeInfo;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Utilities related to xforms:switch.
 */
public class XFormsSwitchUtils {

    public static boolean prepareSwitches(PipelineContext pipelineContext, XFormsControls xformsControls) {
        // Store temporary switch information into appropriate nodes
        boolean found = false;
        for (Iterator i = xformsControls.getCurrentControlsState().getSwitchIdToSelectedCaseIdMap().entrySet().iterator(); i.hasNext();) {
            final Map.Entry entry = (Map.Entry) i.next();
            final String switchId = (String) entry.getKey();

//            System.out.println("xxx 1: switch id: " + switchId);

            if (switchId.indexOf(XFormsConstants.REPEAT_HIERARCHY_SEPARATOR_1) != -1) {
                // This switch id may be affected by this insertion

//                System.out.println("xxx 1: has separator");

                final XFormsControl switchXFormsControl = (XFormsControl) xformsControls.getObjectById(switchId);
                XFormsControl parent = switchXFormsControl;
                while ((parent = parent.getParent()) != null) {
                    if (parent instanceof RepeatIterationControl) {
                        // Found closest enclosing repeat iteration

                        final RepeatIterationControl repeatIterationInfo = (RepeatIterationControl) parent;
                        final XFormsRepeatControl repeatControlInfo = (XFormsRepeatControl) repeatIterationInfo.getParent();

                        final List currentNodeset = repeatControlInfo.getBindingContext().getNodeset();

                        final NodeInfo node = (NodeInfo) currentNodeset.get(repeatIterationInfo.getIteration() - 1);
                        final InstanceData instanceData = XFormsUtils.getLocalInstanceData(node);

                        // Store an original case id instead of an effective case id
                        final String caseId = (String) entry.getValue();
                        instanceData.addSwitchIdToCaseId(switchXFormsControl.getOriginalId(), caseId.substring(0, caseId.indexOf(XFormsConstants.REPEAT_HIERARCHY_SEPARATOR_1)));

//                        System.out.println("xxx 1: adding case id " + switchControlInfo.getOriginalId() + " " + entry.getValue());

                        found = true;

                        break;
                    }
                }
            }
        }
        return found;
    }

    public static void prepareSwitches(PipelineContext pipelineContext, XFormsControls xformsControls, Node sourceElement, Node clonedElement) {
        final boolean found = prepareSwitches(pipelineContext, xformsControls);
        if (found) {
            // Propagate temporary switch information to new nodes
            copySwitchInfo(sourceElement, clonedElement);
        }
    }

    private static void copySwitchInfo(Node sourceNode, Node destNode) {

        final InstanceData sourceInstanceData = XFormsUtils.getLocalInstanceData(sourceNode);
        final InstanceData destInstanceData = XFormsUtils.getLocalInstanceData(destNode);
        destInstanceData.setSwitchIdsToCaseIds(sourceInstanceData.getSwitchIdsToCaseIds());

        if (sourceNode instanceof Element) {
            final Element sourceElement = (Element) sourceNode;
            final Element destElement = (Element) destNode;
            // Recurse over attributes
            {
                final Iterator j = destElement.attributes().iterator();
                for (Iterator i = sourceElement.attributes().iterator(); i.hasNext();) {
                    final Attribute sourceAttribute = (Attribute) i.next();
                    final Attribute destAttribute = (Attribute) j.next();

                    final InstanceData sourceAttributeInstanceData = XFormsUtils.getLocalInstanceData(sourceAttribute);
                    final InstanceData destAttributeInstanceData = XFormsUtils.getLocalInstanceData(destAttribute);

                    destAttributeInstanceData.setSwitchIdsToCaseIds(sourceAttributeInstanceData.getSwitchIdsToCaseIds());
                }
            }
            // Recurse over children elements
            {
                final Iterator j = destElement.elements().iterator();
                for (Iterator i = sourceElement.elements().iterator(); i.hasNext();) {
                    final Element sourceChild = (Element) i.next();
                    final Element destChild = (Element) j.next();
                    copySwitchInfo(sourceChild, destChild);
                }
            }
        }
    }

    public static void updateSwitches(PipelineContext pipelineContext, XFormsControls xformsControls) {
        for (Iterator i = xformsControls.getCurrentControlsState().getSwitchIdToSelectedCaseIdMap().entrySet().iterator(); i.hasNext();) {
            final Map.Entry entry = (Map.Entry) i.next();
            final String switchId = (String) entry.getKey();

//            System.out.println("xxx 2: switch id: " + switchId);

            if (switchId.indexOf(XFormsConstants.REPEAT_HIERARCHY_SEPARATOR_1) != -1) {
                // This switch id may be affected by this insertion

//                System.out.println("xxx 2: has separator");

                final XFormsControl switchXFormsControl = (XFormsControl) xformsControls.getObjectById(switchId);
                XFormsControl parent = switchXFormsControl;
                while ((parent = parent.getParent()) != null) {
                    if (parent instanceof RepeatIterationControl) {
                        // Found closest enclosing repeat iteration

                        final RepeatIterationControl repeatIterationInfo = (RepeatIterationControl) parent;
                        final XFormsRepeatControl repeatControlInfo = (XFormsRepeatControl) repeatIterationInfo.getParent();

                        final List currentNodeset = repeatControlInfo.getBindingContext().getNodeset();

                        final NodeInfo node = (NodeInfo) currentNodeset.get(repeatIterationInfo.getIteration() - 1);
                        final InstanceData instanceData = XFormsUtils.getLocalInstanceData(node);

                        final String caseId = instanceData.getCasedIdForSwitchId(switchXFormsControl.getOriginalId());

//                        System.out.println("xxx 2: found case id " + caseId);

                        if (caseId != null) {
                            // Set effective case id
                            final String effectiveCaseId = caseId + switchId.substring(switchId.indexOf(XFormsConstants.REPEAT_HIERARCHY_SEPARATOR_1));
//                            System.out.println("xxx 2: setting case id " + effectiveCaseId);
                            entry.setValue(effectiveCaseId);
                        }

                        break;
                    }
                }
            }
        }
    }
}
{'fraction_non_alphanumeric': 0.08171962148273484, 'fraction_numerical': 0.0031334210691232687, 'mean_word_length': 2.268742318721835, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1687983', 'n_tokens_mistral': 3932, 'n_tokens_neox': 3747, 'n_words': 980}