* anti-abuse upgrade: filters now stored in the database (experimental)
[mir.git] / source / mircoders / localizer / basic / MirBasicAdminInterfaceLocalizer.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
31 package mircoders.localizer.basic;
32
33 import mir.bundle.Bundle;
34 import mir.config.MirPropertiesConfiguration;
35 import mir.entity.Entity;
36 import mir.entity.adapter.EntityAdapter;
37 import mir.entity.adapter.EntityAdapterFailure;
38 import mir.generator.Generator;
39 import mir.generator.GeneratorExc;
40 import mir.log.LoggerWrapper;
41 import mir.misc.StringUtil;
42 import mir.module.ModuleExc;
43 import mir.storage.StorageObjectFailure;
44 import mir.util.DateTimeFunctions;
45 import mir.util.EntityUtility;
46 import mir.util.StringRoutines;
47 import mir.util.generator.BundleGeneratorFunction;
48 import mircoders.entity.EntityComment;
49 import mircoders.entity.EntityContent;
50 import mircoders.global.MirGlobal;
51 import mircoders.localizer.MirAdminInterfaceLocalizer;
52 import mircoders.localizer.MirLocalizerExc;
53 import mircoders.localizer.MirLocalizerFailure;
54 import mircoders.module.ModuleLanguage;
55 import mircoders.storage.DatabaseContent;
56
57 import java.util.*;
58
59
60 public class MirBasicAdminInterfaceLocalizer implements MirAdminInterfaceLocalizer {
61   /** preview page name (String) -> generator name (String) */
62   private Map previewPages;
63   private List previewPageNames;
64
65   private List simpleCommentOperations;
66   private List simpleArticleOperations;
67   private Map simpleCommentOperationsMap;
68   private Map simpleArticleOperationsMap;
69
70   protected static LoggerWrapper logger = new LoggerWrapper("Localizer.AdminInterface");;
71   protected MirPropertiesConfiguration configuration = MirPropertiesConfiguration.instance();
72
73   public MirBasicAdminInterfaceLocalizer() throws MirLocalizerFailure {
74
75     simpleCommentOperations = new ArrayList();
76     simpleArticleOperations = new ArrayList();
77     simpleCommentOperationsMap = new HashMap();
78     simpleArticleOperationsMap = new HashMap();
79
80     previewPages = new HashMap();
81     previewPageNames = new ArrayList();
82
83     String[] previewConfiguration = configuration.getStringArray("Mir.Localizer.Admin.ArticlePreview");
84
85     for (int i = 0; i<previewConfiguration.length; i++) {
86       try {
87         List parts = StringRoutines.separateString(previewConfiguration[i], "=");
88         if (parts.size() == 2) {
89           String key = ((String) parts.get(0)).trim();
90           previewPages.put(key,((String) parts.get(1)).trim());
91           previewPageNames.add(key);
92         }
93         else {
94           throw new Exception("'=' expected");
95         }
96       }
97       catch (Exception e) {
98         logger.error("Error while processing preview configuration '" + previewConfiguration[i] + "': " + e.toString());
99       }
100     }
101
102     addSimpleArticleOperation(new ChangeArticleFieldOperation("newswire", "to_article_type", "0", "1", false));
103     addSimpleArticleOperation(new ModifyArticleFieldOperation("unhide", "is_published", "1", false));
104     addSimpleArticleOperation(new ModifyArticleFieldOperation("hide", "is_published", "0", false));
105
106     addSimpleCommentOperation(new ModifyCommentFieldOperation("unhide", "is_published", "1"));
107     addSimpleCommentOperation(new ModifyCommentFieldOperation("hide", "is_published", "0"));
108   }
109
110   /** {@inheritDoc} */
111   public String getAdminPageGenerator(String aPage, Map aTemplateData, EntityAdapter aUser, String aDefault) throws MirLocalizerExc {
112     return aDefault;
113   }
114
115   /** {@inheritDoc} */
116   public Generator prepareArticlePreview(String aPreviewPage, EntityAdapter anArticle, Map aContext) throws MirLocalizerExc {
117     MirGlobal.localizer().producerAssistant().initializeGenerationValueSet(aContext);
118     aContext.put("article", anArticle);
119
120     try {
121       aContext.put(
122           "language",
123           MirGlobal.localizer().dataModel().adapterModel().makeEntityAdapter("language",
124               new ModuleLanguage().languageForCode(configuration.getString("Mir.Localizer.Admin.ArticlePreviewLanguage"))));
125     }
126     catch (EntityAdapterFailure e) {
127       throw new MirLocalizerFailure("Can't create entity adapter", e);
128     }
129     catch (ModuleExc e) {
130       throw new MirLocalizerFailure("Can't find language", e);
131     }
132     aContext.put("pathprefix", configuration.getString("Mir.Localizer.Admin.ArticlePreviewLanguage")); 
133
134     aContext.put("lang",
135         new BundleGeneratorFunction(
136             new Bundle[] {
137               MirGlobal.getBundleFactory().getBundle(
138                   "etc/bundles/producer",
139                   new String[] {
140                     configuration.getString("Mir.Localizer.Admin.ArticlePreviewLanguage") }) }));
141
142
143     if (previewPages.containsKey(aPreviewPage)) {
144       try {
145         return MirGlobal.localizer().generators().makeAdminGeneratorLibrary().makeGenerator((String) previewPages.get(aPreviewPage));
146       }
147       catch (GeneratorExc e) {
148         throw new MirLocalizerFailure(e);
149       }
150     }
151     else {
152       throw new MirLocalizerExc("Unknown preview: " + aPreviewPage);
153     }
154   }
155
156   /** {@inheritDoc} */
157   public List getPreviewPages(EntityAdapter anArticle) throws MirLocalizerExc{
158     return Collections.unmodifiableList(previewPageNames);
159   }
160
161   /** {@inheritDoc} */
162   public String makePasswordDigest(String aPassword) {
163     return aPassword;
164   }
165
166   public void initializeArticle(Map anArticle) {
167     anArticle.put("is_published", "0");
168     anArticle.put("date", StringUtil.date2webdbDate(new GregorianCalendar()));
169   };
170
171   public List simpleCommentOperations() {
172     return Collections.unmodifiableList(simpleCommentOperations);
173   };
174
175   public List simpleArticleOperations() {
176     return Collections.unmodifiableList(simpleArticleOperations);
177   };
178
179   public MirSimpleEntityOperation simpleArticleOperationForName(String aName) {
180     return (MirSimpleEntityOperation) simpleArticleOperationsMap.get(aName);
181   };
182
183   public MirSimpleEntityOperation simpleCommentOperationForName(String aName) {
184     return (MirSimpleEntityOperation) simpleCommentOperationsMap.get(aName);
185   };
186
187   public void removeSimpleArticleOperation(String aName) {
188     simpleArticleOperations.remove(simpleArticleOperationsMap.get(aName));
189     simpleArticleOperationsMap.remove(aName);
190   }
191
192   public void addSimpleArticleOperation(MirSimpleEntityOperation anOperation) {
193     removeSimpleArticleOperation(anOperation.getName());
194     simpleArticleOperationsMap.put(anOperation.getName(), anOperation);
195     simpleArticleOperations.add(anOperation);
196   }
197
198   public void removeSimpleCommentOperation(String aName) {
199     simpleCommentOperations.remove(simpleCommentOperationsMap.get(aName));
200     simpleCommentOperationsMap.remove(aName);
201   }
202
203   public void addSimpleCommentOperation(MirSimpleEntityOperation anOperation) {
204     removeSimpleCommentOperation(anOperation.getName());
205     simpleCommentOperationsMap.put(anOperation.getName(), anOperation);
206     simpleCommentOperations.add(anOperation);
207   }
208
209   protected abstract static class EntityModifyingOperation implements MirSimpleEntityOperation {
210     private String name;
211     private boolean logOperation;
212
213     protected EntityModifyingOperation(String aName, boolean aLogOperation) {
214       name = aName;
215       logOperation = aLogOperation;
216     }
217
218     public String getName() {
219       return name;
220     };
221
222     public boolean isAvailable(EntityAdapter anEntity) {
223       try {
224         Entity entity = anEntity.getEntity();
225         return isAvailable(entity);
226       }
227       catch (Throwable t) {
228         return false;
229       }
230     };
231
232     public void perform(EntityAdapter aUser, EntityAdapter anEntity) throws MirLocalizerExc, MirLocalizerFailure {
233       Entity entity = anEntity.getEntity();
234       try {
235         performModification(aUser, entity);
236
237         if (logOperation) {
238           try {
239             StringBuffer line = new StringBuffer();
240
241             line.append(DateTimeFunctions.advancedDateFormat(
242                 MirGlobal.config().getString("Mir.DefaultDateTimeFormat"),
243                 (new GregorianCalendar()).getTime(),
244                 MirGlobal.config().getString("Mir.DefaultTimezone")));
245             line.append(" ");
246             if (aUser != null)
247               line.append(aUser.get("login"));
248             else
249               line.append("unknown");
250
251             line.append(" ");
252             line.append(getName());
253             EntityUtility.appendLineToField(entity, "comment", line.toString());
254           }
255           catch (Throwable t) {
256             logger.error("Error while trying to log an article operation: " + t.toString());
257           }
258         }
259
260         entity.update();
261       }
262       catch (Throwable t) {
263         throw new MirLocalizerFailure(t);
264       }
265     };
266
267     protected abstract boolean isAvailable(Entity anEntity) throws StorageObjectFailure ;
268     protected abstract void performModification(EntityAdapter aUser, Entity anEntity)  throws MirLocalizerExc, MirLocalizerFailure ;
269   }
270
271   public static abstract class CommentModifyingOperation extends EntityModifyingOperation {
272     public CommentModifyingOperation(String aName, boolean aLogOperation) {
273       super(aName, aLogOperation);
274     }
275
276     public CommentModifyingOperation(String aName) {
277       this(aName, true);
278     }
279
280     protected boolean isAvailable(Entity anEntity) throws StorageObjectFailure {
281       return anEntity instanceof EntityComment && isAvailable((EntityComment) anEntity);
282     }
283
284     protected void performModification(EntityAdapter aUser, Entity anEntity) throws StorageObjectFailure {
285       performModification(aUser, (EntityComment) anEntity);
286       DatabaseContent.getInstance().setUnproduced("id="+anEntity.getFieldValue("to_media"));
287     };
288
289     protected abstract boolean isAvailable(EntityComment aComment) throws StorageObjectFailure ;
290     protected abstract void performModification(EntityAdapter aUser, EntityComment aComment) throws StorageObjectFailure ;
291   }
292
293   public static abstract class ArticleModifyingOperation extends EntityModifyingOperation {
294     public ArticleModifyingOperation(String aName, boolean aLogOperation) {
295       super(aName, aLogOperation);
296     }
297
298     protected boolean isAvailable(Entity anEntity) throws StorageObjectFailure {
299       return anEntity instanceof EntityContent && isAvailable((EntityContent) anEntity);
300     }
301
302     protected void performModification(EntityAdapter aUser, Entity anEntity) throws StorageObjectFailure {
303       performModification(aUser, (EntityContent) anEntity);
304       anEntity.setFieldValue("is_produced", "0");
305     };
306
307     protected abstract boolean isAvailable(EntityContent anArticle) throws StorageObjectFailure ;
308     protected abstract void performModification(EntityAdapter aUser, EntityContent anArticle) throws StorageObjectFailure ;
309   }
310
311   protected static class SetCommentFieldOperation extends CommentModifyingOperation {
312     private String field;
313     private String value;
314
315     public SetCommentFieldOperation(String aName, String aField, String aValue) {
316       super(aName);
317
318       field = aField;
319       value = aValue;
320     }
321
322     protected boolean isAvailable(EntityComment aComment) {
323       return true;
324     }
325
326     protected void performModification(EntityAdapter aUser, EntityComment aComment) throws StorageObjectFailure {
327       aComment.setFieldValue(field, value);
328     }
329   }
330
331   protected static class SetCommentFieldsOperation extends CommentModifyingOperation {
332     private Map values;
333
334     public SetCommentFieldsOperation(String aName, String aFields[], String aValues[]) {
335       super(aName);
336
337       values = new HashMap();
338
339       for (int i=0; i<aFields.length; i++)
340         values.put(aFields[i], aValues[i]);
341     }
342
343     protected boolean isAvailable(EntityComment aComment) {
344       return true;
345     }
346
347     protected void performModification(EntityAdapter aUser, EntityComment aComment) throws StorageObjectFailure {
348       Iterator i = values.entrySet().iterator();
349
350       while (i.hasNext()) {
351         Map.Entry entry = (Map.Entry) i.next();
352         aComment.setFieldValue((String) entry.getKey(), (String) entry.getValue());
353       }
354     }
355   }
356
357
358   protected static class ModifyCommentFieldOperation extends CommentModifyingOperation {
359     private String field;
360     private String value;
361
362     public ModifyCommentFieldOperation(String aName, String aField, String aValue) {
363       super(aName);
364
365       field = aField;
366       value = aValue;
367     }
368
369     protected boolean isAvailable(EntityComment aComment) {
370       return aComment.getFieldValue(field) == null || !aComment.getFieldValue(field).equals(value);
371     }
372
373     protected void performModification(EntityAdapter aUser, EntityComment aComment) throws StorageObjectFailure {
374       aComment.setFieldValue(field, value);
375     }
376   }
377
378   protected static class SetArticleFieldOperation extends ArticleModifyingOperation {
379     private String field;
380     private String value;
381
382     public SetArticleFieldOperation(String aName, String aField, String aValue, boolean aLogOperation) {
383       super(aName, aLogOperation);
384
385       field = aField;
386       value = aValue;
387     }
388
389     protected boolean isAvailable(EntityContent anArticle) {
390       return true;
391     }
392
393     protected void performModification(EntityAdapter aUser, EntityContent anArticle) throws StorageObjectFailure {
394       anArticle.setFieldValue(field, value);
395     }
396   }
397
398   protected static class ModifyArticleFieldOperation extends ArticleModifyingOperation {
399     private String field;
400     private String value;
401
402     public ModifyArticleFieldOperation(String aName, String aField, String aValue, boolean aLogOperation) {
403       super(aName, aLogOperation);
404
405       field = aField;
406       value = aValue;
407     }
408
409     protected boolean isAvailable(EntityContent anArticle) {
410       return anArticle.getFieldValue(field) == null || !anArticle.getFieldValue(field).equals(value);
411     }
412
413     protected void performModification(EntityAdapter aUser, EntityContent anArticle) throws StorageObjectFailure {
414       anArticle.setFieldValue(field, value);
415     }
416   }
417
418   protected static class ChangeArticleFieldOperation extends ArticleModifyingOperation {
419     private String field;
420     private Set oldValues;
421     private String newValue;
422
423     public ChangeArticleFieldOperation(String aName, String aField, String anOldValues[], String aNewValue, boolean aLogOperation) {
424       super(aName, aLogOperation);
425
426       field = aField;
427       newValue = aNewValue;
428       oldValues = new HashSet(Arrays.asList(anOldValues));
429     }
430     public ChangeArticleFieldOperation(String aName, String aField, String anOldValue, String aNewValue, boolean aLogOperation) {
431       this(aName, aField, new String[] {anOldValue}, aNewValue, aLogOperation);
432     }
433
434     protected boolean isAvailable(EntityContent anArticle) {
435       return anArticle.getFieldValue(field) != null && oldValues.contains(anArticle.getFieldValue(field));
436     }
437
438     protected void performModification(EntityAdapter aUser, EntityContent anArticle) throws StorageObjectFailure {
439       anArticle.setFieldValue(field, newValue);
440     }
441   }
442 }