/**
 *  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.action.actions;

import org.dom4j.Element;
import org.orbeon.oxf.common.OXFException;
import org.orbeon.oxf.pipeline.api.PipelineContext;
import org.orbeon.oxf.xforms.XFormsContainingDocument;
import org.orbeon.oxf.xforms.XFormsControls;
import org.orbeon.oxf.xforms.XFormsUtils;
import org.orbeon.oxf.xforms.action.XFormsAction;
import org.orbeon.oxf.xforms.action.XFormsActionInterpreter;
import org.orbeon.oxf.xforms.control.XFormsControl;
import org.orbeon.oxf.xforms.event.XFormsEventHandlerContainer;
import org.orbeon.oxf.xforms.event.XFormsEventTarget;
import org.orbeon.oxf.xforms.event.events.XFormsFocusEvent;

/**
 * 10.1.7 The setfocus Element
 */
public class XFormsSetfocusAction extends XFormsAction {
    public void execute(XFormsActionInterpreter actionInterpreter, PipelineContext pipelineContext, String targetId, XFormsEventHandlerContainer eventHandlerContainer, Element actionElement) {

        final XFormsControls xformsControls = actionInterpreter.getXFormsControls();
        final XFormsContainingDocument containingDocument = actionInterpreter.getContainingDocument();

        final String controlId = XFormsUtils.namespaceId(containingDocument, actionElement.attributeValue("control"));
        if (controlId == null)
            throw new OXFException("Missing mandatory 'control' attribute on xforms:control element.");
        final String effectiveControlId = xformsControls.getCurrentControlsState().findEffectiveControlId(controlId);


        // "4.7 Resolving ID References in XForms [...] a null search result for an IDREF resolution is handled
        // differently depending on the source object. If there is a null search result for the target object and the
        // source object is an XForms action such as dispatch, send, setfocus, setindex or toggle, then the action is
        // terminated with no effect."

        if (effectiveControlId == null) {
            return;
           // TODO: It would be nice to have a warning mechanism in place to help the developer
//            throw new OXFException("Could not find actual control on xforms:setfocus element for control: " + controlId);
        }

        final Object controlObject = containingDocument.getObjectById(pipelineContext, effectiveControlId);

        if (!(controlObject instanceof XFormsControl)) {
            return;
            // TODO: It would be nice to have a warning mechanism in place to help the developer
//            throw new OXFException("xforms:setfocus attribute 'control' must refer to a control: " + controlId);
        }

        containingDocument.dispatchEvent(pipelineContext, new XFormsFocusEvent((XFormsEventTarget) controlObject));
    }
}

@@ -1775,24 +1775,25 @@
 ocument();%0A%0A
+%0A
         fina
@@ -1810,16 +1810,30 @@
 ontrolId
+AttributeValue
  = XForm
@@ -1926,32 +1926,46 @@
    if (controlId
+AttributeValue
  == null)%0A      
@@ -2062,16 +2062,622 @@
 ent.%22);%0A
+%0A        final XFormsControls.BindingContext bindingContext = xformsControls.getCurrentBindingContext();%0A        final String resolvedControlId;%0A        %7B%0A            // NOP if there is an AVT but no context node%0A            if (bindingContext.getSingleNode() == null && controlIdAttributeValue.indexOf('%7B') != -1)%0A                return;%0A%0A            // Resolve AVT%0A            resolvedControlId = XFormsUtils.resolveAttributeValueTemplates(pipelineContext, bindingContext.getSingleNode(),%0A                    null, xformsControls.getFunctionLibrary(), actionElement, controlIdAttributeValue);%0A        %7D%0A%0A
         
@@ -2774,17 +2774,25 @@
 ntrolId(
-c
+resolvedC
 ontrolId
@@ -2791,25 +2791,24 @@
 ontrolId);%0A%0A
-%0A
         // %22
@@ -3445,33 +3445,41 @@
 or control: %22 + 
-c
+resolvedC
 ontrolId);%0A     
@@ -3870,17 +3870,25 @@
 ol: %22 + 
-c
+resolvedC
 ontrolId

Support AVT on xforms:setvalue/@control.