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