Package util.program

Source Code of util.program.ProgramTextCreator

/*
* TV-Browser
* Copyright (C) 04-2003 Martin Oberhauser (darras@users.sourceforge.net)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*
* CVS information:
*  $RCSfile$
*   $Source$
*     $Date: 2011-03-26 21:21:11 +0100 (Sat, 26 Mar 2011) $
*   $Author: bananeweizen $
* $Revision: 6974 $
*/

package util.program;

import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.regex.Pattern;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;

import org.apache.commons.lang.StringUtils;

import tvbrowser.extras.common.InternalPluginProxyIf;
import tvbrowser.extras.common.InternalPluginProxyList;
import tvbrowser.extras.favoritesplugin.FavoritesPluginProxy;
import tvbrowser.extras.favoritesplugin.core.Favorite;
import tvbrowser.extras.favoritesplugin.dlgs.FavoriteTreeModel;
import tvbrowser.extras.programinfo.ProgramInfo;
import util.settings.PluginPictureSettings;
import util.settings.ProgramPanelSettings;
import util.ui.Localizer;
import util.ui.TVBrowserIcons;
import util.ui.UiUtilities;
import util.ui.html.ExtendedHTMLDocument;
import util.ui.html.HTMLTextHelper;
import util.ui.html.HorizontalLine;
import devplugin.Date;
import devplugin.Marker;
import devplugin.Plugin;
import devplugin.PluginAccess;
import devplugin.Program;
import devplugin.ProgramFieldType;
import devplugin.ProgramInfoHelper;

/**
* Creates the String for the ProgramInfoDialog
*/
public class ProgramTextCreator {

  /**
   * The Localizer for this class.
   */
  private static final util.ui.Localizer mLocalizer = util.ui.Localizer
      .getLocalizerFor(ProgramTextCreator.class);

  private static String mBodyFontSize;

  /** The used link protocol for actor links */
  public static final String TVBROWSER_URL_PROTOCOL = "tvbrowser://";


  /**
   *
   * @param prog
   *          The Program to show
   * @param doc
   *          The HTMLDocument.
   * @param fieldArr The object array with the field types.
   * @param tFont The title Font.
   * @param bFont The body Font.
   * @param showImage If the image should be shown if it is available.
   * @param showHelpLinks Show the Help-Links (Quality of Data, ShowView)
   * @return The HTML String.
   */
  public static String createInfoText(Program prog, ExtendedHTMLDocument doc,
      Object[] fieldArr, Font tFont, Font bFont, boolean showImage, boolean showHelpLinks) {
    return createInfoText(prog,doc,fieldArr,tFont,bFont,new ProgramPanelSettings(showImage ? ProgramPanelSettings.SHOW_PICTURES_EVER : ProgramPanelSettings.SHOW_PICTURES_NEVER, -1, -1, false, true, 10),showHelpLinks, 100);
  }

  /**
   *
   * @param prog
   *          The Program to show
   * @param doc
   *          The HTMLDocument.
   * @param fieldArr
   *          The object array with the field types.
   * @param tFont
   *          The title Font.
   * @param bFont
   *          The body Font.
   * @param settings
   *          Settings of the ProgramPanel
   * @param showHelpLinks
   *          Show the Help-Links (Quality of Data, ShowView)
   * @param zoom The zoom value for the picture.
   * @return The HTML String.
   * @since 2.2.2
   */
  public static String createInfoText(Program prog, ExtendedHTMLDocument doc,
      Object[] fieldArr, Font tFont, Font bFont, ProgramPanelSettings settings,
      boolean showHelpLinks, int zoom) {
    return createInfoText(prog,doc,fieldArr,tFont,bFont,settings,showHelpLinks, zoom, true);
  }

  /**
   *
   * @param prog
   *          The Program to show
   * @param doc
   *          The HTMLDocument.
   * @param fieldArr
   *          The object array with the field types.
   * @param tFont
   *          The title Font.
   * @param bFont
   *          The body Font.
   * @param settings
   *          Settings of the ProgramPanel
   * @param showHelpLinks
   *          Show the Help-Links (Quality of Data, ShowView)
   * @param zoom The zoom value for the picture.
   * @return The HTML String.
   * @since 2.6
   */
  public static String createInfoText(Program prog, ExtendedHTMLDocument doc,
      Object[] fieldArr, Font tFont, Font bFont, PluginPictureSettings settings,
      boolean showHelpLinks, int zoom) {
    return createInfoText(prog,doc,fieldArr,tFont,bFont,new ProgramPanelSettings(settings,false),showHelpLinks, zoom, true);
  }

  /**
   *
   * @param prog
   *          The Program to show
   * @param doc
   *          The HTMLDocument.
   * @param fieldArr
   *          The object array with the field types.
   * @param tFont
   *          The title Font.
   * @param bFont
   *          The body Font.
   * @param settings
   *          Settings of the ProgramPanel
   * @param showHelpLinks
   *          Show the Help-Links (Quality of Data, ShowView)
   * @param zoom The zoom value for the picture.
   * @param showPluginIcons If the plugin icons should be shown.
   * @return The HTML String.
   * @since 2.5.3
   */
  public static String createInfoText(Program prog, ExtendedHTMLDocument doc,
      Object[] fieldArr, Font tFont, Font bFont, ProgramPanelSettings settings,
      boolean showHelpLinks, int zoom, boolean showPluginIcons) {
    return createInfoText(prog, doc, fieldArr, tFont, bFont, settings,
        showHelpLinks, zoom, showPluginIcons, true);
  }

