org.apache.wicket.ConverterLocator.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.wicket.ConverterLocator.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.wicket;

import java.lang.ref.WeakReference;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import org.apache.wicket.util.convert.ConversionException;
import org.apache.wicket.util.convert.IConverter;
import org.apache.wicket.util.convert.converter.BigDecimalConverter;
import org.apache.wicket.util.convert.converter.BigIntegerConverter;
import org.apache.wicket.util.convert.converter.BooleanConverter;
import org.apache.wicket.util.convert.converter.ByteConverter;
import org.apache.wicket.util.convert.converter.CalendarConverter;
import org.apache.wicket.util.convert.converter.CharacterConverter;
import org.apache.wicket.util.convert.converter.DateConverter;
import org.apache.wicket.util.convert.converter.DoubleConverter;
import org.apache.wicket.util.convert.converter.FloatConverter;
import org.apache.wicket.util.convert.converter.IntegerConverter;
import org.apache.wicket.util.convert.converter.LocalDateConverter;
import org.apache.wicket.util.convert.converter.LocalDateTimeConverter;
import org.apache.wicket.util.convert.converter.LocalTimeConverter;
import org.apache.wicket.util.convert.converter.LongConverter;
import org.apache.wicket.util.convert.converter.ShortConverter;
import org.apache.wicket.util.convert.converter.SqlDateConverter;
import org.apache.wicket.util.convert.converter.SqlTimeConverter;
import org.apache.wicket.util.convert.converter.SqlTimestampConverter;
import org.apache.wicket.util.convert.converter.ZonedDateTimeConverter;
import org.apache.wicket.util.lang.Args;
import org.apache.wicket.util.lang.Objects;

/**
 * Implementation of {@link IConverterLocator} interface, which locates converters for a given type.
 * It serves as a registry for {@link IConverter} instances stored by type, and is the default
 * locator for Wicket.
 * 
 * @see IConverterLocator
 * @author Eelco Hillenius
 * @author Jonathan Locke
 * 
 */
public class ConverterLocator implements IConverterLocator {
    /**
     * ConverterLocator that is to be used when no registered converter is found.
     * 
     * @param <C>
     *            The object to convert from and to String
     */
    private static class DefaultConverter<C> implements IConverter<C> {
        private static final long serialVersionUID = 1L;

        private final transient WeakReference<Class<C>> type;

        /**
         * Construct.
         * 
         * @param type
         */
        private DefaultConverter(Class<C> type) {
            this.type = new WeakReference<>(type);
        }

        @Override
        public C convertToObject(String value, Locale locale) {
            if (value == null) {
                return null;
            }
            Class<C> theType = type.get();
            if ("".equals(value)) {
                if (String.class.equals(theType)) {
                    return theType.cast("");
                }
                return null;
            }

            try {
                C converted = Objects.convertValue(value, theType);
                if (converted != null) {
                    return converted;
                }

                if (theType != null && theType.isInstance(value)) {
                    return theType.cast(value);
                }
            } catch (Exception e) {
                throw new ConversionException(e.getMessage(), e).setSourceValue(value);
            }

            throw new ConversionException("Could not convert value: " + value + " to type: " + theType.getName()
                    + ". Could not find compatible converter.").setSourceValue(value);
        }

        @Override
        public String convertToString(C value, Locale locale) {
            if (value == null || "".equals(value)) {
                return "";
            }

            try {
                return Objects.convertValue(value, String.class);
            } catch (RuntimeException e) {
                throw new ConversionException("Could not convert object of type: " + value.getClass()
                        + " to String. Possible its #toString() returned null. "
                        + "Either install a custom converter (see IConverterLocator) or "
                        + "override #toString() to return a non-null value.", e).setSourceValue(value)
                                .setConverter(this);
            }
        }
    }

    private static final long serialVersionUID = 1L;

    /** Maps Classes to ITypeConverters. */
    private final Map<String, IConverter<?>> classToConverter = new HashMap<>();

    /**
     * Constructor
     */
    public ConverterLocator() {
        set(Boolean.TYPE, BooleanConverter.INSTANCE);
        set(Boolean.class, BooleanConverter.INSTANCE);
        set(Byte.TYPE, ByteConverter.INSTANCE);
        set(Byte.class, ByteConverter.INSTANCE);
        set(Character.TYPE, CharacterConverter.INSTANCE);
        set(Character.class, CharacterConverter.INSTANCE);
        set(Double.TYPE, DoubleConverter.INSTANCE);
        set(Double.class, DoubleConverter.INSTANCE);
        set(Float.TYPE, FloatConverter.INSTANCE);
        set(Float.class, FloatConverter.INSTANCE);
        set(Integer.TYPE, IntegerConverter.INSTANCE);
        set(Integer.class, IntegerConverter.INSTANCE);
        set(Long.TYPE, LongConverter.INSTANCE);
        set(Long.class, LongConverter.INSTANCE);
        set(Short.TYPE, ShortConverter.INSTANCE);
        set(Short.class, ShortConverter.INSTANCE);
        set(BigDecimal.class, new BigDecimalConverter());
        set(BigInteger.class, new BigIntegerConverter());
        set(Date.class, new DateConverter());
        set(java.sql.Date.class, new SqlDateConverter());
        set(java.sql.Time.class, new SqlTimeConverter());
        set(java.sql.Timestamp.class, new SqlTimestampConverter());
        set(Calendar.class, new CalendarConverter());
        set(LocalDate.class, new LocalDateConverter());
        set(LocalDateTime.class, new LocalDateTimeConverter());
        set(LocalTime.class, new LocalTimeConverter());
        set(ZonedDateTime.class, new ZonedDateTimeConverter());
    }

    /**
     * Gets the type converter that is registered for class c.
     * 
     * @param <C>
     *            The object to convert from and to String
     * @param c
     *            The class to get the type converter for
     * @return The type converter that is registered for class c or null if no type converter was
     *         registered for class c
     */
    public final <C> IConverter<C> get(Class<C> c) {
        return (IConverter<C>) classToConverter.get(c.getName());
    }

    /**
     * Converts the given value to class c.
     * 
     * @param type
     *            Class to get the converter for.
     * 
     * @return The converter for the given type
     * 
     * @see org.apache.wicket.util.convert.IConverter#convertToObject(String, java.util.Locale)
     */
    @Override
    public final <C> IConverter<C> getConverter(Class<C> type) {
        // Null is always converted to null
        if (type == null) {
            @SuppressWarnings("unchecked")
            IConverter<C> converter = (IConverter<C>) new DefaultConverter<String>(String.class);
            return converter;
        }

        // Get type converter for class
        final IConverter<C> converter = get(type);
        if (converter == null) {
            return new DefaultConverter<>(type);
        }
        return converter;
    }

    /**
     * Removes the type converter currently registered for class c.
     * 
     * @param c
     *            The class for which the converter registration should be removed
     * @return The converter that was registered for class c before removal or null if none was
     *         registered
     */
    public final IConverter<?> remove(Class<?> c) {
        return classToConverter.remove(c.getName());
    }

    /**
     * Registers a converter for use with class c.
     * 
     * @param converter
     *            The converter to add
     * @param c
     *            The class for which the converter should be used
     * @return The previous registered converter for class c or null if none was registered yet for
     *         class c
     */
    public final IConverter<?> set(final Class<?> c, final IConverter<?> converter) {
        Args.notNull(c, "Class");
        Args.notNull(converter, "converter");
        return classToConverter.put(c.getName(), converter);
    }
}