001    // Copyright 2007, 2008, 2010 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    // http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry5.internal.services;
016    
017    import java.util.Collections;
018    import java.util.List;
019    import java.util.Map;
020    
021    import org.apache.tapestry5.Translator;
022    import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
023    import org.apache.tapestry5.ioc.util.AvailableValues;
024    import org.apache.tapestry5.ioc.util.StrategyRegistry;
025    import org.apache.tapestry5.ioc.util.UnknownValueException;
026    import org.apache.tapestry5.services.InvalidationListener;
027    import org.apache.tapestry5.services.TranslatorSource;
028    
029    @SuppressWarnings("unchecked")
030    public class TranslatorSourceImpl implements TranslatorSource, InvalidationListener
031    {
032        private final Map<String, Translator> nameToTranslator = CollectionFactory.newCaseInsensitiveMap();
033    
034        private final StrategyRegistry<Translator> registry;
035    
036        private static final Map<String, Translator> EMPTY = Collections.emptyMap();
037    
038        public TranslatorSourceImpl(Map<Class, Translator> configuration)
039        {
040            this(configuration, EMPTY);
041        }
042    
043        public TranslatorSourceImpl(Map<Class, Translator> configuration, Map<String, Translator> alternates)
044        {
045            for (Map.Entry<Class, Translator> me : configuration.entrySet())
046            {
047                Class type = me.getKey();
048                Translator translator = me.getValue();
049    
050                if (!type.equals(translator.getType()))
051                    throw new RuntimeException(
052                            String
053                                    .format(
054                                            "Contributed translator for type %s reports its type as %s. Please change the contribution so that the key matches that translator type.",
055                                            type.getName(), translator.getType().getName()));
056    
057                String name = translator.getName();
058    
059                if (nameToTranslator.containsKey(name))
060                    throw new RuntimeException(
061                            String
062                                    .format(
063                                            "Two different Translators contributed to the TranslatorSource service use the same translator name: '%s'.  Translator names must be unique.",
064                                            name));
065    
066                nameToTranslator.put(name, translator);
067            }
068    
069            for (String name : alternates.keySet())
070            {
071                if (nameToTranslator.containsKey(name))
072                    throw new RuntimeException(
073                            String
074                                    .format(
075                                            "Translator '%s' contributed to the TranslatorAlternatesSource service has the same name as a standard Translator contributed to the TranslatorSource service.",
076                                            name));
077    
078                nameToTranslator.put(name, alternates.get(name));
079            }
080    
081            registry = StrategyRegistry.newInstance(Translator.class, configuration, true);
082        }
083    
084        public Translator get(String name)
085        {
086            Translator result = nameToTranslator.get(name);
087    
088            if (result == null)
089                throw new UnknownValueException(String.format("Unknown translator type '%s'.", name), new AvailableValues(
090                        "Configured translators", nameToTranslator));
091    
092            return result;
093        }
094    
095        public Translator getByType(Class valueType)
096        {
097            Translator result = registry.get(valueType);
098    
099            if (result == null)
100            {
101                List<String> names = CollectionFactory.newList();
102    
103                for (Class type : registry.getTypes())
104                {
105                    names.add(type.getName());
106                }
107    
108                throw new IllegalArgumentException(ServicesMessages.noTranslatorForType(valueType, names));
109            }
110    
111            return result;
112        }
113    
114        public Translator findByType(Class valueType)
115        {
116            return registry.get(valueType);
117        }
118    
119        public void objectWasInvalidated()
120        {
121            registry.clearCache();
122        }
123    }