All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.omnifaces.taghandler.Converter Maven / Gradle / Ivy

There is a newer version: 4.4.1
Show newest version
/*
 * Copyright OmniFaces
 *
 * 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
 *
 *     https://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.omnifaces.taghandler;

import static org.omnifaces.taghandler.DeferredTagHandlerHelper.collectDeferredAttributes;
import static org.omnifaces.taghandler.DeferredTagHandlerHelper.getValueExpression;

import java.io.IOException;
import java.io.Serializable;

import javax.el.ELContext;
import javax.el.ValueExpression;
import javax.faces.component.UIComponent;
import javax.faces.component.ValueHolder;
import javax.faces.context.FacesContext;
import javax.faces.view.facelets.ComponentHandler;
import javax.faces.view.facelets.ConverterConfig;
import javax.faces.view.facelets.ConverterHandler;
import javax.faces.view.facelets.FaceletContext;
import javax.faces.view.facelets.TagAttribute;
import javax.faces.view.facelets.TagHandlerDelegate;

import org.omnifaces.taghandler.DeferredTagHandlerHelper.DeferredAttributes;
import org.omnifaces.taghandler.DeferredTagHandlerHelper.DeferredTagHandler;
import org.omnifaces.taghandler.DeferredTagHandlerHelper.DeferredTagHandlerDelegate;
import org.omnifaces.util.Callback;

/**
 * 

* The <o:converter> is a taghandler that extends the standard <f:converter> tag * family with support for deferred value expressions in all attributes. In other words, the converter attributes are * not evaluated anymore on a per view build time basis, but just on every access like as with UI components and bean * properties. This has among others the advantage that they can be evaluated on a per-iteration basis inside an * iterating component, and that they can be set on a custom converter without needing to explicitly register it in a * tagfile. * *

Usage

*

* When you specify for example the standard <f:convertDateTime> by * converterId="javax.faces.DateTime", then you'll be able to use all its attributes such as * pattern and locale as per its documentation, but then with the possibility to supply * deferred value expressions. *

 * <o:converter converterId="javax.faces.DateTime" pattern="#{item.pattern}" locale="#{item.locale}" />
 * 
*

* The converter ID of all standard JSF converters can be found in * their javadocs. * First go to the javadoc of the class of interest, then go to CONVERTER_ID in its field summary * and finally click the Constant Field Values link to see the value. * * @author Bauke Scholtz * @see DeferredTagHandlerHelper */ public class Converter extends ConverterHandler implements DeferredTagHandler { // Constructors --------------------------------------------------------------------------------------------------- /** * The constructor. * @param config The converter config. */ public Converter(ConverterConfig config) { super(config); } // Actions -------------------------------------------------------------------------------------------------------- /** * Create a {@link javax.faces.convert.Converter} based on the binding and/or converterId * attributes as per the standard JSF <f:converter> implementation and collect the render time * attributes. Then create an anonymous Converter implementation which wraps the created * Converter and delegates the methods to it after setting the render time attributes. Finally set the * anonymous implementation on the parent component. * @param context The involved facelet context. * @param parent The parent component to set the Converter on. * @throws IOException If something fails at I/O level. */ @Override public void apply(FaceletContext context, UIComponent parent) throws IOException { boolean insideCompositeComponent = UIComponent.getCompositeComponentParent(parent) != null; if (!ComponentHandler.isNew(parent) && !insideCompositeComponent) { // If it's not new nor inside a composite component, we're finished. return; } if (!(parent instanceof ValueHolder) || (insideCompositeComponent && getAttribute("for") == null)) { // It's inside a composite component and not reattached. TagHandlerDelegate will pickup it and pass the target component back if necessary. super.apply(context, parent); return; } ValueExpression binding = getValueExpression(context, this, "binding", Object.class); ValueExpression id = getValueExpression(context, this, "converterId", String.class); javax.faces.convert.Converter converter = createInstance(context.getFacesContext(), context, binding, id); DeferredAttributes attributes = collectDeferredAttributes(context, this, converter); ((ValueHolder) parent).setConverter(new DeferredConverter(converter, binding, id, attributes)); } @Override public TagAttribute getTagAttribute(String name) { return getAttribute(name); } @Override protected TagHandlerDelegate getTagHandlerDelegate() { return new DeferredTagHandlerDelegate(this, super.getTagHandlerDelegate()); } @Override public boolean isDisabled(FaceletContext context) { return false; // This attribute isn't supported on converters anyway. } // Helpers -------------------------------------------------------------------------------------------------------- private static javax.faces.convert.Converter createInstance(final FacesContext facesContext, ELContext elContext, ValueExpression binding, ValueExpression id) { return DeferredTagHandlerHelper.createInstance(elContext, binding, id, new Callback.ReturningWithArgument() { @Override public javax.faces.convert.Converter invoke(String converterId) { return facesContext.getApplication().createConverter(converterId); } }, "converter"); } // Nested classes ------------------------------------------------------------------------------------------------- /** * So that we can have a serializable converter. * * @author Bauke Scholtz */ protected static class DeferredConverter implements javax.faces.convert.Converter, Serializable { private static final long serialVersionUID = 1L; private transient javax.faces.convert.Converter converter; private final ValueExpression binding; private final ValueExpression id; private final DeferredAttributes attributes; public DeferredConverter(javax.faces.convert.Converter converter, ValueExpression binding, ValueExpression id, DeferredAttributes attributes) { this.converter = converter; this.binding = binding; this.id = id; this.attributes = attributes; } @Override public Object getAsObject(FacesContext context, UIComponent component, String value) { javax.faces.convert.Converter converter = getConverter(context); attributes.invokeSetters(context.getELContext(), converter); return converter.getAsObject(context, component, value); } @Override public String getAsString(FacesContext context, UIComponent component, Object value) { javax.faces.convert.Converter converter = getConverter(context); attributes.invokeSetters(context.getELContext(), converter); return converter.getAsString(context, component, value); } private javax.faces.convert.Converter getConverter(FacesContext context) { if (converter == null) { converter = Converter.createInstance(context, context.getELContext(), binding, id); } return converter; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy