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.ui.apps.git;
029
030import org.opencms.file.CmsObject;
031import org.opencms.file.CmsUser;
032import org.opencms.main.CmsException;
033import org.opencms.main.CmsLog;
034import org.opencms.main.OpenCms;
035import org.opencms.module.CmsModule;
036import org.opencms.ui.A_CmsUI;
037import org.opencms.ui.CmsVaadinUtils;
038import org.opencms.ui.components.CmsResourceInfo;
039import org.opencms.util.CmsStringUtil;
040import org.opencms.workplace.CmsWorkplace;
041
042import java.util.ArrayList;
043import java.util.Collection;
044import java.util.Collections;
045import java.util.List;
046import java.util.Map;
047
048import org.apache.commons.logging.Log;
049
050import com.google.common.base.Strings;
051import com.google.common.collect.Lists;
052import com.google.common.collect.Maps;
053import com.vaadin.v7.data.Property.ValueChangeEvent;
054import com.vaadin.v7.data.Property.ValueChangeListener;
055import com.vaadin.v7.shared.ui.combobox.FilteringMode;
056import com.vaadin.v7.shared.ui.label.ContentMode;
057import com.vaadin.ui.AbstractLayout;
058import com.vaadin.ui.Alignment;
059import com.vaadin.ui.Button;
060import com.vaadin.ui.Button.ClickEvent;
061import com.vaadin.ui.Button.ClickListener;
062import com.vaadin.v7.ui.CheckBox;
063import com.vaadin.v7.ui.ComboBox;
064import com.vaadin.ui.Component;
065import com.vaadin.v7.ui.HorizontalLayout;
066import com.vaadin.v7.ui.Label;
067import com.vaadin.ui.Notification;
068import com.vaadin.ui.Notification.Type;
069import com.vaadin.ui.Panel;
070import com.vaadin.ui.TabSheet;
071import com.vaadin.ui.TabSheet.SelectedTabChangeEvent;
072import com.vaadin.ui.TabSheet.SelectedTabChangeListener;
073import com.vaadin.v7.ui.TextArea;
074import com.vaadin.v7.ui.TextField;
075import com.vaadin.v7.ui.VerticalLayout;
076import com.vaadin.ui.Window;
077import com.vaadin.ui.themes.ValoTheme;
078
079/**
080 * Main widget for the Git check-in tool.<p>
081 */
082public class CmsGitToolOptionsPanel extends VerticalLayout {
083
084    /**
085     * Enum describing the type of action to perform.<p>
086     */
087    enum ActionType {
088        /** Check in. */
089        checkIn,
090
091        /** Checkout action. */
092        checkOut,
093
094        /** Reset to HEAD. */
095        resetHead,
096
097        /** Reset to remote head. */
098        resetRemoteHead;
099    }
100
101    /**
102     * Enum representing the dialog's tabs.
103     */
104    enum DialogTab {
105        /** The 'check in' tab. */
106        checkIn,
107
108        /** The 'import' tab. */
109        checkOut;
110    }
111
112    /** Additional info key for the email address. */
113    public static final String ADDINFO_EMAIL = "git_cms_email";
114
115    /** Additional info key for the commit message. */
116    public static final String ADDINFO_MESSAGE = "git_cms_message";
117
118    /** Additional info key for the user name. */
119    public static final String ADDINFO_USER = "git_cms_user";
120
121    /** Logger instance for this class. */
122    private static final Log LOG = CmsLog.getLog(CmsGitToolOptionsPanel.class);
123
124    /** Serial version id. */
125    private static final long serialVersionUID = 1L;
126
127    /** True when advanced options are currently visible. */
128    protected boolean m_advancedVisible;
129
130    /** Map of check boxes for selectable modules, with the module names as keys. */
131    Map<String, CheckBox> m_moduleCheckboxes = Maps.newHashMap();
132
133    /** Field for 'Add and commit' setting. */
134    private CheckBox m_addAndCommit;
135
136    /** The advanced options layout. */
137    private VerticalLayout m_advancedLayout;
138
139    /** Cancel button. */
140    private Button m_cancel;
141
142    /** The check-in bean. */
143    private CmsGitCheckin m_checkinBean;
144
145    /** The tab with the import settings. */
146    private Component m_checkoutTab;
147
148    /** Field for 'Commit message' setting. */
149    private TextArea m_commitMessage;
150
151    /** Panel for the configuration selection. */
152    private Panel m_configurationSelectionPanel;
153
154    /** Configuration selector. */
155    private ComboBox m_configurationSelector;
156
157    /** Field for 'Copy and unzip' setting. */
158    private CheckBox m_copyAndUnzip;
159
160    /** Current window (using an array so the Vaadin field binder doesn't process this. */
161    private Window[] m_currentWindow = new Window[] {null};
162
163    /** Button for deselecting all modules. */
164    private Button m_deselectAll;
165
166    /** The initial dialog tab. */
167    private DialogTab m_dialogTab = DialogTab.checkIn;
168
169    /** The field for the email address. */
170    private TextField m_emailField;
171
172    /** Field for 'Exclude lib' setting. */
173    private CheckBox m_excludeLib;
174
175    /** Email field for module import. */
176    private TextField m_fakeEmailField;
177
178    /** User field for module import. */
179    private TextField m_fakeUserField;
180
181    /** Checkbox for the 'fetch and reset' option. */
182    private CheckBox m_fetchAndReset;
183
184    /** Field for 'Ignroe unclean' setting. */
185    private CheckBox m_ignoreUnclean;
186
187    /** Selected mode. */
188    private ActionType m_mode = ActionType.checkIn;
189
190    /** Container for the module selector. */
191    private VerticalLayout m_moduleSelectionContainer;
192
193    /** Module selector. */
194    private ComboBox m_moduleSelector;
195
196    /** Container for the module selector drop-down and the "Deselect all" button. */
197    private HorizontalLayout m_moduleSelectorContainer;
198
199    /** Button for check-in. */
200    private Button m_okButton;
201
202    /** Field for 'Pull after commit' setting. */
203    private CheckBox m_pullAfterCommit;
204
205    /** Field for 'Pull first' setting. */
206    private CheckBox m_pullFirst;
207
208    /** Field for 'Push automatically' setting. */
209    private CheckBox m_pushAutomatically;
210
211    /** Tab sheet. */
212    private TabSheet m_tabs;
213
214    /** Button used to toggle advanced options. */
215    private Button m_toggleOptions;
216
217    /** Current user. */
218    private CmsUser m_user;
219
220    /** The field for the git user name. */
221    private TextField m_userField;
222
223    /**
224     * Creates a new instance.<p>
225     *
226     * @param checkinBean the bean to be used for the check-in operation.
227     */
228    public CmsGitToolOptionsPanel(CmsGitCheckin checkinBean) {
229        m_checkinBean = checkinBean;
230        if (!checkinBean.hasValidConfiguration()) {
231            setMargin(true);
232            Label errorLabel = new Label(CmsVaadinUtils.getMessageText(Messages.GUI_GIT_APP_UNCONFIGURED_0));
233            errorLabel.setContentMode(ContentMode.HTML);
234            addComponent(errorLabel);
235            return;
236        }
237        CmsVaadinUtils.readAndLocalizeDesign(this, CmsVaadinUtils.getWpMessagesForCurrentLocale(), null);
238        configureConfigurationSelector();
239        updateForNewConfiguration(m_checkinBean.getCurrentConfiguration());
240
241        m_user = A_CmsUI.getCmsObject().getRequestContext().getCurrentUser();
242        restoreFieldsFromUserInfo();
243
244        setAdvancedVisible(false);
245        m_toggleOptions.addClickListener(new ClickListener() {
246
247            private static final long serialVersionUID = 1L;
248
249            public void buttonClick(ClickEvent event) {
250
251                setAdvancedVisible(!m_advancedVisible);
252            }
253        });
254        m_okButton.addClickListener(new ClickListener() {
255
256            private static final long serialVersionUID = 1L;
257
258            @SuppressWarnings("synthetic-access")
259            public void buttonClick(ClickEvent event) {
260
261                if (m_dialogTab == DialogTab.checkIn) {
262                    runAction(ActionType.checkIn);
263                } else {
264                    runAction(ActionType.checkOut);
265                }
266            }
267        });
268        m_cancel.addClickListener(new ClickListener() {
269
270            private static final long serialVersionUID = 1L;
271
272            public void buttonClick(ClickEvent event) {
273
274                A_CmsUI.get().getPage().setLocation(CmsVaadinUtils.getWorkplaceLink());
275            }
276        });
277        m_deselectAll.addClickListener(new ClickListener() {
278
279            private static final long serialVersionUID = 1L;
280
281            public void buttonClick(ClickEvent event) {
282
283                for (Map.Entry<String, CheckBox> entry : m_moduleCheckboxes.entrySet()) {
284                    CheckBox checkBox = entry.getValue();
285                    checkBox.setValue(Boolean.FALSE);
286                }
287            }
288        });
289
290        m_tabs.addStyleName(ValoTheme.TABSHEET_FRAMED);
291        m_tabs.addStyleName(ValoTheme.TABSHEET_PADDED_TABBAR);
292        m_tabs.addSelectedTabChangeListener(new SelectedTabChangeListener() {
293
294            private static final long serialVersionUID = 1L;
295
296            @SuppressWarnings("synthetic-access")
297            public void selectedTabChange(SelectedTabChangeEvent event) {
298
299                DialogTab tab;
300                if (m_tabs.getSelectedTab() == m_checkoutTab) {
301                    tab = DialogTab.checkOut;
302                } else {
303                    tab = DialogTab.checkIn;
304                }
305                CmsGitToolOptionsPanel.this.setTab(tab);
306
307            }
308
309        });
310        m_fetchAndReset.setValue(Boolean.TRUE);
311        setTab(m_dialogTab);
312    }
313
314    /**
315     * Opens a modal window with the given component as content.<p>
316     *
317     * @param component the window content
318     *
319     * @return the window which is opened
320     */
321    public Window addAsWindow(Component component) {
322
323        // Have to use an array because Vaadin declarative tries to bind the field otherwise
324        if (m_currentWindow[0] != null) {
325            m_currentWindow[0].close();
326            m_currentWindow[0] = null;
327        }
328
329        Window window = new Window();
330        window.setContent(component);
331        window.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_GIT_SCRIPT_RESULTS_0));
332        window.setWidth("1000px");
333        window.setModal(true);
334        window.setResizable(false);
335        A_CmsUI.get().addWindow(window);
336
337        m_currentWindow[0] = window;
338        return window;
339    }
340
341    /**
342     * Adds a check box and info widget for a module which should be selectable for check-in.<p>
343     *
344     * @param moduleName the name of the module
345     */
346    public void addSelectableModule(final String moduleName) {
347
348        boolean enabled = true; /* OpenCms.getModuleManager().hasModule(moduleName); */
349        CheckBox moduleCheckBox = new CheckBox();
350        String iconUri = CmsWorkplace.getResourceUri("tools/modules/buttons/modules.png");
351        CmsResourceInfo info = new CmsResourceInfo(moduleName, "", iconUri);
352        HorizontalLayout line = new HorizontalLayout();
353        line.setWidth("100%");
354        line.addComponent(moduleCheckBox);
355        info.setWidth("100%");
356        line.addComponent(info);
357        line.setComponentAlignment(moduleCheckBox, Alignment.MIDDLE_CENTER);
358        line.setExpandRatio(info, 1.0f);
359        moduleCheckBox.setEnabled(true);
360        moduleCheckBox.setValue(Boolean.valueOf(enabled)); // If enabled, then checked by default
361        m_moduleCheckboxes.put(moduleName, moduleCheckBox);
362        m_moduleSelectionContainer.addComponent(line, m_moduleSelectionContainer.getComponentCount() - 1);
363        setTab(m_dialogTab);
364    }
365
366    /**
367     * Enables/disables checkboxes for listed modules which are not installed.<p>
368     *
369     * @param enable true if the checkboxes for modules which are not installed should be enabled, false if they should be disabled
370     */
371    public void enableCheckboxesForNotInstalledModules(boolean enable) {
372
373        for (Map.Entry<String, CheckBox> entry : m_moduleCheckboxes.entrySet()) {
374            String moduleName = entry.getKey();
375            CheckBox checkbox = entry.getValue();
376            if (!OpenCms.getModuleManager().hasModule(moduleName)) {
377                checkbox.setEnabled(enable);
378                if (!enable) {
379                    checkbox.setValue(Boolean.FALSE);
380                }
381            }
382        }
383    }
384
385    /**
386     * Gets the modules which are selected for check-in.<p>
387     *
388     * @return the selected modules
389     */
390    public Collection<String> getSelectedModules() {
391
392        List<String> result = Lists.newArrayList();
393        for (Map.Entry<String, CheckBox> entry : m_moduleCheckboxes.entrySet()) {
394            if (entry.getValue().getValue().booleanValue()) {
395                result.add(entry.getKey());
396            }
397        }
398        return result;
399    }
400
401    /**
402     * Executes one of the dialog actions.<p>
403     *
404     * @param action the action to perform
405     */
406    public void runAction(ActionType action) {
407
408        m_mode = action;
409        setActionFlags();
410        setCommonParameters();
411        m_checkinBean.clearModules();
412        for (String moduleName : getSelectedModules()) {
413            m_checkinBean.addModuleToExport(moduleName);
414        }
415        int result = m_checkinBean.checkIn();
416        String log = m_checkinBean.getLogText();
417        String message = null;
418        boolean error = false;
419        switch (action) {
420            case checkIn:
421                String messageToSave = m_checkinBean.getCommitMessage();
422                String emailToSave = m_checkinBean.getGitUserEmail();
423                String userToSave = m_checkinBean.getGitUserName();
424                CmsObject cms = m_checkinBean.getCmsObject();
425                CmsUser user = cms.getRequestContext().getCurrentUser();
426                setUserInfo(user, ADDINFO_USER, userToSave);
427                setUserInfo(user, ADDINFO_EMAIL, emailToSave);
428                setUserInfo(user, ADDINFO_MESSAGE, messageToSave);
429                try {
430                    cms.writeUser(user);
431                } catch (CmsException e) {
432                    LOG.error(e.getLocalizedMessage(), e);
433                }
434
435                List<Button> resetButtons = new ArrayList<Button>();
436
437                Button resetHead = new Button(CmsVaadinUtils.getMessageText(Messages.GUI_GIT_BUTTON_RESET_HEAD_0));
438                resetHead.setDescription(CmsVaadinUtils.getMessageText(Messages.GUI_GIT_BUTTON_RESET_HEAD_DESC_0));
439                resetHead.addClickListener(new ClickListener() {
440
441                    private static final long serialVersionUID = 1L;
442
443                    public void buttonClick(ClickEvent event) {
444
445                        runAction(ActionType.resetHead);
446                    }
447                });
448
449                Button resetRemoteHead = new Button(
450                    CmsVaadinUtils.getMessageText(Messages.GUI_GIT_BUTTON_RESET_REMOTE_HEAD_0));
451                resetRemoteHead.setDescription(
452                    CmsVaadinUtils.getMessageText(Messages.GUI_GIT_BUTTON_RESET_REMOTE_HEAD_DESC_0));
453                resetRemoteHead.addClickListener(new ClickListener() {
454
455                    private static final long serialVersionUID = 1L;
456
457                    public void buttonClick(ClickEvent event) {
458
459                        runAction(ActionType.resetRemoteHead);
460                    }
461                });
462
463                if (result == 0) {
464                    message = CmsVaadinUtils.getMessageText(Messages.GUI_GIT_CHECKIN_SUCCESSFUL_0);
465                } else if (result == 10) {
466                    message = CmsVaadinUtils.getMessageText(Messages.GUI_GIT_CHECKIN_FAILED_0);
467                    error = true;
468                    resetButtons.add(resetRemoteHead);
469                    resetButtons.add(resetHead);
470                } else {
471                    message = CmsVaadinUtils.getMessageText(Messages.GUI_GIT_CHECKIN_FAILED_0);
472                    error = true;
473                    resetButtons.add(resetRemoteHead);
474                }
475                CmsGitActionResultPanel panel = new CmsGitActionResultPanel(message, log, error, resetButtons);
476                addAsWindow(panel);
477                break;
478            case checkOut:
479                if (result == 0) {
480                    message = CmsVaadinUtils.getMessageText(Messages.GUI_GIT_IMPORT_SUCCESSFUL_0);
481                } else {
482                    message = CmsVaadinUtils.getMessageText(Messages.GUI_GIT_IMPORT_FAILED_0);
483                }
484                CmsGitActionResultPanel checkoutResult = new CmsGitActionResultPanel(
485                    message,
486                    log,
487                    error,
488                    new ArrayList<Button>());
489                addAsWindow(checkoutResult);
490                break;
491            case resetHead:
492                if (result == 0) {
493                    message = CmsVaadinUtils.getMessageText(Messages.GUI_GIT_RESET_SUCCESSFUL_0);
494                } else {
495                    error = true;
496                    message = CmsVaadinUtils.getMessageText(Messages.GUI_GIT_RESET_FAILED_0);
497                }
498                CmsGitActionResultPanel resetResult = new CmsGitActionResultPanel(
499                    message,
500                    log,
501                    error,
502                    new ArrayList<Button>());
503                addAsWindow(resetResult);
504                break;
505            case resetRemoteHead:
506                if (result == 0) {
507                    message = CmsVaadinUtils.getMessageText(Messages.GUI_GIT_RESET_SUCCESSFUL_0);
508                } else {
509                    error = true;
510                    message = CmsVaadinUtils.getMessageText(Messages.GUI_GIT_RESET_FAILED_0);
511                }
512                CmsGitActionResultPanel resetRemoteResult = new CmsGitActionResultPanel(
513                    message,
514                    log,
515                    error,
516                    new ArrayList<Button>());
517                addAsWindow(resetRemoteResult);
518                break;
519            default:
520                // Should never happen
521        }
522    }
523
524    /**
525     * Sets the flags for the current action.<p>
526     */
527    public void setActionFlags() {
528
529        m_checkinBean.setFetchAndResetBeforeImport(m_fetchAndReset.getValue().booleanValue());
530        switch (m_mode) {
531            case checkOut:
532                m_checkinBean.setCheckout(true);
533                m_checkinBean.setResetHead(false);
534                m_checkinBean.setResetRemoteHead(false);
535                break;
536            case checkIn:
537                m_checkinBean.setCheckout(false);
538                m_checkinBean.setResetHead(false);
539                m_checkinBean.setResetRemoteHead(false);
540                break;
541            case resetHead:
542                m_checkinBean.setCheckout(false);
543                m_checkinBean.setResetHead(true);
544                m_checkinBean.setResetRemoteHead(false);
545                break;
546            case resetRemoteHead:
547                m_checkinBean.setCheckout(false);
548                m_checkinBean.setResetHead(false);
549                m_checkinBean.setResetRemoteHead(true);
550                break;
551            default:
552                break;
553        }
554
555    }
556
557    /**
558     * Changes visibility of the advanced options.<p>
559     *
560     * @param visible true if the options should be shown
561     */
562    public void setAdvancedVisible(boolean visible) {
563
564        m_advancedLayout.setVisible(visible);
565        m_advancedVisible = visible;
566        m_toggleOptions.setCaption(
567            visible
568            ? CmsVaadinUtils.getMessageText(Messages.GUI_GIT_OPTIONS_HIDE_0)
569            : CmsVaadinUtils.getMessageText(Messages.GUI_GIT_OPTIONS_SHOW_0));
570    }
571
572    /**
573     * Called when the active tab is switched.<p>
574     *
575     * @param dialogTab the dialog tab to which the user has switched
576     */
577    public void setTab(DialogTab dialogTab) {
578
579        m_dialogTab = dialogTab;
580        switch (dialogTab) {
581            case checkIn:
582                enableCheckboxesForNotInstalledModules(false);
583                m_okButton.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_GIT_BUTTON_CHECK_IN_0));
584                break;
585            case checkOut:
586                m_fakeEmailField.setValue(m_emailField.getValue());
587                m_fakeUserField.setValue(m_userField.getValue());
588                m_okButton.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_GIT_BUTTON_IMPORT_0));
589                enableCheckboxesForNotInstalledModules(true);
590                break;
591            default:
592                break;
593        }
594    }
595
596    /**
597     * Updates the selection widget for adding new modules.<p>
598     */
599    public void updateNewModuleSelector() {
600
601        ComboBox newModuleSelector = createModuleSelector();
602        ((AbstractLayout)(m_moduleSelector.getParent())).replaceComponent(m_moduleSelector, newModuleSelector);
603        m_moduleSelector = newModuleSelector;
604        m_moduleSelector.addValueChangeListener(new ValueChangeListener() {
605
606            private static final long serialVersionUID = 1L;
607
608            public void valueChange(ValueChangeEvent event) {
609
610                String moduleName = (String)(event.getProperty().getValue());
611                addSelectableModule(moduleName);
612                updateNewModuleSelector();
613            }
614        });
615    }
616
617    /**
618     * Updates the options panel for a special configuration.
619     * @param gitConfig the git configuration.
620     */
621    protected void updateForNewConfiguration(CmsGitConfiguration gitConfig) {
622
623        if (!m_checkinBean.setCurrentConfiguration(gitConfig)) {
624            Notification.show(
625                CmsVaadinUtils.getMessageText(Messages.GUI_GIT_CONFIGURATION_SWITCH_FAILED_0),
626                CmsVaadinUtils.getMessageText(Messages.GUI_GIT_CONFIGURATION_SWITCH_FAILED_DESC_0),
627                Type.ERROR_MESSAGE);
628            m_configurationSelector.select(m_checkinBean.getCurrentConfiguration());
629            return;
630        }
631
632        resetSelectableModules();
633        for (final String moduleName : gitConfig.getConfiguredModules()) {
634            addSelectableModule(moduleName);
635        }
636        updateNewModuleSelector();
637        m_pullFirst.setValue(Boolean.valueOf(gitConfig.getDefaultAutoPullBefore()));
638        m_pullAfterCommit.setValue(Boolean.valueOf(gitConfig.getDefaultAutoPullAfter()));
639        m_addAndCommit.setValue(Boolean.valueOf(gitConfig.getDefaultAutoCommit()));
640        m_pushAutomatically.setValue(Boolean.valueOf(gitConfig.getDefaultAutoPush()));
641        m_commitMessage.setValue(Strings.nullToEmpty(gitConfig.getDefaultCommitMessage()));
642        m_copyAndUnzip.setValue(Boolean.valueOf(gitConfig.getDefaultCopyAndUnzip()));
643        m_excludeLib.setValue(Boolean.valueOf(gitConfig.getDefaultExcludeLibs()));
644        m_ignoreUnclean.setValue(Boolean.valueOf(gitConfig.getDefaultIngoreUnclean()));
645        m_userField.setValue(Strings.nullToEmpty(gitConfig.getDefaultGitUserName()));
646        m_emailField.setValue(Strings.nullToEmpty(gitConfig.getDefaultGitUserEmail()));
647
648    }
649
650    /**
651     * Configures the configuration selector.
652     */
653    private void configureConfigurationSelector() {
654
655        if (m_checkinBean.getConfigurations().size() < 2) {
656            // Do not show the configuration selection at all.
657            removeComponent(m_configurationSelectionPanel);
658        } else {
659            for (CmsGitConfiguration configuration : m_checkinBean.getConfigurations()) {
660                m_configurationSelector.addItem(configuration);
661                m_configurationSelector.setItemCaption(configuration, configuration.getName());
662            }
663            m_configurationSelector.setNullSelectionAllowed(false);
664            m_configurationSelector.setNewItemsAllowed(false);
665            m_configurationSelector.setWidth("350px");
666            m_configurationSelector.select(m_checkinBean.getCurrentConfiguration());
667
668            // There is really a choice between configurations
669            m_configurationSelector.addValueChangeListener(new ValueChangeListener() {
670
671                private static final long serialVersionUID = 1L;
672
673                @SuppressWarnings("synthetic-access")
674                public void valueChange(ValueChangeEvent event) {
675
676                    updateForNewConfiguration((CmsGitConfiguration)event.getProperty().getValue());
677                    restoreFieldsFromUserInfo();
678
679                }
680            });
681        }
682    }
683
684    /**
685     * Creates a new module selector, containing only the modules for which no check box is already displayed.<p>
686     *
687     * @return the new module selector
688     */
689    private ComboBox createModuleSelector() {
690
691        ComboBox result = new ComboBox();
692        result.setPageLength(20);
693        result.setWidth("350px");
694        result.setFilteringMode(FilteringMode.CONTAINS);
695        result.setNewItemsAllowed(false);
696        result.setNullSelectionAllowed(false);
697        List<String> moduleNames = Lists.newArrayList();
698        for (CmsModule module : OpenCms.getModuleManager().getAllInstalledModules()) {
699            String moduleName = module.getName();
700            if (!m_moduleCheckboxes.containsKey(moduleName)) {
701                moduleNames.add(moduleName);
702            }
703        }
704        Collections.sort(moduleNames);
705        for (String moduleName : moduleNames) {
706            result.addItem(moduleName);
707        }
708
709        return result;
710    }
711
712    /**
713     * Removes all currently selectable modules.
714     */
715    private void resetSelectableModules() {
716
717        m_moduleCheckboxes.clear();
718
719        m_moduleSelectionContainer.removeAllComponents();
720        m_moduleSelectionContainer.addComponent(m_moduleSelectorContainer);
721
722    }
723
724    /**
725     * Restores user/email/message input fields from saved values.<p>
726     */
727    private void restoreFieldsFromUserInfo() {
728
729        String savedEmail = (String)(m_user.getAdditionalInfo().get(ADDINFO_EMAIL));
730        String savedName = (String)(m_user.getAdditionalInfo().get(ADDINFO_USER));
731        String savedMessage = (String)(m_user.getAdditionalInfo().get(ADDINFO_MESSAGE));
732
733        if (savedEmail != null) {
734            m_emailField.setValue(savedEmail);
735        }
736
737        if (savedName != null) {
738            m_userField.setValue(savedName);
739        }
740
741        if (savedMessage != null) {
742            m_commitMessage.setValue(savedMessage);
743        }
744    }
745
746    /**
747     * Transfers the parameters from the form to the check-in bean.<p>
748     */
749    private void setCommonParameters() {
750
751        m_checkinBean.setPullBefore(m_pullFirst.getValue().booleanValue());
752        m_checkinBean.setPullAfter(m_pullAfterCommit.getValue().booleanValue());
753        m_checkinBean.setPush(m_pushAutomatically.getValue().booleanValue());
754        m_checkinBean.setExcludeLibs(m_excludeLib.getValue().booleanValue());
755        m_checkinBean.setCommit(m_addAndCommit.getValue().booleanValue());
756        m_checkinBean.setIgnoreUnclean(m_ignoreUnclean.getValue().booleanValue());
757        m_checkinBean.setCopyAndUnzip(m_copyAndUnzip.getValue().booleanValue());
758        m_checkinBean.setGitUserEmail(m_emailField.getValue());
759        m_checkinBean.setGitUserName(m_userField.getValue());
760        String commitMessage = m_commitMessage.getValue();
761        if (!CmsStringUtil.isEmptyOrWhitespaceOnly(commitMessage)) {
762            m_checkinBean.setCommitMessage(commitMessage);
763        }
764    }
765
766    /**
767     * Sets an additional info value if it's not empty.<p>
768     *
769     * @param user the user on which to set the additional info
770     * @param key the additional info key
771     * @param value the additional info value
772     */
773    private void setUserInfo(CmsUser user, String key, String value) {
774
775        if (!CmsStringUtil.isEmptyOrWhitespaceOnly(value)) {
776            user.getAdditionalInfo().put(key, value);
777        }
778    }
779
780}