diff --git a/gcloud-java-translate/src/main/java/com/google/cloud/translate/Translate.java b/gcloud-java-translate/src/main/java/com/google/cloud/translate/Translate.java index 1d661a978794..5e406a9e2e28 100644 --- a/gcloud-java-translate/src/main/java/com/google/cloud/translate/Translate.java +++ b/gcloud-java-translate/src/main/java/com/google/cloud/translate/Translate.java @@ -70,4 +70,46 @@ public static LanguageListOption targetLanguage(String targetLanguage) { * } */ List listSupportedLanguages(LanguageListOption... options); + + /** + * Detects the language of the provided texts. + * + *

Example of detecting the language of some texts: + *

 {@code
+   * List texts = new LinkedList<>();
+   * texts.add("Hello, World!");
+   * texts.add("¡Hola Mundo!");
+   * List detections = translate.detect(texts);
+   * }
+ * + * @param texts the texts for which language should be detected + * @return a list of objects containing information on the language detection, one for each + * provided text, in order. + */ + List detect(List texts); + + /** + * Detects the language of the provided texts. + * + *

Example of detecting the language of some texts: + *

 {@code
+   * List detections = translate.detect("Hello, World!", "¡Hola Mundo!");
+   * }
+ * + * @param texts the texts for which language should be detected + * @return a list of objects containing information on the language detection, one for each + * provided text, in order. + */ + List detect(String... texts); + + /** + * Detects the language of the provided text. Returns an object containing information on the + * language detection. + * + *

Example of detecting the language a text: + *

 {@code
+   * Detection detection = translate.detect("Hello, World!");
+   * }
+ */ + Detection detect(String text); } diff --git a/gcloud-java-translate/src/main/java/com/google/cloud/translate/TranslateImpl.java b/gcloud-java-translate/src/main/java/com/google/cloud/translate/TranslateImpl.java index 36d0b3afc863..e7aa8dfd6200 100644 --- a/gcloud-java-translate/src/main/java/com/google/cloud/translate/TranslateImpl.java +++ b/gcloud-java-translate/src/main/java/com/google/cloud/translate/TranslateImpl.java @@ -18,14 +18,20 @@ import static com.google.cloud.RetryHelper.runWithRetries; import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import com.google.api.services.translate.model.DetectionsResourceItems; import com.google.api.services.translate.model.LanguagesResource; import com.google.cloud.BaseService; import com.google.cloud.RetryHelper.RetryHelperException; import com.google.cloud.translate.spi.TranslateRpc; +import com.google.common.base.Function; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; @@ -34,6 +40,14 @@ final class TranslateImpl extends BaseService implements Trans private final TranslateRpc translateRpc; + private static final Function, Detection> + DETECTION_FROM_PB_FUNCTION = new Function, Detection>() { + @Override + public Detection apply(List detectionPb) { + return Detection.fromPb(detectionPb.get(0)); + } + }; + TranslateImpl(TranslateOptions options) { super(options); translateRpc = options.rpc(); @@ -53,6 +67,41 @@ public List call() { } } + @Override + public List detect(final List texts) { + try { + List> detectionsPb = + runWithRetries(new Callable>>() { + @Override + public List> call() { + return translateRpc.detect(texts); + } + }, options().retryParams(), EXCEPTION_HANDLER, options().clock()); + Iterator> detectionIterator = detectionsPb.iterator(); + Iterator textIterator = texts.iterator(); + while (detectionIterator.hasNext() && textIterator.hasNext()) { + List detectionPb = detectionIterator.next(); + String text = textIterator.next(); + checkState(detectionPb != null && !detectionPb.isEmpty(), + "No detection found for text: %s", text); + checkState(detectionPb.size() == 1, "Multiple detections found for text: %s", text); + } + return Lists.transform(detectionsPb, DETECTION_FROM_PB_FUNCTION); + } catch (RetryHelperException e) { + throw TranslateException.translateAndThrow(e); + } + } + + @Override + public List detect(String... texts) { + return detect(Arrays.asList(texts)); + } + + @Override + public Detection detect(String text) { + return detect(Collections.singletonList(text)).get(0); + } + private Map optionMap(Option... options) { Map optionMap = Maps.newEnumMap(TranslateRpc.Option.class); for (Option option : options) { diff --git a/gcloud-java-translate/src/main/java/com/google/cloud/translate/spi/DefaultTranslateRpc.java b/gcloud-java-translate/src/main/java/com/google/cloud/translate/spi/DefaultTranslateRpc.java index 14f4a326399d..1af329a0be47 100644 --- a/gcloud-java-translate/src/main/java/com/google/cloud/translate/spi/DefaultTranslateRpc.java +++ b/gcloud-java-translate/src/main/java/com/google/cloud/translate/spi/DefaultTranslateRpc.java @@ -57,10 +57,10 @@ private static TranslateException translate(IOException exception) { } @Override - public List> detect(List text) { + public List> detect(List texts) { try { List> detections = - translate.detections().list(text).setKey(options.apiKey()).execute().getDetections(); + translate.detections().list(texts).setKey(options.apiKey()).execute().getDetections(); return detections != null ? detections : ImmutableList.>of(); } catch (IOException ex) { throw translate(ex); @@ -82,14 +82,14 @@ public List listSupportedLanguages(Map optionMap) } @Override - public List translate(List text, Map optionMap) { + public List translate(List texts, Map optionMap) { try { String targetLanguage = firstNonNull(TARGET_LANGUAGE.getString(optionMap), options.targetLanguage()); final String sourceLanguage = SOURCE_LANGUAGE.getString(optionMap); List translations = translate.translations() - .list(text, targetLanguage) + .list(texts, targetLanguage) .setSource(sourceLanguage) .setKey(options.apiKey()) .execute() diff --git a/gcloud-java-translate/src/test/java/com/google/cloud/translate/TranslateImplTest.java b/gcloud-java-translate/src/test/java/com/google/cloud/translate/TranslateImplTest.java index 73bca24c118b..24b56a5bb0cb 100644 --- a/gcloud-java-translate/src/test/java/com/google/cloud/translate/TranslateImplTest.java +++ b/gcloud-java-translate/src/test/java/com/google/cloud/translate/TranslateImplTest.java @@ -19,6 +19,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; +import com.google.api.services.translate.model.DetectionsResourceItems; import com.google.api.services.translate.model.LanguagesResource; import com.google.cloud.RetryParams; import com.google.cloud.translate.Translate.LanguageListOption; @@ -56,6 +57,12 @@ public class TranslateImplTest { private static final Language LANGUAGE4 = Language.fromPb(LANGUAGE4_PB); private static final List LANGUAGES1 = ImmutableList.of(LANGUAGE1, LANGUAGE2); private static final List LANGUAGES2 = ImmutableList.of(LANGUAGE3, LANGUAGE4); + private static final DetectionsResourceItems DETECTION1_PB = + new DetectionsResourceItems().setLanguage("en").setConfidence(0.9F); + private static final DetectionsResourceItems DETECTION2_PB = + new DetectionsResourceItems().setLanguage("en").setConfidence(0.8F); + private static final Detection DETECTION1 = Detection.fromPb(DETECTION1_PB); + private static final Detection DETECTION2 = Detection.fromPb(DETECTION2_PB); // Empty TranslateRpc options private static final Map EMPTY_RPC_OPTIONS = ImmutableMap.of(); @@ -104,7 +111,7 @@ public void testGetOptions() { } @Test - public void testListSupporteLanguages() { + public void testListSupportedLanguages() { EasyMock.expect(translateRpcMock.listSupportedLanguages(EMPTY_RPC_OPTIONS)) .andReturn(ImmutableList.of(LANGUAGE1_PB, LANGUAGE2_PB)); EasyMock.replay(translateRpcMock); @@ -113,7 +120,7 @@ public void testListSupporteLanguages() { } @Test - public void testListSupporteLanguagesWithOptions() { + public void testListSupportedLanguagesWithOptions() { EasyMock.expect(translateRpcMock.listSupportedLanguages(LANGUAGE_LIST_OPTIONS)) .andReturn(ImmutableList.of(LANGUAGE3_PB, LANGUAGE4_PB)); EasyMock.replay(translateRpcMock); @@ -122,6 +129,126 @@ public void testListSupporteLanguagesWithOptions() { LanguageListOption.targetLanguage(TARGET_LANGUAGE))); } + @Test + public void testDetect() { + String text = "text"; + EasyMock.expect(translateRpcMock.detect(ImmutableList.of(text))) + .andReturn( + ImmutableList.>of(ImmutableList.of(DETECTION1_PB))); + EasyMock.replay(translateRpcMock); + initializeService(); + assertEquals(DETECTION1, translate.detect(text)); + } + + @Test + public void testDetectMultipleDetections() { + String text = "text"; + EasyMock.expect(translateRpcMock.detect(ImmutableList.of(text))) + .andReturn(ImmutableList.>of( + ImmutableList.of(DETECTION1_PB, DETECTION2_PB))); + EasyMock.replay(translateRpcMock); + initializeService(); + thrown.expect(IllegalStateException.class); + thrown.expectMessage("Multiple detections found for text: text"); + translate.detect(text); + } + + @Test + public void testDetectNoDetection() { + String text = "text"; + EasyMock.expect(translateRpcMock.detect(ImmutableList.of(text))) + .andReturn(ImmutableList.>of( + ImmutableList.of())); + EasyMock.replay(translateRpcMock); + initializeService(); + thrown.expect(IllegalStateException.class); + thrown.expectMessage("No detection found for text: text"); + translate.detect(text); + } + + @Test + public void testDetectList() { + String text1 = "text"; + String text2 = "other text"; + List texts = ImmutableList.of(text1, text2); + EasyMock.expect(translateRpcMock.detect(texts)) + .andReturn(ImmutableList.>of( + ImmutableList.of(DETECTION1_PB), ImmutableList.of(DETECTION2_PB))); + EasyMock.replay(translateRpcMock); + initializeService(); + assertEquals(ImmutableList.of(DETECTION1, DETECTION2), translate.detect(texts)); + } + + @Test + public void testDetectListMultipleDetections() { + String text1 = "text"; + String text2 = "other text"; + List texts = ImmutableList.of(text1, text2); + EasyMock.expect(translateRpcMock.detect(texts)) + .andReturn(ImmutableList.>of( + ImmutableList.of(DETECTION1_PB, DETECTION2_PB), ImmutableList.of(DETECTION1_PB))); + EasyMock.replay(translateRpcMock); + initializeService(); + thrown.expect(IllegalStateException.class); + thrown.expectMessage("Multiple detections found for text: text"); + translate.detect(texts); + } + + @Test + public void testDetectListNoDetection() { + String text1 = "text"; + String text2 = "other text"; + List texts = ImmutableList.of(text1, text2); + EasyMock.expect(translateRpcMock.detect(texts)) + .andReturn(ImmutableList.>of( + ImmutableList.of(DETECTION1_PB), ImmutableList.of())); + EasyMock.replay(translateRpcMock); + initializeService(); + thrown.expect(IllegalStateException.class); + thrown.expectMessage("No detection found for text: other text"); + translate.detect(texts); + } + + @Test + public void testDetectVararg() { + String text1 = "text"; + String text2 = "other text"; + EasyMock.expect(translateRpcMock.detect(ImmutableList.of(text1, text2))) + .andReturn(ImmutableList.>of( + ImmutableList.of(DETECTION1_PB), ImmutableList.of(DETECTION2_PB))); + EasyMock.replay(translateRpcMock); + initializeService(); + assertEquals(ImmutableList.of(DETECTION1, DETECTION2), translate.detect(text1, text2)); + } + + @Test + public void testDetectVarargMultipleDetections() { + String text1 = "text"; + String text2 = "other text"; + EasyMock.expect(translateRpcMock.detect(ImmutableList.of(text1, text2))) + .andReturn(ImmutableList.>of( + ImmutableList.of(DETECTION1_PB, DETECTION2_PB), ImmutableList.of(DETECTION1_PB))); + EasyMock.replay(translateRpcMock); + initializeService(); + thrown.expect(IllegalStateException.class); + thrown.expectMessage("Multiple detections found for text: text"); + translate.detect(text1, text2); + } + + @Test + public void testDetectVarargNoDetection() { + String text1 = "text"; + String text2 = "other text"; + EasyMock.expect(translateRpcMock.detect(ImmutableList.of(text1, text2))) + .andReturn(ImmutableList.>of( + ImmutableList.of(DETECTION1_PB), ImmutableList.of())); + EasyMock.replay(translateRpcMock); + initializeService(); + thrown.expect(IllegalStateException.class); + thrown.expectMessage("No detection found for text: other text"); + translate.detect(text1, text2); + } + @Test public void testRetryableException() { EasyMock.expect(translateRpcMock.listSupportedLanguages(EMPTY_RPC_OPTIONS))