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    }