com.sun.faces.application.ValidateComponentNesting Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of javax.faces Show documentation
Show all versions of javax.faces Show documentation
This is the master POM file for Oracle's Implementation of the JSF 2.2 Specification.
package com.sun.faces.application;
import java.util.EnumSet;
import javax.faces.application.FacesMessage;
import javax.faces.application.ProjectStage;
import javax.faces.component.ActionSource;
import javax.faces.component.ActionSource2;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.component.UIForm;
import javax.faces.component.UIViewAction;
import javax.faces.component.UIViewParameter;
import javax.faces.component.UIViewRoot;
import javax.faces.component.visit.VisitCallback;
import javax.faces.component.visit.VisitContext;
import javax.faces.component.visit.VisitHint;
import javax.faces.component.visit.VisitResult;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.SystemEvent;
import javax.faces.event.SystemEventListener;
import com.sun.faces.util.MessageUtils;
/**
* ValidateFormComponentNesting performs component tree validation to assure {@link ActionSource}
* , {@link ActionSource2} and {@link EditableValueHolder} components are placed inside a form.
* ValidateFormComponentNesting is installed automatically if {@link ProjectStage#Development} is
* active.
*
* @author dueni
*
*/
public class ValidateComponentNesting implements SystemEventListener {
@Override
public boolean isListenerForSource(Object source) {
return (source instanceof UIViewRoot);
}
/**
* Process PostAddToViewEvent on UIViewRoot to validate form - action/input nesting.
*/
@Override
public void processEvent(SystemEvent event) throws AbortProcessingException {
UIComponent root = (UIComponent) event.getSource();
FacesContext jsf = FacesContext.getCurrentInstance();
EnumSet hints = EnumSet.of(VisitHint.SKIP_ITERATION);
VisitContext visitContext = VisitContext.createVisitContext(jsf, null, hints);
root.visitTree(visitContext, new ValidateFormNestingCallback());
}
static class ValidateFormNestingCallback implements VisitCallback {
// report missing form problem only once
boolean reportedOmittedFormOnce = false;
// report missing metadata problem only once
boolean reportedOmittedMetadataOnce = false;
@Override
public VisitResult visit(VisitContext context, UIComponent target) {
// default result: continue tree walk
VisitResult result = VisitResult.ACCEPT;
if (target instanceof UIForm || target.getFamily().endsWith("Form")
|| UIViewRoot.METADATA_FACET_NAME.equals(target.getId())) {
// stop tree walk if component is of type UIForm or component family ends on "Form"
// or if the component is the UIPanel with id METADATA_FACET_NAME
result = VisitResult.REJECT;
} else if (target instanceof UIViewParameter || target instanceof UIViewAction) {
if (reportedOmittedMetadataOnce) {
// report first detected problem only, then stop tree walk
result = VisitResult.COMPLETE;
}
addOmittedMessage(context.getFacesContext(), target.getClientId(context
.getFacesContext()), MessageUtils.MISSING_METADATA_ERROR);
reportedOmittedMetadataOnce = true;
} else if (target instanceof EditableValueHolder || target instanceof ActionSource
|| target instanceof ActionSource2) {
if (reportedOmittedFormOnce) {
// report first detected problem only, then stop tree walk
result = VisitResult.COMPLETE;
}
// if we find ActionSource, ActionSource2 or EditableValueHolder, that component
// must be outside of a form add warning message
addOmittedMessage(context.getFacesContext(), target.getClientId(context
.getFacesContext()), MessageUtils.MISSING_FORM_ERROR);
reportedOmittedFormOnce = true;
}
return result;
}
}
/**
* method for adding a message regarding missing ancestor to context
*
* @param ctx
* @param clientId
*/
private static void addOmittedMessage(FacesContext jsf, String clientId, String key) {
Object[] params = new Object[] {};
FacesMessage m = MessageUtils.getExceptionMessage(key, params);
m.setSeverity(FacesMessage.SEVERITY_WARN);
jsf.addMessage(clientId, m);
}
}