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 GmbH & Co. KG, 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.workplace.tools.searchindex;
029
030import org.opencms.configuration.CmsSearchConfiguration;
031import org.opencms.i18n.CmsMessageContainer;
032import org.opencms.jsp.CmsJspActionElement;
033import org.opencms.main.CmsLog;
034import org.opencms.main.OpenCms;
035import org.opencms.search.CmsSearchDocumentType;
036import org.opencms.search.CmsSearchIndexSource;
037import org.opencms.search.CmsSearchManager;
038import org.opencms.workplace.CmsWorkplaceSettings;
039import org.opencms.workplace.list.CmsListColumnAlignEnum;
040import org.opencms.workplace.list.CmsListColumnDefinition;
041import org.opencms.workplace.list.CmsListDefaultAction;
042import org.opencms.workplace.list.CmsListDirectAction;
043import org.opencms.workplace.list.CmsListItem;
044import org.opencms.workplace.list.CmsListItemDetails;
045import org.opencms.workplace.list.CmsListItemDetailsFormatter;
046import org.opencms.workplace.list.CmsListMetadata;
047import org.opencms.workplace.list.CmsListMultiAction;
048import org.opencms.workplace.list.CmsListOrderEnum;
049
050import java.util.ArrayList;
051import java.util.Collections;
052import java.util.Iterator;
053import java.util.List;
054
055import javax.servlet.http.HttpServletRequest;
056import javax.servlet.http.HttpServletResponse;
057import javax.servlet.jsp.PageContext;
058
059import org.apache.commons.logging.Log;
060
061/**
062 * A list that displays the document types of the system that are not assigned to
063 * a request parameter given
064 * <code>{@link org.opencms.search.CmsSearchIndexSource}</code> ("indexsource") and
065 * offers add single- and multi-actions that add those document types to the current
066 * indexsource.<p>
067 *
068 * This list is no stand-alone page but has to be embedded in another dialog
069 * (see <code> {@link org.opencms.workplace.tools.searchindex.A_CmsEmbeddedListDialog}</code>. <p>
070 *
071 * @since 6.0.0
072 */
073public class CmsDocumentTypeAddList extends A_CmsEmbeddedListDialog {
074
075    /** list action id constant. */
076    public static final String LIST_ACTION_ADD_DOCTYPE = "aad";
077
078    /** list action id constant. */
079    public static final String LIST_ACTION_ADD_DOCTYPE2 = LIST_ACTION_ADD_DOCTYPE + "2";
080
081    /** list action dummy id constant. */
082    public static final String LIST_ACTION_NONE = "an";
083
084    /** list column id constant. */
085    public static final String LIST_COLUMN_ADD_DOCTYPE = "cad";
086
087    /** list column id constant. */
088    public static final String LIST_COLUMN_DOCCLASS = "cdc";
089
090    /** list column id constant. */
091    public static final String LIST_COLUMN_ICON = "ci";
092
093    /** list column id constant. */
094    public static final String LIST_COLUMN_NAME = "cn";
095
096    /** list item detail id constant. */
097    public static final String LIST_DETAIL_MIMETYPES = "dmt";
098
099    /** list item detail id constant. */
100    public static final String LIST_DETAIL_RESOURCETYPES = "drt";
101
102    /** list id constant. */
103    public static final String LIST_ID = "lssisdta";
104
105    /** list action id constant. */
106    public static final String LIST_MACTION_ADD_DOCTYPE = "maad";
107
108    /** The log object for this class. */
109    private static final Log LOG = CmsLog.getLog(CmsDocumentTypeAddList.class);
110
111    /** Stores the value of the request parameter for the search index source name. */
112    private String m_paramIndexsource;
113
114    /**
115     * Public constructor.<p>
116     *
117     * @param jsp an initialized JSP action element
118     */
119    public CmsDocumentTypeAddList(CmsJspActionElement jsp) {
120
121        this(jsp, LIST_ID, Messages.get().container(Messages.GUI_LIST_DOCUMENTTYPES_AVAIL_NAME_0));
122    }
123
124    /**
125     * Public constructor.<p>
126     *
127     * @param jsp an initialized JSP action element
128     * @param listId the id of the list
129     * @param listName the list name
130     */
131    public CmsDocumentTypeAddList(CmsJspActionElement jsp, String listId, CmsMessageContainer listName) {
132
133        this(jsp, listId, listName, LIST_COLUMN_NAME, CmsListOrderEnum.ORDER_ASCENDING, null);
134    }
135
136    /**
137     * Public constructor.<p>
138     *
139     * @param jsp an initialized JSP action element
140     * @param listId the id of the displayed list
141     * @param listName the name of the list
142     * @param sortedColId the a priory sorted column
143     * @param sortOrder the order of the sorted column
144     * @param searchableColId the column to search into
145     */
146    public CmsDocumentTypeAddList(
147        CmsJspActionElement jsp,
148        String listId,
149        CmsMessageContainer listName,
150        String sortedColId,
151        CmsListOrderEnum sortOrder,
152        String searchableColId) {
153
154        super(jsp, listId, listName, sortedColId, sortOrder, searchableColId);
155
156    }
157
158    /**
159     * Public constructor.<p>
160     *
161     * Public constructor with JSP variables.<p>
162     *
163     * @param context the JSP page context
164     * @param req the JSP request
165     * @param res the JSP response
166     */
167    public CmsDocumentTypeAddList(PageContext context, HttpServletRequest req, HttpServletResponse res) {
168
169        this(new CmsJspActionElement(context, req, res));
170    }
171
172    /**
173     * @see org.opencms.workplace.list.A_CmsListDialog#executeListMultiActions()
174     */
175    @Override
176    public void executeListMultiActions() {
177
178        CmsSearchManager searchManager = OpenCms.getSearchManager();
179        if (getParamListAction().equals(LIST_MACTION_ADD_DOCTYPE)) {
180            // execute the delete multiaction
181            Iterator<CmsListItem> itItems = getSelectedItems().iterator();
182            CmsListItem listItem;
183            String doctype;
184            CmsSearchIndexSource idxsrc = searchManager.getIndexSource(getParamIndexsource());
185            while (itItems.hasNext()) {
186                listItem = itItems.next();
187                doctype = (String)listItem.get(LIST_COLUMN_NAME);
188                idxsrc.addDocumentType(doctype);
189            }
190            writeConfiguration(false);
191            refreshList();
192        }
193        listSave();
194    }
195
196    /**
197     * @see org.opencms.workplace.list.A_CmsListDialog#executeListSingleActions()
198     */
199    @Override
200    public void executeListSingleActions() {
201
202        CmsSearchManager searchManager = OpenCms.getSearchManager();
203        String action = getParamListAction();
204        if (action.equals(LIST_ACTION_ADD_DOCTYPE) || action.equals(LIST_ACTION_ADD_DOCTYPE2)) {
205            CmsSearchIndexSource idxsrc = searchManager.getIndexSource(getParamIndexsource());
206            CmsListItem item = getSelectedItem();
207            String doctypeName = (String)item.get(LIST_COLUMN_NAME);
208            idxsrc.addDocumentType(doctypeName);
209            refreshList();
210            writeConfiguration(false);
211        }
212    }
213
214    /**
215     * Returns the request parameter "indexsource".<p>
216     *
217     * @return the request parameter "indexsource"
218     */
219    public String getParamIndexsource() {
220
221        return m_paramIndexsource;
222    }
223
224    /**
225     * Sets the request parameter "indexsource". <p>
226     *
227     * Method intended for workplace-properietary automatic filling of
228     * request parameter values to dialogs, not for manual invocation. <p>
229     *
230     * @param indexsource the request parameter "indexsource" to set
231     */
232    public void setParamIndexsource(String indexsource) {
233
234        m_paramIndexsource = indexsource;
235    }
236
237    /**
238     * @see org.opencms.workplace.list.A_CmsListDialog#fillDetails(java.lang.String)
239     */
240    @Override
241    protected void fillDetails(String detailId) {
242
243        // get content
244        List<CmsListItem> items = getList().getAllContent();
245        Iterator<CmsListItem> itItems = items.iterator();
246        CmsListItem item;
247        if (detailId.equals(LIST_DETAIL_MIMETYPES)) {
248            while (itItems.hasNext()) {
249                item = itItems.next();
250                fillDetailMimetypes(item, detailId);
251
252            }
253        }
254        if (detailId.equals(LIST_DETAIL_RESOURCETYPES)) {
255            while (itItems.hasNext()) {
256                item = itItems.next();
257                fillDetailResourceTypes(item, detailId);
258
259            }
260
261        }
262
263    }
264
265    /**
266     * @see org.opencms.workplace.list.A_CmsListDialog#getListItems()
267     */
268    @Override
269    protected List<CmsListItem> getListItems() {
270
271        List<CmsListItem> result = new ArrayList<CmsListItem>();
272        // get content
273        List<CmsSearchDocumentType> doctypes = documentTypes();
274        Iterator<CmsSearchDocumentType> itDoctypes = doctypes.iterator();
275        CmsSearchDocumentType doctype;
276        while (itDoctypes.hasNext()) {
277            doctype = itDoctypes.next();
278            CmsListItem item = getList().newItem(doctype.getName());
279            item.set(LIST_COLUMN_NAME, doctype.getName());
280            item.set(LIST_COLUMN_DOCCLASS, doctype.getClassName());
281            result.add(item);
282        }
283        return result;
284    }
285
286    /**
287     * @see org.opencms.workplace.CmsWorkplace#initMessages()
288     */
289    @Override
290    protected void initMessages() {
291
292        // add specific dialog resource bundle
293        addMessages(Messages.get().getBundleName());
294        // add default resource bundles
295        super.initMessages();
296    }
297
298    /**
299     * @see org.opencms.workplace.list.A_CmsListDialog#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest)
300     */
301    @Override
302    protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) {
303
304        super.initWorkplaceRequestValues(settings, request);
305    }
306
307    /**
308     * @see org.opencms.workplace.list.A_CmsListDialog#setColumns(org.opencms.workplace.list.CmsListMetadata)
309     */
310    @Override
311    protected void setColumns(CmsListMetadata metadata) {
312
313        // create dummy column for corporate design reasons
314        CmsListColumnDefinition dummyCol = new CmsListColumnDefinition(LIST_COLUMN_ICON);
315        dummyCol.setName(Messages.get().container(Messages.GUI_LIST_DOCUMENTTYPE_NAME_0));
316        dummyCol.setHelpText(Messages.get().container(Messages.GUI_LIST_DOCUMENTTYPE_NAME_HELP_0));
317        dummyCol.setWidth("20");
318        dummyCol.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT);
319        dummyCol.setSorteable(false);
320        // add dummy icon
321        CmsListDirectAction dummyAction = new CmsListDirectAction(LIST_ACTION_NONE);
322        dummyAction.setName(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_COL_ICON_NAME_0));
323        dummyAction.setHelpText(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_COL_ICON_NAME_HELP_0));
324        dummyAction.setIconPath(CmsDocumentTypeList.ICON_DOCTYPE);
325        // disable!
326        dummyAction.setEnabled(false);
327        dummyCol.addDirectAction(dummyAction);
328        // add it to the list definition
329        metadata.addColumn(dummyCol);
330
331        // add column for add single-action
332        CmsListColumnDefinition addCol = new CmsListColumnDefinition(LIST_COLUMN_ADD_DOCTYPE);
333        addCol.setName(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_COL_ADD_DOCTYPE_NAME_0));
334        addCol.setHelpText(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_COL_ADD_DOCTYPE_NAME_HELP_0));
335        addCol.setWidth("20");
336        addCol.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT);
337        addCol.setSorteable(false);
338        // add add action
339        CmsListDirectAction addAction = new CmsListDirectAction(LIST_ACTION_ADD_DOCTYPE);
340        addAction.setName(Messages.get().container(Messages.GUI_LIST_SEARCHINDEX_ACTION_ADD_DOCTYPE_NAME_0));
341        addAction.setHelpText(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_COL_ADD_DOCTYPE_NAME_HELP_0));
342        addAction.setIconPath(ICON_ADD);
343        addCol.addDirectAction(addAction);
344        metadata.addColumn(addCol);
345
346        // add column for name
347        CmsListColumnDefinition nameCol = new CmsListColumnDefinition(LIST_COLUMN_NAME);
348        nameCol.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT);
349        nameCol.setName(Messages.get().container(Messages.GUI_LIST_SEARCHINDEX_COL_NAME_0));
350        nameCol.setWidth("50%");
351
352        // add duplicate remove action
353        CmsListDefaultAction remAction2 = new CmsListDefaultAction(LIST_ACTION_ADD_DOCTYPE2);
354        remAction2.setName(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_COL_ADD_DOCTYPE_NAME_0));
355        remAction2.setHelpText(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_COL_ADD_DOCTYPE_NAME_HELP_0));
356        nameCol.addDefaultAction(remAction2);
357        metadata.addColumn(nameCol);
358
359        // add column for document implementation class
360        CmsListColumnDefinition docclassCol = new CmsListColumnDefinition(LIST_COLUMN_DOCCLASS);
361        docclassCol.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT);
362        docclassCol.setName(Messages.get().container(Messages.GUI_LIST_DOCTYPE_COL_DOCCLASS_0));
363        docclassCol.setWidth("45%");
364        metadata.addColumn(docclassCol);
365
366    }
367
368    /**
369     * @see org.opencms.workplace.list.A_CmsListDialog#setIndependentActions(org.opencms.workplace.list.CmsListMetadata)
370     */
371    @Override
372    protected void setIndependentActions(CmsListMetadata metadata) {
373
374        // add document types of index source detail help
375        CmsListItemDetails mimetypeDetails = new CmsListItemDetails(LIST_DETAIL_MIMETYPES);
376        mimetypeDetails.setAtColumn(LIST_COLUMN_NAME);
377        mimetypeDetails.setVisible(false);
378        mimetypeDetails.setShowActionName(Messages.get().container(Messages.GUI_LIST_DOCTYPE_DETAIL_MIMETYPES_SHOW_0));
379        mimetypeDetails.setShowActionHelpText(
380            Messages.get().container(Messages.GUI_LIST_DOCTYPE_DETAIL_MIMETYPES_SHOW_HELP_0));
381        mimetypeDetails.setHideActionName(Messages.get().container(Messages.GUI_LIST_DOCTYPE_DETAIL_MIMETYPES_HIDE_0));
382        mimetypeDetails.setHideActionHelpText(
383            Messages.get().container(Messages.GUI_LIST_DOCTYPE_DETAIL_MIMETYPES_HIDE_HELP_0));
384        mimetypeDetails.setName(Messages.get().container(Messages.GUI_LIST_DOCTYPE_DETAIL_MIMETYPES_NAME_0));
385        mimetypeDetails.setFormatter(
386            new CmsListItemDetailsFormatter(
387                Messages.get().container(Messages.GUI_LIST_DOCTYPE_DETAIL_MIMETYPES_NAME_0)));
388        metadata.addItemDetails(mimetypeDetails);
389
390        // add resources of index source detail help
391        CmsListItemDetails resourceDetails = new CmsListItemDetails(LIST_DETAIL_RESOURCETYPES);
392        resourceDetails.setAtColumn(LIST_COLUMN_NAME);
393        resourceDetails.setVisible(false);
394        resourceDetails.setShowActionName(
395            Messages.get().container(Messages.GUI_LIST_DOCTYPE_DETAIL_RESOURCETYPES_SHOW_0));
396        resourceDetails.setShowActionHelpText(
397            Messages.get().container(Messages.GUI_LIST_DOCTYPE_DETAIL_RESOURCETYPES_SHOW_HELP_0));
398        resourceDetails.setHideActionName(
399            Messages.get().container(Messages.GUI_LIST_DOCTYPE_DETAIL_RESOURCETYPES_HIDE_0));
400        resourceDetails.setHideActionHelpText(
401            Messages.get().container(Messages.GUI_LIST_DOCTYPE_DETAIL_RESOURCETYPES_HIDE_HELP_0));
402        resourceDetails.setName(Messages.get().container(Messages.GUI_LIST_DOCTYPE_DETAIL_RESOURCETYPES_NAME_0));
403        resourceDetails.setFormatter(
404            new CmsListItemDetailsFormatter(
405                Messages.get().container(Messages.GUI_LIST_DOCTYPE_DETAIL_RESOURCETYPES_NAME_0)));
406        metadata.addItemDetails(resourceDetails);
407
408    }
409
410    /**
411     * @see org.opencms.workplace.list.A_CmsListDialog#setMultiActions(org.opencms.workplace.list.CmsListMetadata)
412     */
413    @Override
414    protected void setMultiActions(CmsListMetadata metadata) {
415
416        // add add multi action
417        CmsListMultiAction addMultiAction = new CmsListMultiAction(LIST_MACTION_ADD_DOCTYPE);
418        addMultiAction.setName(Messages.get().container(Messages.GUI_LIST_SEARCHINDEX_MACTION_ADD_DOCTYPE_NAME_0));
419        addMultiAction.setHelpText(
420            Messages.get().container(Messages.GUI_LIST_SEARCHINDEX_MACTION_ADD_DOCTYPE_NAME_HELP_0));
421        addMultiAction.setIconPath(ICON_MULTI_ADD);
422        metadata.addMultiAction(addMultiAction);
423    }
424
425    /**
426     * Writes the updated search configuration back to the XML
427     * configuration file and refreshes the complete list.<p>
428     *
429     * @param refresh if true, the list items are refreshed
430     */
431    protected void writeConfiguration(boolean refresh) {
432
433        // update the XML configuration
434        OpenCms.writeConfiguration(CmsSearchConfiguration.class);
435        if (refresh) {
436            refreshList();
437        }
438    }
439
440    /**
441     * Returns the systems configured document types that are not assigned
442     * to the current indexsource (those that may be added).<p>
443     *
444     * @return the systems configured document types that are not assigned
445     *         to the current indexsource (those that may be added)
446     */
447    private List<CmsSearchDocumentType> documentTypes() {
448
449        CmsSearchManager manager = OpenCms.getSearchManager();
450        CmsSearchIndexSource indexsource = manager.getIndexSource(getParamIndexsource());
451        List<CmsSearchDocumentType> result;
452        if (indexsource != null) {
453            List<String> systemDoctypeNames = new ArrayList<String>();
454            Iterator<CmsSearchDocumentType> itDocTypes = manager.getDocumentTypeConfigs().iterator();
455            while (itDocTypes.hasNext()) {
456                CmsSearchDocumentType docType = itDocTypes.next();
457                systemDoctypeNames.add(docType.getName());
458            }
459            // accept only the complement of system doctypes to the indexsources doctypes:
460            systemDoctypeNames.removeAll(indexsource.getDocumentTypes());
461
462            // transform these mere names to real document types...
463            result = new ArrayList<CmsSearchDocumentType>(systemDoctypeNames.size());
464            Iterator<String> it = systemDoctypeNames.iterator();
465            String doctypename = "";
466            CmsSearchDocumentType doctype;
467            while (it.hasNext()) {
468                doctypename = it.next();
469                if (doctypename != null) {
470                    doctype = manager.getDocumentTypeConfig(doctypename);
471                    if (doctype != null) {
472                        result.add(doctype);
473                    }
474                }
475            }
476        } else {
477            result = Collections.emptyList();
478            if (LOG.isErrorEnabled()) {
479                LOG.error(Messages.get().getBundle().key(Messages.ERR_SEARCHINDEX_EDIT_MISSING_PARAM_1, "indexsource"));
480            }
481        }
482        return result;
483    }
484
485    /**
486     * Fills details about configured mime types of the document type into the given item. <p>
487     *
488     * @param item the list item to fill
489     * @param detailId the id for the detail to fill
490     *
491     */
492    private void fillDetailMimetypes(CmsListItem item, String detailId) {
493
494        CmsSearchManager searchManager = OpenCms.getSearchManager();
495        StringBuffer html = new StringBuffer();
496
497        String doctypeName = (String)item.get(LIST_COLUMN_NAME);
498        CmsSearchDocumentType docType = searchManager.getDocumentTypeConfig(doctypeName);
499
500        // output of mime types
501        Iterator<String> itMimetypes = docType.getMimeTypes().iterator();
502        html.append("<ul>\n");
503        while (itMimetypes.hasNext()) {
504            html.append("  <li>\n").append("  ").append(itMimetypes.next()).append("\n");
505            html.append("  </li>");
506        }
507
508        html.append("</ul>\n");
509        item.set(detailId, html.toString());
510    }
511
512    /**
513     * Fills details about resource types of the document type into the given item. <p>
514     *
515     * @param item the list item to fill
516     * @param detailId the id for the detail to fill
517     *
518     */
519    private void fillDetailResourceTypes(CmsListItem item, String detailId) {
520
521        CmsSearchManager searchManager = OpenCms.getSearchManager();
522        StringBuffer html = new StringBuffer();
523
524        String doctypeName = (String)item.get(LIST_COLUMN_NAME);
525        CmsSearchDocumentType docType = searchManager.getDocumentTypeConfig(doctypeName);
526
527        // output of resource types
528        Iterator<String> itResourcetypes = docType.getResourceTypes().iterator();
529        html.append("<ul>\n");
530        while (itResourcetypes.hasNext()) {
531            html.append("  <li>\n").append("  ").append(itResourcetypes.next()).append("\n");
532            html.append("  </li>");
533        }
534
535        html.append("</ul>\n");
536        item.set(detailId, html.toString());
537    }
538}