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.ade.sitemap.client.alias;
029
030import static org.opencms.ade.sitemap.client.alias.CmsAliasMessages.messagePage;
031import static org.opencms.ade.sitemap.client.alias.CmsAliasMessages.messagePermanentRedirect;
032import static org.opencms.ade.sitemap.client.alias.CmsAliasMessages.messageRedirect;
033import static org.opencms.ade.sitemap.client.alias.CmsAliasMessages.messageRowCount;
034
035import org.opencms.ade.sitemap.client.alias.rewrite.CmsRewriteAliasTable;
036import org.opencms.ade.sitemap.client.alias.simple.CmsAliasCellTable;
037import org.opencms.gwt.client.ui.CmsPopup;
038import org.opencms.gwt.client.ui.CmsPushButton;
039import org.opencms.gwt.client.ui.I_CmsButton;
040import org.opencms.gwt.client.ui.I_CmsButton.ButtonStyle;
041import org.opencms.gwt.client.ui.input.CmsSelectBox;
042import org.opencms.gwt.client.ui.input.CmsTextBox;
043import org.opencms.gwt.shared.alias.CmsAliasMode;
044import org.opencms.gwt.shared.alias.CmsAliasTableRow;
045import org.opencms.gwt.shared.alias.CmsRewriteAliasTableRow;
046import org.opencms.gwt.shared.alias.CmsRewriteAliasValidationReply;
047import org.opencms.util.CmsUUID;
048
049import java.util.ArrayList;
050import java.util.HashMap;
051import java.util.LinkedHashMap;
052import java.util.List;
053import java.util.Map;
054
055import com.google.gwt.core.client.GWT;
056import com.google.gwt.event.dom.client.ClickEvent;
057import com.google.gwt.uibinder.client.UiBinder;
058import com.google.gwt.uibinder.client.UiField;
059import com.google.gwt.uibinder.client.UiHandler;
060import com.google.gwt.user.cellview.client.ColumnSortEvent;
061import com.google.gwt.user.cellview.client.ColumnSortList;
062import com.google.gwt.user.client.ui.Composite;
063import com.google.gwt.user.client.ui.HasText;
064import com.google.gwt.user.client.ui.Panel;
065import com.google.gwt.user.client.ui.Widget;
066import com.google.gwt.view.client.RowCountChangeEvent;
067
068/**
069 * The widget containing the table and the buttons used for editing aliases.<p>
070 */
071public class CmsAliasView extends Composite {
072
073    /** The UiBinder interface for this widget. */
074    protected interface I_CmsAliasViewUiBinder extends UiBinder<Widget, CmsAliasView> {
075        // empty
076    }
077
078    /** The 'Cancel' button. */
079    @UiField
080    protected CmsPushButton m_cancelButton;
081
082    /** The alias table controller. */
083    protected CmsAliasTableController m_controller;
084
085    /** Text container for the row count. */
086    @UiField
087    protected HasText m_countLabel;
088
089    /** The 'Delete' button. */
090    @UiField
091    protected CmsPushButton m_deleteButton;
092
093    /** The 'Download' button. */
094    @UiField
095    protected CmsPushButton m_downloadButton;
096
097    /** The text box for entering the path for a new alias. */
098    @UiField
099    protected CmsTextBox m_newAliasPath;
100
101    /** The button for adding a new alias. */
102    @UiField
103    protected CmsPushButton m_newButton;
104
105    /** The select box for selecting the mode of a new alias. */
106    @UiField
107    protected CmsSelectBox m_newMode;
108
109    /** The text box for entering the resource path for a new alias. */
110    @UiField
111    protected CmsTextBox m_newResourcePath;
112
113    /** The button for adding a new rewrite alias. */
114    @UiField
115    protected CmsPushButton m_newRewriteButton;
116
117    /** The select box for selecting a mode for new rewrite aliases. */
118    @UiField
119    protected CmsSelectBox m_newRewriteMode;
120
121    /** The text box for entering a new rewrite pattern. */
122    @UiField
123    protected CmsTextBox m_newRewriteRegex;
124
125    /** The text box for entering a new rewrite replacement string. */
126    @UiField
127    protected CmsTextBox m_newRewriteReplacement;
128
129    /** The button for deleting rewrite aliases. */
130    @UiField
131    protected CmsPushButton m_rewriteDeleteButton;
132
133    /**
134     * The container for the rewrite table.<p>
135     */
136    @UiField
137    protected Panel m_rewriteTableContainer;
138
139    /** The button for saving the alias table. */
140    @UiField
141    protected CmsPushButton m_saveButton;
142
143    /** The panel containing the alias cell table. */
144    @UiField
145    protected Panel m_tableContainer;
146
147    /** The button for importing alias CSV files. */
148    @UiField
149    protected CmsPushButton m_uploadButton;
150
151    /** The popup in which this view is displayed. */
152    private CmsPopup m_popup;
153
154    /** The cell table for editing rewrite aliases. */
155    private CmsRewriteAliasTable m_rewriteTable;
156
157    /** The table containing the alias data. */
158    private CmsAliasCellTable m_table;
159
160    /**
161     * Creates new view instance.<p>
162     *
163     * @param controller the controller for the view
164     */
165    @SuppressWarnings("unchecked")
166    public CmsAliasView(CmsAliasTableController controller) {
167
168        initWidget(((UiBinder<Widget, CmsAliasView>)GWT.create(I_CmsAliasViewUiBinder.class)).createAndBindUi(this));
169        Map<String, String> items = new LinkedHashMap<String, String>();
170        items.put(CmsAliasMode.permanentRedirect.toString(), messagePermanentRedirect());
171        items.put(CmsAliasMode.redirect.toString(), messageRedirect());
172        items.put(CmsAliasMode.page.toString(), messagePage());
173        m_newMode.setItems(items);
174
175        Map<String, String> rewriteItems = new LinkedHashMap<String, String>();
176        rewriteItems.put(CmsAliasMode.permanentRedirect.toString(), messagePermanentRedirect());
177        rewriteItems.put(CmsAliasMode.redirect.toString(), messageRedirect());
178        rewriteItems.put(CmsAliasMode.passthrough.toString(), CmsAliasMessages.messagePassthrough());
179        m_newRewriteMode.setItems(rewriteItems);
180
181        m_controller = controller;
182        m_deleteButton.setEnabled(false);
183        m_rewriteDeleteButton.setEnabled(false);
184        m_table = new CmsAliasCellTable(controller);
185        m_tableContainer.add(m_table);
186        m_rewriteTable = new CmsRewriteAliasTable(controller);
187        m_rewriteTableContainer.add(m_rewriteTable);
188        setNewButtonStyle(m_newButton);
189        setNewButtonStyle(m_newRewriteButton);
190        m_table.addRowCountChangeHandler(new RowCountChangeEvent.Handler() {
191
192            public void onRowCountChange(RowCountChangeEvent event) {
193
194                String message = messageRowCount(event.getNewRowCount());
195                m_countLabel.setText(message);
196            }
197        });
198        setWidth("100%"); //$NON-NLS-1$
199    }
200
201    /**
202     * Clears the input fields used to add new aliases.<p>
203     */
204    public void clearNew() {
205
206        m_newAliasPath.setFormValueAsString(""); //$NON-NLS-1$
207        m_newAliasPath.setErrorMessage(null);
208        m_newResourcePath.setFormValueAsString(""); //$NON-NLS-1$
209        m_newResourcePath.setErrorMessage(null);
210    }
211
212    /**
213     * Clears the text boxes for adding new rewrites.<p>
214     */
215    public void clearRewriteNew() {
216
217        m_newRewriteRegex.setFormValueAsString("");
218        m_newRewriteReplacement.setFormValueAsString("");
219    }
220
221    /**
222     * Clears the validation errors for the text boxes used to add new aliases.<p>
223     */
224    public void clearValidationsForNew() {
225
226        m_newResourcePath.setErrorMessage(null);
227        m_newAliasPath.setErrorMessage(null);
228    }
229
230    /**
231     * Hides the popup.<p>
232     */
233    public void close() {
234
235        m_popup.hide();
236    }
237
238    /**
239     * Gets the buttons which should be displayed in the button bar of the popup containing this view.<p>
240     *
241     * @return the buttons for the popup button bar
242     */
243    public List<CmsPushButton> getButtonBar() {
244
245        List<CmsPushButton> buttons = new ArrayList<CmsPushButton>();
246        buttons.add(m_cancelButton);
247        buttons.add(m_saveButton);
248        buttons.add(m_downloadButton);
249        buttons.add(m_uploadButton);
250        return buttons;
251    }
252
253    /**
254     * Gets the list of rows used by the data provider.<p>
255     *
256     * @return the list of rows used by the data provider
257     */
258    public List<CmsAliasTableRow> getLiveData() {
259
260        return m_table.getLiveDataList();
261    }
262
263    /**
264     * Gets the rewrite alias data.<p>
265     *
266     * @return the rewrite alias list
267     */
268    public List<CmsRewriteAliasTableRow> getRewriteData() {
269
270        return m_rewriteTable.getLiveDataList();
271    }
272
273    /**
274     * Gets the rewrite alias cell table.<p>
275     *
276     * @return the rewrite alias cell table
277     */
278    public CmsRewriteAliasTable getRewriteTable() {
279
280        return m_rewriteTable;
281    }
282
283    /**
284     * Gets the cell table used to edit the alias data.<p>
285     *
286     * @return the alias cell table
287     */
288    public CmsAliasCellTable getTable() {
289
290        return m_table;
291    }
292
293    /**
294     * Replaces the contents of the live data row list with another list of rows.<p>
295     *
296     * @param data the new list of rows to be placed into the live data list
297     * @param rewriteData the list of rewrite alias data
298     */
299    public void setData(List<CmsAliasTableRow> data, List<CmsRewriteAliasTableRow> rewriteData) {
300
301        m_table.getLiveDataList().clear();
302        m_table.getLiveDataList().addAll(data);
303        m_rewriteTable.getLiveDataList().clear();
304        m_rewriteTable.getLiveDataList().addAll(rewriteData);
305    }
306
307    /**
308     * Enables or disables the delete button.<p>
309     *
310     * @param enabled if true, the delete button will be enabled, else disabled
311     */
312    public void setDeleteButtonEnabled(boolean enabled) {
313
314        m_deleteButton.setEnabled(enabled);
315    }
316
317    /**
318     * Sets the validation error message for the alias path text box.<p>
319     *
320     * @param error the validation error message
321     */
322    public void setNewAliasPathError(String error) {
323
324        m_newAliasPath.setErrorMessage(error);
325
326    }
327
328    /**
329     * Sets the validation error message for the resource path text box.<p>
330     *
331     * @param error the validation error message
332     */
333    public void setNewAliasResourceError(String error) {
334
335        m_newResourcePath.setErrorMessage(error);
336    }
337
338    /**
339     * Sets the popup used to display this widget.<p>
340     *
341     * @param popup the popup instance
342     */
343    public void setPopup(CmsPopup popup) {
344
345        m_popup = popup;
346    }
347
348    /**
349     * Enables or disables the delete button for rewrite aliases.<p>
350     *
351     * @param enabled true if the delete button should be enabled
352     */
353    public void setRewriteDeleteButtonEnabled(boolean enabled) {
354
355        m_rewriteDeleteButton.setEnabled(enabled);
356    }
357
358    /**
359     * Enables or disables the save button.<p>
360     *
361     * @param enabled true if the save button should be enabled, false if it should be disabled
362     */
363    public void setSaveButtonEnabled(boolean enabled) {
364
365        m_saveButton.setEnabled(enabled);
366    }
367
368    /**
369     * Ensures that rows with errors will be placed at the top of the table.<p>
370     */
371    public void sortByErrors() {
372
373        ColumnSortList columnSort = m_table.getColumnSortList();
374        columnSort.clear();
375        columnSort.push(m_table.getErrorColumn());
376        columnSort.push(m_table.getErrorColumn());
377        ColumnSortEvent.fire(m_table, columnSort);
378    }
379
380    /**
381     * Updates the view after the rewrite aliases have been validated.<p>
382     *
383     * @param result the result of the rewrite alias validation
384     */
385    public void update(CmsRewriteAliasValidationReply result) {
386
387        Map<CmsUUID, String> errors = result.getErrors();
388        for (CmsRewriteAliasTableRow row : getRewriteData()) {
389            String error = errors.get(row.getId());
390            row.setError(error);
391        }
392        m_rewriteTable.redraw();
393    }
394
395    /**
396     * Updates the table data with a new list of rows.<p>
397     *
398     * Rows in the table for which a row with the same key is also contained in the 'data' parameter
399     * will be updated, the other rows from the 'data' list will be added.<p>
400     *
401     * @param data the list of rows to update
402     */
403    public void update(List<CmsAliasTableRow> data) {
404
405        Map<String, CmsAliasTableRow> currentRowsByKey = new HashMap<String, CmsAliasTableRow>();
406        for (CmsAliasTableRow row : m_table.getLiveDataList()) {
407            currentRowsByKey.put(row.getKey(), row);
408        }
409        List<CmsAliasTableRow> rowsToAdd = new ArrayList<CmsAliasTableRow>();
410        for (CmsAliasTableRow updateRow : data) {
411            String key = updateRow.getKey();
412            CmsAliasTableRow existingRow = currentRowsByKey.get(key);
413            if (existingRow != null) {
414                existingRow.update(updateRow);
415            } else {
416                rowsToAdd.add(updateRow);
417            }
418        }
419        m_table.getLiveDataList().addAll(rowsToAdd);
420        m_table.redraw();
421    }
422
423    /**
424     * The event handler for the button to delete rewrite aliases.<p>
425     *
426     * @param e the click event
427     */
428    @UiHandler("m_rewriteDeleteButton")
429    protected void onClickDeleteRewrite(ClickEvent e) {
430
431        List<CmsRewriteAliasTableRow> rowsToDelete = m_rewriteTable.getSelectedRows();
432        m_controller.deleteRewrites(rowsToDelete);
433    }
434
435    /**
436     * The click handler for the 'Cancel' button.<p>
437     *
438     * @param e the click event
439     */
440    @UiHandler("m_cancelButton")
441    void onClickCancel(ClickEvent e) {
442
443        m_popup.hide();
444    }
445
446    /**
447     * The click handler for the 'Delete' button.<p>
448     *
449     * @param e the click event
450     */
451    @UiHandler("m_deleteButton")
452    void onClickDelete(ClickEvent e) {
453
454        List<CmsAliasTableRow> rowsToDelete = m_table.getSelectedRows();
455        m_controller.deleteRows(rowsToDelete);
456    }
457
458    /**
459     * The click handler for the 'Download' button.<p>
460     *
461     * @param e the click event
462     */
463    @UiHandler("m_downloadButton")
464    void onClickDownload(ClickEvent e) {
465
466        m_controller.download();
467    }
468
469    /**
470     * The click handler for the 'New' button.<p>
471     *
472     * @param e the click event
473     */
474    @UiHandler("m_newButton")
475    void onClickNew(ClickEvent e) {
476
477        String aliasPath = m_newAliasPath.getText();
478        String resourcePath = m_newResourcePath.getText();
479        m_controller.editNewAlias(aliasPath, resourcePath, CmsAliasMode.valueOf(m_newMode.getFormValueAsString()));
480    }
481
482    /**
483     * The event handler for the button for adding new rewrite aliases.<p>
484     *
485     * @param e the click event
486     */
487    @UiHandler("m_newRewriteButton")
488    void onClickNewRewrite(ClickEvent e) {
489
490        String rewriteRegex = m_newRewriteRegex.getText();
491        String rewriteReplacement = m_newRewriteReplacement.getText();
492        String mode = m_newRewriteMode.getFormValueAsString();
493        m_controller.editNewRewrite(rewriteRegex, rewriteReplacement, CmsAliasMode.valueOf(mode));
494    }
495
496    /**
497     * The click handler for the 'Save' button.<p>
498     *
499     * @param e the click event
500     */
501    @UiHandler("m_saveButton")
502    void onClickSave(ClickEvent e) {
503
504        m_controller.save();
505    }
506
507    /**
508     * The click handler for the upload button.<p>
509     *
510     * @param e the click handler for the upload button
511     */
512    @UiHandler("m_uploadButton")
513    void onClickUpload(ClickEvent e) {
514
515        m_popup.hide();
516        CmsImportView.showPopup();
517
518    }
519
520    /**
521     * Styles a button for adding new aliases.<p>
522     *
523     * @param newButton the button to style
524     */
525    private void setNewButtonStyle(CmsPushButton newButton) {
526
527        newButton.setImageClass(I_CmsButton.ADD_SMALL);
528        newButton.setButtonStyle(ButtonStyle.FONT_ICON, null);
529    }
530
531}