whoops
[mir.git] / source / mircoders / localizer / basic / MirBasicDataModelLocalizer.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 mircoders.localizer.basic;
31
32 import mir.config.MirPropertiesConfiguration;
33 import mir.entity.Entity;
34 import mir.entity.adapter.EntityAdapter;
35 import mir.entity.adapter.EntityAdapterDefinition;
36 import mir.entity.adapter.EntityAdapterModel;
37 import mir.entity.adapter.ToManyRelationField;
38 import mir.entity.adapter.ToOneRelationField;
39 import mir.generator.Generator;
40 import mir.generator.GeneratorExc;
41 import mir.generator.GeneratorFailure;
42 import mir.log.LoggerWrapper;
43 import mir.media.MediaHandler;
44 import mir.misc.NumberUtils;
45 import mir.util.JDBCStringRoutines;
46 import mir.util.ParameterExpander;
47 import mir.util.StructuredContentParser;
48 import mircoders.entity.EntityContent;
49 import mircoders.entity.EntityUploadedMedia;
50 import mircoders.global.MirGlobal;
51 import mircoders.localizer.MirAdminInterfaceLocalizer;
52 import mircoders.localizer.MirDataModelLocalizer;
53 import mircoders.localizer.MirLocalizerExc;
54 import mircoders.localizer.MirLocalizerFailure;
55 import mircoders.media.MediaHelper;
56 import mircoders.module.ModuleContent;
57 import mircoders.module.ModuleLanguage;
58 import mircoders.module.ModuleCommentStatus;
59 import mircoders.storage.*;
60 import multex.Failure;
61
62 import java.util.ArrayList;
63 import java.util.Collections;
64 import java.util.HashMap;
65 import java.util.Iterator;
66 import java.util.List;
67 import java.util.Map;
68
69 public class MirBasicDataModelLocalizer implements MirDataModelLocalizer {
70   protected LoggerWrapper logger = new LoggerWrapper("Localizer.DataModel");
71   protected MirPropertiesConfiguration configuration = MirPropertiesConfiguration.instance();
72   protected ModuleLanguage languageModule = new ModuleLanguage();
73
74   protected void constructContentAdapterDefinition(EntityAdapterDefinition anEntityAdapterDefinition) throws MirLocalizerFailure, MirLocalizerExc {
75     try {
76       anEntityAdapterDefinition.addDBDateField("creationdate", "webdb_create", configuration.getString("Mir.DefaultTimezone"));
77       anEntityAdapterDefinition.addDBDateField("changedate", "webdb_lastchange", configuration.getString("Mir.DefaultTimezone"));
78       anEntityAdapterDefinition.addMirDateField("date", "date", configuration.getString("Mir.DefaultTimezone"));
79
80       anEntityAdapterDefinition.addCalculatedField("lockinguser", new ToOneRelationField("to_locking_user", "id", "user"));
81       anEntityAdapterDefinition.addCalculatedField("is_locked", new ContentToIsLockedField());
82
83       anEntityAdapterDefinition.addCalculatedField("to_topics", new ContentToTopicsField());
84       anEntityAdapterDefinition.addCalculatedField("to_comments", new ContentToCommentsField());
85       anEntityAdapterDefinition.addCalculatedField("language", new ToOneRelationField("to_language", "language", "id"));
86       anEntityAdapterDefinition.addCalculatedField("commentcount", new ContentCommentCountField(" and is_published='1'"));
87       anEntityAdapterDefinition.addCalculatedField("fullcommentcount", new ContentCommentCountField(""));
88       anEntityAdapterDefinition.addCalculatedField("commentstatuscount", new CommentStatusCountField());
89
90       anEntityAdapterDefinition.addCalculatedField("mediacount", new ContentMediaCountField("uploaded_media", true));
91       anEntityAdapterDefinition.addCalculatedField("fullmediacount", new ContentMediaCountField("uploaded_media", false));
92
93       anEntityAdapterDefinition.addCalculatedField("to_uploaded_media", new ContentToMediaField( "uploadedMedia" ));
94       anEntityAdapterDefinition.addCalculatedField("to_media_images",  new ContentToMediaField( "image" ));
95       anEntityAdapterDefinition.addCalculatedField("to_media_audio", new ContentToMediaField( "audio" ));
96       anEntityAdapterDefinition.addCalculatedField("to_media_video", new ContentToMediaField( "video" ));
97       anEntityAdapterDefinition.addCalculatedField("to_media_other", new ContentToMediaField( "otherMedia" ));
98
99       anEntityAdapterDefinition.addCalculatedField("firstImage",  new ContentToFirstMediaField( "image" ));
100       anEntityAdapterDefinition.addCalculatedField("firstAudio", new ContentToFirstMediaField( "audio" ));
101       anEntityAdapterDefinition.addCalculatedField("firstVideo", new ContentToFirstMediaField( "video" ));
102       anEntityAdapterDefinition.addCalculatedField("firstOther", new ContentToFirstMediaField( "otherMedia" ));
103
104       anEntityAdapterDefinition.addCalculatedField("to_all_uploaded_media", new ContentToMediaField( "uploadedMedia", false));
105       anEntityAdapterDefinition.addCalculatedField("to_all_media_images",  new ContentToMediaField( "image", false));
106       anEntityAdapterDefinition.addCalculatedField("to_all_media_audio", new ContentToMediaField( "audio", false));
107       anEntityAdapterDefinition.addCalculatedField("to_all_media_video", new ContentToMediaField( "video", false));
108       anEntityAdapterDefinition.addCalculatedField("to_all_media_other", new ContentToMediaField( "otherMedia", false));
109       anEntityAdapterDefinition.addCalculatedField("to_media_icon", new ContentToIconField());
110
111       anEntityAdapterDefinition.addCalculatedField("article_type", new ToOneRelationField("to_article_type", "articleType", "id"));
112
113       anEntityAdapterDefinition.addCalculatedField("description_parsed", new FilteredField("description"));
114       anEntityAdapterDefinition.addCalculatedField("content_data_parsed", new FilteredField("content_data"));
115
116       anEntityAdapterDefinition.addCalculatedField("children", new ContentToChildrenField());
117       anEntityAdapterDefinition.addCalculatedField("parent", new ToOneRelationField("to_content", "content", "id"));
118
119       anEntityAdapterDefinition.addCalculatedField("publicurl", new ExpandedField(configuration.getString("Article.PublicUrl")));
120
121       anEntityAdapterDefinition.addCalculatedField("operations",
122           new EntityToSimpleOperationsField(MirGlobal.localizer().adminInterface().simpleArticleOperations()));
123       
124       anEntityAdapterDefinition.addCalculatedField("languagename", new ContentToLanguageNameField());
125
126       anEntityAdapterDefinition.addCalculatedField("is_original", new ContentIsOriginalField());
127       anEntityAdapterDefinition.addCalculatedField("to_original", new ContentToOriginalField());
128       anEntityAdapterDefinition.addCalculatedField("to_translations", new ContentToTranslationsField());
129       anEntityAdapterDefinition.addCalculatedField("to_translation", new ContentToTranslationField());
130
131       anEntityAdapterDefinition.addCalculatedField("allow_publication",
132           new EntityAdapterDefinition.CalculatedField() {
133
134             public Object getValue(EntityAdapter anEntityAdapter) {
135               try {
136                 return new Boolean(MirGlobal.localizer().openPostings().
137                     allowArticlePublication((EntityContent) anEntityAdapter.getEntity()));
138               }
139               catch (Throwable t) {
140                 return  Boolean.FALSE;
141               }
142             }
143           }
144       );
145
146       anEntityAdapterDefinition.addCalculatedField("previews", new EntityAdapterDefinition.CalculatedField() {
147         public Object getValue(EntityAdapter anEntityAdapter) {
148           try {
149             return MirGlobal.localizer().adminInterface().getPreviewPages(anEntityAdapter);
150           }
151           catch (MirLocalizerExc e) {
152             throw new Failure("Cannot get previews for article", e);
153           }
154         }
155       });
156     }
157     catch (Throwable t) {
158       throw new MirLocalizerFailure(t.getMessage(), t);
159     }
160   }
161
162
163
164   protected void constructCommentAdapterDefinition(EntityAdapterDefinition anEntityAdapterDefinition) throws MirLocalizerFailure {
165     try {
166       anEntityAdapterDefinition.addDBDateField("creationdate", "webdb_create", configuration.getString("Mir.DefaultTimezone"));
167       anEntityAdapterDefinition.addCalculatedField("to_content", new ToOneRelationField("to_media", "content", "id"));
168       anEntityAdapterDefinition.addCalculatedField("status", new CommentToStatusField());
169
170       anEntityAdapterDefinition.addCalculatedField("to_uploaded_media", new CommentToMediaField( "uploadedMedia" ));
171       anEntityAdapterDefinition.addCalculatedField("to_media_images",  new CommentToMediaField( "image" ));
172       anEntityAdapterDefinition.addCalculatedField("to_media_audio", new CommentToMediaField( "audio" ));
173       anEntityAdapterDefinition.addCalculatedField("to_media_video", new CommentToMediaField( "video" ));
174       anEntityAdapterDefinition.addCalculatedField("to_media_other", new CommentToMediaField( "otherMedia" ));
175       anEntityAdapterDefinition.addCalculatedField("to_all_uploaded_media", new CommentToMediaField( "uploadedMedia", false));
176       anEntityAdapterDefinition.addCalculatedField("to_all_media_images",  new CommentToMediaField( "image", false));
177       anEntityAdapterDefinition.addCalculatedField("to_all_media_audio", new CommentToMediaField( "audio", false));
178       anEntityAdapterDefinition.addCalculatedField("to_all_media_video", new CommentToMediaField( "video", false));
179       anEntityAdapterDefinition.addCalculatedField("to_all_media_other", new CommentToMediaField( "otherMedia", false));
180
181       anEntityAdapterDefinition.addCalculatedField("publicurl", new ExpandedField(configuration.getString("Comment.PublicUrl")));
182
183       anEntityAdapterDefinition.addCalculatedField("description_parsed", new FilteredField("description"));
184       anEntityAdapterDefinition.addCalculatedField("operations",
185           new EntityToSimpleOperationsField(MirGlobal.localizer().adminInterface().simpleCommentOperations()));
186     }
187     catch (Throwable t) {
188       throw new MirLocalizerFailure(t.getMessage(), t);
189     }
190   }
191
192   public EntityAdapterModel adapterModel() throws MirLocalizerFailure, MirLocalizerExc {
193     EntityAdapterModel result = new EntityAdapterModel();
194
195     try {
196       EntityAdapterDefinition definition;
197
198       definition = new EntityAdapterDefinition();
199       constructContentAdapterDefinition( definition );
200       result.addMapping( "content", DatabaseContent.getInstance(), definition);
201
202       definition = new EntityAdapterDefinition();
203       constructCommentAdapterDefinition( definition );
204       result.addMapping( "comment", DatabaseComment.getInstance(), definition);
205       result.addMapping( "commentStatus", DatabaseCommentStatus.getInstance(), new EntityAdapterDefinition());
206
207       result.addMapping( "articleType", DatabaseArticleType.getInstance(), new EntityAdapterDefinition());
208
209       result.addMapping( "mediaType", DatabaseMediaType.getInstance(), new EntityAdapterDefinition());
210
211
212       definition = new EntityAdapterDefinition();
213       definition.addDBDateField("creationdate", "webdb_create", configuration.getString("Mir.DefaultTimezone"));
214       result.addMapping( "breakingNews", DatabaseBreaking.getInstance(), definition);
215
216       definition = new EntityAdapterDefinition();
217       definition.addDBDateField("creationdate", "webdb_create", configuration.getString("Mir.DefaultTimezone"));
218       result.addMapping( "internalMessage", DatabaseMessages.getInstance(), definition);
219
220       definition = new EntityAdapterDefinition();
221       definition.addCalculatedField("mediafolder", new ToOneRelationField("to_media_folder", "mediaFolder", "id"));
222       definition.addCalculatedField("human_readable_size", new HumanReadableSizeField("value"));
223       definition.addDBDateField("creationdate", "webdb_create", configuration.getString("Mir.DefaultTimezone"));
224       definition.addCalculatedField("info", new MediaToMediaInfoField());
225       result.addMapping( "uploadedMedia", DatabaseUploadedMedia.getInstance(), definition);
226       definition = new EntityAdapterDefinition();
227       definition.addCalculatedField("mediafolder", new ToOneRelationField("to_media_folder", "mediaFolder", "id"));
228       definition.addCalculatedField("human_readable_size", new HumanReadableSizeField("value"));
229       definition.addDBDateField("creationdate", "webdb_create", configuration.getString("Mir.DefaultTimezone"));
230       definition.addCalculatedField("info", new MediaToMediaInfoField());
231       definition.addCalculatedField("big_icon", new MediaToBigIconField());
232       result.addMapping( "image", DatabaseImages.getInstance(), definition);
233       definition = new EntityAdapterDefinition();
234       definition.addCalculatedField("mediafolder", new ToOneRelationField("to_media_folder", "mediaFolder", "id"));
235       definition.addCalculatedField("human_readable_size", new HumanReadableSizeField("value"));
236       definition.addDBDateField("creationdate", "webdb_create", configuration.getString("Mir.DefaultTimezone"));
237       definition.addCalculatedField("info", new MediaToMediaInfoField());
238       definition.addCalculatedField("big_icon", new MediaToBigIconField());
239       result.addMapping( "audio", DatabaseAudio.getInstance(), definition);
240       definition = new EntityAdapterDefinition();
241       definition.addCalculatedField("mediafolder", new ToOneRelationField("to_media_folder", "mediaFolder", "id"));
242       definition.addCalculatedField("human_readable_size", new HumanReadableSizeField("value"));
243       definition.addDBDateField("creationdate", "webdb_create", configuration.getString("Mir.DefaultTimezone"));
244       definition.addCalculatedField("info", new MediaToMediaInfoField());
245       definition.addCalculatedField("big_icon", new MediaToBigIconField());
246       result.addMapping( "video", DatabaseVideo.getInstance(), definition);
247
248       definition = new EntityAdapterDefinition();
249       definition.addCalculatedField("mediafolder", new ToOneRelationField("to_media_folder", "mediaFolder", "id"));
250       definition.addCalculatedField("human_readable_size", new HumanReadableSizeField("value"));
251       definition.addDBDateField("creationdate", "webdb_create", configuration.getString("Mir.DefaultTimezone"));
252       definition.addCalculatedField("info", new MediaToMediaInfoField());
253       definition.addCalculatedField("big_icon", new MediaToBigIconField());
254       result.addMapping( "otherMedia", DatabaseOther.getInstance(), definition);
255
256
257       result.addMapping( "mediaFolder", DatabaseMediafolder.getInstance(), new EntityAdapterDefinition());
258       result.addMapping( "imageType", DatabaseImageType.getInstance(), new EntityAdapterDefinition());
259       result.addMapping( "language", DatabaseLanguage.getInstance(), new EntityAdapterDefinition());
260       result.addMapping( "mediaType", DatabaseMediaType.getInstance(), new EntityAdapterDefinition());
261       result.addMapping( "topic", DatabaseTopics.getInstance(), new EntityAdapterDefinition());
262
263       definition = new EntityAdapterDefinition();
264       definition.addDBDateField("creationdate", "webdb_create", configuration.getString("Mir.DefaultTimezone"));
265       definition.addDBDateField("lastlogindate", "lastlogin", configuration.getString("Mir.DefaultTimezone"));
266       definition.addCalculatedField("structuredProfile", new StructuredContentField("profile"));
267       result.addMapping( "user", DatabaseUsers.getInstance(), definition);
268
269       result.addMapping( "content_x_topic", DatabaseContentToTopics.getInstance(), new EntityAdapterDefinition());
270
271       definition = new EntityAdapterDefinition();
272       definition.addCalculatedField("to_filters",
273           new ToManyRelationField("id", "filter", "filter_group_id", "priority asc"));
274       result.addMapping("filterGroup", DatabaseFilterGroup.getInstance(), definition);
275       definition = new EntityAdapterDefinition();
276       definition.addDBDateField("lasthit", "last_hit", configuration.getString("Mir.DefaultTimezone"));
277       definition.addCalculatedField("to_filter_group",
278           new ToOneRelationField("filter_group_id", "filter_group", "id"));
279       result.addMapping("filter", DatabaseFilter.getInstance(), definition);
280     }
281     catch (Throwable t) {
282       throw new MirLocalizerFailure(t.getMessage(), t);
283     }
284
285     return result;
286   }
287
288   protected class CommentToStatusField implements EntityAdapterDefinition.CalculatedField {
289     public Object getValue(EntityAdapter anEntityAdapter) {
290       try {
291         return anEntityAdapter.getToOneRelation(
292                     "id="+anEntityAdapter.get("to_comment_status"),
293                     "id",
294                     "commentStatus" );
295       }
296       catch (Throwable t) {
297         throw new RuntimeException(t.getMessage());
298       }
299     }
300   }
301
302   protected class EntityToSimpleOperationsField implements EntityAdapterDefinition.CalculatedField {
303     private List operations;
304
305     public EntityToSimpleOperationsField(List anOperations) {
306       operations = anOperations;
307     }
308
309     public Object getValue(EntityAdapter anEntityAdapter) {
310       try {
311         Iterator i = operations.iterator();
312         List availableOperations = new ArrayList();
313
314         while (i.hasNext()) {
315           MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation =
316             (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) i.next();
317
318           if (operation.isAvailable(anEntityAdapter)) {
319             availableOperations.add(operation.getName());
320           }
321         }
322
323         return availableOperations;
324       }
325       catch (Throwable t) {
326         throw new RuntimeException(t.getMessage());
327       }
328     }
329   }
330
331   protected class FilteredField implements EntityAdapterDefinition.CalculatedField {
332     private String fieldName;
333
334     public FilteredField(String aFieldName) {
335       fieldName = aFieldName;
336     }
337
338     public Object getValue(EntityAdapter anEntityAdapter) {
339       try {
340         if (anEntityAdapter.get("is_html")!=null && anEntityAdapter.get("is_html").equals("1")) {
341           return MirGlobal.localizer().producerAssistant().filterHTMLText((String) anEntityAdapter.get(fieldName));
342         }
343                                 return MirGlobal.localizer().producerAssistant().filterNonHTMLText((String) anEntityAdapter.get(fieldName));
344       }
345       catch (Throwable t) {
346         throw new RuntimeException(t.getMessage());
347       }
348     }
349   }
350
351   protected class StructuredContentField implements EntityAdapterDefinition.CalculatedField {
352     private String expression;
353
354     public StructuredContentField(String anExpression) {
355       expression = anExpression;
356     }
357
358     public Object getValue(EntityAdapter anEntityAdapter) {
359       try {
360         return StructuredContentParser.parse(ParameterExpander.evaluateStringExpression(anEntityAdapter, expression));
361       }
362       catch (Throwable t) {
363         throw new RuntimeException(t.getMessage());
364       }
365     }
366   }
367
368   protected class ExpandedField implements EntityAdapterDefinition.CalculatedField {
369     private String expression;
370
371     public ExpandedField(String anExpression) {
372       expression = anExpression;
373     }
374
375     public Object getValue(EntityAdapter anEntityAdapter) {
376       try {
377         return ParameterExpander.expandExpression(anEntityAdapter, expression);
378       }
379       catch (Throwable t) {
380         throw new RuntimeException(t.getMessage());
381       }
382     }
383   }
384
385   protected class EvaluatedField implements EntityAdapterDefinition.CalculatedField {
386     private String expression;
387
388     public EvaluatedField(String anExpression) {
389       expression = anExpression;
390     }
391
392     public Object getValue(EntityAdapter anEntityAdapter) {
393       try {
394         return ParameterExpander.evaluateExpression(anEntityAdapter, expression);
395       }
396       catch (Throwable t) {
397         throw new RuntimeException(t.getMessage());
398       }
399     }
400   }
401
402   protected class ContentToChildrenField implements EntityAdapterDefinition.CalculatedField {
403     public Object getValue(EntityAdapter anEntityAdapter) {
404       try {
405         return anEntityAdapter.getRelation(
406                     "to_content="+anEntityAdapter.get("id"),
407                     "id",
408                     "content" );
409       }
410       catch (Throwable t) {
411         throw new RuntimeException(t.getMessage());
412       }
413     }
414   }
415   public static class MediaInfo {
416     private MediaHandler mediaHandler;
417
418     public MediaInfo(MediaHandler aHandler) {
419       mediaHandler = aHandler;
420     }
421     public String getBigIcon() {
422       if (mediaHandler == null)
423         return "bla";
424                         return mediaHandler.getBigIconName();
425     }
426
427     public String getSmallIcon() {
428       if (mediaHandler == null)
429         return "bla";
430                         return mediaHandler.getTinyIconName();
431     }
432
433     public String getMediaType() {
434       return "";
435     }
436   }
437
438   protected class MediaToMediaInfoField implements EntityAdapterDefinition.CalculatedField {
439     public Object getValue(EntityAdapter anEntityAdapter) {
440       try {
441         MediaHandler mediaHandler = MediaHelper.getHandler(((EntityUploadedMedia) anEntityAdapter.getEntity()).getMediaType());
442
443         return new MediaInfo(mediaHandler);
444       }
445       catch (Throwable t) {
446         throw new RuntimeException(t.getMessage());
447       }
448     }
449   }
450
451   protected class MediaToBigIconField implements EntityAdapterDefinition.CalculatedField {
452     public Object getValue(EntityAdapter anEntityAdapter) {
453       try {
454         return MediaHelper.getHandler(((EntityUploadedMedia) anEntityAdapter.getEntity()).getMediaType()).getBigIconName();
455       }
456       catch (Throwable t) {
457         throw new RuntimeException(t.getMessage());
458       }
459     }
460   }
461
462   protected class ContentToCommentsField implements EntityAdapterDefinition.CalculatedField {
463     private String extracondition;
464     private String order;
465
466     public ContentToCommentsField() {
467       this ( " and is_published='1'", "webdb_create");
468     }
469
470     public ContentToCommentsField(String anExtraCondition, String anOrder) {
471       order = anOrder;
472       extracondition = anExtraCondition;
473     }
474
475     public Object getValue(EntityAdapter anEntityAdapter) {
476       try {
477         return anEntityAdapter.getRelation(
478                     "to_media="+anEntityAdapter.get("id")+" " + extracondition,
479                     order,
480                     "comment" );
481       }
482       catch (Throwable t) {
483         throw new RuntimeException(t.getMessage());
484       }
485     }
486   }
487
488   protected class ContentToTopicsField implements EntityAdapterDefinition.CalculatedField {
489     private String topicCondition;
490     private String topicOrder;
491
492     public ContentToTopicsField() {
493       this(null);
494     }
495
496     public ContentToTopicsField(String aTopicCondition) {
497       this(aTopicCondition, "title");
498     }
499
500     public ContentToTopicsField(String aTopicCondition, String aTopicOrder) {
501       topicCondition = aTopicCondition;
502       topicOrder = aTopicOrder;
503     }
504
505     public Object getValue(EntityAdapter anEntityAdapter) {
506       try {
507
508
509         String condition = "cxt.content_id="+anEntityAdapter.get("id")+
510           " and cxt.topic_id=t.id";
511
512         if (topicCondition!=null && topicCondition.length()>0)
513           condition = "(" + topicCondition + ") and " + condition;
514
515         return anEntityAdapter.getComplexRelation("t", Collections.singletonList("content_x_topic cxt"),
516                     condition, topicOrder, "topic" );
517       }
518       catch (Throwable t) {
519         throw new RuntimeException(t.getMessage());
520       }
521     }
522   }
523
524   protected class ContentToMediaField implements EntityAdapterDefinition.CalculatedField {
525     private String definition;
526     private boolean published;
527
528     public ContentToMediaField(String aDefinition, boolean anOnlyPublished) {
529       definition = aDefinition;
530       published = anOnlyPublished;
531     }
532
533     public ContentToMediaField(String aDefinition) {
534       this(aDefinition, true);
535     }
536
537     public Object getValue(EntityAdapter anEntityAdapter) {
538       try {
539         String condition = "cxm.content_id="+ anEntityAdapter.get("id") +
540           " and cxm.media_id = m.id";
541
542         if (published) {
543           condition = "is_published='t' and " + condition;
544         }
545
546         List extraTables = new ArrayList();
547         extraTables.add("content_x_media cxm");
548
549         return anEntityAdapter.getComplexRelation("m", extraTables, condition, "id", definition);
550       }
551       catch (Throwable t) {
552         throw new RuntimeException(t.getMessage());
553       }
554     }
555   }
556
557   protected class ContentToFirstMediaField implements EntityAdapterDefinition.CalculatedField {
558     private String definition;
559     private boolean published;
560
561     public ContentToFirstMediaField(String aDefinition, boolean anOnlyPublished) {
562       definition = aDefinition;
563       published = anOnlyPublished;
564     }
565
566     public ContentToFirstMediaField(String aDefinition) {
567       this(aDefinition, true);
568     }
569
570     public Object getValue(EntityAdapter anEntityAdapter) {
571       try {
572         String condition = "cxm.content_id="+ anEntityAdapter.get("id") +
573           " and cxm.media_id = m.id";
574         if (published)
575           condition = "is_published='t' and " + condition;
576
577         List extraTables = new ArrayList();
578         extraTables.add("content_x_media cxm");
579
580         return anEntityAdapter.getComplexToOneRelation("m", extraTables, condition, "id", definition);
581       }
582       catch (Throwable t) {
583         throw new RuntimeException(t.getMessage());
584       }
585     }
586   }
587
588   protected class CommentToMediaField implements EntityAdapterDefinition.CalculatedField {
589     private String definition;
590     private boolean published;
591
592     public CommentToMediaField(String aDefinition, boolean anOnlyPublished) {
593       definition = aDefinition;
594       published = anOnlyPublished;
595     }
596
597     public CommentToMediaField(String aDefinition) {
598       this(aDefinition, true);
599     }
600
601     public Object getValue(EntityAdapter anEntityAdapter) {
602       try {
603
604         String condition = "cxm.comment_id = " + anEntityAdapter.get("id") + " and cxm.media_id = m.id";
605
606         if (published) {
607            condition = "is_published='t' and " + condition;
608         }
609
610         return anEntityAdapter.getComplexRelation("m", Collections.singletonList("comment_x_media cxm"),
611             condition, "id", definition);
612       }
613       catch (Throwable t) {
614         throw new RuntimeException(t.getMessage());
615       }
616     }
617   }
618
619   protected class ContentToIconField implements EntityAdapterDefinition.CalculatedField {
620     public Object getValue(EntityAdapter anEntityAdapter) {
621       String tinyIcon;
622       String iconAlt;
623
624       try {
625         tinyIcon = MirGlobal.config().getString("Producer.Icon.TinyText");
626         iconAlt = "Text";
627
628         Iterator iterator = anEntityAdapter.getIterator("to_media_video");
629         if (!iterator.hasNext()) {
630           iterator = anEntityAdapter.getIterator("to_media_audio");
631         }
632         if (!iterator.hasNext()) {
633           iterator = anEntityAdapter.getIterator("to_media_images");
634         }
635         if (!iterator.hasNext()) {
636           iterator = anEntityAdapter.getIterator("to_media_other");
637         }
638
639         if (iterator.hasNext()) {
640           EntityAdapter media = (EntityAdapter) iterator.next();
641
642           Entity mediaType = ((EntityUploadedMedia) (media.getEntity())).getMediaType();
643           MediaHandler mediaHandler = MediaHelper.getHandler(mediaType);
644
645           tinyIcon = mediaHandler.getTinyIconName();
646           iconAlt = mediaHandler.getIconAltName();
647         }
648       }
649       catch (Throwable t) {
650         logger.error("ContentToIconField: ", t);
651
652         throw new RuntimeException(t.getMessage());
653       }
654
655       Map result = new HashMap();
656       result.put("tiny_icon", MirGlobal.config().getString("Producer.ImageRoot") + "/" + tinyIcon);
657       result.put("icon_alt", iconAlt);
658
659       return result;
660     }
661   }
662
663   protected class ContentCommentCountField implements EntityAdapterDefinition.CalculatedField {
664     private String extraCondition;
665
666     public ContentCommentCountField(String anExtraCondition) {
667       super();
668
669       extraCondition = anExtraCondition;
670     }
671
672     public Object getValue(EntityAdapter anEntityAdapter) {
673       try {
674         return Integer.toString(
675             DatabaseComment.getInstance().getSize(
676                   "to_media="+anEntityAdapter.get("id")+" " + extraCondition));
677       }
678       catch (Throwable t) {
679         throw new RuntimeException(t.getMessage());
680       }
681     }
682   }
683
684   protected class HumanReadableSizeField implements EntityAdapterDefinition.CalculatedField {
685       private String fieldName;
686
687       public HumanReadableSizeField(String aFieldName) {
688         fieldName= aFieldName;
689       }
690
691       public Object getValue(EntityAdapter anEntityAdapter) {
692         try {
693           String size = (String) anEntityAdapter.get(fieldName);
694           if (size!=null)
695             return NumberUtils.humanReadableSize(Double.parseDouble(size));
696                                         return "";
697         }
698         catch (Throwable t) {
699           throw new RuntimeException(t.getMessage());
700         }
701       }
702     }
703
704
705   protected class ContentMediaCountField implements EntityAdapterDefinition.CalculatedField {
706     private String table;
707     private boolean published;
708
709     public ContentMediaCountField(String aTable, boolean anOnlyPublished) {
710       table = aTable;
711       published = anOnlyPublished;
712     }
713
714     public ContentMediaCountField(String aTable) {
715       this(aTable, true);
716     }
717
718     public Object getValue(EntityAdapter anEntityAdapter) {
719       try {
720         ArrayList extraTable = new ArrayList();
721         extraTable.add(table+" m");
722         String selectSql = "cxm.media_id=m.id and cxm.content_id="+
723           anEntityAdapter.get("id");
724         if (published)
725           selectSql+= " and m.is_published='t'";
726
727         return Integer.toString(
728             DatabaseContentToMedia.getInstance().getSize(
729               "cxm", extraTable, selectSql));
730       }
731       catch (Throwable t) {
732         throw new RuntimeException(t.getMessage());
733       }
734     }
735   }
736
737   protected class ContentToIsLockedField implements EntityAdapterDefinition.CalculatedField {
738     private ModuleContent contentModule;
739
740     public ContentToIsLockedField() {
741       contentModule = new ModuleContent();
742     }
743
744     public Object getValue(EntityAdapter anEntityAdapter) {
745       try {
746         return new Boolean(contentModule.queryArticleLock(anEntityAdapter.getEntity().getId())!=null);
747       }
748       catch (Throwable t) {
749         throw new RuntimeException(t.getMessage());
750       }
751     }
752   }
753     protected class ContentIsOriginalField implements EntityAdapterDefinition.CalculatedField {
754     public Object getValue(EntityAdapter anEntityAdapter) throws MirLocalizerFailure {
755       try {
756
757         //ML: add check on article type
758         boolean result = (anEntityAdapter.get("parent")==null);
759
760         return new Boolean(result);
761       }
762       catch (Throwable t) {
763         throw new MirLocalizerFailure(t);
764       }
765     }
766   }
767
768   protected class ContentToOriginalField implements EntityAdapterDefinition.CalculatedField {
769     public Object getValue(EntityAdapter anEntityAdapter) throws MirLocalizerFailure {
770       try {
771         if (anEntityAdapter.get("parent")!=null)
772           return anEntityAdapter.get("parent");
773                                 return anEntityAdapter;
774       }
775       catch (Throwable t) {
776         throw new MirLocalizerFailure(t);
777       }
778     }
779   }
780
781   protected class ContentToTranslationsField implements EntityAdapterDefinition.CalculatedField {
782     public Object getValue(EntityAdapter anEntityAdapter) {
783       try {
784         return anEntityAdapter.getRelation(
785                     "is_published='t' and to_content="+anEntityAdapter.get("id"),
786                     "id",
787                     "content" );
788       }
789       catch (Throwable t) {
790         throw new RuntimeException(t.getMessage());
791       }
792     }
793   }
794
795   protected class ContentToLanguageNameField implements EntityAdapterDefinition.CalculatedField {
796     public Object getValue(EntityAdapter anEntityAdapter) throws MirLocalizerFailure {
797       try {
798         String result = "";
799         EntityAdapter language = (EntityAdapter) anEntityAdapter.get("language");
800         if (language != null) {
801           if (language.get("code").equals("ot")) {
802             result = ((String) anEntityAdapter.get("subtitle")).trim();
803             if (result == null || result.equals(""))
804               result = (String) language.get("name");
805           } else {
806             result = (String) language.get("name");
807           }
808         }
809
810         return result;
811       }
812       catch (Throwable t) {
813         throw new MirLocalizerFailure(t);
814       }
815     }
816   }
817
818   protected class ContentToTranslationFunction implements Generator.Function {
819     private EntityAdapter target;
820     private String targetId;
821     private String targetLanguageId;
822
823     public ContentToTranslationFunction(EntityAdapter aTarget) {
824       target = aTarget;
825       targetId = (String) target.get("id");
826       targetLanguageId = (String) target.get("to_language");
827     }
828
829     public Object perform(List aParameters) throws GeneratorExc, GeneratorFailure {
830       if (aParameters.size()!=1 || !(aParameters.get(0) instanceof String))
831         throw new GeneratorExc("1 string parameter expected");
832
833       try {
834         String language = (String) aParameters.get(0);
835         String languageId = languageModule.languageIdForCode(language);
836         Object result = null;
837
838         if (languageId != null && !targetLanguageId.equals(languageId)) {
839           result = target.getToOneRelation(
840               "is_published='t' and to_content=" + targetId + " and to_language='" + JDBCStringRoutines.escapeStringLiteral(languageId) + "'",
841               "id", "content");
842         }
843
844         if (result == null)
845           result = target;
846
847         return result;
848       }
849       catch (Throwable t) {
850         t.printStackTrace(System.out);
851         throw new GeneratorFailure(t);
852       }
853     }
854   }
855
856   protected class ContentToTranslationField implements EntityAdapterDefinition.CalculatedField {
857     public Object getValue(EntityAdapter anEntityAdapter) throws MirLocalizerFailure {
858       try {
859         return new ContentToTranslationFunction((EntityAdapter) anEntityAdapter.get("to_original"));
860       }
861       catch (Throwable t) {
862         throw new MirLocalizerFailure(t);
863       }
864     }
865   }
866
867   protected static class CommentStatusCountField implements EntityAdapterDefinition.CalculatedField {
868     public Object getValue(EntityAdapter anEntityAdapter) {
869       return new CommentStatusCountField2(anEntityAdapter);
870     }
871   }
872
873   public static class CommentStatusCountField2 {
874     private final EntityAdapter comment;
875     private final ModuleCommentStatus mcs = new ModuleCommentStatus();
876
877     CommentStatusCountField2(EntityAdapter anEntityAdapter) {
878       comment = anEntityAdapter;
879     }
880
881     public String get(String aCommentStatus) {
882       try {
883         return Integer.toString(
884             DatabaseComment.getInstance().getSize(
885                   "to_media=" + comment.get("id") + " and is_published='1' and to_comment_status = " +
886                       mcs.commentStatusIdForName(aCommentStatus)));
887       }
888       catch (Exception e) {
889         return "0";
890       }
891     }
892   }
893 }
894