597248bdc025068c04b7683afa68f9fece464d0b
[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 the com.oreilly.servlet library, any library
22  * licensed under the Apache Software License, The Sun (tm) Java Advanced
23  * Imaging library (JAI), The Sun JIMI library (or with modified versions of
24  * the above that use the same license as the above), and distribute linked
25  * combinations including the two.  You must obey the GNU General Public
26  * License in all respects for all of the code used other than the above
27  * mentioned libraries.  If you modify this file, you may extend this exception
28  * to your version of the file, but you are not obligated to do so.  If you do
29  * not wish to do so, delete this exception statement from your version.
30  */
31
32 package mircoders.localizer.basic;
33
34 import java.util.HashMap;\r
35 import java.util.Iterator;\r
36 import java.util.List;\r
37 import java.util.Map;\r
38 import java.util.Vector;\r
39 \r
40 import mir.config.MirPropertiesConfiguration;\r
41 import mir.entity.Entity;\r
42 import mir.entity.adapter.EntityAdapter;\r
43 import mir.entity.adapter.EntityAdapterDefinition;\r
44 import mir.entity.adapter.EntityAdapterModel;\r
45 import mir.log.LoggerWrapper;\r
46 import mir.media.MediaHelper;\r
47 import mir.media.MirMedia;\r
48 import mir.util.ParameterExpander;\r
49 import mir.util.RewindableIterator;\r
50 import mircoders.entity.EntityUploadedMedia;\r
51 import mircoders.global.MirGlobal;\r
52 import mircoders.localizer.MirAdminInterfaceLocalizer;\r
53 import mircoders.localizer.MirDataModelLocalizer;\r
54 import mircoders.localizer.MirLocalizerExc;\r
55 import mircoders.localizer.MirLocalizerFailure;\r
56 import mircoders.storage.DatabaseArticleType;\r
57 import mircoders.storage.DatabaseAudio;\r
58 import mircoders.storage.DatabaseBreaking;\r
59 import mircoders.storage.DatabaseComment;\r
60 import mircoders.storage.DatabaseCommentStatus;\r
61 import mircoders.storage.DatabaseContent;\r
62 import mircoders.storage.DatabaseImageType;\r
63 import mircoders.storage.DatabaseImages;\r
64 import mircoders.storage.DatabaseLanguage;\r
65 import mircoders.storage.DatabaseMedia;\r
66 import mircoders.storage.DatabaseMediaType;\r
67 import mircoders.storage.DatabaseMediafolder;\r
68 import mircoders.storage.DatabaseMessages;\r
69 import mircoders.storage.DatabaseOther;\r
70 import mircoders.storage.DatabaseTopics;\r
71 import mircoders.storage.DatabaseUploadedMedia;\r
72 import mircoders.storage.DatabaseUsers;\r
73 import mircoders.storage.DatabaseVideo;
74
75 public class MirBasicDataModelLocalizer implements MirDataModelLocalizer {
76   private EntityAdapterModel model;
77   protected LoggerWrapper logger;
78   protected MirPropertiesConfiguration configuration;
79
80   public MirBasicDataModelLocalizer() throws MirLocalizerFailure, MirLocalizerExc {
81     model=null;
82     logger = new LoggerWrapper("Localizer.DataModel");
83
84     try {
85       configuration = MirPropertiesConfiguration.instance();
86     }
87     catch (Throwable e) {
88       throw new MirLocalizerFailure("Can't get configuration: " + e.getMessage(), e);
89     }
90   }
91
92   public EntityAdapterModel adapterModel() throws MirLocalizerFailure {
93     if (model==null)
94       model = buildModel();
95
96     return model;
97   };
98
99   protected void constructContentAdapterDefinition(EntityAdapterDefinition anEntityAdapterDefinition) throws MirLocalizerFailure {
100     try {
101       anEntityAdapterDefinition.addDBDateField("creationdate", "webdb_create");
102       anEntityAdapterDefinition.addDBDateField("changedate", "webdb_lastchange");
103       anEntityAdapterDefinition.addMirDateField("date", "date");
104       anEntityAdapterDefinition.addCalculatedField("to_topics", new ContentToTopicsField());
105       anEntityAdapterDefinition.addCalculatedField("to_comments", new ContentToCommentsField());
106       anEntityAdapterDefinition.addCalculatedField("language", new ContentToLanguageField());
107
108       anEntityAdapterDefinition.addCalculatedField("commentcount", new ContentCommentCountField(" and is_published='1'"));
109       anEntityAdapterDefinition.addCalculatedField("fullcommentcount", new ContentCommentCountField(""));
110
111       anEntityAdapterDefinition.addCalculatedField("to_uploaded_media", new ContentToMediaField( "uploadedMedia" ));
112       anEntityAdapterDefinition.addCalculatedField("to_media_images",  new ContentToMediaField( "image" ));
113       anEntityAdapterDefinition.addCalculatedField("to_media_audio", new ContentToMediaField( "audio" ));
114       anEntityAdapterDefinition.addCalculatedField("to_media_video", new ContentToMediaField( "video" ));
115       anEntityAdapterDefinition.addCalculatedField("to_media_other", new ContentToMediaField( "otherMedia" ));
116       anEntityAdapterDefinition.addCalculatedField("to_all_uploaded_media", new ContentToMediaField( "uploadedMedia", false));
117       anEntityAdapterDefinition.addCalculatedField("to_all_media_images",  new ContentToMediaField( "image", false));
118       anEntityAdapterDefinition.addCalculatedField("to_all_media_audio", new ContentToMediaField( "audio", false));
119       anEntityAdapterDefinition.addCalculatedField("to_all_media_video", new ContentToMediaField( "video", false));
120       anEntityAdapterDefinition.addCalculatedField("to_all_media_other", new ContentToMediaField( "otherMedia", false));
121       anEntityAdapterDefinition.addCalculatedField("to_media_icon", new ContentToIconField());
122
123       anEntityAdapterDefinition.addCalculatedField("article_type", new ContentToArticleTypeField());
124
125       anEntityAdapterDefinition.addCalculatedField("description_parsed", new FilteredField("description"));
126       anEntityAdapterDefinition.addCalculatedField("content_data_parsed", new FilteredField("content_data"));
127
128       anEntityAdapterDefinition.addCalculatedField("children", new ContentToChildrenField());
129       anEntityAdapterDefinition.addCalculatedField("parent", new ContentToParentField());
130
131       anEntityAdapterDefinition.addCalculatedField("publicurl", new ExpandedField(configuration.getString("Article.PublicUrl")));
132
133       anEntityAdapterDefinition.addCalculatedField("operations",
134           new EntityToSimpleOperationsField(MirGlobal.localizer().adminInterface().simpleArticleOperations()));
135     }
136     catch (Throwable t) {
137       throw new MirLocalizerFailure(t.getMessage(), t);
138     }
139   }
140
141   protected void constructCommentAdapterDefinition(EntityAdapterDefinition anEntityAdapterDefinition) throws MirLocalizerFailure {
142     try {
143       anEntityAdapterDefinition.addDBDateField("creationdate", "webdb_create");
144       anEntityAdapterDefinition.addCalculatedField("to_content", new CommentToContentField());
145       anEntityAdapterDefinition.addCalculatedField("status", new CommentToStatusField());
146
147       anEntityAdapterDefinition.addCalculatedField("to_uploaded_media", new CommentToMediaField( "uploadedMedia" ));
148       anEntityAdapterDefinition.addCalculatedField("to_media_images",  new CommentToMediaField( "image" ));
149       anEntityAdapterDefinition.addCalculatedField("to_media_audio", new CommentToMediaField( "audio" ));
150       anEntityAdapterDefinition.addCalculatedField("to_media_video", new CommentToMediaField( "video" ));
151       anEntityAdapterDefinition.addCalculatedField("to_media_other", new CommentToMediaField( "otherMedia" ));
152       anEntityAdapterDefinition.addCalculatedField("to_all_uploaded_media", new CommentToMediaField( "uploadedMedia", false));
153       anEntityAdapterDefinition.addCalculatedField("to_all_media_images",  new CommentToMediaField( "image", false));
154       anEntityAdapterDefinition.addCalculatedField("to_all_media_audio", new CommentToMediaField( "audio", false));
155       anEntityAdapterDefinition.addCalculatedField("to_all_media_video", new CommentToMediaField( "video", false));
156       anEntityAdapterDefinition.addCalculatedField("to_all_media_other", new CommentToMediaField( "otherMedia", false));
157
158       anEntityAdapterDefinition.addCalculatedField("publicurl", new ExpandedField(configuration.getString("Comment.PublicUrl")));
159
160       anEntityAdapterDefinition.addCalculatedField("description_parsed", new FilteredField("description"));
161       anEntityAdapterDefinition.addCalculatedField("operations",
162           new EntityToSimpleOperationsField(MirGlobal.localizer().adminInterface().simpleCommentOperations()));
163     }
164     catch (Throwable t) {
165       throw new MirLocalizerFailure(t.getMessage(), t);
166     }
167   }
168
169   protected EntityAdapterModel buildModel() throws MirLocalizerFailure {
170     EntityAdapterModel result = new EntityAdapterModel();
171
172     try {
173       EntityAdapterDefinition definition;
174
175       definition = new EntityAdapterDefinition();
176       constructContentAdapterDefinition( definition );
177       result.addMapping( "content", DatabaseContent.getInstance(), definition);
178
179       definition = new EntityAdapterDefinition();
180       constructCommentAdapterDefinition( definition );
181       result.addMapping( "comment", DatabaseComment.getInstance(), definition);
182
183       result.addMapping( "articleType", DatabaseArticleType.getInstance(), new EntityAdapterDefinition());
184       result.addMapping( "commentStatus", DatabaseCommentStatus.getInstance(), new EntityAdapterDefinition());
185
186       definition = new EntityAdapterDefinition();
187       definition.addDBDateField("creationdate", "webdb_create");
188       result.addMapping( "breakingNews", DatabaseBreaking.getInstance(), definition);
189
190       result.addMapping( "imageType", DatabaseImageType.getInstance(), new EntityAdapterDefinition());
191       result.addMapping( "language", DatabaseLanguage.getInstance(), new EntityAdapterDefinition());
192       result.addMapping( "mediaFolder", DatabaseMediafolder.getInstance(), new EntityAdapterDefinition());
193       result.addMapping( "mediaType", DatabaseMediaType.getInstance(), new EntityAdapterDefinition());
194       result.addMapping( "internalMessage", DatabaseMessages.getInstance(), new EntityAdapterDefinition());
195       result.addMapping( "topic", DatabaseTopics.getInstance(), new EntityAdapterDefinition());
196       result.addMapping( "user", DatabaseUsers.getInstance(), new EntityAdapterDefinition());
197       result.addMapping( "media", DatabaseMedia.getInstance(), new EntityAdapterDefinition());
198       result.addMapping( "uploadedMedia", DatabaseUploadedMedia.getInstance(), new EntityAdapterDefinition());
199       result.addMapping( "image", DatabaseImages.getInstance(), new EntityAdapterDefinition());
200       result.addMapping( "audio", DatabaseAudio.getInstance(), new EntityAdapterDefinition());
201       result.addMapping( "video", DatabaseVideo.getInstance(), new EntityAdapterDefinition());
202       result.addMapping( "otherMedia", DatabaseOther.getInstance(), new EntityAdapterDefinition());
203     }
204     catch (Throwable t) {
205       throw new MirLocalizerFailure(t.getMessage(), t);
206     }
207
208     return result;
209   }
210
211   protected class CommentToContentField implements EntityAdapterDefinition.CalculatedField {
212     public Object getValue(EntityAdapter anEntityAdapter) {
213       try {
214         return anEntityAdapter.getToOneRelation(
215                     "id="+anEntityAdapter.get("to_media"),
216                     "id",
217                     "content" );
218       }
219       catch (Throwable t) {
220         throw new RuntimeException(t.getMessage());
221       }
222     }
223   }
224
225   protected class CommentToStatusField implements EntityAdapterDefinition.CalculatedField {
226     public Object getValue(EntityAdapter anEntityAdapter) {
227       try {
228         return anEntityAdapter.getToOneRelation(
229                     "id="+anEntityAdapter.get("to_comment_status"),
230                     "id",
231                     "commentStatus" );
232       }
233       catch (Throwable t) {
234         throw new RuntimeException(t.getMessage());
235       }
236     }
237   }
238
239   protected class EntityToSimpleOperationsField implements EntityAdapterDefinition.CalculatedField {
240     private List operations;
241
242     public EntityToSimpleOperationsField(List anOperations) {
243       operations = anOperations;
244     }
245
246     public Object getValue(EntityAdapter anEntityAdapter) {
247       try {
248         Iterator i = operations.iterator();
249         List availableOperations = new Vector();
250
251         while (i.hasNext()) {
252           MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation =
253             (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) i.next();
254
255           if (operation.isAvailable(anEntityAdapter)) {
256             availableOperations.add(operation.getName());
257           }
258         };
259
260         return availableOperations;
261       }
262       catch (Throwable t) {
263         throw new RuntimeException(t.getMessage());
264       }
265     }
266   }
267
268   protected class FilteredField implements EntityAdapterDefinition.CalculatedField {
269     private String fieldName;
270
271     public FilteredField(String aFieldName) {
272       fieldName = aFieldName;
273     }
274
275     public Object getValue(EntityAdapter anEntityAdapter) {
276       try {
277         if (anEntityAdapter.get("is_html")!=null && anEntityAdapter.get("is_html").equals("1")) {
278           return anEntityAdapter.get(fieldName);
279         }
280         else {
281           return MirGlobal.localizer().producerAssistant().filterText((String) anEntityAdapter.get(fieldName));
282         }
283       }
284       catch (Throwable t) {
285         throw new RuntimeException(t.getMessage());
286       }
287     }
288   }
289
290   protected class ExpandedField implements EntityAdapterDefinition.CalculatedField {
291     private String expression;
292
293     public ExpandedField(String anExpression) {
294       expression = anExpression;
295     }
296
297     public Object getValue(EntityAdapter anEntityAdapter) {
298       try {
299         return ParameterExpander.expandExpression(anEntityAdapter, expression);
300       }
301       catch (Throwable t) {
302         throw new RuntimeException(t.getMessage());
303       }
304     }
305   }
306
307   protected class EvaluatedField implements EntityAdapterDefinition.CalculatedField {
308     private String expression;
309
310     public EvaluatedField(String anExpression) {
311       expression = anExpression;
312     }
313
314     public Object getValue(EntityAdapter anEntityAdapter) {
315       try {
316         return ParameterExpander.evaluateExpression(anEntityAdapter, expression);
317       }
318       catch (Throwable t) {
319         throw new RuntimeException(t.getMessage());
320       }
321     }
322   }
323
324   protected class ContentToParentField implements EntityAdapterDefinition.CalculatedField {
325     public Object getValue(EntityAdapter anEntityAdapter) {
326       try {
327         logger.debug("ContentToParentField.getValue");
328         return anEntityAdapter.getToOneRelation(
329                     "id="+anEntityAdapter.get("to_content"),
330                     "id",
331                     "content" );
332       }
333       catch (Throwable t) {
334         throw new RuntimeException(t.getMessage());
335       }
336     }
337   }
338
339   protected class ContentToChildrenField implements EntityAdapterDefinition.CalculatedField {
340     public Object getValue(EntityAdapter anEntityAdapter) {
341       try {
342         return anEntityAdapter.getRelation(
343                     "to_content="+anEntityAdapter.get("id"),
344                     "id",
345                     "content" );
346       }
347       catch (Throwable t) {
348         throw new RuntimeException(t.getMessage());
349       }
350     }
351   }
352
353   protected class ContentToLanguageField implements EntityAdapterDefinition.CalculatedField {
354     public Object getValue(EntityAdapter anEntityAdapter) {
355       try {
356         return anEntityAdapter.getToOneRelation(
357                     "id="+anEntityAdapter.get("to_language"),
358                     "id",
359                     "language" );
360       }
361       catch (Throwable t) {
362         throw new RuntimeException(t.getMessage());
363       }
364     }
365   }
366
367   protected class ContentToArticleTypeField implements EntityAdapterDefinition.CalculatedField {
368     public Object getValue(EntityAdapter anEntityAdapter) {
369       try {
370         return anEntityAdapter.getToOneRelation(
371                     "id="+anEntityAdapter.get("to_article_type"),
372                     "id",
373                     "articleType" );
374       }
375       catch (Throwable t) {
376         throw new RuntimeException(t.getMessage());
377       }
378     }
379   }
380
381   protected class ContentToCommentsField implements EntityAdapterDefinition.CalculatedField {
382     public Object getValue(EntityAdapter anEntityAdapter) {
383       try {
384         return anEntityAdapter.getRelation(
385                     "to_media="+anEntityAdapter.get("id")+" and is_published='1'",
386                     "webdb_create",
387                     "comment" );
388       }
389       catch (Throwable t) {
390         throw new RuntimeException(t.getMessage());
391       }
392     }
393   }
394
395   protected class ContentToTopicsField implements EntityAdapterDefinition.CalculatedField {
396     public Object getValue(EntityAdapter anEntityAdapter) {
397       try {
398         return anEntityAdapter.getRelation(
399                     "exists (select * from content_x_topic where content_id="+anEntityAdapter.get("id")+" and topic_id=id)",
400                     "title",
401                     "topic" );
402       }
403       catch (Throwable t) {
404         throw new RuntimeException(t.getMessage());
405       }
406     }
407   }
408
409   protected class ContentToMediaField implements EntityAdapterDefinition.CalculatedField {
410     private String definition;
411     private boolean published;
412
413     public ContentToMediaField(String aDefinition, boolean anOnlyPublished) {
414       definition = aDefinition;
415       published = anOnlyPublished;
416     }
417
418     public ContentToMediaField(String aDefinition) {
419       this(aDefinition, true);
420     }
421
422     public Object getValue(EntityAdapter anEntityAdapter) {
423       try {
424         String condition = "exists (select * from content_x_media where content_id="+anEntityAdapter.get("id")+" and media_id=id)";
425         if (published)
426           condition = "is_published='t' and " + condition;
427         return anEntityAdapter.getRelation(
428            condition,
429           "id",
430           definition);
431       }
432       catch (Throwable t) {
433         throw new RuntimeException(t.getMessage());
434       }
435     }
436   }
437
438   protected class CommentToMediaField implements EntityAdapterDefinition.CalculatedField {
439     private String definition;
440     private boolean published;
441
442     public CommentToMediaField(String aDefinition, boolean anOnlyPublished) {
443       definition = aDefinition;
444       published = anOnlyPublished;
445     }
446
447     public CommentToMediaField(String aDefinition) {
448       this(aDefinition, true);
449     }
450
451     public Object getValue(EntityAdapter anEntityAdapter) {
452       try {
453         String condition = "exists (select * from comment_x_media where comment_id="+anEntityAdapter.get("id")+" and media_id=id)";
454         if (published)
455           condition = "is_published='t' and " + condition;
456         return anEntityAdapter.getRelation(
457            condition,
458           "id",
459           definition);
460       }
461       catch (Throwable t) {
462         throw new RuntimeException(t.getMessage());
463       }
464     }
465   }
466
467   protected class ContentToIconField implements EntityAdapterDefinition.CalculatedField {
468     public Object getValue(EntityAdapter anEntityAdapter) {
469       EntityAdapter media;
470       Entity mediaType;
471       RewindableIterator iterator;
472       Map result;
473       MirMedia mediaHandler;
474       String tinyIcon;
475       String iconAlt;
476
477       try {
478         iterator = (RewindableIterator) (anEntityAdapter.get("to_uploaded_media"));
479         iterator.rewind();
480
481         tinyIcon = MirGlobal.config().getString("Producer.Icon.TinyText");
482         iconAlt = "Text";
483
484         if (iterator.hasNext()) {
485           media = (EntityAdapter) iterator.next();
486
487           mediaType = ((EntityUploadedMedia) (media.getEntity())).getMediaType();
488           mediaHandler = MediaHelper.getHandler( mediaType );
489
490           if (mediaHandler.isVideo()) {
491             tinyIcon = MirGlobal.config().getString("Producer.Icon.TinyVideo");
492             iconAlt = "Video";
493           }
494           else if (mediaHandler.isAudio()) {
495             tinyIcon = MirGlobal.config().getString("Producer.Icon.TinyAudio");
496             iconAlt = "Audio";
497           }
498           else if (mediaHandler.isImage()) {
499             tinyIcon = MirGlobal.config().getString("Producer.Icon.TinyImage");
500             iconAlt = "Image";
501           }
502           else {
503             tinyIcon = mediaHandler.getTinyIconName();
504             iconAlt = mediaHandler.getIconAltName();
505           }
506
507         }
508       }
509       catch (Throwable t) {
510         logger.error("ContentToIconField: " +t.getMessage());
511         throw new RuntimeException(t.getMessage());
512       }
513
514       result = new HashMap();
515       result.put("tiny_icon", MirGlobal.config().getString("Producer.ImageRoot") + "/" + tinyIcon);
516       result.put("icon_alt", iconAlt);
517
518       return result;
519     }
520   }
521
522   protected class ContentCommentCountField implements EntityAdapterDefinition.CalculatedField {
523     private String extraCondition;
524
525     public ContentCommentCountField(String anExtraCondition) {
526       super();
527
528       extraCondition = anExtraCondition;
529     }
530
531     public Object getValue(EntityAdapter anEntityAdapter) {
532       try {
533         return Integer.toString(
534             DatabaseComment.getInstance().getSize(
535                   "to_media="+anEntityAdapter.get("id")+" " + extraCondition));
536       }
537       catch (Throwable t) {
538         throw new RuntimeException(t.getMessage());
539       }
540     }
541   }
542 }