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.ugc.client.export;
029
030import org.opencms.ugc.client.CmsJsUtils;
031import org.opencms.ugc.client.CmsUgcWrapper;
032import org.opencms.ugc.shared.CmsUgcConstants;
033import org.opencms.ugc.shared.CmsUgcContent;
034import org.opencms.ugc.shared.CmsUgcException;
035import org.opencms.util.CmsUUID;
036
037import java.util.HashSet;
038import java.util.Map;
039import java.util.Set;
040
041import org.timepedia.exporter.client.Export;
042import org.timepedia.exporter.client.ExportPackage;
043import org.timepedia.exporter.client.Exportable;
044import org.timepedia.exporter.client.NoExport;
045
046import com.google.common.base.Function;
047import com.google.common.collect.Maps;
048import com.google.gwt.core.client.JavaScriptObject;
049import com.google.gwt.dom.client.Element;
050import com.google.gwt.user.client.rpc.AsyncCallback;
051
052/**
053 * Client side object representing a form editing session.<p>
054 */
055@Export
056@ExportPackage("opencmsugc")
057public class CmsClientUgcSession implements Exportable {
058
059    /** The CmsXmlContentFormApi which was used to create this session object. */
060    private CmsXmlContentUgcApi m_apiRoot;
061
062    /** The form content returned from the server. */
063    private CmsUgcContent m_content;
064
065    /** The form wrapper widget. */
066    private CmsUgcWrapper m_formWrapper;
067
068    /**
069     * Creates a new instance.<p>
070     *
071     * @param apiRoot the CmsXmlContentFormApi instance which was used to create this session object
072     * @param content the form data returned from the server
073     */
074    public CmsClientUgcSession(CmsXmlContentUgcApi apiRoot, CmsUgcContent content) {
075
076        m_content = content;
077        m_apiRoot = apiRoot;
078    }
079
080    /**
081     * Destroys the session.<p>
082     */
083    public void destroy() {
084
085        CmsXmlContentUgcApi.SERVICE.destroySession(m_content.getSessionId(), new AsyncCallback<Void>() {
086
087            public void onFailure(Throwable caught) {
088
089                throw new RuntimeException(caught);
090
091            }
092
093            public void onSuccess(Void result) {
094
095                // do nothing
096
097            }
098        });
099
100    }
101
102    /**
103     * Gets the content form API instance.<p>
104     *
105     * @return the content form API instance
106     */
107    @NoExport
108    public CmsXmlContentUgcApi getContentFormApi() {
109
110        return m_apiRoot;
111
112    }
113
114    /**
115     * Fetches the link for a given path from the server.<p>
116     *
117     * @param path the path for which we want the link
118     *
119     * @param callback the callback to call with the result
120     */
121    public void getLink(String path, final I_CmsStringCallback callback) {
122
123        m_apiRoot.getRpcHelper().executeRpc(CmsXmlContentUgcApi.SERVICE.getLink(path, new AsyncCallback<String>() {
124
125            @SuppressWarnings("synthetic-access")
126            public void onFailure(Throwable caught) {
127
128                m_apiRoot.handleError(caught, null);
129            }
130
131            public void onSuccess(String result) {
132
133                callback.call(result);
134            }
135        }));
136    }
137
138    /**
139     * Gets the session id.<p>
140     *
141     * @return the session id
142     */
143    public String getSessionId() {
144
145        return "" + m_content.getSessionId();
146    }
147
148    /**
149     * Gets the site path of the edited content.<p>
150     *
151     * @return the site path of the edited content
152     */
153    public String getSitePath() {
154
155        return m_content.getSitePath();
156    }
157
158    /**
159     * Gets the old content values as a Javascript object.<p>
160     *
161     * @return a Javascript object whose properties are the xpaths of the existing content values
162     */
163    public JavaScriptObject getValues() {
164
165        return CmsJsUtils.convertMapToJsObject(m_content.getContentValues());
166    }
167
168    /**
169     * Initializes the form belonging to this session.<p>
170     *
171     * @param formElement the form element
172     */
173    @NoExport
174    public void initFormElement(Element formElement) {
175
176        m_formWrapper = new CmsUgcWrapper(formElement, getSessionId());
177        m_formWrapper.setFormSession(this);
178    }
179
180    /**
181     * Gets the session id as a UUID.<p>
182     *
183     * @return the session id
184     */
185    @NoExport
186    public CmsUUID internalGetSessionId() {
187
188        return m_content.getSessionId();
189    }
190
191    /**
192     * Asks the server to save the values set via setNewValue in the XML content.<p>
193     *
194     * @param newValues the new values to set
195     * @param onSuccess the callback to be called in case of success
196     * @param onFailure the callback to be called in case of failure
197     */
198    public void saveContent(
199        JavaScriptObject newValues,
200        final I_CmsStringCallback onSuccess,
201        final I_CmsErrorCallback onFailure) {
202
203        m_apiRoot.getRpcHelper().executeRpc(
204            CmsXmlContentUgcApi.SERVICE.saveContent(
205                m_content.getSessionId(),
206                CmsJsUtils.convertJsObjectToMap(newValues),
207                new AsyncCallback<Map<String, String>>() {
208
209                    @SuppressWarnings("synthetic-access")
210                    public void onFailure(Throwable caught) {
211
212                        CmsUgcException formException = (CmsUgcException)caught;
213                        m_apiRoot.handleError(formException, onFailure);
214                    }
215
216                    public void onSuccess(Map<String, String> result) {
217
218                        if ((result == null) || result.isEmpty()) {
219                            onSuccess.call("");
220                        } else {
221                            JavaScriptObject validationErrorsJso = CmsJsUtils.convertMapToJsObject(result);
222                            onFailure.call(CmsUgcConstants.ErrorCode.errValidation.toString(), "", validationErrorsJso);
223                        }
224                    }
225                }));
226
227    }
228
229    /**
230     * Uploads multiple files.<p>
231     *
232     * @param fieldNames the array of form field names containing files to upload
233     * @param fileCallback the callback for the results
234     * @param errorCallback the error handling callback
235     */
236    public void uploadFiles(
237        String[] fieldNames,
238        final I_CmsJavaScriptObjectCallback fileCallback,
239        I_CmsErrorCallback errorCallback) {
240
241        Set<String> fieldSet = new HashSet<String>();
242        for (String field : fieldNames) {
243            fieldSet.add(field);
244        }
245
246        m_formWrapper.uploadFields(fieldSet, new Function<Map<String, String>, Void>() {
247
248            public Void apply(Map<String, String> input) {
249
250                fileCallback.call(CmsJsUtils.convertMapToJsObject(input));
251                return null;
252            }
253        }, errorCallback);
254    }
255
256    /**
257     * Validates the new content values.<p>
258     *
259     * @param newValues a Javascript object with the value xpaths as keys and the corresponding content values as values.<p>
260     *
261     * @param onSuccess the callback to call with the validation results
262     */
263    public void validate(JavaScriptObject newValues, final I_CmsJavaScriptObjectCallback onSuccess) {
264
265        AsyncCallback<Map<String, String>> rpcCallback = new AsyncCallback<Map<String, String>>() {
266
267            @SuppressWarnings("synthetic-access")
268            public void onFailure(Throwable caught) {
269
270                m_apiRoot.handleError(caught, null);
271            }
272
273            public void onSuccess(Map<String, String> result) {
274
275                if (result == null) {
276                    result = Maps.newHashMap();
277                }
278                onSuccess.call(CmsJsUtils.convertMapToJsObject(result));
279            }
280        };
281        m_apiRoot.getRpcHelper().executeRpc(
282            CmsXmlContentUgcApi.SERVICE.validateContent(
283                m_content.getSessionId(),
284                CmsJsUtils.convertJsObjectToMap(newValues),
285                rpcCallback));
286
287    }
288}