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
015package org.apache.tapestry5.internal.services;
016
017import java.util.Arrays;
018import java.util.Collections;
019import java.util.List;
020import java.util.Locale;
021
022import org.apache.tapestry5.SymbolConstants;
023import org.apache.tapestry5.func.Worker;
024import org.apache.tapestry5.ioc.Messages;
025import org.apache.tapestry5.ioc.Resource;
026import org.apache.tapestry5.ioc.annotations.Symbol;
027import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
028import org.apache.tapestry5.ioc.internal.util.URLChangeTracker;
029import org.apache.tapestry5.ioc.services.ClasspathURLConverter;
030import org.apache.tapestry5.model.ComponentModel;
031import org.apache.tapestry5.services.InvalidationEventHub;
032import org.apache.tapestry5.services.UpdateListener;
033import org.apache.tapestry5.services.messages.ComponentMessagesSource;
034import org.apache.tapestry5.services.messages.PropertiesFileParser;
035import org.apache.tapestry5.services.pageload.ComponentResourceLocator;
036import org.apache.tapestry5.services.pageload.ComponentResourceSelector;
037
038public 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}