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;
029
030import org.opencms.ade.configuration.CmsElementView;
031import org.opencms.ade.configuration.CmsResourceTypeConfig;
032import org.opencms.ade.containerpage.CmsAddDialogTypeHelper;
033import org.opencms.ade.galleries.shared.CmsResourceTypeBean;
034import org.opencms.ade.galleries.shared.CmsResourceTypeBean.Origin;
035import org.opencms.configuration.preferences.CmsElementViewPreference;
036import org.opencms.db.CmsUserSettings;
037import org.opencms.file.CmsObject;
038import org.opencms.file.CmsResource;
039import org.opencms.main.CmsLog;
040import org.opencms.main.OpenCms;
041import org.opencms.ui.A_CmsUI;
042import org.opencms.ui.CmsVaadinUtils;
043import org.opencms.ui.I_CmsDialogContext;
044import org.opencms.ui.Messages;
045import org.opencms.ui.components.CmsBasicDialog;
046import org.opencms.ui.components.CmsOkCancelActionHandler;
047import org.opencms.ui.components.CmsResourceInfo;
048import org.opencms.util.CmsUUID;
049import org.opencms.workplace.explorer.CmsExplorerTypeSettings;
050import org.opencms.workplace.explorer.CmsResourceUtil;
051
052import java.util.ArrayList;
053import java.util.Collections;
054import java.util.Comparator;
055import java.util.HashMap;
056import java.util.LinkedHashMap;
057import java.util.List;
058import java.util.Locale;
059import java.util.Map;
060
061import org.apache.commons.logging.Log;
062
063import com.google.common.base.Predicate;
064import com.google.common.collect.ComparisonChain;
065import com.google.common.collect.Lists;
066import com.google.common.collect.Maps;
067import com.vaadin.event.LayoutEvents.LayoutClickEvent;
068import com.vaadin.event.LayoutEvents.LayoutClickListener;
069import com.vaadin.server.VaadinService;
070import com.vaadin.ui.AbstractComponent;
071import com.vaadin.ui.Button;
072import com.vaadin.ui.Button.ClickEvent;
073import com.vaadin.ui.Button.ClickListener;
074import com.vaadin.ui.Component;
075import com.vaadin.ui.declarative.Design;
076import com.vaadin.v7.data.Property.ValueChangeEvent;
077import com.vaadin.v7.data.Property.ValueChangeListener;
078import com.vaadin.v7.ui.AbstractSelect.ItemCaptionMode;
079import com.vaadin.v7.ui.ComboBox;
080import com.vaadin.v7.ui.VerticalLayout;
081
082public abstract class A_CmsSelectResourceTypeDialog extends CmsBasicDialog {
083
084    /** Default value for the 'default location' check box. */
085    public static final Boolean DEFAULT_LOCATION_DEFAULT = Boolean.TRUE;
086
087    /** Id for the 'All' pseudo-view. */
088    public static final CmsUUID ID_VIEW_ALL = CmsUUID.getConstantUUID("view-all");
089
090    /** Setting name for the standard view. */
091    public static final String SETTING_STANDARD_VIEW = "newDialogStandardView";
092
093    /** The 'All' pseudo-view. */
094    public static final CmsElementView VIEW_ALL = new CmsElementView(ID_VIEW_ALL);
095
096    /** Logger instance for this class. */
097    private static final Log LOG = CmsLog.getLog(CmsNewDialog.class);
098
099    /** Serial version id. */
100    private static final long serialVersionUID = 1L;
101
102    private Map<CmsResourceTypeBean, CmsResourceInfo> m_resourceInfoMap = new HashMap<CmsResourceTypeBean, CmsResourceInfo>();
103
104    /** The created resource. */
105    protected CmsResource m_createdResource;
106
107    /** The current view id. */
108    protected CmsElementView m_currentView;
109
110    /** The dialog context. */
111    protected I_CmsDialogContext m_dialogContext;
112
113    /** The current folder. */
114    protected CmsResource m_folderResource;
115
116    /** The selected type. */
117    protected CmsResourceTypeBean m_selectedType;
118
119    /** The type helper. */
120    protected CmsAddDialogTypeHelper m_typeHelper;
121
122    private Runnable m_selectedRunnable;
123
124    /** List of all types. */
125    private List<CmsResourceTypeBean> m_allTypes;
126
127    /**
128     * Creates a new instance.<p>
129     *
130     * @param folderResource the folder resource
131     * @param context the context
132     */
133    public A_CmsSelectResourceTypeDialog(CmsResource folderResource, I_CmsDialogContext context) {
134
135        m_folderResource = folderResource;
136        m_dialogContext = context;
137
138        Design.read(this);
139        CmsVaadinUtils.visitDescendants(this, new Predicate<Component>() {
140
141            public boolean apply(Component component) {
142
143                component.setCaption(CmsVaadinUtils.localizeString(component.getCaption()));
144                return true;
145            }
146        });
147        CmsUUID initViewId = (CmsUUID)VaadinService.getCurrentRequest().getWrappedSession().getAttribute(
148            SETTING_STANDARD_VIEW);
149        if (initViewId == null) {
150            try {
151                CmsUserSettings settings = new CmsUserSettings(A_CmsUI.getCmsObject());
152                String viewSettingStr = settings.getAdditionalPreference(
153                    CmsElementViewPreference.EXPLORER_PREFERENCE_NAME,
154                    true);
155                if ((viewSettingStr != null) && CmsUUID.isValidUUID(viewSettingStr)) {
156                    initViewId = new CmsUUID(viewSettingStr);
157                }
158            } catch (Exception e) {
159                LOG.error(e.getLocalizedMessage(), e);
160            }
161        }
162        if (initViewId == null) {
163            initViewId = CmsUUID.getNullUUID();
164        }
165        CmsElementView initView = initViews(initViewId);
166
167        getCancelButton().addClickListener(new ClickListener() {
168
169            private static final long serialVersionUID = 1L;
170
171            public void buttonClick(ClickEvent event) {
172
173                finish(new ArrayList<CmsUUID>());
174            }
175        });
176
177        getViewSelector().setNullSelectionAllowed(false);
178        getViewSelector().setTextInputAllowed(false);
179        getVerticalLayout().addLayoutClickListener(new LayoutClickListener() {
180
181            private static final long serialVersionUID = 1L;
182
183            public void layoutClick(LayoutClickEvent event) {
184
185                CmsResourceTypeBean clickedType = (CmsResourceTypeBean)(((AbstractComponent)(event.getChildComponent())).getData());
186                handleSelection(clickedType);
187            }
188        });
189        setActionHandler(new CmsOkCancelActionHandler() {
190
191            private static final long serialVersionUID = 1L;
192
193            @Override
194            protected void cancel() {
195
196                finish(new ArrayList<CmsUUID>());
197            }
198
199            @Override
200            protected void ok() {
201
202                // nothing to do
203            }
204        });
205        init(initView, true);
206    }
207
208    /**
209     * Notifies the context that the given ids have changed.<p>
210     *
211     * @param ids the ids
212     */
213    public void finish(List<CmsUUID> ids) {
214
215        if (m_selectedRunnable == null) {
216            m_dialogContext.finish(ids);
217            if (ids.size() == 1) {
218                m_dialogContext.focus(ids.get(0));
219
220            }
221        } else {
222            m_selectedRunnable.run();
223        }
224    }
225
226    public abstract Button getCancelButton();
227
228    public CmsResourceInfo getTypeInfoLayout() {
229
230        return m_selectedType != null ? m_resourceInfoMap.get(m_selectedType) : null;
231    }
232
233    public abstract VerticalLayout getVerticalLayout();
234
235    public abstract ComboBox getViewSelector();
236
237    /**
238     * Handles selection of a type.<p>
239     *
240     * @param selectedType the selected type
241     */
242    public abstract void handleSelection(final CmsResourceTypeBean selectedType);
243
244    /**
245     * Initializes and displays the type list for the given view.<p>
246     *
247     * @param view the element view
248     * @param useDefault true if we should use the default location for resource creation
249     */
250    public void init(CmsElementView view, boolean useDefault) {
251
252        m_currentView = view;
253        if (!view.getId().equals(getViewSelector().getValue())) {
254            getViewSelector().setValue(view.getId());
255        }
256        getVerticalLayout().removeAllComponents();
257
258        List<CmsResourceTypeBean> typeBeans = m_typeHelper.getPrecomputedTypes(view);
259        if (view.getId().equals(ID_VIEW_ALL)) {
260            typeBeans = m_allTypes;
261        }
262
263        if (typeBeans == null) {
264
265            LOG.warn("precomputed type list is null: " + view.getTitle(A_CmsUI.getCmsObject(), Locale.ENGLISH));
266            return;
267        }
268        for (CmsResourceTypeBean type : typeBeans) {
269            final String typeName = type.getType();
270            String title = typeName;
271            String subtitle = getSubtitle(type, useDefault);
272            CmsExplorerTypeSettings explorerType = OpenCms.getWorkplaceManager().getExplorerTypeSetting(typeName);
273
274            title = CmsVaadinUtils.getMessageText(explorerType.getKey());
275            CmsResourceInfo info = new CmsResourceInfo(
276                title,
277                subtitle,
278                CmsResourceUtil.getBigIconResource(explorerType, null));
279            info.setData(type);
280            m_resourceInfoMap.put(type, info);
281            getVerticalLayout().addComponent(info);
282        }
283    }
284
285    public void setSelectedRunnable(Runnable run) {
286
287        m_selectedRunnable = run;
288    }
289
290    public abstract boolean useDefault();
291
292    /**
293     * Creates type helper which is responsible for generating the type list.<p>
294     *
295     * @return the type helper
296     */
297    protected CmsAddDialogTypeHelper createTypeHelper() {
298
299        return new CmsAddDialogTypeHelper(CmsResourceTypeConfig.AddMenuType.workplace) {
300
301            @Override
302            protected boolean exclude(CmsResourceTypeBean type) {
303
304                String typeName = type.getType();
305                CmsExplorerTypeSettings explorerType = OpenCms.getWorkplaceManager().getExplorerTypeSetting(typeName);
306                boolean noCreate = !(type.isCreatableType() && !type.isDeactivated());
307                return noCreate || (explorerType == null) || !explorerType.isCreatable();
308            }
309        };
310
311    }
312
313    /**
314     * Gets the subtitle for the type info widget.<p>
315     *
316     * @param type the type
317     * @param useDefault true if we are in 'use default' mode
318     *
319     * @return the subtitle
320     */
321    protected String getSubtitle(CmsResourceTypeBean type, boolean useDefault) {
322
323        String subtitle = "";
324        CmsExplorerTypeSettings explorerType = OpenCms.getWorkplaceManager().getExplorerTypeSetting(type.getType());
325        if ((explorerType != null) && (explorerType.getInfo() != null)) {
326            subtitle = CmsVaadinUtils.getMessageText(explorerType.getInfo());
327        }
328        if (useDefault && (type.getOrigin() == Origin.config) && (type.getCreatePath() != null)) {
329            String path = type.getCreatePath();
330            CmsObject cms = A_CmsUI.getCmsObject();
331            path = cms.getRequestContext().removeSiteRoot(path);
332            subtitle = CmsVaadinUtils.getMessageText(Messages.GUI_NEW_CREATE_IN_PATH_1, path);
333        }
334        return subtitle;
335    }
336
337    /**
338     * Initializes the view selector, using the given view id as an initial value.<p>
339     *
340     * @param startId the start view
341     *
342     * @return the start view
343     */
344    private CmsElementView initViews(CmsUUID startId) {
345
346        Map<CmsUUID, CmsElementView> viewMap = OpenCms.getADEManager().getElementViews(A_CmsUI.getCmsObject());
347        List<CmsElementView> viewList = new ArrayList<CmsElementView>(viewMap.values());
348        Collections.sort(viewList, new Comparator<CmsElementView>() {
349
350            public int compare(CmsElementView arg0, CmsElementView arg1) {
351
352                return ComparisonChain.start().compare(arg0.getOrder(), arg1.getOrder()).result();
353            }
354
355        });
356        getViewSelector().setItemCaptionMode(ItemCaptionMode.EXPLICIT);
357        m_typeHelper = createTypeHelper();
358        m_typeHelper.precomputeTypeLists(
359            A_CmsUI.getCmsObject(),
360            m_folderResource.getRootPath(),
361            A_CmsUI.getCmsObject().getRequestContext().removeSiteRoot(m_folderResource.getRootPath()),
362            viewList,
363            null);
364
365        // also collect types in LinkedHashMap to preserve order and ensure uniqueness
366        LinkedHashMap<String, CmsResourceTypeBean> allTypes = Maps.newLinkedHashMap();
367
368        for (CmsElementView view : viewList) {
369
370            if (view.hasPermission(A_CmsUI.getCmsObject(), m_folderResource)) {
371
372                List<CmsResourceTypeBean> typeBeans = m_typeHelper.getPrecomputedTypes(view);
373
374                if (typeBeans.isEmpty()) {
375                    continue;
376                }
377                for (CmsResourceTypeBean typeBean : typeBeans) {
378                    allTypes.put(typeBean.getType(), typeBean);
379                }
380                getViewSelector().addItem(view.getId());
381                getViewSelector().setItemCaption(
382                    view.getId(),
383                    view.getTitle(A_CmsUI.getCmsObject(), A_CmsUI.get().getLocale()));
384            }
385        }
386        getViewSelector().addItem(VIEW_ALL.getId());
387        getViewSelector().setItemCaption(VIEW_ALL.getId(), CmsVaadinUtils.getMessageText(Messages.GUI_VIEW_ALL_0));
388        m_allTypes = Lists.newArrayList(allTypes.values());
389        if (allTypes.size() <= 8) {
390            startId = ID_VIEW_ALL;
391        }
392        if (getViewSelector().getItem(startId) == null) {
393            startId = (CmsUUID)(getViewSelector().getItemIds().iterator().next());
394        }
395
396        getViewSelector().addValueChangeListener(new ValueChangeListener() {
397
398            private static final long serialVersionUID = 1L;
399
400            public void valueChange(ValueChangeEvent event) {
401
402                CmsUUID viewId = (CmsUUID)(event.getProperty().getValue());
403                CmsElementView selectedView;
404                if (viewId.equals(ID_VIEW_ALL)) {
405                    selectedView = VIEW_ALL;
406                } else {
407                    selectedView = OpenCms.getADEManager().getElementViews(A_CmsUI.getCmsObject()).get(
408                        event.getProperty().getValue());
409                }
410                init(selectedView, useDefault());
411                if (selectedView != VIEW_ALL) {
412                    VaadinService.getCurrentRequest().getWrappedSession().setAttribute(
413                        SETTING_STANDARD_VIEW,
414                        (event.getProperty().getValue()));
415                }
416            }
417        });
418        if (startId.equals(ID_VIEW_ALL)) {
419            return VIEW_ALL;
420        } else {
421            return OpenCms.getADEManager().getElementViews(A_CmsUI.getCmsObject()).get(startId);
422        }
423    }
424
425}