    001    // Copyright 2006, 2007, 2008, 2009, 2010, 2011 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.Arrays;
    018    import java.util.Collections;
    019    import java.util.List;
    020    import java.util.Locale;
    021
    022    import org.apache.tapestry5.SymbolConstants;
    023    import org.apache.tapestry5.func.Worker;
    024    import org.apache.tapestry5.ioc.Messages;
    025    import org.apache.tapestry5.ioc.Resource;
    026    import org.apache.tapestry5.ioc.annotations.Symbol;
    027    import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
    028    import org.apache.tapestry5.ioc.internal.util.URLChangeTracker;
    029    import org.apache.tapestry5.ioc.services.ClasspathURLConverter;
    030    import org.apache.tapestry5.model.ComponentModel;
    031    import org.apache.tapestry5.services.InvalidationEventHub;
    032    import org.apache.tapestry5.services.UpdateListener;
    033    import org.apache.tapestry5.services.messages.ComponentMessagesSource;
    034    import org.apache.tapestry5.services.messages.PropertiesFileParser;
    035    import org.apache.tapestry5.services.pageload.ComponentResourceLocator;
    036    import org.apache.tapestry5.services.pageload.ComponentResourceSelector;
    037
    038    public class ComponentMessagesSourceImpl implements ComponentMessagesSource, UpdateListener
    039    {
    040        private final MessagesSource messagesSource;
    041
    042        private final MessagesBundle appCatalogBundle;
    043
    044        private class ComponentModelBundle implements MessagesBundle
    045        {
    046            private final ComponentModel model;
    047
    048            public ComponentModelBundle(ComponentModel model)
    049            {
    050                this.model = model;
    051            }
    052
    053            public Resource getBaseResource()
    054            {
    055                return model.getBaseResource();
    056            }
    057
    058            public Object getId()
    059            {
    060                return model.getComponentClassName();
    061            }
    062
    063            public MessagesBundle getParent()
    064            {
    065                ComponentModel parentModel = model.getParentModel();
    066
    067                if (parentModel == null)
    068                    return appCatalogBundle;
    069
    070                return new ComponentModelBundle(parentModel);
    071            }
    072        }
    073
    074        public ComponentMessagesSourceImpl(@Symbol(SymbolConstants.PRODUCTION_MODE)
    075        boolean productionMode, List<Resource> appCatalogResources, PropertiesFileParser parser,
    076                ComponentResourceLocator resourceLocator, ClasspathURLConverter classpathURLConverter)
    077        {
    078            this(productionMode, appCatalogResources, resourceLocator, parser, new URLChangeTracker(classpathURLConverter));
    079        }
    080
    081        ComponentMessagesSourceImpl(boolean productionMode, Resource appCatalogResource,
    082                ComponentResourceLocator resourceLocator, PropertiesFileParser parser, URLChangeTracker tracker)
    083        {
    084            this(productionMode, Arrays.asList(appCatalogResource), resourceLocator, parser, tracker);
    085        }
    086
    087        ComponentMessagesSourceImpl(boolean productionMode, List<Resource> appCatalogResources,
    088                ComponentResourceLocator resourceLocator, PropertiesFileParser parser, URLChangeTracker tracker)
    089        {
    090            messagesSource = new MessagesSourceImpl(productionMode, productionMode ? null : tracker, resourceLocator,
    091                    parser);
    092
    093            appCatalogBundle = createAppCatalogBundle(appCatalogResources);
    094        }
    095
    096        public void checkForUpdates()
    097        {
    098            messagesSource.checkForUpdates();
    099        }
    100
    101        public Messages getMessages(ComponentModel componentModel, Locale locale)
    102        {
    103            return getMessages(componentModel, new ComponentResourceSelector(locale));
    104        }
    105
    106        public Messages getMessages(ComponentModel componentModel, ComponentResourceSelector selector)
    107        {
    108            MessagesBundle bundle = new ComponentModelBundle(componentModel);
    109
    110            return messagesSource.getMessages(bundle, selector);
    111        }
    112
    113        public Messages getApplicationCatalog(Locale locale)
    114        {
    115            return messagesSource.getMessages(appCatalogBundle, new ComponentResourceSelector(locale));
    116        }
    117
    118        private MessagesBundle createAppCatalogBundle(List<Resource> resources)
    119        {
    120            MessagesBundle current = null;
    121
    122            for (Resource r : resources)
    123            {
    124                current = createMessagesBundle(r, current);
    125            }
    126
    127            return current;
    128        }
    129
    130        private MessagesBundle createMessagesBundle(final Resource resource, final MessagesBundle parent)
    131        {
    132            return new MessagesBundle()
    133            {
    134                public Resource getBaseResource()
    135                {
    136                    return resource;
    137                }
    138
    139                public Object getId()
    140                {
    141                    return resource.getPath();
    142                }
    143
    144                public MessagesBundle getParent()
    145                {
    146                    return parent;
    147                }
    148            };
    149        }
    150
    151        public InvalidationEventHub getInvalidationEventHub()
    152        {
    153            return messagesSource;
    154        }
    155    }