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