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.ade.containerpage.client;
029
030import org.opencms.ade.containerpage.client.ui.CmsContainerPageContainer;
031import org.opencms.ade.containerpage.client.ui.CmsContainerPageElementPanel;
032import org.opencms.ade.containerpage.client.ui.CmsOptionDialog;
033import org.opencms.ade.containerpage.client.ui.I_CmsDropContainer;
034import org.opencms.ade.containerpage.shared.CmsCntPageData;
035import org.opencms.ade.containerpage.shared.CmsDialogOptionsAndInfo;
036import org.opencms.ade.contenteditor.client.CmsContentEditor;
037import org.opencms.ade.contenteditor.client.CmsEditorContext;
038import org.opencms.ade.contenteditor.client.I_CmsEditorCloseHandler;
039import org.opencms.ade.contenteditor.shared.CmsContentDefinition;
040import org.opencms.ade.contenteditor.shared.CmsEditHandlerData;
041import org.opencms.ade.publish.shared.CmsPublishOptions;
042import org.opencms.gwt.client.CmsCoreProvider;
043import org.opencms.gwt.client.CmsEditableData;
044import org.opencms.gwt.client.I_CmsEditableData;
045import org.opencms.gwt.client.ui.contenteditor.CmsContentEditorDialog;
046import org.opencms.gwt.client.ui.contenteditor.CmsContentEditorDialog.DialogOptions;
047import org.opencms.gwt.client.ui.contenteditor.I_CmsContentEditorHandler;
048import org.opencms.gwt.client.util.CmsDebugLog;
049import org.opencms.gwt.client.util.CmsDomUtil;
050import org.opencms.gwt.client.util.I_CmsSimpleCallback;
051import org.opencms.gwt.shared.CmsGwtConstants;
052import org.opencms.util.CmsStringUtil;
053import org.opencms.util.CmsUUID;
054
055import java.util.HashMap;
056import java.util.Map;
057
058import com.google.gwt.dom.client.Element;
059import com.google.gwt.http.client.URL;
060import com.google.gwt.json.client.JSONBoolean;
061import com.google.gwt.json.client.JSONNumber;
062import com.google.gwt.json.client.JSONObject;
063import com.google.gwt.json.client.JSONString;
064import com.google.gwt.user.client.Command;
065import com.google.gwt.user.client.History;
066import com.google.gwt.user.client.Window;
067
068import jsinterop.base.Js;
069
070/**
071 * The container-page editor implementation of the XML content editor handler.<p>
072 *
073 * @since 8.0.0
074 */
075public class CmsContentEditorHandler implements I_CmsContentEditorHandler {
076
077    /** Content editor hash key whre a return to the opened editor is not possible. */
078    private static final String EDITOR_FOR_NO_RETURN_HASH_KEY = "cE";
079
080    /** Content editor hash key used for history management. */
081    private static final String EDITOR_HASH_KEY = "cE:";
082
083    /** The container-page handler. */
084    CmsContainerpageHandler m_handler;
085
086    /** The content element to be replaced by the edited content. */
087    CmsContainerPageElementPanel m_replaceElement;
088
089    /** The currently edited element's id. */
090    private String m_currentElementId;
091
092    /** The depending element's id. */
093    private String m_dependingElementId;
094
095    /** Flag indicating the content editor is currently opened. */
096    private boolean m_editorOpened;
097
098    /**
099     * Constructor.<p>
100     *
101     * @param handler the container-page handler
102     */
103    public CmsContentEditorHandler(CmsContainerpageHandler handler) {
104
105        m_handler = handler;
106    }
107
108    /**
109     * Closes the content editor.<p>
110     */
111    public void closeContentEditor() {
112
113        CmsContentEditor.getInstance().closeEditor();
114        m_editorOpened = false;
115    }
116
117    /**
118     * @see org.opencms.gwt.client.ui.contenteditor.I_CmsContentEditorHandler#onClose(java.lang.String, org.opencms.util.CmsUUID, boolean, boolean, boolean)
119     */
120    public void onClose(
121        String sitePath,
122        CmsUUID structureId,
123        boolean isNew,
124        boolean hasChangedSettings,
125        boolean usedPublishDialog) {
126
127        if (m_currentElementId == null) {
128            m_currentElementId = structureId.toString();
129        }
130        Runnable checkPublishLocks = () -> {
131            if (usedPublishDialog) {
132                m_handler.m_controller.startPublishLockCheck();
133            }
134        };
135
136        if (m_replaceElement != null) {
137            if ((m_handler.m_controller.getData().getDetailId() != null)
138                && m_replaceElement.getId().startsWith(m_handler.m_controller.getData().getDetailId().toString())) {
139                Window.Location.assign(
140                    CmsStringUtil.joinPaths(
141                        CmsCoreProvider.get().getVfsPrefix(),
142                        CmsContainerpageController.getCurrentUri(),
143                        CmsContainerpageController.getServerId(m_currentElementId)));
144            }
145
146            m_handler.replaceElement(m_replaceElement, m_currentElementId, checkPublishLocks);
147            m_replaceElement = null;
148            if (m_dependingElementId != null) {
149                m_handler.reloadElements(new String[] {m_dependingElementId}, checkPublishLocks);
150                m_dependingElementId = null;
151            }
152        } else if (m_dependingElementId != null) {
153            m_handler.reloadElements(new String[] {m_currentElementId, m_dependingElementId}, checkPublishLocks);
154            m_dependingElementId = null;
155        } else {
156            m_handler.reloadElements(new String[] {m_currentElementId}, checkPublishLocks);
157        }
158        if (m_currentElementId != null) {
159            m_handler.addToRecent(m_currentElementId);
160        }
161        m_handler.enableToolbarButtons();
162        m_handler.activateSelection();
163        m_handler.m_controller.setContentEditing(false);
164        m_handler.m_controller.reInitInlineEditing();
165        m_currentElementId = null;
166        if (hasChangedSettings) {
167            m_handler.m_controller.setPageChanged(new Runnable[] {});
168        }
169        m_editorOpened = false;
170    }
171
172    /**
173     * Opens the XML content editor.<p>
174     *
175     * @param element the container element widget
176     * @param inline <code>true</code> to open the in-line editor for the given element if available
177     * @param wasNew <code>true</code> in case this is a newly created element not previously edited
178     */
179    public void openDialog(final CmsContainerPageElementPanel element, final boolean inline, boolean wasNew) {
180
181        if (!inline && element.hasEditHandler()) {
182            m_handler.m_controller.getEditOptions(
183                element.getId(),
184                false,
185                new I_CmsSimpleCallback<CmsDialogOptionsAndInfo>() {
186
187                    public void execute(CmsDialogOptionsAndInfo editOptions) {
188
189                        final I_CmsSimpleCallback<CmsUUID> editCallBack = new I_CmsSimpleCallback<CmsUUID>() {
190
191                            public void execute(CmsUUID arg) {
192
193                                String contentId = element.getId();
194                                if (!element.getId().startsWith(arg.toString())) {
195                                    // the content structure ID has changed, the current element needs to be replaced after editing
196                                    m_replaceElement = element;
197                                    contentId = arg.toString();
198                                }
199                                internalOpenDialog(element, contentId, inline, wasNew);
200                            }
201                        };
202                        if (editOptions == null) {
203                            internalOpenDialog(element, element.getId(), inline, wasNew);
204                        } else if (editOptions.getOptions().getOptions().size() == 1) {
205                            m_handler.m_controller.prepareForEdit(
206                                element.getId(),
207                                editOptions.getOptions().getOptions().get(0).getValue(),
208                                editCallBack);
209                        } else {
210                            CmsOptionDialog dialog = new CmsOptionDialog(
211                                Messages.get().key(Messages.GUI_EDIT_HANDLER_SELECT_EDIT_OPTION_0),
212                                editOptions.getOptions(),
213                                editOptions.getInfo(),
214                                new I_CmsSimpleCallback<String>() {
215
216                                    public void execute(String arg) {
217
218                                        m_handler.m_controller.prepareForEdit(element.getId(), arg, editCallBack);
219                                    }
220                                });
221                            dialog.addDialogClose(new Command() {
222
223                                public void execute() {
224
225                                    cancelEdit();
226                                }
227                            });
228                            dialog.center();
229                        }
230                    }
231                });
232        } else {
233            internalOpenDialog(element, element.getId(), inline, wasNew);
234        }
235    }
236
237    /**
238     * Opens the XML content editor, checking for if an edit handler is configured first.<p>
239     *
240     * @param editableData the data of the element to edit
241     * @param isNew <code>true</code> if a new resource should be created
242     * @param dependingElementId the id of a depending element
243     * @param mode the element creation mode
244     * @param handlerDataForNew the edit handler data, if we are using an edit handler to create a new element; null otherwise
245     */
246    public void openDialog(
247        final I_CmsEditableData editableData,
248        final boolean isNew,
249        final String dependingElementId,
250        final String mode,
251        final CmsEditHandlerData handlerDataForNew) {
252
253        if (!m_editorOpened) {
254            m_editorOpened = true;
255            m_handler.disableToolbarButtons();
256            m_handler.deactivateCurrentButton();
257
258            if (!isNew && (editableData.getStructureId() != null) && editableData.hasEditHandler()) {
259                final String elementId = CmsContentEditor.getClientIdForEditable(editableData);
260                m_handler.m_controller.getEditOptions(
261                    elementId,
262                    true,
263                    new I_CmsSimpleCallback<CmsDialogOptionsAndInfo>() {
264
265                        public void execute(CmsDialogOptionsAndInfo editOptions) {
266
267                            final I_CmsSimpleCallback<CmsUUID> editCallBack = new I_CmsSimpleCallback<CmsUUID>() {
268
269                                public void execute(CmsUUID arg) {
270
271                                    I_CmsEditableData data = editableData;
272                                    if (!data.getStructureId().equals(arg)) {
273                                        // the content structure ID has changed, change the editableData
274                                        data = new CmsEditableData(data);
275                                        ((CmsEditableData)data).setStructureId(arg);
276                                    }
277                                    internalOpenDialog(data, isNew, dependingElementId, mode, null);
278                                }
279                            };
280                            if (editOptions == null) {
281                                internalOpenDialog(editableData, isNew, dependingElementId, mode, null);
282                            } else if (editOptions.getOptions().getOptions().size() == 1) {
283                                m_handler.m_controller.prepareForEdit(
284                                    elementId,
285                                    editOptions.getOptions().getOptions().get(0).getValue(),
286                                    editCallBack);
287                            } else {
288                                CmsOptionDialog dialog = new CmsOptionDialog(
289                                    Messages.get().key(Messages.GUI_EDIT_HANDLER_SELECT_EDIT_OPTION_0),
290                                    editOptions.getOptions(),
291                                    editOptions.getInfo(),
292                                    new I_CmsSimpleCallback<String>() {
293
294                                        public void execute(String arg) {
295
296                                            m_handler.m_controller.prepareForEdit(elementId, arg, editCallBack);
297                                        }
298                                    });
299                                dialog.addDialogClose(new Command() {
300
301                                    public void execute() {
302
303                                        cancelEdit();
304                                    }
305                                });
306                                dialog.center();
307                            }
308                        }
309                    });
310            } else {
311                internalOpenDialog(editableData, isNew, dependingElementId, mode, handlerDataForNew);
312            }
313
314        } else {
315            CmsDebugLog.getInstance().printLine("Editor is already being opened.");
316        }
317    }
318
319    /**
320     * Opens the content editor according to the history hash.<p>
321     *
322     * @param historyHash the history hash
323     */
324    public void openEditorForHistory(String historyHash) {
325
326        if (historyHash.startsWith(EDITOR_HASH_KEY)) {
327            if (!m_editorOpened) {
328                m_editorOpened = true;
329                CmsDebugLog.getInstance().printLine("EditorHandler - Opening editor from history");
330                m_handler.m_controller.setContentEditing(true);
331                String id = historyHash.substring(EDITOR_HASH_KEY.length(), historyHash.indexOf(";"));
332                if (id.contains(",")) {
333                    String[] ids = id.split(",");
334                    m_currentElementId = URL.decodePathSegment(ids[0]);
335                    m_dependingElementId = URL.decodePathSegment(ids[1]);
336                } else {
337                    m_currentElementId = URL.decodePathSegment(id);
338                }
339                I_CmsEditorCloseHandler onClose = new I_CmsEditorCloseHandler() {
340
341                    public void onClose(boolean hasChangedSettings, boolean usedPublishDialog) {
342
343                        addClosedEditorHistoryItem();
344                        CmsContentEditorHandler.this.onClose(
345                            null,
346                            new CmsUUID(getCurrentElementId()),
347                            false,
348                            hasChangedSettings,
349                            usedPublishDialog);
350                    }
351                };
352                String editorLocale = CmsCoreProvider.get().getLocale();
353
354                CmsContentEditor.getInstance().openFormEditor(
355                    getEditorContext(),
356                    editorLocale,
357                    m_currentElementId,
358                    null,
359                    null,
360                    null,
361                    null,
362                    null,
363                    m_handler.m_controller.getData().getMainLocale(),
364                    null,
365                    onClose);
366            }
367        } else {
368            closeContentEditor();
369        }
370    }
371
372    /**
373     * Returns the currently edited element's id.<p>
374     *
375     * @return the currently edited element's id
376     */
377    protected String getCurrentElementId() {
378
379        return m_currentElementId;
380    }
381
382    /**
383     * Adds a history item for the closed editor.<p>
384     */
385    void addClosedEditorHistoryItem() {
386
387        History.newItem("", false);
388    }
389
390    /**
391     * Cancels opening the editor.<p>
392     */
393    void cancelEdit() {
394
395        m_handler.enableToolbarButtons();
396        m_handler.activateSelection();
397        m_handler.m_controller.setContentEditing(false);
398        m_handler.m_controller.reInitInlineEditing();
399        m_replaceElement = null;
400        m_dependingElementId = null;
401        m_currentElementId = null;
402        m_editorOpened = false;
403    }
404
405    /**
406     * Gets the editor context to use for the Acacia editor.<p>
407     *
408     * @return the editor context
409     */
410    CmsEditorContext getEditorContext() {
411
412        CmsEditorContext result = new CmsEditorContext();
413        result.getPublishParameters().put(
414            CmsPublishOptions.PARAM_CONTAINERPAGE,
415            "" + CmsCoreProvider.get().getStructureId());
416        result.getPublishParameters().put(
417            CmsPublishOptions.PARAM_DETAIL,
418            "" + CmsContainerpageController.get().getData().getDetailId());
419        result.getPublishParameters().put(CmsPublishOptions.PARAM_START_WITH_CURRENT_PAGE, "");
420        elemental2.dom.HTMLMetaElement meta = Js.cast(
421            elemental2.dom.DomGlobal.document.querySelector(
422                "meta[name=" + CmsGwtConstants.META_EDITOR_STYLESHEET + "]"));
423        if (meta != null) {
424            result.setEditorStylesheet(meta.content);
425        }
426        return result;
427    }
428
429    /**
430     * Opens the edit dialog.<p>
431     *
432     * @param element the element to edit
433     * @param editContentId the edit content id
434     * @param inline <code>true</code> to edit the content inline
435     * @param wasNew <code>true</code> in case this is a newly created element not previously edited
436     */
437    void internalOpenDialog(
438        final CmsContainerPageElementPanel element,
439        String editContentId,
440        final boolean inline,
441        boolean wasNew) {
442
443        if (!m_editorOpened) {
444            m_editorOpened = true;
445            m_handler.disableToolbarButtons();
446            m_handler.deactivateCurrentButton();
447            m_currentElementId = editContentId;
448            final String serverId = CmsContainerpageController.getServerId(m_currentElementId);
449            final Runnable classicEdit = new Runnable() {
450
451                public void run() {
452
453                    CmsEditableData editableData = new CmsEditableData();
454                    editableData.setElementLanguage(CmsCoreProvider.get().getLocale());
455                    editableData.setStructureId(new CmsUUID(serverId));
456                    editableData.setSitePath(element.getSitePath());
457                    editableData.setMainLanguage(m_handler.m_controller.getData().getMainLocale());
458                    CmsContentEditorDialog.get().openEditDialog(
459                        editableData,
460                        false,
461                        null,
462                        new DialogOptions(),
463                        CmsContentEditorHandler.this);
464                }
465            };
466
467            if (m_handler.m_controller.getData().isUseClassicEditor() || element.isNewEditorDisabled()) {
468                classicEdit.run();
469            } else {
470                String editorLocale = CmsCoreProvider.get().getLocale();
471                final String mainLocale;
472                if (m_handler.m_controller.getData().getMainLocale() == null) {
473                    Element htmlEl = CmsDomUtil.querySelector(
474                        "[" + CmsGwtConstants.ATTR_DATA_ID + "*='" + serverId + "']",
475                        element.getElement());
476                    if (htmlEl != null) {
477                        String entityId = htmlEl.getAttribute(CmsGwtConstants.ATTR_DATA_ID);
478                        mainLocale = CmsContentDefinition.getLocaleFromId(entityId);
479                    } else {
480                        mainLocale = null;
481                    }
482                } else {
483                    mainLocale = m_handler.m_controller.getData().getMainLocale();
484                }
485                I_CmsEditorCloseHandler onClose = new I_CmsEditorCloseHandler() {
486
487                    public void onClose(boolean hasChangedSettings, boolean usedPublishDialog) {
488
489                        addClosedEditorHistoryItem();
490                        CmsContentEditorHandler.this.onClose(
491                            element.getSitePath(),
492                            new CmsUUID(serverId),
493                            false,
494                            hasChangedSettings,
495                            usedPublishDialog);
496
497                    }
498                };
499                if (inline && CmsContentEditor.hasEditable(element.getElement())) {
500                    addEditingHistoryItem(true);
501                    CmsEditorContext context = getEditorContext();
502                    context.setHtmlContextInfo(getContextInfo(element));
503                    // remove expired style before initializing the editor
504                    element.setReleasedAndNotExpired(true);
505                    // in case of new elements, ignore load time
506                    long loadTime = wasNew ? Long.MAX_VALUE : m_handler.m_controller.getLoadTime();
507                    CmsContentEditor.getInstance().openInlineEditor(
508                        context,
509                        new CmsUUID(serverId),
510                        editorLocale,
511                        element,
512                        mainLocale,
513                        loadTime,
514                        onClose);
515                } else {
516                    addEditingHistoryItem(false);
517                    Map<String, String> settingPresets = new HashMap<String, String>();
518                    CmsEditorContext context = getEditorContext();
519                    I_CmsDropContainer dropContainer = element.getParentTarget();
520                    if (dropContainer instanceof CmsContainerPageContainer) {
521                        CmsContainerPageContainer container = (CmsContainerPageContainer)dropContainer;
522                        settingPresets.putAll(container.getSettingPresets());
523                    }
524                    context.setSettingPresets(settingPresets);
525
526                    boolean allowSettings = m_handler.m_controller.getData().allowSettingsInEditor()
527                        && !m_handler.m_controller.isEditingDisabled()
528                        && !serverId.equals(String.valueOf(m_handler.m_controller.getData().getDetailId()));
529                    I_CmsSimpleCallback<Boolean> openEditor = new I_CmsSimpleCallback<Boolean>() {
530
531                        public void execute(Boolean lockedPage) {
532
533                            CmsContentEditor.getInstance().openFormEditor(
534                                context,
535                                editorLocale,
536                                serverId,
537                                lockedPage.booleanValue() ? getCurrentElementId() : null,
538                                null,
539                                null,
540                                null,
541                                null,
542                                mainLocale,
543                                null,
544                                onClose);
545                        }
546                    };
547                    if (allowSettings) {
548                        if (m_handler.m_controller.getData().getDetailContainerPage() != null) {
549                            CmsCoreProvider.get().lock(
550                                m_handler.m_controller.getData().getDetailContainerPage(),
551                                m_handler.m_controller.getLoadTime(),
552                                openEditor);
553                        } else {
554                            CmsCoreProvider.get().lock(
555                                CmsCoreProvider.get().getStructureId(),
556                                m_handler.m_controller.getLoadTime(),
557                                openEditor);
558                        }
559                    } else {
560                        openEditor.execute(Boolean.FALSE);
561                    }
562
563                }
564            }
565        } else {
566            CmsDebugLog.getInstance().printLine("Editor is already being opened.");
567        }
568    }
569
570    /**
571     * Opens the XML content editor internally.<p>
572     *
573     * @param editableData the data of the element to edit
574     * @param isNew <code>true</code> if a new resource should be created
575     * @param dependingElementId the id of a depending element
576     * @param mode the element creation mode
577     * @param editHandlerData the edit handler data, if we are using an edit handler to create a new element; null otherwise
578     */
579    void internalOpenDialog(
580        final I_CmsEditableData editableData,
581        final boolean isNew,
582        String dependingElementId,
583        String mode,
584        CmsEditHandlerData editHandlerData) {
585
586        if ((editableData.getStructureId() != null) && !isNew) {
587            m_currentElementId = editableData.getStructureId().toString();
588        } else {
589            m_currentElementId = null;
590        }
591        m_dependingElementId = dependingElementId;
592        if (m_handler.m_controller.getData().isUseClassicEditor()) {
593            CmsContentEditorDialog.get().openEditDialog(editableData, isNew, mode, new DialogOptions(), this);
594        } else {
595            String newLink = null;
596            if (isNew) {
597                newLink = editableData.getNewLink();
598                // the new link is URL encoded twice, decode it
599                newLink = URL.decodeQueryString(newLink);
600                newLink = URL.decodeQueryString(newLink);
601            }
602            addEditingHistoryItem(isNew);
603            CmsContentEditor.getInstance().openFormEditor(
604                getEditorContext(),
605                CmsCoreProvider.get().getLocale(),
606                editableData.getStructureId().toString(),
607                null,
608                newLink,
609                null,
610                editableData.getPostCreateHandler(),
611                mode,
612                m_handler.m_controller.getData().getMainLocale(),
613                editHandlerData,
614                new I_CmsEditorCloseHandler() {
615
616                    public void onClose(boolean hasChangedSettings, boolean usedPublishDialog) {
617
618                        addClosedEditorHistoryItem();
619                        CmsContentEditorHandler.this.onClose(
620                            editableData.getSitePath(),
621                            editableData.getStructureId(),
622                            isNew,
623                            hasChangedSettings,
624                            usedPublishDialog);
625                    }
626                });
627        }
628
629    }
630
631    /**
632     * Adds a history item for the opened editor.<p>
633     * Use the prohibitReturn flag to deny a return to the opened editor through the browser history.
634     * Use this feature for inline editing or when opening the editor for new resources.<p>
635     *
636     * @param prohibitReturn if <code>true</code> returning to the opened editor through the browser history is denied
637     */
638    private void addEditingHistoryItem(boolean prohibitReturn) {
639
640        if (prohibitReturn) {
641            History.newItem(EDITOR_FOR_NO_RETURN_HASH_KEY, false);
642        } else {
643            History.newItem(
644                EDITOR_HASH_KEY
645                    + CmsContainerpageController.getServerId(getCurrentElementId())
646                    + (m_dependingElementId != null ? "," + m_dependingElementId + ";" : ";"),
647                false);
648        }
649    }
650
651    /**
652     * Returns the HTML context info for the given element.<p>
653     *
654     * @param element the edited element
655     *
656     * @return the JSON string
657     */
658    private String getContextInfo(CmsContainerPageElementPanel element) {
659
660        CmsContainerPageContainer container;
661        if (m_handler.m_controller.isGroupcontainerEditing()) {
662            container = (CmsContainerPageContainer)((CmsContainerPageElementPanel)element.getParentTarget()).getParentTarget();
663        } else {
664            container = (CmsContainerPageContainer)element.getParentTarget();
665        }
666        JSONObject result = new JSONObject();
667        putString(result, CmsCntPageData.JSONKEY_ELEMENT_ID, element.getId());
668        CmsUUID detailId = m_handler.m_controller.getData().getDetailId();
669        if (detailId != null) {
670            putString(result, CmsCntPageData.JSONKEY_DETAIL_ELEMENT_ID, "" + detailId);
671        }
672        putString(result, CmsCntPageData.JSONKEY_NAME, "" + container.getContainerId());
673        putString(result, CmsCntPageData.JSONKEY_TYPE, "" + container.getContainerType());
674        result.put(CmsCntPageData.JSONKEY_WIDTH, new JSONNumber(container.getConfiguredWidth()));
675        result.put(CmsCntPageData.JSONKEY_DETAILVIEW, JSONBoolean.getInstance(container.isDetailView()));
676        result.put(
677            CmsCntPageData.JSONKEY_ISDETAILVIEWCONTAINER,
678            JSONBoolean.getInstance(container.isDetailViewContainer()));
679        result.put(CmsCntPageData.JSONKEY_DETAILONLY, JSONBoolean.getInstance(container.isDetailOnly()));
680        result.put(CmsCntPageData.JSONKEY_MAXELEMENTS, new JSONNumber(1));
681        JSONObject presets = new JSONObject();
682        Map<String, String> presetsMap = container.getSettingPresets();
683        for (Map.Entry<String, String> entry : presetsMap.entrySet()) {
684            presets.put(entry.getKey(), new JSONString(entry.getValue()));
685        }
686        result.put(CmsCntPageData.JSONKEY_PRESETS, presets);
687        return result.toString();
688    }
689
690    /**
691     * Adds a String value to the JSON object.<p>
692     *
693     * @param obj the object to manipulate
694     * @param key the key
695     * @param val the value
696     */
697    private void putString(JSONObject obj, String key, String val) {
698
699        obj.put(key, new JSONString(val));
700    }
701
702}