KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opencms > workplace > tools > searchindex > CmsDocumentTypeRemoveList


1 /*
2  * File : $Source: /usr/local/cvs/opencms/src-modules/org/opencms/workplace/tools/searchindex/CmsDocumentTypeRemoveList.java,v $
3  * Date : $Date: 2006/03/27 14:52:21 $
4  * Version: $Revision: 1.2 $
5  *
6  * This library is part of OpenCms -
7  * the Open Source Content Mananagement System
8  *
9  * Copyright (c) 2005 Alkacon Software GmbH (http://www.alkacon.com)
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * For further information about Alkacon Software GmbH, please see the
22  * company website: http://www.alkacon.com
23  *
24  * For further information about OpenCms, please see the
25  * project website: http://www.opencms.org
26  *
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30  */

31
32 package org.opencms.workplace.tools.searchindex;
33
34 import org.opencms.configuration.CmsSearchConfiguration;
35 import org.opencms.i18n.CmsMessageContainer;
36 import org.opencms.jsp.CmsJspActionElement;
37 import org.opencms.main.CmsIllegalStateException;
38 import org.opencms.main.CmsLog;
39 import org.opencms.main.OpenCms;
40 import org.opencms.search.CmsSearchDocumentType;
41 import org.opencms.search.CmsSearchIndexSource;
42 import org.opencms.search.CmsSearchManager;
43 import org.opencms.workplace.CmsWorkplaceSettings;
44 import org.opencms.workplace.list.CmsListColumnAlignEnum;
45 import org.opencms.workplace.list.CmsListColumnDefinition;
46 import org.opencms.workplace.list.CmsListDefaultAction;
47 import org.opencms.workplace.list.CmsListDirectAction;
48 import org.opencms.workplace.list.CmsListItem;
49 import org.opencms.workplace.list.CmsListItemDetails;
50 import org.opencms.workplace.list.CmsListItemDetailsFormatter;
51 import org.opencms.workplace.list.CmsListMetadata;
52 import org.opencms.workplace.list.CmsListMultiAction;
53 import org.opencms.workplace.list.CmsListOrderEnum;
54
55 import java.util.ArrayList JavaDoc;
56 import java.util.Iterator JavaDoc;
57 import java.util.List JavaDoc;
58
59 import javax.servlet.http.HttpServletRequest JavaDoc;
60 import javax.servlet.http.HttpServletResponse JavaDoc;
61 import javax.servlet.jsp.PageContext JavaDoc;
62
63 import org.apache.commons.logging.Log;
64
65 /**
66  * A list that displays the document types of the system that are assigned to
67  * a request parameter given
68  * <code>{@link org.opencms.search.CmsSearchIndexSource}</code> ("indexsource") and
69  * offers single- and multi-actions that remove those document types to the current
70  * indexsource.<p>
71  *
72  * This list is no stand-alone page but has to be embedded in another dialog
73  * (see <code> {@link org.opencms.workplace.tools.searchindex.A_CmsEmbeddedListDialog}</code>. <p>
74  *
75  * @author Achim Westermann
76  *
77  * @version $Revision: 1.2 $
78  *
79  * @since 6.0.0
80  */

