A new wrapper to BidiFormatter whose methods return SafeHtml instead of String
Review at http://gwt-code-reviews.appspot.com/1234801
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9464 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/i18n/shared/BidiFormatter.java b/user/src/com/google/gwt/i18n/shared/BidiFormatter.java
index 69e1221..b6b728c 100644
--- a/user/src/com/google/gwt/i18n/shared/BidiFormatter.java
+++ b/user/src/com/google/gwt/i18n/shared/BidiFormatter.java
@@ -18,7 +18,6 @@
import com.google.gwt.i18n.client.HasDirection.Direction;
import com.google.gwt.i18n.client.LocaleInfo;
-import com.google.gwt.safehtml.shared.SafeHtmlUtils;
/**
* Utility class for formatting text for display in a potentially
@@ -61,63 +60,18 @@
* to the caller to insert the return value in the output.
*
*/
-public class BidiFormatter {
+public class BidiFormatter extends BidiFormatterBase {
- /**
- * A container class for direction-related string constants, e.g. Unicode
- * formatting characters.
- */
- static final class Format {
- /**
- * "left" string constant.
- */
- public static final String LEFT = "left";
-
- /**
- * Unicode "Left-To-Right Embedding" (LRE) character.
- */
- public static final char LRE = '\u202A';
-
- /**
- * Unicode "Left-To-Right Mark" (LRM) character.
- */
- public static final char LRM = '\u200E';
-
- /**
- * String representation of LRM.
- */
- public static final String LRM_STRING = Character.toString(LRM);
-
- /**
- * Unicode "Pop Directional Formatting" (PDF) character.
- */
- public static final char PDF = '\u202C';
-
- /**
- * "right" string constant.
- */
- public static final String RIGHT = "right";
-
- /**
- * Unicode "Right-To-Left Embedding" (RLE) character.
- */
- public static final char RLE = '\u202B';
-
- /**
- * Unicode "Right-To-Left Mark" (RLM) character.
- */
- public static final char RLM = '\u200F';
-
- /**
- * String representation of RLM.
- */
- public static final String RLM_STRING = Character.toString(RLM);
-
- // Not instantiable.
- private Format() {
+ static class Factory extends BidiFormatterBase.Factory<BidiFormatter> {
+ @Override
+ public BidiFormatter createInstance(Direction contextDir,
+ boolean alwaysSpan) {
+ return new BidiFormatter(contextDir, alwaysSpan);
}
}
+ private static Factory factory = new Factory();
+
/**
* Factory for creating an instance of BidiFormatter given the context
* direction. The default behavior of {@link #spanWrap} and its variations is
@@ -182,7 +136,7 @@
*/
public static BidiFormatter getInstance(Direction contextDir,
boolean alwaysSpan) {
- return new BidiFormatter(contextDir, alwaysSpan);
+ return factory.getInstance(contextDir, alwaysSpan);
}
/**
@@ -209,9 +163,6 @@
return getInstance(LocaleInfo.getCurrentLocale().isRTL(), alwaysSpan);
}
- private boolean alwaysSpan;
- private Direction contextDir;
-
/**
* @param contextDir The context direction
* @param alwaysSpan Whether {@link #spanWrap} (and its variations) should
@@ -220,8 +171,7 @@
* does not depend on the combination of directions
*/
private BidiFormatter(Direction contextDir, boolean alwaysSpan) {
- this.contextDir = contextDir;
- this.alwaysSpan = alwaysSpan;
+ super(contextDir, alwaysSpan);
}
/**
@@ -247,7 +197,7 @@
* in non-LTR context; else, the empty string.
*/
public String dirAttr(String str, boolean isHtml) {
- return knownDirAttr(BidiUtils.get().estimateDirection(str, isHtml));
+ return dirAttrBase(str, isHtml);
}
/**
@@ -255,53 +205,7 @@
* unknown context direction) returns "right".
*/
public String endEdge() {
- return contextDir == Direction.RTL ? Format.LEFT : Format.RIGHT;
- }
-
- /**
- * Like {@link #estimateDirection(String, boolean)}, but assumes {@code
- * isHtml} is false.
- *
- * @param str String whose direction is to be estimated
- * @return {@code str}'s estimated overall direction
- */
- public Direction estimateDirection(String str) {
- return BidiUtils.get().estimateDirection(str);
- }
-
- /**
- * Estimates the direction of a string using the best known general-purpose
- * method, i.e. using relative word counts. Direction.DEFAULT return value
- * indicates completely neutral input.
- *
- * @param str String whose direction is to be estimated
- * @param isHtml Whether {@code str} is HTML / HTML-escaped
- * @return {@code str}'s estimated overall direction
- */
- public Direction estimateDirection(String str, boolean isHtml) {
- return BidiUtils.get().estimateDirection(str, isHtml);
- }
-
- /**
- * Returns whether the span structure added by the formatter should be stable,
- * i.e., spans added even when the direction does not need to be declared.
- */
- public boolean getAlwaysSpan() {
- return alwaysSpan;
- }
-
- /**
- * Returns the context direction.
- */
- public Direction getContextDir() {
- return contextDir;
- }
-
- /**
- * Returns whether the context direction is RTL.
- */
- public boolean isRtlContext() {
- return contextDir == Direction.RTL;
+ return endEdgeBase();
}
/**
@@ -313,11 +217,7 @@
* in non-LTR context; else, the empty string.
*/
public String knownDirAttr(Direction dir) {
- if (dir != contextDir) {
- return dir == Direction.LTR ? "dir=ltr" : dir == Direction.RTL
- ? "dir=rtl" : "";
- }
- return "";
+ return knownDirAttrBase(dir);
}
/**
@@ -326,8 +226,7 @@
* default / unknown context direction.
*/
public String mark() {
- return contextDir == Direction.LTR ? Format.LRM_STRING
- : contextDir == Direction.RTL ? Format.RLM_STRING : "";
+ return markBase();
}
/**
@@ -353,9 +252,7 @@
* else, the empty string.
*/
public String markAfter(String str, boolean isHtml) {
- str = BidiUtils.get().stripHtmlIfNeeded(str, isHtml);
- return dirResetIfNeeded(str, BidiUtils.get().estimateDirection(str), false,
- true);
+ return markAfterBase(str, isHtml);
}
/**
@@ -407,8 +304,7 @@
* @return Input string after applying the above processing.
*/
public String spanWrap(String str, boolean isHtml, boolean dirReset) {
- Direction dir = BidiUtils.get().estimateDirection(str, isHtml);
- return spanWrapWithKnownDir(dir, str, isHtml, dirReset);
+ return spanWrapBase(str, isHtml, dirReset);
}
/**
@@ -466,26 +362,7 @@
*/
public String spanWrapWithKnownDir(Direction dir, String str, boolean isHtml,
boolean dirReset) {
- boolean dirCondition = dir != Direction.DEFAULT && dir != contextDir;
- String origStr = str;
- if (!isHtml) {
- str = SafeHtmlUtils.htmlEscape(str);
- }
-
- StringBuilder result = new StringBuilder();
- if (alwaysSpan || dirCondition) {
- result.append("<span");
- if (dirCondition) {
- result.append(" ");
- result.append(dir == Direction.RTL ? "dir=rtl" : "dir=ltr");
- }
- result.append(">" + str + "</span>");
- } else {
- result.append(str);
- }
- // origStr is passed (more efficient when isHtml is false).
- result.append(dirResetIfNeeded(origStr, dir, isHtml, dirReset));
- return result.toString();
+ return spanWrapWithKnownDirBase(dir, str, isHtml, dirReset);
}
/**
@@ -493,7 +370,7 @@
* unknown context direction) returns "left".
*/
public String startEdge() {
- return contextDir == Direction.RTL ? Format.RIGHT : Format.LEFT;
+ return startEdgeBase();
}
/**
@@ -545,8 +422,7 @@
* @return Input string after applying the above processing.
*/
public String unicodeWrap(String str, boolean isHtml, boolean dirReset) {
- Direction dir = BidiUtils.get().estimateDirection(str, isHtml);
- return unicodeWrapWithKnownDir(dir, str, isHtml, dirReset);
+ return unicodeWrapBase(str, isHtml, dirReset);
}
/**
@@ -605,45 +481,6 @@
*/
public String unicodeWrapWithKnownDir(Direction dir, String str,
boolean isHtml, boolean dirReset) {
- StringBuilder result = new StringBuilder();
- if (dir != Direction.DEFAULT && dir != contextDir) {
- result.append(dir == Direction.RTL ? Format.RLE : Format.LRE);
- result.append(str);
- result.append(Format.PDF);
- } else {
- result.append(str);
- }
-
- result.append(dirResetIfNeeded(str, dir, isHtml, dirReset));
- return result.toString();
- }
-
- /**
- * Returns a unicode BiDi mark matching the context direction (LRM or RLM) if
- * {@code dirReset}, and if the overall direction or the exit direction of
- * {@code str} are opposite to the context direction. Otherwise returns the
- * empty string.
- *
- * @param str The input string
- * @param dir {@code str}'s overall direction
- * @param isHtml Whether {@code str} is HTML / HTML-escaped
- * @param dirReset Whether to perform the reset
- * @return A unicode BiDi mark or the empty string.
- */
- private String dirResetIfNeeded(String str, Direction dir, boolean isHtml,
- boolean dirReset) {
- // endsWithRtl and endsWithLtr are called only if needed (short-circuit).
- if (dirReset
- && ((contextDir == Direction.LTR &&
- (dir == Direction.RTL ||
- BidiUtils.get().endsWithRtl(str, isHtml))) ||
- (contextDir == Direction.RTL &&
- (dir == Direction.LTR ||
- BidiUtils.get().endsWithLtr(str, isHtml))))) {
- return contextDir == Direction.LTR ? Format.LRM_STRING
- : Format.RLM_STRING;
- } else {
- return "";
- }
+ return unicodeWrapWithKnownDirBase(dir, str, isHtml, dirReset);
}
}
diff --git a/user/src/com/google/gwt/i18n/shared/BidiFormatterBase.java b/user/src/com/google/gwt/i18n/shared/BidiFormatterBase.java
new file mode 100644
index 0000000..91f83fe
--- /dev/null
+++ b/user/src/com/google/gwt/i18n/shared/BidiFormatterBase.java
@@ -0,0 +1,360 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.i18n.shared;
+
+import com.google.gwt.i18n.client.HasDirection.Direction;
+import com.google.gwt.safehtml.shared.SafeHtmlUtils;
+
+/**
+ * Base class for {@link BidiFormatter} and {@link SafeHtmlBidiFormatter} that
+ * contains their common implementation.
+ */
+public abstract class BidiFormatterBase {
+
+ /**
+ * Abstract factory class for BidiFormatterBase.
+ * BidiFormatterBase subclasses will usually have a non-abstract inner Factory
+ * class subclassed from this one, and use a static member of that class in
+ * order to prevent the needless creation of objects. For example, see
+ * {@link BidiFormatter}.
+ */
+ protected abstract static class Factory<T extends BidiFormatterBase> {
+ private T[] instances;
+
+ @SuppressWarnings("unchecked")
+ public Factory() {
+ instances = (T[]) new BidiFormatterBase[6];
+ }
+
+ public abstract T createInstance(Direction contextDir,
+ boolean alwaysSpan);
+
+ public T getInstance(Direction contextDir,
+ boolean alwaysSpan) {
+ int index = calculateIndex(contextDir, alwaysSpan);
+ T formatter = instances[index];
+ if (formatter == null) {
+ formatter = createInstance(contextDir, alwaysSpan);
+ instances[index] = formatter;
+ }
+ return formatter;
+ }
+
+ // Index should be in the range [0, 5].
+ private int calculateIndex(Direction contextDir, boolean alwaysSpan) {
+ int i = contextDir == Direction.LTR ? 0 : contextDir == Direction.RTL ? 1
+ : 2;
+ if (alwaysSpan) {
+ i += 3;
+ }
+ return i;
+ }
+ }
+
+ /**
+ * A container class for direction-related string constants, e.g. Unicode
+ * formatting characters.
+ */
+ static final class Format {
+ /**
+ * "left" string constant.
+ */
+ public static final String LEFT = "left";
+
+ /**
+ * Unicode "Left-To-Right Embedding" (LRE) character.
+ */
+ public static final char LRE = '\u202A';
+
+ /**
+ * Unicode "Left-To-Right Mark" (LRM) character.
+ */
+ public static final char LRM = '\u200E';
+
+ /**
+ * String representation of LRM.
+ */
+ public static final String LRM_STRING = Character.toString(LRM);
+
+ /**
+ * Unicode "Pop Directional Formatting" (PDF) character.
+ */
+ public static final char PDF = '\u202C';
+
+ /**
+ * "right" string constant.
+ */
+ public static final String RIGHT = "right";
+
+ /**
+ * Unicode "Right-To-Left Embedding" (RLE) character.
+ */
+ public static final char RLE = '\u202B';
+
+ /**
+ * Unicode "Right-To-Left Mark" (RLM) character.
+ */
+ public static final char RLM = '\u200F';
+
+ /**
+ * String representation of RLM.
+ */
+ public static final String RLM_STRING = Character.toString(RLM);
+
+ // Not instantiable.
+ private Format() {
+ }
+ }
+
+ private boolean alwaysSpan;
+ private Direction contextDir;
+
+ protected BidiFormatterBase(Direction contextDir, boolean alwaysSpan) {
+ this.contextDir = contextDir;
+ this.alwaysSpan = alwaysSpan;
+ }
+
+ /**
+ * Like {@link #estimateDirection(String, boolean)}, but assumes {@code
+ * isHtml} is false.
+ *
+ * @param str String whose direction is to be estimated
+ * @return {@code str}'s estimated overall direction
+ */
+ public Direction estimateDirection(String str) {
+ return BidiUtils.get().estimateDirection(str);
+ }
+
+ /**
+ * Estimates the direction of a string using the best known general-purpose
+ * method, i.e. using relative word counts. Direction.DEFAULT return value
+ * indicates completely neutral input.
+ *
+ * @param str String whose direction is to be estimated
+ * @param isHtml Whether {@code str} is HTML / HTML-escaped
+ * @return {@code str}'s estimated overall direction
+ */
+ public Direction estimateDirection(String str, boolean isHtml) {
+ return BidiUtils.get().estimateDirection(str, isHtml);
+ }
+
+ /**
+ * Returns whether the span structure added by the formatter should be stable,
+ * i.e., spans added even when the direction does not need to be declared.
+ */
+ public boolean getAlwaysSpan() {
+ return alwaysSpan;
+ }
+
+ /**
+ * Returns the context direction.
+ */
+ public Direction getContextDir() {
+ return contextDir;
+ }
+
+ /**
+ * Returns whether the context direction is RTL.
+ */
+ public boolean isRtlContext() {
+ return contextDir == Direction.RTL;
+ }
+
+ /**
+ * @see BidiFormatter#dirAttr(String, boolean)
+ *
+ * @param str String whose direction is to be estimated
+ * @param isHtml Whether {@code str} is HTML / HTML-escaped
+ * @return "dir=rtl" for RTL text in non-RTL context; "dir=ltr" for LTR text
+ * in non-LTR context; else, the empty string.
+ */
+ protected String dirAttrBase(String str, boolean isHtml) {
+ return knownDirAttrBase(BidiUtils.get().estimateDirection(str, isHtml));
+ }
+
+ /**
+ * @see BidiFormatter#endEdge
+ */
+ protected String endEdgeBase() {
+ return contextDir == Direction.RTL ? Format.LEFT : Format.RIGHT;
+ }
+
+ /**
+ * @see BidiFormatter#knownDirAttr(Direction)
+ *
+ * @param dir Given direction
+ * @return "dir=rtl" for RTL text in non-RTL context; "dir=ltr" for LTR text
+ * in non-LTR context; else, the empty string.
+ */
+ protected String knownDirAttrBase(Direction dir) {
+ if (dir != contextDir) {
+ return dir == Direction.LTR ? "dir=ltr" : dir == Direction.RTL
+ ? "dir=rtl" : "";
+ }
+ return "";
+ }
+
+ /**
+ * @see BidiFormatter#markAfter(String, boolean)
+ *
+ * @param str String after which the mark may need to appear
+ * @param isHtml Whether {@code str} is HTML / HTML-escaped
+ * @return LRM for RTL text in LTR context; RLM for LTR text in RTL context;
+ * else, the empty string.
+ */
+ protected String markAfterBase(String str, boolean isHtml) {
+ str = BidiUtils.get().stripHtmlIfNeeded(str, isHtml);
+ return dirResetIfNeeded(str, BidiUtils.get().estimateDirection(str), false,
+ true);
+ }
+
+ /**
+ * @see BidiFormatter#mark()
+ */
+ protected String markBase() {
+ return contextDir == Direction.LTR ? Format.LRM_STRING
+ : contextDir == Direction.RTL ? Format.RLM_STRING : "";
+ }
+
+ /**
+ * @see BidiFormatter#spanWrap(String, boolean, boolean)
+ *
+ * @param str The input string
+ * @param isHtml Whether {@code str} is HTML / HTML-escaped
+ * @param dirReset Whether to append a trailing unicode bidi mark matching the
+ * context direction, when needed, to prevent the possible garbling
+ * of whatever may follow {@code str}
+ * @return Input string after applying the above processing.
+ */
+ protected String spanWrapBase(String str, boolean isHtml, boolean dirReset) {
+ Direction dir = BidiUtils.get().estimateDirection(str, isHtml);
+ return spanWrapWithKnownDirBase(dir, str, isHtml, dirReset);
+ }
+
+ /**
+ * @see BidiFormatter#spanWrapWithKnownDir(Direction, String, boolean, boolean)
+ *
+ * @param dir {@code str}'s direction
+ * @param str The input string
+ * @param isHtml Whether {@code str} is HTML / HTML-escaped
+ * @param dirReset Whether to append a trailing unicode bidi mark matching the
+ * context direction, when needed, to prevent the possible garbling
+ * of whatever may follow {@code str}
+ * @return Input string after applying the above processing.
+ */
+ protected String spanWrapWithKnownDirBase(Direction dir, String str,
+ boolean isHtml, boolean dirReset) {
+ boolean dirCondition = dir != Direction.DEFAULT && dir != contextDir;
+ String origStr = str;
+ if (!isHtml) {
+ str = SafeHtmlUtils.htmlEscape(str);
+ }
+
+ StringBuilder result = new StringBuilder();
+ if (alwaysSpan || dirCondition) {
+ result.append("<span");
+ if (dirCondition) {
+ result.append(" ");
+ result.append(dir == Direction.RTL ? "dir=rtl" : "dir=ltr");
+ }
+ result.append(">" + str + "</span>");
+ } else {
+ result.append(str);
+ }
+ // origStr is passed (more efficient when isHtml is false).
+ result.append(dirResetIfNeeded(origStr, dir, isHtml, dirReset));
+ return result.toString();
+ }
+
+ /**
+ * @see BidiFormatter#startEdge
+ */
+ protected String startEdgeBase() {
+ return contextDir == Direction.RTL ? Format.RIGHT : Format.LEFT;
+ }
+
+ /**
+ * @see BidiFormatter#unicodeWrap(String, boolean, boolean)
+ *
+ * @param str The input string
+ * @param isHtml Whether {@code str} is HTML / HTML-escaped
+ * @param dirReset Whether to append a trailing unicode bidi mark matching the
+ * context direction, when needed, to prevent the possible garbling
+ * of whatever may follow {@code str}
+ * @return Input string after applying the above processing.
+ */
+ protected String unicodeWrapBase(String str, boolean isHtml,
+ boolean dirReset) {
+ Direction dir = BidiUtils.get().estimateDirection(str, isHtml);
+ return unicodeWrapWithKnownDirBase(dir, str, isHtml, dirReset);
+ }
+
+ /**
+ * @see BidiFormatter#unicodeWrapWithKnownDir(Direction, String, boolean, boolean)
+ *
+ * @param dir {@code str}'s direction
+ * @param str The input string
+ * @param isHtml Whether {@code str} is HTML / HTML-escaped
+ * @param dirReset Whether to append a trailing unicode bidi mark matching the
+ * context direction, when needed, to prevent the possible garbling
+ * of whatever may follow {@code str}
+ * @return Input string after applying the above processing.
+ */
+ protected String unicodeWrapWithKnownDirBase(Direction dir, String str,
+ boolean isHtml, boolean dirReset) {
+ StringBuilder result = new StringBuilder();
+ if (dir != Direction.DEFAULT && dir != contextDir) {
+ result.append(dir == Direction.RTL ? Format.RLE : Format.LRE);
+ result.append(str);
+ result.append(Format.PDF);
+ } else {
+ result.append(str);
+ }
+
+ result.append(dirResetIfNeeded(str, dir, isHtml, dirReset));
+ return result.toString();
+ }
+
+ /**
+ * Returns a unicode BiDi mark matching the context direction (LRM or RLM) if
+ * {@code dirReset}, and if the overall direction or the exit direction of
+ * {@code str} are opposite to the context direction. Otherwise returns the
+ * empty string.
+ *
+ * @param str The input string
+ * @param dir {@code str}'s overall direction
+ * @param isHtml Whether {@code str} is HTML / HTML-escaped
+ * @param dirReset Whether to perform the reset
+ * @return A unicode BiDi mark or the empty string.
+ */
+ private String dirResetIfNeeded(String str, Direction dir, boolean isHtml,
+ boolean dirReset) {
+ // endsWithRtl and endsWithLtr are called only if needed (short-circuit).
+ if (dirReset
+ && ((contextDir == Direction.LTR &&
+ (dir == Direction.RTL ||
+ BidiUtils.get().endsWithRtl(str, isHtml))) ||
+ (contextDir == Direction.RTL &&
+ (dir == Direction.LTR ||
+ BidiUtils.get().endsWithLtr(str, isHtml))))) {
+ return contextDir == Direction.LTR ? Format.LRM_STRING
+ : Format.RLM_STRING;
+ } else {
+ return "";
+ }
+ }
+}
diff --git a/user/src/com/google/gwt/i18n/shared/SafeHtmlBidiFormatter.java b/user/src/com/google/gwt/i18n/shared/SafeHtmlBidiFormatter.java
new file mode 100644
index 0000000..592a144
--- /dev/null
+++ b/user/src/com/google/gwt/i18n/shared/SafeHtmlBidiFormatter.java
@@ -0,0 +1,474 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.i18n.shared;
+
+import com.google.gwt.i18n.client.HasDirection.Direction;
+import com.google.gwt.i18n.client.LocaleInfo;
+import com.google.gwt.safehtml.shared.SafeHtml;
+import com.google.gwt.safehtml.shared.SafeHtmlUtils;
+
+import java.util.HashMap;
+
+/**
+ * A wrapper to {@link BidiFormatter} whose methods return {@code SafeHtml}
+ * instead of {@code String}.
+ */
+public class SafeHtmlBidiFormatter extends BidiFormatterBase {
+
+ static class Factory extends BidiFormatterBase.Factory<SafeHtmlBidiFormatter> {
+ @Override
+ public SafeHtmlBidiFormatter createInstance(Direction contextDir,
+ boolean alwaysSpan) {
+ return new SafeHtmlBidiFormatter(contextDir, alwaysSpan);
+ }
+ }
+
+ private static Factory factory = new Factory();
+
+ private static HashMap<String, SafeHtml> cachedSafeHtmlValues = null;
+
+ /**
+ * Factory for creating an instance of SafeHtmlBidiFormatter given the context
+ * direction. The default behavior of {@link #spanWrap} and its variations is
+ * set to avoid span wrapping unless it's necessary ('dir' attribute needs to
+ * be set).
+ *
+ * @param rtlContext Whether the context direction is RTL.
+ * In one simple use case, the context direction would simply be the
+ * locale direction, which can be retrieved using
+ * {@code LocaleInfo.getCurrentLocale().isRTL()}
+ */
+ public static SafeHtmlBidiFormatter getInstance(boolean rtlContext) {
+ return getInstance(rtlContext, false);
+ }
+
+ /**
+ * Factory for creating an instance of SafeHtmlBidiFormatter given the context
+ * direction and the desired span wrapping behavior (see below).
+ *
+ * @param rtlContext Whether the context direction is RTL. See an example of
+ * a simple use case at {@link #getInstance(boolean)}
+ * @param alwaysSpan Whether {@link #spanWrap} (and its variations) should
+ * always use a 'span' tag, even when the input direction is neutral
+ * or matches the context, so that the DOM structure of the output
+ * does not depend on the combination of directions
+ */
+ public static SafeHtmlBidiFormatter getInstance(boolean rtlContext,
+ boolean alwaysSpan) {
+ return getInstance(rtlContext ? Direction.RTL : Direction.LTR, alwaysSpan);
+ }
+
+ /**
+ * Factory for creating an instance of SafeHtmlBidiFormatter given the context
+ * direction. The default behavior of {@link #spanWrap} and its variations is
+ * set to avoid span wrapping unless it's necessary ('dir' attribute needs to
+ * be set).
+ *
+ * @param contextDir The context direction. See an example of a simple use
+ * case at {@link #getInstance(boolean)}. Note: Direction.DEFAULT
+ * indicates unknown context direction. Try not to use it, since it
+ * is impossible to reset the direction back to the context when it
+ * is unknown
+ */
+ public static SafeHtmlBidiFormatter getInstance(Direction contextDir) {
+ return getInstance(contextDir, false);
+ }
+
+ /**
+ * Factory for creating an instance of SafeHtmlBidiFormatter given the context
+ * direction and the desired span wrapping behavior (see below).
+ *
+ * @param contextDir The context direction. See an example of a simple use
+ * case at {@link #getInstance(boolean)}. Note: Direction.DEFAULT
+ * indicates unknown context direction. Try not to use it, since it
+ * is impossible to reset the direction back to the context when it
+ * is unknown
+ * @param alwaysSpan Whether {@link #spanWrap} (and its variations) should
+ * always use a 'span' tag, even when the input direction is neutral
+ * or matches the context, so that the DOM structure of the output
+ * does not depend on the combination of directions
+ */
+ public static SafeHtmlBidiFormatter getInstance(Direction contextDir,
+ boolean alwaysSpan) {
+ return factory.getInstance(contextDir, alwaysSpan);
+ }
+
+ /**
+ * Factory for creating an instance of SafeHtmlBidiFormatter whose context
+ * direction matches the current locale's direction. The default behavior of
+ * {@link #spanWrap} and its variations is set to avoid span wrapping unless
+ * it's necessary ('dir' attribute needs to be set).
+ */
+ public static SafeHtmlBidiFormatter getInstanceForCurrentLocale() {
+ return getInstanceForCurrentLocale(false);
+ }
+
+ /**
+ * Factory for creating an instance of SafeHtmlBidiFormatter whose context
+ * direction matches the current locale's direction, and given the desired
+ * span wrapping behavior (see below).
+ *
+ * @param alwaysSpan Whether {@link #spanWrap} (and its variations) should
+ * always use a 'span' tag, even when the input direction is neutral
+ * or matches the context, so that the DOM structure of the output
+ * does not depend on the combination of directions
+ */
+ public static SafeHtmlBidiFormatter getInstanceForCurrentLocale(
+ boolean alwaysSpan) {
+ return getInstance(LocaleInfo.getCurrentLocale().isRTL(), alwaysSpan);
+ }
+
+ /**
+ * @param contextDir The context direction
+ * @param alwaysSpan Whether {@link #spanWrap} (and its variations) should
+ * always use a 'span' tag, even when the input direction is neutral
+ * or matches the context, so that the DOM structure of the output
+ * does not depend on the combination of directions
+ */
+ private SafeHtmlBidiFormatter(Direction contextDir, boolean alwaysSpan) {
+ super(contextDir, alwaysSpan);
+ }
+
+ /**
+ * @see BidiFormatter#dirAttr(String, boolean)
+ *
+ * @param html Html whose direction is to be estimated
+ * @return "dir=rtl" for RTL text in non-RTL context; "dir=ltr" for LTR text
+ * in non-LTR context; else, the empty string.
+ */
+ public SafeHtml dirAttr(SafeHtml html) {
+ return cachedSafeHtml(dirAttrBase(html.asString(), true));
+ }
+
+ /**
+ * @see BidiFormatter#dirAttr
+ *
+ * @param str String whose direction is to be estimated
+ * @return "dir=rtl" for RTL text in non-RTL context; "dir=ltr" for LTR text
+ * in non-LTR context; else, the empty string.
+ */
+ public SafeHtml dirAttr(String str) {
+ return cachedSafeHtml(dirAttrBase(str, false));
+ }
+
+ /**
+ * Returns "left" for RTL context direction. Otherwise (LTR or default /
+ * unknown context direction) returns "right".
+ */
+ public SafeHtml endEdge() {
+ return cachedSafeHtml(endEdgeBase());
+ }
+
+ /**
+ * @see BidiFormatterBase#estimateDirection(String, boolean)
+ *
+ * @param html Html whose direction is to be estimated
+ * @return {@code html}'s estimated overall direction
+ */
+ public Direction estimateDirection(SafeHtml html) {
+ return estimateDirection(html.asString(), true);
+ }
+
+ /**
+ * @see BidiFormatter#knownDirAttr
+ *
+ * @param dir Given direction
+ * @return "dir=rtl" for RTL text in non-RTL context; "dir=ltr" for LTR text
+ * in non-LTR context; else, the empty string.
+ */
+ public SafeHtml knownDirAttr(Direction dir) {
+ return cachedSafeHtml(knownDirAttrBase(dir));
+ }
+
+ /**
+ * @see BidiFormatter#mark
+ */
+ public SafeHtml mark() {
+ return cachedSafeHtml(markBase());
+ }
+
+ /**
+ * @see BidiFormatter#markAfter
+ *
+ * @param html Html after which the mark may need to appear
+ * @return LRM for RTL text in LTR context; RLM for LTR text in RTL context;
+ * else, the empty string.
+ */
+ public SafeHtml markAfter(SafeHtml html) {
+ return cachedSafeHtml(markAfterBase(html.asString(), true));
+ }
+
+ /**
+ * @see BidiFormatter#markAfter
+ *
+ * @param str String after which the mark may need to appear
+ * @return LRM for RTL text in LTR context; RLM for LTR text in RTL context;
+ * else, the empty string.
+ */
+ public SafeHtml markAfter(String str) {
+ return cachedSafeHtml(markAfterBase(str, false));
+ }
+
+ /**
+ * @see BidiFormatter#spanWrap(String, boolean)
+ *
+ * @param html The input html
+ * @return Input html after applying the above processing.
+ */
+ public SafeHtml spanWrap(SafeHtml html) {
+ return spanWrap(html, true);
+ }
+
+ /**
+ * @see BidiFormatter#spanWrap(String, boolean, boolean)
+ *
+ * @param html The input html
+ * @param dirReset Whether to append a trailing unicode bidi mark matching the
+ * context direction, when needed, to prevent the possible garbling
+ * of whatever may follow {@code html}
+ * @return Input html after applying the above processing.
+ */
+ public SafeHtml spanWrap(SafeHtml html, boolean dirReset) {
+ return SafeHtmlUtils.fromTrustedString(
+ spanWrapBase(html.asString(), true, dirReset));
+ }
+
+ /**
+ * @see BidiFormatter#spanWrap(String)
+ *
+ * @param str The input string
+ * @return Input string after applying the above processing.
+ */
+ public SafeHtml spanWrap(String str) {
+ return spanWrap(str, true);
+ }
+
+ /**
+ * @see BidiFormatter#spanWrap(String, boolean, boolean)
+ *
+ * @param str The input string
+ * @param dirReset Whether to append a trailing unicode bidi mark matching the
+ * context direction, when needed, to prevent the possible garbling
+ * of whatever may follow {@code str}
+ * @return Input string after applying the above processing.
+ */
+ public SafeHtml spanWrap(String str, boolean dirReset) {
+ // This is safe since spanWrapBase escapes plain-text input.
+ return SafeHtmlUtils.fromTrustedString(spanWrapBase(str, false, dirReset));
+ }
+
+ /**
+ * @see BidiFormatter#spanWrapWithKnownDir(
+ * com.google.gwt.i18n.client.HasDirection.Direction, String, boolean)
+ *
+ * @param dir {@code str}'s direction
+ * @param html The input html
+ * @return Input html after applying the above processing.
+ */
+ public SafeHtml spanWrapWithKnownDir(Direction dir, SafeHtml html) {
+ return spanWrapWithKnownDir(dir, html, true);
+ }
+
+ /**
+ * @see BidiFormatter#spanWrapWithKnownDir(
+ * com.google.gwt.i18n.client.HasDirection.Direction, String, boolean, boolean)
+ *
+ * @param dir {@code html}'s direction
+ * @param html The input html
+ * @param dirReset Whether to append a trailing unicode bidi mark matching the
+ * context direction, when needed, to prevent the possible garbling
+ * of whatever may follow {@code html}
+ * @return Input html after applying the above processing.
+ */
+ public SafeHtml spanWrapWithKnownDir(Direction dir, SafeHtml html,
+ boolean dirReset) {
+ return SafeHtmlUtils.fromTrustedString(
+ spanWrapWithKnownDirBase(dir, html.asString(), true, dirReset));
+ }
+
+ /**
+ * @see BidiFormatter#spanWrapWithKnownDir(
+ * com.google.gwt.i18n.client.HasDirection.Direction, String)
+ *
+ * @param dir {@code str}'s direction
+ * @param str The input string
+ * @return Input string after applying the above processing.
+ */
+ public SafeHtml spanWrapWithKnownDir(Direction dir, String str) {
+ return spanWrapWithKnownDir(dir, str, true);
+ }
+
+ /**
+ * @see BidiFormatter#spanWrapWithKnownDir(
+ * com.google.gwt.i18n.client.HasDirection.Direction, String, boolean, boolean)
+ *
+ * @param dir {@code str}'s direction
+ * @param str The input string
+ * @param dirReset Whether to append a trailing unicode bidi mark matching the
+ * context direction, when needed, to prevent the possible garbling
+ * of whatever may follow {@code str}
+ * @return Input string after applying the above processing.
+ */
+ public SafeHtml spanWrapWithKnownDir(Direction dir, String str,
+ boolean dirReset) {
+ // This is safe since spanWrapWithKnownDirBase escapes plain-text input.
+ return SafeHtmlUtils.fromTrustedString(
+ spanWrapWithKnownDirBase(dir, str, false, dirReset));
+ }
+
+ /**
+ * Returns "right" for RTL context direction. Otherwise (LTR or default /
+ * unknown context direction) returns "left".
+ */
+ public SafeHtml startEdge() {
+ return cachedSafeHtml(startEdgeBase());
+ }
+
+ /**
+ * @see BidiFormatter#unicodeWrap(String, boolean)
+ *
+ * @param html The input html
+ * @return Input html after applying the above processing.
+ */
+ public SafeHtml unicodeWrap(SafeHtml html) {
+ return unicodeWrap(html, true);
+ }
+
+ /**
+ * @see BidiFormatter#unicodeWrap(String, boolean, boolean)
+ *
+ * @param html The input html
+ * @param dirReset Whether to append a trailing unicode bidi mark matching the
+ * context direction, when needed, to prevent the possible garbling
+ * of whatever may follow {@code html}
+ * @return Input html after applying the above processing.
+ */
+ public SafeHtml unicodeWrap(SafeHtml html, boolean dirReset) {
+ return SafeHtmlUtils.fromTrustedString(
+ unicodeWrapBase(html.asString(), true, dirReset));
+ }
+
+ /**
+ * @see BidiFormatter#unicodeWrap(String)
+ *
+ * @param str The input string
+ * @return Input string after applying the above processing.
+ */
+ public SafeHtml unicodeWrap(String str) {
+ return unicodeWrap(str, true);
+ }
+
+ /**
+ * @see BidiFormatter#unicodeWrap(String, boolean, boolean)
+ *
+ * @param str The input string
+ * @param dirReset Whether to append a trailing unicode bidi mark matching the
+ * context direction, when needed, to prevent the possible garbling
+ * of whatever may follow {@code str}
+ * @return Input string after applying the above processing.
+ */
+ public SafeHtml unicodeWrap(String str, boolean dirReset) {
+ // unicodeWrapBase does not HTML-escape, so its return value is not trusted.
+ return SafeHtmlUtils.fromString(unicodeWrapBase(str, false, dirReset));
+ }
+
+ /**
+ * @see BidiFormatter#unicodeWrapWithKnownDir(
+ * com.google.gwt.i18n.client.HasDirection.Direction, String, boolean)
+ *
+ * @param dir {@code html}'s direction
+ * @param html The input html
+ * @return Input html after applying the above processing.
+ */
+ public SafeHtml unicodeWrapWithKnownDir(Direction dir, SafeHtml html) {
+ return unicodeWrapWithKnownDir(dir, html, true);
+ }
+
+ /**
+ * @see BidiFormatter#unicodeWrapWithKnownDir(
+ * com.google.gwt.i18n.client.HasDirection.Direction, String, boolean, boolean)
+ *
+ * @param dir {@code html}'s direction
+ * @param html The input html
+ * @param dirReset Whether to append a trailing unicode bidi mark matching the
+ * context direction, when needed, to prevent the possible garbling
+ * of whatever may follow {@code html}
+ * @return Input html after applying the above processing.
+ */
+ public SafeHtml unicodeWrapWithKnownDir(Direction dir, SafeHtml html,
+ boolean dirReset) {
+ return SafeHtmlUtils.fromTrustedString(
+ unicodeWrapWithKnownDirBase(dir, html.asString(), true, dirReset));
+ }
+
+ /**
+ * @see BidiFormatter#unicodeWrapWithKnownDir(
+ * com.google.gwt.i18n.client.HasDirection.Direction, String)
+ *
+ * @param dir {@code str}'s direction
+ * @param str The input string
+ * @return Input string after applying the above processing.
+ */
+ public SafeHtml unicodeWrapWithKnownDir(Direction dir, String str) {
+ return unicodeWrapWithKnownDir(dir, str, true);
+ }
+
+ /**
+ * @see BidiFormatter#unicodeWrapWithKnownDir(
+ * com.google.gwt.i18n.client.HasDirection.Direction, String, boolean, boolean)
+ *
+ * @param dir {@code str}'s direction
+ * @param str The input string
+ * @param dirReset Whether to append a trailing unicode bidi mark matching the
+ * context direction, when needed, to prevent the possible garbling
+ * of whatever may follow {@code str}
+ * @return Input string after applying the above processing.
+ */
+ public SafeHtml unicodeWrapWithKnownDir(Direction dir, String str,
+ boolean dirReset) {
+ /*
+ * unicodeWrapWithKnownDirBase does not HTML-escape, so its return value is
+ * not trusted.
+ */
+ return SafeHtmlUtils.fromString(
+ unicodeWrapWithKnownDirBase(dir, str, false, dirReset));
+ }
+
+ /**
+ * Converts an input string into a SafeHtml. Input String must be safe (see
+ * {@link com.google.gwt.safehtml.shared.SafeHtml}).
+ * Implementation: first, tries to find the input in the static map,
+ * {@link #cachedSafeHtmlValues}. If not found, creates a SafeHtml instance
+ * for the string and adds it to the map.
+ *
+ * @param str String to search for. Must be safe (see
+ * {@link com.google.gwt.safehtml.shared.SafeHtml}).
+ *
+ * @return Input as SafeHtml
+ */
+ private SafeHtml cachedSafeHtml(String str) {
+ if (cachedSafeHtmlValues == null) {
+ cachedSafeHtmlValues = new HashMap<String, SafeHtml>();
+ }
+ SafeHtml entry = cachedSafeHtmlValues.get(str);
+ if (entry == null) {
+ entry = SafeHtmlUtils.fromString(str);
+ cachedSafeHtmlValues.put(str, entry);
+ }
+ return entry;
+ }
+}
diff --git a/user/test/com/google/gwt/i18n/shared/BidiFormatterBaseTest.java b/user/test/com/google/gwt/i18n/shared/BidiFormatterBaseTest.java
new file mode 100644
index 0000000..1936ed0
--- /dev/null
+++ b/user/test/com/google/gwt/i18n/shared/BidiFormatterBaseTest.java
@@ -0,0 +1,359 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.i18n.shared;
+
+import static com.google.gwt.i18n.shared.BidiFormatterBase.Format.*;
+
+import com.google.gwt.i18n.client.HasDirection.Direction;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for {@link BidiFormatterBase}.
+ */
+public class BidiFormatterBaseTest extends TestCase {
+
+ /**
+ * A trivial extension to {@link BidiFormatterBase} for testing purposes.
+ */
+ public static class TestableBidiFormatterBase extends BidiFormatterBase {
+ static class Factory extends BidiFormatterBase.Factory<TestableBidiFormatterBase> {
+ @Override
+ public TestableBidiFormatterBase createInstance(Direction contextDir,
+ boolean alwaysSpan) {
+ return new TestableBidiFormatterBase(contextDir, alwaysSpan);
+ }
+ }
+
+ private static Factory factory = new Factory();
+
+ public static TestableBidiFormatterBase getInstance(Direction contextDir,
+ boolean alwaysSpan) {
+ return factory.getInstance(contextDir, alwaysSpan);
+ }
+
+ private TestableBidiFormatterBase(Direction contextDir, boolean alwaysSpan) {
+ super(contextDir, alwaysSpan);
+ }
+ }
+
+ static final Direction DEFAULT = Direction.DEFAULT;
+ static final Direction LTR = Direction.LTR;
+ static final Direction RTL = Direction.RTL;
+
+ String en = "abba";
+ String he = "\u05e0\u05e1";
+ String html = "<";
+ String longEn = "abba sabba gabba ";
+ String longHe = "\u05e0 \u05e1 \u05e0 ";
+ BidiFormatterBase ltrFmt = TestableBidiFormatterBase.getInstance(LTR,
+ false); // LTR context
+ BidiFormatterBase rtlFmt = TestableBidiFormatterBase.getInstance(RTL,
+ false); // RTL context
+ BidiFormatterBase unkFmt = TestableBidiFormatterBase.getInstance(DEFAULT,
+ false); // DEFAULT context
+ BidiFormatterBase ltrAlwaysSpanFmt =
+ TestableBidiFormatterBase.getInstance(LTR, true); // LTR context
+ BidiFormatterBase rtlAlwaysSpanFmt =
+ TestableBidiFormatterBase.getInstance(RTL, true); // RTL context
+ BidiFormatterBase unkAlwaysSpanFmt =
+ TestableBidiFormatterBase.getInstance(DEFAULT, true); // DEFAULT context
+
+ public void testGetInstance() {
+ assertEquals(ltrFmt.getContextDir(), LTR);
+ assertEquals(rtlFmt.getContextDir(), RTL);
+ assertEquals(unkFmt.getContextDir(), DEFAULT);
+ assertFalse(ltrFmt.getAlwaysSpan());
+ assertFalse(rtlFmt.getAlwaysSpan());
+ assertFalse(unkFmt.getAlwaysSpan());
+
+ // Always-span formatters
+ assertEquals(ltrAlwaysSpanFmt.getContextDir(), LTR);
+ assertEquals(rtlAlwaysSpanFmt.getContextDir(), RTL);
+ assertEquals(unkAlwaysSpanFmt.getContextDir(), DEFAULT);
+ assertTrue(ltrAlwaysSpanFmt.getAlwaysSpan());
+ assertTrue(rtlAlwaysSpanFmt.getAlwaysSpan());
+ assertTrue(unkAlwaysSpanFmt.getAlwaysSpan());
+
+ // Assert that instances with similar parameters are identical.
+ assertEquals(ltrFmt,
+ TestableBidiFormatterBase.getInstance(LTR, false));
+ assertEquals(rtlFmt,
+ TestableBidiFormatterBase.getInstance(RTL, false));
+ assertEquals(unkFmt,
+ TestableBidiFormatterBase.getInstance(DEFAULT, false));
+ assertEquals(ltrAlwaysSpanFmt,
+ TestableBidiFormatterBase.getInstance(LTR, true));
+ assertEquals(rtlAlwaysSpanFmt,
+ TestableBidiFormatterBase.getInstance(RTL, true));
+ assertEquals(unkAlwaysSpanFmt,
+ TestableBidiFormatterBase.getInstance(DEFAULT, true));
+ }
+
+ public void testDirAttrBase() {
+ // Regular cases:
+ assertEquals("dir=rtl", ltrFmt.dirAttrBase(he, true));
+ assertEquals("", rtlFmt.dirAttrBase(he, true));
+ assertEquals("dir=ltr", rtlFmt.dirAttrBase(en, true));
+ assertEquals("", ltrFmt.dirAttrBase(en, true));
+
+ // Text contains HTML or HTML-escaping:
+ assertEquals("dir=rtl",
+ ltrFmt.dirAttrBase(he + "<some sort of an HTML tag>", true));
+ assertEquals("",
+ ltrFmt.dirAttrBase(he + "<some sort of an HTML tag>", false));
+ }
+
+ public void testEndEdge() {
+ assertEquals(LEFT, rtlFmt.endEdgeBase());
+ assertEquals(RIGHT, ltrFmt.endEdgeBase());
+ assertEquals(RIGHT, unkFmt.endEdgeBase());
+ }
+
+ public void testEstimateDirection() {
+ // Regular cases.
+ assertEquals(DEFAULT, ltrFmt.estimateDirection(""));
+ assertEquals(DEFAULT, rtlFmt.estimateDirection(""));
+ assertEquals(DEFAULT, unkFmt.estimateDirection(""));
+ assertEquals(LTR, ltrFmt.estimateDirection(en));
+ assertEquals(LTR, rtlFmt.estimateDirection(en));
+ assertEquals(LTR, unkFmt.estimateDirection(en));
+ assertEquals(RTL, ltrFmt.estimateDirection(he));
+ assertEquals(RTL, rtlFmt.estimateDirection(he));
+ assertEquals(RTL, unkFmt.estimateDirection(he));
+
+ // Text contains HTML or HTML-escaping.
+ assertEquals(LTR, ltrFmt.estimateDirection("<some sort of tag/>" + he
+ + " &", false));
+ assertEquals(RTL, ltrFmt.estimateDirection(he + "<some sort of tag/>" + he
+ + " &", true));
+ }
+
+ public void testGetContextDir() {
+ assertEquals(LTR, ltrFmt.getContextDir());
+ assertEquals(RTL, rtlFmt.getContextDir());
+ assertEquals(DEFAULT, unkFmt.getContextDir());
+ }
+
+ public void testIsRtlContext() {
+ assertEquals(false, ltrFmt.isRtlContext());
+ assertEquals(true, rtlFmt.isRtlContext());
+ assertEquals(false, unkFmt.isRtlContext());
+ }
+
+ public void testKnownDirAttrBase() {
+ // Regular cases:
+ assertEquals("dir=rtl", ltrFmt.knownDirAttrBase(RTL));
+ assertEquals("", rtlFmt.knownDirAttrBase(RTL));
+ assertEquals("dir=ltr", rtlFmt.knownDirAttrBase(LTR));
+ assertEquals("", ltrFmt.knownDirAttrBase(LTR));
+ }
+
+ public void testMarkBase() {
+ assertEquals(RLM_STRING, rtlFmt.markBase());
+ assertEquals(LRM_STRING, ltrFmt.markBase());
+ assertEquals("", unkFmt.markBase());
+ }
+
+ public void testMarkAfterBase() {
+ assertEquals("exit dir (RTL) is opposite to context dir (LTR)", LRM_STRING,
+ ltrFmt.markAfterBase(longEn + he + html, true));
+ assertEquals("exit dir (LTR) is opposite to context dir (RTL)", RLM_STRING,
+ rtlFmt.markAfterBase(longHe + en, true));
+ assertEquals("exit dir (LTR) doesnt match context dir (DEFAULT)", "",
+ unkFmt.markAfterBase(longEn + en, true));
+ assertEquals("overall dir (RTL) is opposite to context dir (LTR)",
+ LRM_STRING, ltrFmt.markAfterBase(longHe + en, true));
+ assertEquals("overall dir (LTR) is opposite to context dir (RTL)",
+ RLM_STRING, rtlFmt.markAfterBase(longEn + he, true));
+ assertEquals("exit dir and overall dir match context dir (LTR)", "",
+ ltrFmt.markAfterBase(longEn + he + html, false));
+ assertEquals("exit dir and overall dir matches context dir (RTL)", "",
+ rtlFmt.markAfterBase(longHe + he, true));
+ }
+
+ public void testSpanWrapBase() {
+ // The main testing of the logic is done in testSpanWrapWithKnownDirBase.
+ assertEquals("<span dir=rtl>" + he + "</span>" + LRM, ltrFmt.spanWrapBase(
+ he, true, true));
+ assertEquals(he, rtlFmt.spanWrapBase(he, true, true));
+ assertEquals("<span dir=ltr>" + en + "</span>" + RLM, rtlFmt.spanWrapBase(
+ en, true, true));
+ assertEquals(en, ltrFmt.spanWrapBase(en, true, true));
+ }
+
+ public void testSpanWrapWithKnownDirBase() {
+ assertEquals("overall dir matches context dir (LTR)", en + "<",
+ ltrFmt.spanWrapWithKnownDirBase(LTR, en + "<", false, true));
+ assertEquals("overall dir matches context dir (LTR), HTML", en + "<br>",
+ ltrFmt.spanWrapWithKnownDirBase(LTR, en + "<br>", true, true));
+ assertEquals("overall dir matches context dir (RTL)", he + "<",
+ rtlFmt.spanWrapWithKnownDirBase(RTL, he + "<", false, true));
+ assertEquals("overall dir matches context dir (RTL), HTML", he
+ + " <some strange tag>", rtlFmt.spanWrapWithKnownDirBase(RTL, he
+ + " <some strange tag>", true, true));
+
+ assertEquals("overall dir (RTL) doesnt match context dir (LTR)",
+ "<span dir=rtl>" + he + "</span>" + LRM,
+ ltrFmt.spanWrapWithKnownDirBase(RTL, he, false, true));
+ assertEquals(
+ "overall dir (RTL) doesnt match context dir (LTR), no dirReset",
+ "<span dir=rtl>" + he + "</span>",
+ ltrFmt.spanWrapWithKnownDirBase(RTL, he, false, false));
+ assertEquals("overall dir (LTR) doesnt match context dir (RTL)",
+ "<span dir=ltr>" + en + "</span>" + RLM,
+ rtlFmt.spanWrapWithKnownDirBase(LTR, en, false, true));
+ assertEquals(
+ "overall dir (LTR) doesnt match context dir (RTL), no dirReset",
+ "<span dir=ltr>" + en + "</span>",
+ rtlFmt.spanWrapWithKnownDirBase(LTR, en, false, false));
+ assertEquals("overall dir (RTL) doesnt match context dir (unknown)",
+ "<span dir=rtl>" + he + "</span>",
+ unkFmt.spanWrapWithKnownDirBase(RTL, he, false, true));
+ assertEquals(
+ "overall dir (LTR) doesnt match context dir (unknown), no dirReset",
+ "<span dir=ltr>" + en + "</span>",
+ unkFmt.spanWrapWithKnownDirBase(LTR, en, false, false));
+ assertEquals("overall dir (neutral) doesnt match context dir (LTR)", ".",
+ ltrFmt.spanWrapWithKnownDirBase(DEFAULT, ".", false, true));
+
+ assertEquals("exit dir (but not overall dir) is opposite to context dir",
+ longEn + he + LRM,
+ ltrFmt.spanWrapWithKnownDirBase(LTR, longEn + he, false, true));
+ assertEquals("overall dir (but not exit dir) is opposite to context dir",
+ "<span dir=ltr>" + longEn + he + "</span>" + RLM,
+ rtlFmt.spanWrapWithKnownDirBase(LTR, longEn + he, false, true));
+
+ assertEquals("exit dir (but not overall dir) is opposite to context dir",
+ longEn + he + html + LRM,
+ ltrFmt.spanWrapWithKnownDirBase(LTR, longEn + he + html, true, true));
+ assertEquals(
+ "overall dir (but not exit dir) is opposite to context dir, dirReset",
+ "<span dir=ltr>" + longEn + he + "</span>" + RLM,
+ rtlFmt.spanWrapWithKnownDirBase(LTR, longEn + he, true, true));
+
+ assertEquals("plain text overall and exit dir same as context dir",
+ "<br> " + he + " <br>", ltrFmt.spanWrapWithKnownDirBase(LTR,
+ "<br> " + he + " <br>", false, true));
+ assertEquals("HTML overall and exit dir opposite to context dir",
+ "<span dir=rtl><br> " + he + " <br></span>" + LRM,
+ ltrFmt.spanWrapWithKnownDirBase(RTL, "<br> " + he + " <br>", true,
+ true));
+
+ // Always-span formatters
+ assertEquals("alwaysSpan, overall dir matches context dir (LTR)", "<span>"
+ + en + "</span>",
+ ltrAlwaysSpanFmt.spanWrapWithKnownDirBase(LTR, en, false, true));
+ assertEquals(
+ "alwaysSpan, overall dir matches context dir (LTR), no dirReset",
+ "<span>" + en + "</span>",
+ ltrAlwaysSpanFmt.spanWrapWithKnownDirBase(LTR, en, false, false));
+ assertEquals("alwaysSpan, overall dir matches context dir (RTL)", "<span>"
+ + he + "</span>",
+ rtlAlwaysSpanFmt.spanWrapWithKnownDirBase(RTL, he, false, true));
+ assertEquals(
+ "alwaysSpan, overall dir matches context dir (RTL), no dirReset",
+ "<span>" + he + "</span>",
+ rtlAlwaysSpanFmt.spanWrapWithKnownDirBase(RTL, he, false, false));
+
+ assertEquals(
+ "alwaysSpan, exit dir (but not overall dir) is opposite to context dir",
+ "<span>" + longEn + he + "</span>" + LRM,
+ ltrAlwaysSpanFmt.spanWrapWithKnownDirBase(LTR, longEn + he, true, true));
+ assertEquals(
+ "alwaysSpan, overall dir (but not exit dir) is opposite to context dir, dirReset",
+ "<span dir=ltr>" + longEn + he + "</span>" + RLM,
+ rtlAlwaysSpanFmt.spanWrapWithKnownDirBase(LTR, longEn + he, true, true));
+
+ assertEquals(
+ "alwaysSpan, plain text overall and exit dir same as context dir",
+ "<span><br> " + he + " <br></span>",
+ ltrAlwaysSpanFmt.spanWrapWithKnownDirBase(LTR, "<br> " + he + " <br>",
+ false, true));
+ assertEquals(
+ "alwaysSpan, HTML overall and exit dir opposite to context dir",
+ "<span dir=rtl><br> " + he + " <br></span>" + LRM,
+ ltrAlwaysSpanFmt.spanWrapWithKnownDirBase(RTL, "<br> " + he + " <br>",
+ true, true));
+ }
+
+ public void testStartEdgeBase() {
+ assertEquals(RIGHT, rtlFmt.startEdgeBase());
+ assertEquals(LEFT, ltrFmt.startEdgeBase());
+ assertEquals(LEFT, unkFmt.startEdgeBase());
+ }
+
+ public void testUnicodeWrapBase() {
+ // The main testing of the logic is done in testUnicodeWrapWithKnownDirBase.
+ assertEquals(RLE + he + PDF + LRM, ltrFmt.unicodeWrapBase(he, true, true));
+ assertEquals(he, rtlFmt.unicodeWrapBase(he, true, true));
+ assertEquals(LRE + en + PDF + RLM, rtlFmt.unicodeWrapBase(en, true, true));
+ assertEquals(en, ltrFmt.unicodeWrapBase(en, true, true));
+ }
+
+ public void testUnicodeWrapWithKnownDirBase() {
+ assertEquals("overall dir matches context dir (LTR)", en + "<",
+ ltrFmt.unicodeWrapWithKnownDirBase(LTR, en + "<", false, true));
+ assertEquals("overall dir matches context dir (LTR), HTML", en + "<br>",
+ ltrFmt.unicodeWrapWithKnownDirBase(LTR, en + "<br>", true, true));
+ assertEquals("overall dir matches context dir (RTL)", he + "<",
+ rtlFmt.unicodeWrapWithKnownDirBase(RTL, he + "<", false, true));
+ assertEquals("overall dir matches context dir (RTL), HTML", he
+ + " <some strange tag>", rtlFmt.unicodeWrapWithKnownDirBase(RTL, he
+ + " <some strange tag>", true, true));
+
+ assertEquals("overall dir (RTL) doesnt match context dir (LTR), dirReset",
+ RLE + he + PDF + LRM,
+ ltrFmt.unicodeWrapWithKnownDirBase(RTL, he, false, true));
+ assertEquals(
+ "overall dir (RTL) doesnt match context dir (LTR), no dirReset", RLE
+ + he + PDF,
+ ltrFmt.unicodeWrapWithKnownDirBase(RTL, he, false, false));
+ assertEquals("overall dir (LTR) doesnt match context dir (RTL), dirReset",
+ LRE + en + PDF + RLM,
+ rtlFmt.unicodeWrapWithKnownDirBase(LTR, en, false, true));
+ assertEquals(
+ "overall dir (LTR) doesnt match context dir (RTL), no dirReset", LRE
+ + en + PDF,
+ rtlFmt.unicodeWrapWithKnownDirBase(LTR, en, false, false));
+ assertEquals(
+ "overall dir (RTL) doesnt match context dir (unknown), dirReset", RLE
+ + he + PDF,
+ unkFmt.unicodeWrapWithKnownDirBase(RTL, he, false, true));
+ assertEquals(
+ "overall dir (LTR) doesnt match context dir (unknown), no dirReset",
+ LRE + en + PDF,
+ unkFmt.unicodeWrapWithKnownDirBase(LTR, en, false, false));
+ assertEquals(
+ "overall dir (neutral) doesnt match context dir (LTR), dirReset", ".",
+ ltrFmt.unicodeWrapWithKnownDirBase(DEFAULT, ".", false, true));
+
+ assertEquals("exit dir (but not overall dir) is opposite to context dir",
+ longEn + he + LRM,
+ ltrFmt.unicodeWrapWithKnownDirBase(LTR, longEn + he, false, true));
+ assertEquals("overall dir (but not exit dir) is opposite to context dir",
+ LRE + longEn + he + PDF + RLM,
+ rtlFmt.unicodeWrapWithKnownDirBase(LTR, longEn + he, false, true));
+
+ assertEquals("plain text overall and exit dir same as context dir", html
+ + " " + he + " " + html, ltrFmt.unicodeWrapWithKnownDirBase(
+ LTR, html + " " + he + " " + html, false, true));
+ assertEquals("HTML overall and exit dir opposite to context dir", RLE
+ + html + " " + he + " " + html + PDF + LRM,
+ ltrFmt.unicodeWrapWithKnownDirBase(RTL, html + " " + he + " " + html,
+ true, true));
+ }
+}
diff --git a/user/test/com/google/gwt/i18n/shared/BidiFormatterTest.java b/user/test/com/google/gwt/i18n/shared/BidiFormatterTest.java
index 72fe789..7afda50 100644
--- a/user/test/com/google/gwt/i18n/shared/BidiFormatterTest.java
+++ b/user/test/com/google/gwt/i18n/shared/BidiFormatterTest.java
@@ -15,273 +15,115 @@
*/
package com.google.gwt.i18n.shared;
-import static com.google.gwt.i18n.shared.BidiFormatter.Format.*;
+import static com.google.gwt.i18n.shared.BidiFormatterBase.Format.*;
import com.google.gwt.i18n.client.HasDirection.Direction;
import junit.framework.TestCase;
/**
- * Unit tests for BidiFormatter.
+ * Unit tests for {@link BidiFormatter}.
+ * Tests only methods added in {@code BidiFormatter}, i.e. instantiating and
+ * method overloading.
*/
public class BidiFormatterTest extends TestCase {
+
static final Direction DEFAULT = Direction.DEFAULT;
static final Direction LTR = Direction.LTR;
static final Direction RTL = Direction.RTL;
String en = "abba";
String he = "\u05e0\u05e1";
- String html = "<";
String longEn = "abba sabba gabba ";
- String longHe = "\u05e0 \u05e1 \u05e0 ";
- BidiFormatter ltrFmt = BidiFormatter.getInstance(LTR); // LTR context
- BidiFormatter rtlFmt = BidiFormatter.getInstance(RTL); // RTL context
- BidiFormatter unkFmt = BidiFormatter.getInstance(DEFAULT); // DEFAULT context
-
- public void testDirAttr() {
- // Regular cases:
- assertEquals("dir=rtl", ltrFmt.dirAttr(he, true));
- assertEquals("", rtlFmt.dirAttr(he, true));
- assertEquals("dir=ltr", rtlFmt.dirAttr(en, true));
- assertEquals("", ltrFmt.dirAttr(en, true));
+ String longHtmlTag = "<some nasty nasty nasty tag/>";
+ BidiFormatter ltrFormatter = BidiFormatter.getInstance(LTR, false);
- // Text contains HTML or HTML-escaping:
- assertEquals("dir=rtl", ltrFmt.dirAttr(he + "<some sort of an HTML tag>",
- true));
- assertEquals("", ltrFmt.dirAttr(he + "<some sort of an HTML tag>", false));
+ public void testDirAttr() {
+ assertEquals("dirAttr(String)", "dir=rtl", ltrFormatter.dirAttr(he));
+ assertEquals("dirAttr(String, boolean)", "dir=rtl",
+ ltrFormatter.dirAttr(he + longHtmlTag, true));
}
public void testEndEdge() {
- assertEquals(LEFT, rtlFmt.endEdge());
- assertEquals(RIGHT, ltrFmt.endEdge());
- assertEquals(RIGHT, unkFmt.endEdge());
+ assertEquals(RIGHT, ltrFormatter.endEdge());
}
- public void testEstimateDirection() {
- // Regular cases.
- assertEquals(DEFAULT, ltrFmt.estimateDirection(""));
- assertEquals(DEFAULT, rtlFmt.estimateDirection(""));
- assertEquals(DEFAULT, unkFmt.estimateDirection(""));
- assertEquals(LTR, ltrFmt.estimateDirection(en));
- assertEquals(LTR, rtlFmt.estimateDirection(en));
- assertEquals(LTR, unkFmt.estimateDirection(en));
- assertEquals(RTL, ltrFmt.estimateDirection(he));
- assertEquals(RTL, rtlFmt.estimateDirection(he));
- assertEquals(RTL, unkFmt.estimateDirection(he));
-
- // Text contains HTML or HTML-escaping.
- assertEquals(LTR, ltrFmt.estimateDirection("<some sort of tag/>" + he
- + " &", false));
- assertEquals(RTL, ltrFmt.estimateDirection(he + "<some sort of tag/>" + he
- + " &", true));
- }
-
- public void testGetContextDir() {
- assertEquals(LTR, ltrFmt.getContextDir());
- assertEquals(RTL, rtlFmt.getContextDir());
- assertEquals(DEFAULT, unkFmt.getContextDir());
- }
-
- public void testGetInstanceForRtlContext() {
+ public void testGetInstance() {
+ // Check contextDir
assertEquals(LTR, BidiFormatter.getInstance(false).getContextDir());
assertEquals(RTL, BidiFormatter.getInstance(true).getContextDir());
- }
+ assertEquals(LTR, BidiFormatter.getInstance(LTR).getContextDir());
+ assertEquals(RTL, BidiFormatter.getInstance(RTL).getContextDir());
+ assertEquals(DEFAULT,
+ BidiFormatter.getInstance(DEFAULT).getContextDir());
- public void testIsRtlContext() {
- assertEquals(false, ltrFmt.isRtlContext());
- assertEquals(true, rtlFmt.isRtlContext());
- assertEquals(false, unkFmt.isRtlContext());
+ // Check alwaysSpan
+ assertEquals(true, BidiFormatter.getInstance(false, true).getAlwaysSpan());
+ assertEquals(false, BidiFormatter.getInstance(false, false).getAlwaysSpan());
}
public void testKnownDirAttr() {
- // Regular cases:
- assertEquals("dir=rtl", ltrFmt.knownDirAttr(RTL));
- assertEquals("", rtlFmt.knownDirAttr(RTL));
- assertEquals("dir=ltr", rtlFmt.knownDirAttr(LTR));
- assertEquals("", ltrFmt.knownDirAttr(LTR));
+ assertEquals("dir=rtl", ltrFormatter.knownDirAttr(RTL));
}
public void testMark() {
- assertEquals(RLM_STRING, rtlFmt.mark());
- assertEquals(LRM_STRING, ltrFmt.mark());
- assertEquals("", unkFmt.mark());
+ assertEquals(LRM_STRING, ltrFormatter.mark());
}
public void testMarkAfter() {
- assertEquals("exit dir (RTL) is opposite to context dir (LTR)", LRM_STRING,
- ltrFmt.markAfter(longEn + he + html, true));
- assertEquals("exit dir (LTR) is opposite to context dir (RTL)", RLM_STRING,
- rtlFmt.markAfter(longHe + en, true));
- assertEquals("exit dir (LTR) doesnt match context dir (DEFAULT)", "",
- unkFmt.markAfter(longEn + en, true));
- assertEquals("overall dir (RTL) is opposite to context dir (LTR)",
- LRM_STRING, ltrFmt.markAfter(longHe + en, true));
- assertEquals("overall dir (LTR) is opposite to context dir (RTL)",
- RLM_STRING, rtlFmt.markAfter(longEn + he, true));
- assertEquals("exit dir and overall dir match context dir (LTR)", "",
- ltrFmt.markAfter(longEn + he + html, false));
- assertEquals("exit dir and overall dir matches context dir (RTL)", "",
- rtlFmt.markAfter(longHe + he, true));
+ assertEquals("markAfter(String)", LRM_STRING, ltrFormatter.markAfter(longEn
+ + he));
+ assertEquals("markAfter(String, boolean)", LRM_STRING,
+ ltrFormatter.markAfter(longEn + he + longHtmlTag, true));
}
public void testSpanWrap() {
- // The main testing of the logic is done in testSpanWrapWithKnownDir.
- assertEquals("<span dir=rtl>" + he + "</span>" + LRM, ltrFmt.spanWrap(he,
- true));
- assertEquals(he, rtlFmt.spanWrap(he, true));
- assertEquals("<span dir=ltr>" + en + "</span>" + RLM, rtlFmt.spanWrap(en,
- true));
- assertEquals(en, ltrFmt.spanWrap(en, true));
+ assertEquals("spanWrap(String)",
+ "<span dir=rtl>" + he + "<</span>" + LRM,
+ ltrFormatter.spanWrap(he + "<"));
+ assertEquals("spanWrap(String, boolean)", "<span dir=rtl>" + he
+ + longHtmlTag + "</span>" + LRM, ltrFormatter.spanWrap(
+ he + longHtmlTag, true));
+ assertEquals("spanWrap(String, boolean, boolean)", "<span dir=rtl>" + he
+ + longHtmlTag + "</span>", ltrFormatter.spanWrap(he + longHtmlTag,
+ true, false));
}
public void testSpanWrapWithKnownDir() {
- assertEquals("overall dir matches context dir (LTR)", en + "<",
- ltrFmt.spanWrapWithKnownDir(LTR, en + "<"));
- assertEquals("overall dir matches context dir (LTR), HTML", en + "<br>",
- ltrFmt.spanWrapWithKnownDir(LTR, en + "<br>", true));
- assertEquals("overall dir matches context dir (RTL)", he + "<",
- rtlFmt.spanWrapWithKnownDir(RTL, he + "<"));
- assertEquals("overall dir matches context dir (RTL), HTML", he
- + " <some strange tag>", rtlFmt.spanWrapWithKnownDir(RTL, he
- + " <some strange tag>", true));
-
- assertEquals("overall dir (RTL) doesnt match context dir (LTR)",
- "<span dir=rtl>" + he + "</span>" + LRM, ltrFmt.spanWrapWithKnownDir(
- RTL, he));
- assertEquals(
- "overall dir (RTL) doesnt match context dir (LTR), no dirReset",
- "<span dir=rtl>" + he + "</span>", ltrFmt.spanWrapWithKnownDir(RTL, he,
- false, false));
- assertEquals("overall dir (LTR) doesnt match context dir (RTL)",
- "<span dir=ltr>" + en + "</span>" + RLM, rtlFmt.spanWrapWithKnownDir(
- LTR, en));
- assertEquals(
- "overall dir (LTR) doesnt match context dir (RTL), no dirReset",
- "<span dir=ltr>" + en + "</span>", rtlFmt.spanWrapWithKnownDir(LTR, en,
- false, false));
- assertEquals("overall dir (RTL) doesnt match context dir (unknown)",
- "<span dir=rtl>" + he + "</span>", unkFmt.spanWrapWithKnownDir(RTL, he));
- assertEquals(
- "overall dir (LTR) doesnt match context dir (unknown), no dirReset",
- "<span dir=ltr>" + en + "</span>", unkFmt.spanWrapWithKnownDir(LTR, en,
- false, false));
- assertEquals("overall dir (neutral) doesnt match context dir (LTR)", ".",
- ltrFmt.spanWrapWithKnownDir(DEFAULT, "."));
-
- assertEquals("exit dir (but not overall dir) is opposite to context dir",
- longEn + he + LRM, ltrFmt.spanWrapWithKnownDir(LTR, longEn + he));
- assertEquals("overall dir (but not exit dir) is opposite to context dir",
- "<span dir=ltr>" + longEn + he + "</span>" + RLM,
- rtlFmt.spanWrapWithKnownDir(LTR, longEn + he));
-
- assertEquals("exit dir (but not overall dir) is opposite to context dir",
- longEn + he + html + LRM, ltrFmt.spanWrapWithKnownDir(LTR, longEn + he
- + html, true, true));
- assertEquals(
- "overall dir (but not exit dir) is opposite to context dir, dirReset",
- "<span dir=ltr>" + longEn + he + "</span>" + RLM,
- rtlFmt.spanWrapWithKnownDir(LTR, longEn + he, true, true));
-
- assertEquals("plain text overall and exit dir same as context dir",
- "<br> " + he + " <br>", ltrFmt.spanWrapWithKnownDir(LTR,
- "<br> " + he + " <br>", false));
- assertEquals("HTML overall and exit dir opposite to context dir",
- "<span dir=rtl><br> " + he + " <br></span>" + LRM,
- ltrFmt.spanWrapWithKnownDir(RTL, "<br> " + he + " <br>", true));
-
- BidiFormatter ltrAlwaysSpanFmt = BidiFormatter.getInstance(LTR, true);
- BidiFormatter rtlAlwaysSpanFmt = BidiFormatter.getInstance(RTL, true);
- BidiFormatter unkAlwaysSpanFmt = BidiFormatter.getInstance(DEFAULT, true);
-
- assertEquals("alwaysSpan, overall dir matches context dir (LTR)", "<span>"
- + en + "</span>", ltrAlwaysSpanFmt.spanWrapWithKnownDir(LTR, en));
- assertEquals(
- "alwaysSpan, overall dir matches context dir (LTR), no dirReset",
- "<span>" + en + "</span>", ltrAlwaysSpanFmt.spanWrapWithKnownDir(LTR,
- en, false, false));
- assertEquals("alwaysSpan, overall dir matches context dir (RTL)", "<span>"
- + he + "</span>", rtlAlwaysSpanFmt.spanWrapWithKnownDir(RTL, he));
- assertEquals(
- "alwaysSpan, overall dir matches context dir (RTL), no dirReset",
- "<span>" + he + "</span>", rtlAlwaysSpanFmt.spanWrapWithKnownDir(RTL,
- he, false, false));
-
- assertEquals(
- "alwaysSpan, exit dir (but not overall dir) is opposite to context dir",
- "<span>" + longEn + he + "</span>" + LRM,
- ltrAlwaysSpanFmt.spanWrapWithKnownDir(LTR, longEn + he, true, true));
- assertEquals(
- "alwaysSpan, overall dir (but not exit dir) is opposite to context dir, dirReset",
- "<span dir=ltr>" + longEn + he + "</span>" + RLM,
- rtlAlwaysSpanFmt.spanWrapWithKnownDir(LTR, longEn + he, true, true));
-
- assertEquals(
- "alwaysSpan, plain text overall and exit dir same as context dir",
- "<span><br> " + he + " <br></span>",
- ltrAlwaysSpanFmt.spanWrapWithKnownDir(LTR, "<br> " + he + " <br>",
- false));
- assertEquals(
- "alwaysSpan, HTML overall and exit dir opposite to context dir",
- "<span dir=rtl><br> " + he + " <br></span>" + LRM,
- ltrAlwaysSpanFmt.spanWrapWithKnownDir(RTL, "<br> " + he + " <br>", true));
+ assertEquals("spanWrapWithKnownDir(Direction, String)", "<span dir=rtl>"
+ + en + "<</span>" + LRM,
+ ltrFormatter.spanWrapWithKnownDir(RTL, en + "<"));
+ assertEquals("spanWrapWithKnownDir(Direction, String, boolean)",
+ "<span dir=rtl>" + en + longHtmlTag + "</span>" + LRM,
+ ltrFormatter.spanWrapWithKnownDir(RTL, en + longHtmlTag, true));
+ assertEquals("spanWrapWithKnownDir(Direction, String, boolean, boolean)",
+ "<span dir=rtl>" + en + longHtmlTag + "</span>",
+ ltrFormatter.spanWrapWithKnownDir(RTL, en + longHtmlTag, true, false));
}
public void testStartEdge() {
- assertEquals(RIGHT, rtlFmt.startEdge());
- assertEquals(LEFT, ltrFmt.startEdge());
- assertEquals(LEFT, unkFmt.startEdge());
+ assertEquals(LEFT, ltrFormatter.startEdge());
}
public void testUnicodeWrap() {
- // The main testing of the logic is done in testUnicodeWrapWithKnownDir.
- assertEquals(RLE + he + PDF + LRM, ltrFmt.unicodeWrap(he, true));
- assertEquals(he, rtlFmt.unicodeWrap(he, true));
- assertEquals(LRE + en + PDF + RLM, rtlFmt.unicodeWrap(en, true));
- assertEquals(en, ltrFmt.unicodeWrap(en, true));
+ assertEquals("unicodeWrap(String)", RLE + he + PDF + LRM,
+ ltrFormatter.unicodeWrap(he));
+ assertEquals("unicodeWrap(String, boolean)", RLE + he + longHtmlTag + PDF
+ + LRM, ltrFormatter.unicodeWrap(he + longHtmlTag, true));
+ assertEquals("unicodeWrap(String, boolean, boolean)", RLE + he
+ + longHtmlTag + PDF, ltrFormatter.unicodeWrap(he + longHtmlTag, true,
+ false));
}
public void testUnicodeWrapWithKnownDir() {
- assertEquals("overall dir matches context dir (LTR)", en + "<",
- ltrFmt.unicodeWrapWithKnownDir(LTR, en + "<"));
- assertEquals("overall dir matches context dir (LTR), HTML", en + "<br>",
- ltrFmt.unicodeWrapWithKnownDir(LTR, en + "<br>", true));
- assertEquals("overall dir matches context dir (RTL)", he + "<",
- rtlFmt.unicodeWrapWithKnownDir(RTL, he + "<"));
- assertEquals("overall dir matches context dir (RTL), HTML", he
- + " <some strange tag>", rtlFmt.unicodeWrapWithKnownDir(RTL, he
- + " <some strange tag>", true));
-
- assertEquals("overall dir (RTL) doesnt match context dir (LTR), dirReset",
- RLE + he + PDF + LRM, ltrFmt.unicodeWrapWithKnownDir(RTL, he));
+ assertEquals("unicodeWrapWithKnownDir(Direction, String)", RLE + en + PDF
+ + LRM, ltrFormatter.unicodeWrapWithKnownDir(RTL, en));
+ assertEquals("unicodeWrapWithKnownDir(Direction, String, boolean)", RLE
+ + en + longHtmlTag + PDF + LRM, ltrFormatter.unicodeWrapWithKnownDir(
+ RTL, en + longHtmlTag, true));
assertEquals(
- "overall dir (RTL) doesnt match context dir (LTR), no dirReset", RLE
- + he + PDF, ltrFmt.unicodeWrapWithKnownDir(RTL, he, false, false));
- assertEquals("overall dir (LTR) doesnt match context dir (RTL), dirReset",
- LRE + en + PDF + RLM, rtlFmt.unicodeWrapWithKnownDir(LTR, en));
- assertEquals(
- "overall dir (LTR) doesnt match context dir (RTL), no dirReset", LRE
- + en + PDF, rtlFmt.unicodeWrapWithKnownDir(LTR, en, false, false));
- assertEquals(
- "overall dir (RTL) doesnt match context dir (unknown), dirReset", RLE
- + he + PDF, unkFmt.unicodeWrapWithKnownDir(RTL, he));
- assertEquals(
- "overall dir (LTR) doesnt match context dir (unknown), no dirReset",
- LRE + en + PDF, unkFmt.unicodeWrapWithKnownDir(LTR, en, false, false));
- assertEquals(
- "overall dir (neutral) doesnt match context dir (LTR), dirReset", ".",
- ltrFmt.unicodeWrapWithKnownDir(DEFAULT, "."));
-
- assertEquals("exit dir (but not overall dir) is opposite to context dir",
- longEn + he + LRM, ltrFmt.unicodeWrapWithKnownDir(LTR, longEn + he));
- assertEquals("overall dir (but not exit dir) is opposite to context dir",
- LRE + longEn + he + PDF + RLM, rtlFmt.unicodeWrapWithKnownDir(LTR,
- longEn + he));
-
- assertEquals("plain text overall and exit dir same as context dir", html
- + " " + he + " " + html, ltrFmt.unicodeWrapWithKnownDir(LTR, html + " "
- + he + " " + html, false));
- assertEquals("HTML overall and exit dir opposite to context dir", RLE
- + html + " " + he + " " + html + PDF + LRM,
- ltrFmt.unicodeWrapWithKnownDir(RTL, html + " " + he + " " + html, true));
+ "unicodeWrapWithKnownDir(Direction, String, boolean, boolean)", RLE
+ + en + longHtmlTag + PDF, ltrFormatter.unicodeWrapWithKnownDir(RTL,
+ en + longHtmlTag, true, false));
}
}
diff --git a/user/test/com/google/gwt/i18n/shared/SafeHtmlBidiFormatterTest.java b/user/test/com/google/gwt/i18n/shared/SafeHtmlBidiFormatterTest.java
new file mode 100644
index 0000000..916bebf
--- /dev/null
+++ b/user/test/com/google/gwt/i18n/shared/SafeHtmlBidiFormatterTest.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.i18n.shared;
+
+import static com.google.gwt.i18n.shared.BidiFormatterBase.Format.*;
+
+import com.google.gwt.i18n.client.HasDirection.Direction;
+import com.google.gwt.safehtml.shared.SafeHtml;
+import com.google.gwt.safehtml.shared.SafeHtmlUtils;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for {@link SafeHtmlBidiFormatter}.
+ * Tests only methods added in {@code SafeHtmlBidiFormatter}, i.e.
+ * instantiating and method overloading.
+ */
+public class SafeHtmlBidiFormatterTest extends TestCase {
+
+ static final Direction DEFAULT = Direction.DEFAULT;
+ static final Direction LTR = Direction.LTR;
+ static final Direction RTL = Direction.RTL;
+
+ String en = "abba";
+ String he = "\u05e0\u05e1";
+ String longEn = "abba sabba gabba ";
+ String htmlTag = "<br/>";
+ String htmlTagEscaped = "<br/>";
+ SafeHtmlBidiFormatter ltrFormatter = SafeHtmlBidiFormatter.getInstance(LTR,
+ false);
+
+ public void testDirAttr() {
+ assertEquals("dirAttr(SafeHtml)", "dir=rtl",
+ ltrFormatter.dirAttr(toSafeHtml(he)).asString());
+ assertEquals("dirAttr(String)", "dir=rtl",
+ ltrFormatter.dirAttr(he).asString());
+ }
+
+ public void testEndEdge() {
+ assertEquals(toSafeHtml(RIGHT), ltrFormatter.endEdge());
+ }
+
+ public void testGetInstance() {
+ // Check contextDir
+ assertEquals(LTR, SafeHtmlBidiFormatter.getInstance(false).getContextDir());
+ assertEquals(RTL, SafeHtmlBidiFormatter.getInstance(true).getContextDir());
+ assertEquals(LTR, SafeHtmlBidiFormatter.getInstance(LTR).getContextDir());
+ assertEquals(RTL, SafeHtmlBidiFormatter.getInstance(RTL).getContextDir());
+ assertEquals(DEFAULT,
+ SafeHtmlBidiFormatter.getInstance(DEFAULT).getContextDir());
+
+ // Check alwaysSpan
+ assertEquals(true,
+ SafeHtmlBidiFormatter.getInstance(false, true).getAlwaysSpan());
+ assertEquals(false,
+ SafeHtmlBidiFormatter.getInstance(false, false).getAlwaysSpan());
+ }
+
+ public void testKnownDirAttr() {
+ assertEquals("dir=rtl", ltrFormatter.knownDirAttr(RTL).asString());
+ }
+
+ public void testMark() {
+ assertEquals(toSafeHtml(LRM_STRING), ltrFormatter.mark());
+ }
+
+ public void testMarkAfter() {
+ String text = longEn + he;
+ assertEquals("markAfter(SafeHtml)", LRM_STRING, ltrFormatter.markAfter(
+ toSafeHtml(text)).asString());
+ assertEquals("markAfter(String)", LRM_STRING,
+ ltrFormatter.markAfter(text).asString());
+ }
+
+ public void testSafeHtmlEstimateDirection() {
+ assertEquals(LTR, ltrFormatter.estimateDirection(toSafeHtml(he
+ + "<some verbose tag/>")));
+ }
+
+ public void testSpanWrap() {
+ String text = he + htmlTag;
+ String baseResult = "<span dir=rtl>" + he + htmlTagEscaped + "</span>";
+ assertEquals("spanWrap(SafeHtml)", baseResult + LRM, ltrFormatter.spanWrap(
+ toSafeHtml(text)).asString());
+ assertEquals("spanWrap(String)", baseResult + LRM, ltrFormatter.spanWrap(
+ text).asString());
+ assertEquals("spanWrap(SafeHtml, boolean)", baseResult,
+ ltrFormatter.spanWrap(toSafeHtml(text), false).asString());
+ assertEquals("spanWrap(String, boolean)", baseResult,
+ ltrFormatter.spanWrap(text, false).asString());
+ }
+
+ public void testSpanWrapWithKnownDir() {
+ String text = en + htmlTag;
+ String baseResult = "<span dir=rtl>" + en + htmlTagEscaped + "</span>";
+ assertEquals("spanWrapWithKnownDir(Direction, SafeHtml)", baseResult + LRM,
+ ltrFormatter.spanWrapWithKnownDir(RTL, toSafeHtml(text)).asString());
+ assertEquals("spanWrapWithKnownDir(Direction, String)", baseResult + LRM,
+ ltrFormatter.spanWrapWithKnownDir(RTL, text).asString());
+ assertEquals("spanWrapWithKnownDir(Direction, SafeHtml, boolean)",
+ baseResult, ltrFormatter.spanWrapWithKnownDir(RTL, toSafeHtml(text),
+ false).asString());
+ assertEquals("spanWrapWithKnownDir(Direction, String, boolean)",
+ baseResult,
+ ltrFormatter.spanWrapWithKnownDir(RTL, text, false).asString());
+ }
+
+ public void testStartEdge() {
+ assertEquals(toSafeHtml(LEFT), ltrFormatter.startEdge());
+ }
+
+ public void testUnicodeWrap() {
+ String text = he + htmlTag;
+ String baseResult = RLE + he + htmlTagEscaped + PDF;
+ assertEquals("unicodeWrap(SafeHtml)", baseResult + LRM,
+ ltrFormatter.unicodeWrap(toSafeHtml(text)).asString());
+ assertEquals("unicodeWrap(String)", baseResult + LRM,
+ ltrFormatter.unicodeWrap(text).asString());
+ assertEquals("unicodeWrap(SafeHtml, boolean)", baseResult,
+ ltrFormatter.unicodeWrap(toSafeHtml(text), false).asString());
+ assertEquals("unicodeWrap(String, boolean)", baseResult,
+ ltrFormatter.unicodeWrap(text, false).asString());
+ }
+
+ public void testUnicodeWrapWithKnownDir() {
+ String text = en + htmlTag;
+ String baseResult = RLE + en + htmlTagEscaped + PDF;
+ assertEquals("unicodeWrap(SafeHtml)", baseResult + LRM,
+ ltrFormatter.unicodeWrapWithKnownDir(RTL, toSafeHtml(text)).asString());
+ assertEquals("unicodeWrap(String)", baseResult + LRM,
+ ltrFormatter.unicodeWrapWithKnownDir(RTL, text).asString());
+ assertEquals(
+ "unicodeWrap(SafeHtml, boolean)",
+ baseResult, ltrFormatter.unicodeWrapWithKnownDir(RTL, toSafeHtml(text),
+ false).asString());
+ assertEquals("unicodeWrap(String, boolean)", baseResult,
+ ltrFormatter.unicodeWrapWithKnownDir(RTL, text, false).asString());
+ }
+
+ private SafeHtml toSafeHtml(String untrustedString) {
+ return SafeHtmlUtils.fromString(untrustedString);
+ }
+}