ef75632d4b7ba77ab097f7a9bc940ad1293e7fb4
[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().
154             makeGenerator((String) previewPages.get(aPreviewPage), null);
155       }
156       catch (GeneratorExc e) {
157         throw new MirLocalizerFailure(e);
158       }
159     }
160                 throw new MirLocalizerExc("Unknown preview: " + aPreviewPage);
161   }
162
163   /** {@inheritDoc} */
164   public List getPreviewPages(EntityAdapter anArticle) throws MirLocalizerExc{
165     return Collections.unmodifiableList(previewPageNames);
166   }
167
168   /** {@inheritDoc} */
169   public String makePasswordDigest(String aPassword) {
170     
171
172     return aPassword;
173   }
174
175   /** {@inheritDoc} */
176   public void initializeArticle(Map anArticle) {
177     anArticle.put("is_published", "0");
178     anArticle.put("date", StringUtil.date2webdbDate(new GregorianCalendar()));
179   }
180
181   public List simpleCommentOperations() {
182     return Collections.unmodifiableList(simpleCommentOperations);
183   }
184
185   public List simpleArticleOperations() {
186     return Collections.unmodifiableList(simpleArticleOperations);
187   }
188
189   public MirSimpleEntityOperation simpleArticleOperationForName(String aName) {
190     return (MirSimpleEntityOperation) simpleArticleOperationsMap.get(aName);
191   }
192
193   public MirSimpleEntityOperation simpleCommentOperationForName(String aName) {
194     return (MirSimpleEntityOperation) simpleCommentOperationsMap.get(aName);
195   }
196
197   public void removeSimpleArticleOperation(String aName) {
198     simpleArticleOperations.remove(simpleArticleOperationsMap.get(aName));
199     simpleArticleOperationsMap.remove(aName);
200   }
201
202   public void addSimpleArticleOperation(MirSimpleEntityOperation anOperation) {
203     removeSimpleArticleOperation(anOperation.getName());
204     simpleArticleOperationsMap.put(anOperation.getName(), anOperation);
205     simpleArticleOperations.add(anOperation);
206   }
207
208   public void removeSimpleCommentOperation(String aName) {
209     simpleCommentOperations.remove(simpleCommentOperationsMap.get(aName));
210     simpleCommentOperationsMap.remove(aName);
211   }
212
213   public void addSimpleCommentOperation(MirSimpleEntityOperation anOperation) {
214     removeSimpleCommentOperation(anOperation.getName());
215     simpleCommentOperationsMap.put(anOperation.getName(), anOperation);
216     simpleCommentOperations.add(anOperation);
217   }
218
219   protected abstract static class EntityModifyingOperation implements MirSimpleEntityOperation {
220     private String name;
221     private boolean logOperation;
222
223     protected EntityModifyingOperation(String aName, boolean aLogOperation) {
224       name = aName;
225       logOperation = aLogOperation;
226     }
227
228     public String getName() {
229       return name;
230     }
231
232     public boolean isAvailable(EntityAdapter anEntity) {
233       try {
234         Entity entity = anEntity.getEntity();
235         return isAvailable(entity);
236       }
237       catch (Throwable t) {
238         return false;
239       }
240     }
241
242     public void perform(EntityAdapter aUser, EntityAdapter anEntity) throws MirLocalizerExc, MirLocalizerFailure {
243       Entity entity = anEntity.getEntity();
244       try {
245         performModification(aUser, entity);
246
247         if (logOperation) {
248           try {
249             StringBuffer line = new StringBuffer();
250
251             line.append(DateTimeRoutines.advancedDateFormat(
252                 MirGlobal.config().getString("Mir.DefaultDateTimeFormat"),
253                 (new GregorianCalendar()).getTime(),
254                 MirGlobal.config().getString("Mir.DefaultTimezone")));
255             line.append(" ");
256             if (aUser != null)
257               line.append(aUser.get("login"));
258             else
259               line.append("unknown");
260
261             line.append(" ");
262             line.append(getName());
263             EntityUtility.appendLineToField(entity, "comment", line.toString());
264           }
265           catch (Throwable t) {
266             logger.error("Error while trying to log an article operation: " + t.toString());
267           }
268         }
269
270         entity.update();
271       }
272       catch (Throwable t) {
273         throw new MirLocalizerFailure(t);
274       }
275     }
276
277     protected abstract boolean isAvailable(Entity anEntity) throws DatabaseFailure ;
278     protected abstract void performModification(EntityAdapter aUser, Entity anEntity)  throws MirLocalizerExc, MirLocalizerFailure ;
279   }
280
281   public static abstract class CommentModifyingOperation extends EntityModifyingOperation {
282     public CommentModifyingOperation(String aName, boolean aLogOperation) {
283       super(aName, aLogOperation);
284     }
285
286     public CommentModifyingOperation(String aName) {
287       this(aName, true);
288     }
289
290     protected boolean isAvailable(Entity anEntity) throws DatabaseFailure {
291       return anEntity instanceof EntityComment && isAvailable((EntityComment) anEntity);
292     }
293
294     protected void performModification(EntityAdapter aUser, Entity anEntity) throws DatabaseFailure {
295       performModification(aUser, (EntityComment) anEntity);
296       DatabaseContent.getInstance().setUnproduced("id="+anEntity.getFieldValue("to_media"));
297     }
298
299     protected abstract boolean isAvailable(EntityComment aComment) throws DatabaseFailure ;
300     protected abstract void performModification(EntityAdapter aUser, EntityComment aComment) throws DatabaseFailure ;
301   }
302
303   public static abstract class ArticleModifyingOperation extends EntityModifyingOperation {
304     public ArticleModifyingOperation(String aName, boolean aLogOperation) {
305       super(aName, aLogOperation);
306     }
307
308     protected boolean isAvailable(Entity anEntity) throws DatabaseFailure {
309       return anEntity instanceof EntityContent && isAvailable((EntityContent) anEntity);
310     }
311
312     protected void performModification(EntityAdapter aUser, Entity anEntity) throws DatabaseFailure {
313       performModification(aUser, (EntityContent) anEntity);
314       anEntity.setFieldValue("is_produced", "0");
315     }
316
317     protected abstract boolean isAvailable(EntityContent anArticle) throws DatabaseFailure ;
318     protected abstract void performModification(EntityAdapter aUser, EntityContent anArticle) throws DatabaseFailure ;
319   }
320
321   protected static class SetCommentFieldOperation extends CommentModifyingOperation {
322     private String field;
323     private String value;
324
325     public SetCommentFieldOperation(String aName, String aField, String aValue) {
326       super(aName);
327
328       field = aField;
329       value = aValue;
330     }
331
332     protected boolean isAvailable(EntityComment aComment) {
333       return true;
334     }
335
336     protected void performModification(EntityAdapter aUser, EntityComment aComment) throws DatabaseFailure {
337       aComment.setFieldValue(field, value);
338     }
339   }
340
341   protected static class SetCommentFieldsOperation extends CommentModifyingOperation {
342     private Map values;
343
344     public SetCommentFieldsOperation(String aName, String aFields[], String aValues[]) {
345       super(aName);
346
347       values = new HashMap();
348
349       for (int i=0; i<aFields.length; i++)
350         values.put(aFields[i], aValues[i]);
351     }
352
353     protected boolean isAvailable(EntityComment aComment) {
354       return true;
355     }
356
357     protected void performModification(EntityAdapter aUser, EntityComment aComment) throws DatabaseFailure {
358       Iterator i = values.entrySet().iterator();
359
360       while (i.hasNext()) {
361         Map.Entry entry = (Map.Entry) i.next();
362         aComment.setFieldValue((String) entry.getKey(), (String) entry.getValue());
363       }
364     }
365   }
366
367
368   protected static class ModifyCommentFieldOperation extends CommentModifyingOperation {
369     private String field;
370     private String value;
371
372     public ModifyCommentFieldOperation(String aName, String aField, String aValue) {
373       super(aName);
374
375       field = aField;
376       value = aValue;
377     }
378
379     protected boolean isAvailable(EntityComment aComment) {
380       return aComment.getFieldValue(field) == null || !aComment.getFieldValue(field).equals(value);
381     }
382
383     protected void performModification(EntityAdapter aUser, EntityComment aComment) throws DatabaseFailure {
384       aComment.setFieldValue(field, value);
385     }
386   }
387
388   protected static class SetArticleFieldOperation extends ArticleModifyingOperation {
389     private String field;
390     private String value;
391
392     public SetArticleFieldOperation(String aName, String aField, String aValue, boolean aLogOperation) {
393       super(aName, aLogOperation);
394
395       field = aField;
396       value = aValue;
397     }
398
399     protected boolean isAvailable(EntityContent anArticle) {
400       return true;
401     }
402
403     protected void performModification(EntityAdapter aUser, EntityContent anArticle) throws DatabaseFailure {
404       anArticle.setFieldValue(field, value);
405     }
406   }
407
408   protected static class ModifyArticleFieldOperation extends ArticleModifyingOperation {
409     private String field;
410     private String value;
411
412     public ModifyArticleFieldOperation(String aName, String aField, String aValue, boolean aLogOperation) {
413       super(aName, aLogOperation);
414
415       field = aField;
416       value = aValue;
417     }
418
419     protected boolean isAvailable(EntityContent anArticle) {
420       return anArticle.getFieldValue(field) == null || !anArticle.getFieldValue(field).equals(value);
421     }
422
423     protected void performModification(EntityAdapter aUser, EntityContent anArticle) throws DatabaseFailure {
424       anArticle.setFieldValue(field, value);
425     }
426   }
427
428   protected static class ChangeArticleFieldOperation extends ArticleModifyingOperation {
429     private String field;
430     private Set oldValues;
431     private String newValue;
432
433     public ChangeArticleFieldOperation(String aName, String aField, String anOldValues[], String aNewValue, boolean aLogOperation) {
434       super(aName, aLogOperation);
435
436       field = aField;
437       newValue = aNewValue;
438       oldValues = new HashSet(Arrays.asList(anOldValues));
439     }
440     public ChangeArticleFieldOperation(String aName, String aField, String anOldValue, String aNewValue, boolean aLogOperation) {
441       this(aName, aField, new String[] {anOldValue}, aNewValue, aLogOperation);
442     }
443
444     protected boolean isAvailable(EntityContent anArticle) {
445       return anArticle.getFieldValue(field) != null && oldValues.contains(anArticle.getFieldValue(field));
446     }
447
448     protected void performModification(EntityAdapter aUser, EntityContent anArticle) throws DatabaseFailure {
449       anArticle.setFieldValue(field, newValue);
450     }
451   }
452 }