001: // Copyright 2006, 2007 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.internal.structure;
016:
017: import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newCaseInsensitiveMap;
018:
019: import java.util.Locale;
020: import java.util.Map;
021:
022: import org.apache.commons.logging.Log;
023: import org.apache.tapestry.Binding;
024: import org.apache.tapestry.Block;
025: import org.apache.tapestry.ComponentEventHandler;
026: import org.apache.tapestry.ComponentResources;
027: import org.apache.tapestry.Link;
028: import org.apache.tapestry.MarkupWriter;
029: import org.apache.tapestry.internal.InternalComponentResources;
030: import org.apache.tapestry.internal.services.Instantiator;
031: import org.apache.tapestry.ioc.AnnotationProvider;
032: import org.apache.tapestry.ioc.Location;
033: import org.apache.tapestry.ioc.Messages;
034: import org.apache.tapestry.ioc.Resource;
035: import org.apache.tapestry.ioc.internal.util.TapestryException;
036: import org.apache.tapestry.ioc.services.TypeCoercer;
037: import org.apache.tapestry.model.ComponentModel;
038: import org.apache.tapestry.runtime.Component;
039: import org.apache.tapestry.runtime.RenderQueue;
040: import org.apache.tapestry.services.ComponentMessagesSource;
041:
042: /**
043: * The bridge between a component and its {@link ComponentPageElement}, that supplies all kinds of
044: * resources to the component, including access to its parameters, parameter bindings, and
045: * persistent field data.
046: */
047: public class InternalComponentResourcesImpl implements
048: InternalComponentResources {
049: private final ComponentModel _componentModel;
050:
051: private final ComponentPageElement _element;
052:
053: private final TypeCoercer _typeCoercer;
054:
055: private final Component _component;
056:
057: private final ComponentResources _containerResources;
058:
059: // Case insensitive
060: private Map<String, Binding> _bindings;
061:
062: private final ComponentMessagesSource _messagesSource;
063:
064: private Messages _messages;
065:
066: public InternalComponentResourcesImpl(ComponentPageElement element,
067: ComponentResources containerResources,
068: Instantiator componentInstantiator,
069: TypeCoercer typeCoercer,
070: ComponentMessagesSource messagesSource) {
071: _element = element;
072: _containerResources = containerResources;
073: _componentModel = componentInstantiator.getModel();
074: _typeCoercer = typeCoercer;
075: _messagesSource = messagesSource;
076:
077: _component = componentInstantiator.newInstance(this );
078: }
079:
080: public Location getLocation() {
081: return _element.getLocation();
082: }
083:
084: @Override
085: public String toString() {
086: return String.format("InternalComponentResources[%s]",
087: getCompleteId());
088: }
089:
090: public ComponentModel getComponentModel() {
091: return _componentModel;
092: }
093:
094: public Component getEmbeddedComponent(String embeddedId) {
095: return _element.getEmbeddedElement(embeddedId).getComponent();
096: }
097:
098: public Object getFieldChange(String fieldName) {
099: return _element.getFieldChange(fieldName);
100: }
101:
102: public String getId() {
103: return _element.getId();
104: }
105:
106: public boolean hasFieldChange(String fieldName) {
107: return _element.hasFieldChange(fieldName);
108: }
109:
110: public Link createActionLink(String action, boolean forForm,
111: Object... context) {
112: return _element.createActionLink(action, forForm, context);
113: }
114:
115: public Link createPageLink(String pageName, boolean override,
116: Object... context) {
117: return _element.createPageLink(pageName, override, context);
118: }
119:
120: public String getCompleteId() {
121: return _element.getCompleteId();
122: }
123:
124: public Component getComponent() {
125: return _component;
126: }
127:
128: public boolean isBound(String parameterName) {
129: return getBinding(parameterName) != null;
130: }
131:
132: public boolean isRendering() {
133: return _element.isRendering();
134: }
135:
136: public boolean triggerEvent(String eventType, Object[] context,
137: ComponentEventHandler handler) {
138: return _element.triggerEvent(eventType, context, handler);
139: }
140:
141: public String getNestedId() {
142: return _element.getNestedId();
143: }
144:
145: public Component getPage() {
146: return _element.getContainingPage().getRootComponent();
147: }
148:
149: public boolean isInvariant(String parameterName) {
150: Binding b = getBinding(parameterName);
151:
152: return b != null && b.isInvariant();
153: }
154:
155: public boolean isLoaded() {
156: return _element.isLoaded();
157: }
158:
159: public void persistFieldChange(String fieldName, Object newValue) {
160: try {
161: _element.persistFieldChange(this , fieldName, newValue);
162: } catch (Exception ex) {
163: throw new TapestryException(
164: StructureMessages.fieldPersistFailure(
165: getCompleteId(), fieldName, ex),
166: getLocation(), ex);
167: }
168: }
169:
170: public void bindParameter(String parameterName, Binding binding) {
171: if (_bindings == null)
172: _bindings = newCaseInsensitiveMap();
173:
174: _bindings.put(parameterName, binding);
175: }
176:
177: @SuppressWarnings("unchecked")
178: public <T> T readParameter(String parameterName,
179: Class<T> expectedType) {
180: Binding b = getBinding(parameterName);
181:
182: try {
183: // Will throw NPE if binding is null, but this should never be called if the
184: // parameter is not bound.
185:
186: Object boundValue = b.get();
187:
188: return _typeCoercer.coerce(boundValue, expectedType);
189: } catch (Exception ex) {
190: throw new TapestryException(StructureMessages
191: .getParameterFailure(parameterName,
192: getCompleteId(), ex), b, ex);
193: }
194: }
195:
196: public Class getBoundType(String parameterName) {
197: Binding b = getBinding(parameterName);
198:
199: return b != null ? b.getBindingType() : null;
200: }
201:
202: @SuppressWarnings("unchecked")
203: public <T> void writeParameter(String parameterName,
204: T parameterValue) {
205: Binding b = getBinding(parameterName);
206:
207: Class bindingType = b.getBindingType();
208:
209: try {
210: Object coerced = _typeCoercer.coerce(parameterValue,
211: bindingType);
212:
213: b.set(coerced);
214: } catch (Exception ex) {
215: throw new TapestryException(StructureMessages
216: .writeParameterFailure(parameterName,
217: getCompleteId(), ex), b, ex);
218: }
219: }
220:
221: private Binding getBinding(String parameterName) {
222: return _bindings == null ? null : _bindings.get(parameterName);
223: }
224:
225: public AnnotationProvider getAnnotationProvider(String parameterName) {
226: return getBinding(parameterName);
227: }
228:
229: public Log getLog() {
230: return _componentModel.getLog();
231: }
232:
233: public Component getMixinByClassName(String mixinClassName) {
234: return _element.getMixinByClassName(mixinClassName);
235: }
236:
237: public void renderInformalParameters(MarkupWriter writer) {
238: if (_bindings == null)
239: return;
240:
241: for (String name : _bindings.keySet()) {
242: // Skip all formal parameters.
243:
244: if (_componentModel.getParameterModel(name) != null)
245: continue;
246:
247: Binding b = _bindings.get(name);
248:
249: Object value = b.get();
250:
251: if (value == null)
252: continue;
253:
254: // Because Blocks can be passed in (right from the template, using <t:parameter>,
255: // we want to skip those when rending informal parameters.
256:
257: if (value instanceof Block)
258: continue;
259:
260: String valueString = _typeCoercer.coerce(value,
261: String.class);
262:
263: writer.attributes(name, valueString);
264: }
265: }
266:
267: public Component getContainer() {
268: ComponentPageElement containerElement = _element
269: .getContainerElement();
270:
271: return containerElement == null ? null : containerElement
272: .getComponent();
273: }
274:
275: public ComponentResources getContainerResources() {
276: return _containerResources;
277: }
278:
279: public Messages getContainerMessages() {
280: return _containerResources != null ? _containerResources
281: .getMessages() : null;
282: }
283:
284: public Locale getLocale() {
285: return _element.getLocale();
286: }
287:
288: public Messages getMessages() {
289: if (_messages == null)
290: _messages = _messagesSource.getMessages(_componentModel,
291: getLocale());
292:
293: return _messages;
294: }
295:
296: public Component getCoreComponent() {
297: return _element.getComponent();
298: }
299:
300: public String getElementName() {
301: return _element.getElementName();
302: }
303:
304: public void queueRender(RenderQueue queue) {
305: _element.queueRender(queue);
306: }
307:
308: public Block getBlock(String blockId) {
309: return _element.getBlock(blockId);
310: }
311:
312: public Block getBlockParameter(String parameterName) {
313: // Is allowed explicitly to not exist and be informal, otherwise the
314: // component in question would just use @Parameter.
315:
316: if (getBinding(parameterName) != null)
317: return readParameter(parameterName, Block.class);
318:
319: return null;
320: }
321:
322: public Block findBlock(String blockId) {
323: return _element.findBlock(blockId);
324: }
325:
326: public Resource getBaseResource() {
327: return _componentModel.getBaseResource();
328: }
329:
330: public String getPageName() {
331: return _element.getPageName();
332: }
333:
334: }
|