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