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
015package org.apache.tapestry5.internal.services;
016
017import org.apache.tapestry5.Binding;
018import org.apache.tapestry5.BindingConstants;
019import org.apache.tapestry5.ComponentResources;
020import org.apache.tapestry5.FieldTranslator;
021import org.apache.tapestry5.FieldValidator;
022import org.apache.tapestry5.MarkupWriter;
023import org.apache.tapestry5.ValidationException;
024import org.apache.tapestry5.ValueEncoder;
025import org.apache.tapestry5.commons.Messages;
026import org.apache.tapestry5.commons.services.PropertyAccess;
027import org.apache.tapestry5.internal.TapestryInternalUtils;
028import org.apache.tapestry5.internal.bindings.InvariantBinding;
029import org.apache.tapestry5.ioc.internal.util.InternalUtils;
030import org.apache.tapestry5.runtime.Component;
031import org.apache.tapestry5.services.BindingSource;
032import org.apache.tapestry5.services.ComponentDefaultProvider;
033import org.apache.tapestry5.services.FieldTranslatorSource;
034import org.apache.tapestry5.services.FieldValidatorDefaultSource;
035import org.apache.tapestry5.services.ValueEncoderSource;
036
037public 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}