81 public class CmsDocumentTypeRemoveList extends A_CmsEmbeddedListDialog {
82
83     /** list action dummy id constant. */
84     public static final String JavaDoc LIST_ACTION_NONE = "an";
85
86     /** list action id constant. */
87     public static final String JavaDoc LIST_ACTION_REMOVE_DOCTYPE = "ard";
88
89     /** list action id constant. */
90     public static final String JavaDoc LIST_ACTION_REMOVE_DOCTYPE2 = LIST_ACTION_REMOVE_DOCTYPE + "2";
91
92     /** list column id constant. */
93     public static final String JavaDoc LIST_COLUMN_DOCCLASS = "cdc";
94
95     /** list column id constant. */
96     public static final String JavaDoc LIST_COLUMN_ICON = "ci";
97
98     /** list column id constant. */
99     public static final String JavaDoc LIST_COLUMN_NAME = "cn";
100
101     /** list column id constant. */
102     public static final String JavaDoc LIST_COLUMN_REMOVE_DOCTYPE = "crd";
103
104     /** list item detail id constant. */
105     public static final String JavaDoc LIST_DETAIL_MIMETYPES = "dmt";
106
107     /** list item detail id constant. */
108     public static final String JavaDoc LIST_DETAIL_RESOURCETYPES = "drt";
109
110     /** list id constant. */
111     public static final String JavaDoc LIST_ID = "lssisdtr";
112
113     /** list action id constant. */
114     public static final String JavaDoc LIST_MACTION_REMOVE_DOCTYPE = "mard";
115
116     /** The log object for this class. */
117     private static final Log LOG = CmsLog.getLog(CmsDocumentTypeRemoveList.class);
118
119     /** Stores the value of the request parameter for the search index source name. */
120     private String JavaDoc m_paramIndexsource;
121
122     /**
123      * Public constructor.<p>
124      *
125      * @param jsp an initialized JSP action element
126      */

127     public CmsDocumentTypeRemoveList(CmsJspActionElement jsp) {
128
129         this(jsp, LIST_ID, Messages.get().container(Messages.GUI_LIST_DOCUMENTTYPES_NAME_0));
130     }
131
132     /**
133      * Public constructor.<p>
134      *
135      * @param jsp an initialized JSP action element
136      * @param listId the id of the list
137      * @param listName the list name
138      */

139     public CmsDocumentTypeRemoveList(CmsJspActionElement jsp, String JavaDoc listId, CmsMessageContainer listName) {
140
141         this(jsp, listId, listName, LIST_COLUMN_NAME, CmsListOrderEnum.ORDER_ASCENDING, null);
142     }
143
144     /**
145      * Public constructor.<p>
146      *
147      * @param jsp an initialized JSP action element
148      * @param listId the id of the displayed list
149      * @param listName the name of the list
150      * @param sortedColId the a priory sorted column
151      * @param sortOrder the order of the sorted column
152      * @param searchableColId the column to search into
153      */

154     public CmsDocumentTypeRemoveList(
155         CmsJspActionElement jsp,
156         String JavaDoc listId,
157         CmsMessageContainer listName,
158         String JavaDoc sortedColId,
159         CmsListOrderEnum sortOrder,
160         String JavaDoc searchableColId) {
161
162         super(jsp, listId, listName, sortedColId, sortOrder, searchableColId);
163
164     }
165
166     /**
167      * Public constructor.<p>
168      *
169      * Public constructor with JSP variables.<p>
170      *
171      * @param context the JSP page context
172      * @param req the JSP request
173      * @param res the JSP response
174      */

175     public CmsDocumentTypeRemoveList(PageContext JavaDoc context, HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res) {
176
177         this(new CmsJspActionElement(context, req, res));
178     }
179
180     /**
181      * @see org.opencms.workplace.list.A_CmsListDialog#executeListMultiActions()
182      */

183     public void executeListMultiActions() {
184
185         CmsSearchManager searchManager = OpenCms.getSearchManager();
186         if (getParamListAction().equals(LIST_MACTION_REMOVE_DOCTYPE)) {
187             // execute the delete multiaction
188
Iterator JavaDoc itItems = getSelectedItems().iterator();
189             CmsListItem listItem;
190             String JavaDoc doctype;
191             CmsSearchIndexSource idxsrc = searchManager.getIndexSource(getParamIndexsource());
192             while (itItems.hasNext()) {
193                 listItem = (CmsListItem)itItems.next();
194                 doctype = (String JavaDoc)listItem.get(LIST_COLUMN_NAME);
195                 idxsrc.removeDocumentType(doctype);
196                 getList().removeItem(listItem.getId(), getLocale());
197             }
198             writeConfiguration(false);
199             refreshList();
200         }
201         listSave();
202     }
203
204     /**
205      * @see org.opencms.workplace.list.A_CmsListDialog#executeListSingleActions()
206      */

207     public void executeListSingleActions() {
208
209         CmsSearchManager searchManager = OpenCms.getSearchManager();
210         String JavaDoc action = getParamListAction();
211         if (action.equals(LIST_ACTION_REMOVE_DOCTYPE) || action.equals(LIST_ACTION_REMOVE_DOCTYPE2)) {
212             CmsSearchIndexSource idxsrc = searchManager.getIndexSource(getParamIndexsource());
213             CmsListItem item = getSelectedItem();
214             String JavaDoc doctypeName = (String JavaDoc)item.get(LIST_COLUMN_NAME);
215             idxsrc.removeDocumentType(doctypeName);
216             getList().removeItem(item.getId(), getLocale());
217             refreshList();
218             writeConfiguration(false);
219         }
220     }
221
222     /**
223      * Returns the request parameter "indexsource".<p>
224      *
225      * @return the request parameter "indexsource"
226      */

227     public String JavaDoc getParamIndexsource() {
228
229         return m_paramIndexsource;
230     }
231
232     /**
233      * Sets the request parameter "indexsource". <p>
234      *
235      * Method intended for workplace-properietary automatic filling of
236      * request parameter values to dialogs, not for manual invocation. <p>
237      *
238      * @param indexsource the request parameter "indexsource" to set
239      */

240     public void setParamIndexsource(String JavaDoc indexsource) {
241
242         m_paramIndexsource = indexsource;
243     }
244
245     /**
246      * @see org.opencms.workplace.list.A_CmsListDialog#fillDetails(java.lang.String)
247      */

248     protected void fillDetails(String JavaDoc detailId) {
249
250         // get content
251
List JavaDoc items = getList().getAllContent();
252         Iterator JavaDoc itItems = items.iterator();
253         CmsListItem item;
254         if (detailId.equals(LIST_DETAIL_MIMETYPES)) {
255             while (itItems.hasNext()) {
256                 item = (CmsListItem)itItems.next();
257                 fillDetailMimetypes(item, detailId);
258
259             }
260         }
261         if (detailId.equals(LIST_DETAIL_RESOURCETYPES)) {
262             while (itItems.hasNext()) {
263                 item = (CmsListItem)itItems.next();
264                 fillDetailResourceTypes(item, detailId);
265
266             }
267
268         }
269
270     }
271
272     /**
273      * @see org.opencms.workplace.list.A_CmsListDialog#getListItems()
274      */

275     protected List JavaDoc getListItems() {
276
277         List JavaDoc result = new ArrayList JavaDoc();
278         // get content
279
List JavaDoc doctypes = documentTypes();
280         Iterator JavaDoc itDoctypes = doctypes.iterator();
281         CmsSearchDocumentType doctype;
282         while (itDoctypes.hasNext()) {
283             doctype = (CmsSearchDocumentType)itDoctypes.next();
284             CmsListItem item = getList().newItem(doctype.getName());
285             item.set(LIST_COLUMN_NAME, doctype.getName());
286             item.set(LIST_COLUMN_DOCCLASS, doctype.getClassName());
287             result.add(item);
288         }
289         return result;
290     }
291
292     /**
293      * @see org.opencms.workplace.CmsWorkplace#initMessages()
294      */

295     protected void initMessages() {
296
297         // add specific dialog resource bundle
298
addMessages(Messages.get().getBundleName());
299         // add default resource bundles
300
super.initMessages();
301     }
302
303     /**
304      * @see org.opencms.workplace.list.A_CmsListDialog#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest)
305      */

306     protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest JavaDoc request) {
307
308         super.initWorkplaceRequestValues(settings, request);
309     }
310
311     /**
312      * @see org.opencms.workplace.list.A_CmsListDialog#setColumns(org.opencms.workplace.list.CmsListMetadata)
313      */

