/* * Copyright 2004-2009 the original author or authors. * * 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. */ package org.compass.core.converter.basic; import java.util.Locale; import org.compass.core.CompassException; import org.compass.core.Property; import org.compass.core.config.CompassConfigurable; import org.compass.core.config.CompassEnvironment; import org.compass.core.config.CompassSettings; import org.compass.core.converter.basic.format.Formatter; import org.compass.core.converter.basic.format.FormatterFactory; import org.compass.core.converter.basic.format.ThreadSafeFormat; import org.compass.core.util.StringUtils; /** * A base class that can handle {@link ThreadSafeFormat} and provide formatting support. * The format is read from a configuration setting {@link CompassEnvironment.Converter.Format#FORMAT}. * Uses a pool of formatters for better performance, using {@link CompassEnvironment.Converter.Format#MIN_POOL_SIZE}, * and {@link CompassEnvironment.Converter.Format#MAX_POOL_SIZE} as configuration settings for the pool size. * * <p>If specific locale is required for the formatted, the {@link CompassEnvironment.Converter.Format#LOCALE} can * be used to specify the required locale. * * <p>Allows to specify the default format if none is provided by overriding {@link #doGetDefaultFormat()}. * * @author kimchy */ public abstract class AbstractFormatConverter<T> extends AbstractBasicConverter<T> implements CompassConfigurable, FormatConverter<T> { protected Formatter[] formatters; protected boolean hasFormatter = true; protected Locale locale; public void configure(CompassSettings settings) throws CompassException { String format = settings.getSetting(CompassEnvironment.Converter.Format.FORMAT); if (format == null) { format = doGetDefaultFormat(); } String localeSetting = settings.getSetting(CompassEnvironment.Converter.Format.LOCALE); if (localeSetting != null) { locale = new Locale(localeSetting); } else { locale = Locale.getDefault(); } if (format == null) { hasFormatter = false; return; } createFormatters(format, settings); } public void setFormat(String format) { createFormatters(format, null); } public FormatConverter copy() { try { AbstractFormatConverter copy = getClass().newInstance(); copy.locale = locale; return copy; } catch (Exception e) { throw new CompassException("Should not happen", e); } } protected abstract FormatterFactory doCreateFormatterFactory(); protected String doGetDefaultFormat() { return null; } private void createFormatters(String format, CompassSettings settings) { String[] formatStrings = StringUtils.delimitedListToStringArray(format, "||"); formatters = new Formatter[formatStrings.length]; for (int i = 0; i < formatters.length; i++) { String currentFromat = formatStrings[i]; FormatterFactory formatterFactory = doCreateFormatterFactory(); formatterFactory.configure(currentFromat, locale); formatters[i] = formatterFactory.create(); if (!formatters[i].isThreadSafe()) { int minPoolSize = 4; int maxPoolSize = 20; if (settings != null) { minPoolSize = settings.getSettingAsInt(CompassEnvironment.Converter.Format.MIN_POOL_SIZE, minPoolSize); maxPoolSize = settings.getSettingAsInt(CompassEnvironment.Converter.Format.MAX_POOL_SIZE, maxPoolSize); } formatters[i] = new ThreadSafeFormat(minPoolSize, maxPoolSize, formatterFactory); } } } /** * Format based converters should can be used (and should) when using query parser notation. * Returns <code>true</code>. */ public boolean canNormalize() { return true; } /** * Formattable types should usually be {@link org.compass.core.Property.Index#NOT_ANALYZED}. */ public Property.Index suggestIndex() { return Property.Index.NOT_ANALYZED; } }