001    // Copyright 2007, 2008, 2009, 2010 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.tapestry5.internal.services;
016    
017    import org.apache.tapestry5.Binding;
018    import org.apache.tapestry5.BindingConstants;
019    import org.apache.tapestry5.ComponentResources;
020    import org.apache.tapestry5.FieldTranslator;
021    import org.apache.tapestry5.FieldValidator;
022    import org.apache.tapestry5.MarkupWriter;
023    import org.apache.tapestry5.ValidationException;
024    import org.apache.tapestry5.ValueEncoder;
025    import org.apache.tapestry5.internal.TapestryInternalUtils;
026    import org.apache.tapestry5.internal.bindings.InvariantBinding;
027    import org.apache.tapestry5.ioc.Messages;
028    import org.apache.tapestry5.ioc.internal.util.InternalUtils;
029    import org.apache.tapestry5.ioc.services.PropertyAccess;
030    import org.apache.tapestry5.runtime.Component;
031    import org.apache.tapestry5.services.BindingSource;
032    import org.apache.tapestry5.services.ComponentDefaultProvider;
033    import org.apache.tapestry5.services.FieldTranslatorSource;
034    import org.apache.tapestry5.services.FieldValidatorDefaultSource;
035    import org.apache.tapestry5.services.ValueEncoderSource;
036    
037    public class ComponentDefaultProviderImpl implements ComponentDefaultProvider
038    {
039        private final PropertyAccess propertyAccess;
040    
041        private final BindingSource bindingSource;
042    
043        private final ValueEncoderSource valueEncoderSource;
044    
045        private final FieldTranslatorSource fieldTranslatorSource;
046    
047        private final FieldValidatorDefaultSource fieldValidatorDefaultSource;
048    
049        static final FieldValidator NOOP_VALIDATOR = new FieldValidator()
050        {
051            public void validate(Object value) throws ValidationException
052            {
053                // Do nothing
054            }
055    
056            public void render(MarkupWriter writer)
057            {
058            }
059    
060            public boolean isRequired()
061            {
062                return false;
063            }
064        };
065    
066        public ComponentDefaultProviderImpl(PropertyAccess propertyAccess, BindingSource bindingSource,
067                                            ValueEncoderSource valueEncoderSource,
068                                            FieldTranslatorSource fieldTranslatorSource,
069                                            FieldValidatorDefaultSource fieldValidatorDefaultSource)
070        {
071            this.propertyAccess = propertyAccess;
072            this.bindingSource = bindingSource;
073            this.valueEncoderSource = valueEncoderSource;
074            this.fieldTranslatorSource = fieldTranslatorSource;
075            this.fieldValidatorDefaultSource = fieldValidatorDefaultSource;
076        }
077    
078        public String defaultLabel(ComponentResources resources)
079        {
080            assert resources != null;
081            String componentId = resources.getId();
082            String key = componentId + "-label";
083    
084            Messages containerMessages = resources.getContainerResources().getMessages();
085    
086            if (containerMessages.contains(key)) return containerMessages.get(key);
087    
088            return TapestryInternalUtils.toUserPresentable(componentId);
089        }
090    
091        public Binding defaultBinding(String parameterName, ComponentResources resources)
092        {
093            assert InternalUtils.isNonBlank(parameterName);
094            assert resources != null;
095            String componentId = resources.getId();
096    
097            Component container = resources.getContainer();
098    
099            // Only provide a default binding if the container actually contains the property.
100            // This sets up an error condition for when the parameter is not bound, and
101            // the binding can't be deduced.
102    
103            if (propertyAccess.getAdapter(container).getPropertyAdapter(componentId) == null)
104                return null;
105    
106            ComponentResources containerResources = resources.getContainerResources();
107    
108            return bindingSource.newBinding(
109                    "default " + parameterName,
110                    containerResources,
111                    BindingConstants.PROP,
112                    componentId);
113        }
114    
115        @SuppressWarnings({ "unchecked" })
116        public ValueEncoder defaultValueEncoder(String parameterName, ComponentResources resources)
117        {
118            assert InternalUtils.isNonBlank(parameterName);
119            assert resources != null;
120            Class parameterType = resources.getBoundType(parameterName);
121    
122            if (parameterType == null) return null;
123    
124            return valueEncoderSource.getValueEncoder(parameterType);
125        }
126    
127        public FieldTranslator defaultTranslator(String parameterName, ComponentResources resources)
128        {
129            return fieldTranslatorSource.createDefaultTranslator(resources, parameterName);
130        }
131    
132        public Binding defaultTranslatorBinding(final String parameterName, final ComponentResources resources)
133        {
134            String description = String.format("default translator, parameter %s of %s",
135                                               parameterName, resources.getCompleteId());
136    
137            return new InvariantBinding(resources.getLocation(), FieldTranslator.class, description)
138            {
139                public Object get()
140                {
141                    return defaultTranslator(parameterName, resources);
142                }
143            };
144        }
145    
146        public FieldValidator defaultValidator(String parameterName, ComponentResources resources)
147        {
148            FieldValidator result = fieldValidatorDefaultSource.createDefaultValidator(resources, parameterName);
149    
150            return result == null ? NOOP_VALIDATOR : result;
151        }
152    
153        public Binding defaultValidatorBinding(final String parameterName, final ComponentResources resources)
154        {
155            String description = String.format("default validator, parameter %s of %s", parameterName,
156                                               resources.getCompleteId());
157    
158            return new InvariantBinding(resources.getLocation(), FieldValidator.class, description)
159            {
160                public Object get()
161                {
162                    return defaultValidator(parameterName, resources);
163                }
164            };
165        }
166    }