001    // Copyright 2005 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.tapestry.services.impl;
016    
017    import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
018    import org.apache.hivemind.Resource;
019    import org.apache.hivemind.lib.chain.ChainBuilder;
020    import org.apache.tapestry.IComponent;
021    import org.apache.tapestry.INamespace;
022    import org.apache.tapestry.engine.IPropertySource;
023    import org.apache.tapestry.event.ResetEventListener;
024    import org.apache.tapestry.services.ComponentPropertySource;
025    import org.apache.tapestry.spec.IComponentSpecification;
026    import org.apache.tapestry.util.PropertyHolderPropertySource;
027    
028    import java.util.ArrayList;
029    import java.util.List;
030    import java.util.Locale;
031    import java.util.Map;
032    
033    /**
034     * Implementation of tapestry.props.ComponentPropertySource.
035     * <p>
036     * TODO: Figure out a testing strategy for this beast!
037     *
038     * @author Howard M. Lewis Ship
039     * @since 4.0
040     */
041    public class ComponentPropertySourceImpl implements ComponentPropertySource, ResetEventListener
042    {
043        private IPropertySource _globalProperties;
044    
045        private ChainBuilder _chainBuilder;
046    
047        private Map _componentSources = new ConcurrentHashMap();
048    
049        private Map _localizedComponentSources = new ConcurrentHashMap();
050    
051        private Map _namespaceSources = new ConcurrentHashMap();
052    
053        private Map _localizedNamespaceSources = new ConcurrentHashMap();
054    
055        public void resetEventDidOccur()
056        {
057            _componentSources.clear();
058            _localizedComponentSources.clear();
059            _namespaceSources.clear();
060            _localizedNamespaceSources.clear();
061        }
062    
063        private IPropertySource getSourceForNamespace(INamespace namespace)
064        {
065            Resource key = namespace.getSpecificationLocation();
066    
067            IPropertySource result = (IPropertySource) _namespaceSources.get(key);
068    
069            if (result == null)
070            {
071                result = createSourceForNamespace(namespace);
072    
073                _namespaceSources.put(key, result);
074            }
075    
076            return result;
077        }
078    
079        private IPropertySource getSourceForComponent(IComponent component)
080        {
081            Resource key = component.getSpecification().getSpecificationLocation();
082    
083            IPropertySource result = (IPropertySource) _componentSources.get(key);
084    
085            if (result == null)
086            {
087                result = createSourceForComponent(component);
088                _componentSources.put(key, result);
089            }
090    
091            return result;
092        }
093    
094        private LocalizedPropertySource getLocalizedSourceForComponent(IComponent component)
095        {
096            Resource key = component.getSpecification().getSpecificationLocation();
097    
098            LocalizedPropertySource result = (LocalizedPropertySource) _localizedComponentSources.get(key);
099    
100            if (result == null)
101            {
102                result = new LocalizedPropertySource(getSourceForComponent(component));
103    
104                _localizedComponentSources.put(key, result);
105            }
106    
107            return result;
108        }
109    
110        private LocalizedPropertySource getLocalizedSourceForNamespace(INamespace namespace)
111        {
112            Resource key = namespace.getSpecificationLocation();
113    
114            LocalizedPropertySource result = (LocalizedPropertySource) _localizedNamespaceSources.get(key);
115    
116            if (result == null)
117            {
118                result = new LocalizedPropertySource(getSourceForNamespace(namespace));
119    
120                _localizedNamespaceSources.put(key, result);
121            }
122    
123            return result;
124        }
125    
126        private IPropertySource createSourceForComponent(IComponent component)
127        {
128            IComponentSpecification specification = component.getSpecification();
129    
130            List sources = new ArrayList();
131    
132            sources.add(new PropertyHolderPropertySource(specification));
133            sources.add(getSourceForNamespace(component.getNamespace()));
134    
135            return (IPropertySource) _chainBuilder.buildImplementation(
136              IPropertySource.class,
137              sources,
138              ImplMessages.componentPropertySourceDescription(specification));
139        }
140    
141        private IPropertySource createSourceForNamespace(INamespace namespace)
142        {
143            List sources = new ArrayList();
144    
145            sources.add(new PropertyHolderPropertySource(namespace.getSpecification()));
146            sources.add(_globalProperties);
147    
148            return (IPropertySource) _chainBuilder.buildImplementation(IPropertySource.class,
149                                                                       sources,
150                                                                       ImplMessages.namespacePropertySourceDescription(namespace));
151        }
152    
153        public String getComponentProperty(IComponent component, String propertyName)
154        {
155            return getSourceForComponent(component).getPropertyValue(propertyName);
156        }
157    
158        public String getLocalizedComponentProperty(IComponent component, Locale locale, String propertyName)
159        {
160            return getLocalizedSourceForComponent(component).getPropertyValue(propertyName, locale);
161        }
162    
163        public String getNamespaceProperty(INamespace namespace, String propertyName)
164        {
165            return getSourceForNamespace(namespace).getPropertyValue(propertyName);
166        }
167    
168        public String getLocalizedNamespaceProperty(INamespace namespace, Locale locale, String propertyName)
169        {
170            return getLocalizedSourceForNamespace(namespace).getPropertyValue(propertyName, locale);
171        }
172    
173        public void setChainBuilder(ChainBuilder chainBuilder)
174        {
175            _chainBuilder = chainBuilder;
176        }
177    
178        public void setGlobalProperties(IPropertySource globalProperties)
179        {
180            _globalProperties = globalProperties;
181        }
182    }