60389f47bae9d6294dbd28762a36b41261184cdb
[mir.git] / source / mir / servlet / AdminServletModule.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  any library licensed under the Apache Software License,
22  * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
23  * (or with modified versions of the above that use the same license as the above),
24  * and distribute linked combinations including the two.  You must obey the
25  * GNU General Public License in all respects for all of the code used other than
26  * the above mentioned libraries.  If you modify this file, you may extend this
27  * exception to your version of the file, but you are not obligated to do so.
28  * If you do not wish to do so, delete this exception statement from your version.
29  */
30 package mir.servlet;
31
32 import mir.entity.adapter.EntityAdapterEngine;
33 import mir.entity.adapter.EntityAdapterModel;
34 import mir.module.AbstractModule;
35 import mir.module.ModuleExc;
36 import mir.storage.Database;
37 import mir.util.HTTPRequestParser;
38 import mir.util.URLBuilder;
39 import mir.util.StringRoutines;
40 import mircoders.global.MirGlobal;
41 import mircoders.localizer.MirLocalizerExc;
42 import mircoders.servlet.ServletHelper;
43
44 import javax.servlet.http.HttpServletRequest;
45 import javax.servlet.http.HttpServletResponse;
46 import java.util.Collections;
47 import java.util.HashMap;
48 import java.util.HashSet;
49 import java.util.Iterator;
50 import java.util.List;
51 import java.util.Map;
52 import java.util.Set;
53 import java.io.IOException;
54
55 /**
56  *
57  */
58
59 public abstract class AdminServletModule extends ServletModule {
60   protected AbstractModule mainModule;
61   protected String definition;
62   private EntityAdapterModel model;
63
64   protected String listGenerator;
65   protected String editGenerator;
66   protected String deleteConfirmationGenerator;
67   protected int nrEntitiesPerListPage;
68
69   /** the list of parameters that need to be propagated in the list */
70   private Set propagatedParameters = new HashSet();
71
72   protected void addPropagatedParameter(String aParameter) {
73     propagatedParameters.add(aParameter);
74   }
75
76   protected AdminServletModule(){
77     addPropagatedParameter("searchfield");
78     addPropagatedParameter("searchtext");
79     addPropagatedParameter("searchispublished");
80     addPropagatedParameter("searchstatus");
81     addPropagatedParameter("searchorder");
82
83     definition = null;
84     try {
85       model = MirGlobal.localizer().dataModel().adapterModel();
86     }
87     catch (MirLocalizerExc e) {
88       getLogger().error("Can't create model: " + e.toString());
89
90       throw new ServletModuleFailure("Can't retrieve model", e);
91     }
92
93     listGenerator = getConfiguration().getString("ServletModule." + getName() + ".ListTemplate");
94     editGenerator = getConfiguration().getString("ServletModule." + getName() + ".EditTemplate");
95     deleteConfirmationGenerator = getConfiguration().getString("ServletModule." + getName() + ".DeleteConfirmationTemplate");
96     nrEntitiesPerListPage =
97         getConfiguration().getInt("ServletModule."+getName()+".ListSize",
98         getConfiguration().getInt("ServletModule.Default.ListSize", 20));
99
100   }
101
102   protected EntityAdapterModel getModel() {
103     return model;
104   }
105
106   protected void logAdminUsage(HttpServletRequest aRequest, String anObject, String aDescription) {
107     MirGlobal.logAdminUsage(ServletHelper.getUser(aRequest), getName() + ":" + anObject, aDescription);
108   }
109
110   /**
111    * Function to specify the default ordering for lists. May be overridden.
112    */
113   protected String getDefaultListOrdering() {
114
115     if (mainModule!=null && mainModule.getStorageObject()!=null &&
116         mainModule.getStorageObject().hasField("webdb_create")) {
117       return "webdb_create desc";
118     }
119     else {
120       return "id asc";
121     }
122   }
123
124   /**
125    * Generic list servlet method
126    */
127
128   public void list(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
129     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
130
131     String where = requestParser.getParameter("where");
132     String order = requestParser.getParameterWithDefault("order", getDefaultListOrdering());
133     int offset = requestParser.getIntegerWithDefault("offset", 0);
134     String mainTablePrefix = requestParser.getParameter("mainTablePrefix");
135     String extraTables = requestParser.getParameter("extraTables");
136
137     returnList(aRequest, aResponse, where, order, offset, Collections.EMPTY_MAP, mainTablePrefix, extraTables);
138   }
139
140
141   public void returnList(HttpServletRequest aRequest, HttpServletResponse aResponse,
142                          String aWhereClause, String anOrderByClause, int anOffset) throws ServletModuleExc {
143     returnList(aRequest, aResponse, aWhereClause, anOrderByClause, anOffset, Collections.EMPTY_MAP);
144   }
145
146   public void returnList(HttpServletRequest aRequest, HttpServletResponse aResponse,
147                          String aWhereClause, String anOrderByClause, int anOffset,
148                          Map anOverridingRequestParameters) throws ServletModuleExc {
149     returnList(aRequest, aResponse, aWhereClause, anOrderByClause, anOffset, anOverridingRequestParameters, "", null);
150   }
151   public void returnList(HttpServletRequest aRequest, HttpServletResponse aResponse,
152                          String aWhereClause, String anOrderByClause, int anOffset,
153                          Map anOverridingRequestParameters, String aMainTablePrefix, String someExtraTables) throws ServletModuleExc {
154     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest, anOverridingRequestParameters);
155     URLBuilder urlBuilder = new URLBuilder();
156
157     try {
158       Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, getLocales(aRequest));
159
160       List extraTables = null;
161       if (someExtraTables!=null && someExtraTables.length() > 0) {
162         extraTables = StringRoutines.splitString(someExtraTables, ",");
163       }
164
165       List list =
166          EntityAdapterEngine.retrieveAdapterList(model, definition, aMainTablePrefix, extraTables, aWhereClause, anOrderByClause, nrEntitiesPerListPage, anOffset);
167
168       responseData.put("nexturl", null);
169       responseData.put("prevurl", null);
170       responseData.put("module", getName());
171
172       urlBuilder.setValue("module", getName());
173       urlBuilder.setValue("do", "list");
174       urlBuilder.setValue("where", aWhereClause);
175       urlBuilder.setValue("order", anOrderByClause);
176       urlBuilder.setValue("extraTables", someExtraTables);
177       urlBuilder.setValue("mainTablePrefix", aMainTablePrefix);
178
179
180       urlBuilder.setValue("offset", anOffset);
181       responseData.put("offset" , Integer.toString(anOffset));
182       responseData.put("thisurl" , urlBuilder.getQuery());
183
184       propagateFields(requestParser, urlBuilder, responseData);
185
186       if (list.size()>=nrEntitiesPerListPage) {
187         urlBuilder.setValue("offset", anOffset + nrEntitiesPerListPage);
188         responseData.put("nexturl" , urlBuilder.getQuery());
189       }
190
191       if (anOffset>0) {
192         urlBuilder.setValue("offset", Math.max(anOffset - nrEntitiesPerListPage, 0));
193         responseData.put("prevurl" , urlBuilder.getQuery());
194       }
195
196       responseData.put("entities", list);
197       responseData.put("from" , Integer.toString(anOffset+1));
198       responseData.put("count", "?");
199       responseData.put("to", Integer.toString(anOffset+list.size()-1));
200
201       ServletHelper.generateResponse(aResponse.getWriter(), responseData, listGenerator);
202     }
203     catch (Throwable e) {
204       throw new ServletModuleFailure(e);
205     }
206   }
207
208   public void editObject(HttpServletRequest aRequest, HttpServletResponse aResponse, String anId) throws ServletModuleExc {
209     try {
210       editObject(aRequest, aResponse, model.makeEntityAdapter(definition, mainModule.getById(anId)), false, anId);
211     }
212     catch (Throwable t) {
213       throw new ServletModuleFailure(t);
214     }
215   }
216
217   public void editObject(HttpServletRequest aRequest, HttpServletResponse aResponse, Object anObject, boolean anIsNew, String anId) throws ServletModuleExc {
218     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
219     URLBuilder urlBuilder = new URLBuilder();
220
221     try {
222       Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, getLocales(aRequest));
223
224       responseData.put("module", getName());
225       responseData.put("entity", anObject);
226       responseData.put("new", new Boolean(anIsNew));
227
228
229       urlBuilder.setValue("module", getName());
230       urlBuilder.setValue("returnurl", requestParser.getParameter("returnurl"));
231       if (anIsNew) {
232         urlBuilder.setValue("do", "add");
233       }
234       else {
235         urlBuilder.setValue("id", anId);
236         urlBuilder.setValue("do", "edit");
237       }
238       responseData.put("returnurl", requestParser.getParameter("returnurl"));
239       responseData.put("thisurl", urlBuilder.getQuery());
240
241       ServletHelper.generateResponse(aResponse.getWriter(), responseData, editGenerator);
242     }
243     catch (Throwable e) {
244       throw new ServletModuleFailure(e);
245     }
246   }
247
248   /**
249    * Generic add servlet method
250    */
251   public void add(HttpServletRequest aRequest, HttpServletResponse aResponse)
252       throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure  {
253
254     Map object = new HashMap();
255
256     Iterator i = mainModule.getStorageObject().getFieldNames().iterator();
257
258     while (i.hasNext()) {
259       object.put(i.next(), "");
260     }
261
262     initializeNewObject(object, aRequest, aResponse);
263
264     editObject(aRequest, aResponse, object, true, null);
265   }
266
267   protected void initializeNewObject(Map aNewObject, HttpServletRequest aRequest, HttpServletResponse aResponse) {
268   }
269
270   /**
271    * Generic edit servlet method
272    */
273   public void edit(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure  {
274     edit(aRequest, aResponse, aRequest.getParameter("id"));
275   }
276
277   /**
278    */
279   public void edit(HttpServletRequest aRequest, HttpServletResponse aResponse, String anIdentifier)
280       throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure  {
281     try {
282       editObject(aRequest, aResponse, model.makeEntityAdapter(definition, mainModule.getById(anIdentifier)), false, anIdentifier);
283     }
284     catch (Throwable e) {
285       throw new ServletModuleFailure(e);
286     }
287   }
288
289   /**
290    * Generic update servlet method
291    */
292   public void update(HttpServletRequest aRequest, HttpServletResponse aResponse)
293       throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure  {
294     try {
295       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
296
297       String id = aRequest.getParameter("id");
298       Map withValues = getIntersectingValues(aRequest, mainModule.getStorageObject());
299       mainModule.set(withValues);
300
301       logAdminUsage(aRequest, id, "object modified");
302
303       String returnUrl = requestParser.getParameter("returnurl");
304
305       if (returnUrl!=null) {
306         ServletHelper.redirect(aResponse, returnUrl);
307       }
308       else {
309         edit(aRequest, aResponse, id);
310       }
311     }
312     catch (Throwable e) {
313       throw new ServletModuleFailure(e);
314     }
315   }
316
317   /**
318    * Generic insert servlet method
319    */
320   public void insert(HttpServletRequest aRequest, HttpServletResponse aResponse)
321       throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure  {
322     try {
323       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
324
325       Map object = getIntersectingValues(aRequest, mainModule.getStorageObject());
326
327       String id = processInstertedObject(object, aRequest, aResponse);
328
329       logAdminUsage(aRequest, id, "object inserted");
330
331       String returnUrl = requestParser.getParameter("returnurl");
332
333       if (returnUrl!=null) {
334         ServletHelper.redirect(aResponse, returnUrl);
335       }
336       else {
337         edit(aRequest, aResponse, id);
338       }
339     }
340     catch (Throwable e) {
341       throw new ServletModuleFailure(e);
342     }
343   }
344
345   /**
346    *
347    */
348   public String processInstertedObject(Map anObject, HttpServletRequest aRequest, HttpServletResponse aResponse) {
349     try {
350       return mainModule.add(anObject);
351     }
352     catch (ModuleExc t) {
353       throw new ServletModuleFailure(t);
354     }
355   }
356
357   /**
358    * Generic delete confirmation servlet method
359    */
360   public void confirmdelete(HttpServletRequest aRequest, HttpServletResponse aResponse) {
361     try {
362       String idParam = aRequest.getParameter("id");
363       String confirmParam = aRequest.getParameter("confirm");
364
365       if (confirmParam != null && !"".equals(confirmParam)) {
366         mainModule.deleteById(idParam);
367         logAdminUsage(aRequest, idParam, "object deleted");
368         ServletHelper.redirect(aResponse, aRequest.getParameter("okurl"));
369       }
370       else {
371         ServletHelper.redirect(aResponse, aRequest.getParameter("cancelurl"));
372       }
373     }
374     catch (Throwable t) {
375       throw new ServletModuleFailure(t);
376     }
377   }
378
379   /**
380    * Generic delete servlet method
381    */
382   public void delete(HttpServletRequest aRequest, HttpServletResponse aResponse)
383       throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure  {
384     String idParam = aRequest.getParameter("id");
385
386     if (idParam == null) {
387       throw new ServletModuleExc("Invalid call to delete: no id supplied");
388     }
389
390     Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, getLocales(aRequest));
391
392     responseData.put("module", getName());
393     responseData.put("id", idParam);
394     responseData.put("cancelurl", aRequest.getParameter("cancelurl"));
395     responseData.put("okurl", aRequest.getParameter("okurl"));
396
397     try {
398       ServletHelper.generateResponse(aResponse.getWriter(), responseData, deleteConfirmationGenerator);
399     }
400     catch (IOException e) {
401       throw new ServletModuleFailure(e);
402     }
403   }
404
405   /**
406    * Gets the fields from a httprequest and matches them with the metadata from
407    * the database object. Returns the keys that match, with their values.
408    *
409    * @return Map with the values
410    */
411   public Map getIntersectingValues(HttpServletRequest aRequest, Database aDatabase)
412       throws ServletModuleExc, ServletModuleFailure {
413
414     HTTPRequestParser parser = new HTTPRequestParser(aRequest);
415
416     List fields = aDatabase.getFieldNames();
417
418     Map result = new HashMap();
419     for (int i = 0; i < fields.size(); i++) {
420       String aField = (String) fields.get(i);
421
422       String aValue = parser.getParameter(aField);
423       if (aValue != null) {
424         result.put(aField, aValue);
425       }
426     }
427
428     return result;
429   }
430
431   private void propagateFields(HTTPRequestParser aRequest, URLBuilder aUrlBuilder, Map aResponseData) {
432     Iterator i = propagatedParameters.iterator();
433     while (i.hasNext()) {
434       String parameter = (String) i.next();
435       String value = aRequest.getParameter(parameter);
436       aUrlBuilder.setValue(parameter, value);
437       aResponseData.put(parameter, value);
438     }
439   }
440 }