updated comments

This commit is contained in:
Greg DiCristofaro 2020-03-06 15:42:23 -05:00
parent 9304b1d63b
commit ba60762d44
2 changed files with 126 additions and 38 deletions

View File

@ -39,7 +39,13 @@ import org.sleuthkit.autopsy.texttranslation.ui.TranslateTextTask;
*/ */
class TranslatablePanel extends JPanel { class TranslatablePanel extends JPanel {
/**
* an exception that can occur during the normal operation of the translatable panel
* for instance, this exception can be thrown if it is not possible to set the child
* content to the provided content string
*/
class TranslatablePanelException extends Exception { class TranslatablePanelException extends Exception {
public static final long serialVersionUID = 1L;
TranslatablePanelException(String message) { TranslatablePanelException(String message) {
super(message); super(message);
@ -168,9 +174,6 @@ class TranslatablePanel extends JPanel {
private final ImageIcon warningIcon = new ImageIcon(TranslatablePanel.class.getResource("/org/sleuthkit/autopsy/images/warning16.png")); private final ImageIcon warningIcon = new ImageIcon(TranslatablePanel.class.getResource("/org/sleuthkit/autopsy/images/warning16.png"));
private final ContentComponent contentComponent; private final ContentComponent contentComponent;
private final Component rootComponent;
private final String origOptionText;
private final String translatedOptionText;
private final TextTranslationService translationService; private final TextTranslationService translationService;
private final ThreadFactory translationThreadFactory = new ThreadFactoryBuilder().setNameFormat("translatable-panel-%d").build(); private final ThreadFactory translationThreadFactory = new ThreadFactoryBuilder().setNameFormat("translatable-panel-%d").build();
private final ExecutorService executorService = Executors.newSingleThreadExecutor(translationThreadFactory); private final ExecutorService executorService = Executors.newSingleThreadExecutor(translationThreadFactory);
@ -180,6 +183,7 @@ class TranslatablePanel extends JPanel {
private String content; private String content;
private String contentDescriptor; private String contentDescriptor;
private boolean prevTranslateSelection;
private volatile TranslatedText cachedTranslated; private volatile TranslatedText cachedTranslated;
private volatile OnTranslation backgroundTask = null; private volatile OnTranslation backgroundTask = null;
@ -201,31 +205,37 @@ class TranslatablePanel extends JPanel {
TranslatablePanel(ContentComponent contentComponent, String origOptionText, String translatedOptionText, String origContent, TranslatablePanel(ContentComponent contentComponent, String origOptionText, String translatedOptionText, String origContent,
TextTranslationService translationService) { TextTranslationService translationService) {
this.contentComponent = contentComponent; this.contentComponent = contentComponent;
this.rootComponent = contentComponent.getRootComponent();
this.origOptionText = origOptionText;
this.translatedOptionText = translatedOptionText;
this.translationService = translationService; this.translationService = translationService;
initComponents(); initComponents();
additionalInit(); additionalInit(contentComponent.getRootComponent(), origOptionText, translatedOptionText);
setTranslationBarVisible(); setTranslationBarVisible();
reset(); reset();
} }
/**
* @return the cached translated text or returns null
*/
private TranslatedText getCachedTranslated() { private TranslatedText getCachedTranslated() {
synchronized (cachedTranslatedLock) { synchronized (cachedTranslatedLock) {
return cachedTranslated; return cachedTranslated;
} }
} }
/**
* @param translated the translated text to be cached
*/
private void setCachedTranslated(TranslatedText translated) { private void setCachedTranslated(TranslatedText translated) {
synchronized (cachedTranslatedLock) { synchronized (cachedTranslatedLock) {
this.cachedTranslated = translated; this.cachedTranslated = translated;
} }
} }
/**
* if a translation worker is running, this is called to cancel the worker
*/
private void cancelPendingTranslation() { private void cancelPendingTranslation() {
synchronized (backgroundTaskLock) { synchronized (backgroundTaskLock) {
if (backgroundTask != null && !backgroundTask.isDone()) { if (backgroundTask != null && !backgroundTask.isDone()) {
@ -235,6 +245,9 @@ class TranslatablePanel extends JPanel {
} }
} }
/**
* runs a translation worker to translate the text
*/
private void runTranslationTask() { private void runTranslationTask() {
synchronized (backgroundTaskLock) { synchronized (backgroundTaskLock) {
cancelPendingTranslation(); cancelPendingTranslation();
@ -246,14 +259,24 @@ class TranslatablePanel extends JPanel {
} }
} }
/**
* resets the component to an empty state and sets the translation bar visibility
* based on whether there is a provider
*/
final void reset() { final void reset() {
setTranslationBarVisible(); setTranslationBarVisible();
setContent(null, null); setContent(null, null);
} }
/**
* sets the content for the component; this also clears the status
* @param content the content for the panel
* @param contentDescriptor the content descriptor to be used in error messages
*/
void setContent(String content, String contentDescriptor) { void setContent(String content, String contentDescriptor) {
cancelPendingTranslation(); cancelPendingTranslation();
this.translateComboBox.setSelectedIndex(0); this.translateComboBox.setSelectedIndex(0);
this.prevTranslateSelection = false;
this.content = content; this.content = content;
this.contentDescriptor = contentDescriptor; this.contentDescriptor = contentDescriptor;
clearStatus(); clearStatus();
@ -274,23 +297,43 @@ class TranslatablePanel extends JPanel {
return translationService.translate(input); return translationService.translate(input);
} }
/**
* clears the status bar
*/
private void clearStatus() { private void clearStatus() {
setStatus(null, false); setStatus(null, false);
} }
/**
* sets the status bar message
* @param msg the status bar message to show
* @param showWarningIcon whether that status is a warning
*/
private synchronized void setStatus(String msg, boolean showWarningIcon) { private synchronized void setStatus(String msg, boolean showWarningIcon) {
statusLabel.setText(msg); statusLabel.setText(msg);
statusLabel.setIcon(showWarningIcon ? warningIcon : null); statusLabel.setIcon(showWarningIcon ? warningIcon : null);
} }
/**
* sets the translation bar visibility based on whether or not there is a provided
*/
private void setTranslationBarVisible() { private void setTranslationBarVisible() {
translationBar.setVisible(this.translationService.hasProvider()); translationBar.setVisible(this.translationService.hasProvider());
} }
/**
* the child component provided in the constructor will have its content set to the string provided
* @param content the content to display in the child component
*/
private void setChildComponentContent(String content) { private void setChildComponentContent(String content) {
setChildComponentContent(content, DEFAULT_ORIENTATION); setChildComponentContent(content, DEFAULT_ORIENTATION);
} }
/**
* the child component provided in the constructor will have its content set to the string provided
* @param content the content to display in the child component
* @param orientation the orientation for the text
*/
@Messages({"# {0} - exception message", "TranslatablePanel.onSetContentError.text=There was an error displaying the text: {0}"}) @Messages({"# {0} - exception message", "TranslatablePanel.onSetContentError.text=There was an error displaying the text: {0}"})
private synchronized void setChildComponentContent(String content, ComponentOrientation orientation) { private synchronized void setChildComponentContent(String content, ComponentOrientation orientation) {
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
@ -302,18 +345,29 @@ class TranslatablePanel extends JPanel {
}); });
} }
private void additionalInit() { /**
add(this.rootComponent, java.awt.BorderLayout.CENTER); * items that are programmatically initialized
*/
private void additionalInit(Component rootComponent, String origOptionText, String translatedOptionText) {
add(rootComponent, java.awt.BorderLayout.CENTER);
translateComboBox.removeAllItems(); translateComboBox.removeAllItems();
translateComboBox.addItem(new TranslateOption(this.origOptionText, false)); translateComboBox.addItem(new TranslateOption(origOptionText, false));
translateComboBox.addItem(new TranslateOption(this.translatedOptionText, true)); translateComboBox.addItem(new TranslateOption(translatedOptionText, true));
} }
/**
* when the combo box choice is selected, this method is fired
* @param translateOption the current translate option
*/
private void handleComboBoxChange(TranslateOption translateOption) { private void handleComboBoxChange(TranslateOption translateOption) {
boolean curTranslateSelection = translateOption.shouldTranslate();
if (curTranslateSelection != this.prevTranslateSelection) {
this.prevTranslateSelection = curTranslateSelection;
cancelPendingTranslation(); cancelPendingTranslation();
clearStatus(); clearStatus();
if (translateOption.shouldTranslate()) { if (curTranslateSelection) {
TranslatedText translated = getCachedTranslated(); TranslatedText translated = getCachedTranslated();
if (translated != null) { if (translated != null) {
setChildComponentContent(translated.getText(), translated.getOrientation()); setChildComponentContent(translated.getText(), translated.getOrientation());
@ -324,6 +378,7 @@ class TranslatablePanel extends JPanel {
setChildComponentContent(content); setChildComponentContent(content);
} }
} }
}
/** /**
* This method is called from within the constructor to initialize the form. * This method is called from within the constructor to initialize the form.

View File

@ -36,7 +36,7 @@ import org.sleuthkit.autopsy.texttranslation.TranslationException;
/** /**
* abstract class for translating text and displaying to the user * abstract class for translating text and displaying to the user
*/ */
public abstract class TranslateTextTask extends SwingWorker<TranslateTextTask.Result, Void> { public abstract class TranslateTextTask extends SwingWorker<TranslateTextTask.TranslateResult, Void> {
private static final Logger logger = Logger.getLogger(TranslatedTextViewer.class.getName()); private static final Logger logger = Logger.getLogger(TranslatedTextViewer.class.getName());
@ -46,21 +46,21 @@ public abstract class TranslateTextTask extends SwingWorker<TranslateTextTask.Re
/** /**
* as a result of running and processing the translation * as a result of running and processing the translation
*/ */
public static class Result { public static class TranslateResult {
private final String errorMessage; private final String errorMessage;
private final String result; private final String result;
private final boolean successful; private final boolean successful;
public static Result error(String message) { public static TranslateResult error(String message) {
return new Result(null, message, false); return new TranslateResult(null, message, false);
} }
public static Result success(String content) { public static TranslateResult success(String content) {
return new Result(content, null, true); return new TranslateResult(content, null, true);
} }
private Result(String result, String errorMessage, boolean successful) { private TranslateResult(String result, String errorMessage, boolean successful) {
this.successful = successful; this.successful = successful;
this.errorMessage = errorMessage; this.errorMessage = errorMessage;
this.result = result; this.result = result;
@ -91,15 +91,42 @@ public abstract class TranslateTextTask extends SwingWorker<TranslateTextTask.Re
this.contentDescriptor = fileDescriptor; this.contentDescriptor = fileDescriptor;
} }
/**
* retrieves the original text content to be translated
* @return the original text content
* @throws IOException
* @throws InterruptedException
* @throws IllegalStateException
*/
protected abstract String retrieveText() throws IOException, InterruptedException, IllegalStateException; protected abstract String retrieveText() throws IOException, InterruptedException, IllegalStateException;
/**
* method to be overridden when a translated text result is received
* @param text the text to display
* @param orientation the orientation of the text
* @param font the font style (returns plain)
*/
protected abstract void onTextDisplay(String text, ComponentOrientation orientation, int font); protected abstract void onTextDisplay(String text, ComponentOrientation orientation, int font);
/**
* when a progress result is received, this method is called
* this method can be overridden depending on the scenario but defaults to just displaying using onTextDisplay
* @param text the text of the status update
* @param orientation the orientation for the status
* @param font the font style of the status
*/
protected void onProgressDisplay(String text, ComponentOrientation orientation, int font) { protected void onProgressDisplay(String text, ComponentOrientation orientation, int font) {
// default to normal display unless overridden // default to normal display unless overridden
onTextDisplay(text, orientation, font); onTextDisplay(text, orientation, font);
} }
/**
* when an error result is received, this method is called
* this method can be overridden depending on the scenario but defaults to just displaying using onTextDisplay
* @param text the text of the error
* @param orientation the orientation for the error
* @param font the font style of the error
*/
protected void onErrorDisplay(String text, ComponentOrientation orientation, int font) { protected void onErrorDisplay(String text, ComponentOrientation orientation, int font) {
// default to normal display unless overridden // default to normal display unless overridden
onTextDisplay(text, orientation, font); onTextDisplay(text, orientation, font);
@ -112,7 +139,7 @@ public abstract class TranslateTextTask extends SwingWorker<TranslateTextTask.Re
"# {0} - exception message", "TranslatedContentViewer.translationException=An error occurred while translating the text ({0})." "# {0} - exception message", "TranslatedContentViewer.translationException=An error occurred while translating the text ({0})."
}) })
@Override @Override
public Result doInBackground() throws InterruptedException { public TranslateResult doInBackground() throws InterruptedException {
if (this.isCancelled()) { if (this.isCancelled()) {
throw new InterruptedException(); throw new InterruptedException();
} }
@ -121,7 +148,7 @@ public abstract class TranslateTextTask extends SwingWorker<TranslateTextTask.Re
try { try {
fileText = retrieveText(); fileText = retrieveText();
} catch (IOException | IllegalStateException ex) { } catch (IOException | IllegalStateException ex) {
return Result.error(ex.getMessage()); return TranslateResult.error(ex.getMessage());
} }
if (this.isCancelled()) { if (this.isCancelled()) {
@ -129,17 +156,23 @@ public abstract class TranslateTextTask extends SwingWorker<TranslateTextTask.Re
} }
if (fileText == null || fileText.isEmpty()) { if (fileText == null || fileText.isEmpty()) {
return Result.error(Bundle.TranslatedContentViewer_fileHasNoText()); return TranslateResult.error(Bundle.TranslatedContentViewer_fileHasNoText());
} }
if (!this.translateText) { if (!this.translateText) {
return Result.success(fileText); return TranslateResult.success(fileText);
} }
return translateRetrievedText(fileText); return translateRetrievedText(fileText);
} }
private Result translateRetrievedText(String fileText) throws InterruptedException { /**
* final step in translation swing worker prior to being done(); translates the text if needed
* @param fileText the text to translate
* @return the translated text
* @throws InterruptedException if operation is canclled, an interrupted exception is thrown
*/
private TranslateResult translateRetrievedText(String fileText) throws InterruptedException {
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
onProgressDisplay(Bundle.TranslatedContentViewer_translatingText(), ComponentOrientation.LEFT_TO_RIGHT, Font.ITALIC); onProgressDisplay(Bundle.TranslatedContentViewer_translatingText(), ComponentOrientation.LEFT_TO_RIGHT, Font.ITALIC);
}); });
@ -151,17 +184,17 @@ public abstract class TranslateTextTask extends SwingWorker<TranslateTextTask.Re
} }
if (translation == null || translation.isEmpty()) { if (translation == null || translation.isEmpty()) {
return Result.error(Bundle.TranslatedContentViewer_emptyTranslation()); return TranslateResult.error(Bundle.TranslatedContentViewer_emptyTranslation());
} else { } else {
return Result.success(translation); return TranslateResult.success(translation);
} }
} catch (NoServiceProviderException ex) { } catch (NoServiceProviderException ex) {
logger.log(Level.WARNING, "Error translating text for file " + this.contentDescriptor, ex); logger.log(Level.WARNING, "Error translating text for file " + this.contentDescriptor, ex);
return Result.error(Bundle.TranslatedContentViewer_noServiceProvider()); return TranslateResult.error(Bundle.TranslatedContentViewer_noServiceProvider());
} catch (TranslationException ex) { } catch (TranslationException ex) {
logger.log(Level.WARNING, "Error translating text for file " + this.contentDescriptor, ex); logger.log(Level.WARNING, "Error translating text for file " + this.contentDescriptor, ex);
return Result.error(Bundle.TranslatedContentViewer_translationException(ex.getMessage())); return TranslateResult.error(Bundle.TranslatedContentViewer_translationException(ex.getMessage()));
} }
} }
@ -169,7 +202,7 @@ public abstract class TranslateTextTask extends SwingWorker<TranslateTextTask.Re
@Override @Override
public void done() { public void done() {
try { try {
Result executionResult = get(); TranslateResult executionResult = get();
if (this.isCancelled()) { if (this.isCancelled()) {
throw new InterruptedException(); throw new InterruptedException();
} }