media in comments, part 1: the admin side
[mir.git] / source / mircoders / servlet / ServletModuleContent.java
1 /*
2  * Copyright (C) 2001, 2002  The Mir-coders group
3  *
4  * This file is part of Mir.
5  *
6  * Mir is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Mir is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Mir; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * In addition, as a special exception, The Mir-coders gives permission to link
21  * the code of this program with the com.oreilly.servlet library, any library
22  * licensed under the Apache Software License, The Sun (tm) Java Advanced
23  * Imaging library (JAI), The Sun JIMI library (or with modified versions of
24  * the above that use the same license as the above), and distribute linked
25  * combinations including the two.  You must obey the GNU General Public
26  * License in all respects for all of the code used other than the above
27  * mentioned libraries.  If you modify this file, you may extend this exception
28  * to your version of the file, but you are not obligated to do so.  If you do
29  * not wish to do so, delete this exception statement from your version.
30  */
31
32 package mircoders.servlet;
33
34 import java.util.GregorianCalendar;\r
35 import java.util.HashMap;\r
36 import java.util.Iterator;\r
37 import java.util.List;\r
38 import java.util.Locale;\r
39 import java.util.Map;\r
40 import javax.servlet.http.HttpServletRequest;\r
41 import javax.servlet.http.HttpServletResponse;\r
42 import javax.servlet.http.HttpSession;\r
43 \r
44 import org.apache.lucene.index.IndexReader;\r
45 import freemarker.template.SimpleHash;\r
46 import mir.entity.adapter.EntityAdapterModel;\r
47 import mir.entity.adapter.EntityIteratorAdapter;\r
48 import mir.log.LoggerWrapper;\r
49 import mir.misc.StringUtil;\r
50 import mir.servlet.ServletModule;\r
51 import mir.servlet.ServletModuleExc;\r
52 import mir.servlet.ServletModuleFailure;\r
53 import mir.util.CachingRewindableIterator;\r
54 import mir.util.HTTPRequestParser;\r
55 import mir.util.JDBCStringRoutines;\r
56 import mir.util.SQLQueryBuilder;\r
57 import mir.util.URLBuilder;\r
58 import mircoders.entity.EntityContent;\r
59 import mircoders.entity.EntityUsers;\r
60 import mircoders.global.MirGlobal;\r
61 import mircoders.module.ModuleContent;\r
62 import mircoders.search.IndexUtil;\r
63 import mircoders.storage.DatabaseComment;\r
64 import mircoders.storage.DatabaseContent;\r
65 import mircoders.storage.DatabaseContentToMedia;\r
66 import mircoders.storage.DatabaseContentToTopics;
67
68 /*
69  *  ServletModuleContent -
70  *  deliver html for the article admin form.
71  *
72  * @version $Id: ServletModuleContent.java,v 1.48 2003/04/10 03:31:47 zapata Exp $
73  * @author rk, mir-coders
74  *
75  */
76
77 public class ServletModuleContent extends ServletModule
78 {
79   private String editTemplate = configuration.getString("ServletModule.Content.ObjektTemplate");;
80   private String listTemplate = configuration.getString("ServletModule.Content.ListTemplate");
81
82   private static ServletModuleContent instance = new ServletModuleContent();
83   public static ServletModule getInstance() { return instance; }
84
85   private ServletModuleContent() {
86     super();
87     logger = new LoggerWrapper("ServletModule.Content");
88     try {
89
90       templateListString = configuration.getString("ServletModule.Content.ListTemplate");
91       templateObjektString = configuration.getString("ServletModule.Content.ObjektTemplate");
92       templateConfirmString = configuration.getString("ServletModule.Content.ConfirmTemplate");
93
94       mainModule = new ModuleContent(DatabaseContent.getInstance());
95     }
96     catch (Throwable e) {
97       logger.fatal("ServletModuleContent could not be initialized: " + e.toString());
98     }
99   }
100
101   public void list(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc
102   {
103     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
104
105     String where = requestParser.getParameter("where");
106     String order = requestParser.getParameterWithDefault("order", "webdb_create desc");
107     int offset = requestParser.getIntegerWithDefault("offset", 0);
108     String selectArticleUrl = requestParser.getParameter("selectarticleurl");
109
110     returnArticleList(aRequest, aResponse, where, order, offset, selectArticleUrl);
111   }
112
113   public void search(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc, ServletModuleFailure {
114     try {
115       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
116       SQLQueryBuilder queryBuilder = new SQLQueryBuilder();
117       String searchField = requestParser.getParameterWithDefault("searchfield", "");
118       String searchValue = requestParser.getParameterWithDefault("searchvalue", "").trim();
119       String searchOrder = requestParser.getParameterWithDefault("searchorder", "");
120       String searchispublished = requestParser.getParameterWithDefault("searchispublished", "");
121       String searchArticleType = requestParser.getParameterWithDefault("searcharticletype", "");
122       String selectArticleUrl = requestParser.getParameter("selectarticleurl");
123
124       if (searchValue.length()>0) {
125         if (searchField.equals("id"))
126           queryBuilder.appendAndCondition(
127             "id='"+JDBCStringRoutines.escapeStringLiteral(searchValue)+"'");
128         else if (searchField.equals("contents"))
129           queryBuilder.appendAndCondition(
130             "(lower(content_data) like " + "'%" + JDBCStringRoutines.escapeStringLiteral(searchValue.toLowerCase()) + "%')"+
131             " or (lower(description) like " + "'%" + JDBCStringRoutines.escapeStringLiteral(searchValue.toLowerCase()) + "%')");
132         else
133           queryBuilder.appendAndCondition(
134             "lower("+ searchField + ") like " +
135             "'%" + JDBCStringRoutines.escapeStringLiteral(searchValue.toLowerCase()) + "%'");
136       }
137
138       if (searchispublished.length()>0) {
139         if (searchispublished.equals("0"))
140           queryBuilder.appendAndCondition("is_published='f'");
141         else
142           queryBuilder.appendAndCondition("is_published='t'");
143       }
144
145       if (searchArticleType.length()>0) {
146         queryBuilder.appendAndCondition("to_article_type="+Integer.parseInt(searchArticleType));
147       }
148
149       if (searchOrder.length()>0) {
150         if (searchOrder.equals("datedesc"))
151           queryBuilder.appendAscendingOrder("webdb_create");
152         else if (searchOrder.equals("dateasc"))
153           queryBuilder.appendDescendingOrder("webdb_create");
154         else if (searchOrder.equals("title"))
155           queryBuilder.appendDescendingOrder("title");
156         else if (searchOrder.equals("creator"))
157           queryBuilder.appendDescendingOrder("creator");
158       }
159
160       returnArticleList(aRequest, aResponse, queryBuilder.getWhereClause(), queryBuilder.getOrderByClause(), 0, selectArticleUrl);
161     }
162     catch (Throwable e) {
163       throw new ServletModuleFailure(e);
164     }
165   }
166
167   public void add(HttpServletRequest req, HttpServletResponse res) throws ServletModuleExc {
168     _showObject(null, req, res);
169   }
170
171
172   public void insert(HttpServletRequest req, HttpServletResponse res) throws ServletModuleExc
173   {
174 //theLog.printDebugInfo(":: content :: trying to insert");
175     try {
176       EntityUsers   user = _getUser(req);
177       Map withValues = getIntersectingValues(req, DatabaseContent.getInstance());
178
179       String now = StringUtil.date2webdbDate(new GregorianCalendar());
180       withValues.put("date", now);
181       withValues.put("publish_path", StringUtil.webdbDate2path(now));
182       withValues.put("to_publisher", user.getId());
183       withValues.put("is_produced", "0");
184       if (!withValues.containsKey("is_published"))
185         withValues.put("is_published","0");
186       if (!withValues.containsKey("is_html"))
187         withValues.put("is_html","0");
188
189       String id = mainModule.add(withValues);
190       DatabaseContentToTopics.getInstance().setTopics(id,req.getParameterValues("to_topic"));
191
192       _showObject(id, req, res);
193     }
194     catch (Throwable e) {
195       throw new ServletModuleFailure(e);
196     }
197   }
198
199   public void delete(HttpServletRequest req, HttpServletResponse res) throws ServletModuleExc
200   {
201     EntityUsers   user = _getUser(req);
202
203     String idParam = req.getParameter("id");
204     if (idParam == null) throw new ServletModuleExc("Invalid call: id missing");
205
206     String confirmParam = req.getParameter("confirm");
207     String cancelParam = req.getParameter("cancel");
208
209     logger.info("where = " + req.getParameter("where"));
210
211     if (confirmParam == null && cancelParam == null) {
212
213       SimpleHash mergeData = new SimpleHash();
214       mergeData.put("module", "Content");
215       mergeData.put("infoString", "Content: " + idParam);
216       mergeData.put("id", idParam);
217       mergeData.put("where", req.getParameter("where"));
218       mergeData.put("order", req.getParameter("order"));
219       mergeData.put("offset", req.getParameter("offset"));
220       deliver(req, res, mergeData, templateConfirmString);
221     }
222     else {
223       if (confirmParam!= null && !confirmParam.equals("")) {
224         try {
225           mainModule.deleteById(idParam);
226
227           /** @todo the following two should be implied in
228            *  DatabaseContent */
229           DatabaseContentToTopics.getInstance().deleteByContentId(idParam);
230           DatabaseComment.getInstance().deleteByContentId(idParam);
231           DatabaseContentToMedia.getInstance().deleteByContentId(idParam);
232
233
234           //delete from lucene index, if any
235           String index = configuration.getString("IndexPath");
236           if (IndexReader.indexExists(index)){
237             IndexUtil.unindexID(idParam,index);
238           }
239
240         }
241         catch (Throwable e) {
242           throw new ServletModuleFailure(e);
243         }
244         list(req,res);
245       }
246       else {
247         // Datensatz anzeigen
248         _showObject(idParam, req, res);
249       }
250     }
251   }
252
253   public void edit(HttpServletRequest req, HttpServletResponse res) throws ServletModuleExc
254   {
255     String idParam = req.getParameter("id");
256     if (idParam == null)
257       throw new ServletModuleExc("Invalid call: id not supplied ");
258     _showObject(idParam, req, res);
259   }
260
261 // methods for attaching media file
262   public void attach(HttpServletRequest req, HttpServletResponse res) throws ServletModuleExc
263   {
264     String  mediaIdParam = req.getParameter("mid");
265     String  articleId = req.getParameter("articleid");
266
267     if (articleId == null || mediaIdParam==null)
268       throw new ServletModuleExc("smod content :: attach :: articleid/mid missing");
269
270     try {
271       EntityContent entContent = (EntityContent) mainModule.getById(articleId);
272       entContent.attach(mediaIdParam);
273     }
274     catch(Throwable e) {
275       throw new ServletModuleFailure(e);
276     }
277
278     _showObject(articleId, req, res);
279   }
280
281   public void dettach(HttpServletRequest req, HttpServletResponse res) throws ServletModuleExc
282   {
283     String  articleId = req.getParameter("articleid");
284     String  midParam = req.getParameter("mid");
285     if (articleId == null)
286       throw new ServletModuleExc("smod content :: dettach :: articleid missing");
287     if (midParam == null)
288       throw new ServletModuleExc("smod content :: dettach :: mid missing");
289
290     try {
291       EntityContent entContent = (EntityContent)mainModule.getById(articleId);
292       entContent.dettach(articleId, midParam);
293     }
294     catch(Throwable e) {
295       throw new ServletModuleFailure(e);
296     }
297
298     _showObject(articleId, req, res);
299   }
300
301   public void update(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc
302   {
303     try {
304       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
305
306       String returnUrl = requestParser.getParameter("returnurl");
307
308       String idParam = aRequest.getParameter("id");
309       if (idParam == null)
310         throw new ServletModuleExc("Wrong call: (id) is missing");
311
312       Map withValues = getIntersectingValues(aRequest, DatabaseContent.getInstance());
313       String[] topic_id = aRequest.getParameterValues("to_topic");
314       String content_id = aRequest.getParameter("id");
315
316       withValues.put("is_produced", "0");
317       if (!withValues.containsKey("is_published"))
318         withValues.put("is_published","0");
319       if (!withValues.containsKey("is_html"))
320         withValues.put("is_html","0");
321
322       String id = mainModule.set(withValues);
323       DatabaseContentToTopics.getInstance().setTopics(aRequest.getParameter("id"),topic_id);
324
325       String whereParam = aRequest.getParameter("where");
326       String orderParam = aRequest.getParameter("order");
327
328       if (returnUrl!=null){
329         redirect(aResponse, returnUrl);
330       }
331       else
332         _showObject(idParam, aRequest, aResponse);
333     }
334     catch (Throwable e) {
335       throw new ServletModuleFailure(e);
336     }
337   }
338
339 /*
340   * HelperMethod shows the basic article editing form.
341   *
342   * if the "id" parameter is null, it means show an empty form to add a new
343   * article.
344 */
345   public void _showObject(String id, HttpServletRequest aRequest, HttpServletResponse aResponse)
346       throws ServletModuleExc {
347     try {
348       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
349       Map responseData = ServletHelper.makeGenerationData(new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)});
350       EntityAdapterModel model = MirGlobal.localizer().dataModel().adapterModel();
351       Map article;
352       URLBuilder urlBuilder = new URLBuilder();
353
354       urlBuilder.setValue("module", "Content");
355       urlBuilder.setValue("do", "edit");
356       urlBuilder.setValue("id", id);
357       urlBuilder.setValue("returnurl", requestParser.getParameter("returnurl"));
358
359       if (id!=null) {
360         responseData.put("new", Boolean.FALSE);
361         article = model.makeEntityAdapter("content", mainModule.getById(id));
362       }
363       else {
364         List fields = DatabaseContent.getInstance().getFields();
365         responseData.put("new", Boolean.TRUE);
366         article = new HashMap();
367         Iterator i = fields.iterator();
368         while (i.hasNext()) {
369           article.put(i.next(), null);
370         }
371
372         article.put("to_topics", null);
373
374         MirGlobal.localizer().adminInterface().initializeArticle(article);
375       }
376       responseData.put("article", article);
377
378       responseData.put("topics",
379           new EntityIteratorAdapter("", configuration.getString("Mir.Localizer.Admin.TopicListOrder"),
380           20, MirGlobal.localizer().dataModel().adapterModel(), "topic"));
381
382
383
384       responseData.put("returnurl", requestParser.getParameter("returnurl"));
385       responseData.put("thisurl", urlBuilder.getQuery());
386
387       ServletHelper.generateResponse(aResponse.getWriter(), responseData, editTemplate);
388     }
389     catch (Throwable e) {
390       throw new ServletModuleFailure(e);
391     }
392   }
393
394   public void returnArticleList(
395        HttpServletRequest aRequest,
396        HttpServletResponse aResponse,
397        String aWhereClause,
398        String anOrderByClause,
399        int anOffset,
400        String aSelectArticleUrl) throws ServletModuleExc {
401
402     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
403     URLBuilder urlBuilder = new URLBuilder();
404     EntityAdapterModel model;
405     int nrArticlesPerPage = 20;
406     int count;
407
408     try {
409       Map responseData = ServletHelper.makeGenerationData(new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)});
410       model = MirGlobal.localizer().dataModel().adapterModel();
411
412       Object articleList =
413           new CachingRewindableIterator(
414             new EntityIteratorAdapter( aWhereClause, anOrderByClause, nrArticlesPerPage,
415                MirGlobal.localizer().dataModel().adapterModel(), "content", nrArticlesPerPage, anOffset)
416       );
417
418       responseData.put("nexturl", null);
419       responseData.put("prevurl", null);
420
421       count=mainModule.getSize(aWhereClause);
422
423       urlBuilder.setValue("module", "Content");
424       urlBuilder.setValue("do", "list");
425       urlBuilder.setValue("where", aWhereClause);
426       urlBuilder.setValue("order", anOrderByClause);
427
428
429       urlBuilder.setValue("searchfield", requestParser.getParameter("searchfield"));
430       urlBuilder.setValue("searchvalue", requestParser.getParameter("searchvalue"));
431       urlBuilder.setValue("searchispublished", requestParser.getParameter("searchispublished"));
432       urlBuilder.setValue("searchorder", requestParser.getParameter("searchorder"));
433       urlBuilder.setValue("searcharticletype", requestParser.getParameter("searcharticletype"));
434       urlBuilder.setValue("selectarticleurl", aSelectArticleUrl);
435
436       responseData.put("searchfield", requestParser.getParameter("searchfield"));
437       responseData.put("searchvalue", requestParser.getParameter("searchvalue"));
438       responseData.put("searchispublished", requestParser.getParameter("searchispublished"));
439       responseData.put("searchorder", requestParser.getParameter("searchorder"));
440       responseData.put("searcharticletype", requestParser.getParameter("searcharticletype"));
441       responseData.put("selectarticleurl", aSelectArticleUrl);
442
443       urlBuilder.setValue("offset", anOffset);
444       responseData.put("offset" , new Integer(anOffset).toString());
445       responseData.put("thisurl" , urlBuilder.getQuery());
446
447       if (count>=anOffset+nrArticlesPerPage) {
448         urlBuilder.setValue("offset", (anOffset + nrArticlesPerPage));
449         responseData.put("nexturl" , urlBuilder.getQuery());
450       }
451
452       if (anOffset>0) {
453         urlBuilder.setValue("offset", Math.max(anOffset - nrArticlesPerPage, 0));
454         responseData.put("prevurl" , urlBuilder.getQuery());
455       }
456
457       responseData.put("articles", articleList);
458
459       responseData.put("from" , Integer.toString(anOffset+1));
460       responseData.put("count", Integer.toString(count));
461       responseData.put("to", Integer.toString(Math.min(anOffset+nrArticlesPerPage, count)));
462       responseData.put("offset" , Integer.toString(anOffset));
463       responseData.put("order", anOrderByClause);
464       responseData.put("where" , aWhereClause);
465
466       ServletHelper.generateResponse(aResponse.getWriter(), responseData, listTemplate);
467     }
468     catch (Throwable e) {
469       throw new ServletModuleFailure(e);
470     }
471   }
472
473   public void selectparent(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc
474   {
475     try {
476       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
477       URLBuilder urlBuilder = new URLBuilder();
478
479       urlBuilder.setValue("module", "Content");
480       urlBuilder.setValue("do", "setparent");
481       urlBuilder.setValue("childid", requestParser.getParameter("id"));
482       urlBuilder.setValue("returnurl", requestParser.getParameter("returnurl"));
483
484       returnArticleList(aRequest, aResponse, "", "", 0, urlBuilder.getQuery());
485     }
486     catch (Throwable e) {
487       throw new ServletModuleFailure(e);
488     }
489   }
490
491   public void listchildren(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc
492   {
493     try {
494       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
495       String articleId = requestParser.getParameter("article_id");
496
497       if (articleId == null)
498         throw new ServletModuleExc("ServletModuleContent.listchildren: article_id not set!");
499
500       returnArticleList(aRequest, aResponse, "to_content = " + articleId, "", 0, null);
501     }
502     catch (Throwable e) {
503       throw new ServletModuleFailure(e);
504     }
505   }
506
507   public void setparent(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc
508   {
509     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
510     String articleId = aRequest.getParameter("childid");
511     String parentId  = aRequest.getParameter("id");
512     String returnUrl = aRequest.getParameter("returnurl");
513
514     try {
515       EntityContent article = (EntityContent) mainModule.getById(articleId);
516       article.setValueForProperty("to_content", parentId);
517       article.setProduced(false);
518       article.update();
519     }
520     catch(Throwable e) {
521       logger.error("ServletModuleContent.setparent: " + e.getMessage());
522       throw new ServletModuleFailure(e);
523     }
524
525     redirect(aResponse, returnUrl);
526   }
527
528   public void clearparent(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc
529   {
530     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
531     String articleId = requestParser.getParameter("id");
532     String returnUrl = requestParser.getParameter("returnurl");
533
534     try {
535       EntityContent article = (EntityContent) mainModule.getById(articleId);
536       article.setValueForProperty("to_content", "");
537       article.setProduced(false);
538       article.update();
539     }
540     catch(Throwable e) {
541       e.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE));
542       logger.error("ServletModuleContent.clearparent: " + e.getMessage());
543
544       throw new ServletModuleFailure("ServletModuleContent.clearparent: " + e.getMessage(), e);
545     }
546
547     redirect(aResponse, returnUrl);
548   }
549
550   private EntityUsers _getUser(HttpServletRequest req)
551   {
552     HttpSession session=req.getSession(false);
553
554     return (EntityUsers)session.getAttribute("login.uid");
555   }
556 }