Coverage Report - org.apache.myfaces.flow.FlowImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
FlowImpl
0%
0/133
0%
0/40
1.719
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements.  See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership.  The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License.  You may obtain a copy of the License at
 9  
  *
 10  
  *   http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied.  See the License for the
 16  
  * specific language governing permissions and limitations
 17  
  * under the License.
 18  
  */
 19  
 package org.apache.myfaces.flow;
 20  
 
 21  
 import java.util.ArrayList;
 22  
 import java.util.Collections;
 23  
 import java.util.HashMap;
 24  
 import java.util.HashSet;
 25  
 import java.util.List;
 26  
 import java.util.Map;
 27  
 import java.util.Set;
 28  
 import javax.el.MethodExpression;
 29  
 import javax.faces.application.NavigationCase;
 30  
 import javax.faces.context.FacesContext;
 31  
 import javax.faces.flow.Flow;
 32  
 import javax.faces.flow.FlowCallNode;
 33  
 import javax.faces.flow.FlowNode;
 34  
 import javax.faces.flow.MethodCallNode;
 35  
 import javax.faces.flow.Parameter;
 36  
 import javax.faces.flow.ReturnNode;
 37  
 import javax.faces.flow.SwitchNode;
 38  
 import javax.faces.flow.ViewNode;
 39  
 import javax.faces.lifecycle.ClientWindow;
 40  
 
 41  
 /**
 42  
  *
 43  
  * @since 2.2
 44  
  * @author Leonardo Uribe
 45  
  */
 46  
 public class FlowImpl extends Flow implements Freezable
 47  
 {
 48  
     private MethodExpression _initializer;
 49  
     private MethodExpression _finalizer;
 50  
     private String _startNodeId;
 51  
     private String _id;
 52  
     private String _definingDocumentId;
 53  
     
 54  
     private Map<String, FlowNode> _flowNodeMap;
 55  
     
 56  
     // The idea is use a normal HashMap, since there will not be modifications
 57  
     // after initialization ( all setters must call checkInitialized() )
 58  
     private Map<String, Parameter> _inboundParametersMap;
 59  
     private Map<String, FlowCallNode> _flowCallsMap;
 60  
     private List<MethodCallNode> _methodCallsList;
 61  
     private Map<String, ReturnNode> _returnsMap;
 62  
     private Map<String, SwitchNode> _switchesMap;
 63  
     private List<ViewNode> _viewsList;
 64  
     
 65  
     // Note this class should be thread safe and inmutable once
 66  
     // the flow is initialized or placed into service by the runtime.
 67  
     private Map<String, Parameter> _unmodifiableInboundParametersMap;
 68  
     private Map<String, FlowCallNode> _unmodifiableFlowCallsMap;
 69  
     private List<MethodCallNode> _unmodifiableMethodCallsList;
 70  
     private Map<String, ReturnNode> _unmodifiableReturnsMap;
 71  
     private Map<String, SwitchNode> _unmodifiableSwitchesMap;
 72  
     private List<ViewNode> _unmodifiableViewsList;
 73  
     
 74  
     private Map<String, Set<NavigationCase>> _navigationCases;
 75  
     private Map<String, Set<NavigationCase>> _unmodifiableNavigationCases;
 76  
     
 77  
     // No need to make it volatile, because FlowImpl instances are
 78  
     // created and initialized only at application startup, by a single
 79  
     // thread.
 80  
     private boolean _initialized;
 81  
     
 82  
     public FlowImpl()
 83  0
     {
 84  0
         _flowNodeMap = new HashMap<String, FlowNode>();
 85  0
         _inboundParametersMap = new HashMap<String, Parameter>();
 86  0
         _flowCallsMap = new HashMap<String, FlowCallNode>();
 87  0
         _methodCallsList = new ArrayList<MethodCallNode>();
 88  0
         _returnsMap = new HashMap<String, ReturnNode>();
 89  0
         _switchesMap = new HashMap<String, SwitchNode>();
 90  0
         _viewsList = new ArrayList<ViewNode>();
 91  0
         _navigationCases = new HashMap<String, Set<NavigationCase>>();
 92  
         
 93  
         // Collections.unmodifiableMap(...) uses delegation pattern, so as long
 94  
         // as we don't modify _inboundParametersMap in the wrong time, it
 95  
         // will be thread safe and inmutable.
 96  0
         _unmodifiableInboundParametersMap = Collections.unmodifiableMap(_inboundParametersMap);
 97  0
         _unmodifiableFlowCallsMap = Collections.unmodifiableMap(_flowCallsMap);
 98  0
         _unmodifiableMethodCallsList = Collections.unmodifiableList(_methodCallsList);
 99  0
         _unmodifiableReturnsMap = Collections.unmodifiableMap(_returnsMap);
 100  0
         _unmodifiableSwitchesMap = Collections.unmodifiableMap(_switchesMap);
 101  0
         _unmodifiableViewsList = Collections.unmodifiableList(_viewsList);
 102  
         
 103  0
         _unmodifiableNavigationCases = Collections.unmodifiableMap(_navigationCases);
 104  0
     }
 105  
     
 106  
     public void freeze()
 107  
     {
 108  
         
 109  
         
 110  0
         _initialized = true;
 111  
         
 112  0
         for (Map.Entry<String, Parameter> entry : _inboundParametersMap.entrySet())
 113  
         {
 114  0
             if (entry.getValue() instanceof Freezable)
 115  
             {
 116  0
                 ((Freezable)entry.getValue()).freeze();
 117  
             }
 118  0
         }
 119  
             
 120  0
         for (Map.Entry<String, FlowCallNode> entry : _flowCallsMap.entrySet())
 121  
         {
 122  0
             if (entry.getValue() instanceof Freezable)
 123  
             {
 124  0
                 ((Freezable)entry.getValue()).freeze();
 125  
             }
 126  0
         }
 127  
 
 128  0
         for (MethodCallNode value : _methodCallsList)
 129  
         {
 130  0
             if (value instanceof Freezable)
 131  
             {
 132  0
                 ((Freezable)value).freeze();
 133  
             }
 134  0
         }
 135  
 
 136  0
         for (Map.Entry<String, ReturnNode> entry : _returnsMap.entrySet())
 137  
         {
 138  0
             if (entry.getValue() instanceof Freezable)
 139  
             {
 140  0
                 ((Freezable)entry.getValue()).freeze();
 141  
             }
 142  0
         }
 143  
 
 144  0
         for (Map.Entry<String, SwitchNode> entry : _switchesMap.entrySet())
 145  
         {
 146  0
             if (entry.getValue() instanceof Freezable)
 147  
             {
 148  0
                 ((Freezable)entry.getValue()).freeze();
 149  
             }
 150  0
         }
 151  
         
 152  0
         for (ViewNode value : _viewsList)
 153  
         {
 154  0
             if (value instanceof Freezable)
 155  
             {
 156  0
                 ((Freezable)value).freeze();
 157  
             }
 158  0
         }
 159  0
     }
 160  
 
 161  
     @Override
 162  
     public String getClientWindowFlowId(ClientWindow curWindow)
 163  
     {
 164  0
         String id = getId();
 165  0
         String documentId = getDefiningDocumentId();
 166  
         // Faces Flow relies on ClientWindow feature, so it should be enabled,
 167  
         // and the expected id cannot be null.
 168  0
         String windowId = curWindow.getId();
 169  0
         StringBuilder sb = new StringBuilder( id.length() + 1 + windowId.length() );
 170  0
         sb.append(windowId).append('_').append(documentId).append('_').append(id);
 171  0
         return sb.toString();
 172  
     }
 173  
 
 174  
     @Override
 175  
     public String getDefiningDocumentId()
 176  
     {
 177  0
         return _definingDocumentId;
 178  
     }
 179  
     
 180  
     public void setDefiningDocumentId(String definingDocumentId)
 181  
     {
 182  0
         checkInitialized();
 183  0
         _definingDocumentId = definingDocumentId;
 184  0
     }
 185  
 
 186  
     @Override
 187  
     public String getId()
 188  
     {
 189  0
         return _id;
 190  
     }
 191  
     
 192  
     public void setId(String id)
 193  
     {
 194  0
         checkInitialized();
 195  0
         _id = id;
 196  0
     }
 197  
 
 198  
     @Override
 199  
     public MethodExpression getInitializer()
 200  
     {
 201  0
         return _initializer;
 202  
     }
 203  
     
 204  
     public void setInitializer(MethodExpression initializer)
 205  
     {
 206  0
         checkInitialized();
 207  0
         _initializer = initializer;
 208  0
     }
 209  
 
 210  
     @Override
 211  
     public MethodExpression getFinalizer()
 212  
     {
 213  0
         return _finalizer;
 214  
     }
 215  
     
 216  
     public void setFinalizer(MethodExpression finalizer)
 217  
     {
 218  0
         checkInitialized();
 219  0
         _finalizer = finalizer;
 220  0
     }
 221  
 
 222  
     @Override
 223  
     public String getStartNodeId()
 224  
     {
 225  0
         return _startNodeId;
 226  
     }
 227  
     
 228  
     public void setStartNodeId(String startNodeId)
 229  
     {
 230  0
         checkInitialized();
 231  0
         _startNodeId = startNodeId;
 232  0
     }
 233  
     
 234  
     @Override
 235  
     public Map<String, Parameter> getInboundParameters()
 236  
     {
 237  0
         return _unmodifiableInboundParametersMap;
 238  
     }
 239  
     
 240  
     public void putInboundParameter(String key, Parameter value)
 241  
     {
 242  0
         checkInitialized();
 243  0
         _inboundParametersMap.put(key, value);
 244  0
     }
 245  
     
 246  
     @Override
 247  
     public Map<String, FlowCallNode> getFlowCalls()
 248  
     {
 249  0
         return _unmodifiableFlowCallsMap;
 250  
     }
 251  
     
 252  
     public void putFlowCall(String key, FlowCallNode value)
 253  
     {
 254  0
         checkInitialized();
 255  0
         _flowCallsMap.put(key, value);
 256  0
         _flowNodeMap.put(value.getId(), value);
 257  0
     }
 258  
 
 259  
     @Override
 260  
     public List<MethodCallNode> getMethodCalls()
 261  
     {
 262  0
         return _unmodifiableMethodCallsList;
 263  
     }
 264  
 
 265  
     public void addMethodCall(MethodCallNode value)
 266  
     {
 267  0
         checkInitialized();
 268  0
         _methodCallsList.add(value);
 269  0
         _flowNodeMap.put(value.getId(), value);
 270  0
     }
 271  
 
 272  
     @Override
 273  
     public Map<String, ReturnNode> getReturns()
 274  
     {
 275  0
         return _unmodifiableReturnsMap;
 276  
     }
 277  
     
 278  
     public void putReturn(String key, ReturnNode value)
 279  
     {
 280  0
         checkInitialized();
 281  0
         _returnsMap.put(key, value);
 282  0
         _flowNodeMap.put(value.getId(), value);
 283  0
     }
 284  
 
 285  
     @Override
 286  
     public Map<String, SwitchNode> getSwitches()
 287  
     {
 288  0
         return _unmodifiableSwitchesMap;
 289  
     }
 290  
     
 291  
     public void putSwitch(String key, SwitchNode value)
 292  
     {
 293  0
         checkInitialized();
 294  0
         _switchesMap.put(key, value);
 295  0
         _flowNodeMap.put(value.getId(), value);
 296  0
     }
 297  
 
 298  
     @Override
 299  
     public List<ViewNode> getViews()
 300  
     {
 301  0
         return _unmodifiableViewsList;
 302  
     }
 303  
     
 304  
     public void addView(ViewNode value)
 305  
     {
 306  0
         checkInitialized();
 307  0
         _viewsList.add(value);
 308  0
         _flowNodeMap.put(value.getId(), value);
 309  0
     }
 310  
 
 311  
     @Override
 312  
     public FlowCallNode getFlowCall(Flow targetFlow)
 313  
     {
 314  0
         FacesContext facesContext = null;
 315  0
         for (Map.Entry<String, FlowCallNode> entry : _flowCallsMap.entrySet())
 316  
         {
 317  0
             if (facesContext == null)
 318  
             {
 319  0
                 facesContext = FacesContext.getCurrentInstance();
 320  
             }
 321  0
             String calledDocumentId = entry.getValue().getCalledFlowDocumentId(facesContext);
 322  0
             String calledFlowId = entry.getValue().getCalledFlowId(facesContext);
 323  0
             if (targetFlow.getDefiningDocumentId().equals(calledDocumentId) &&
 324  
                 targetFlow.getId().equals(calledFlowId) )
 325  
             {
 326  0
                 return entry.getValue();
 327  
             }
 328  0
         }
 329  0
         return null;
 330  
     }
 331  
     
 332  
     @Override
 333  
     public FlowNode getNode(String nodeId)
 334  
     {
 335  0
         return _flowNodeMap.get(nodeId);
 336  
     }
 337  
     
 338  
     public void addNavigationCases(String fromViewId, Set<NavigationCase> navigationCases)
 339  
     {
 340  0
         checkInitialized();
 341  0
         Set<NavigationCase> navigationCaseSet = _navigationCases.get(fromViewId);
 342  0
         if (navigationCaseSet == null)
 343  
         {
 344  0
             navigationCaseSet = new HashSet<NavigationCase>();
 345  0
             _navigationCases.put(fromViewId, navigationCaseSet);
 346  
         }
 347  0
         navigationCaseSet.addAll(navigationCases);
 348  0
     }
 349  
     
 350  
     public void addNavigationCase(NavigationCase navigationCase)
 351  
     {
 352  0
         checkInitialized();
 353  0
         Set<NavigationCase> navigationCaseSet = _navigationCases.get(navigationCase.getFromViewId());
 354  0
         if (navigationCaseSet == null)
 355  
         {
 356  0
             navigationCaseSet = new HashSet<NavigationCase>();
 357  0
             _navigationCases.put(navigationCase.getFromViewId(), navigationCaseSet);
 358  
         }
 359  0
         navigationCaseSet.add(navigationCase);
 360  0
     }
 361  
     
 362  
     public void removeNavigationCase(NavigationCase navigationCase)
 363  
     {
 364  0
         checkInitialized();
 365  0
         Set<NavigationCase> navigationCaseSet = _navigationCases.get(navigationCase.getFromViewId());
 366  0
         if (navigationCaseSet == null)
 367  
         {
 368  0
             return;
 369  
         }
 370  0
         navigationCaseSet.remove(navigationCase);
 371  0
     }
 372  
 
 373  
     private void checkInitialized() throws IllegalStateException
 374  
     {
 375  0
         if (_initialized)
 376  
         {
 377  0
             throw new IllegalStateException("Flow is inmutable once initialized");
 378  
         }
 379  0
     }
 380  
 
 381  
     @Override
 382  
     public Map<String, Set<NavigationCase>> getNavigationCases()
 383  
     {
 384  0
         return _unmodifiableNavigationCases;
 385  
     }
 386  
     
 387  
 }