merge media InputStream changes from MIR_1_0 branch
[mir.git] / source / mircoders / entity / EntityContent.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.entity;
33
34 import java.lang.*;
35 import java.io.*;
36 import java.util.*;
37 import java.sql.*;
38 import java.lang.reflect.*;
39
40 import freemarker.template.*;
41
42 import mir.entity.*;
43 import mir.misc.*;
44 import mir.media.*;
45 import mir.storage.*;
46
47 import mircoders.storage.*;
48
49 /**
50  * this class implements mapping of one line of the database table content
51  * to a java object
52  *
53  * @version $Id: EntityContent.java,v 1.11 2002/11/04 04:35:21 mh Exp $
54  * @author mir-coders group
55  *
56  */
57
58
59 public class EntityContent extends Entity
60 {
61
62   String mirconf_extLinkName  = MirConfig.getProp("Producer.ExtLinkName");
63   String mirconf_intLinkName  = MirConfig.getProp("Producer.IntLinkName");
64   String mirconf_mailLinkName = MirConfig.getProp("Producer.MailLinkName");
65   String mirconf_imageRoot    = MirConfig.getProp("Producer.ImageRoot");
66
67   //this should always be transient i.e it can never be stored in the db
68   //or ObjectStore. (so the ObjectStore should only be caching what comes
69   //directly out of the DB. @todo confirm this with rk. -mh
70   HashMap _entCache = new HashMap();
71   Boolean _hasMedia = null;
72
73         // constructors
74
75         public EntityContent()
76         {
77                 super();
78     //content_data is now filed-type "text"
79                 //streamedInput = new ArrayList();
80                 //streamedInput.add("content_data");
81         }
82
83         public EntityContent(StorageObject theStorage) {
84                 this();
85                 setStorage(theStorage);
86         }
87
88         //
89         // methods
90
91  /**
92         * set is_produced flag for the article
93         */
94
95         public void setProduced(boolean yesno) throws StorageObjectException
96         {
97                 String value = (yesno) ? "1":"0";
98                 if (value.equals( getValue("is_produced") )) return;
99
100     Connection con=null;Statement stmt=null;
101     String sql = "update content set is_produced='" + value + "' where id='" + getId()+"'";
102                 try {
103                         con = theStorageObject.getPooledCon();
104                         /** @todo should be preparedStatement: faster!! */
105                         stmt = con.createStatement();
106                         theStorageObject.executeUpdate(stmt,sql);
107                 } catch (StorageObjectException e) {
108             throwStorageObjectException(e, "\n -- set produced failed");
109                 } catch (SQLException e) {
110             throwStorageObjectException(e, "\n -- set produced failed");
111                 } finally {
112                         theStorageObject.freeConnection(con,stmt);
113                 }
114         }
115
116
117  /**
118         * make openposting to newswire
119         */
120
121         public void newswire() throws StorageObjectException
122         {
123                 String sql = "update content set to_article_type='1', is_produced='0' where id='" + getId()+"'";
124                 try {
125                                 theStorageObject.executeUpdate(sql);
126                 } catch (StorageObjectException e) {
127             throwStorageObjectException(e, "\n -- newswire failed");
128                 } catch (SQLException e) {
129             throwStorageObjectException(e, "\n -- newswire failed");
130                 }
131         }
132
133
134  /**
135         * dettach from media
136         */
137         public void dettach(String cid,String mid) throws StorageObjectException
138         {
139                 if (mid!=null){
140                         try{
141                                 DatabaseContentToMedia.getInstance().delete(cid,mid);
142                         } catch (Exception e){
143                 throwStorageObjectException(e, "\n -- failed to get instance");
144                         }
145                         //set Content to unproduced
146                         setProduced(false);
147                 }
148         }
149
150  /**
151         * attach to media
152         */
153
154         public void attach(String mid) throws StorageObjectException
155         {
156                 if (mid!=null) {
157                         //write media-id mid and content-id in table content_x_media
158                         try{
159                                 DatabaseContentToMedia.getInstance().addMedia(getId(),mid);
160                         } catch(StorageObjectException e){
161                                 throwStorageObjectException(e, "attach: could not get the instance");
162                         }
163                         //set Content to unproduced
164                         setProduced(false);
165                 }       else {
166                         theLog.printError("EntityContent: attach without mid");
167                 }
168         }
169
170         /**
171          * overridden method getValue to include formatted date into every
172          * entityContent
173          */
174
175         public String getValue(String field)
176   {
177     String returnField = null;
178     if (field!=null)
179     {
180       if (field.equals("date_formatted") || field.equals("webdb_create_short") )
181       {
182                   if (hasValueForField("date"))
183         returnField = StringUtil.webdbDate2readableDate(getValue("webdb_create"));
184                 }
185       else if (field.equals("description_parsed"))
186         returnField = getDescriptionParsed();
187       else if (field.equals("description_sentence"))
188         returnField = getDescriptionSentence();
189       else if (field.equals("content_data_parsed"))
190         returnField = getContentDataParsed();
191       else
192         return super.getValue(field);
193     }
194     return returnField;
195         }
196
197   public TemplateModel get(java.lang.String key) throws TemplateModelException
198   {
199     if (key!=null) {
200       if (_entCache.containsKey(key)) {
201         return (TemplateModel)_entCache.get(key);
202       }
203       if (key.equals("to_comments")) {
204         try {
205           _entCache.put(key, getComments());
206           return (TemplateModel)_entCache.get(key);
207         } catch (Exception ex) {
208           theLog.printWarning("-- getComments: could not fetch data " + ex.toString());
209           throw new TemplateModelException(ex.toString());
210         }
211       }
212       if (key.equals("to_media_images")) {
213         try {
214           _entCache.put(key, getImagesForContent());
215           return (TemplateModel)_entCache.get(key);
216         }
217         catch (Exception ex) {
218           theLog.printWarning("-- getImagesForContent: could not fetch data " + ex.toString());
219           throw new TemplateModelException(ex.toString());
220         }
221       }
222       if (key.equals("to_media_audio")) {
223         try {
224           _entCache.put(key, getAudioForContent());
225           return (TemplateModel)_entCache.get(key);
226         }
227         catch (Exception ex) {
228           theLog.printWarning("-- getAudioForContent: could not fetch data " + ex.toString());
229           throw new TemplateModelException(ex.toString());
230         }
231       }
232       if (key.equals("to_media_video")) {
233         try {
234           _entCache.put(key, getVideoForContent());
235           return (TemplateModel)_entCache.get(key);
236         }
237         catch (Exception ex) {
238           theLog.printWarning("-- getVideoForContent: could not fetch data " + ex.toString());
239           throw new TemplateModelException(ex.toString());
240         }
241       }
242       if (key.equals("to_media_other")) {
243         try {
244           _entCache.put(key, getOtherMediaForContent());
245           return (TemplateModel)_entCache.get(key);
246         }
247         catch (Exception ex) {
248           theLog.printWarning("-- getOtherMediaForContent: could not fetch data " + ex.toString());
249           throw new TemplateModelException(ex.toString());
250         }
251       }
252       else if (key.equals("to_media_icon")) {
253         try {
254           _entCache.put(key, getUploadedMediaForNewswire());
255           return (TemplateModel)_entCache.get(key);
256         }
257         catch (Exception ex) {
258           theLog.printWarning("-- getUploadedMediaForNewswire: could not fetch data " + ex.toString());
259           throw new TemplateModelException(ex.toString());
260         }
261       }
262       else if (key.equals("to_topics")) {
263         try {
264           _entCache.put(key, 
265                         DatabaseContentToTopics.getInstance().getTopics(this));
266           return (TemplateModel)_entCache.get(key);
267         }
268         catch (Exception ex) {
269           theLog.printWarning("-- getTopics: could not fetch data " + ex.toString());
270           throw new TemplateModelException(ex.toString());
271         }
272       }
273       else {
274         return new SimpleScalar(getValue(key));
275       }
276
277     }
278     return null;
279   }
280
281
282
283
284         /**
285          * overridden method setValues to patch creator_main_url
286          */
287         public void setValues(HashMap theStringValues) {
288                 if (theStringValues != null) {
289                         if (theStringValues.containsKey("creator_main_url")){
290                                 if (((String)theStringValues.get("creator_main_url")).equalsIgnoreCase("http://")){
291                                         theStringValues.remove("creator_main_url");
292         } else if (!((String)theStringValues.get("creator_main_url")).startsWith("http://")){
293           theStringValues.put("creator_main_url","http://"+((String)theStringValues.get("creator_main_url")));
294         }
295       }
296                 }
297                 super.setValues(theStringValues);
298         }
299
300
301   private String getContentDataParsed() {
302     String returnField = getValue("content_data");
303     if ((returnField!=null) && (returnField.length()>0) ) {
304       returnField=StringUtil.deleteForbiddenTags(returnField);
305       //create http-links and email-links
306       if (getValue("is_html").equals("0")) {
307         returnField = StringUtil.createHTML(returnField,mirconf_imageRoot,
308                                             mirconf_mailLinkName,mirconf_extLinkName,
309                                             mirconf_intLinkName);
310       }
311       // commented this out as I don't think it necessary as we don't
312       // "encodeHTML" in the first place anymore.. -mh 2002.07.19
313       //returnField = StringUtil.decodeHTMLinTags(returnField);
314     }
315     return returnField;
316   }
317
318   private String getDescriptionSentence() {
319     String returnField = getValue("description");
320     if (returnField != null && returnField.length()>0) {
321        returnField = StringUtil.removeHTMLTags(returnField);
322        int endOfFirstSentence=StringUtil.findEndOfSentence(returnField,0);
323        if (endOfFirstSentence > 0){
324          returnField = returnField.substring(0,endOfFirstSentence);
325        }
326     }
327     return returnField;
328   }
329
330   private String getDescriptionParsed() {
331     String returnField = getValue("description");
332     if (returnField != null && returnField.length()>0) {
333       returnField = StringUtil.deleteForbiddenTags(returnField);
334       if (getValue("is_html").equals("0")) {
335         returnField = StringUtil.createHTML(returnField,mirconf_imageRoot,
336                                             mirconf_mailLinkName,mirconf_extLinkName,
337                                             mirconf_intLinkName);
338       }
339       returnField = StringUtil.decodeHTMLinTags(returnField);
340     }
341     return returnField;
342   }
343
344         /**
345          * fetches all the comments belonging to an article
346          *
347          * @return freemarker.template.SimpleList
348          */
349         private EntityList getComments() throws StorageObjectException {
350                 return ((DatabaseContent)theStorageObject).getComments(this);
351         }
352
353   // @todo this needs to optimized. expensive SQL
354   private SimpleHash getUploadedMediaForNewswire()
355     throws StorageObjectException, TemplateModelException
356   {
357     // fetching/setting the images
358     // return to_media_icons
359     String        tinyIcon = null, iconAlt = null;
360     MirMedia      mediaHandler = null;
361     EntityUploadedMedia uploadedMedia;
362     Entity        mediaType;
363     SimpleHash    returnHash = new SimpleHash();
364
365     EntityList upMediaEntityList =
366                     DatabaseContentToMedia.getInstance().getUploadedMedia(this);
367     if (upMediaEntityList!=null && upMediaEntityList.getCount()>=1) {
368
369       for (int n=0; n < upMediaEntityList.size();n++) {
370         uploadedMedia = (EntityUploadedMedia)upMediaEntityList.elementAt(n);
371         mediaType = uploadedMedia.getMediaType();
372         try {
373           mediaHandler = MediaHelper.getHandler( mediaType );
374         } catch (MirMediaException ex) {
375           throw new TemplateModelException(ex.toString());
376         }
377         //the "best" media type to show
378         if (mediaHandler.isVideo()) {
379           tinyIcon = MirConfig.getProp("Producer.Icon.TinyVideo");
380           iconAlt = "Video";
381           break;
382         } else if (mediaHandler.isAudio()) {
383           tinyIcon = MirConfig.getProp("Producer.Icon.TinyAudio");
384           iconAlt = "Audio";
385         } else if (tinyIcon == null && !mediaHandler.isImage()) {
386           tinyIcon = mediaHandler.getTinyIconName();
387           iconAlt = mediaHandler.getIconAltName();
388         }
389
390       }
391       //it only has image(s)
392       if (tinyIcon == null) {
393         tinyIcon = MirConfig.getProp("Producer.Icon.TinyImage");
394         iconAlt = "Image";
395       }
396     // uploadedMedia Entity list is empty.
397     // we only have text
398     } else {
399       tinyIcon = MirConfig.getProp("Producer.Icon.TinyText");
400       iconAlt = "Text";
401     }
402     returnHash.put("tiny_icon", mirconf_imageRoot+"/"+tinyIcon);
403     returnHash.put("icon_alt", iconAlt);
404     return returnHash;
405   }
406
407   private boolean hasMedia() throws StorageObjectException
408   {
409     if (_hasMedia == null) {
410       _hasMedia =
411         new Boolean(DatabaseContentToMedia.getInstance().hasMedia(this));
412     }
413     return _hasMedia.booleanValue();
414   }
415
416   //######## @todo all of the following getBlahForContent should have
417   // and optimized version where LIMIT=1 sql for list view.
418   private EntityList getImagesForContent()
419     throws StorageObjectException, TemplateModelException
420   {
421     if (hasMedia())
422       return DatabaseContentToMedia.getInstance().getImages(this);
423     else
424       return null;
425   }
426
427   private EntityList getAudioForContent()
428     throws StorageObjectException, TemplateModelException
429   {
430     if (hasMedia())
431       return DatabaseContentToMedia.getInstance().getAudio(this) ;
432     else
433       return null;
434   }
435
436   private EntityList getVideoForContent()
437     throws StorageObjectException, TemplateModelException
438   {
439     if (hasMedia())
440       return DatabaseContentToMedia.getInstance().getVideo(this) ;
441     else
442       return null;
443   }
444
445   private EntityList getOtherMediaForContent()
446     throws StorageObjectException, TemplateModelException
447   {
448     if (hasMedia())
449       return DatabaseContentToMedia.getInstance().getOther(this);
450     else
451       return null;
452   }
453
454 }