  /**
   *
   * @param prog
   *          The Program to show
   * @param doc
   *          The HTMLDocument.
   * @param fieldArr
   *          The object array with the field types.
   * @param tFont
   *          The title Font.
   * @param bFont
   *          The body Font.
   * @param settings
   *          Settings of the ProgramPanel
   * @param showHelpLinks
   *          Show the Help-Links (Quality of Data, ShowView)
   * @param zoom
   *          The zoom value for the picture.
   * @param showPluginIcons
   *          If the plugin icons should be shown.
   * @return The HTML String.
   * @since 3.0
   */
  public static String createInfoText(Program prog, ExtendedHTMLDocument doc,
      Object[] fieldArr, Font tFont, Font bFont, ProgramPanelSettings settings,
      boolean showHelpLinks, int zoom, boolean showPluginIcons,
      boolean showPersonLinks) {
    String debugTables = "0"; //set to "1" for debugging, to "0" for no debugging
    try {
    // NOTE: All field types are included until type 25 (REPETITION_ON_TYPE)
      StringBuilder buffer = new StringBuilder(1024);

    String titleFont, titleSize, bodyFont;

    int bodyStyle;
    int titleStyle;
    if (tFont == null && bFont != null) {
      titleFont = bodyFont = bFont.getFamily();
      titleSize = mBodyFontSize = String.valueOf(bFont.getSize());
      titleStyle = bodyStyle = bFont.getStyle();
    } else if (tFont != null && bFont != null) {
      titleFont = tFont.getFamily();
      bodyFont = bFont.getFamily();
      titleSize = String.valueOf(tFont.getSize());
      mBodyFontSize = String.valueOf(bFont.getSize());
      titleStyle = tFont.getStyle();
      bodyStyle = bFont.getStyle();
    } else {
      return null;
    }

    if (fieldArr == null) {
      return null;
    }

    buffer.append("<html>");
    buffer.append("<table width=\"100%\" border=\"" + debugTables + "\" style=\"font-family:");

    buffer.append(bodyFont);

    buffer.append(";").append(getCssStyle(bodyStyle)).append("\"><tr>");
    buffer.append("<td width=\"60\">");
    buffer.append("<p \"align=center\">");

    JLabel channelLogo = new JLabel(prog.getChannel().getIcon());
    channelLogo.setToolTipText(prog.getChannel().getName());
    buffer.append(doc.createCompTag(channelLogo));

    buffer.append("</p></td><td><table width=\"100%\" border=\""+ debugTables +"\" cellpadding=\"0\"><tr><td>");
    buffer.append("<div style=\"color:#ff0000; font-size:");

    buffer.append(mBodyFontSize);

    buffer.append(";\"><b>");

    Date currentDate = Date.getCurrentDate();
    Date programDate = prog.getDate();
    if(programDate.equals(currentDate.addDays(-1))) {
      buffer.append(Localizer.getLocalization(Localizer.I18N_YESTERDAY));
      buffer.append(" · ");
    }
    else if(programDate.equals(currentDate)){
      buffer.append(Localizer.getLocalization(Localizer.I18N_TODAY));
      buffer.append(" · ");
    }
    else if(programDate.equals(currentDate.addDays(1))){
      buffer.append(Localizer.getLocalization(Localizer.I18N_TOMORROW));
      buffer.append(" · ");
    }
    buffer.append(prog.getDateString());

    buffer.append(" · ");
    buffer.append(prog.getTimeString());
    if (prog.getLength() > 0) {
      buffer.append('-');
      buffer.append(prog.getEndTimeString());
    }
    buffer.append(" · ");
    buffer.append(prog.getChannel());

    buffer.append("</b></div><div style=\"color:#003366; font-size:");

    buffer.append(titleSize);

    buffer.append("; line-height:2.5em; font-family:");
    buffer.append(titleFont).append(";").append(getCssStyle(titleStyle));
    buffer.append("\">");
    buffer.append(prog.getTitle());
    buffer.append("</div>");

    String episode = CompoundedProgramFieldType.EPISODE_COMPOSITION.getFormattedValueForProgram(prog);

    if (episode != null && episode.trim().length() > 0) {
      buffer.append("<div style=\"color:#808080; font-size:");

      buffer.append(mBodyFontSize);

      buffer.append("\">");
      buffer.append(episode);
      buffer.append("</div>");
    }

    buffer.append("</td><td align=\"right\" valign=\"top\"><table border=\"" + debugTables +"\"><tr><td>");
    JButton btn = new JButton(TVBrowserIcons.left(TVBrowserIcons.SIZE_SMALL));
    buffer.append(doc.createCompTag(btn));
    btn.addActionListener(new ActionListener() {

      @Override
      public void actionPerformed(ActionEvent e) {
        ProgramInfo.getInstance().historyBack();
      }
    });
    btn.setEnabled(ProgramInfo.getInstance().canNavigateBack());
    btn.setToolTipText(ProgramInfo.getInstance().navigationBackwardText());

    buffer.append("</td><td>");
    btn = new JButton(TVBrowserIcons.right(TVBrowserIcons.SIZE_SMALL));
    buffer.append(doc.createCompTag(btn));
    btn.addActionListener(new ActionListener() {

      @Override
      public void actionPerformed(ActionEvent e) {
        ProgramInfo.getInstance().historyForward();
      }
    });
    btn.setEnabled(ProgramInfo.getInstance().canNavigateForward());
    btn.setToolTipText(ProgramInfo.getInstance().navigationForwardText());

    buffer.append("</td></tr></table></td></tr></table></td></tr>");

    boolean show = false;

    if(settings.isShowingPictureForPlugins()) {
      String[] pluginIds = settings.getPluginIds();
      Marker[] markers = prog.getMarkerArr();

      if(markers != null && pluginIds != null) {
        for (Marker marker : markers) {
          for (String pluginId : pluginIds) {
            if(marker.getId().compareTo(pluginId) == 0) {
              show = true;
              break;
            }
          }
        }
      }
    }

    Color foreground = Color.black;//Settings.propProgramPanelForegroundColor.getColor();

    if(settings.isShowingPictureEver() ||
      (settings.isShowingPictureInTimeRange() && !ProgramUtilities.isNotInTimeRange(settings.getPictureTimeRangeStart(),settings.getPictureTimeRangeEnd(), prog)) ||
      show || (settings.isShowingPictureForDuration() && settings.getDuration() <= prog.getLength())) {
      byte[] image = prog.getBinaryField(ProgramFieldType.PICTURE_TYPE);
      if (image != null) {
        String line = "<tr><td></td><td valign=\"top\" style=\"color:rgb("+ foreground.getRed() + "," + foreground.getGreen() + "," + foreground.getBlue() + "); font-size:0\">";
        buffer.append(line);
        try {
          ImageIcon imageIcon = new ImageIcon(image);

          if(zoom != 100) {
            imageIcon = (ImageIcon)UiUtilities.scaleIcon(imageIcon, imageIcon.getIconWidth() * zoom/100);
          }

          StringBuilder value = new StringBuilder();

          String textField = prog.getTextField(ProgramFieldType.PICTURE_COPYRIGHT_TYPE);
          if (textField != null) {
            value.append(textField);
          }

          if (settings.isShowingPictureDescription()) {
              textField = prog
                  .getTextField(ProgramFieldType.PICTURE_DESCRIPTION_TYPE);
              if (textField != null) {
                value.append("<br>").append(textField);
              }
          }

          buffer.append(doc.createCompTag(new JLabel(imageIcon)));
          buffer.append("<div style=\"font-size:");

          buffer.append(mBodyFontSize);

          buffer.append("\">");
          buffer.append(value);
          buffer.append("</div>");
          buffer.append("</td></tr>");
        } catch (Exception e) {
          // Picture was wrong;
          buffer.delete(buffer.length() - line.length(), buffer.length());
        }
      }
    }

    Marker[] pluginArr = prog.getMarkerArr();
    if (showPluginIcons && (pluginArr != null) && (pluginArr.length != 0)) {
      addSeparator(doc, buffer);

      buffer.append("<tr><td valign=\"top\" style=\"color:#808080; font-size:");

      buffer.append(mBodyFontSize);

      buffer.append("\"><b>");
      buffer.append(mLocalizer.msg("markedBy", "Marked by"));
      buffer.append("</b></td><td valign=\"middle\" style=\"font-size:4\">");
      openPara(buffer, "info");

      // Workaround: Without the &nbsp; the component are not put in one line.
      buffer.append("&nbsp;");
      for (int markerCount = pluginArr.length-1; markerCount >= 0; markerCount--) {
        Icon[] icons = pluginArr[markerCount].getMarkIcons(prog);

        if (icons != null) {
          for(int i = icons.length - 1; i >= 0 ; i--) {
            JLabel iconLabel = new JLabel(icons[i]);
            PluginAccess plugin = Plugin.getPluginManager()
                .getActivatedPluginForId(pluginArr[markerCount].getId());
            if (plugin != null) {
              iconLabel.setToolTipText(plugin.getInfo().getName());
            }
            else {
              InternalPluginProxyIf internalPlugin = InternalPluginProxyList.getInstance().getProxyForId(pluginArr[markerCount].getId());
              if (internalPlugin != null) {
                iconLabel.setToolTipText(internalPlugin.getName());
                if (internalPlugin.equals(FavoritesPluginProxy.getInstance())) {
                  // if this is a favorite, add the names of the favorite
                  String favTitles = "";
                  for (Favorite favorite : FavoriteTreeModel.getInstance().getFavoritesContainingProgram(prog)) {
                    if (favTitles.length() > 0) {
                      favTitles = favTitles + ", ";
                    }
                    favTitles = favTitles + favorite.getName();
                  }
                  if (favTitles.length() > 0) {
                    iconLabel.setToolTipText(iconLabel.getToolTipText() + " (" + favTitles + ")");
                  }
                }
              }
              else {
                iconLabel.setToolTipText(pluginArr[markerCount].toString());
              }
            }

            buffer.append(doc.createCompTag(iconLabel));
            buffer.append("&nbsp;&nbsp;");
          }
        }
      }
      closePara(buffer);
      buffer.append("</td></tr>");
    }

    PluginAccess[] plugins = Plugin.getPluginManager().getActivatedPlugins();
    ArrayList<JLabel> iconLabels = new ArrayList<JLabel>();
    for (PluginAccess plugin : plugins) {
      Icon[] icons = plugin.getProgramTableIcons(prog);

      if (icons != null) {
        for (Icon icon : icons) {
          JLabel iconLabel = new JLabel(icon);
          iconLabel.setToolTipText(plugin.getInfo().getName());
          iconLabels.add(iconLabel);
        }
      }
    }

    if (showPluginIcons && iconLabels.size() > 0) {
      addSeparator(doc, buffer);

      buffer
          .append("<tr><td valign=\"middle\" style=\"color:#808080; font-size:");

      buffer.append(mBodyFontSize);

      buffer.append("\"><b>");
      buffer.append("Plugin-Icons");
      buffer.append("</b></td><td valign=\"top\" style=\"font-size:4\">");

      openPara(buffer, "info");
      // Workaround: Without the &nbsp; the component are not put in one line.
      buffer.append("&nbsp;");

      for (JLabel iconLabel : iconLabels) {
        buffer.append(doc.createCompTag(iconLabel));
        buffer.append("&nbsp;&nbsp;");
      }

      closePara(buffer);
      buffer.append("</td></tr>");
    }

    addSeparator(doc, buffer);

    for (Object id : fieldArr) {
      ProgramFieldType type = null;

      if (id instanceof String) {
        if (((String) id).matches("\\d+")) {
          try {
            type = ProgramFieldType
                .getTypeForId(Integer.parseInt((String) id, 10));
          } catch (Exception e) {
            // Empty Catch
          }
        }

        if (type == null) {
          int length = prog.getLength();
          if (length > 0 && ((String) id).trim().length() > 0) {

            buffer
                .append("<tr><td valign=\"top\" style=\"color:gray; font-size:");

            buffer.append(mBodyFontSize);

            buffer.append("\"><b>");
            buffer.append(mLocalizer.msg("duration",
                "Program duration/<br>-end"));
            buffer.append("</b></td><td style=\"color:rgb("+ foreground.getRed() + "," + foreground.getGreen() + "," + foreground.getBlue() + "); font-size:");

            buffer.append(mBodyFontSize);

            buffer.append("\">");

            openPara(buffer, "time");

            String msg = mLocalizer.msg("minutes", "{0} min", length);
            buffer.append(msg).append(" (");
            buffer.append(mLocalizer.msg("until", "until {0}", prog.getEndTimeString()));

            int netLength = prog
                .getIntField(ProgramFieldType.NET_PLAYING_TIME_TYPE);
            if (netLength != -1) {
              msg = mLocalizer.msg("netMinuted", "{0} min net", netLength);
              buffer.append(" - ").append(msg);
            }
            buffer.append(')');

            closePara(buffer);

            buffer.append("</td></tr>");
            addSeparator(doc, buffer);
          }
        }
      } else if(id instanceof CompoundedProgramFieldType) {
        CompoundedProgramFieldType value = (CompoundedProgramFieldType) id;
        String entry = value.getFormattedValueForProgram(prog);

        if(entry != null) {
          startInfoSection(buffer, value.getName());
          buffer.append(HTMLTextHelper.convertTextToHtml(entry, false));

          addSeparator(doc,buffer);
        }
      }
      else {
        type = (ProgramFieldType) id;

        if (type == ProgramFieldType.DESCRIPTION_TYPE) {
          String description = checkDescription(prog.getDescription());
          if (description != null
              && description.length() > 0) {
            addEntry(doc, buffer, prog, ProgramFieldType.DESCRIPTION_TYPE, true,
                showHelpLinks, showPersonLinks);
          } else {
            addEntry(doc, buffer, prog, ProgramFieldType.SHORT_DESCRIPTION_TYPE,
                true, showHelpLinks,
                  showPersonLinks);
          }
        } else if (type == ProgramFieldType.INFO_TYPE) {
          int info = prog.getInfo();
          if ((info != -1) && (info != 0)) {
            buffer
                .append("<tr><td valign=\"top\" style=\"color:gray; font-size:");

            buffer.append(mBodyFontSize);

            buffer.append("\"><b>");
            buffer
                .append(type.getLocalizedName());
            buffer
                .append("</b></td><td valign=\"middle\" style=\"font-size:5\">");

            openPara(buffer, "info");
            // Workaround: Without the &nbsp; the component are not put in one
            // line.
            buffer.append("&nbsp;");

            int[] infoBitArr = ProgramInfoHelper.getInfoBits();
            Icon[] infoIconArr = ProgramInfoHelper.getInfoIcons();
            String[] infoMsgArr = ProgramInfoHelper.getInfoIconMessages();

            for (int i = 0; i < infoBitArr.length; i++) {
              if (ProgramInfoHelper.bitSet(info, infoBitArr[i])) {
                JLabel iconLabel;

                if (infoIconArr[i] != null) {
                  iconLabel = new JLabel(infoIconArr[i]);
                }
                else {
                  iconLabel = new JLabel(infoMsgArr[i]);
                }

                iconLabel.setToolTipText(infoMsgArr[i]);
                buffer.append(doc.createCompTag(iconLabel));

                buffer.append("&nbsp;&nbsp;");
              }
            }

            closePara(buffer);

            buffer.append("</td></tr>");
            addSeparator(doc, buffer);
          }
        } else if (type == ProgramFieldType.URL_TYPE) {
          addEntry(doc, buffer, prog, ProgramFieldType.URL_TYPE, true,
              showHelpLinks, showPersonLinks);
        }
        else if (type == ProgramFieldType.ACTOR_LIST_TYPE) {
          ArrayList<String> knownNames = new ArrayList<String>();
          String[] recognizedActors = ProgramUtilities.getActorNames(prog);
          if (recognizedActors != null) {
            knownNames.addAll(Arrays.asList(recognizedActors));
          }
          String actorField = prog.getTextField(type);
          if (actorField != null) {
            ArrayList<String>[] lists = ProgramUtilities.splitActors(prog);
            if (lists == null) {
              lists = splitActorsSimple(prog);
            }
            if (lists != null && lists[0].size() > 0) {
              startInfoSection(buffer, type.getLocalizedName());
              buffer.append("<table border=\"0\" cellpadding=\"0\" style=\"font-family:");
              buffer.append(bodyFont);
              buffer.append(";\">");
              for (int i=0; i < lists[0].size(); i++) {
                String[] parts = new String[2];
                parts[0] = lists[0].get(i);
                parts[1] = "";
                if (i < lists[1].size()) {
                  parts[1] = lists[1].get(i);
                }
                int actorIndex = 0;
                if (showPersonLinks) {
                    if (knownNames.contains(parts[0])) {
                      parts[0] = addPersonLink(parts[0]);
                    } else if (knownNames.contains(parts[1])) {
                      parts[1] = addPersonLink(parts[1]);
                      actorIndex = 1;
                    }
                }
                buffer.append("<tr><td valign=\"top\">&#8226;&nbsp;</td><td valign=\"top\">");
                buffer.append(parts[actorIndex]);
                buffer.append("</td><td width=\"10\">&nbsp;</td>");

                if (parts[1-actorIndex].length() > 0) {
                  buffer.append("<td valign=\"top\">");
                  buffer.append(parts[1-actorIndex]);
                  buffer.append("</td>");
                } else {
                  // if roles are missing add next actor in the same line
                   if (i+1 < lists[0].size() && lists[1].size() == 0) {
                    i++;
                    buffer.append("<td valign=\"top\">&#8226;&nbsp;</td><td valign=\"top\">");
                    if (showPersonLinks) {
                        buffer.append(addSearchLink(lists[0].get(i)));
                      } else {
                        buffer.append(lists[0].get(i));
                      }
                    buffer.append("</td>");
                  }
                }
                buffer.append("</td></tr>");
              }
              buffer.append("</table>");
              buffer.append("</td></tr>");
              addSeparator(doc, buffer);
            }
            else {
              addEntry(doc, buffer, prog, type, showHelpLinks,
                    showPersonLinks);
            }
          }
        }
        else {
          addEntry(doc, buffer, prog, type, showHelpLinks, showPersonLinks);
        }
      }
    }

    if (showHelpLinks) {
      buffer
          .append("<tr><td colspan=\"2\" valign=\"top\" align=\"center\" style=\"color:#808080; font-size:");
      buffer.append(mBodyFontSize).append("\">");
      buffer.append("<a href=\"");
      buffer.append(
          mLocalizer.msg("dataInfo",
              "http://wiki.tvbrowser.org/index.php/Qualit%C3%A4t_der_Daten"))
          .append("\">");
      buffer.append(mLocalizer
          .msg("dataQuality", "Details of the data quality"));
      buffer.append("</a>");
      buffer.append("</td></tr>");
    }
    buffer.append("</table></html>");

    return buffer.toString();}catch(Exception e) {e.printStackTrace();}
    return "";
  }