314     protected void setColumns(CmsListMetadata metadata) {
315
316         // create dummy column for corporate design reasons
317
CmsListColumnDefinition dummyCol = new CmsListColumnDefinition(LIST_COLUMN_ICON);
318         dummyCol.setName(Messages.get().container(Messages.GUI_LIST_DOCUMENTTYPE_NAME_0));
319         dummyCol.setHelpText(Messages.get().container(Messages.GUI_LIST_DOCUMENTTYPE_NAME_HELP_0));
320         dummyCol.setWidth("20");
321         dummyCol.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT);
322         dummyCol.setSorteable(false);
323         // add dummy icon
324
CmsListDirectAction dummyAction = new CmsListDirectAction(LIST_ACTION_NONE);
325         dummyAction.setName(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_COL_ICON_NAME_0));
326         dummyAction.setHelpText(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_COL_ICON_NAME_HELP_0));
327         dummyAction.setIconPath(CmsDocumentTypeList.ICON_DOCTYPE);
328         // disable!
329
dummyAction.setEnabled(false);
330         dummyCol.addDirectAction(dummyAction);
331         // add it to the list definition
332
metadata.addColumn(dummyCol);
333
334         // add column for add single-action
335
CmsListColumnDefinition remCol = new CmsListColumnDefinition(LIST_COLUMN_REMOVE_DOCTYPE);
336         remCol.setName(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_COL_REMOVE_DOCTYPE_NAME_0));
337         remCol.setHelpText(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_COL_REMOVE_DOCTYPE_NAME_HELP_0));
338         remCol.setWidth("20");
339         remCol.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT);
340         remCol.setSorteable(false);
341         // add add action
342
CmsListDirectAction remAction = new CmsListDirectAction(LIST_ACTION_REMOVE_DOCTYPE);
343         remAction.setName(Messages.get().container(Messages.GUI_LIST_SEARCHINDEX_ACTION_REMOVE_DOCTYPE_NAME_0));
344         remAction.setHelpText(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_COL_REMOVE_DOCTYPE_NAME_HELP_0));
345         remAction.setIconPath(ICON_MINUS);
346         remCol.addDirectAction(remAction);
347         metadata.addColumn(remCol);
348
349         // add column for name
350
CmsListColumnDefinition nameCol = new CmsListColumnDefinition(LIST_COLUMN_NAME);
351         nameCol.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT);
352         nameCol.setName(Messages.get().container(Messages.GUI_LIST_SEARCHINDEX_COL_NAME_0));
353         nameCol.setWidth("50%");
354         metadata.addColumn(nameCol);
355         // add a duplicate action
356
CmsListDefaultAction remAction2 = new CmsListDefaultAction(LIST_ACTION_REMOVE_DOCTYPE2);
357         remAction2.setName(Messages.get().container(Messages.GUI_LIST_SEARCHINDEX_ACTION_REMOVE_DOCTYPE_NAME_0));
358         remAction2.setHelpText(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_COL_REMOVE_DOCTYPE_NAME_HELP_0));
359         nameCol.addDefaultAction(remAction2);
360         metadata.addColumn(nameCol);
361
362         // add column for document implementation class
363
CmsListColumnDefinition docclassCol = new CmsListColumnDefinition(LIST_COLUMN_DOCCLASS);
364         docclassCol.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT);
365         docclassCol.setName(Messages.get().container(Messages.GUI_LIST_DOCTYPE_COL_DOCCLASS_0));
366         docclassCol.setWidth("45%");
367         metadata.addColumn(docclassCol);
368
369     }
370
371     /**
372      * @see org.opencms.workplace.list.A_CmsListDialog#setIndependentActions(org.opencms.workplace.list.CmsListMetadata)
373      */

