/**************************************************************************
OmegaT - Computer Assisted Translation (CAT) tool
with fuzzy matching, translation memory, keyword search,
glossaries, and translation leveraging into updated projects.
Copyright (C) 2014 Alex Buloichik, Didier Briel
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.core.data;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.omegat.util.StringUtil;
import org.omegat.util.TMXProp;
/**
* Utility class for import translations from tm/auto/ files.
*
* @author Alex Buloichik (alex73mail@gmail.com)
* @author Didier Briel
*/
public class ImportFromAutoTMX {
final RealProject project;
/** Map of all segments in project by source text. Just for optimize some processes. */
Map<String, List<SourceTextEntry>> existEntries = new HashMap<String, List<SourceTextEntry>>();
public ImportFromAutoTMX(RealProject project, List<SourceTextEntry> allProjectEntries) {
this.project = project;
for (SourceTextEntry ste : allProjectEntries) {
List<SourceTextEntry> list = existEntries.get(ste.getSrcText());
if (list == null) {
list = new ArrayList<SourceTextEntry>();
existEntries.put(ste.getSrcText(), list);
}
list.add(ste);
}
}
/**
* Process a TMX from an automatic folder
* @param tmx The name of the TMX to process
* @param isEnforcedTMX If true, existing default translations will be overwritten in all cases
*/
void process(ExternalTMX tmx, boolean isEnforcedTMX) {
for (PrepareTMXEntry e : tmx.getEntries()) { // iterate by all entries in TMX
List<SourceTextEntry> list = existEntries.get(e.source);
if (list == null) {
continue; // there is no entries for this source
}
for (SourceTextEntry ste : list) { // for each TMX entry - get all sources in project
TMXEntry existTranslation = project.getTranslationInfo(ste);
String id = ste.getKey().id;
boolean hasICE = id != null && e.hasPropValue(ProjectTMX.PROP_XICE, id);
boolean has100PC = id != null && e.hasPropValue(ProjectTMX.PROP_X100PC, id);
if (!hasICE && !has100PC) {// TMXEntry without x-ids
boolean isDefaultTranslation = !isAltTranslation(e);
if (!existTranslation.defaultTranslation && isDefaultTranslation) {
// Existing translation is alt but the TMX entry is not.
continue;
}
if (!isDefaultTranslation && !altTranslationMatches(e, ste.getKey())) {
// TMX entry is an alternative translation that does not match this STE.
continue;
}
if (existTranslation.isTranslated()) { // default translation already exist
if (existTranslation.linked == TMXEntry.ExternalLinked.xAUTO
&& !StringUtil.equalsWithNulls(existTranslation.translation, e.translation)
|| isEnforcedTMX) {
// translation already from auto and really changed or translation comes
// from the enforce folder
setTranslation(ste, e, isDefaultTranslation, TMXEntry.ExternalLinked.xAUTO);
}
} else {
// default translation not exist - use from auto tmx
setTranslation(ste, e, isDefaultTranslation, TMXEntry.ExternalLinked.xAUTO);
}
} else {// TMXEntry with x-ids
if (!existTranslation.isTranslated() || existTranslation.defaultTranslation) {
// need to update if id in xICE or x100PC
if (hasICE) {
setTranslation(ste, e, false, TMXEntry.ExternalLinked.xICE);
} else if (has100PC) {
setTranslation(ste, e, false, TMXEntry.ExternalLinked.x100PC);
}
} else if (existTranslation.linked == TMXEntry.ExternalLinked.xICE
|| existTranslation.linked == TMXEntry.ExternalLinked.x100PC) {
// already contains x-ice
if (hasICE
&& !StringUtil.equalsWithNulls(existTranslation.translation, e.translation)) {
setTranslation(ste, e, false, TMXEntry.ExternalLinked.xICE);
}
} else if (existTranslation.linked == TMXEntry.ExternalLinked.x100PC) {
// already contains x-100pc
if (has100PC
&& !StringUtil.equalsWithNulls(existTranslation.translation, e.translation)) {
setTranslation(ste, e, false, TMXEntry.ExternalLinked.x100PC);
}
}
}
}
}
}
private boolean isAltTranslation(PrepareTMXEntry entry) {
boolean hasFileProp = false;
boolean hasOtherProp = false;
for (TMXProp p : entry.otherProperties) {
if (p.getType().equals(ProjectTMX.PROP_FILE)) {
hasFileProp = true;
} else if (p.getType().equals(ProjectTMX.PROP_ID)
|| p.getType().equals(ProjectTMX.PROP_NEXT)
|| p.getType().equals(ProjectTMX.PROP_PATH)
|| p.getType().equals(ProjectTMX.PROP_PREV)) {
hasOtherProp = true;
}
}
return EntryKey.isIgnoreFileContext() ? hasFileProp && hasOtherProp : hasFileProp;
}
private boolean altTranslationMatches(PrepareTMXEntry entry, EntryKey key) {
try {
for (TMXProp p : entry.otherProperties) {
if (p.getType().equals(ProjectTMX.PROP_FILE) && EntryKey.isIgnoreFileContext()) {
continue;
}
Field f = EntryKey.class.getField(p.getType());
Object value = f.get(key);
if (!value.equals(p.getValue())) {
return false;
}
}
return true;
} catch (Exception e) {
return false;
}
}
private void setTranslation(SourceTextEntry entry, PrepareTMXEntry trans, boolean defaultTranslation,
TMXEntry.ExternalLinked externalLinked) {
if (StringUtil.isEmpty(trans.note)) {
trans.note = null;
}
trans.source = entry.getSrcText();
TMXEntry newTrEntry;
if (trans.translation == null && trans.note == null) {
// no translation, no note
newTrEntry = null;
} else {
newTrEntry = new TMXEntry(trans, defaultTranslation, externalLinked);
}
project.projectTMX.setTranslation(entry, newTrEntry, defaultTranslation);
}
}