001    /*
002     * Copyright 2002-2007 the original author or authors.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005     * use this file except in compliance with the License. You may obtain a copy of
006     * the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012     * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013     * License for the specific language governing permissions and limitations under
014     * the License.
015     */
016    package org.springframework.richclient.form.builder;
017    
018    import java.util.HashMap;
019    import java.util.Map;
020    
021    import javax.swing.JComboBox;
022    import javax.swing.JComponent;
023    import javax.swing.JLabel;
024    import javax.swing.JPasswordField;
025    
026    import org.springframework.binding.form.FormModel;
027    import org.springframework.rules.constraint.Constraint;
028    import org.springframework.richclient.application.ApplicationServicesLocator;
029    import org.springframework.richclient.factory.ComponentFactory;
030    import org.springframework.richclient.form.binding.Binding;
031    import org.springframework.richclient.form.binding.BindingFactory;
032    import org.springframework.richclient.form.binding.swing.ComboBoxBinder;
033    import org.springframework.util.Assert;
034    
035    /**
036     * Base class for form builders.
037     *
038     * @author oliverh
039     * @author Mathias Broekelmann
040     */
041    public abstract class AbstractFormBuilder {
042    
043            private final BindingFactory bindingFactory;
044    
045            private ComponentFactory componentFactory;
046    
047            private FormComponentInterceptor interceptor;
048    
049            private FormComponentInterceptorFactory interceptorFactory;
050    
051            /**
052             * Default constructor providing the {@link BindingFactory}.
053             *
054             * @param bindingFactory the factory creating the {@link Binding}s.
055             */
056            protected AbstractFormBuilder(BindingFactory bindingFactory) {
057                    Assert.notNull(bindingFactory);
058                    this.bindingFactory = bindingFactory;
059            }
060    
061            /**
062             * Returns the {@link FormComponentInterceptor} that will be used when
063             * creating a component with this builder.
064             */
065            protected FormComponentInterceptor getFormComponentInterceptor() {
066                    if (interceptor == null) {
067                            if (interceptorFactory == null) {
068                                    interceptorFactory = (FormComponentInterceptorFactory) ApplicationServicesLocator.services()
069                                                    .getService(FormComponentInterceptorFactory.class);
070                            }
071                            interceptor = interceptorFactory.getInterceptor(getFormModel());
072                    }
073    
074                    return interceptor;
075            }
076    
077            /**
078             * Set the factory that delivers the {@link FormComponentInterceptor}.
079             */
080            public void setFormComponentInterceptorFactory(FormComponentInterceptorFactory interceptorFactory) {
081                    this.interceptorFactory = interceptorFactory;
082                    this.interceptor = null;
083            }
084    
085            /**
086             * Returns the {@link ComponentFactory} that delivers all the visual
087             * components.
088             */
089            protected ComponentFactory getComponentFactory() {
090                    if (componentFactory == null) {
091                            componentFactory = (ComponentFactory) ApplicationServicesLocator.services().getService(
092                                            ComponentFactory.class);
093                    }
094                    return componentFactory;
095            }
096    
097            /**
098             * Set the {@link ComponentFactory}.
099             */
100            public void setComponentFactory(ComponentFactory componentFactory) {
101                    this.componentFactory = componentFactory;
102            }
103    
104            /**
105             * Returns the {@link BindingFactory}.
106             */
107            protected BindingFactory getBindingFactory() {
108                    return bindingFactory;
109            }
110    
111            /**
112             * Convenience method to return the formModel that is used in the
113             * {@link BindingFactory} and that should be used in the builder.
114             */
115            protected FormModel getFormModel() {
116                    return bindingFactory.getFormModel();
117            }
118    
119            /**
120             * Create a binding by looking up the appropriate registered binding.
121             *
122             * @param fieldName the name of the property to bind.
123             * @return the {@link Binding} for the property which provides a component
124             * that is bound to the valueModel of the property.
125             */
126            protected Binding createDefaultBinding(String fieldName) {
127                    return getBindingFactory().createBinding(fieldName);
128            }
129    
130            /**
131             * Create a binding that uses the given component instead of its default
132             * component.
133             *
134             * @param fieldName the name of the property to bind.
135             * @param component the component to bind to the property.
136             * @return the {@link Binding} that binds the component to the valuemodel of
137             * the property.
138             */
139            protected Binding createBinding(String fieldName, JComponent component) {
140                    return getBindingFactory().bindControl(component, fieldName);
141            }
142    
143            /**
144             * Create a binding that uses the given component instead of its default
145             * component. Additionally providing a context which is used by the binding
146             * to allow custom settings.
147             *
148             * @param fieldName the name of the property to bind.
149             * @param component the component to bind to the property.
150             * @param context a map of with additional settings providing a specific
151             * context.
152             * @return the {@link Binding} that binds the component to the valuemodel of
153             * the property.
154             */
155            protected Binding createBinding(String fieldName, JComponent component, Map context) {
156                    return getBindingFactory().bindControl(component, fieldName, context);
157            }
158    
159            /**
160             * Creates a component which is used as a selector in the form. This
161             * implementation creates a {@link JComboBox}
162             *
163             * @param fieldName the name of the field for the selector
164             * @param filter an optional filter constraint
165             * @return the component to use for a selector, not null
166             */
167            protected JComponent createSelector(String fieldName, Constraint filter) {
168                    Map context = new HashMap();
169                    context.put(ComboBoxBinder.FILTER_KEY, filter);
170                    return getBindingFactory().createBinding(JComboBox.class, fieldName).getControl();
171            }
172    
173            /**
174             * Creates a component which is used as a scrollpane for a component
175             *
176             * @param fieldName the fieldname for the scrollpane
177             * @param component the component to place into the scrollpane
178             * @return the scrollpane component
179             */
180            protected JComponent createScrollPane(String fieldName, JComponent component) {
181                    return getComponentFactory().createScrollPane(component);
182            }
183    
184            /**
185             * Create a password field for the given property.
186             *
187             * @param fieldName the name of the property.
188             * @return the password field.
189             */
190            protected JPasswordField createPasswordField(String fieldName) {
191                    return getComponentFactory().createPasswordField();
192            }
193    
194            /**
195             * Create a textarea for the given property.
196             *
197             * @param fieldName the name of the property.
198             * @return the textarea.
199             */
200            protected JComponent createTextArea(String fieldName) {
201                    return getComponentFactory().createTextArea(5, 40);
202            }
203    
204            /**
205             * Create a label for the property.
206             *
207             * @param fieldName the name of the property.
208             * @param component the component of the property which is related to the
209             * label.
210             * @return a {@link JLabel} for the property.
211             */
212            protected JLabel createLabelFor(String fieldName, JComponent component) {
213                    JLabel label = getComponentFactory().createLabel("");
214                    getFormModel().getFieldFace(fieldName).configure(label);
215                    label.setLabelFor(component);
216    
217                    FormComponentInterceptor interceptor = getFormComponentInterceptor();
218                    if (interceptor != null) {
219                            interceptor.processLabel(fieldName, label);
220                    }
221    
222                    return label;
223            }
224    }