diff --git a/zanata-war/src/main/java/org/zanata/service/TranslationStateCache.java b/zanata-war/src/main/java/org/zanata/service/TranslationStateCache.java index 7d403fda0f..b779dc7a4d 100644 --- a/zanata-war/src/main/java/org/zanata/service/TranslationStateCache.java +++ b/zanata-war/src/main/java/org/zanata/service/TranslationStateCache.java @@ -62,5 +62,5 @@ public interface TranslationStateCache * @param validationId * @return */ - Boolean textFlowTargetHasError(Long textFlowTargetId, ValidationId validationId); + Boolean textFlowTargetHasWarningOrError(Long textFlowTargetId, ValidationId validationId); } diff --git a/zanata-war/src/main/java/org/zanata/service/ValidationService.java b/zanata-war/src/main/java/org/zanata/service/ValidationService.java index 9ab9aa94f3..0166b104e1 100644 --- a/zanata-war/src/main/java/org/zanata/service/ValidationService.java +++ b/zanata-war/src/main/java/org/zanata/service/ValidationService.java @@ -10,6 +10,7 @@ import org.zanata.common.LocaleId; import org.zanata.model.HDocument; import org.zanata.model.HTextFlow; +import org.zanata.webtrans.shared.model.TransUnitUpdateRequest; import org.zanata.webtrans.shared.model.ValidationAction; import org.zanata.webtrans.shared.model.ValidationId; @@ -61,7 +62,7 @@ public interface ValidationService * @param maxSize * @throws IOException */ - List filterHasErrorTextFlow(List textFlows, List validationIds, + List filterHasWarningOrErrorTextFlow(List textFlows, List validationIds, LocaleId localeId, int startIndex, int maxSize); /** @@ -75,4 +76,14 @@ List filterHasErrorTextFlow(List textFlows, List updateRequests); } diff --git a/zanata-war/src/main/java/org/zanata/service/impl/TranslationStateCacheImpl.java b/zanata-war/src/main/java/org/zanata/service/impl/TranslationStateCacheImpl.java index a64c4d4f71..5bd200dcea 100644 --- a/zanata-war/src/main/java/org/zanata/service/impl/TranslationStateCacheImpl.java +++ b/zanata-war/src/main/java/org/zanata/service/impl/TranslationStateCacheImpl.java @@ -151,7 +151,7 @@ private void invalidateDocLastTranslatedCache(Long documentId, LocaleId localeId } @Override - public Boolean textFlowTargetHasError(Long targetId, ValidationId validationId) + public Boolean textFlowTargetHasWarningOrError(Long targetId, ValidationId validationId) { Map cacheEntry = targetValidationCache.getWithLoader(targetId); if (!cacheEntry.containsKey(validationId)) diff --git a/zanata-war/src/main/java/org/zanata/service/impl/ValidationServiceImpl.java b/zanata-war/src/main/java/org/zanata/service/impl/ValidationServiceImpl.java index 3d551c5793..a3a17ed590 100644 --- a/zanata-war/src/main/java/org/zanata/service/impl/ValidationServiceImpl.java +++ b/zanata-war/src/main/java/org/zanata/service/impl/ValidationServiceImpl.java @@ -4,6 +4,7 @@ package org.zanata.service.impl; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; @@ -30,6 +31,7 @@ import org.zanata.service.ValidationService; import org.zanata.webtrans.server.rpc.TransUnitTransformer; import org.zanata.webtrans.shared.model.DocumentStatus; +import org.zanata.webtrans.shared.model.TransUnitUpdateRequest; import org.zanata.webtrans.shared.model.ValidationAction; import org.zanata.webtrans.shared.model.ValidationAction.State; import org.zanata.webtrans.shared.model.ValidationId; @@ -82,7 +84,6 @@ private ValidationFactory getValidationFactory() @Override public Collection getValidationAction(String projectSlug) { - Collection allValidations = getValidationFactory().getAllValidationActions().values(); Map customizedValidations = Maps.newHashMap(); if (!StringUtils.isEmpty(projectSlug)) @@ -91,25 +92,15 @@ public Collection getValidationAction(String projectSlug) customizedValidations = project.getCustomizedValidations(); } - for (ValidationAction valAction : allValidations) - { - String name = valAction.getId().name(); - if (customizedValidations.containsKey(name)) - { - State persistedState = State.valueOf(customizedValidations.get(name)); - valAction.setState(persistedState); - } - } - return allValidations; + return mergeCustomisedStateToAllValidations(customizedValidations); } @Override public Collection getValidationAction(String projectSlug, String versionSlug) { - Collection allValidations = getValidationFactory().getAllValidationActions().values(); Map customizedValidations = Maps.newHashMap(); - if (!StringUtils.isEmpty(projectSlug)) + if (!StringUtils.isEmpty(projectSlug) && !StringUtils.isEmpty(versionSlug)) { HProjectIteration version = projectIterationDAO.getBySlug(projectSlug, versionSlug); @@ -120,10 +111,17 @@ public Collection getValidationAction(String projectSlug, Stri */ if (customizedValidations.isEmpty()) { - customizedValidations = version.getProject().getCustomizedValidations(); + return getValidationAction(projectSlug); } } + return mergeCustomisedStateToAllValidations(customizedValidations); + } + + private Collection mergeCustomisedStateToAllValidations(Map customizedValidations) + { + Collection allValidations = getValidationFactory().getAllValidationActions().values(); + for (ValidationAction valAction : allValidations) { String name = valAction.getId().name(); @@ -136,33 +134,41 @@ public Collection getValidationAction(String projectSlug, Stri return allValidations; } - private List getWarnOrErrorValidationIds(HProjectIteration version) + /** + * Get validation id of the HProjectIteration with includeStates. Leave includeStates empty to get all states + * @param version + * @return + */ + private List getValidationIds(HProjectIteration version, State... includeStates) { - Collection allValidations = getValidationFactory().getAllValidationActions().values(); Map customizedValidations = Maps.newHashMap(); + List includeStateList = Arrays.asList(includeStates); - List warnOrErrorValidationIds = new ArrayList(); + List filteredValidationIds = new ArrayList(); if (version != null) { customizedValidations = version.getCustomizedValidations(); - // Inherits validations from project if version has no defined - // validations + /** + * Inherits validations from project if version has no defined validations + */ if (customizedValidations.isEmpty()) { customizedValidations = version.getProject().getCustomizedValidations(); } } - for (ValidationAction valAction : allValidations) + Collection mergedList = mergeCustomisedStateToAllValidations(customizedValidations); + + for (ValidationAction action : mergedList) { - if (customizedValidations.containsKey(valAction.getId().name())) + if (includeStateList.isEmpty() || includeStateList.contains(action.getState())) { - warnOrErrorValidationIds.add(valAction.getId()); + filteredValidationIds.add(action.getId()); } } - return warnOrErrorValidationIds; + return filteredValidationIds; } /** @@ -189,7 +195,7 @@ public boolean runDocValidations(Long hDocId, List validationIds, else { HDocument hDoc = documentDAO.findById(hDocId, false); - result = documentHasError(hDoc, validationIds, localeId); + result = documentHasWarningOrError(hDoc, validationIds, localeId); } log.debug("Finished runDocValidations in " + stopwatch); @@ -202,19 +208,19 @@ public boolean runDocValidationsWithServerRules(HDocument hDoc, LocaleId localeI log.debug("Start runDocValidationsWithServerRules {0}", hDoc.getId()); Stopwatch stopwatch = new Stopwatch().start(); - List validationIds = getWarnOrErrorValidationIds(hDoc.getProjectIteration()); + List validationIds = getValidationIds(hDoc.getProjectIteration(), State.Warning, State.Error); - boolean hasError = documentHasError(hDoc, validationIds, localeId); + boolean hasError = documentHasWarningOrError(hDoc, validationIds, localeId); log.debug("Finished runDocValidationsWithServerRules in " + stopwatch); return hasError; } - private boolean documentHasError(HDocument hDoc, List validationIds, LocaleId localeId) + private boolean documentHasWarningOrError(HDocument hDoc, List validationIds, LocaleId localeId) { for (HTextFlow textFlow : hDoc.getTextFlows()) { - boolean hasError = textFlowTargetHasError(textFlow.getId(), validationIds, localeId); + boolean hasError = textFlowTargetHasWarningOrError(textFlow.getId(), validationIds, localeId); if (hasError) { // return true if error found, else continue @@ -225,7 +231,7 @@ private boolean documentHasError(HDocument hDoc, List validationId } @Override - public List filterHasErrorTextFlow(List textFlows, List validationIds, + public List filterHasWarningOrErrorTextFlow(List textFlows, List validationIds, LocaleId localeId, int startIndex, int maxSize) { log.debug("Start filter {0} textFlows", textFlows.size()); @@ -235,8 +241,8 @@ public List filterHasErrorTextFlow(List textFlows, List filterHasErrorTextFlow(List textFlows, List validationIds, LocaleId localeId) + private boolean textFlowTargetHasWarningOrError(Long textFlowId, List validationIds, LocaleId localeId) { HTextFlowTarget target = textFlowTargetDAO.getTextFlowTarget(textFlowId, localeId); if (target != null) { for (ValidationId validationId : validationIds) { - Boolean value = translationStateCacheImpl.textFlowTargetHasError(target.getId(), validationId); + Boolean value = translationStateCacheImpl.textFlowTargetHasWarningOrError(target.getId(), validationId); if (value != null && value.booleanValue()) { return value.booleanValue(); @@ -273,4 +279,23 @@ private boolean textFlowTargetHasError(Long textFlowId, List valid } return false; } + + @Override + public boolean updateRequestHasError(String projectSlug, String versionSlug, LocaleId localeId, + List updateRequests) + { + HProjectIteration version = projectIterationDAO.getBySlug(projectSlug, versionSlug); + List validationIds = getValidationIds(version, State.Error); + + for (TransUnitUpdateRequest updateRequest : updateRequests) + { + if (textFlowTargetHasWarningOrError(updateRequest.getTransUnitId().getId(), validationIds, localeId)) + { + return true; + } + } + + return false; + } + } diff --git a/zanata-war/src/main/java/org/zanata/webtrans/client/resources/TableEditorMessages.java b/zanata-war/src/main/java/org/zanata/webtrans/client/resources/TableEditorMessages.java index 8c2e35e261..45ed6bb330 100644 --- a/zanata-war/src/main/java/org/zanata/webtrans/client/resources/TableEditorMessages.java +++ b/zanata-war/src/main/java/org/zanata/webtrans/client/resources/TableEditorMessages.java @@ -131,4 +131,13 @@ public interface TableEditorMessages extends Messages @DefaultMessage("Save changes before filtering view?") String saveChangesConfirmationMessage(); + + @DefaultMessage("You''re trying to save translation that contains validation error.") + String validationErrorMessage(); + + @DefaultMessage("Translation") + String translation(); + + @DefaultMessage("Error message") + String errorMessage(); } diff --git a/zanata-war/src/main/java/org/zanata/webtrans/client/ui/ValidationWarningPanel.java b/zanata-war/src/main/java/org/zanata/webtrans/client/ui/ValidationWarningPanel.java index 47b1dfb06a..805382b1d1 100644 --- a/zanata-war/src/main/java/org/zanata/webtrans/client/ui/ValidationWarningPanel.java +++ b/zanata-war/src/main/java/org/zanata/webtrans/client/ui/ValidationWarningPanel.java @@ -82,7 +82,7 @@ public ValidationWarningPanel(TableEditorMessages messages) HTMLPanel container = uiBinder.createAndBindUi(this); - messageLabel.setText("You're trying to save translation that contains validation error."); + messageLabel.setText(messages.validationErrorMessage()); setGlassEnabled(true); setWidget(container); diff --git a/zanata-war/src/main/java/org/zanata/webtrans/client/ui/ValidationWarningPanel.ui.xml b/zanata-war/src/main/java/org/zanata/webtrans/client/ui/ValidationWarningPanel.ui.xml index c7aaf942f3..b78e70ebd5 100644 --- a/zanata-war/src/main/java/org/zanata/webtrans/client/ui/ValidationWarningPanel.ui.xml +++ b/zanata-war/src/main/java/org/zanata/webtrans/client/ui/ValidationWarningPanel.ui.xml @@ -3,17 +3,19 @@ xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:z='urn:import:org.zanata.webtrans.client.ui'> + +
  • -
    Translations
    +
  • -
    Error message
    +
  • diff --git a/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/GetTransUnitListHandler.java b/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/GetTransUnitListHandler.java index e90bbb5cca..e47e34ab2f 100755 --- a/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/GetTransUnitListHandler.java +++ b/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/GetTransUnitListHandler.java @@ -137,7 +137,7 @@ private List getTextFlows(GetTransUnitList action, HLocale hLocale, i // TODO debt: this is not scalable. But we may not have other choice // for validation filter. Maybe use scrollable result will help? textFlows = textFlowDAO.getAllTextFlowsByDocumentId(action.getDocumentId()); - textFlows = validationServiceImpl.filterHasErrorTextFlow(textFlows, action.getValidationIds(), hLocale.getLocaleId(), offset, action.getCount()); + textFlows = validationServiceImpl.filterHasWarningOrErrorTextFlow(textFlows, action.getValidationIds(), hLocale.getLocaleId(), offset, action.getCount()); } } // has status and phrase filter @@ -159,7 +159,7 @@ private List getTextFlows(GetTransUnitList action, HLocale hLocale, i else { textFlows = textFlowDAO.getAllTextFlowByDocumentIdWithConstraints(action.getDocumentId(), hLocale, constraints); - textFlows = validationServiceImpl.filterHasErrorTextFlow(textFlows, action.getValidationIds(), hLocale.getLocaleId(), offset, action.getCount()); + textFlows = validationServiceImpl.filterHasWarningOrErrorTextFlow(textFlows, action.getValidationIds(), hLocale.getLocaleId(), offset, action.getCount()); } } return textFlows; diff --git a/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/UpdateTransUnitHandler.java b/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/UpdateTransUnitHandler.java index f925d77750..d05e4d9687 100644 --- a/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/UpdateTransUnitHandler.java +++ b/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/UpdateTransUnitHandler.java @@ -36,6 +36,7 @@ import org.zanata.service.SecurityService; import org.zanata.service.TranslationService; import org.zanata.service.TranslationService.TranslationResult; +import org.zanata.service.ValidationService; import org.zanata.webtrans.server.ActionHandlerFor; import org.zanata.webtrans.server.TranslationWorkspace; import org.zanata.webtrans.shared.auth.EditorClientId; @@ -48,7 +49,6 @@ import org.zanata.webtrans.shared.rpc.UpdateTransUnit; import org.zanata.webtrans.shared.rpc.UpdateTransUnitResult; - @Name("webtrans.gwt.UpdateTransUnitHandler") @Scope(ScopeType.STATELESS) @ActionHandlerFor(UpdateTransUnit.class) @@ -63,12 +63,15 @@ public class UpdateTransUnitHandler extends AbstractActionHandler updateRequests, EditorClientId editorClientId, TransUnitUpdated.UpdateType updateType) + protected UpdateTransUnitResult doTranslation(LocaleId localeId, TranslationWorkspace workspace, + List updateRequests, EditorClientId editorClientId, + TransUnitUpdated.UpdateType updateType) { UpdateTransUnitResult result = new UpdateTransUnitResult(); List translationResults = translationServiceImpl.translate(localeId, updateRequests); @@ -93,7 +111,10 @@ protected UpdateTransUnitResult doTranslation(LocaleId localeId, TranslationWork HTextFlow hTextFlow = newTarget.getTextFlow(); int wordCount = hTextFlow.getWordCount().intValue(); TransUnit tu = transUnitTransformer.transform(hTextFlow, newTarget.getLocale()); - TransUnitUpdateInfo updateInfo = new TransUnitUpdateInfo(translationResult.isTranslationSuccessful(), translationResult.isTargetChanged(), new DocumentId(hTextFlow.getDocument().getId(), hTextFlow.getDocument().getDocId()), tu, wordCount, translationResult.getBaseVersionNum(), translationResult.getBaseContentState()); + TransUnitUpdateInfo updateInfo = new TransUnitUpdateInfo(translationResult.isTranslationSuccessful(), + translationResult.isTargetChanged(), new DocumentId(hTextFlow.getDocument().getId(), hTextFlow + .getDocument().getDocId()), tu, wordCount, translationResult.getBaseVersionNum(), + translationResult.getBaseContentState()); workspace.publish(new TransUnitUpdated(updateInfo, editorClientId, updateType)); result.addUpdateResult(updateInfo); @@ -103,7 +124,8 @@ protected UpdateTransUnitResult doTranslation(LocaleId localeId, TranslationWork } @Override - public void rollback(UpdateTransUnit action, UpdateTransUnitResult result, ExecutionContext context) throws ActionException + public void rollback(UpdateTransUnit action, UpdateTransUnitResult result, ExecutionContext context) + throws ActionException { // TODO implement rollback by checking result for success // if success, looking up base revision from action and set values back to that diff --git a/zanata-war/src/test/java/org/zanata/service/impl/TranslationStateCacheImplTest.java b/zanata-war/src/test/java/org/zanata/service/impl/TranslationStateCacheImplTest.java index edc69f717f..63e11a0de2 100644 --- a/zanata-war/src/test/java/org/zanata/service/impl/TranslationStateCacheImplTest.java +++ b/zanata-war/src/test/java/org/zanata/service/impl/TranslationStateCacheImplTest.java @@ -106,7 +106,7 @@ public void testTextFlowTargetHasError() throws Exception when(targetValidationLoader.load(targetId)).thenReturn(map); // Run: - Boolean result = tsCache.textFlowTargetHasError(targetId, validationId); + Boolean result = tsCache.textFlowTargetHasWarningOrError(targetId, validationId); // Then: verify(targetValidationLoader).load(targetId); // only load the value once @@ -125,7 +125,7 @@ public void testTextFlowTargetHasError2() throws Exception when(targetValidationLoader.load(targetId)).thenReturn(map); // Run: - Boolean result = tsCache.textFlowTargetHasError(targetId, validationId); + Boolean result = tsCache.textFlowTargetHasWarningOrError(targetId, validationId); // Then: verify(targetValidationLoader).load(targetId); // only load the value once