/* * #%L * Lapis JSF Exporter Core * %% * Copyright (C) 2013 - 2015 Lapis Software Associates * %% * 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 * * 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. * #L% */ package com.lapis.jsfexporter; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.ServiceLoader; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.lapis.jsfexporter.spi.IValueFormatter; public class ValueFormatterFactory { private static final Logger L = LoggerFactory.getLogger(ValueFormatterFactory.class); private static final String LOADED_KEY = ValueFormatterFactory.class.getName() + "-loaded"; private static final String COMPUTED_KEY = ValueFormatterFactory.class.getName() + "-computed"; public static void initialize(FacesContext context) { List<IValueFormatter<?>> availableFormatters = new ArrayList<IValueFormatter<?>>(); ServiceLoader<IValueFormatter> loader = ServiceLoader.load(IValueFormatter.class); for (IValueFormatter<?> loadedFormatter : loader) { availableFormatters.add(loadedFormatter); L.debug("Registered class {} for component type {}", loadedFormatter.getClass().getName(), loadedFormatter.getSupportedClass().getName()); } Map<String, Object> applicationMap = context.getExternalContext().getApplicationMap(); applicationMap.put(LOADED_KEY, availableFormatters); applicationMap.put(COMPUTED_KEY, new ConcurrentHashMap<Class<?>, IValueFormatter<?>>()); } public static <T extends UIComponent> IValueFormatter<T> getValueFormatter(FacesContext context, T componentToExport) { Map<String, Object> applicationMap = context.getExternalContext().getApplicationMap(); ConcurrentMap<Class<?>, IValueFormatter<?>> formatters = (ConcurrentMap<Class<?>, IValueFormatter<?>>) applicationMap.get(COMPUTED_KEY); Class<?> componentType = componentToExport.getClass(); IValueFormatter<T> formatter = (IValueFormatter<T>) formatters.get(componentType); if (formatter == null) { List<IValueFormatter<?>> availableFormatters = (List<IValueFormatter<?>>) applicationMap.get(LOADED_KEY); for (IValueFormatter<?> availableFormatter : availableFormatters) { if (availableFormatter.getSupportedClass().isAssignableFrom(componentType) && (formatter == null || formatter.getPrecedence() < availableFormatter.getPrecedence())) { formatter = (IValueFormatter<T>) availableFormatter; } } formatters.putIfAbsent(componentType, formatter); L.debug("Calculated formatter {} for component type {}", formatter.getClass().getName(), componentType.getName()); } return formatter; } }