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
015package org.apache.tapestry.services.impl;
016
017import java.util.ArrayList;
018import java.util.HashMap;
019import java.util.List;
020import java.util.Locale;
021import java.util.Map;
022
023import org.apache.hivemind.Resource;
024import org.apache.hivemind.lib.chain.ChainBuilder;
025import org.apache.tapestry.IComponent;
026import org.apache.tapestry.INamespace;
027import org.apache.tapestry.engine.IPropertySource;
028import org.apache.tapestry.event.ResetEventListener;
029import org.apache.tapestry.services.ComponentPropertySource;
030import org.apache.tapestry.spec.IComponentSpecification;
031import org.apache.tapestry.util.PropertyHolderPropertySource;
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 */
041public class ComponentPropertySourceImpl implements ComponentPropertySource, ResetEventListener
042{
043    private IPropertySource _globalProperties;
044
045    private ChainBuilder _chainBuilder;
046
047    private Map _componentSources = new HashMap();
048
049    private Map _localizedComponentSources = new HashMap();
050
051    private Map _namespaceSources = new HashMap();
052
053    private Map _localizedNamespaceSources = new HashMap();
054
055    public synchronized void resetEventDidOccur()
056    {
057        _componentSources.clear();
058        _localizedComponentSources.clear();
059        _namespaceSources.clear();
060        _localizedNamespaceSources.clear();
061    }
062
063    private synchronized 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            _namespaceSources.put(key, result);
073        }
074
075        return result;
076    }
077
078    private synchronized IPropertySource getSourceForComponent(IComponent component)
079    {
080        Resource key = component.getSpecification().getSpecificationLocation();
081
082        IPropertySource result = (IPropertySource) _componentSources.get(key);
083
084        if (result == null)
085        {
086            result = createSourceForComponent(component);
087            _componentSources.put(key, result);
088        }
089
090        return result;
091    }
092
093    private synchronized LocalizedPropertySource getLocalizedSourceForComponent(IComponent component)
094    {
095        Resource key = component.getSpecification().getSpecificationLocation();
096
097        LocalizedPropertySource result = (LocalizedPropertySource) _localizedComponentSources
098                .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 synchronized LocalizedPropertySource getLocalizedSourceForNamespace(INamespace namespace)
111    {
112        Resource key = namespace.getSpecificationLocation();
113
114        LocalizedPropertySource result = (LocalizedPropertySource) _localizedNamespaceSources
115                .get(key);
116
117        if (result == null)
118        {
119            result = new LocalizedPropertySource(getSourceForNamespace(namespace));
120
121            _localizedNamespaceSources.put(key, result);
122        }
123
124        return result;
125    }
126
127    private IPropertySource createSourceForComponent(IComponent component)
128    {
129        IComponentSpecification specification = component.getSpecification();
130
131        List sources = new ArrayList();
132
133        sources.add(new PropertyHolderPropertySource(specification));
134        sources.add(getSourceForNamespace(component.getNamespace()));
135
136        return (IPropertySource) _chainBuilder.buildImplementation(
137                IPropertySource.class,
138                sources,
139                ImplMessages.componentPropertySourceDescription(specification));
140    }
141
142    private IPropertySource createSourceForNamespace(INamespace namespace)
143    {
144        List sources = new ArrayList();
145
146        sources.add(new PropertyHolderPropertySource(namespace.getSpecification()));
147        sources.add(_globalProperties);
148
149        return (IPropertySource) _chainBuilder.buildImplementation(
150                IPropertySource.class,
151                sources,
152                ImplMessages.namespacePropertySourceDescription(namespace));
153    }
154
155    public String getComponentProperty(IComponent component, String propertyName)
156    {
157        return getSourceForComponent(component).getPropertyValue(propertyName);
158    }
159
160    public String getLocalizedComponentProperty(IComponent component, Locale locale,
161            String propertyName)
162    {
163        return getLocalizedSourceForComponent(component).getPropertyValue(propertyName, locale);
164    }
165
166    public String getNamespaceProperty(INamespace namespace, String propertyName)
167    {
168        return getSourceForNamespace(namespace).getPropertyValue(propertyName);
169    }
170
171    public String getLocalizedNamespaceProperty(INamespace namespace, Locale locale,
172            String propertyName)
173    {
174        return getLocalizedSourceForNamespace(namespace).getPropertyValue(propertyName, locale);
175    }
176
177    public void setChainBuilder(ChainBuilder chainBuilder)
178    {
179        _chainBuilder = chainBuilder;
180    }
181
182    public void setGlobalProperties(IPropertySource globalProperties)
183    {
184        _globalProperties = globalProperties;
185    }
186}