  private static String getCssStyle(final int style) {
    StringBuilder result = new StringBuilder();
    if ((style & Font.BOLD) == Font.BOLD) {
      result.append("font-weight:bold;");
    }
    if ((style & Font.ITALIC) == Font.ITALIC) {
      result.append("font-style:italic;");
    }
    return result.toString();
  }

  private static String checkDescription(String desc) {
    if (desc != null) {
      desc = desc.trim();
      // remove duplicate lines directly after each other
      StringBuilder buffer = new StringBuilder();
      String[] lines = desc.split("\n");
      for (int i = 0; i < lines.length; i++) {
        if (i == 0 || ! lines[i].equals(lines[i - 1])) {
          if (buffer.length() > 0) {
            buffer.append('\n');
          }
          buffer.append(lines[i]);
        }
      }
      desc = buffer.toString();
      int size = 50;
      if (desc.length() >= size) {
        // search re-occurings in the description, independent of line breaks
        int index = desc.indexOf(desc.substring(0, size), size);
        if (index >= size) {
          if (desc.indexOf(desc.substring(0, index - 1).trim(), index) == index) {
            desc = desc.substring(index).trim();
          }
        }
      }
      return desc;
    }
    return null;
  }

  private static String addPersonLink(final String name) {
    if (name == null || name.isEmpty()) {
      return mLocalizer.msg("unknown", "(unknown)");
    }
    return addSearchLink(name);
  }

