Package ru.org.linux.util.formatter

Source Code of ru.org.linux.util.formatter.ToHtmlFormatter

/*
* Copyright 1998-2014 Linux.org.ru
*    Licensed under the Apache License, Version 2.0 (the "License");
*    you may not use this file except in compliance with the License.
*    You may obtain a copy of the License at
*
*        http://www.apache.org/licenses/LICENSE-2.0
*
*    Unless required by applicable law or agreed to in writing, software
*    distributed under the License is distributed on an "AS IS" BASIS,
*    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*    See the License for the specific language governing permissions and
*    limitations under the License.
*/

package ru.org.linux.util.formatter;

import org.apache.commons.httpclient.URI;
import org.apache.commons.httpclient.URIException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import ru.org.linux.comment.Comment;
import ru.org.linux.comment.CommentService;
import ru.org.linux.site.MessageNotFoundException;
import ru.org.linux.spring.SiteConfig;
import ru.org.linux.topic.Topic;
import ru.org.linux.topic.TopicDao;
import ru.org.linux.user.User;
import ru.org.linux.util.LorURL;
import ru.org.linux.util.StringUtil;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Форматирует сообщение в html
* Основная функция преобразование того, что похоже на ссылку в html ссылку
*/
@Service
public class ToHtmlFormatter {

  private static final String URL_REGEX = "(?:(?:(?:https?://(?:(?:\\w+\\:)?\\w+@)?)|(?:ftp://(?:(?:\\w+\\:)?\\w+@)?)|(?:www\\.)|(?:ftp\\.))[a-z0-9.-]+(?:\\.[a-z]+)?(?::[0-9]+)?" +
    "(?:/(?:([\\w=?+/\\[\\]~%;,._@#'!\\p{L}:-]|(\\([^\\)]*\\)))*([\\p{L}:'" +
    "\\w=?+/~@%#-]|(?:&[\\w:|\\[\\]$_.+!*'#%(),@\\p{L}=;/-]+)+|(\\([^\\)]*\\))))?)?)" +
    "|(?:mailto: ?[a-z0-9+.]+@[a-z0-9.-]+.[a-z]+)|(?:news:([\\w+]\\.?)+)";

  private static final Pattern URL_PATTERN = Pattern.compile(URL_REGEX, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);

  /*
  Замена двойного минуса на тире
  */

  public static final String MDASH_REGEX = " -- ";
  public static final String MDASH_REPLACE = " — ";

  private SiteConfig siteConfig;
  private TopicDao messageDao;

  @Autowired
  private CommentService commentService;

  private int maxLength=80;

  @Autowired
  public void setSiteConfig(SiteConfig siteConfig) {
    this.siteConfig = siteConfig;
  }

  @Autowired
  public void setMessageDao(TopicDao messageDao) {
    this.messageDao = messageDao;
  }

  // для тестирования (todo: заюзать SpringContext)
  public void setCommentService(CommentService commentService) {
    this.commentService = commentService;
  }

  // для тестирования
  public void setMaxLength(int maxLength) {
    this.maxLength = maxLength;
  }

  /**
   * Форматирует текст
   *
   * @param text текст
   * @param secure флаг https
   * @param nofollow
   * @return отфарматированный текст
   */
  public String format(String text, boolean secure, boolean nofollow) {
    return format(text, secure, nofollow, null);
  }

  public String format(String text, boolean secure, boolean nofollow, RuTypoChanger changer) {
    String escapedText = StringUtil.escapeHtml(text);


    StringTokenizer st = new StringTokenizer(escapedText, " \n", true);
    StringBuilder sb = new StringBuilder();

    while (st.hasMoreTokens()) {
      String token = st.nextToken();
      String formattedToken = formatURL(token, secure, nofollow, changer);
      sb.append(formattedToken);
    }

    return sb.toString().replaceAll(MDASH_REGEX, MDASH_REPLACE);
  }

  /**
   * Только escape и замены
   * @param text текст
   * @return форматированый текст
   */
  public String simpleFormat(String text) {
    return StringUtil.escapeHtml(text).replaceAll(MDASH_REGEX, MDASH_REPLACE);
  }

  private String formatWithMagic(String text, RuTypoChanger changer) {
    String text2 = changer!=null ? changer.format(text) : text;
    return text2;
  }

