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