  private static ArrayList<String>[] splitActorsSimple(Program prog) {
    @SuppressWarnings("unchecked")
    ArrayList<String> list1 = new ArrayList();
    @SuppressWarnings("unchecked")
    ArrayList<String> list2 = new ArrayList();
    String actorField = prog.getTextField(ProgramFieldType.ACTOR_LIST_TYPE).trim();
    String[] actors;
    // don't try any parsing if newlines and commas are available
    // this must be recognized by the more advanced actors parsing
    if (actorField.contains("\n")) {
      if (actorField.contains(",")) {
        return null;
      }
      actors = actorField.split("\n");
    }
    else if (actorField.contains(",")) {
      actors = actorField.split(",");
    }
    else if (actorField.contains("\t")) {
      actors = new String[1];
      actors[0] = actorField;
    }
    else {
      return null;
    }
    for (String actor : actors) {
      actor = actor.trim();
      if (actor.length() > 0) {
        String part1 = actor;
        String part2 = "";
        if (actor.contains("\t")) {
          part1 = StringUtils.substringBefore(actor,"\t").trim();
          part2 = StringUtils.substringAfter(actor,"\t").trim();
        }
        else if (actor.contains("(") && actor.contains(")")) {
          part1 = actor.substring(0, actor.indexOf("(")).trim();
          part2 = actor.substring(actor.indexOf("(")+1, actor.lastIndexOf(")")).trim();
        }
        list1.add(part1);
        list2.add(part2);
      }
    }
    @SuppressWarnings("unchecked")
    ArrayList<String>[] result = new ArrayList[2];
    result[0] = list1;
    result[1] = list2;
    return result;
  }

