001/*
002 * (C) Copyright 2006-2010 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Thierry Delprat
016 */
017package org.nuxeo.apidoc.browse;
018
019import java.io.Serializable;
020import java.io.UnsupportedEncodingException;
021import java.net.URLDecoder;
022import java.net.URLEncoder;
023import java.util.ArrayList;
024import java.util.List;
025import java.util.Map;
026
027import javax.ws.rs.FormParam;
028import javax.ws.rs.GET;
029import javax.ws.rs.POST;
030import javax.ws.rs.Path;
031import javax.ws.rs.PathParam;
032import javax.ws.rs.Produces;
033import javax.ws.rs.QueryParam;
034
035import org.nuxeo.apidoc.api.AssociatedDocuments;
036import org.nuxeo.apidoc.api.DocumentationItem;
037import org.nuxeo.apidoc.api.NuxeoArtifact;
038import org.nuxeo.apidoc.doc.SimpleDocumentationItem;
039import org.nuxeo.apidoc.documentation.DocumentationService;
040import org.nuxeo.apidoc.snapshot.SnapshotManager;
041import org.nuxeo.ecm.core.api.Blobs;
042import org.nuxeo.ecm.core.api.DocumentModel;
043import org.nuxeo.ecm.core.api.IdRef;
044import org.nuxeo.ecm.webengine.model.Template;
045import org.nuxeo.ecm.webengine.model.exceptions.WebSecurityException;
046import org.nuxeo.ecm.webengine.model.impl.DefaultObject;
047import org.nuxeo.runtime.api.Framework;
048
049public abstract class NuxeoArtifactWebObject extends DefaultObject {
050
051    protected String nxArtifactId;
052
053    @Override
054    protected void initialize(Object... args) {
055        nxArtifactId = (String) args[0];
056    }
057
058    protected String getNxArtifactId() {
059        return nxArtifactId;
060    }
061
062    protected SnapshotManager getSnapshotManager() {
063        return Framework.getLocalService(SnapshotManager.class);
064    }
065
066    @Override
067    public Template getView(String viewId) {
068        return super.getView(viewId).arg(Distribution.DIST_ID, getDistributionId()).arg("enableDocumentationView",
069                Boolean.TRUE);
070    }
071
072    public abstract NuxeoArtifact getNxArtifact();
073
074    protected abstract Object doGet();
075
076    protected String getDistributionId() {
077        return (String) ctx.getProperty(Distribution.DIST_ID);
078    }
079
080    public AssociatedDocuments getAssociatedDocuments() {
081        NuxeoArtifact nxItem = getNxArtifact();
082        return nxItem.getAssociatedDocuments(ctx.getCoreSession());
083    }
084
085    @POST
086    @Produces("text/html")
087    @Path("updateDocumentation")
088    public Object doUpdateDocumentation(DocumentationItem docItem) {
089        if (!SecurityHelper.canEditDocumentation(getContext())) {
090            throw new WebSecurityException("You are not allowed to do this operation");
091        }
092
093        DocumentationService ds = Framework.getLocalService(DocumentationService.class);
094
095        ds.updateDocumentationItem(ctx.getCoreSession(), docItem);
096        return redirect(getDocUrl());
097    }
098
099    protected String getDocUrl() {
100        String path = getPath() + "/doc";
101        // //TODO encode path segments if needed
102        return path;
103    }
104
105    @Deprecated
106    protected String computeUrl(String suffix) throws UnsupportedEncodingException {
107        String targetUrl = ctx.getUrlPath();
108        targetUrl = URLDecoder.decode(targetUrl, "ISO-8859-1");
109        targetUrl = targetUrl.replace(ctx.getBasePath(), "");
110        targetUrl = targetUrl.replace(suffix, "/doc");
111        targetUrl = URLEncoder.encode(targetUrl, "ISO-8859-1");
112        return targetUrl;
113    }
114
115    @POST
116    @Produces("text/html")
117    @Path("createDocumentation")
118    public Object doCreateDocumentation(DocumentationItem docItem) {
119        if (!SecurityHelper.canEditDocumentation(getContext())) {
120            throw new WebSecurityException("You are not allowed to do this operation");
121        }
122
123        DocumentationService ds = Framework.getLocalService(DocumentationService.class);
124        ds.createDocumentationItem(ctx.getCoreSession(), getNxArtifact(), docItem.getTitle(), docItem.getContent(),
125                docItem.getType(), docItem.getApplicableVersion(), docItem.isApproved(), docItem.getRenderingType());
126        return redirect(getDocUrl());
127    }
128
129    @POST
130    @Produces("text/html")
131    @Path("deleteDocumentation")
132    public Object doDeleteDocumentation(@FormParam("uuid") String uuid) {
133        if (!SecurityHelper.canEditDocumentation(getContext())) {
134            throw new WebSecurityException("You are not allowed to do this operation");
135        }
136        DocumentationService ds = Framework.getLocalService(DocumentationService.class);
137        ds.deleteDocumentationItem(ctx.getCoreSession(), uuid);
138        return redirect(getDocUrl());
139    }
140
141    @GET
142    @Produces("text/html")
143    public Object doViewDefault() {
144        NuxeoArtifact nxItem = getNxArtifact();
145        AssociatedDocuments docs = nxItem.getAssociatedDocuments(ctx.getCoreSession());
146        return getView("default").arg("nxItem", nxItem).arg("docs", docs).arg("selectedTab", "defView");
147    }
148
149    @GET
150    @Produces("text/html")
151    @Path("doc")
152    public Object doViewDoc() {
153        NuxeoArtifact nxItem = getNxArtifact();
154        AssociatedDocuments docs = nxItem.getAssociatedDocuments(ctx.getCoreSession());
155        return getView("../documentation").arg("nxItem", nxItem).arg("docs", docs).arg("selectedTab", "docView");
156    }
157
158    @GET
159    @Produces("text/html")
160    @Path("aggregated")
161    public Object doViewAggregated() {
162        NuxeoArtifact nxItem = getNxArtifact();
163        AssociatedDocuments docs = nxItem.getAssociatedDocuments(ctx.getCoreSession());
164        return getView("aggregated").arg("nxItem", nxItem).arg("docs", docs).arg("selectedTab", "aggView");
165    }
166
167    @GET
168    @Produces("text/html")
169    @Path("createForm")
170    public Object doAddDoc(@QueryParam("inline") Boolean inline, @QueryParam("type") String type) {
171        NuxeoArtifact nxItem = getNxArtifact();
172        List<String> versions = getSnapshotManager().getAvailableVersions(ctx.getCoreSession(), nxItem);
173        DocumentationItem docItem = new SimpleDocumentationItem(nxItem);
174        String targetView = "../docForm";
175        if (inline != null && inline.equals(Boolean.TRUE)) {
176            targetView = "../../docItemForm";
177        }
178        return getView(targetView).arg("nxItem", nxItem).arg("mode", "create").arg("docItem", docItem).arg("versions",
179                versions).arg("selectedTab", "docView").arg("preselectedType", type);
180    }
181
182    @GET
183    @Produces("text/html")
184    @Path("editForm/{uuid}")
185    public Object doEditDoc(@PathParam("uuid") String uuid) {
186        NuxeoArtifact nxItem = getNxArtifact();
187        List<String> versions = getSnapshotManager().getAvailableVersions(ctx.getCoreSession(), nxItem);
188        DocumentModel existingDoc = ctx.getCoreSession().getDocument(new IdRef(uuid));
189        DocumentationItem docItem = existingDoc.getAdapter(DocumentationItem.class);
190        return getView("../docForm").arg("nxItem", nxItem).arg("mode", "edit").arg("docItem", docItem).arg("versions",
191                versions).arg("selectedTab", "docView");
192    }
193
194    @GET
195    @Produces("text/plain")
196    @Path("quickEdit/{editId}")
197    public Object quickEdit(@PathParam("editId") String editId) {
198
199        if (editId == null || editId.startsWith("placeholder_")) {
200            return "";
201        }
202
203        DocumentModel doc = getContext().getCoreSession().getDocument(new IdRef(editId));
204        DocumentationItem item = doc.getAdapter(DocumentationItem.class);
205
206        return item.getContent();
207    }
208
209    @POST
210    @Produces("text/plain")
211    @Path("quickEdit/{editId}")
212    public Object quickEditSave(@PathParam("editId") String editId) {
213
214        String title = getContext().getForm().getString("title");
215        String content = getContext().getForm().getString("content");
216        String type = getContext().getForm().getString("type");
217        if (type == null || type.trim().length() == 0) {
218            type = "description";
219        }
220
221        String renderingType = "wiki";
222        if (content.contains("<ul>") || content.contains("<p>") || content.contains("<br/>")) {
223            renderingType = "html";
224        }
225
226        List<String> applicableVersions = new ArrayList<String>();
227        applicableVersions.add(getSnapshotManager().getSnapshot(getDistributionId(), getContext().getCoreSession()).getVersion()); // XXX
228                                                                                                                                   // !!!
229        DocumentationService ds = Framework.getLocalService(DocumentationService.class);
230        if (editId == null || editId.startsWith("placeholder_")) {
231            ds.createDocumentationItem(getContext().getCoreSession(), getNxArtifact(), title, content, type,
232                    applicableVersions, false, renderingType);
233        } else {
234            DocumentModel doc = getContext().getCoreSession().getDocument(new IdRef(editId));
235            doc.setPropertyValue("dc:title", title);
236            doc.setPropertyValue("file:content", (Serializable) Blobs.createBlob(content));
237            DocumentationItem item = doc.getAdapter(DocumentationItem.class);
238
239            ds.updateDocumentationItem(getContext().getCoreSession(), item);
240        }
241
242        return "OK";
243    }
244
245    public Map<String, String> getCategories() {
246        DocumentationService ds = Framework.getLocalService(DocumentationService.class);
247        return ds.getCategories();
248    }
249
250}