/* Copyright 2014 InterCommIT b.v. * * This file is part of the "Weaves" project hosted on https://github.com/intercommit/Weaves * * Weaves is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * Weaves 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Weaves. If not, see <http://www.gnu.org/licenses/>. * */ package nl.intercommit.weaves.components; import java.util.LinkedList; import java.util.List; import nl.intercommit.weaves.base.BasicClientElement; import org.apache.tapestry5.annotations.BeginRender; import org.apache.tapestry5.annotations.Import; import org.apache.tapestry5.annotations.Parameter; import org.apache.tapestry5.annotations.Property; /** * Marks specific keywords in a text with a yellow background. * * @tapestrydoc */ @Import(stylesheet="TextMarker.css") public class TextMarker extends BasicClientElement { private final static String POINTS = "..."; @Parameter(required = true) private String value; @Parameter(required = true) private String[] keywords; @Parameter(value="20") private int paddingSize; @Parameter(value="0") private int maxLength; @Property private List<Match> matches; @Property private Match match; @BeginRender public void makeMatches() { final String[] lowerCaseKeywords= new String[keywords.length]; int i =0; for (String keyword: keywords) { lowerCaseKeywords[i++] = keyword.toLowerCase(); } String workingMessage = value; StringBuilder returnValue = null; int currentLength = 0 ; matches = new LinkedList<Match>(); match = nextOccurence(workingMessage, lowerCaseKeywords); while (match != null) { returnValue = new StringBuilder(); if (currentLength == 0) { if (match.pos > paddingSize) { returnValue.append(POINTS); returnValue.append(workingMessage.substring(match.pos-paddingSize,match.pos)); } else { returnValue.append(workingMessage.substring(0, match.pos)); } } else { if (match.pos > paddingSize) { returnValue.append(workingMessage.substring(0,paddingSize)).append(POINTS); } else { returnValue.append(workingMessage.substring(0, match.pos)); } } match.prefix = returnValue.toString(); currentLength += returnValue.length() + match.word.length(); matches.add(match); workingMessage = workingMessage.substring(match.pos+ match.word.length()); match = nextOccurence(workingMessage, lowerCaseKeywords); if (maxLength > 0 && currentLength >= maxLength) { match = null; } } // end match = new Match(0,null); if (!matches.isEmpty()) { int remainder = 0; if (maxLength > 0 ) { remainder = maxLength - currentLength; if (remainder <0) remainder= 0; } else { remainder = workingMessage.length(); } if (remainder > paddingSize) { match.prefix = workingMessage.substring(0, paddingSize) + POINTS; } else { match.prefix = workingMessage.substring(0,remainder); } } else { match.prefix = workingMessage; } matches.add(match); } /** * finds a next occurence of a word from words in the searchText * * @param searchText * @param words * @return null if nothing was found, a {@link Match} otherwise */ private Match nextOccurence(final String searchText,final String[] words) { Match nextMatch = null; final String lowerCaseSearchText = searchText.toLowerCase(); for (String word:words) { if (lowerCaseSearchText.indexOf(word) != -1) { if (nextMatch == null) { final int pos = lowerCaseSearchText.indexOf(word); nextMatch = new Match(pos,searchText.substring(pos, pos+ word.length())); } else { if (lowerCaseSearchText.indexOf(word) < nextMatch.pos) { final int pos = lowerCaseSearchText.indexOf(word); nextMatch = new Match(pos,searchText.substring(pos, pos+ word.length())); } } } } return nextMatch; } public class Match { private int pos; private String prefix; private String word; public Match(final int pos,final String word) { this.pos = pos; this.word = word; } public int getPos() { return pos; } public String getWord() { return word; } public String getPrefix() { return prefix; } } }