  private static String addSearchLink(String topic, String displayText) {
    Color foreground = Color.black;//Settings.propProgramPanelForegroundColor.getColor();

    String style = " style=\"color:rgb("+ foreground.getRed() + "," + foreground.getGreen() + "," + foreground.getBlue() + "); border-bottom: 1px dashed;\"";
      StringBuilder buffer = new StringBuilder(32);
      buffer.append("<a href=\"");
      buffer.append(TVBROWSER_URL_PROTOCOL);
      buffer.append(StringUtils.remove(StringUtils.remove(topic, '"'), '\''));

      buffer.append("\" ");
      buffer.append(style);
      buffer.append('>');
      buffer.append(displayText);
      buffer.append("</a>");
      return buffer.toString();
  }

  private static String addSearchLink(String topic) {
    if (topic == null || topic.isEmpty()) {
      return "";
    }
    return addSearchLink(topic, topic);
  }

  private static void addEntry(ExtendedHTMLDocument doc, StringBuilder buffer,
      Program prog, ProgramFieldType fieldType, boolean showHelpLinks,
      boolean showPersonLinks) {
    addEntry(doc, buffer, prog, fieldType, false, showHelpLinks,
        showPersonLinks);
  }

  private static void addEntry(ExtendedHTMLDocument doc, StringBuilder buffer,
      Program prog, ProgramFieldType fieldType, boolean createLinks,
      boolean showHelpLinks, boolean showPersonLinks) {

    try {
      String text = null;
      String name = fieldType.getLocalizedName();
      int blank = name.indexOf(' ', 16);
      if (blank > 0) {
        name = name.substring(0, blank) + "<br>" + name.substring(blank +1);
      }
      if (fieldType.getFormat() == ProgramFieldType.TEXT_FORMAT) {
        text = prog.getTextField(fieldType);
        if (ProgramFieldType.SHORT_DESCRIPTION_TYPE == fieldType) {
          text = checkDescription(text);
        }

        // Lazily add short description, but only if it differs from description
        if (fieldType == ProgramFieldType.DESCRIPTION_TYPE) {
          String description = checkDescription(prog.getDescription());
          text = description;

          if (prog.getShortInfo() != null) {
            StringBuilder shortInfo = new StringBuilder(checkDescription(prog.getShortInfo())
                .trim());

            // delete "..." at the end, but only for duplication check, not for display
            while (shortInfo.toString().endsWith(".")) {
              shortInfo.deleteCharAt(shortInfo.length() - 1);
            }

            if (!description.trim().startsWith(shortInfo.toString())) {
              addEntry(doc, buffer, prog,
                  ProgramFieldType.SHORT_DESCRIPTION_TYPE, true, showHelpLinks);
            }
          }
          text = text.replace("\\-", ""); // replace conditional dashes
          text = removeArtificialLineBreaks(text);
          text = HTMLTextHelper.convertTextToHtml(text, createLinks);
          // scan for moderation in beginning of description
          String[] lines = text.split("<br>");
          String[] tags = { "von und mit", "präsentiert von", "mit", "film von",
              "moderation", "zu gast" };
          for (int i = 0; i < 2; i++) {
            if (lines.length > i && lines[i].length() < 60) {
              String line = lines[i];
              for (String tag : tags) {
                if (line.toLowerCase().startsWith(tag)
                    || line.toLowerCase().startsWith(tag + ':')) {
                  String personsString = line.substring(tag.length(), line.length())
                      .trim();
                  if (personsString.startsWith(":")) {
                    personsString = personsString.substring(1).trim();
                  }
                  if (personsString.endsWith(".")) {
                    personsString = personsString.substring(0, personsString.length() - 1).trim();
                  }
                  String[] persons = personsString.split(" und ");
                  boolean doLink = true;
                  for (String person : persons) {
                    if (person.isEmpty() || !Character.isLetter(person.charAt(0)) || Character.isLowerCase(person.charAt(0))) {
                      doLink = false;
                      break;
                    }
                  }
                  if (doLink) {
                    for (String person : persons) {
                      String[] names = person.split(" ");
                      int partCount = names.length;
                      if (partCount >= 2 && partCount < 4) {
                        for (String n : names) {
                          if (!StringUtils.isAlpha(n)) {
                            doLink = false;
                          }
                        }
                        if (doLink) {
                          text = StringUtils.replaceOnce(text, person, addSearchLink(person));
                        }
                      }
                    }
                    break;
                  }
                }
              }
            }
          }
        }

      } else if (fieldType.getFormat() == ProgramFieldType.TIME_FORMAT) {
        text = prog.getTimeFieldAsString(fieldType);
      } else if (fieldType.getFormat() == ProgramFieldType.INT_FORMAT) {
        if (fieldType == ProgramFieldType.RATING_TYPE) {
          int value = prog.getIntField(fieldType);
          if (value > -1) {
            text = new DecimalFormat("##.#").format((double)prog.getIntField(fieldType) / 10) + "/10";
          }
        } else {
          text = prog.getIntFieldAsString(fieldType);
          if (text == null && fieldType == ProgramFieldType.AGE_LIMIT_TYPE) {
            final String ageRating = prog.getTextField(ProgramFieldType.AGE_RATING_TYPE);
            if (ageRating != null && !ageRating.isEmpty()) {
              int age = ProgramUtilities.getAgeLimit(ageRating);
              if (age >= 0) {
                text = Integer.toString(age);
              }
            }
          }
        }
      }

      if (fieldType == ProgramFieldType.ORIGIN_TYPE) {
        String temp = prog
            .getIntFieldAsString(ProgramFieldType.PRODUCTION_YEAR_TYPE);
        if (temp != null && temp.trim().length() > 0) {
          if (text == null || text.trim().length() < 1) {
            name = ProgramFieldType.PRODUCTION_YEAR_TYPE.getLocalizedName();
            text = temp;
          } else {
            name += "/<br>"
                + ProgramFieldType.PRODUCTION_YEAR_TYPE.getLocalizedName();
            text += " " + temp;
          }
        }
        temp = prog
        .getIntFieldAsString(ProgramFieldType.LAST_PRODUCTION_YEAR_TYPE);
        if (temp != null && temp.trim().length() > 0) {
          if (text == null || text.trim().length() < 1) {
            name = ProgramFieldType.LAST_PRODUCTION_YEAR_TYPE.getLocalizedName();
            text = temp;
          } else {

            text += " - " + temp;
          }
        }
      }

      if (text == null || text.trim().length() < 1) {
        if (ProgramFieldType.CUSTOM_TYPE == fieldType) {
          text = mLocalizer.msg("noCustom", "No custom information ");
        } else {
          return;
        }
      }

      startInfoSection(buffer, name);

      // add person links
      if (ProgramFieldType.DIRECTOR_TYPE == fieldType
          || ProgramFieldType.SCRIPT_TYPE == fieldType
          || ProgramFieldType.CAMERA_TYPE == fieldType
          || ProgramFieldType.CUTTER_TYPE == fieldType
          || ProgramFieldType.MUSIC_TYPE == fieldType
          || ProgramFieldType.MODERATION_TYPE == fieldType
          || ProgramFieldType.ADDITIONAL_PERSONS_TYPE == fieldType
          || ProgramFieldType.PRODUCER_TYPE == fieldType) {
        if (showPersonLinks && text.length() < 200) {
          // if field is longer, this is probably not a list of names
          if (text.endsWith(".")) {
            text = text.substring(0, text.length() - 1);
          }
          String[] persons = splitPersons(text);
          for (int i = 0; i < persons.length; i++) {
            // remove duplicate entries
            boolean duplicate = false;
            if (i < persons.length - 1) {
              for (int j = i + 1; j < persons.length; j++) {
                if (persons[i].equalsIgnoreCase(persons[j])) {
                  duplicate = true;
                  break;
                }
              }
            }
            if (duplicate) {
              text = text.replaceFirst(Pattern.quote(persons[i]), "").trim();
              if (text.startsWith(",")) {
                text = text.substring(1).trim();
              }
              text = text.replaceAll(",\\s*,", ",");
              continue;
            }
            // a name shall not have more name parts
            if (persons[i].trim().split(" ").length <= 3) {
              String link;
              if (persons[i].contains("(")) {
                int index = persons[i].indexOf('(');
                String topic = persons[i].substring(0, index).trim();
                link = addSearchLink(topic) + " " + persons[i].substring(index).trim();
              } else {
                link = addSearchLink(persons[i]);
              }
              text = text.replace(persons[i], link);
            }
          }
        }
        buffer.append(text);
      }
      else if (ProgramFieldType.DESCRIPTION_TYPE == fieldType) {
        buffer.append(text);
      } else {
        buffer.append(HTMLTextHelper.convertTextToHtml(text, createLinks));
      }

      if ((ProgramFieldType.CUSTOM_TYPE == fieldType) && (showHelpLinks)) {
        buffer.append(" (<a href=\"").append(
            mLocalizer.msg("customInfo",
                "http://enwiki.tvbrowser.org/index.php/CustomInformation")).append(
            "\">?</a>)");
      }
      if ((ProgramFieldType.AGE_RATING_TYPE == fieldType) && (showHelpLinks)) {
        addHelpLink(buffer, mLocalizer.msg("ratingInfo", "http://en.wikipedia.org/wiki/Motion_picture_rating_system"));
      }

      buffer.append("</td></tr>");

      addSeparator(doc, buffer);
    } catch (Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

  private static void addHelpLink(final StringBuilder buffer, final String url) {
    buffer.append(" (<a href=\"").append(url).append("\">?</a>)");
  }

  private static String[] splitPersons(final String textField) {
    return ProgramUtilities.splitPersons(textField);
  }

  /**
   * remove line breaks from description texts which are formatted as block text
   * with lines up to around 80 characters
   *
   * @param text
   * @return floating text
   */
  private static String removeArtificialLineBreaks(String text) {
    String[] lines = text.split("\n");
    if (lines.length > 5) {
      int avg = (text.length() - lines.length + 1) / lines.length;
      if (avg < 120 && avg > 50) {
        StringBuilder result = new StringBuilder();
        for (String line : lines) {
          result.append(line);
          if (line.length() < avg - 10) {
            result.append('\n');
          } else {
            result.append(' ');
          }
        }
        return result.toString();
      }
    }
    return text;
  }

  private static void startInfoSection(StringBuilder buffer, String section) {
    Color foreground = Color.black;//Settings.propProgramPanelForegroundColor.getColor();

    buffer.append("<tr><td valign=\"top\" style=\"color:#808080; font-size:");
    buffer.append(mBodyFontSize);
    buffer.append("\"><b>");
    buffer.append(section);
    buffer.append("</b></td><td style=\"color:rgb("+ foreground.getRed() + "," + foreground.getGreen() + "," + foreground.getBlue() + "); font-size:");
    buffer.append(mBodyFontSize);
    buffer.append("\">");
  }

  private static void addSeparator(ExtendedHTMLDocument doc,
      StringBuilder buffer) {
    buffer.append("<tr><td colspan=\"2\">");
    buffer.append("<div style=\"font-size:0;\">").append(
        doc.createCompTag(new HorizontalLine())).append("</div></td></tr>");
  }

  private static void openPara(StringBuilder buffer, String style) {
    buffer.append("<div id=\"").append(style).append("\">");
  }

  private static void closePara(StringBuilder buffer) {
    buffer.append("</div>\n");
  }

  /**
   *
   * @return The default order of the entries.
   */
  public static Object[] getDefaultOrder() {
    ArrayList<Object> list = new ArrayList<Object>(Arrays.asList(new Object[] {
        ProgramFieldType.GENRE_TYPE,
        ProgramFieldType.DESCRIPTION_TYPE,
        ProgramFieldType.ADDITIONAL_INFORMATION_TYPE,
        ProgramFieldType.RATING_TYPE,
        ProgramFieldType.ORIGIN_TYPE,
        ProgramFieldType.DIRECTOR_TYPE,
        ProgramFieldType.SCRIPT_TYPE,
        ProgramFieldType.ACTOR_LIST_TYPE,
        ProgramFieldType.MODERATION_TYPE,
        ProgramFieldType.MUSIC_TYPE,
        ProgramFieldType.PRODUCER_TYPE,
        ProgramFieldType.CAMERA_TYPE,
        ProgramFieldType.CUTTER_TYPE,
        ProgramFieldType.ADDITIONAL_PERSONS_TYPE,
        ProgramFieldType.URL_TYPE,
        ProgramFieldType.ORIGINAL_TITLE_TYPE,
        ProgramFieldType.ORIGINAL_EPISODE_TYPE,
        ProgramFieldType.PRODUCTION_COMPANY_TYPE,
        ProgramFieldType.REPETITION_OF_TYPE,
        ProgramFieldType.REPETITION_ON_TYPE,
        ProgramFieldType.AGE_LIMIT_TYPE,
        ProgramFieldType.INFO_TYPE,
        ProgramFieldType.VPS_TYPE,
        ProgramFieldType.CUSTOM_TYPE,
        getDurationTypeString()}));
    // append missing fields (which may have been added in recent versions)
    for (Iterator<ProgramFieldType> iterator = ProgramFieldType.getTypeIterator(); iterator.hasNext();) {
      ProgramFieldType type = iterator.next();
      // exclude binary information which need special handling anyway
      if (type.getFormat() == ProgramFieldType.BINARY_FORMAT) {
        continue;
      }
      if (!list.contains(type)) {
        list.add(type);
      }
    }
    return list.toArray();
  }

  /**
   * @return The String for the duration/end of a program.
   */
  public static String getDurationTypeString() {
    return mLocalizer.msg("duration", "Program duration/<br>-end").replaceAll(
        "<br>", "");
  }
}
TOP

Related Classes of util.program.ProgramTextCreator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.