/**************************************************************************
OmegaT - Computer Assisted Translation (CAT) tool
with fuzzy matching, translation memory, keyword search,
glossaries, and translation leveraging into updated projects.
Copyright (C) 2013-2016 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.core.data;
import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.madlonkay.supertmxmerge.data.ITmx;
import org.madlonkay.supertmxmerge.data.ITu;
import org.madlonkay.supertmxmerge.data.ITuv;
import org.madlonkay.supertmxmerge.data.Key;
import org.madlonkay.supertmxmerge.data.ResolutionSet;
import org.madlonkay.supertmxmerge.data.WriteFailedException;
import org.madlonkay.supertmxmerge.util.ReflectionUtil;
/**
* A wrapper class for use with SuperTMXMerge.
*
* @author Aaron Madlon-Kay <aaron@madlon-kay.com>
*/
public final class SyncTMX implements ITmx {
private ProjectTMX tmx;
private final String name;
private final String sourceLanguage;
private final String targetLanguage;
private Map<Key, ITu> tuMap;
private Map<Key, ITuv> tuvMap;
public SyncTMX(ProjectTMX tmx, String name, String sourceLanguage, String targetLanguage) {
this.tmx = tmx;
this.name = name;
this.sourceLanguage = sourceLanguage;
this.targetLanguage = targetLanguage;
generateMaps();
}
private void generateMaps() {
tuvMap = new HashMap<Key, ITuv>();
tuMap = new HashMap<Key, ITu>();
for (Entry<String, TMXEntry> e : tmx.defaults.entrySet()) {
ITu tu = new SyncTu(e.getValue(), targetLanguage);
Key key = makeKey(e.getKey(), e.getValue());
assert (!tuMap.containsKey(key));
assert (!tuvMap.containsKey(key));
tuMap.put(key, tu);
tuvMap.put(key, tu.getTargetTuv());
}
for (Entry<EntryKey, TMXEntry> e : tmx.alternatives.entrySet()) {
ITu tu = new SyncTu(e.getValue(), targetLanguage);
Key key = makeKey(e.getKey(), e.getValue());
assert (!tuMap.containsKey(key));
assert (!tuvMap.containsKey(key));
tuMap.put(key, tu);
tuvMap.put(key, tu.getTargetTuv());
}
}
private Key makeKey(Object entryKey, TMXEntry tmxEntry) {
Key key = new Key(tmxEntry.source, entryKey);
if (entryKey instanceof EntryKey) {
EntryKey ek = (EntryKey) entryKey;
key.addProp("file", ek.file);
key.addProp("id", ek.id);
key.addProp("next", ek.next);
key.addProp("path", ek.path);
key.addProp("prev", ek.prev);
}
return key;
}
@Override
public String getSourceLanguage() {
return sourceLanguage;
}
@Override
public String getName() {
return name;
}
@Override
public int getSize() {
return tmx.alternatives.size() + tmx.defaults.size();
}
@Override
public Map<String, String> getMetadata() {
return Collections.emptyMap();
}
@Override
public ITmx applyChanges(ResolutionSet resolution) {
ProjectTMX originalData = clone(tmx);
for (Key key : resolution.toDelete) {
remove(key);
}
for (Entry<Key, ITuv> e : resolution.toReplace.entrySet()) {
remove(e.getKey());
add(e.getKey(), (TMXEntry) e.getValue().getUnderlyingRepresentation());
}
for (Entry<Key, ITu> e : resolution.toAdd.entrySet()) {
add(e.getKey(), (TMXEntry) e.getValue().getUnderlyingRepresentation());
}
ProjectTMX modifiedData = tmx;
this.tmx = originalData;
this.tuvMap = null;
this.tuMap = null;
return new SyncTMX(modifiedData, this.name, this.sourceLanguage, this.targetLanguage);
}
private void add(Key key, TMXEntry tuv) {
if (key.foreignKey instanceof String) {
tmx.defaults.put((String) key.foreignKey, tuv);
} else if (key.foreignKey instanceof EntryKey) {
tmx.alternatives.put((EntryKey) key.foreignKey, tuv);
} else {
throw new IllegalArgumentException(
"Cannot add key of type " + key.getClass().getName() + " to a " + getClass().getName());
}
}
private void remove(Key key) {
if (key.foreignKey instanceof String) {
tmx.defaults.remove((String) key.foreignKey);
} else if (key.foreignKey instanceof EntryKey) {
tmx.alternatives.remove((EntryKey) key.foreignKey);
} else {
throw new IllegalArgumentException(
"Cannot remove key of type " + key.getClass().getName() + " from a " + getClass().getName());
}
}
private static ProjectTMX clone(ProjectTMX tmx) {
ProjectTMX newTmx = new ProjectTMX();
for (Entry<EntryKey, TMXEntry> e : tmx.alternatives.entrySet()) {
newTmx.alternatives.put(e.getKey(), e.getValue());
}
for (Entry<String, TMXEntry> e : tmx.defaults.entrySet()) {
newTmx.defaults.put(e.getKey(), e.getValue());
}
return newTmx;
}
@Override
public void writeTo(File outputFile) throws WriteFailedException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Object getUnderlyingRepresentation() {
return tmx;
}
@Override
public ITu getTu(Key key) {
return tuMap.get(key);
}
@Override
public int size() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean isEmpty() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean containsKey(Object key) {
return tuvMap.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public ITuv get(Object key) {
return tuvMap.get(key);
}
@Override
public ITuv put(Key key, ITuv value) {
return tuvMap.put(key, value);
}
@Override
public ITuv remove(Object key) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void putAll(Map<? extends Key, ? extends ITuv> m) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void clear() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Set<Key> keySet() {
return tuvMap.keySet();
}
@Override
public Collection<ITuv> values() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Set<Entry<Key, ITuv>> entrySet() {
return tuvMap.entrySet();
}
private static class SyncTu implements ITu {
private final TMXEntry tmxEntry;
private final String targetLanguage;
SyncTu(TMXEntry tmxEntry, String targetLanguage) {
this.tmxEntry = tmxEntry;
this.targetLanguage = targetLanguage;
}
@Override
public ITuv getTargetTuv() {
return new SyncTuv(tmxEntry, targetLanguage);
}
@Override
public Object getUnderlyingRepresentation() {
return tmxEntry;
}
}
private static class SyncTuv implements ITuv {
private final TMXEntry tmxEntry;
private final String language;
private Map<String, String> props;
SyncTuv(TMXEntry tmxEntry, String language) {
this.tmxEntry = tmxEntry;
this.language = language;
}
@Override
public String getContent() {
return tmxEntry.translation;
}
@Override
public Map<String, String> getMetadata() {
if (props == null) {
props = Collections.unmodifiableMap(ReflectionUtil.simpleMembersToMap(tmxEntry));
}
return props;
}
@Override
public String getLanguage() {
return language;
}
@Override
public Object getUnderlyingRepresentation() {
return tmxEntry;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final SyncTuv other = (SyncTuv) obj;
return tmxEntry.equals(other.tmxEntry) && this.language.equals(other.language);
}
@Override
public int hashCode() {
int hash = 5;
hash = 89 * hash + (this.tmxEntry != null ? this.tmxEntry.hashCode() : 0);
hash = 89 * hash + (this.language != null ? this.language.hashCode() : 0);
return hash;
}
@Override
public boolean equivalentTo(ITuv o) {
if (o == null) {
return false;
}
if (!(o instanceof SyncTuv)) {
throw new IllegalArgumentException("Cannot check equivalence between SyncTuv and non-SyncTuv");
}
SyncTuv other = (SyncTuv) o;
return tmxEntry.equalsTranslation(other.tmxEntry);
}
}
}