/**************************************************************************
OmegaT - Computer Assisted Translation (CAT) tool
with fuzzy matching, translation memory, keyword search,
glossaries, and translation leveraging into updated projects.
Copyright (C) 2013 Alex Buloichik, 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.util;
import java.util.ArrayDeque;
import java.util.Map;
import java.util.TreeMap;
import org.omegat.filters3.Tag;
/**
* This class handles inline tags, i.e. helps to replace all tags into
* shortcuts. It handles bpt,ept,it tags numeration.
*
* @author Alex Buloichik (alex73mail@gmail.com)
* @author Aaron Madlon-Kay
*/
public class InlineTagHandler {
/** map of 'i' attributes to tag numbers */
Map<String, Integer> pairTags = new TreeMap<String, Integer>();
Map<String, ArrayDeque<Integer>> pairedOtherTags = new TreeMap<String, ArrayDeque<Integer>>();
Map<String, Integer> shortcutLetters = new TreeMap<String, Integer>();
String currentI;
String currentPos;
int tagIndex;
int otherTagShortcutLetter;
/**
* Reset stored info for process new part of XML.
*/
public void reset() {
pairTags.clear();
pairedOtherTags.clear();
currentI = null;
currentPos = null;
tagIndex = 0;
}
/**
* Handle "bpt" tag start for TMX. OmegaT internal tag number
* will be based off the x attr (if provided).
*
* @param i TMX i attribute value
* @param x TMX x attribute value (can be null)
*/
public void startBPT(String i, String x) {
if (i == null) {
throw new RuntimeException("Wrong index in inline tag");
}
currentI = i;
int index = tagIndex++;
try {
// If a value for the @x attr was provided, base the tag
// number off of it for matching purposes.
// Subtract 1 because OmegaT 0-indexes tags, while TMX
// seems to start at 1 (though the spec only says it must be
// unique for each <bpt> in the segment, so we clip to 0
// to prevent negative tag numbers).
index = Math.max(0, Integer.parseInt(x) - 1);
} catch (Exception ex) {
// Ignore
}
pairTags.put(currentI, index);
}
/**
* Handle "bpt" tag start. Identifier will be first non-null
* attribute in provided attributes. OmegaT internal tag number
* will be its index in the list of tags in the segment (starting
* with 0).
*
* @param attributeValues
* attributes to identify pairs
*/
public void startBPT(String... attributeValues) {
currentI = nvl(attributeValues);
pairTags.put(currentI, tagIndex++);
}
/**
* Store shortcut letter for current 'i' value.
*
* @param letter
* letter to store
*/
public void setTagShortcutLetter(int letter) {
if (letter != 0) {
shortcutLetters.put(currentI, letter);
}
}
/**
* Get stored shortcut letter for current 'i' value.
*
* @return
*/
public int getTagShortcutLetter() {
Integer c = shortcutLetters.get(currentI);
return c != null ? c : 0;
}
/**
* Store shortcut letter for current other tag.
*
* @param letter
* letter to store
*/
public void setOtherTagShortcutLetter(int letter) {
otherTagShortcutLetter = letter;
}
/**
* Get stored shortcut letter for current other tag.
*
* @return
*/
public int getOtherTagShortcutLetter() {
return otherTagShortcutLetter;
}
/**
* Handle "ept" tag start.
*
* @param attributeValues
* attributes to identify pairs
*/
public void startEPT(String... attributeValues) {
currentI = nvl(attributeValues);
}
/**
* Handle other tag start.
*/
public void startOTHER() {
currentI = null;
}
/**
* Handle "bpt" tag end.
*
* @return shortcut index
*/
public Integer endBPT() {
return pairTags.get(currentI);
}
/**
* Handle "ept" tag end.
*
* @return shortcut index
*/
public Integer endEPT() {
return pairTags.get(currentI);
}
/**
* Handle other tag end.
*
* @return shortcut index
*/
public int endOTHER() {
int result = tagIndex;
tagIndex++;
return result;
}
/**
* Handle paired tag end.
*
* @return shortcut index
*/
public int paired(String tagName, Tag.Type tagType) {
int result;
switch (tagType) {
case BEGIN:
result = tagIndex;
cacheTagIndex(tagName, result);
tagIndex++;
return result;
case END:
Integer index = getCachedTagIndex(tagName);
if (index == null) {
index = tagIndex;
tagIndex++;
}
return index;
case ALONE:
result = tagIndex;
tagIndex++;
return result;
default:
throw new RuntimeException("Impossible tag type");
}
}
private void cacheTagIndex(String tagName, int result) {
ArrayDeque<Integer> cache = pairedOtherTags.get(tagName);
if (cache == null) {
cache = new ArrayDeque<Integer>();
pairedOtherTags.put(tagName, cache);
}
cache.addFirst(result);
}
private Integer getCachedTagIndex(String tagName) {
ArrayDeque<Integer> cache = pairedOtherTags.get(tagName);
if (cache == null) {
return null;
}
return cache.pollFirst();
}
/**
* Remember current begin/end mark of "it" tag.
*/
public void setCurrentPos(String currentPos) {
this.currentPos = currentPos;
}
/**
* Returns current begin/end mark of "it" tag.
*/
public String getCurrentPos() {
return currentPos;
}
private String nvl(String... attributeValues) {
String result = StringUtil.nvl(attributeValues);
if (result == null) {
throw new RuntimeException("Wrong index in inline tag");
}
return result;
}
}