com.sun.faces.config.processor.FacesFlowDefinitionConfigProcessor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jsf-impl Show documentation
Show all versions of jsf-impl Show documentation
This is the master POM file for Oracle's Implementation of the JSF 2.2 Specification.
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.faces.config.processor;
import com.sun.faces.RIConstants;
import com.sun.faces.application.ApplicationAssociate;
import com.sun.faces.config.DocumentInfo;
import com.sun.faces.config.WebConfiguration;
import com.sun.faces.facelets.util.ReflectionUtil;
import com.sun.faces.flow.FlowImpl;
import com.sun.faces.flow.ParameterImpl;
import com.sun.faces.flow.builder.FlowBuilderImpl;
import com.sun.faces.util.FacesLogger;
import com.sun.faces.util.Util;
import java.net.MalformedURLException;
import java.net.URI;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.el.ELContext;
import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.FactoryFinder;
import javax.faces.application.Application;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.PostConstructApplicationEvent;
import javax.faces.event.SystemEvent;
import javax.faces.event.SystemEventListener;
import javax.faces.flow.FlowHandler;
import javax.faces.flow.FlowHandlerFactory;
import javax.faces.flow.FlowNode;
import javax.faces.flow.Parameter;
import javax.faces.flow.builder.FlowBuilder;
import javax.faces.flow.builder.FlowCallBuilder;
import javax.faces.flow.builder.MethodCallBuilder;
import javax.faces.flow.builder.NavigationCaseBuilder;
import javax.faces.flow.builder.SwitchBuilder;
import javax.servlet.ServletContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
*
* This ConfigProcessor
handles all elements defined under
* /faces-config/flow-definition
.
*
*/
public class FacesFlowDefinitionConfigProcessor extends AbstractConfigProcessor {
private static final Logger LOGGER = FacesLogger.CONFIG.getLogger();
/**
* /faces-config/flow-definition
*/
private static final String FACES_FLOW_DEFINITION = "flow-definition";
public FacesFlowDefinitionConfigProcessor() {
}
public static boolean uriIsFlowDefinition(URI uri) {
boolean result = false;
String path = uri.getPath();
String [] segments = path.split("/");
if (1 < segments.length) {
String flowName = segments[segments.length-2];
String definingName = segments[segments.length-1];
result = definingName.equals(flowName + "-flow.xml");
}
return result;
}
/*
* Implement the requirements of 11.4.3.3
*
* @param uri
* @param toPopulate
* @return
*/
public static Document synthesizeEmptyFlowDefinition(URI uri) throws ParserConfigurationException {
Document newDoc = null;
String path = uri.getPath();
String [] segments = path.split("/");
if (segments.length < 2) {
return newDoc;
}
String flowName = segments[segments.length-2];
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder builder = dbf.newDocumentBuilder();
DOMImplementation domImpl = builder.getDOMImplementation();
newDoc = domImpl.createDocument(RIConstants.JAVAEE_XMLNS, "faces-config", null);
Node documentElement = newDoc.getDocumentElement();
Attr versionAttribute = newDoc.createAttribute("version");
versionAttribute.setValue("2.2");
documentElement.getAttributes().setNamedItem(versionAttribute);
Node facesConfig = newDoc.getFirstChild();
Element flowDefinition = newDoc.createElementNS(RIConstants.JAVAEE_XMLNS, "flow-definition");
flowDefinition.setAttribute("id", flowName);
facesConfig.appendChild(flowDefinition);
final String flowReturnStr = flowName + "-return";
Element flowReturn = newDoc.createElementNS(RIConstants.JAVAEE_XMLNS, "flow-return");
flowReturn.setAttribute("id", flowReturnStr);
flowDefinition.appendChild(flowReturn);
Element fromOutcome = newDoc.createElementNS(RIConstants.JAVAEE_XMLNS, "from-outcome");
flowReturn.appendChild(fromOutcome);
fromOutcome.setTextContent("/" + flowReturnStr);
return newDoc;
}
@Override
public void process(ServletContext sc, DocumentInfo[] documentInfos)
throws Exception {
WebConfiguration config = WebConfiguration.getInstance(sc);
FacesContext context = FacesContext.getCurrentInstance();
for (int i = 0; i < documentInfos.length; i++) {
URI definingDocumentURI = documentInfos[i].getSourceURI();
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE,
MessageFormat.format(
"Processing factory elements for document: ''{0}''",
definingDocumentURI));
}
Document document = documentInfos[i].getDocument();
String namespace = document.getDocumentElement()
.getNamespaceURI();
NodeList flowDefinitions = document.getDocumentElement()
.getElementsByTagNameNS(namespace, FACES_FLOW_DEFINITION);
if (flowDefinitions != null && flowDefinitions.getLength() > 0) {
config.setHasFlows(true);
saveFlowDefinition(context, definingDocumentURI, document);
}
}
if (config.isHasFlows()) {
String optionValue = config.getOptionValue(WebConfiguration.WebContextInitParameter.ClientWindowMode);
boolean clientWindowNeedsEnabling = false;
if ("none".equals(optionValue)) {
clientWindowNeedsEnabling = true;
String featureName =
WebConfiguration.WebContextInitParameter.ClientWindowMode.getQualifiedName();
LOGGER.log(Level.WARNING,
"{0} was set to none, but Faces Flows requires {0} is enabled. Setting to ''url''.", new Object[]{featureName});
} else if (null == optionValue) {
clientWindowNeedsEnabling = true;
}
if (clientWindowNeedsEnabling) {
config.setOptionValue(WebConfiguration.WebContextInitParameter.ClientWindowMode, "url");
}
context.getApplication().subscribeToEvent(PostConstructApplicationEvent.class,
Application.class, new PerformDeferredFlowProcessing());
}
invokeNext(sc, documentInfos);
}
//
private static final String flowDefinitionListKey = RIConstants.FACES_PREFIX + "FacesFlowDefinitions";
private void saveFlowDefinition(FacesContext context,
URI definingDocumentURI,
Document flowDefinitions) {
Map appMap = context.getExternalContext().getApplicationMap();
List def = (List) appMap.get(flowDefinitionListKey);
if (null == def) {
def = new ArrayList();
appMap.put(flowDefinitionListKey, def);
}
def.add(new FlowDefinitionDocument(definingDocumentURI, flowDefinitions));
}
private List getSavedFlowDefinitions(FacesContext context) {
Map appMap = context.getExternalContext().getApplicationMap();
List def = (List) appMap.get(flowDefinitionListKey);
return (null != def) ? def : Collections.EMPTY_LIST;
}
private void clearSavedFlowDefinitions(FacesContext context) {
Map appMap = context.getExternalContext().getApplicationMap();
List def = (List) appMap.get(flowDefinitionListKey);
if (null != def) {
for (FlowDefinitionDocument cur : def) {
cur.clear();
}
def.clear();
appMap.remove(flowDefinitionListKey);
}
}
private static class FlowDefinitionDocument {
URI definingDocumentURI;
Document flowDefinitions;
public FlowDefinitionDocument(URI definingDocumentURI,
Document flowDefinitions) {
this.definingDocumentURI = definingDocumentURI;
this.flowDefinitions = flowDefinitions;
}
public void clear() {
this.definingDocumentURI = null;
this.flowDefinitions = null;
}
}
private class PerformDeferredFlowProcessing implements SystemEventListener {
@Override
public boolean isListenerForSource(Object source) {
return source instanceof Application;
}
@Override
public void processEvent(SystemEvent event) throws AbortProcessingException {
FacesContext context = FacesContext.getCurrentInstance();
List flowDefinitions =
FacesFlowDefinitionConfigProcessor.this.getSavedFlowDefinitions(context);
for (FlowDefinitionDocument cur: flowDefinitions) {
try {
FacesFlowDefinitionConfigProcessor.this.
processFacesFlowDefinitions(cur.definingDocumentURI, cur.flowDefinitions);
} catch (XPathExpressionException ex) {
throw new FacesException(ex);
}
}
FacesFlowDefinitionConfigProcessor.this.clearSavedFlowDefinitions(context);
}
}
//
private void processFacesFlowDefinitions(URI definingDocumentURI,
Document document) throws XPathExpressionException {
String namespace = document.getDocumentElement()
.getNamespaceURI();
NodeList flowDefinitions = document.getDocumentElement()
.getElementsByTagNameNS(namespace, FACES_FLOW_DEFINITION);
if (0 == flowDefinitions.getLength()) {
return;
}
FacesContext context = FacesContext.getCurrentInstance();
Application app = context.getApplication();
FlowHandler flowHandler = app.getFlowHandler();
if (null == flowHandler) {
FlowHandlerFactory flowHandlerFactory = (FlowHandlerFactory) FactoryFinder.getFactory(FactoryFinder.FLOW_HANDLER_FACTORY);
app.setFlowHandler(flowHandler =
flowHandlerFactory.createFlowHandler(context));
}
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(new FacesConfigNamespaceContext());
String nameStr = "";
NodeList nameList = (NodeList) xpath.evaluate("./ns1:name/text()",
document.getDocumentElement(), XPathConstants.NODESET);
if (null != nameList && 1 < nameList.getLength()) {
throw new XPathExpressionException(" must have at most one element.");
}
if (null != nameList && 1 == nameList.getLength()) {
nameStr = nameList.item(0).getNodeValue().trim();
if (0 < nameStr.length()) {
ApplicationAssociate associate = ApplicationAssociate.getInstance(context.getExternalContext());
try {
associate.relateUrlToDefiningDocumentInJar(definingDocumentURI.toURL(), nameStr);
} catch (MalformedURLException ex) {
throw new XPathExpressionException(ex);
}
}
}
for (int c = 0, size = flowDefinitions.getLength(); c < size; c++) {
Node flowDefinition = flowDefinitions.item(c);
String flowId = getIdAttribute(flowDefinition);
String uriStr = definingDocumentURI.toASCIIString();
if (uriStr.endsWith(RIConstants.FLOW_DEFINITION_ID_SUFFIX)) {
nameStr = "";
}
FlowBuilderImpl flowBuilder = new FlowBuilderImpl(context);
flowBuilder.id(nameStr, flowId);
processViews(xpath, flowDefinition, flowBuilder);
processNavigationRules(xpath, flowDefinition, flowBuilder);
processReturns(xpath, flowDefinition, flowBuilder);
processInboundParameters(xpath, flowDefinition, flowBuilder);
processFlowCalls(xpath, flowDefinition, flowBuilder);
processSwitches(xpath, flowDefinition, flowBuilder);
processMethodCalls(context, xpath, flowDefinition, flowBuilder);
processInitializerFinalizer(xpath, flowDefinition, flowBuilder);
String startNodeId = processStartNode(xpath, flowDefinition, flowBuilder);
if (null != startNodeId) {
FlowImpl toAdd = flowBuilder._getFlow();
FlowNode startNode = toAdd.getNode(startNodeId);
if (null == startNode) {
throw new XPathExpressionException("Unable to find flow node with id " + startNodeId + " to mark as start node");
} else {
toAdd.setStartNodeId(startNodeId);
}
} else {
flowBuilder.viewNode(flowId, "/" + flowId + "/" + flowId + ".xhtml").markAsStartNode();
}
flowHandler.addFlow(context, flowBuilder.getFlow());
}
}
private void processNavigationRules(XPath xpath, Node flowDefinition, FlowBuilder flowBuilder) throws XPathExpressionException{
//
NodeList navRules = (NodeList) xpath.evaluate(".//ns1:navigation-rule",
flowDefinition, XPathConstants.NODESET);
for (int i_navRule = 0; i_navRule < navRules.getLength(); i_navRule++) {
Node navRule = navRules.item(i_navRule);
NodeList fromViewIdList = (NodeList)
xpath.evaluate(".//ns1:from-view-id/text()", navRule, XPathConstants.NODESET);
if (1 != fromViewIdList.getLength()) {
throw new XPathExpressionException("Within must have exactly one ");
}
String fromViewId = fromViewIdList.item(0).getNodeValue().trim();
NodeList navCases = (NodeList)
xpath.evaluate(".//ns1:navigation-case", navRule, XPathConstants.NODESET);
for (int i_navCase = 0; i_navCase < navCases.getLength(); i_navCase++) {
Node navCase = navCases.item(i_navCase);
NodeList toViewIdList = (NodeList)
xpath.evaluate(".//ns1:to-view-id/text()", navCase, XPathConstants.NODESET);
if (1 != toViewIdList.getLength()) {
throw new XPathExpressionException("Within , must have exactly one ");
}
String toViewId = toViewIdList.item(0).getNodeValue().trim();
NavigationCaseBuilder ncb = flowBuilder.navigationCase();
ncb.fromViewId(fromViewId).toViewId(toViewId);
{
NodeList fromOutcomeList = (NodeList)
xpath.evaluate(".//ns1:from-outcome/text()", navCase, XPathConstants.NODESET);
if (null != fromOutcomeList && 1 < fromOutcomeList.getLength()) {
throw new XPathExpressionException("Within , must have at most one ");
}
if (null != fromOutcomeList && 1 == fromOutcomeList.getLength()) {
String fromOutcome = fromOutcomeList.item(0).getNodeValue().trim();
ncb.fromOutcome(fromOutcome);
}
}
{
NodeList fromActionList = (NodeList)
xpath.evaluate(".//ns1:from-action/text()", navCase, XPathConstants.NODESET);
if (null != fromActionList && 1 < fromActionList.getLength()) {
throw new XPathExpressionException("Within , must have at most one ");
}
if (null != fromActionList && 1 == fromActionList.getLength()) {
String fromAction = fromActionList.item(0).getNodeValue().trim();
ncb.fromAction(fromAction);
}
}
{
NodeList ifList = (NodeList)
xpath.evaluate(".//ns1:if/text()", navCase, XPathConstants.NODESET);
if (null != ifList && 1 < ifList.getLength()) {
throw new XPathExpressionException("Within , must have zero or one ");
}
if (null != ifList && 1 == ifList.getLength()) {
String ifStr = ifList.item(0).getNodeValue().trim();
ncb.condition(ifStr);
}
}
{
NodeList redirectList = (NodeList)
xpath.evaluate(".//ns1:redirect", navCase, XPathConstants.NODESET);
if (null != redirectList && 1 < redirectList.getLength()) {
throw new XPathExpressionException("Within , must have zero or one ");
}
if (null != redirectList && 1 == redirectList.getLength()) {
NavigationCaseBuilder.RedirectBuilder redirector = ncb.redirect();
Node redirectNode = redirectList.item(0);
String includeViewParams = getAttribute(redirectNode, "include-view-params");
if (null != includeViewParams && "true".equalsIgnoreCase(includeViewParams)) {
redirector.includeViewParams();
}
NodeList viewParamList = (NodeList)
xpath.evaluate(".//ns1:redirect-param", redirectNode, XPathConstants.NODESET);
if (null != viewParamList) {
for (int i_viewParam = 0; i_viewParam < viewParamList.getLength(); i_viewParam++) {
Node viewParam = viewParamList.item(i_viewParam);
NodeList nameList = (NodeList)
xpath.evaluate(".//ns1:name/text()", viewParam, XPathConstants.NODESET);
if (null == nameList || 1 != nameList.getLength()) {
throw new XPathExpressionException("Within must have .");
}
String nameStr = nameList.item(0).getNodeValue().trim();
NodeList valueList = (NodeList)
xpath.evaluate(".//ns1:value/text()", viewParam, XPathConstants.NODESET);
if (null == valueList || 1 != valueList.getLength()) {
throw new XPathExpressionException("Within must have .");
}
String valueStr = valueList.item(0).getNodeValue().trim();
redirector.parameter(nameStr, valueStr);
}
}
}
}
}
}
//
}
private void processViews(XPath xpath, Node flowDefinition, FlowBuilder flowBuilder) throws XPathExpressionException{
//
NodeList views = (NodeList) xpath.evaluate(".//ns1:view",
flowDefinition, XPathConstants.NODESET);
for (int i_view = 0; i_view < views.getLength(); i_view++) {
Node viewNode = views.item(i_view);
String viewNodeId = getIdAttribute(viewNode);
NodeList vdlDocumentList = (NodeList)
xpath.evaluate(".//ns1:vdl-document/text()", viewNode, XPathConstants.NODESET);
if (1 != vdlDocumentList.getLength()) {
throw new XPathExpressionException("Within exactly one child is allowed, and it must be a ");
}
String vdlDocumentStr = vdlDocumentList.item(0).getNodeValue().trim();
flowBuilder.viewNode(viewNodeId, vdlDocumentStr);
}
//
}
private void processReturns(XPath xpath, Node flowDefinition, FlowBuilder flowBuilder) throws XPathExpressionException{
//
NodeList returns = (NodeList) xpath.evaluate(".//ns1:flow-return",
flowDefinition, XPathConstants.NODESET);
for (int i_return = 0; i_return < returns.getLength(); i_return++) {
Node returnNode = returns.item(i_return);
NodeList fromOutcomeList = (NodeList)
xpath.evaluate(".//ns1:from-outcome/text()", returnNode, XPathConstants.NODESET);
String id = getIdAttribute(returnNode);
if (null != fromOutcomeList && 1 < fromOutcomeList.getLength()) {
throw new XPathExpressionException("Within only one child is allowed, and it must be a ");
}
if (null != fromOutcomeList && 1 == fromOutcomeList.getLength()) {
String fromOutcomeStr = fromOutcomeList.item(0).getNodeValue().trim();
flowBuilder.returnNode(id).fromOutcome(fromOutcomeStr);
}
}
//
}
private void processInboundParameters(XPath xpath, Node flowDefinition, FlowBuilder flowBuilder) throws XPathExpressionException {
//
NodeList inboundParameters = (NodeList) xpath.evaluate(".//ns1:inbound-parameter",
flowDefinition, XPathConstants.NODESET);
for (int i_inbound = 0; i_inbound < inboundParameters.getLength(); i_inbound++) {
Node inboundParamNode = inboundParameters.item(i_inbound);
NodeList nameList = (NodeList)
xpath.evaluate(".//ns1:name/text()", inboundParamNode, XPathConstants.NODESET);
if (1 < nameList.getLength()) {
throw new XPathExpressionException("Within only one child is allowed");
}
String nameStr = nameList.item(0).getNodeValue().trim();
NodeList valueList = (NodeList)
xpath.evaluate(".//ns1:value/text()", inboundParamNode, XPathConstants.NODESET);
if (1 < valueList.getLength()) {
throw new XPathExpressionException("Within only one child is allowed");
}
String valueStr = valueList.item(0).getNodeValue().trim();
flowBuilder.inboundParameter(nameStr, valueStr);
}
//
}
private void processFlowCalls(XPath xpath, Node flowDefinition, FlowBuilder flowBuilder) throws XPathExpressionException {
//
NodeList flowCalls = (NodeList) xpath.evaluate(".//ns1:flow-call",
flowDefinition, XPathConstants.NODESET);
for (int i_flowCall = 0; i_flowCall < flowCalls.getLength(); i_flowCall++) {
Node flowCallNode = flowCalls.item(i_flowCall);
String flowCallId = getIdAttribute(flowCallNode);
NodeList facesFlowRefList = (NodeList)
xpath.evaluate(".//ns1:flow-reference",
flowCallNode, XPathConstants.NODESET);
if (null == facesFlowRefList || 1 != facesFlowRefList.getLength()) {
throw new XPathExpressionException("Within must have exactly one ");
}
Node facesFlowRefNode = facesFlowRefList.item(0);
NodeList facesFlowIdList = (NodeList)
xpath.evaluate(".//ns1:flow-id/text()",
facesFlowRefNode, XPathConstants.NODESET);
if (null == facesFlowIdList || 1 != facesFlowIdList.getLength()) {
throw new XPathExpressionException("Within must have exactly one ");
}
String destinationId = facesFlowIdList.item(0).getNodeValue().trim();
NodeList definingDocumentIdList = (NodeList)
xpath.evaluate(".//ns1:flow-document-id/text()",
facesFlowRefNode, XPathConstants.NODESET);
if (null == definingDocumentIdList && 1 != definingDocumentIdList.getLength()) {
throw new XPathExpressionException("Within must have at most one ");
}
String definingDocumentId = "";
if (null != definingDocumentIdList && 1 == definingDocumentIdList.getLength()) {
definingDocumentId = definingDocumentIdList.item(0).getNodeValue().trim();
}
FlowCallBuilder flowCallBuilder = flowBuilder.flowCallNode(flowCallId);
flowCallBuilder.flowReference(definingDocumentId, destinationId);
NodeList outboundParameters = (NodeList) xpath.evaluate(".//ns1:outbound-parameter",
flowDefinition, XPathConstants.NODESET);
if (null != outboundParameters) {
for (int i_outbound = 0; i_outbound < outboundParameters.getLength(); i_outbound++) {
Node outboundParamNode = outboundParameters.item(i_outbound);
NodeList nameList = (NodeList)
xpath.evaluate(".//ns1:name/text()", outboundParamNode, XPathConstants.NODESET);
if (1 < nameList.getLength()) {
throw new XPathExpressionException("Within only one child is allowed");
}
String nameStr = nameList.item(0).getNodeValue().trim();
NodeList valueList = (NodeList)
xpath.evaluate(".//ns1:value/text()", outboundParamNode, XPathConstants.NODESET);
if (1 < valueList.getLength()) {
throw new XPathExpressionException("Within only one child is allowed");
}
String valueStr = valueList.item(0).getNodeValue().trim();
flowCallBuilder.outboundParameter(nameStr, valueStr);
}
}
}
//
}
private void processSwitches(XPath xpath, Node flowDefinition, FlowBuilder flowBuilder) throws XPathExpressionException {
//
NodeList switches = (NodeList) xpath.evaluate(".//ns1:switch",
flowDefinition, XPathConstants.NODESET);
if (null == switches) {
return;
}
for (int i_switch = 0; i_switch < switches.getLength(); i_switch++) {
Node switchNode = switches.item(i_switch);
String switchId = getIdAttribute(switchNode);
SwitchBuilder switchBuilder = flowBuilder.switchNode(switchId);
NodeList cases = (NodeList) xpath.evaluate(".//ns1:case",
switchNode, XPathConstants.NODESET);
if (null != cases) {
for (int i_case = 0; i_case < cases.getLength(); i_case++) {
Node caseNode = cases.item(i_case);
NodeList ifList = (NodeList)
xpath.evaluate(".//ns1:if/text()", caseNode, XPathConstants.NODESET);
if (1 < ifList.getLength()) {
throw new XPathExpressionException("Within only one child is allowed");
}
String ifStr = ifList.item(0).getNodeValue().trim();
NodeList fromOutcomeList = (NodeList)
xpath.evaluate(".//ns1:from-outcome/text()", caseNode, XPathConstants.NODESET);
if (1 < fromOutcomeList.getLength()) {
throw new XPathExpressionException("Within only one child is allowed");
}
String fromOutcomeStr = fromOutcomeList.item(0).getNodeValue().trim();
switchBuilder.switchCase().condition(ifStr).fromOutcome(fromOutcomeStr);
}
}
NodeList defaultOutcomeList = (NodeList)
xpath.evaluate(".//ns1:default-outcome/text()", switchNode, XPathConstants.NODESET);
if (null != defaultOutcomeList && 1 < defaultOutcomeList.getLength()) {
throw new XPathExpressionException("Within only one child is allowed");
}
if (null != defaultOutcomeList) {
Node defaultOutcomeNode = defaultOutcomeList.item(0);
if (null != defaultOutcomeNode) {
String defaultOutcomeStr = defaultOutcomeNode.getNodeValue().trim();
switchBuilder.defaultOutcome(defaultOutcomeStr);
}
}
}
//
}
private void processMethodCalls(FacesContext context, XPath xpath, Node flowDefinition, FlowBuilder flowBuilder) throws XPathExpressionException {
//
NodeList methodCalls = (NodeList) xpath.evaluate(".//ns1:method-call",
flowDefinition, XPathConstants.NODESET);
if (null == methodCalls) {
return;
}
for (int i_methodCall = 0; i_methodCall < methodCalls.getLength(); i_methodCall++) {
Node methodCallNode = methodCalls.item(i_methodCall);
String methodCallId = getIdAttribute(methodCallNode);
MethodCallBuilder methodCallBuilder = flowBuilder.methodCallNode(methodCallId);
NodeList methodList = (NodeList)
xpath.evaluate(".//ns1:method/text()", methodCallNode, XPathConstants.NODESET);
if (1 != methodList.getLength()) {
throw new XPathExpressionException("Within exactly one child is allowed");
}
String methodStr = methodList.item(0).getNodeValue().trim();
NodeList params = (NodeList) xpath.evaluate(".//ns1:parameter",
methodCallNode, XPathConstants.NODESET);
if (null != params) {
List paramTypes = Collections.emptyList();
if (0 < params.getLength()) {
paramTypes = new ArrayList();
List paramList = new ArrayList();
Parameter toAdd = null;
ExpressionFactory ef = context.getApplication().getExpressionFactory();
ELContext elContext = context.getELContext();
ValueExpression ve = null;
for (int i_param = 0; i_param < params.getLength(); i_param++) {
Node param = params.item(i_param);
NodeList valueList = (NodeList)
xpath.evaluate(".//ns1:value/text()", param, XPathConstants.NODESET);
if (null == valueList || 1 != valueList.getLength()) {
throw new XPathExpressionException("Within exactly one child is allowed");
}
String valueStr = valueList.item(0).getNodeValue().trim();
String classStr = null;
NodeList classList = (NodeList)
xpath.evaluate(".//ns1:class/text()", param, XPathConstants.NODESET);
if (null != classList && 1 < classList.getLength()) {
throw new XPathExpressionException("Within at most one child is allowed");
}
if (null != classList && 1 == classList.getLength()) {
classStr = classList.item(0).getNodeValue().trim();
}
Class clazz = String.class;
if (null != classStr) {
try {
clazz = ReflectionUtil.forName(classStr);
} catch (ClassNotFoundException e) {
clazz = Object.class;
}
}
ve = ef.createValueExpression(elContext, valueStr, clazz);
toAdd = new ParameterImpl(classStr, ve);
paramList.add(toAdd);
paramTypes.add(clazz);
}
methodCallBuilder.parameters(paramList);
}
Class [] paramArray = new Class[paramTypes.size()];
paramTypes.toArray(paramArray);
methodCallBuilder.expression(methodStr, paramArray);
}
NodeList defaultOutcomeList = (NodeList)
xpath.evaluate(".//ns1:default-outcome/text()", methodCallNode, XPathConstants.NODESET);
if (null != defaultOutcomeList && 1 < defaultOutcomeList.getLength()) {
throw new XPathExpressionException("Within only one child is allowed");
}
if (null != defaultOutcomeList) {
String defaultOutcomeStr = defaultOutcomeList.item(0).getNodeValue().trim();
methodCallBuilder.defaultOutcome(defaultOutcomeStr);
}
}
//
}
private void processInitializerFinalizer(XPath xpath, Node flowDefinition, FlowBuilder flowBuilder) throws XPathExpressionException {
//
NodeList initializerNodeList = (NodeList)
xpath.evaluate(".//ns1:initializer/text()", flowDefinition, XPathConstants.NODESET);
if (1 < initializerNodeList.getLength()) {
throw new XPathExpressionException("At most one is allowed.");
}
if (1 == initializerNodeList.getLength()) {
String initializerStr = initializerNodeList.item(0).getNodeValue().trim();
flowBuilder.initializer(initializerStr);
}
NodeList finalizerNodeList = (NodeList)
xpath.evaluate(".//ns1:finalizer/text()", flowDefinition, XPathConstants.NODESET);
if (1 < finalizerNodeList.getLength()) {
throw new XPathExpressionException("At most one is allowed.");
}
if (1 == finalizerNodeList.getLength()) {
String finalizerStr = finalizerNodeList.item(0).getNodeValue().trim();
flowBuilder.finalizer(finalizerStr);
}
//
}
private String processStartNode(XPath xpath, Node flowDefinition, FlowBuilder flowBuilder) throws XPathExpressionException {
//
String startNodeId = null;
NodeList startNodeList = (NodeList) xpath.evaluate(".//ns1:start-node/text()",
flowDefinition, XPathConstants.NODESET);
if (1 < startNodeList.getLength()) {
throw new XPathExpressionException("Within at most one is allowed");
}
if (null != startNodeList && 1 == startNodeList.getLength()) {
startNodeId = startNodeList.item(0).getNodeValue().trim();
}
return startNodeId;
//
}
protected String getAttribute(Node node, String attrName) {
//
Util.notNull("flow definition element", node);
String result = null;
NamedNodeMap attrs = node.getAttributes();
if (null != attrs) {
Attr idAttr = (Attr) attrs.getNamedItem(attrName);
if (null != idAttr) {
result = idAttr.getValue();
}
}
return result;
//
}
protected String getIdAttribute(Node node) throws XPathExpressionException {
//
Util.notNull("flow definition element", node);
String result = null;
NamedNodeMap attrs = node.getAttributes();
String localName = "";
boolean throwException = false;
if (null != attrs) {
Attr idAttr = (Attr) attrs.getNamedItem("id");
if (null != idAttr) {
result = idAttr.getValue();
if (!idAttr.isId()) {
if (LOGGER.isLoggable(Level.FINEST)) {
LOGGER.log(Level.FINEST, "Element {0} has an id attribute, but it is not declared as type xsd:id", node.getLocalName());
}
}
} else {
localName = node.getLocalName();
throwException = true;
}
} else {
localName = node.getLocalName();
throwException = true;
}
if (throwException) {
throw new XPathExpressionException("<" + localName +
"> must have an \"id\" attribute.");
}
return result;
//
}
}