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.dialogs.permissions;
029
030import org.opencms.security.CmsRole;
031import org.opencms.security.I_CmsPrincipal;
032import org.opencms.ui.A_CmsUI;
033import org.opencms.ui.CmsVaadinUtils;
034import org.opencms.ui.components.CmsBasicDialog;
035import org.opencms.ui.components.CmsBasicDialog.DialogWidth;
036import org.opencms.ui.components.OpenCmsTheme;
037
038import java.util.Collection;
039import java.util.LinkedHashMap;
040import java.util.Map;
041
042import com.vaadin.server.FontAwesome;
043import com.vaadin.ui.Button;
044import com.vaadin.ui.Button.ClickEvent;
045import com.vaadin.ui.Button.ClickListener;
046import com.vaadin.ui.CustomComponent;
047import com.vaadin.ui.Window;
048import com.vaadin.v7.data.Item;
049import com.vaadin.v7.data.Property;
050import com.vaadin.v7.data.Validator;
051import com.vaadin.v7.data.Validator.InvalidValueException;
052import com.vaadin.v7.ui.ComboBox;
053import com.vaadin.v7.ui.Field;
054import com.vaadin.v7.ui.HorizontalLayout;
055import com.vaadin.v7.ui.TextField;
056
057/**
058 * The principal select widget.<p>
059 */
060public class CmsPrincipalSelect extends CustomComponent implements Field<String>, I_CmsPrincipalSelect {
061
062    /**
063     * Handles the principal selection.<p>
064     */
065    public interface I_PrincipalSelectHandler {
066
067        /**
068         * Called to select a principal.<p>
069         *
070         * @param principalType the principal type
071         * @param principalName the principal name
072         */
073        void onPrincipalSelect(String principalType, String principalName);
074    }
075
076    /** The widget types. */
077    public static enum WidgetType {
078        /** Select groups only. */
079        groupwidget,
080        /** Select any principal. */
081        principalwidget,
082        /** Select users only. */
083        userwidget
084    }
085
086    /** The serial version id. */
087    private static final long serialVersionUID = 6944968889428174262L;
088
089    /** The add button. */
090    private Button m_addPermissionSetButton;
091
092    /** The principal name text field. */
093    private TextField m_principalName;
094
095    /** The type select box. */
096    private ComboBox m_principalTypeSelect;
097
098    /** The principal select handler. */
099    private I_PrincipalSelectHandler m_selectHandler;
100
101    /** The open principal select dialog button. */
102    private Button m_selectPrincipalButton;
103
104    /** The widget type. */
105    private WidgetType m_widgetType;
106
107    /** The principal select dialog window. */
108    private Window m_window;
109
110    /** The main layout. */
111    private HorizontalLayout m_main;
112
113    /**Indicates if web ous should be included. */
114    private boolean m_includeWebOus = true;
115
116    /** Controls whether only real users/groups or also pseudo-principals like ALL_OTHERS should be shown. */
117    private boolean m_realOnly;
118
119    /**Ou. */
120    private String m_ou;
121
122    /** Is ou change enabled?*/
123    private boolean m_ouChangeEnabled = true;
124
125    /**
126     * Constructor.<p>
127     */
128    public CmsPrincipalSelect() {
129
130        m_main = new HorizontalLayout();
131        m_main.setSpacing(true);
132        m_main.setWidth("100%");
133        setCompositionRoot(m_main);
134
135        m_widgetType = WidgetType.principalwidget;
136
137        m_principalTypeSelect = new ComboBox();
138        m_principalTypeSelect.setWidth("150px");
139        Map<String, String> principalTypes = new LinkedHashMap<String, String>();
140        principalTypes.put(
141            I_CmsPrincipal.PRINCIPAL_USER,
142            CmsVaadinUtils.getMessageText(org.opencms.workplace.commons.Messages.GUI_LABEL_USER_0));
143        principalTypes.put(
144            I_CmsPrincipal.PRINCIPAL_GROUP,
145            CmsVaadinUtils.getMessageText(org.opencms.workplace.commons.Messages.GUI_LABEL_GROUP_0));
146        CmsVaadinUtils.prepareComboBox(m_principalTypeSelect, principalTypes);
147
148        m_principalTypeSelect.setNewItemsAllowed(false);
149        m_principalTypeSelect.setNullSelectionAllowed(false);
150        m_principalTypeSelect.select(I_CmsPrincipal.PRINCIPAL_USER);
151        m_main.addComponent(m_principalTypeSelect);
152
153        m_principalName = new TextField();
154        m_principalName.setWidth("100%");
155        m_main.addComponent(m_principalName);
156        m_main.setExpandRatio(m_principalName, 2);
157
158        m_selectPrincipalButton = new Button(FontAwesome.USER);
159        m_selectPrincipalButton.addStyleName(OpenCmsTheme.BUTTON_ICON);
160        m_selectPrincipalButton.addClickListener(new ClickListener() {
161
162            private static final long serialVersionUID = 1L;
163
164            public void buttonClick(ClickEvent event) {
165
166                openPrincipalSelect();
167            }
168        });
169        m_main.addComponent(m_selectPrincipalButton);
170    }
171
172    /**
173     * @see com.vaadin.v7.data.Property.ValueChangeNotifier#addListener(com.vaadin.v7.data.Property.ValueChangeListener)
174     */
175    @SuppressWarnings({"deprecation", "javadoc"})
176    public void addListener(com.vaadin.v7.data.Property.ValueChangeListener listener) {
177
178        m_principalName.addListener(listener);
179    }
180
181    /**
182     * @see com.vaadin.data.Validatable#addValidator(com.vaadin.data.Validator)
183     */
184    public void addValidator(Validator validator) {
185
186        m_principalName.addValidator(validator);
187    }
188
189    /**
190     * @see com.vaadin.v7.data.Property.ValueChangeNotifier#addValueChangeListener(com.vaadin.v7.data.Property.ValueChangeListener)
191     */
192    public void addValueChangeListener(com.vaadin.v7.data.Property.ValueChangeListener listener) {
193
194        m_principalName.addValueChangeListener(listener);
195    }
196
197    /**
198     * @see com.vaadin.v7.ui.Field#clear()
199     */
200    public void clear() {
201
202        m_principalName.clear();
203    }
204
205    /**
206     * @see com.vaadin.v7.data.Buffered#commit()
207     */
208    public void commit() throws SourceException, InvalidValueException {
209
210        m_principalName.commit();
211    }
212
213    /**
214     * @see com.vaadin.v7.data.Buffered#discard()
215     */
216    public void discard() throws SourceException {
217
218        m_principalName.discard();
219    }
220
221    /**
222     * @see com.vaadin.ui.AbstractComponent#focus()
223     */
224    @Override
225    public void focus() {
226
227        m_principalName.focus();
228    }
229
230    /**
231     * @see com.vaadin.v7.data.Property.Viewer#getPropertyDataSource()
232     */
233    public Property getPropertyDataSource() {
234
235        return m_principalName.getPropertyDataSource();
236    }
237
238    /**
239     * @see com.vaadin.v7.ui.Field#getRequiredError()
240     */
241    public String getRequiredError() {
242
243        return m_principalName.getRequiredError();
244    }
245
246    /**
247     * @see com.vaadin.ui.Component.Focusable#getTabIndex()
248     */
249    public int getTabIndex() {
250
251        return m_principalName.getTabIndex();
252    }
253
254    /**
255     * @see com.vaadin.v7.data.Property#getType()
256     */
257    public Class<? extends String> getType() {
258
259        return m_principalName.getType();
260    }
261
262    /**
263     * @see com.vaadin.data.Validatable#getValidators()
264     */
265    public Collection<Validator> getValidators() {
266
267        return m_principalName.getValidators();
268    }
269
270    /**
271     * @see com.vaadin.v7.data.Property#getValue()
272     */
273    public String getValue() {
274
275        return m_principalName.getValue();
276    }
277
278    /**
279     * @see org.opencms.ui.dialogs.permissions.I_CmsPrincipalSelect#handlePrincipal(org.opencms.security.I_CmsPrincipal)
280     */
281    public void handlePrincipal(I_CmsPrincipal principal) {
282
283        setValue(principal.getName());
284
285    }
286
287    /**
288     * @see com.vaadin.v7.data.Buffered#isBuffered()
289     */
290    public boolean isBuffered() {
291
292        return m_principalName.isBuffered();
293    }
294
295    /**
296     * @see com.vaadin.v7.ui.Field#isEmpty()
297     */
298    public boolean isEmpty() {
299
300        return m_principalName.isEmpty();
301    }
302
303    /**
304     * @see com.vaadin.data.Validatable#isInvalidAllowed()
305     */
306    public boolean isInvalidAllowed() {
307
308        return m_principalName.isInvalidAllowed();
309    }
310
311    /**
312     * @see com.vaadin.v7.data.BufferedValidatable#isInvalidCommitted()
313     */
314    public boolean isInvalidCommitted() {
315
316        return m_principalName.isInvalidCommitted();
317    }
318
319    /**
320     * @see com.vaadin.v7.data.Buffered#isModified()
321     */
322    public boolean isModified() {
323
324        return m_principalName.isModified();
325    }
326
327    public boolean isReadOnly() {
328
329        return super.isReadOnly();
330    }
331
332    /**
333     * @see com.vaadin.v7.ui.Field#isRequired()
334     */
335    public boolean isRequired() {
336
337        return m_principalName.isRequired();
338    }
339
340    /**
341     * @see com.vaadin.data.Validatable#isValid()
342     */
343    public boolean isValid() {
344
345        return m_principalName.isValid();
346    }
347
348    /**
349     * @see com.vaadin.data.Validatable#removeAllValidators()
350     */
351    public void removeAllValidators() {
352
353        m_principalName.removeAllValidators();
354    }
355
356    /**
357     * @see com.vaadin.v7.data.Property.ValueChangeNotifier#removeListener(com.vaadin.v7.data.Property.ValueChangeListener)
358     */
359    @SuppressWarnings({"deprecation", "javadoc"})
360    public void removeListener(com.vaadin.v7.data.Property.ValueChangeListener listener) {
361
362        m_principalName.removeListener(listener);
363    }
364
365    /**
366     * @see com.vaadin.data.Validatable#removeValidator(com.vaadin.data.Validator)
367     */
368    public void removeValidator(Validator validator) {
369
370        m_principalName.removeValidator(validator);
371    }
372
373    /**
374     * @see com.vaadin.v7.data.Property.ValueChangeNotifier#removeValueChangeListener(com.vaadin.v7.data.Property.ValueChangeListener)
375     */
376    public void removeValueChangeListener(com.vaadin.v7.data.Property.ValueChangeListener listener) {
377
378        m_principalName.removeValueChangeListener(listener);
379    }
380
381    /**
382     * @see com.vaadin.v7.data.Buffered#setBuffered(boolean)
383     */
384    public void setBuffered(boolean buffered) {
385
386        m_principalName.setBuffered(buffered);
387    }
388
389    /**
390     * Set if web Ous should be included. Default behavior is true.<p>
391     *
392     * @param include boolean
393     */
394    public void setIncludeWebOus(boolean include) {
395
396        m_includeWebOus = include;
397    }
398
399    /**
400     * @see com.vaadin.data.Validatable#setInvalidAllowed(boolean)
401     */
402    public void setInvalidAllowed(boolean invalidValueAllowed) throws UnsupportedOperationException {
403
404        m_principalName.setInvalidAllowed(invalidValueAllowed);
405    }
406
407    /**
408     * @see com.vaadin.data.BufferedValidatable#setInvalidCommitted(boolean)
409     */
410    public void setInvalidCommitted(boolean isCommitted) {
411
412        m_principalName.setInvalidCommitted(isCommitted);
413    }
414
415    /**
416     * Enable layout margins. Affects all four sides of the layout.
417     * This will tell the client-side implementation to leave extra space around the layout.
418     * The client-side implementation decides the actual amount, and it can vary between themes.<p>
419     *
420     * @param enabled <code>true</code> if margins should be enabled on all sides, false to disable all margins
421     */
422    public void setMargin(boolean enabled) {
423
424        ((HorizontalLayout)getCompositionRoot()).setMargin(enabled);
425    }
426
427    /**
428     * Set the ou.
429     *
430     * @param ou to choose principals for
431     */
432    public void setOU(String ou) {
433
434        m_ou = ou;
435    }
436
437    public void setOuChangeEnabled(boolean enabled) {
438
439        m_ouChangeEnabled = enabled;
440    }
441
442    /**
443     * Sets the principal type and clears the name.<p>
444     *
445     * @param type the principal type
446     */
447    public void setPrincipalType(String type) {
448
449        m_principalName.setValue("");
450        m_principalTypeSelect.setValue(type);
451    }
452
453    /**
454     * @see com.vaadin.v7.data.Property.Viewer#setPropertyDataSource(com.vaadin.v7.data.Property)
455     */
456    public void setPropertyDataSource(Property newDataSource) {
457
458        m_principalName.setPropertyDataSource(newDataSource);
459    }
460
461    public void setReadOnly(boolean readOnly) {
462
463        super.setReadOnly(readOnly);
464    }
465
466    /**
467     * Controls whether only real users/groups or also pseudo-principals like ALL_OTHERS should be shown.
468     *
469     *  @param realOnly if true, only real users / groups will be shown
470     */
471    public void setRealPrincipalsOnly(boolean realOnly) {
472
473        m_realOnly = realOnly;
474    }
475
476    /**
477     * @see com.vaadin.v7.ui.Field#setRequired(boolean)
478     */
479    public void setRequired(boolean required) {
480
481        m_principalName.setRequired(required);
482    }
483
484    /**
485     * @see com.vaadin.v7.ui.Field#setRequiredError(java.lang.String)
486     */
487    public void setRequiredError(String requiredMessage) {
488
489        m_principalName.setRequiredError(requiredMessage);
490    }
491
492    /**
493     * Enables/disables selection of the 'Roles' prinipal type.<p>
494     *
495     * @param editRoles true if the user should be allowed to select roles
496     */
497    public void setRoleSelectionAllowed(boolean editRoles) {
498
499        m_principalTypeSelect.removeItem(CmsRole.PRINCIPAL_ROLE);
500        if (editRoles) {
501            Item item = m_principalTypeSelect.addItem(CmsRole.PRINCIPAL_ROLE);
502            String roleText = CmsVaadinUtils.getMessageText(org.opencms.workplace.commons.Messages.GUI_LABEL_ROLE_0);
503            item.getItemProperty(CmsVaadinUtils.PROPERTY_LABEL).setValue(roleText);
504        }
505        m_principalTypeSelect.setNewItemsAllowed(!editRoles);
506
507    }
508
509    /**
510     * Sets the principal select handler.<p>
511     *
512     * @param selectHandler the principal select handler
513     */
514    public void setSelectHandler(I_PrincipalSelectHandler selectHandler) {
515
516        m_selectHandler = selectHandler;
517        enableSetButton(m_selectHandler != null);
518    }
519
520    /**
521     * @see com.vaadin.ui.Component.Focusable#setTabIndex(int)
522     */
523    public void setTabIndex(int tabIndex) {
524
525        m_principalName.setTabIndex(tabIndex);
526    }
527
528    /**
529     * @see org.opencms.ui.dialogs.permissions.I_CmsPrincipalSelect#setType(java.lang.String)
530     */
531    public void setType(String type) {
532
533        setPrincipalType(type);
534
535    }
536
537    /**
538     * @see com.vaadin.v7.data.Property#setValue(java.lang.Object)
539     */
540    public void setValue(String newValue) throws com.vaadin.v7.data.Property.ReadOnlyException {
541
542        m_principalName.setValue(newValue);
543    }
544
545    /**
546     * Sets the widget type.<p>
547     *
548     * @param type the widget type
549     */
550    public void setWidgetType(WidgetType type) {
551
552        m_widgetType = type;
553        m_principalTypeSelect.setVisible(m_widgetType.equals(WidgetType.principalwidget));
554        m_principalTypeSelect.setValue(
555            m_widgetType.equals(WidgetType.groupwidget)
556            ? I_CmsPrincipal.PRINCIPAL_GROUP
557            : I_CmsPrincipal.PRINCIPAL_USER);
558    }
559
560    /**
561     * @see com.vaadin.data.Validatable#validate()
562     */
563    public void validate() throws InvalidValueException {
564
565        m_principalName.validate();
566    }
567
568    /**
569     * @see com.vaadin.v7.data.Property.ValueChangeListener#valueChange(com.vaadin.v7.data.Property.ValueChangeEvent)
570     */
571    public void valueChange(com.vaadin.v7.data.Property.ValueChangeEvent event) {
572
573        m_principalName.valueChange(event);
574    }
575
576    /**
577     * Closes the principal select dialog window if present.<p>
578     */
579    protected void closeWindow() {
580
581        if (m_window != null) {
582            m_window.close();
583            m_window = null;
584        }
585    }
586
587    /**
588     * Sets the principal type and name.<p>
589     *
590     * @param type the principal type
591     * @param principalName the principal name
592     */
593    protected void setPrincipal(int type, String principalName) {
594
595        m_principalName.setValue(principalName);
596
597        String typeName = null;
598        switch (type) {
599            case 0:
600                typeName = I_CmsPrincipal.PRINCIPAL_GROUP;
601                break;
602            case 1:
603            default:
604                typeName = I_CmsPrincipal.PRINCIPAL_USER;
605                break;
606        }
607        if (typeName != null) {
608            m_principalTypeSelect.setValue(typeName);
609        }
610    }
611
612    /**
613     * Calls the principal select handler.<p>
614     */
615    void onSelect() {
616
617        if (m_selectHandler != null) {
618            String principalType = (String)m_principalTypeSelect.getValue();
619            if (CmsVaadinUtils.getMessageText(org.opencms.workplace.commons.Messages.GUI_LABEL_ROLE_0).equals(
620                principalType)) {
621                principalType = CmsRole.PRINCIPAL_ROLE;
622            }
623            m_selectHandler.onPrincipalSelect(principalType, m_principalName.getValue());
624        }
625    }
626
627    /**
628     * Opens the principal select dialog window.<p>
629     */
630    void openPrincipalSelect() {
631
632        CmsPrincipalSelectDialog dialog;
633
634        m_window = CmsBasicDialog.prepareWindow(DialogWidth.max);
635        WidgetType defaultType = WidgetType.groupwidget;
636        if (m_principalTypeSelect.getValue().equals(I_CmsPrincipal.PRINCIPAL_USER)) {
637            defaultType = WidgetType.userwidget;
638        }
639
640        dialog = new CmsPrincipalSelectDialog(
641            this,
642            m_ou == null ? A_CmsUI.getCmsObject().getRequestContext().getOuFqn() : m_ou,
643            m_window,
644            m_widgetType,
645            m_realOnly,
646            defaultType,
647            m_includeWebOus);
648
649        dialog.setOuComboBoxEnabled(m_ouChangeEnabled);
650
651        m_window.setCaption(
652            CmsVaadinUtils.getMessageText(
653                org.opencms.workplace.commons.Messages.GUI_PRINCIPALSELECTION_LIST_ACTION_SELECT_NAME_0));
654        m_window.setContent(dialog);
655        A_CmsUI.get().addWindow(m_window);
656    }
657
658    /**
659     * Sets the add permission button enabled.<p>
660     *
661     * @param enabled <code>true</code> to enable the button
662     */
663    private void enableSetButton(boolean enabled) {
664
665        if (enabled) {
666            if (m_addPermissionSetButton == null) {
667                m_addPermissionSetButton = new Button(FontAwesome.PLUS);
668                m_addPermissionSetButton.addStyleName(OpenCmsTheme.BUTTON_ICON);
669                m_addPermissionSetButton.addClickListener(new ClickListener() {
670
671                    private static final long serialVersionUID = 1L;
672
673                    public void buttonClick(ClickEvent event) {
674
675                        onSelect();
676                    }
677                });
678                m_main.addComponent(m_addPermissionSetButton);
679            }
680        } else if (m_addPermissionSetButton != null) {
681            m_main.removeComponent(m_addPermissionSetButton);
682            m_addPermissionSetButton = null;
683        }
684    }
685}