Author: abelevich
Date: 2009-08-20 12:35:59 -0400 (Thu, 20 Aug 2009)
New Revision: 15239
Added:
root/ui/trunk/components/core/src/main/java/org/ajax4jsf/facelets/tag/
root/ui/trunk/components/core/src/main/java/org/ajax4jsf/facelets/tag/AjaxHandler.java
Log:
a4j:ajax Behavior tag handler
Added:
root/ui/trunk/components/core/src/main/java/org/ajax4jsf/facelets/tag/AjaxHandler.java
===================================================================
---
root/ui/trunk/components/core/src/main/java/org/ajax4jsf/facelets/tag/AjaxHandler.java
(rev 0)
+++
root/ui/trunk/components/core/src/main/java/org/ajax4jsf/facelets/tag/AjaxHandler.java 2009-08-20
16:35:59 UTC (rev 15239)
@@ -0,0 +1,155 @@
+package org.ajax4jsf.facelets.tag;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import javax.el.ELContext;
+import javax.el.MethodExpression;
+import javax.faces.application.Application;
+import javax.faces.component.UIComponent;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.context.FacesContext;
+import javax.faces.event.AbortProcessingException;
+import javax.faces.event.AjaxBehaviorEvent;
+import javax.faces.event.AjaxBehaviorListener;
+import javax.faces.view.BehaviorHolderAttachedObjectHandler;
+import javax.faces.view.facelets.BehaviorConfig;
+import javax.faces.view.facelets.CompositeFaceletHandler;
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.TagAttribute;
+import javax.faces.view.facelets.TagException;
+import javax.faces.view.facelets.TagHandler;
+
+import org.ajax4jsf.component.behavior.AjaxBehavior;
+
+/**
+ * @author Anton Belevich
+ *
+ */
+
+public class AjaxHandler extends TagHandler implements
BehaviorHolderAttachedObjectHandler {
+
+ private final TagAttribute event;
+ private final TagAttribute execute;
+ private final TagAttribute render;
+ private final TagAttribute onevent;
+ private final TagAttribute onerror;
+ private final TagAttribute disabled;
+ private final TagAttribute immediate;
+ private final TagAttribute listener;
+ private final TagAttribute limitRender;
+
+ public AjaxHandler(BehaviorConfig config) {
+ super(config);
+ this.event = this.getAttribute("event");
+ this.execute = this.getAttribute("execute");
+ this.render = this.getAttribute("render");
+ this.onevent = this.getAttribute("onevent");
+ this.onerror = this.getAttribute("onerror");
+ this.disabled = this.getAttribute("disabled");
+ this.immediate = this.getAttribute("immediate");
+ this.listener = this.getAttribute("listener");
+ this.limitRender = this.getAttribute("limitRender");
+ }
+
+ public void apply(FaceletContext f�ontext, UIComponent parent) throws IOException {
+ String eventName = getEventName();
+ if(!isWrapping()) {
+ applyAttachedObject(f�ontext, parent, eventName);
+ } else {
+ this.nextHandler.apply(f�ontext, parent);
+ }
+ }
+
+ public void applyAttachedObject(FaceletContext fContext, UIComponent parent, String
eventName) {
+ ClientBehaviorHolder bHolder = (ClientBehaviorHolder) parent;
+ if (null == eventName) {
+ eventName = bHolder.getDefaultEventName();
+ if (null == eventName) {
+ throw new TagException(this.tag, "Event attribute could not be determined:
" + eventName);
+ }
+ } else {
+ Collection<String> eventNames = bHolder.getEventNames();
+ if (!eventNames.contains(eventName)) {
+ throw new TagException(this.tag, eventName + "event is not supported for
the " + parent.getClass().getSimpleName());
+ }
+ }
+ AjaxBehavior ajaxBehavior = createBehavior(fContext, parent, eventName);
+ bHolder.addClientBehavior(eventName, ajaxBehavior);
+ }
+
+
+ public AjaxBehavior createBehavior(FaceletContext fContext, UIComponent parent, String
eventName) {
+ Application application = fContext.getFacesContext().getApplication();
+ AjaxBehavior ajaxBehavior =
(AjaxBehavior)application.createBehavior(AjaxBehavior.BEHAVIOR_ID);
+
+ setBehaviorAttribute(fContext, ajaxBehavior, this.onevent, String.class);
+ setBehaviorAttribute(fContext, ajaxBehavior, this.onerror, String.class);
+ setBehaviorAttribute(fContext, ajaxBehavior, this.disabled, Boolean.class);
+ setBehaviorAttribute(fContext, ajaxBehavior, this.immediate, Boolean.class);
+ setBehaviorAttribute(fContext, ajaxBehavior, this.execute, Object.class);
+ setBehaviorAttribute(fContext, ajaxBehavior, this.render, Object.class);
+ setBehaviorAttribute(fContext, ajaxBehavior, this.limitRender, Boolean.class);
+
+ registerBehaviorListener(fContext, ajaxBehavior, listener);
+
+ return ajaxBehavior;
+ }
+
+ public void applyAttachedObject(FacesContext context, UIComponent parent) {
+ FaceletContext ctx = (FaceletContext)
context.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
+ applyAttachedObject(ctx, parent, getEventName());
+ }
+
+ private void setBehaviorAttribute(FaceletContext ctx, AjaxBehavior behavior,
TagAttribute attr, Class<?> type) {
+ if (attr != null) {
+ behavior.setValueExpression(attr.getLocalName(),
+ attr.getValueExpression(ctx, type));
+ }
+ }
+
+ public String getEventName() {
+ return (this.event != null) ? this.event.getValue() : null;
+ }
+
+ public String getFor() {
+ return null;
+ }
+
+ private boolean isWrapping() {
+ return ((this.nextHandler instanceof TagHandler) || (this.nextHandler instanceof
CompositeFaceletHandler));
+ }
+
+ public void registerBehaviorListener(FaceletContext fContext, AjaxBehavior behavior,
TagAttribute listenerAttr) {
+ if(listenerAttr != null) {
+ MethodExpression mExpression = listenerAttr.getMethodExpression(fContext,
Object.class, new Class[]{AjaxBehaviorEvent.class});
+ behavior.addAjaxBehaviorListener(new AjaxBehaviorListenerImpl(mExpression));
+ }
+ }
+
+ public class AjaxBehaviorListenerImpl implements AjaxBehaviorListener {
+
+ private MethodExpression methodExpression;
+
+ public AjaxBehaviorListenerImpl() {};
+
+ public AjaxBehaviorListenerImpl(MethodExpression expression) {
+ this.methodExpression = expression;
+ }
+
+ public void processAjaxBehavior(AjaxBehaviorEvent event) throws
AbortProcessingException {
+ if(methodExpression != null) {
+ ELContext elContext = FacesContext.getCurrentInstance().getELContext();
+
+ try {
+ methodExpression.invoke(elContext, new Object[] {event});
+ } catch (Exception e) {
+ //TODO: log or message ??
+ throw new AbortProcessingException(e);
+ }
+ }
+ }
+
+ }
+
+}