Package org.springframework.springfaces.mvc.internal

Source Code of org.springframework.springfaces.mvc.internal.MvcNavigationHandler$NavigationContextImpl

/*
* Copyright 2010-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.springfaces.mvc.internal;

import java.util.Iterator;

import javax.faces.FacesException;
import javax.faces.application.ConfigurableNavigationHandler;
import javax.faces.application.FacesMessage;
import javax.faces.application.NavigationCase;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.PreRenderComponentEvent;

import org.springframework.springfaces.application.ConfigurableNavigationHandlerWrapper;
import org.springframework.springfaces.mvc.context.SpringFacesContext;
import org.springframework.springfaces.mvc.navigation.NavigationContext;
import org.springframework.springfaces.mvc.navigation.NavigationOutcome;
import org.springframework.springfaces.mvc.navigation.NavigationOutcomeResolver;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

/**
* A JSF {@link ConfigurableNavigationHandler} that provides integration with Spring MVC. Note: This handler depends on
* the {@link MvcNavigationSystemEventListener} and {@link MvcNavigationActionListener} also being registered.
*
* @author Phillip Webb
*/
public class MvcNavigationHandler extends ConfigurableNavigationHandlerWrapper {

  private ConfigurableNavigationHandler delegate;
  private NavigationOutcomeResolver navigationOutcomeResolver;
  private DestinationAndModelRegistry destinationAndModelRegistry = new DestinationAndModelRegistry();

  public MvcNavigationHandler(ConfigurableNavigationHandler delegate,
      NavigationOutcomeResolver navigationOutcomeResolver) {
    this.delegate = delegate;
    this.navigationOutcomeResolver = navigationOutcomeResolver;
  }

  @Override
  public ConfigurableNavigationHandler getWrapped() {
    return this.delegate;
  }

  @Override
  public NavigationCase getNavigationCase(FacesContext context, String fromAction, String outcome) {
    if (SpringFacesContext.getCurrentInstance() != null) {
      PreRenderComponentEvent preRenderComponentEvent = MvcNavigationSystemEventListener
          .getLastPreRenderComponentEvent(context);
      UIComponent component = (preRenderComponentEvent == null ? null : preRenderComponentEvent.getComponent());
      String defaultDestinationViewId = getDefaultDestinationViewId(context, fromAction, outcome);
      NavigationContext navigationContext = new NavigationContextImpl(fromAction, outcome, true, component,
          defaultDestinationViewId);
      if (this.navigationOutcomeResolver.canResolve(context, navigationContext)) {
        try {
          NavigationOutcome navigationOutcome = this.navigationOutcomeResolver.resolve(context,
              navigationContext);
          Assert.state(navigationOutcome != null, "Unable to resolve required navigation outcome '" + outcome
              + "'");
          UIViewRoot root = context.getViewRoot();
          String fromViewId = (root != null ? root.getViewId() : null);
          String toViewId = this.destinationAndModelRegistry.put(context, new DestinationAndModel(
              navigationOutcome, preRenderComponentEvent));
          return new NavigationCase(fromViewId, fromAction, outcome, null, toViewId, null, false, false);
        } catch (Exception e) {
          throw new FacesException(e);
        }
      }
    }
    return super.getNavigationCase(context, fromAction, outcome);
  }

  @Override
  public void handleNavigation(FacesContext context, String fromAction, String outcome) {
    if (SpringFacesContext.getCurrentInstance() != null) {
      ActionEvent actionEvent = MvcNavigationActionListener.getLastActionEvent(context);
      UIComponent component = (actionEvent == null ? null : actionEvent.getComponent());
      String defaultDestinationViewId = getDefaultDestinationViewId(context, fromAction, outcome);
      NavigationContext navigationContext = new NavigationContextImpl(fromAction, outcome, false, component,
          defaultDestinationViewId);
      if (this.navigationOutcomeResolver.canResolve(context, navigationContext)) {
        try {
          NavigationOutcome navigationOutcome = this.navigationOutcomeResolver.resolve(context,
              navigationContext);
          if (navigationOutcome != null) {
            String viewId = this.destinationAndModelRegistry.put(context, new DestinationAndModel(
                navigationOutcome, actionEvent));
            UIViewRoot newRoot = context.getApplication().getViewHandler().createView(context, viewId);
            context.setViewRoot(newRoot);
          }
        } catch (Exception e) {
          throw new FacesException(e);
        }
        return;
      }
    }
    super.handleNavigation(context, fromAction, outcome);
  }

  private String getDefaultDestinationViewId(FacesContext context, String fromAction, String outcome) {
    int numberOfMessages = context.getMessageList().size();
    NavigationCase navigationCase = super.getNavigationCase(context, fromAction, outcome);
    // If the navigation handler has inserted warning messages about missing navigation cases we need
    // to remove them, we are subverting the use of getNavigationCase a little and it does not matter
    // if we cannot find a case
    Iterator<FacesMessage> messages = context.getMessages();
    while (messages.hasNext()) {
      messages.next();
      numberOfMessages--;
      if (numberOfMessages < 0) {
        messages.remove();
      }
    }
    if (navigationCase == null) {
      return null;
    }
    String defaultDestinationViewId = navigationCase.getToViewId(context);
    if (StringUtils.hasLength(defaultDestinationViewId) && defaultDestinationViewId.startsWith("/")) {
      defaultDestinationViewId = defaultDestinationViewId.substring(1);
    }
    return defaultDestinationViewId;
  }

  /**
   * Allows the {@link DestinationAndModelRegistry} to be changed for testing.
   * @param destinationAndModelRegistry the replacement registry
   */
  final void setDestinationAndModelRegistry(DestinationAndModelRegistry destinationAndModelRegistry) {
    this.destinationAndModelRegistry = destinationAndModelRegistry;
  }

  /**
   * Implementation of the {@link NavigationContext}.
   */
  private static class NavigationContextImpl implements NavigationContext {

    private String fromAction;
    private String outcome;
    private boolean preEmptive;
    private UIComponent component;
    private String defaultDestinationViewId;

    public NavigationContextImpl(String fromAction, String outcome, boolean preEmptive, UIComponent component,
        String defaultDestinationViewId) {
      this.fromAction = fromAction;
      this.outcome = outcome;
      this.preEmptive = preEmptive;
      this.component = component;
      this.defaultDestinationViewId = defaultDestinationViewId;
    }

    public Object getHandler() {
      return SpringFacesContext.getCurrentInstance().getHandler();
    }

    public Object getController() {
      return SpringFacesContext.getCurrentInstance().getController();
    }

    public String getFromAction() {
      return this.fromAction;
    }

    public String getOutcome() {
      return this.outcome;
    }

    public boolean isPreemptive() {
      return this.preEmptive;
    }

    public UIComponent getComponent() {
      return this.component;
    }

    public String getDefaultDestinationViewId() {
      return this.defaultDestinationViewId;
    }
  }
}
TOP

Related Classes of org.springframework.springfaces.mvc.internal.MvcNavigationHandler$NavigationContextImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.