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