  public String memberURL(User user, boolean secure) throws URIException {
    URI mainUri = siteConfig.getMainURI();
    String scheme;
    if(secure) {
      scheme = "https";
    } else {
      scheme = "http";
    }
    return (new URI(scheme, null, mainUri.getHost(), mainUri.getPort(), String.format("/people/%s/profile", user.getNick()))).getEscapedURIReference();
  }

  protected String formatURL(String line, boolean secure, boolean nofollow, RuTypoChanger changer) {
    StringBuilder out = new StringBuilder();
    Matcher m = URL_PATTERN.matcher(line);
    int index = 0;
    while (m.find()) {
      int start = m.start();
      int end = m.end();

      // обработка начальной части до URL
      out.append(formatWithMagic(line.substring(index, start), changer));

      // возможно это url
      String mayUrl = line.substring(start, end);
      // href
      String urlHref = mayUrl;

      if (mayUrl.toLowerCase().startsWith("www.")) {
        urlHref = "http://" + mayUrl;
      } else if (mayUrl.toLowerCase().startsWith("ftp.")) {
        urlHref = "ftp://" + mayUrl;
      }

      try {
        processUrl(secure, nofollow, out, urlHref, null);
      } catch (URIException e) {
        // e.printStackTrace();
        // ссылка не ссылка
        out.append(formatWithMagic(mayUrl, changer));
      }
      index = end;
    }

    // обработка последнего фрагмента
    if (index < line.length()) {
      out.append(formatWithMagic(line.substring(index), changer));
    }

    return out.toString();
  }

  public void processUrl(
          boolean secure,
          boolean nofollow,
          @Nonnull StringBuilder out,
          @Nonnull String urlHref,
          @Nullable String linktext
  ) throws URIException {
    LorURL url = new LorURL(siteConfig.getMainURI(), urlHref);

    if(url.isMessageUrl()) {
      processMessageUrl(secure, out, url, linktext);
    } else if(url.isTrueLorUrl()) {
      processGenericLorUrl(secure, out, url, linktext);
    } else {
      // ссылка не из lorsource
      String fixedUrlHref = url.toString();
      String fixedUrlBody = url.formatUrlBody(maxLength);

      out.append("<a href=\"").append(fixedUrlHref).append("\"");
      if (nofollow) {
        out.append(" rel=nofollow");
      }
      out.append(">");

      if (linktext!=null) {
        out.append(simpleFormat(linktext));
      } else {
        out.append(simpleFormat(fixedUrlBody));
      }

      out.append("</a>");
    }
  }

  private void processGenericLorUrl(
          boolean secure,
          @Nonnull StringBuilder out,
          @Nonnull LorURL url,
          @Nullable String linktext
  ) throws URIException {
    // ссылка внутри lorsource исправляем scheme
    String fixedUrlHref = url.fixScheme(secure);
    String fixedUrlBody = linktext!=null?simpleFormat(linktext):url.formatUrlBody(maxLength);
    out.append("<a href=\"").append(fixedUrlHref).append("\">").append(fixedUrlBody).append("</a>");
  }

  /**
   * Ссылка на топик или комментарий
   *
   * @param secure признак того какой надо url: https или http
   * @param out сюда будет записана ссылка
   * @param url исходный url
   * @throws URIException если uri не корректный
   */
  private void processMessageUrl(
          boolean secure,
          @Nonnull StringBuilder out,
          @Nonnull LorURL url,
          @Nullable String linkText
  ) throws URIException {
    try {
      Topic message = messageDao.getById(url.getMessageId());

      boolean deleted = message.isDeleted();

      if (!deleted && url.isCommentUrl()) {
        Comment comment = commentService.getById(url.getCommentId());

        deleted = comment.isDeleted();
      }

      String urlTitle = linkText!=null?simpleFormat(linkText):StringUtil.escapeHtml(message.getTitle());

      String newUrlHref = url.formatJump(messageDao, secure);
      String fixedUrlBody = url.formatUrlBody(maxLength);

      if (deleted) {
        out.append("<s>");
      }

      out.append("<a href=\"").append(newUrlHref).append("\" title=\"").append(urlTitle).append("\">").append(fixedUrlBody).append("</a>");

      if (deleted) {
        out.append("</s>");
      }
    } catch (MessageNotFoundException ex) {
      out.append("<a href=\"").append(url.toString()).append("\">").append(url.formatUrlBody(maxLength)).append("</a>");
    }
  }
}
TOP

Related Classes of ru.org.linux.util.formatter.ToHtmlFormatter

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.