374     protected void setIndependentActions(CmsListMetadata metadata) {
375
376         // add document types of index source detail help
377
CmsListItemDetails mimetypeDetails = new CmsListItemDetails(LIST_DETAIL_MIMETYPES);
378         mimetypeDetails.setAtColumn(LIST_COLUMN_NAME);
379         mimetypeDetails.setVisible(false);
380         mimetypeDetails.setShowActionName(Messages.get().container(Messages.GUI_LIST_DOCTYPE_DETAIL_MIMETYPES_SHOW_0));
381         mimetypeDetails.setShowActionHelpText(Messages.get().container(
382             Messages.GUI_LIST_DOCTYPE_DETAIL_MIMETYPES_SHOW_HELP_0));
383         mimetypeDetails.setHideActionName(Messages.get().container(Messages.GUI_LIST_DOCTYPE_DETAIL_MIMETYPES_HIDE_0));
384         mimetypeDetails.setHideActionHelpText(Messages.get().container(
385             Messages.GUI_LIST_DOCTYPE_DETAIL_MIMETYPES_HIDE_HELP_0));
386         mimetypeDetails.setName(Messages.get().container(Messages.GUI_LIST_DOCTYPE_DETAIL_MIMETYPES_NAME_0));
387         mimetypeDetails.setFormatter(new CmsListItemDetailsFormatter(Messages.get().container(
388             Messages.GUI_LIST_DOCTYPE_DETAIL_MIMETYPES_NAME_0)));
389         metadata.addItemDetails(mimetypeDetails);
390
391         // add resources of index source detail help
392
CmsListItemDetails resourceDetails = new CmsListItemDetails(LIST_DETAIL_RESOURCETYPES);
393         resourceDetails.setAtColumn(LIST_COLUMN_NAME);
394         resourceDetails.setVisible(false);
395         resourceDetails.setShowActionName(Messages.get().container(
396             Messages.GUI_LIST_DOCTYPE_DETAIL_RESOURCETYPES_SHOW_0));
397         resourceDetails.setShowActionHelpText(Messages.get().container(
398             Messages.GUI_LIST_DOCTYPE_DETAIL_RESOURCETYPES_SHOW_HELP_0));
399         resourceDetails.setHideActionName(Messages.get().container(
400             Messages.GUI_LIST_DOCTYPE_DETAIL_RESOURCETYPES_HIDE_0));
401         resourceDetails.setHideActionHelpText(Messages.get().container(
402             Messages.GUI_LIST_DOCTYPE_DETAIL_RESOURCETYPES_HIDE_HELP_0));
403         resourceDetails.setName(Messages.get().container(Messages.GUI_LIST_DOCTYPE_DETAIL_RESOURCETYPES_NAME_0));
404         resourceDetails.setFormatter(new CmsListItemDetailsFormatter(Messages.get().container(
405             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     protected void setMultiActions(CmsListMetadata metadata) {
414
415         // add add multi action
416
CmsListMultiAction addMultiAction = new CmsListMultiAction(LIST_MACTION_REMOVE_DOCTYPE);
417         addMultiAction.setName(Messages.get().container(Messages.GUI_LIST_SEARCHINDEX_MACTION_REMOVE_DOCTYPE_NAME_0));
418         addMultiAction.setHelpText(Messages.get().container(
419             Messages.GUI_LIST_SEARCHINDEX_MACTION_REMOVE_DOCTYPE_NAME_HELP_0));
420         addMultiAction.setIconPath(ICON_MULTI_MINUS);
421         metadata.addMultiAction(addMultiAction);
422     }
423
424     /**
425      * @see org.opencms.workplace.list.A_CmsListDialog#validateParamaters()
426      */

427     protected void validateParamaters() throws Exception JavaDoc {
428
429         // test the needed parameters
430
if (getParamIndexsource() == null) {
431             throw new CmsIllegalStateException(Messages.get().container(
432                 Messages.ERR_SEARCHINDEX_EDIT_MISSING_PARAM_1,
433                 A_CmsEditIndexSourceDialog.PARAM_INDEXSOURCE));
434         }
435     }
436
437     /**
438      * Writes the updated search configuration back to the XML
439      * configuration file and refreshes the complete list.<p>
440      *
441      * @param refresh if true, the list items are refreshed
442      */

443     protected void writeConfiguration(boolean refresh) {
444
445         // update the XML configuration
446
OpenCms.writeConfiguration(CmsSearchConfiguration.class);
447         if (refresh) {
448             refreshList();
449         }
450     }
451
452     /**
453      * Returns the systems configured document types that are assigned
454      * to the current indexsource (those that may be removed).<p>
455      *
456      * @return the systems configured document types that are assigned
457      * to the current indexsource (those that may be removed)
458      */

459     private List JavaDoc documentTypes() {
460
461         CmsSearchManager manager = OpenCms.getSearchManager();
462         CmsSearchIndexSource indexsource = manager.getIndexSource(getParamIndexsource());
463         List JavaDoc result;
464         if (indexsource != null) {
465             List JavaDoc doctypeNames = indexsource.getDocumentTypes();
466
467             // transform these mere names to real document types...
468
result = new ArrayList JavaDoc(doctypeNames.size());
469             Iterator JavaDoc it = doctypeNames.iterator();
470             String JavaDoc doctypename = "";
471             CmsSearchDocumentType doctype;
472             while (it.hasNext()) {
473                 doctypename = (String JavaDoc)it.next();
474                 if (doctypename != null) {
475                     doctype = manager.getDocumentTypeConfig(doctypename);
476                     if (doctype != null) {
477                         result.add(doctype);
478                     }
479                 }
480             }
481         } else {
482             result = new ArrayList JavaDoc(0);
483             if (LOG.isErrorEnabled()) {
484                 LOG.error(Messages.get().getBundle().key(Messages.ERR_SEARCHINDEX_EDIT_MISSING_PARAM_1, "indexsource"));
485             }
486
487         }
488         return result;
489     }
490
491     /**
492      * Fills details about configured mime types of the document type into the given item. <p>
493      *
494      * @param item the list item to fill
495      * @param detailId the id for the detail to fill
496      *
497      */

498     private void fillDetailMimetypes(CmsListItem item, String JavaDoc detailId) {
499
500         CmsSearchManager searchManager = OpenCms.getSearchManager();
501         StringBuffer JavaDoc html = new StringBuffer JavaDoc();
502
503         String JavaDoc doctypeName = (String JavaDoc)item.get(LIST_COLUMN_NAME);
504         CmsSearchDocumentType docType = searchManager.getDocumentTypeConfig(doctypeName);
505
506         // output of mime types
507
Iterator JavaDoc itMimetypes = docType.getMimeTypes().iterator();
508         html.append("<ul>\n");
509         while (itMimetypes.hasNext()) {
510             html.append(" <li>\n").append(" ").append(itMimetypes.next()).append("\n");
511             html.append(" </li>");
512         }
513
514         html.append("</ul>\n");
515         item.set(detailId, html.toString());
516     }
517
518     /**
519      * Fills details about resource types of the document type into the given item. <p>
520      *
521      * @param item the list item to fill
522      * @param detailId the id for the detail to fill
523      *
524      */

525     private void fillDetailResourceTypes(CmsListItem item, String JavaDoc detailId) {
526
527         CmsSearchManager searchManager = OpenCms.getSearchManager();
528         StringBuffer JavaDoc html = new StringBuffer JavaDoc();
529
530         String JavaDoc doctypeName = (String JavaDoc)item.get(LIST_COLUMN_NAME);
531         CmsSearchDocumentType docType = searchManager.getDocumentTypeConfig(doctypeName);
532
533         // output of resource types
534
Iterator JavaDoc itResourcetypes = docType.getResourceTypes().iterator();
535         html.append("<ul>\n");
536         while (itResourcetypes.hasNext()) {
537             html.append(" <li>\n").append(" ").append(itResourcetypes.next()).append("\n");
538             html.append(" </li>");
539         }
540
541         html.append("</ul>\n");
542         item.set(detailId, html.toString());
543     }
544 }
545
Popular Tags