タイムライン検索で「続きを読む」とキーワードがかぶる

基準位置を含むキーワードを探す方法

「続きを読む」で分割される位置がキーワードを含んでいるかどうかを判定して、trueならマッチングしたスタートからエンドまで、タグを囲う方法

   /*
   * 部分文字列の最後がキーワードのとき部分文字列をspanタグで囲って返します。
   *
   * @param 検索keyword
   * @return 部分文字列sub
   */
  private String subNote(String keyword) {
    String rawNote = note.getValue();
    String regex = "(" + keyword + ")+";
    Pattern pattern = Pattern.compile(regex);
    Matcher matcher = pattern.matcher(note.getValue());
    while (matcher.find()) {
      if (matcher.start() < PRE_NOTE_LENGTH || matcher.end() > PRE_NOTE_LENGTH) {
        StringBuffer result = new StringBuffer();
        result
          .append(rawNote.substring(0, matcher.start()))
          .append("<span class=\"searchKeyword\">")
          .append(rawNote.substring(matcher.start(), PRE_NOTE_LENGTH))
          .append("</span>");
        return ALEipUtils.getMessageList(result.toString(), keyword);
      }
    }
    return ALEipUtils.getMessageList(
      rawNote.substring(0, PRE_NOTE_LENGTH),
      keyword);
  }

結果

失敗

原因1 matcher.start()が0になっていた。

原因2 サニタライジングされてspanタグが見えた

分割位置を変える方法

分割位置にURLがあった場合には、空白文字か改行になるまで分割位置を伸ばすようになっていた。

その分割位置に伸ばす必要がある文字数を足してからsubStringする方法


/** * 分割位置にキーワードがかぶっていたときに何文字伸ばせばいいのかを返します。 * * @param 部分文字列sub * @return */ private int lenOverdKeyword(int pos, String keyword) { if ("".equals(keyword) || keyword != null) { return 0; } String rawNote = note.getValue(); Pattern pattern = Pattern.compile("(" + keyword + ")+"); Matcher matcher = pattern.matcher(rawNote); while (matcher.find()) { if (matcher.start() < pos && matcher.end() > pos) { return pos - matcher.end(); } } return 0; }

結果

失敗

原因 これを使おうとした段階では、すでにHTMLタグで囲まれており、その後から、キーワードを抽出するという処理を使用としていたため。