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 }