Page 2 of 2 FirstFirst 12
Results 11 to 16 of 16

Thread: Is there any better way to configure flow.xml?

  1. #11
    Join Date
    Sep 2004
    Location
    Leuven, Belgium
    Posts
    1,853

    Default

    I've updated to the code to be Spring 1.0 compatible:

    Code:
    package test;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.HashSet;
    import java.util.Set;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.NoSuchBeanDefinitionException;
    import org.springframework.core.io.FileSystemResource;
    import org.springframework.webflow.definition.StateDefinition;
    import org.springframework.webflow.definition.TransitionDefinition;
    import org.springframework.webflow.engine.Flow;
    import org.springframework.webflow.engine.Transition;
    import org.springframework.webflow.engine.TransitionableState;
    import org.springframework.webflow.engine.builder.BaseFlowServiceLocator;
    import org.springframework.webflow.engine.builder.FlowArtifactLookupException;
    import org.springframework.webflow.engine.builder.FlowAssembler;
    import org.springframework.webflow.engine.builder.FlowBuilder;
    import org.springframework.webflow.engine.builder.xml.XmlFlowBuilder;
    import org.springframework.webflow.engine.support.EventIdTransitionCriteria;
    
    public class SwfViz {
    	
    	private static Set<StateDefinition> visitedStates = new HashSet<StateDefinition>();
    	private static Flow flow;
    
    	public static void main(String[] args) {
    		if (args.length != 1) {
    			System.err.println("usage: SwfViz flowFileName");
    		}
    		else {
    			flow = loadFlow(args[0]);
    			printStateTransitions(flow.getStartState());
    		}
    	}
    
    	private static Flow loadFlow(String flowFileName) {
    		FlowBuilder builder = new XmlFlowBuilder(
    				new FileSystemResource(flowFileName), 
    				new BaseFlowServiceLocator() {
    					@Override
    					public Flow getSubflow(String id) throws FlowArtifactLookupException {
    						return new Flow(id);
    					}
    					
    					@Override
    					public BeanFactory getBeanFactory() throws UnsupportedOperationException {
    						return new BeanFactory() {
    
    							public Object getBean(String name) throws BeansException {
    								return new Object();
    							}
    
    							public Object getBean(String name, Class requiredType) throws BeansException {
    								return Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { requiredType }, new InvocationHandler() {
    									public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
    										return null;
    									}
    								});
    							}
    
    							public boolean containsBean(String name) {
    								return true;
    							}
    
    							public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
    								return false;
    							}
    
    							public Class getType(String name) throws NoSuchBeanDefinitionException {
    								return Object.class;
    							}
    
    							public String[] getAliases(String name) {
    								return new String[0];
    							}
    							
    						};
    					}
    				});
    		return new FlowAssembler("flow", builder).assembleFlow();
    	}
    
    	public static void printStateTransitions(StateDefinition state) {
    		
    		if (visitedStates.contains(state)) {
    			return;
    		}
    
    		visitedStates.add(state);
    
    		if (state instanceof TransitionableState) {
    			TransitionableState transitionableState = (TransitionableState)state;
    			for (TransitionDefinition transitionDefinition : transitionableState.getTransitions()) {
    				Transition transition = (Transition)transitionDefinition;
    				String eventId = ((EventIdTransitionCriteria)transition.getMatchingCriteria()).getEventId();
    				String targetStateId = transition.getTargetStateResolver().toString();
    				
    				System.out.println(state.getId() + "->" + targetStateId + "[label=\"" + eventId + "\"];");
    				
    				printStateTransitions(flow.getState(targetStateId));
    			}
    		}
    	}
    }
    For the fileupload sample application this produces the following output:

    selectFile->uploadFile[label="submit"];
    uploadFile->selectFile[label="success"];
    uploadFile->selectFile[label="error"];
    This implementation is limited though, so it will only work on basic flows:
    * only EventIdTransitionCriteria are supported
    * only DefaultTargetStateResolver is supported

    Erwin

  2. #12
    Join Date
    Sep 2004
    Location
    Leuven, Belgium
    Posts
    1,853

    Default

    BTW: Shouldn't an XSLT transformation be able to generate something like this based on the XML flow definition?

    Erwin
    Last edited by klr8; Nov 30th, 2006 at 03:53 AM.

  3. #13
    Join Date
    Mar 2006
    Location
    Sydney
    Posts
    27

    Default

    Klr8,

    I had adapted the previously posted viz code for RC3 and passed it though DOT - that worked nicely.

    My compiler complains about these lines from your latest 1.0 example:


    Code:
    String eventId = ((EventIdTransitionCriteria)transition.getMatchingCriteria()).getEventId();
    String targetStateId = transition.getTargetStateResolver().toString();
    The visibility of getMatchingCriteria doesn't allow me to get the eventId. 1.0 api only allows transitions to be matched, but not inspected.



    Jamie

  4. #14
    Join Date
    Aug 2004
    Location
    Melbourne, FL
    Posts
    2,794

    Default

    Jamie,

    Klr8's name is Erwin just for future reference :-)

    Those methods are made public again in 1.0.1 nighly. 1.0.1 will be released following 1.2.9 which is currently scheduled for mid December.

    Keith
    Keith Donald
    Core Spring Development Team

  5. #15
    Join Date
    Mar 2006
    Location
    Sydney
    Posts
    27

    Default

    Keith + Erwin, OK cool. thanks for the tip.

    And thanks also for the whole Webflow thing, it's something that I've been using on several VoiceXml projects this year - it works very nicely, and brings sanity to app-navigation.

  6. #16
    Join Date
    Sep 2004
    Location
    Leuven, Belgium
    Posts
    1,853

    Default

    The methods getMatchingCriteria, getExecututionCriteria, getTargetStateResolver, and canExecute of the Transition class have been made publicin SWF 1.0.1. See JIRA issue SWF-209 for details.

    I didn't notice when I posted the code since I was compiling against my local 1.0.1 snapshots.

    Erwin

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •