001    /**
002     * $RCSfile: MCRStartClassEditorServlet.java,v $
003     * $Revision: 15225 $ $Date: 2009-05-19 15:33:02 +0200 (Tue, 19 May 2009) $
004     *
005     * This file is part of ** M y C o R e **
006     * Visit our homepage at http://www.mycore.de/ for details.
007     *
008     * This program is free software; you can use it, redistribute it
009     * and / or modify it under the terms of the GNU General Public License
010     * (GPL) as published by the Free Software Foundation; either version 2
011     * of the License or (at your option) any later version.
012     *
013     * This program is distributed in the hope that it will be useful, but
014     * WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016     * GNU General Public License for more details.
017     *
018     * You should have received a copy of the GNU General Public License
019     * along with this program, normally in the file license.txt.
020     * If not, write to the Free Software Foundation Inc.,
021     * 59 Temple Place - Suite 330, Boston, MA  02111-1307 USA
022     *
023     **/
024    
025    package org.mycore.frontend.servlets;
026    
027    import static org.jdom.Namespace.XML_NAMESPACE;
028    
029    import java.io.IOException;
030    import java.util.Properties;
031    
032    import org.apache.commons.fileupload.FileItem;
033    import org.apache.log4j.Logger;
034    import org.jdom.Element;
035    import org.jdom.output.Format;
036    import org.jdom.output.XMLOutputter;
037    
038    import org.mycore.access.MCRAccessManager;
039    import org.mycore.common.MCRConfiguration;
040    import org.mycore.common.MCRSessionMgr;
041    import org.mycore.common.xml.MCRURIResolver;
042    import org.mycore.datamodel.classifications.MCRClassificationBrowserData;
043    import org.mycore.datamodel.classifications.MCRClassificationEditor;
044    import org.mycore.datamodel.classifications2.MCRCategory;
045    import org.mycore.datamodel.classifications2.MCRCategoryID;
046    import org.mycore.datamodel.classifications2.MCRLabel;
047    import org.mycore.datamodel.classifications2.utils.MCRCategoryTransformer;
048    import org.mycore.datamodel.metadata.MCRObjectID;
049    import org.mycore.frontend.editor.MCREditorSubmission;
050    import org.mycore.frontend.editor.MCRRequestParameters;
051    
052    /**
053     * The servlet start the MyCoRe class editor session with some parameters from a
054     * HTML form. The parameters are:<br />
055     * <li> name="todo" values like 'create-classification, modify-classification,
056     * delete-classification, up and down' </li>
057     * <li> name="path" uri to page after editactions </li>
058     * <li> name="clid" classification id </li>
059     * <li> name="categid" category id </li>
060     * 
061     * @author Anja Schaar
062     * @author Jens Kupferschmidt
063     * @version $Revision: 15225 $ $Date: 2009-05-19 15:33:02 +0200 (Tue, 19 May 2009) $
064     */
065    
066    public class MCRStartClassEditorServlet extends MCRServlet {
067    
068        private static final long serialVersionUID = 1L;
069    
070        private static Logger LOGGER = Logger.getLogger(MCRStartClassEditorServlet.class);
071    
072        private String todo = "";
073    
074        private String todo2 = "";
075    
076        private String clid = "";
077    
078        private String categid = "";
079    
080        private String path = "";
081    
082        private static MCRClassificationEditor clE = new MCRClassificationEditor();
083    
084        private static enum ReturnStatus {
085            success, fail
086        }
087    
088        /**
089         * Replace the doGetPost method of MCRServlet. This method will be called
090         * two times when using the classification editor. Firtst time it prepare
091         * date for the editor and second time it execute the operation.
092         */
093        public void think(MCRServletJob job) throws Exception {
094    
095            // read the XML data if given from Editorsession
096            MCREditorSubmission sub = (MCREditorSubmission) (job.getRequest().getAttribute("MCREditorSubmission"));
097    
098            // read the parameter
099            MCRRequestParameters parms;
100            if (sub == null)
101                parms = new MCRRequestParameters(job.getRequest());
102            else {
103                parms = sub.getParameters();
104            }
105    
106            // read the parameter
107            todo = parms.getParameter("todo");
108            todo2 = parms.getParameter("todo2");
109            path = parms.getParameter("path");
110    
111            // get the Classification
112            clid = parms.getParameter("clid");
113    
114            categid = parms.getParameter("categid");
115    
116            if (todo == null)
117                todo = "";
118            if (todo2 == null)
119                todo2 = "";
120    
121            LOGGER.debug("MCRStartClassEditorServlet TODO: " + todo);
122            LOGGER.debug("MCRStartClassEditorServlet TODO2: " + todo2);
123            LOGGER.debug("MCRStartClassEditorServlet CLID: " + clid);
124            LOGGER.debug("MCRStartClassEditorServlet CATEGID: " + categid);
125    
126            String pagedir = MCRConfiguration.instance().getString("MCR.classeditor_page_dir", "");
127            String myfile = "editor_form_" + todo + ".xml";
128    
129            String usererrorpage = pagedir + MCRConfiguration.instance().getString("MCR.classeditor_page_error_user", "editor_error_user.xml");
130            String cancelpage = pagedir + MCRConfiguration.instance().getString("MCR.classeditor_page_cancel", "classeditor_cancel.xml");
131            String icerrorpage = pagedir + MCRConfiguration.instance().getString("MCR.classeditor_page_error_id", "classeditor_error_clid.xml");
132            String iderrorpage = pagedir
133                    + MCRConfiguration.instance().getString("MCR.classeditor_page_error_delete", "editor_error_delete.xml");
134            String imerrorpage = pagedir
135                    + MCRConfiguration.instance().getString("MCR.classeditor_page_error_move", "classeditor_error_move.xml");
136            String imperrorpage = pagedir
137                    + MCRConfiguration.instance().getString("MCR.classeditor_page_error_import", "classeditor_error_import.xml");
138            String isaveerrorpage = pagedir
139                    + MCRConfiguration.instance().getString("MCR.classeditor_page_error_save", "classeditor_error_save.xml");
140            String ipurgeerrorpage = pagedir
141                    + MCRConfiguration.instance().getString("MCR.classeditor_page_error_purge", "classeditor_error_purge.xml");
142    
143            String referrer = job.getRequest().getHeader("Referer");
144            if (referrer == null || referrer.equals("")) {
145                referrer = getBaseURL() + cancelpage;
146            }
147    
148            if (needsCreatePrivilege(todo, todo2)) {
149                if (!(MCRAccessManager.checkPermission("create-classification"))) {
150                    setResponsePage(job, ReturnStatus.fail, getBaseURL() + usererrorpage);
151                    return;
152                }
153            } else if (needsDeleteRight(todo, todo2)) {
154                if (!(MCRAccessManager.checkPermission(clid, "deletedb"))) {
155                    setResponsePage(job, ReturnStatus.fail, getBaseURL() + usererrorpage);
156                    return;
157                }
158            } else {
159                if (!(MCRAccessManager.checkPermission(clid, "writedb"))) {
160                    setResponsePage(job, ReturnStatus.fail, getBaseURL() + usererrorpage);
161                    return;
162                }
163            }
164    
165            // nach Editoraufruf von new/modify auf commit
166            if ("commit-classification".equals(todo)) {
167                org.jdom.Document indoc = sub.getXML();
168                boolean bret = false;
169    
170                // for debug
171                if (LOGGER.isDebugEnabled()) {
172                    XMLOutputter outputter = new XMLOutputter();
173                    LOGGER.debug(outputter.outputString(indoc));
174                }
175    
176                if ("create-category".equals(todo2) || "modify-category".equals(todo2)) {
177                    if ("create-category".equals(todo2)) {
178                        // create
179                        if (!clE.isLocked(clid)) {
180                            MCRCategoryID id = new MCRCategoryID(clid, categid);
181                            bret = clE.createCategoryInClassification(indoc, id);
182                        }
183                    } else {
184                        // modify
185                        if (!clE.isLocked(clid)) {
186                            MCRCategoryID id = new MCRCategoryID(clid, categid);
187                            bret = clE.modifyCategoryInClassification(indoc, id);
188                        }
189                    }
190                    if (bret)
191                        setResponsePage(job, ReturnStatus.success, path + "&categid=" + categid + "&clid=" + clid);
192                } else {
193                    if (path.indexOf("&clid") > 0) {
194                        // Classification abschneiden um wieder auf der
195                        // Classifikationsstartseite zu landen
196                        path = path.substring(0, path.indexOf("&clid"));
197                    }
198                    if ("create-classification".equals(todo2)) {
199                        bret = clE.createNewClassification(indoc);
200                    } else if ("modify-classification".equals(todo2)) {
201                        if (!clE.isLocked(clid)) {
202                            bret = clE.modifyClassificationDescription(indoc, clid);
203                        }
204                    } else if ("import-classification".equals(todo2)) {
205                        String fname = parms.getParameter("/mycoreclass/pathes/path").trim();
206                        fname = clE.setTempFile(fname, (FileItem) sub.getFiles().get(0));
207                        String sUpdate = parms.getParameter("/mycoreclass/update");
208                        boolean update = sUpdate == null ? true : "true".equals(sUpdate);
209                        bret = clE.importClassification(update, fname);
210                        clE.deleteTempFile();
211                        if (!bret) {
212                            setResponsePage(job, ReturnStatus.fail, getBaseURL() + imperrorpage);
213                            return;
214                        }
215                    }
216                    if (bret)
217                        setResponsePage(job, ReturnStatus.success, path);
218                }
219                setResponsePage(job, ReturnStatus.fail, getBaseURL() + icerrorpage);
220                return;
221            }
222    
223            if ("up-category".equals(todo) || "down-category".equals(todo) || "left-category".equals(todo) || "right-category".equals(todo)) {
224                boolean bret = false;
225                if (!clE.isLocked(clid)) {
226                    bret = clE.moveCategoryInClassification(categid, clid, todo.substring(0, todo.indexOf("-")));
227                }
228                if (bret) {
229                    setResponsePage(job, ReturnStatus.success, path + "&categid=" + categid + "&clid=" + clid);
230                }
231                setResponsePage(job, ReturnStatus.fail, getBaseURL() + imerrorpage);
232                return;
233            }
234    
235            // first call, direct without editor
236            else if ("delete-category".equals(todo)) {
237                // l?schen
238                if (!clE.isLocked(clid)) {
239                    int cnt = clE.deleteCategoryInClassification(clid, categid);
240    
241                    if (cnt == 0) { // deleted, no more references
242                        setResponsePage(job, ReturnStatus.success, path + "&clid=" + clid);
243                    }
244                    // not delete cause references exist
245                    setResponsePage(job, ReturnStatus.fail, getBaseURL() + iderrorpage);
246                }
247                return;
248            }
249    
250            // first call, direct without editor
251            else if ("delete-classification".equals(todo)) {
252                if (!clE.isLocked(clid)) {
253                    boolean cnt = clE.deleteClassification(clid);
254                    if (cnt) { // deleted, no more references
255                        path = getBaseURL() + "browse?mode=edit";
256                        setResponsePage(job, ReturnStatus.success, path);
257                    }
258                    // not delete cause references exist
259                    setResponsePage(job, ReturnStatus.fail, getBaseURL() + iderrorpage);
260                }
261                return;
262            }
263    
264            // first call of editor, build the import dialogue
265            else if ("import-classification".equals(todo)) {
266                String base = getBaseURL() + myfile;
267                Properties params = new Properties();
268                params.put("cancelUrl", referrer);
269                params.put("clid", clid);
270                params.put("path", path);
271                params.put("todo2", todo);
272                params.put("todo", "commit-classification");
273                setResponsePage(job, ReturnStatus.success, buildRedirectURL(base, params));
274                return;
275            }
276    
277            else if ("save-all".equals(todo)) {
278                if (clE.saveAll()) {
279                    setResponsePage(job, ReturnStatus.success, path + "&clid=" + clid);
280                }
281                setResponsePage(job, ReturnStatus.fail, getBaseURL() + isaveerrorpage);
282                return;
283            } else if ("purge-all".equals(todo)) {
284                if (clE.purgeAll()) {
285                    setResponsePage(job, ReturnStatus.success, path + "&clid=" + clid);
286                }
287                setResponsePage(job, ReturnStatus.fail, getBaseURL() + ipurgeerrorpage);
288                return;
289            }
290            // first call of editor, build the editor dialogue
291            if ("create-category".equals(todo) || "modify-category".equals(todo) || "create-classification".equals(todo)
292                    || "modify-classification".equals(todo)) {
293    
294                String base = getBaseURL() + myfile;
295                final String sessionObjectID = "classificationEditor";
296                Properties params = new Properties();
297                StringBuffer sb = new StringBuffer();
298                boolean isEdited = MCRClassificationBrowserData.getClassificationPool().isEdited(MCRCategoryID.rootID(clid));
299                MCRCategory classif = null;
300                if (isEdited) {
301                    classif = MCRClassificationBrowserData.getClassificationPool().getClassificationAsPojo(MCRCategoryID.rootID(clid), false);
302                    LOGGER.info("CLASSIF: " + classif.getId());
303                }
304    
305                if ("modify-classification".equals(todo)) {
306                    if (isEdited) {
307                        sb.append("session:").append(sessionObjectID);
308                        MCRSessionMgr.getCurrentSession().put(sessionObjectID,
309                                MCRCategoryTransformer.getMetaDataDocument(classif, true).getRootElement());
310                    } else {
311                        sb.append("classification:metadata:0:children:").append(clid);
312                    }
313                    params.put("sourceUri", sb.toString());
314    
315                }
316                if ("create-classification".equals(todo)) {
317                    MCRObjectID cli = new MCRObjectID();
318                    String idBase = MCRConfiguration.instance().getString("MCR.SWF.Project.ID", "DocPortal") + "_class";
319                    cli.setNextFreeId(idBase);
320    
321                    if (!cli.isValid()) {
322                        LOGGER.error("Create an unique CLID failed. " + cli.toString());
323                    }
324                    Element classRoot = new Element("mycoreclass").setAttribute("ID", cli.getId());
325                    params.put("sourceUri", "session:" + sessionObjectID);
326                    MCRSessionMgr.getCurrentSession().put(sessionObjectID, classRoot);
327                }
328                if ("modify-category".equals(todo)) {
329                    if (isEdited) {
330                        sb.append("session:").append(sessionObjectID);
331                        Element classRoot = new Element("mycoreclass").setAttribute("ID", classif.getId().getRootID());
332                        MCRLabel label = classif.getCurrentLabel();
333                        Element le = new Element("label");
334                        le.setAttribute("lang", label.getLang(), XML_NAMESPACE);
335                        if (label.getText() != null) {
336                            le.setAttribute("text", label.getText());
337                        }
338                        if (label.getDescription() != null) {
339                            le.setAttribute("description", label.getDescription());
340                        }
341                        classRoot.addContent(le);
342    
343                        Element categs = new Element("categories");
344                        MCRCategoryID id = new MCRCategoryID(classif.getId().getRootID(), categid);
345                        MCRCategory cat = clE.findCategory(classif, id);
346                        categs.addContent(MCRCategoryTransformer.getMetaDataElement(cat, true));
347                        classRoot.addContent(categs);
348                        MCRSessionMgr.getCurrentSession().put(sessionObjectID, classRoot);
349                    } else {
350                        sb.append("classification:metadata:0:children:").append(clid).append(':').append(categid);
351                    }
352                    params.put("sourceUri", sb.toString());
353                    params.put("categid", categid);
354                }
355                if ("create-category".equals(todo)) {
356                    if (isEdited) {
357                        sb.append("session:").append(sessionObjectID);
358                        MCRSessionMgr.getCurrentSession().put(sessionObjectID,
359                                MCRCategoryTransformer.getMetaDataDocument(classif, true).getRootElement());
360                    } else {
361                        sb.append("classification:metadata:0:children:").append(clid);
362                    }
363                    params.put("sourceUri", sb.toString());
364                    params.put("categid", categid);
365                }
366                params.put("cancelUrl", referrer);
367                params.put("clid", clid);
368                params.put("path", path);
369                params.put("todo2", todo);
370                params.put("todo", "commit-classification");
371                setResponsePage(job, ReturnStatus.success, buildRedirectURL(base, params));
372                return;
373            }
374            /* Wrong input data, write warning log */
375            LOGGER.warn("MCRStartClassEditorServlet default Case - Nothing to do ? " + todo);
376            setResponsePage(job, ReturnStatus.success, path);
377        }
378    
379        public void setResponsePage(MCRServletJob job, ReturnStatus status, String url) {
380            String key = MCRStartClassEditorServlet.class.toString();
381            String value = job.getResponse().encodeRedirectURL(url);
382            key += "." + status;
383            job.getRequest().setAttribute(key, value);
384        }
385    
386        public String getResponsePage(MCRServletJob job, ReturnStatus status) {
387            String key = MCRStartClassEditorServlet.class.toString() + "." + status;
388            return (String) job.getRequest().getAttribute(key);
389        }
390    
391        public void render(MCRServletJob job, Exception thinkException) throws IOException {
392            String successURL = getResponsePage(job, ReturnStatus.success);
393            String failURL = getResponsePage(job, ReturnStatus.fail);
394    
395            if (thinkException == null && successURL != null) {
396                job.getResponse().sendRedirect(successURL);
397            } else {
398                if (failURL != null)
399                    job.getResponse().sendRedirect(failURL);
400                else
401                    generateErrorPage(job.getRequest(), job.getResponse(), 500, thinkException.getMessage(), thinkException, false);
402            }
403        }
404    
405        private boolean needsCreatePrivilege(String todo, String todo2) {
406            if (todo.equals("commit-classification")) {
407                if (todo2.equals("create-classification") || todo2.equals("import-classification"))
408                    return true;
409            }
410            return false;
411        }
412    
413        private boolean needsDeleteRight(String todo, String todo2) {
414            if (todo.equals("delete-classification")) {
415                return true;
416            }
417            return false;
418        }
419    
420    }