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.gwt.client.util;
029
030import org.opencms.gwt.client.CmsCoreProvider;
031import org.opencms.gwt.client.I_CmsHasInit;
032import org.opencms.gwt.client.ui.contextmenu.I_CmsActionHandler;
033import org.opencms.gwt.client.ui.contextmenu.I_CmsStringSelectHandler;
034import org.opencms.gwt.shared.CmsGwtConstants;
035import org.opencms.gwt.shared.I_CmsEmbeddedDialogInfo;
036import org.opencms.util.CmsStringUtil;
037import org.opencms.util.CmsUUID;
038
039import java.util.ArrayList;
040import java.util.Collections;
041import java.util.HashMap;
042import java.util.List;
043import java.util.Map;
044import java.util.function.Consumer;
045import java.util.stream.Collectors;
046
047import com.google.gwt.core.client.JavaScriptObject;
048import com.google.gwt.core.client.JsArrayString;
049import com.google.gwt.user.client.Command;
050import com.google.gwt.user.client.Timer;
051import com.google.gwt.user.client.Window;
052import com.google.web.bindery.autobean.shared.AutoBean;
053import com.google.web.bindery.autobean.shared.AutoBeanCodex;
054
055/**
056 * Handler for embedded VAADIN dialogs.<p>
057 */
058public class CmsEmbeddedDialogHandler implements I_CmsHasInit, I_CmsEmbeddedDialogHandlerJsCallbacks {
059
060    /** The context menu handler. */
061    private I_CmsActionHandler m_handler;
062
063    /** The on close command. */
064    private Command m_onCloseCommand;
065
066    /** The principle select handler. */
067    private I_CmsStringSelectHandler m_stringSelectHandler;
068
069    /**
070     * Constructor.<p>
071     */
072    public CmsEmbeddedDialogHandler() {
073
074        // nothing to do
075    }
076
077    /**
078     * Constructor.<p>
079     *
080     * @param handler the context handler
081     */
082    public CmsEmbeddedDialogHandler(I_CmsActionHandler handler) {
083
084        this();
085        m_handler = handler;
086    }
087
088    /**
089     * Encodes a parameter value for use in a query string.
090     *
091     * @param str the string to encode
092     * @return the encoded string
093     */
094    public static String encodeParam(String str) {
095
096        return com.google.gwt.http.client.URL.encodeQueryString(str);
097
098    }
099
100    /**
101     * Exports native JS function cmsOpenEmbeddedDialog.
102     */
103    public static native void exportNativeFunctions() /*-{
104        $wnd.cmsOpenEmbeddedDialog = function(dialogId, callback, structureIds,
105                params) {
106            @org.opencms.gwt.client.util.CmsEmbeddedDialogHandler::openEmbeddedDialog(Ljava/lang/String;Lcom/google/gwt/core/client/JavaScriptObject;Lcom/google/gwt/core/client/JsArrayString;Lcom/google/gwt/core/client/JavaScriptObject;)(dialogId, callback, structureIds, params);
107        };
108    }-*/;
109
110    /**
111     * Called on load, exports native functions.
112     */
113    public static void initClass() {
114
115        exportNativeFunctions();
116    }
117
118    /**
119     * Opens the given dialog in an iframe.
120     *
121     * @param dialogId the action class
122     * @param structureIds the structure ids for the action
123     * @param finishCallback the callback to call after the dialog closes
124     */
125    public static void openDialog(String dialogId, List<CmsUUID> structureIds, Consumer<CmsUUID> finishCallback) {
126
127        CmsEmbeddedDialogHandler handler = new CmsEmbeddedDialogHandler(new I_CmsActionHandler() {
128
129            public void leavePage(String targetUri) {
130
131                // TODO Auto-generated method stub
132
133            }
134
135            public void onSiteOrProjectChange(String sitePath, String serverLink) {
136
137                // TODO Auto-generated method stub
138
139            }
140
141            public void refreshResource(CmsUUID structureId) {
142
143                finishCallback.accept(structureId);
144            }
145        });
146        handler.openDialog(dialogId, CmsGwtConstants.CONTEXT_TYPE_FILE_TABLE, structureIds, new HashMap<>());
147    }
148
149    /**
150     * Opens the given dialog in an iframe.
151     *
152     * @param dialogId the action class
153     * @param structureIds the structure ids for the action
154     * @param params additional parameters to pass
155     * @param finishCallback the callback to call after the dialog closes
156     */
157    public static void openDialog(
158        String dialogId,
159        List<CmsUUID> structureIds,
160        Map<String, String> params,
161        Consumer<CmsUUID> finishCallback) {
162
163        CmsEmbeddedDialogHandler handler = new CmsEmbeddedDialogHandler(new I_CmsActionHandler() {
164
165            public void leavePage(String targetUri) {
166
167                // TODO Auto-generated method stub
168
169            }
170
171            public void onSiteOrProjectChange(String sitePath, String serverLink) {
172
173                // TODO Auto-generated method stub
174
175            }
176
177            public void refreshResource(CmsUUID structureId) {
178
179                finishCallback.accept(structureId);
180            }
181        });
182        handler.openDialog(dialogId, CmsGwtConstants.CONTEXT_TYPE_FILE_TABLE, structureIds, params);
183    }
184
185    /**
186     * Opens an embedded dialog.
187     *
188     * @param dialogId the dialog
189     * @param callback the onClose callback
190     * @param structureIds the structure ids
191     * @param params the parameters
192     */
193    public static void openEmbeddedDialog(
194        String dialogId,
195        JavaScriptObject callback,
196        JsArrayString structureIds,
197        JavaScriptObject params) {
198
199        CmsEmbeddedDialogHandler handler = new CmsEmbeddedDialogHandler();
200        if (callback != null) {
201            Command command = CmsJsUtil.convertCallbackToCommand(callback);
202            handler.setOnCloseCommand(command);
203        }
204        Map<String, String> paramsMap = new HashMap<>();
205        if (params != null) {
206            CmsJsUtil.fillStringMapFromJsObject(params, paramsMap);
207        }
208        List<CmsUUID> uuids = new ArrayList<>();
209        if (structureIds != null) {
210            for (int i = 0; i < structureIds.length(); i++) {
211                String uuidStr = structureIds.get(i);
212                try {
213                    uuids.add(new CmsUUID(uuidStr));
214                } catch (Exception e) {
215                    CmsDebugLog.consoleLog(e.getClass() + ":" + e.getLocalizedMessage());
216                }
217            }
218        }
219        handler.openDialog(dialogId, null, uuids, paramsMap);
220    }
221
222    /**
223     * @see org.opencms.gwt.client.util.I_CmsEmbeddedDialogHandlerJsCallbacks#finish(java.lang.String)
224     */
225    @Override
226    public void finish(String resources) {
227
228        CmsEmbeddedDialogFrame.get().hide();
229        if (m_handler != null) {
230
231            List<CmsUUID> resourceIds = parseResources(resources);
232            if (!resourceIds.isEmpty()) {
233                m_handler.refreshResource(resourceIds.get(0));
234            }
235        }
236        if (m_onCloseCommand != null) {
237            m_onCloseCommand.execute();
238        }
239    }
240
241    /**
242     * Called when site and or project have been changed.<p>
243     *
244     * @param sitePath the site path to the resource to display
245     * @param serverLink the server link to the resource to display
246     */
247    @Override
248    public void finishForProjectOrSiteChange(String sitePath, String serverLink) {
249
250        CmsEmbeddedDialogFrame.get().hide();
251        if (m_handler != null) {
252            m_handler.onSiteOrProjectChange(sitePath, serverLink);
253        } else {
254            Window.Location.assign(serverLink);
255        }
256    }
257
258    /**
259     * Navigates to the given URI.<p>
260     *
261     * @param targetUri the target URI
262     */
263    @Override
264    public void leavePage(String targetUri) {
265
266        CmsEmbeddedDialogFrame.get().hide();
267        if (m_handler != null) {
268            m_handler.leavePage(targetUri);
269        } else {
270            // the timer is a workaround for weird Safari behavior, just calling Location.assign doesn't work there
271            Timer timer = new Timer() {
272
273                @Override
274                public void run() {
275
276                    Window.Location.assign(targetUri);
277                }
278            };
279            timer.schedule(10);
280        }
281    }
282
283    /**
284     * Opens the dialog with the given id.<p>
285     *
286     * @param dialogId the dialog id
287     * @param contextType the context type, used to check the action visibility
288     * @param resources the resource to handle
289     */
290    public void openDialog(String dialogId, String contextType, List<CmsUUID> resources) {
291
292        openDialog(dialogId, contextType, resources, null);
293    }
294
295    /**
296     * Opens the dialog with the given id.<p>
297     *
298     * @param dialogId the dialog id
299     * @param contextType the context type, used to check the action visibility
300     * @param resources the resource to handle
301     * @param params additional set of parameters
302     */
303
304    public void openDialog(String dialogId, String contextType, List<CmsUUID> resources, Map<String, String> params) {
305
306        AutoBean<I_CmsEmbeddedDialogInfo> info = CmsCoreProvider.AUTO_BEAN_FACTORY.createDialogInfo();
307        info.as().setDialogId(dialogId);
308        info.as().setContextType(contextType);
309        if (resources == null) {
310            resources = new ArrayList<>();
311        }
312        info.as().setStructureIds(resources.stream().map(id -> "" + id).collect(Collectors.toList()));
313        if (params == null) {
314            params = new HashMap<>();
315        }
316        info.as().setParameters(params);
317        String infoJson = AutoBeanCodex.encode(info).getPayload();
318        CmsEmbeddedDialogFrame.get().loadDialog(infoJson, this);
319    }
320
321    /**
322     * Reloads the current page.<p>
323     */
324    @Override
325    public void reload() {
326
327        if (m_handler != null) {
328            String uri = Window.Location.getHref();
329            m_handler.leavePage(uri);
330        } else {
331            Window.Location.reload();
332        }
333    }
334
335    /**
336     * Calls the principle select handler and closes the dialog frame.<p>
337     *
338     * @param principle the principle to select
339     */
340    @Override
341    public void selectString(String principle) {
342
343        CmsEmbeddedDialogFrame.get().hide();
344        if (m_stringSelectHandler != null) {
345            m_stringSelectHandler.selectString(principle);
346        }
347        if (m_onCloseCommand != null) {
348            m_onCloseCommand.execute();
349        }
350    }
351
352    /**
353     * Sets the on close command.<p>
354     *
355     * @param onCloseCommand the on close command
356     */
357    public void setOnCloseCommand(Command onCloseCommand) {
358
359        m_onCloseCommand = onCloseCommand;
360    }
361
362    /**
363     * Sets the principle select handler.<p>
364     *
365     * @param selectHandler the principle select handler
366     */
367    public void setStringSelectHandler(I_CmsStringSelectHandler selectHandler) {
368
369        m_stringSelectHandler = selectHandler;
370    }
371
372    /**
373     * Parses the resources string.<p>
374     *
375     * @param resources the resources
376     *
377     * @return the list of resource ids
378     */
379    protected List<CmsUUID> parseResources(String resources) {
380
381        if (CmsStringUtil.isEmptyOrWhitespaceOnly(resources)) {
382            return Collections.emptyList();
383        } else {
384            List<CmsUUID> result = new ArrayList<CmsUUID>();
385            String[] resArray = resources.trim().split(";");
386            for (int i = 0; i < resArray.length; i++) {
387                result.add(new CmsUUID(resArray[i]));
388            }
389            return result;
390        }
391    }
392
393}