renderer UI CDK Guide

# Creating a Renderer Base class

After the component tree is restored on the Restore View Phase , each component in the tree extracts its new value from the request parameters by using its `decode()` method. Then the value is stored locally on the component.

In order to create `InputDateRendererBase` class you should proceed to the src/main/java/org/mycompany/renderkit directory and create this class there:

    package org.mycompany.renderkit;
    import java.io.IOException;
    import java.util.Map;
    import java.util.TimeZone;
    import javax.faces.component.UIComponent;
    import javax.faces.context.ExternalContext;
    import javax.faces.context.FacesContext;
    import javax.faces.convert.Converter;
    import javax.faces.convert.ConverterException;
    import javax.faces.convert.DateTimeConverter;
    import org.ajax4jsf.renderkit.HeaderResourcesRendererBase;
    import org.mycompany.component.UIInputDate;

    public abstract class InputDateRendererBase extends HeaderResourcesRendererBase {
    	...
    }

The `InputDateRendererBase` class extends a `HeaderResourcesRendererBase` class. In the `HeaderResourcesRendererBase` class all the `encode()` methods for the right resources encoding are already implemented, so in the `InputDateRendererBase` class you need to override the `decode()` method only:

     ...
    public void decode(FacesContext context, UIComponent component){
    	ExternalContext external = context.getExternalContext();
    	Map requestParams = external.getRequestParameterMap();
    	UIInputDate inputDate = (UIInputDate)component;
    	String clientId = inputDate.getClientId(context);
    	String submittedValue = (String)requestParams.get(clientId);
    	if (submittedValue != null) {
    		inputDate.setSubmittedValue(submittedValue);
    	}
    }
    ...

As you see in the example above the `decode()` method reads values from request parameters, grabs the `clientId` from the component to identify the request parameter to be looked up. The `clientId` is calculated as the fully qualified name of the component given its container path: nameOfForm:nameOfComponent (for example myForm:inputDate). The last step of the `decode()` method is to store the submitted value locally on the component.

Note:

By default, the base Renderer implementation returns the `submittedValue` directly without any conversion! If you want to convert submitted value to a strongly typed object you should implement Converter and the `getConvertedValue()` method in your Renderer class (in our case in the `InputDateRendererBase` class).

converter UI CDK Guide

## Creating a Converter

As it was mentioned before the <inputDate> component at the Apply Request Values phase takes a value and pushes it to the model as a strongly typed Date object. Therefore you need to implement a Converter in the Renderer Base class and also check whether a Converter has been already attached by the application developer. If the conversion of the value fails, an error message associated with the component is generated and queued on FacesContext.

The `getConverter()` method of the `InputDateRendererBase` class returns the a converter, as shown in the following example:

    ...
    private Converter getConverter(FacesContext context, UIInputDate inputDate){
    	Converter converter = inputDate.getConverter();
    	if (converter == null){
    		// default the converter
    		DateTimeConverter datetime = new DateTimeConverter();
    		datetime.setLocale(context.getViewRoot().getLocale());
    		datetime.setTimeZone(TimeZone.getDefault());
    		datetime.setType("date");
    		datetime.setDateStyle("medium");
    		datetime.setPattern("d/m/y");
    		converter = datetime;
    	}
    	return converter;
    }
    ...

During the converter creation you should check whether the application developer has attached a Converter to the <inputDate> component already (for example, <f:convertDateTime>) . If not you should follow the next steps:

- create a new DateTimeConverter

- get the locale for the client from the context with the help of the `getLocale()` method and set it on the new Converter by means of the `setLocale()` method

- set the time zone, date type, date style, and date pattern on the new converter with the help of `setTimeZone()`, `setType()`, `setDateStyle()`, and `setPattern()` methods respectively

- return the Converter

After the Apply Request Values phase the application enters the Process Validation phase during which the `validate()` method calls the `getConvertedValue()` method on every submitted value and passes the newly submitted value from the decode process.

The `getConvertedValue()` method converts the submitted value to a strongly typed object (in our case Date) using the `getAsObject()` method. Then the new strongly typed object is validated and if there are no errors Process Validation phase ends. Otherwise the `getConvertedValue()` method throws a ConverterException.

Here is the snippet:

    ...
    public Object getConvertedValue(FacesContext context, UIComponent component, Object submittedValue) throws ConverterException{
    	UIInputDate inputDate = (UIInputDate)component;
    	Converter converter = getConverter(context, inputDate);
    	String valueString = (String)submittedValue;
    	return converter.getAsObject(context, component, valueString);
    }
    ...

Finally on the Renderer Response phase the value of the component is rendered back to the view. The converter is responsible for transforming the object data back in to a string representation, so you need to implement `getValueAsString()` method:

Here is the example:

    ...
    protected String getValueAsString(FacesContext context, UIComponent component) throws IOException {
    	UIInputDate inputDate = (UIInputDate) component;
    	String valueString = (String) inputDate.getSubmittedValue();
    	if (valueString == null) {
    		Object value = inputDate.getValue();
    		if (value != null) {
    			Converter converter = getConverter(context, inputDate);
    			valueString = converter.getAsString(context, component, value);
    		}
    	}
    	return valueString;
    }
    ...

You could find the whole example of the `InputDateRendererBase` class inInputDateRendererBase.java file.