/**************************************************************************
OmegaT - Computer Assisted Translation (CAT) tool
with fuzzy matching, translation memory, keyword search,
glossaries, and translation leveraging into updated projects.
Copyright (C) 2013 Aaron Madlon-Kay, Zoltan Bartko
2014 Aaron Madlon-Kay
Home page: http://www.omegat.org/
Support center: http://groups.yahoo.com/group/OmegaT/
This file is part of OmegaT.
OmegaT 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 3 of the License, or
(at your option) any later version.
OmegaT 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, see <http://www.gnu.org/licenses/>.
**************************************************************************/
package org.omegat.gui.editor;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import org.omegat.core.Core;
import org.omegat.core.data.ProtectedPart;
import org.omegat.gui.editor.autocompleter.AutoCompleterItem;
import org.omegat.gui.editor.autocompleter.AutoCompleterListView;
import org.omegat.tokenizer.ITokenizer;
import org.omegat.util.OStrings;
import org.omegat.util.TagUtil;
import org.omegat.util.TagUtil.Tag;
import org.omegat.util.Token;
/**
* An AutoCompleterView for inserting missing tags.
*
* @author Aaron Madlon-Kay
*/
public class TagAutoCompleterView extends AutoCompleterListView {
private static final ITokenizer TAG_TOKENIZER = new TagTokenizer();
public TagAutoCompleterView() {
super(OStrings.getString("AC_TAG_VIEW"));
}
@Override
public List<AutoCompleterItem> computeListData(String prevText, boolean contextualOnly) {
String wordChunk = getLastToken(prevText);
List<String> missingGroups = TagUtil.getGroupedMissingTagsFromTarget();
// If wordChunk is a tag, pretend we have a blank wordChunk.
for (Tag tag : TagUtil.getAllTagsInSource()) {
if (tag.tag.equals(wordChunk)) {
wordChunk = "";
break;
}
}
List<String> matchGroups = new ArrayList<String>();
if (!"".equals(wordChunk)) {
// Check for partial matches among missing tag groups.
for (String g : missingGroups) {
if (g.startsWith(wordChunk)) {
matchGroups.add(g);
}
}
}
// If there are no partial matches, show all missing tags as suggestions.
if (matchGroups.isEmpty() && !contextualOnly) {
return convertList(missingGroups, 0);
}
return convertList(matchGroups, wordChunk.length());
}
private static List<AutoCompleterItem> convertList(List<String> list, int replacementLength) {
List<AutoCompleterItem> result = new ArrayList<AutoCompleterItem>();
for (String s : list) {
int sep = s.indexOf(TagUtil.TAG_SEPARATOR_SENTINEL);
String cleaned = s;
String display = s;
int adjustment = 0;
boolean keepSelection = false;
if (sep > -1) {
cleaned = s.replace(TagUtil.TAG_SEPARATOR_SENTINEL, "");
display = s.replace(TagUtil.TAG_SEPARATOR_SENTINEL, "|");
adjustment = -(s.length() - 1 - sep);
keepSelection = true;
}
result.add(new AutoCompleterItem(cleaned, new String[] { display }, adjustment, keepSelection,
replacementLength));
}
return result;
}
@Override
public ITokenizer getTokenizer() {
return TAG_TOKENIZER;
}
@Override
public String itemToString(AutoCompleterItem item) {
return item.extras[0];
}
private static class TagTokenizer implements ITokenizer {
@Override
public Token[] tokenizeWords(String str, StemmingMode stemmingMode) {
return tokenize(str);
}
@Override
public String[] tokenizeWordsToStrings(String str, StemmingMode stemmingMode) {
return null;
}
@Override
public Token[] tokenizeVerbatim(String str) {
return tokenize(str);
}
@Override
public String[] tokenizeVerbatimToStrings(String str) {
return null;
}
private Token[] tokenize(String str) {
String regex = buildRegex();
if (regex == null) {
return new Token[] { new Token(str, 0) };
}
String[] pieces = str.split(regex);
Token[] tokens = new Token[pieces.length];
for (int i = 0, offset = 0; i < pieces.length; i++) {
tokens[i] = new Token(pieces[i], offset);
offset += pieces[i].length();
}
return tokens;
}
/**
* Create a regex that will split a string in front of any protected parts.
* It will look like "(?=c1|c2|c3|...|cn)" where c1,...,cn are the unique first
* characters of protected parts in the current segment.
*
* @return regex string
*/
private String buildRegex() {
ProtectedPart[] protectedParts = Core.getEditor().getCurrentEntry().getProtectedParts();
if (protectedParts.length == 0) {
return null;
}
List<String> initials = new ArrayList<String>();
for (ProtectedPart pp : protectedParts) {
String part = pp.getTextInSourceSegment();
String initial = part.substring(0, part.offsetByCodePoints(0, 1));
if (!initials.contains(initial)) {
initials.add(initial);
}
}
StringBuilder regex = new StringBuilder("(?=");
for (int i = 0, max = initials.size(); i < max; i++) {
regex.append(Pattern.quote(initials.get(i)));
if (i + 1 < max) {
regex.append('|');
}
}
regex.append(')');
return regex.toString();
}
@Override
public String[] getSupportedLanguages() {
return null;
}
}
}