1 16 package org.springframework.webflow.engine; 17 18 import org.springframework.core.style.ToStringCreator; 19 import org.springframework.util.Assert; 20 import org.springframework.webflow.core.collection.AttributeMap; 21 import org.springframework.webflow.core.collection.MutableAttributeMap; 22 import org.springframework.webflow.execution.FlowExecutionException; 23 import org.springframework.webflow.execution.RequestContext; 24 import org.springframework.webflow.execution.ViewSelection; 25 26 45 public class SubflowState extends TransitionableState { 46 47 50 private Flow subflow; 51 52 56 private FlowAttributeMapper attributeMapper; 57 58 67 public SubflowState(Flow flow, String id, Flow subflow) throws IllegalArgumentException { 68 super(flow, id); 69 setSubflow(subflow); 70 } 71 72 75 public Flow getSubflow() { 76 return subflow; 77 } 78 79 83 private void setSubflow(Flow subflow) { 84 Assert.notNull(subflow, "A subflow state must have a subflow; the subflow is required"); 85 this.subflow = subflow; 86 } 87 88 92 public FlowAttributeMapper getAttributeMapper() { 93 return attributeMapper; 94 } 95 96 100 public void setAttributeMapper(FlowAttributeMapper attributeMapper) { 101 this.attributeMapper = attributeMapper; 102 } 103 104 116 protected ViewSelection doEnter(RequestControlContext context) throws FlowExecutionException { 117 if (logger.isDebugEnabled()) { 118 logger.debug("Spawning subflow '" + getSubflow().getId() + "' within flow '" + getFlow().getId() + "'"); 119 } 120 return context.start(getSubflow(), createSubflowInput(context)); 121 } 122 123 127 protected MutableAttributeMap createSubflowInput(RequestContext context) { 128 if (getAttributeMapper() != null) { 129 if (logger.isDebugEnabled()) { 130 logger.debug("Messaging the configured attribute mapper to map attributes " 131 + "down to the spawned subflow for access within the subflow"); 132 } 133 return getAttributeMapper().createFlowInput(context); 134 } 135 else { 136 if (logger.isDebugEnabled()) { 137 logger.debug("No attribute mapper configured for this subflow state '" + getId() 138 + "' -- As a result, no attributes will be passed to the spawned subflow '" 139 + subflow.getId() + "'"); 140 } 141 return null; 142 } 143 } 144 145 149 public ViewSelection onEvent(RequestControlContext context) { 150 mapSubflowOutput(context.getLastEvent().getAttributes(), context); 151 return super.onEvent(context); 152 } 153 154 158 private void mapSubflowOutput(AttributeMap subflowOutput, RequestContext context) { 159 if (getAttributeMapper() != null) { 160 if (logger.isDebugEnabled()) { 161 logger.debug("Messaging the configured attribute mapper to map subflow result attributes to the " 162 + "resuming parent flow -- It will have access to attributes passed up by the completed subflow"); 163 } 164 attributeMapper.mapFlowOutput(subflowOutput, context); 165 } 166 else { 167 if (logger.isDebugEnabled()) { 168 logger.debug("No attribute mapper is configured for the resuming subflow state '" + getId() 169 + "' -- As a result, no attributes of the ending flow will be passed to the resuming parent flow"); 170 } 171 } 172 } 173 174 protected void appendToString(ToStringCreator creator) { 175 creator.append("subflow", subflow.getId()).append("attributeMapper", attributeMapper); 176 super.appendToString(creator); 177 } 178 } | Popular Tags |