001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (C) Alkacon Software (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.property.definition;
029
030import org.opencms.gwt.client.CmsCoreProvider;
031import org.opencms.gwt.client.rpc.CmsRpcAction;
032import org.opencms.gwt.client.ui.CmsPopup;
033import org.opencms.gwt.client.ui.CmsPushButton;
034import org.opencms.gwt.client.ui.css.I_CmsInputLayoutBundle;
035import org.opencms.gwt.client.ui.input.CmsTextBox;
036import org.opencms.util.CmsStringUtil;
037
038import java.util.Collection;
039import java.util.HashSet;
040import java.util.Set;
041
042import com.google.gwt.core.client.GWT;
043import com.google.gwt.event.dom.client.ClickEvent;
044import com.google.gwt.event.dom.client.KeyPressEvent;
045import com.google.gwt.event.dom.client.KeyPressHandler;
046import com.google.gwt.uibinder.client.UiBinder;
047import com.google.gwt.uibinder.client.UiField;
048import com.google.gwt.uibinder.client.UiHandler;
049import com.google.gwt.user.client.ui.Composite;
050import com.google.gwt.user.client.ui.Label;
051import com.google.gwt.user.client.ui.Panel;
052import com.google.gwt.user.client.ui.Widget;
053
054/**
055 * Widget for defining new properties.<p>
056 */
057public class CmsPropertyDefinitionView extends Composite {
058
059    /** The UiBinder interface for this class. */
060    interface I_CmsPropertyDefinitionViewUiBinder extends UiBinder<Widget, CmsPropertyDefinitionView> {
061        // empty
062    }
063
064    /** The max allowed property name length. */
065    private static final int MAX_PROPERTY_NAME_LENGTH = 128;
066
067    /** The UiBinder instance for this widget. */
068    private static I_CmsPropertyDefinitionViewUiBinder uiBinder = GWT.create(I_CmsPropertyDefinitionViewUiBinder.class);
069
070    /** The Cancel button. */
071    @UiField
072    CmsPushButton m_cancelButton;
073
074    /** The panel displaying the existing properties.<p> */
075    @UiField
076    Panel m_existingProperties;
077
078    /** The set of existing properties. */
079    Set<String> m_existingPropertyNames = new HashSet<String>();
080
081    /** The OK button. */
082    @UiField
083    CmsPushButton m_okButton;
084
085    /** The popup containing this widget. */
086    CmsPopup m_popup;
087
088    /** The input field for the property name. */
089    @UiField
090    CmsTextBox m_propertyNameField;
091
092    /**
093     * Creates a new instance.<p>
094     *
095     * @param existingProperties the names of already existing properties
096     */
097    public CmsPropertyDefinitionView(Collection<String> existingProperties) {
098
099        initWidget(uiBinder.createAndBindUi(this));
100        addStyleName(I_CmsInputLayoutBundle.INSTANCE.inputCss().highTextBoxes());
101        for (String existingProperty : existingProperties) {
102            m_existingProperties.add(new Label(existingProperty));
103            m_existingPropertyNames.add(existingProperty);
104        }
105        m_propertyNameField.addKeyPressHandler(new KeyPressHandler() {
106
107            public void onKeyPress(KeyPressEvent event) {
108
109                int code = event.getNativeEvent().getKeyCode();
110                if (code == 13) {
111                    onClickOk(null);
112                }
113            }
114        });
115        m_propertyNameField.getTextBox().setMaxLength(MAX_PROPERTY_NAME_LENGTH);
116    }
117
118    /**
119     * Closes the popup if possible.<p>
120     */
121    public void closePopup() {
122
123        if (m_popup != null) {
124            m_popup.hide();
125            m_popup = null;
126        }
127    }
128
129    /**
130     * Gets the cancel button.<p>
131     *
132     * @return the cancel button
133     */
134    public CmsPushButton getCancelButton() {
135
136        return m_cancelButton;
137
138    }
139
140    /**
141     * Gets the OK button.<p>
142     *
143     * @return the OK button
144     */
145    public CmsPushButton getOkButton() {
146
147        return m_okButton;
148    }
149
150    /**
151     * Sets the popup which contains this widget.<p>
152     *
153     * @param popup the popup
154     */
155    public void setPopup(CmsPopup popup) {
156
157        m_popup = popup;
158    }
159
160    /**
161     * Button handler for the cancel button.<p>
162     *
163     * @param e the click event
164     */
165    @UiHandler("m_cancelButton")
166    void onClickCancel(ClickEvent e) {
167
168        closePopup();
169    }
170
171    /**
172     * Button handler for the OK button.<p>
173     *
174     * @param e the click event
175     */
176    @UiHandler("m_okButton")
177    void onClickOk(ClickEvent e) {
178
179        String propName = m_propertyNameField.getFormValueAsString();
180        if (CmsStringUtil.isEmptyOrWhitespaceOnly(propName)) {
181            m_propertyNameField.setErrorMessage(CmsPropertyDefinitionMessages.messageEmpty());
182            return;
183        }
184        String normalizedName = propName.trim();
185        if (!isValidName(normalizedName)) {
186            m_propertyNameField.setErrorMessage(CmsPropertyDefinitionMessages.messageInvalidName());
187            return;
188        }
189        if (m_existingPropertyNames.contains(normalizedName)) {
190            m_propertyNameField.setErrorMessage(CmsPropertyDefinitionMessages.alreadyExists());
191            return;
192        }
193        savePropertyDefinitionAndQuit(normalizedName);
194    }
195
196    /**
197     * Checks whether the property name is valid.<p>
198     *
199     * @param normalizedName the property name to check
200     *
201     * @return true if the name is valid
202     */
203    private boolean isValidName(String normalizedName) {
204
205        return normalizedName.matches("^[a-zA-Z0-9_\\-\\.~\\$]+$");
206    }
207
208    /**
209     * Saves the property definition and closes the dialog.<p>
210     *
211     * @param normalizedName the property name
212     */
213    private void savePropertyDefinitionAndQuit(final String normalizedName) {
214
215        CmsRpcAction<Void> action = new CmsRpcAction<Void>() {
216
217            @Override
218            public void execute() {
219
220                start(200, true);
221                CmsCoreProvider.getVfsService().createPropertyDefinition(normalizedName, this);
222            }
223
224            @Override
225            protected void onResponse(Void result) {
226
227                stop(false);
228                closePopup();
229            }
230
231        };
232        action.execute();
233    }
234}