/*
* Copyright (c) 2001-2015, Inversoft Inc., All Rights Reserved
*
* 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.primeframework.mvc.action.result;
import javax.servlet.ServletException;
import java.io.IOException;
import java.lang.annotation.Annotation;
import org.primeframework.mvc.action.ActionInvocation;
import org.primeframework.mvc.action.ActionInvocationStore;
import org.primeframework.mvc.action.result.ForwardResult.ForwardImpl;
import org.primeframework.mvc.action.result.RedirectResult.RedirectImpl;
import org.primeframework.mvc.config.MVCConfiguration;
import org.primeframework.mvc.workflow.WorkflowChain;
import com.google.inject.Inject;
/**
* Handles invoking the result.
*
* @author Brian Pontarelli
*/
public class DefaultResultInvocationWorkflow implements ResultInvocationWorkflow {
private final ActionInvocationStore actionInvocationStore;
private final MVCConfiguration configuration;
private final ResultFactory factory;
private final ResourceLocator resourceLocator;
private final ResultStore resultStore;
@Inject
public DefaultResultInvocationWorkflow(ActionInvocationStore actionInvocationStore, MVCConfiguration configuration,
ResultStore resultStore, ResourceLocator resourceLocator,
ResultFactory factory) {
this.actionInvocationStore = actionInvocationStore;
this.configuration = configuration;
this.resultStore = resultStore;
this.resourceLocator = resourceLocator;
this.factory = factory;
}
/**
* Performs the action invocation using this process.
* <p>
* <h3>Action-less request</h3>
* <p>
* <ul> <li>Lookup an action-less result invocation</li> <li>If it doesn't exist, continue down the chain</li> <li>If
* it does exist, call the ResultRegistry to find the Result</li> <li>Invoke the Result</li> </ul>
* <p>
* <h3>Action request</h3>
* <p>
* <ul> <li>Lookup an result invocation using the action invocation, action URI and result code from the action</li>
* <li>If it doesn't exist, error out</li> <li>If it does exist, call the ResultRegistry to find the Result</li>
* <li>Invoke the Result</li> </ul>
*
* @param chain The chain.
* @throws IOException If the chain throws an IOException.
* @throws ServletException If the chain throws a ServletException or if the result can't be found.
*/
@SuppressWarnings("unchecked")
public void perform(WorkflowChain chain) throws IOException, ServletException {
try {
ActionInvocation actionInvocation = actionInvocationStore.getCurrent();
if (actionInvocation.executeResult) {
Annotation annotation = null;
String resultCode = "success";
if (actionInvocation.action != null) {
resultCode = resultStore.get();
annotation = actionInvocation.configuration.resultConfigurations.get(resultCode);
}
if (annotation == null) {
annotation = new ForwardImpl("", resultCode);
}
Result result = factory.build(annotation.annotationType());
boolean handled = result.execute(annotation);
if (!handled) {
handleContinueOrRedirect(actionInvocation, chain);
}
}
} finally {
resultStore.clear();
}
}
@SuppressWarnings("unchecked")
private void handleContinueOrRedirect(ActionInvocation actionInvocation, WorkflowChain chain) throws IOException, ServletException {
if (actionInvocation.actionURI.endsWith("/")) {
chain.continueWorkflow();
} else {
String uri = resourceLocator.locateIndex(configuration.resourceDirectory() + "/templates");
if (uri == null) {
chain.continueWorkflow();
} else {
Annotation annotation = new RedirectImpl(uri, "success", true, false);
Result redirectResult = factory.build(annotation.annotationType());
redirectResult.execute(annotation);
}
}
}
}