abstracted TranslateTextTask

This commit is contained in:
Greg DiCristofaro 2020-03-05 09:10:05 -05:00
parent 1f7ab40a4d
commit fe86d86dd2
4 changed files with 175 additions and 109 deletions

View File

@ -110,7 +110,7 @@ final class TextTranslatableComponent implements TranslatablePanel.TranslatableC
this.translated = this.translationService.translate(originalContent); this.translated = this.translationService.translate(originalContent);
} catch (NoServiceProviderException | TranslationException ex) { } catch (NoServiceProviderException | TranslationException ex) {
LOGGER.log(Level.WARNING, "Unable to translate text with translation service", ex); LOGGER.log(Level.WARNING, "Unable to translate text with translation service", ex);
return Bundle.TextTranslatableComponent_setTranslated_onTranslateError(); //return Bundle.TextTranslatableComponent_setTranslated_onTranslateError();
} }
}); });
} }

View File

@ -30,7 +30,9 @@ import org.sleuthkit.autopsy.texttranslation.TextTranslationService;
* A panel for translation with a subcomponent that allows for translation * A panel for translation with a subcomponent that allows for translation
*/ */
final class TranslatablePanel extends JPanel { final class TranslatablePanel extends JPanel {
interface ContentSetter {
void set(String content) throws Exception;
}
/** /**
* an option in drop down of whether or not to translate * an option in drop down of whether or not to translate

View File

@ -0,0 +1,160 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* 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 org.sleuthkit.autopsy.texttranslation.ui;
import java.awt.ComponentOrientation;
import java.awt.Font;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.TextUtil;
import org.sleuthkit.autopsy.texttranslation.NoServiceProviderException;
import org.sleuthkit.autopsy.texttranslation.TextTranslationService;
import org.sleuthkit.autopsy.texttranslation.TranslationException;
/**
* abstract class for translating text and displaying to the user
*/
public abstract class TranslateTextTask extends SwingWorker<String, Void> {
private static final Logger logger = Logger.getLogger(TranslatedTextViewer.class.getName());
private final boolean translateText;
private final String contentDescriptor;
/**
*
* @param translateText whether or not to translate text
* @param contentDescriptor the content descriptor for the item being translated (used for logging errors)
*/
public TranslateTextTask(boolean translateText, String fileDescriptor) {
this.translateText = translateText;
this.contentDescriptor = fileDescriptor;
}
protected abstract String retrieveText() throws Exception;
protected abstract void onTextDisplay(String text, ComponentOrientation orientation, int font);
@NbBundle.Messages({
"TranslatedContentViewer.extractingText=Extracting text, please wait...",
"TranslatedContentViewer.translatingText=Translating text, please wait...",
"# {0} - exception message", "TranslatedContentViewer.errorExtractingText=An error occurred while extracting the text ({0}).",
"TranslatedContentViewer.fileHasNoText=File has no text.",
"TranslatedContentViewer.noServiceProvider=The machine translation software was not found.",
"# {0} - exception message", "TranslatedContentViewer.translationException=An error occurred while translating the text ({0})."
})
@Override
public String doInBackground() throws InterruptedException {
if (this.isCancelled()) {
throw new InterruptedException();
}
SwingUtilities.invokeLater(() -> {
onTextDisplay(Bundle.TranslatedContentViewer_extractingText(), ComponentOrientation.LEFT_TO_RIGHT, Font.ITALIC);
});
String fileText;
try {
fileText = retrieveText();
} catch (InterruptedException | CancellationException e) {
// bubble up cancellation instead of continuing
throw e;
} catch (Exception ex) {
logger.log(Level.WARNING, "Error extracting text for file " + this.contentDescriptor, ex);
return Bundle.TranslatedContentViewer_errorExtractingText(ex.getMessage());
}
if (this.isCancelled()) {
throw new InterruptedException();
}
if (fileText == null || fileText.isEmpty()) {
return Bundle.TranslatedContentViewer_fileHasNoText();
}
if (!this.translateText) {
return fileText;
}
SwingUtilities.invokeLater(() -> {
onTextDisplay(Bundle.TranslatedContentViewer_translatingText(), ComponentOrientation.LEFT_TO_RIGHT, Font.ITALIC);
});
String translation;
try {
translation = translate(fileText);
} catch (NoServiceProviderException ex) {
logger.log(Level.WARNING, "Error translating text for file " + this.contentDescriptor, ex);
translation = Bundle.TranslatedContentViewer_noServiceProvider();
} catch (TranslationException ex) {
logger.log(Level.WARNING, "Error translating text for file " + this.contentDescriptor, ex);
translation = Bundle.TranslatedContentViewer_translationException(ex.getMessage());
}
if (this.isCancelled()) {
throw new InterruptedException();
}
return translation;
}
@Override
public void done() {
try {
String result = get();
if (this.isCancelled()) {
throw new InterruptedException();
}
int len = result.length();
int maxOrientChars = Math.min(len, 1024);
String orientDetectSubstring = result.substring(0, maxOrientChars);
ComponentOrientation orientation = TextUtil.getTextDirection(orientDetectSubstring);
onTextDisplay(result, orientation, Font.PLAIN);
} catch (InterruptedException | CancellationException ignored) {
// Task cancelled, no error.
} catch (ExecutionException ex) {
logger.log(Level.WARNING, "Error occurred during background task execution for file " + this.contentDescriptor, ex);
onTextDisplay(Bundle.TranslatedContentViewer_translationException(ex.getMessage()), ComponentOrientation.LEFT_TO_RIGHT, Font.ITALIC);
}
}
/**
* Pass the translation off to the Translation service provider.
*
* @param input Text to be translated
*
* @return Translated text or error message
*/
@NbBundle.Messages({
"TranslatedContentViewer.emptyTranslation=The machine translation software did not return any text."
})
private String translate(String input) throws NoServiceProviderException, TranslationException {
TextTranslationService translatorInstance = TextTranslationService.getInstance();
String translatedResult = translatorInstance.translate(input);
if (translatedResult.isEmpty()) {
return Bundle.TranslatedContentViewer_emptyTranslation();
}
return translatedResult;
}
}

View File

@ -160,112 +160,13 @@ public final class TranslatedTextViewer implements TextViewer {
/** /**
* Extracts text from a file and optionally translates it. * Extracts text from a file and optionally translates it.
*/ */
private class ExtractAndTranslateTextTask extends SwingWorker<String, Void> { private class ExtractAndTranslateTextTask extends TranslateTextTask {
private final AbstractFile file; private final AbstractFile file;
private final boolean translateText;
private ExtractAndTranslateTextTask(AbstractFile file, boolean translateText) { private ExtractAndTranslateTextTask(AbstractFile file, boolean translateText) {
super(translateText, String.format("%s (objId=%d)", file.getName(), file.getId()));
this.file = file; this.file = file;
this.translateText = translateText;
}
@NbBundle.Messages({
"TranslatedContentViewer.extractingText=Extracting text, please wait...",
"TranslatedContentViewer.translatingText=Translating text, please wait...",
"# {0} - exception message", "TranslatedContentViewer.errorExtractingText=An error occurred while extracting the text ({0}).",
"TranslatedContentViewer.fileHasNoText=File has no text.",
"TranslatedContentViewer.noServiceProvider=The machine translation software was not found.",
"# {0} - exception message", "TranslatedContentViewer.translationException=An error occurred while translating the text ({0})."
})
@Override
public String doInBackground() throws InterruptedException {
if (this.isCancelled()) {
throw new InterruptedException();
}
SwingUtilities.invokeLater(() -> {
panel.display(Bundle.TranslatedContentViewer_extractingText(), ComponentOrientation.LEFT_TO_RIGHT, Font.ITALIC);
});
String fileText;
try {
fileText = getFileText(file);
} catch (IOException | TextExtractor.InitReaderException ex) {
logger.log(Level.WARNING, String.format("Error extracting text for file %s (objId=%d)", file.getName(), file.getId()), ex);
return Bundle.TranslatedContentViewer_errorExtractingText(ex.getMessage());
}
if (this.isCancelled()) {
throw new InterruptedException();
}
if (fileText == null || fileText.isEmpty()) {
return Bundle.TranslatedContentViewer_fileHasNoText();
}
if (!this.translateText) {
return fileText;
}
SwingUtilities.invokeLater(() -> {
panel.display(Bundle.TranslatedContentViewer_translatingText(), ComponentOrientation.LEFT_TO_RIGHT, Font.ITALIC);
});
String translation;
try {
translation = translate(fileText);
} catch (NoServiceProviderException ex) {
logger.log(Level.WARNING, String.format("Error translating text for file %s (objId=%d)", file.getName(), file.getId()), ex);
translation = Bundle.TranslatedContentViewer_noServiceProvider();
} catch (TranslationException ex) {
logger.log(Level.WARNING, String.format("Error translating text for file %s (objId=%d)", file.getName(), file.getId()), ex);
translation = Bundle.TranslatedContentViewer_translationException(ex.getMessage());
}
if (this.isCancelled()) {
throw new InterruptedException();
}
return translation;
}
@Override
public void done() {
try {
String result = get();
if (this.isCancelled()) {
throw new InterruptedException();
}
int len = result.length();
int maxOrientChars = Math.min(len, 1024);
String orientDetectSubstring = result.substring(0, maxOrientChars);
ComponentOrientation orientation = TextUtil.getTextDirection(orientDetectSubstring);
panel.display(result, orientation, Font.PLAIN);
} catch (InterruptedException | CancellationException ignored) {
// Task cancelled, no error.
} catch (ExecutionException ex) {
logger.log(Level.WARNING, String.format("Error occurred during background task execution for file %s (objId=%d)", file.getName(), file.getId()), ex);
panel.display(Bundle.TranslatedContentViewer_translationException(ex.getMessage()), ComponentOrientation.LEFT_TO_RIGHT, Font.ITALIC);
}
}
/**
* Pass the translation off to the Translation service provider.
*
* @param input Text to be translated
*
* @return Translated text or error message
*/
@NbBundle.Messages({
"TranslatedContentViewer.emptyTranslation=The machine translation software did not return any text."
})
private String translate(String input) throws NoServiceProviderException, TranslationException {
TextTranslationService translatorInstance = TextTranslationService.getInstance();
String translatedResult = translatorInstance.translate(input);
if (translatedResult.isEmpty()) {
return Bundle.TranslatedContentViewer_emptyTranslation();
}
return translatedResult;
} }
/** /**
@ -275,13 +176,9 @@ public final class TranslatedTextViewer implements TextViewer {
* *
* @return Extracted text * @return Extracted text
* *
* @throws IOException * @throws Exception
* @throws InterruptedException
* @throws
* org.sleuthkit.autopsy.textextractors.TextExtractor.InitReaderException
*/ */
private String getFileText(AbstractFile file) throws IOException, protected String retrieveText() throws Exception {
InterruptedException, TextExtractor.InitReaderException {
final boolean isImage = file.getMIMEType().toLowerCase().startsWith("image/"); // NON-NLS final boolean isImage = file.getMIMEType().toLowerCase().startsWith("image/"); // NON-NLS
String result; String result;
@ -382,8 +279,15 @@ public final class TranslatedTextViewer implements TextViewer {
return TextExtractorFactory.getStringsExtractor(file, context).getReader(); return TextExtractorFactory.getStringsExtractor(file, context).getReader();
} }
} }
@Override
protected void onTextDisplay(String text, ComponentOrientation orientation, int font) {
panel.display(text, orientation, font);
}
} }
/** /**
* Listens for drop-down selection changes and pushes processing off of the * Listens for drop-down selection changes and pushes processing off of the
* EDT and into a SwingWorker. * EDT and into a SwingWorker.