// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.infobar;
import android.text.TextUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* A class that keeps the state of the different translation options and
* languages.
*/
public class TranslateOptions {
/**
* A container for Language Code and it's translated representation
* For example for Spanish when viewed from a French locale, this will contain es, Espagnol
**/
public static class TranslateLanguagePair {
public final String mLanguageCode;
public final String mLanguageRepresentation;
public TranslateLanguagePair(String languageCode, String languageRepresentation) {
assert languageCode != null;
assert languageRepresentation != null;
mLanguageCode = languageCode;
mLanguageRepresentation = languageRepresentation;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof TranslateLanguagePair)) {
return false;
}
TranslateLanguagePair other = (TranslateLanguagePair) obj;
return this.mLanguageCode.equals(other.mLanguageCode)
&& this.mLanguageRepresentation.equals(other.mLanguageRepresentation);
}
@Override
public int hashCode() {
return (mLanguageCode + mLanguageRepresentation).hashCode();
}
@Override
public String toString() {
return "mLanguageCode:" + mLanguageCode + " - mlanguageRepresentation "
+ mLanguageRepresentation;
}
}
// This would be an enum but they are not good for mobile.
// The checkBoundaries method below needs to be updated if new options are added.
private static final int NEVER_LANGUAGE = 0;
private static final int NEVER_DOMAIN = 1;
private static final int ALWAYS_LANGUAGE = 2;
private String mSourceLanguageCode;
private String mTargetLanguageCode;
private final ArrayList<TranslateLanguagePair> mAllLanguages;
// language code to translated language name map
// Conceptually final
private Map<String, String> mCodeToRepresentation;
// Will reflect the state before the object was ever modified
private final boolean[] mOriginalOptions;
private final String mOriginalSourceLanguageCode;
private final String mOriginalTargetLanguageCode;
private final boolean mTriggeredFromMenu;
private final boolean[] mOptions;
private TranslateOptions(String sourceLanguageCode, String targetLanguageCode,
ArrayList<TranslateLanguagePair> allLanguages, boolean neverLanguage,
boolean neverDomain, boolean alwaysLanguage, boolean triggeredFromMenu,
boolean[] originalOptions) {
mOptions = new boolean[3];
mOptions[NEVER_LANGUAGE] = neverLanguage;
mOptions[NEVER_DOMAIN] = neverDomain;
mOptions[ALWAYS_LANGUAGE] = alwaysLanguage;
if (originalOptions == null) {
mOriginalOptions = mOptions.clone();
} else {
mOriginalOptions = originalOptions.clone();
}
mSourceLanguageCode = sourceLanguageCode;
mTargetLanguageCode = targetLanguageCode;
mOriginalSourceLanguageCode = mSourceLanguageCode;
mOriginalTargetLanguageCode = mTargetLanguageCode;
mTriggeredFromMenu = triggeredFromMenu;
mAllLanguages = allLanguages;
mCodeToRepresentation = new HashMap<String, String>();
for (TranslateLanguagePair language : allLanguages) {
mCodeToRepresentation.put(language.mLanguageCode, language.mLanguageRepresentation);
}
}
public TranslateOptions(String sourceLanguageCode, String targetLanguageCode,
ArrayList<TranslateLanguagePair> allLanguages, boolean alwaysTranslate,
boolean triggeredFromMenu) {
this(sourceLanguageCode, targetLanguageCode, allLanguages, false, false, alwaysTranslate,
triggeredFromMenu, null);
}
/**
* Copy constructor
*/
public TranslateOptions(TranslateOptions other) {
this(other.mSourceLanguageCode, other.mTargetLanguageCode, other.mAllLanguages,
other.mOptions[NEVER_LANGUAGE], other.mOptions[NEVER_DOMAIN],
other.mOptions[ALWAYS_LANGUAGE], other.mTriggeredFromMenu, other.mOriginalOptions);
}
public String sourceLanguageName() {
if (isValidLanguageCode(mSourceLanguageCode)) {
return mCodeToRepresentation.get(mSourceLanguageCode);
}
return "";
}
public String targetLanguageName() {
if (isValidLanguageCode(mTargetLanguageCode)) {
return mCodeToRepresentation.get(mTargetLanguageCode);
}
return "";
}
public String sourceLanguageCode() {
return mSourceLanguageCode;
}
public String targetLanguageCode() {
return mTargetLanguageCode;
}
public boolean triggeredFromMenu() {
return mTriggeredFromMenu;
}
public boolean optionsChanged() {
return (!mSourceLanguageCode.equals(mOriginalSourceLanguageCode))
|| (!mTargetLanguageCode.equals(mOriginalTargetLanguageCode))
|| (mOptions[NEVER_LANGUAGE] != mOriginalOptions[NEVER_LANGUAGE])
|| (mOptions[NEVER_DOMAIN] != mOriginalOptions[NEVER_DOMAIN])
|| (mOptions[ALWAYS_LANGUAGE] != mOriginalOptions[ALWAYS_LANGUAGE]);
}
public List<TranslateLanguagePair> allLanguages() {
return mAllLanguages;
}
public boolean neverTranslateLanguageState() {
return mOptions[NEVER_LANGUAGE];
}
public boolean alwaysTranslateLanguageState() {
return mOptions[ALWAYS_LANGUAGE];
}
public boolean neverTranslateDomainState() {
return mOptions[NEVER_DOMAIN];
}
public boolean setSourceLanguage(String languageCode) {
boolean canSet = canSetLanguage(languageCode, mTargetLanguageCode);
if (canSet) {
mSourceLanguageCode = languageCode;
}
return canSet;
}
public boolean setTargetLanguage(String languageCode) {
boolean canSet = canSetLanguage(mSourceLanguageCode, languageCode);
if (canSet) {
mTargetLanguageCode = languageCode;
}
return canSet;
}
/**
* Sets the new state of never translate domain.
*
* @return true if the toggling was possible
*/
public boolean toggleNeverTranslateDomainState(boolean value) {
return toggleState(NEVER_DOMAIN, value);
}
/**
* Sets the new state of never translate language.
*
* @return true if the toggling was possible
*/
public boolean toggleNeverTranslateLanguageState(boolean value) {
// Do not toggle if we are activating NeverLanguge but AlwaysTranslate
// for a language pair with the same source language is already active.
if (mOptions[ALWAYS_LANGUAGE] && value) {
return false;
}
return toggleState(NEVER_LANGUAGE, value);
}
/**
* Sets the new state of never translate a language pair.
*
* @return true if the toggling was possible
*/
public boolean toggleAlwaysTranslateLanguageState(boolean value) {
// Do not toggle if we are activating AlwaysLanguge but NeverLanguage is active already.
if (mOptions[NEVER_LANGUAGE] && value) {
return false;
}
return toggleState(ALWAYS_LANGUAGE, value);
}
private boolean toggleState(int element, boolean newValue) {
if (!checkElementBoundaries(element)) return false;
mOptions[element] = newValue;
return true;
}
private boolean isValidLanguageCode(String languageCode) {
return !TextUtils.isEmpty(languageCode) && mCodeToRepresentation.containsKey(languageCode);
}
private boolean canSetLanguage(String sourceCode, String targetCode) {
return isValidLanguageCode(sourceCode) && isValidLanguageCode(targetCode)
&& !sourceCode.equals(targetCode);
}
private static boolean checkElementBoundaries(int element) {
return element >= NEVER_LANGUAGE && element <= ALWAYS_LANGUAGE;
}
@Override
public String toString() {
return new StringBuilder()
.append(sourceLanguageCode())
.append(" -> ")
.append(targetLanguageCode())
.append(" - ")
.append("Never Language:")
.append(mOptions[NEVER_LANGUAGE])
.append(" Always Language:")
.append(mOptions[ALWAYS_LANGUAGE])
.append(" Never Domain:")
.append(mOptions[NEVER_DOMAIN])
.toString();
}
}