001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.gwt.client.ui.input.form;
029
030import org.opencms.gwt.client.ui.input.CmsRegexValidator;
031import org.opencms.gwt.client.ui.input.I_CmsFormField;
032import org.opencms.gwt.client.ui.input.I_CmsFormWidget;
033import org.opencms.gwt.client.ui.input.I_CmsHasGhostValue;
034import org.opencms.gwt.client.ui.input.I_CmsStringModel;
035import org.opencms.gwt.client.validation.I_CmsValidator;
036import org.opencms.util.CmsStringUtil;
037import org.opencms.xml.content.CmsXmlContentProperty;
038
039import java.util.Collection;
040import java.util.Collections;
041import java.util.LinkedHashMap;
042import java.util.Map;
043
044import com.google.common.base.Optional;
045import com.google.gwt.event.logical.shared.ValueChangeEvent;
046import com.google.gwt.event.logical.shared.ValueChangeHandler;
047import com.google.gwt.event.shared.HandlerRegistration;
048
049/**
050 * Basic implementation of the I_CmsFormField class.<p>
051 *
052 * @since 8.0.0
053 */
054public class CmsBasicFormField implements I_CmsFormField {
055
056    /** The default value of the form field. */
057    private Object m_defaultValue;
058
059    /** Description for the form field. */
060    private String m_description;
061
062    /** Handler registration of the ValueChangeHandler for the string model object, if available. */
063    private HandlerRegistration m_handlerRegistration;
064
065    /** Id of the form field.*/
066    private String m_id;
067
068    /** Label of the form field. */
069    private String m_label;
070
071    /** A map of strings containing layout information for rendering the field's widget. */
072    private LayoutData m_layoutData = new LayoutData();
073
074    /** The string model. */
075    private I_CmsStringModel m_model;
076
077    /** The current validation status (only used if the field has a validator). */
078    private I_CmsFormField.ValidationStatus m_validationStatus = I_CmsFormField.ValidationStatus.unknown;
079
080    /** Validator of the form field. */
081    private I_CmsValidator m_validator;
082
083    /** Widget of the form field. */
084    private I_CmsFormWidget m_widget;
085
086    /**
087     * Constructs a new form field.<p>
088     *
089     * @param id the id of the form field
090     * @param description the description of the form field
091     * @param label the label of the form field
092     * @param defaultValue the default value of the form field
093     * @param widget the widget of the form field
094     */
095    public CmsBasicFormField(String id, String description, String label, Object defaultValue, I_CmsFormWidget widget) {
096
097        super();
098        m_id = id;
099        m_description = description;
100        m_label = label;
101        m_widget = widget;
102        m_defaultValue = defaultValue;
103    }
104
105    /**
106     * Utility method for creating a single basic form field from an id and a property configuration.
107     *
108     * @param propertyConfig the configuration of the property
109     *
110     * @return the newly created form field
111     */
112    public static CmsBasicFormField createField(CmsXmlContentProperty propertyConfig) {
113
114        return createField(propertyConfig, Collections.<String, String> emptyMap());
115    }
116
117    /**
118     * Utility method for creating a basic form field.<p>
119     *
120     * @param propertyConfig the property configuration
121     * @param additionalParams the additional parameters
122     *
123     * @return the newly created form fields
124     */
125    public static CmsBasicFormField createField(
126        CmsXmlContentProperty propertyConfig,
127        Map<String, String> additionalParams) {
128
129        return createField(
130            propertyConfig,
131            propertyConfig.getName(),
132            CmsWidgetFactoryRegistry.instance(),
133            additionalParams,
134            false);
135    }
136
137    /**
138     * Utility method for creating a single basic form field from an id and a property configuration.
139     *
140     * @param propertyConfig the configuration of the property
141     * @param fieldId the field id
142     * @param factory a factory for creating form  widgets
143     * @param additionalParams additional field parameters
144     * @param alwaysAllowEmpty indicates an empty value is allowed
145     *
146     * @return the newly created form field
147     */
148    public static CmsBasicFormField createField(
149        CmsXmlContentProperty propertyConfig,
150        String fieldId,
151        I_CmsFormWidgetMultiFactory factory,
152        Map<String, String> additionalParams,
153        boolean alwaysAllowEmpty) {
154
155        String widgetConfigStr = propertyConfig.getWidgetConfiguration();
156        if (widgetConfigStr == null) {
157            widgetConfigStr = "";
158        }
159
160        String label = propertyConfig.getNiceName();
161        if (label == null) {
162            label = propertyConfig.getName();
163        }
164
165        String description = propertyConfig.getDescription();
166        if (CmsStringUtil.isEmpty(description)) {
167            description = "";
168        }
169
170        Map<String, String> widgetConfig = CmsStringUtil.splitAsMap(widgetConfigStr, "|", ":");
171        widgetConfig.putAll(additionalParams);
172        String widgetType = propertyConfig.getWidget();
173        I_CmsFormWidget widget = factory.createFormWidget(
174            widgetType,
175            widgetConfig,
176            Optional.fromNullable(propertyConfig.getDefault()));
177        CmsBasicFormField field = new CmsBasicFormField(
178            fieldId,
179            description,
180            label,
181            propertyConfig.getDefault(),
182            widget);
183        String ruleRegex = propertyConfig.getRuleRegex();
184        if (!CmsStringUtil.isEmpty(ruleRegex)) {
185            String error = propertyConfig.getError();
186            if (error == null) {
187                error = "??? validation error";
188            }
189            field.setValidator(new CmsRegexValidator(ruleRegex, error, alwaysAllowEmpty));
190        }
191        return field;
192    }
193
194    /**
195     * Creates a map of fields from a map of field configurations.<p>
196     *
197     * @param propertyConfigurations the map of field configurations
198     *
199     * @return a map of form fields
200     */
201    public static Map<String, I_CmsFormField> createFields(Collection<CmsXmlContentProperty> propertyConfigurations) {
202
203        // using LinkedHashMap to preserve the order
204        Map<String, I_CmsFormField> result = new LinkedHashMap<String, I_CmsFormField>();
205        for (CmsXmlContentProperty propConfig : propertyConfigurations) {
206            CmsBasicFormField field = createField(propConfig);
207            result.put(propConfig.getName(), field);
208        }
209        return result;
210
211    }
212
213    /**
214     * @see org.opencms.gwt.client.ui.input.I_CmsFormField#bind(org.opencms.gwt.client.ui.input.I_CmsStringModel)
215     */
216    public void bind(I_CmsStringModel model) {
217
218        assert m_model == null;
219        m_model = model;
220        m_handlerRegistration = m_model.addValueChangeHandler(new ValueChangeHandler<String>() {
221
222            public void onValueChange(ValueChangeEvent<String> event) {
223
224                I_CmsFormWidget widget = getWidget();
225                if ((widget instanceof I_CmsHasGhostValue)
226                    && !CmsStringUtil.isEmptyOrWhitespaceOnly(event.getValue())) {
227                    ((I_CmsHasGhostValue)widget).setGhostMode(false);
228                }
229                widget.setFormValueAsString(event.getValue());
230            }
231        });
232    }
233
234    /**
235     * @see java.lang.Object#equals(java.lang.Object)
236     */
237    @Override
238    public boolean equals(Object o) {
239
240        return (o instanceof CmsBasicFormField) && ((CmsBasicFormField)o).getId().equals(m_id);
241    }
242
243    /**
244     * @see org.opencms.gwt.client.ui.input.I_CmsFormField#getDefaultValue()
245     */
246    public Object getDefaultValue() {
247
248        return m_defaultValue;
249    }
250
251    /**
252     * @see org.opencms.gwt.client.ui.input.I_CmsFormField#getDescription()
253     */
254    public String getDescription() {
255
256        return m_description;
257    }
258
259    /**
260     * @see org.opencms.gwt.client.ui.input.I_CmsFormField#getId()
261     */
262    public String getId() {
263
264        return m_id;
265    }
266
267    /**
268     * @see org.opencms.gwt.client.ui.input.I_CmsFormField#getLabel()
269     */
270    public String getLabel() {
271
272        return m_label;
273    }
274
275    /**
276     * @see org.opencms.gwt.client.ui.input.I_CmsFormField#getLayoutData()
277     */
278    public LayoutData getLayoutData() {
279
280        return m_layoutData;
281    }
282
283    /**
284     * @see org.opencms.gwt.client.ui.input.I_CmsFormField#getModel()
285     */
286    public I_CmsStringModel getModel() {
287
288        return m_model;
289    }
290
291    /**
292     * @see org.opencms.gwt.client.ui.input.I_CmsFormField#getModelId()
293     */
294    public String getModelId() {
295
296        if (m_model != null) {
297            return m_model.getId();
298        }
299        return getId();
300    }
301
302    /**
303     * @see org.opencms.gwt.client.ui.input.I_CmsFormField#getModelValue()
304     */
305    public String getModelValue() {
306
307        if (m_model != null) {
308            return m_model.getValue();
309        }
310        return getWidget().getFormValueAsString();
311    }
312
313    /**
314     * @see org.opencms.gwt.client.ui.input.I_CmsFormField#getValidationStatus()
315     */
316    public I_CmsFormField.ValidationStatus getValidationStatus() {
317
318        return m_validator != null ? m_validationStatus : I_CmsFormField.ValidationStatus.valid;
319    }
320
321    /**
322     * @see org.opencms.gwt.client.ui.input.I_CmsFormField#getValidator()
323     */
324    public I_CmsValidator getValidator() {
325
326        return m_validator;
327    }
328
329    /**
330     * @see org.opencms.gwt.client.ui.input.I_CmsFormField#getWidget()
331     */
332    public I_CmsFormWidget getWidget() {
333
334        return m_widget;
335    }
336
337    /**
338     * @see java.lang.Object#hashCode()
339     */
340    @Override
341    public int hashCode() {
342
343        return m_id.hashCode();
344    }
345
346    /**
347     * @see org.opencms.gwt.client.ui.input.I_CmsFormField#setId(java.lang.String)
348     */
349    public void setId(String id) {
350
351        m_id = id;
352    }
353
354    /**
355     * @see org.opencms.gwt.client.ui.input.I_CmsFormField#setValidationStatus(org.opencms.gwt.client.ui.input.I_CmsFormField.ValidationStatus)
356     */
357    public void setValidationStatus(I_CmsFormField.ValidationStatus validationStatus) {
358
359        if (m_validator != null) {
360            m_validationStatus = validationStatus;
361        }
362    }
363
364    /**
365     * @see org.opencms.gwt.client.ui.input.I_CmsFormField#setValidator(org.opencms.gwt.client.validation.I_CmsValidator)
366     */
367    public void setValidator(I_CmsValidator validator) {
368
369        m_validator = validator;
370    }
371
372    /**
373     * @see org.opencms.gwt.client.ui.input.I_CmsFormField#unbind()
374     */
375    public void unbind() {
376
377        if (m_handlerRegistration != null) {
378            m_handlerRegistration.removeHandler();
379            m_handlerRegistration = null;
380        }
381    }
382
383}