Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

Commit

Permalink
Work in progress: server side validation checking on editor update tr…
Browse files Browse the repository at this point in the history
…anslation
  • Loading branch information
Alex Eng committed Sep 2, 2013
1 parent 72697ef commit 150a92a
Show file tree
Hide file tree
Showing 10 changed files with 118 additions and 49 deletions.
Expand Up @@ -62,5 +62,5 @@ public interface TranslationStateCache
* @param validationId
* @return
*/
Boolean textFlowTargetHasError(Long textFlowTargetId, ValidationId validationId);
Boolean textFlowTargetHasWarningOrError(Long textFlowTargetId, ValidationId validationId);
}
Expand Up @@ -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;

Expand Down Expand Up @@ -61,7 +62,7 @@ public interface ValidationService
* @param maxSize
* @throws IOException
*/
List<HTextFlow> filterHasErrorTextFlow(List<HTextFlow> textFlows, List<ValidationId> validationIds,
List<HTextFlow> filterHasWarningOrErrorTextFlow(List<HTextFlow> textFlows, List<ValidationId> validationIds,
LocaleId localeId, int startIndex, int maxSize);

/**
Expand All @@ -75,4 +76,14 @@ List<HTextFlow> filterHasErrorTextFlow(List<HTextFlow> textFlows, List<Validatio
* @param localeId
*/
boolean runDocValidationsWithServerRules(HDocument hDoc, LocaleId localeId);

/**
* Run "Error" state validations check on update request
* @param versionSlug
* @param projectSlug
* @param localeId
* @param updateRequests
* @return hasError
*/
boolean updateRequestHasError(String projectSlug, String versionSlug, LocaleId localeId, List<TransUnitUpdateRequest> updateRequests);
}
Expand Up @@ -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<ValidationId, Boolean> cacheEntry = targetValidationCache.getWithLoader(targetId);
if (!cacheEntry.containsKey(validationId))
Expand Down
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -82,7 +84,6 @@ private ValidationFactory getValidationFactory()
@Override
public Collection<ValidationAction> getValidationAction(String projectSlug)
{
Collection<ValidationAction> allValidations = getValidationFactory().getAllValidationActions().values();
Map<String, String> customizedValidations = Maps.newHashMap();

if (!StringUtils.isEmpty(projectSlug))
Expand All @@ -91,25 +92,15 @@ public Collection<ValidationAction> 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<ValidationAction> getValidationAction(String projectSlug, String versionSlug)
{
Collection<ValidationAction> allValidations = getValidationFactory().getAllValidationActions().values();
Map<String, String> customizedValidations = Maps.newHashMap();

if (!StringUtils.isEmpty(projectSlug))
if (!StringUtils.isEmpty(projectSlug) && !StringUtils.isEmpty(versionSlug))
{
HProjectIteration version = projectIterationDAO.getBySlug(projectSlug, versionSlug);

Expand All @@ -120,10 +111,17 @@ public Collection<ValidationAction> getValidationAction(String projectSlug, Stri
*/
if (customizedValidations.isEmpty())
{
customizedValidations = version.getProject().getCustomizedValidations();
return getValidationAction(projectSlug);
}
}

return mergeCustomisedStateToAllValidations(customizedValidations);
}

private Collection<ValidationAction> mergeCustomisedStateToAllValidations(Map<String, String> customizedValidations)
{
Collection<ValidationAction> allValidations = getValidationFactory().getAllValidationActions().values();

for (ValidationAction valAction : allValidations)
{
String name = valAction.getId().name();
Expand All @@ -136,33 +134,41 @@ public Collection<ValidationAction> getValidationAction(String projectSlug, Stri
return allValidations;
}

private List<ValidationId> getWarnOrErrorValidationIds(HProjectIteration version)
/**
* Get validation id of the HProjectIteration with includeStates. Leave includeStates empty to get all states
* @param version
* @return
*/
private List<ValidationId> getValidationIds(HProjectIteration version, State... includeStates)
{
Collection<ValidationAction> allValidations = getValidationFactory().getAllValidationActions().values();
Map<String, String> customizedValidations = Maps.newHashMap();
List<State> includeStateList = Arrays.asList(includeStates);

List<ValidationId> warnOrErrorValidationIds = new ArrayList<ValidationId>();
List<ValidationId> filteredValidationIds = new ArrayList<ValidationId>();

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<ValidationAction> 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;
}

/**
Expand All @@ -189,7 +195,7 @@ public boolean runDocValidations(Long hDocId, List<ValidationId> validationIds,
else
{
HDocument hDoc = documentDAO.findById(hDocId, false);
result = documentHasError(hDoc, validationIds, localeId);
result = documentHasWarningOrError(hDoc, validationIds, localeId);
}

log.debug("Finished runDocValidations in " + stopwatch);
Expand All @@ -202,19 +208,19 @@ public boolean runDocValidationsWithServerRules(HDocument hDoc, LocaleId localeI
log.debug("Start runDocValidationsWithServerRules {0}", hDoc.getId());
Stopwatch stopwatch = new Stopwatch().start();

List<ValidationId> validationIds = getWarnOrErrorValidationIds(hDoc.getProjectIteration());
List<ValidationId> 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<ValidationId> validationIds, LocaleId localeId)
private boolean documentHasWarningOrError(HDocument hDoc, List<ValidationId> 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
Expand All @@ -225,7 +231,7 @@ private boolean documentHasError(HDocument hDoc, List<ValidationId> validationId
}

@Override
public List<HTextFlow> filterHasErrorTextFlow(List<HTextFlow> textFlows, List<ValidationId> validationIds,
public List<HTextFlow> filterHasWarningOrErrorTextFlow(List<HTextFlow> textFlows, List<ValidationId> validationIds,
LocaleId localeId, int startIndex, int maxSize)
{
log.debug("Start filter {0} textFlows", textFlows.size());
Expand All @@ -235,8 +241,8 @@ public List<HTextFlow> filterHasErrorTextFlow(List<HTextFlow> textFlows, List<Va

for (HTextFlow textFlow : textFlows)
{
boolean hasError = textFlowTargetHasError(textFlow.getId(), validationIds, localeId);
if (hasError)
boolean hasWarningOrError = textFlowTargetHasWarningOrError(textFlow.getId(), validationIds, localeId);
if (hasWarningOrError)
{
result.add(textFlow);
}
Expand All @@ -257,14 +263,14 @@ public List<HTextFlow> filterHasErrorTextFlow(List<HTextFlow> textFlows, List<Va
return result.subList(startIndex, toIndex);
}

private boolean textFlowTargetHasError(Long textFlowId, List<ValidationId> validationIds, LocaleId localeId)
private boolean textFlowTargetHasWarningOrError(Long textFlowId, List<ValidationId> 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();
Expand All @@ -273,4 +279,23 @@ private boolean textFlowTargetHasError(Long textFlowId, List<ValidationId> valid
}
return false;
}

@Override
public boolean updateRequestHasError(String projectSlug, String versionSlug, LocaleId localeId,
List<TransUnitUpdateRequest> updateRequests)
{
HProjectIteration version = projectIterationDAO.getBySlug(projectSlug, versionSlug);
List<ValidationId> validationIds = getValidationIds(version, State.Error);

for (TransUnitUpdateRequest updateRequest : updateRequests)
{
if (textFlowTargetHasWarningOrError(updateRequest.getTransUnitId().getId(), validationIds, localeId))
{
return true;
}
}

return false;
}

}
Expand Up @@ -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();
}
Expand Up @@ -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);
Expand Down
Expand Up @@ -3,17 +3,19 @@
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:z='urn:import:org.zanata.webtrans.client.ui'>

<ui:with field="messages" type="org.zanata.webtrans.client.resources.TableEditorMessages" />

<g:HTMLPanel styleName="new-zanata" width="800px">
<ul class="list--no-bullets">
<li class="l--pad-v-half">
<g:Label ui:field="messageLabel" styleName="epsilon"/>
</li>
<li class="l--pad-v-half">
<h5>Translations</h5>
<h5><ui:text from="{messages.translation}"/></h5>
<z:UnorderedListWidget ui:field="translations" styleName="list--no-bullets"/>
</li>
<li class="l--pad-v-half">
<h5>Error message</h5>
<h5><ui:text from="{messages.errorMessage}"/></h5>
<z:UnorderedListWidget ui:field="errorList" styleName="list--no-bullets l--pad-h-half"/>
</li>
<li class="l--pad-all-half">
Expand Down
Expand Up @@ -137,7 +137,7 @@ private List<HTextFlow> 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
Expand All @@ -159,7 +159,7 @@ private List<HTextFlow> 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;
Expand Down

0 comments on commit 150a92a

Please sign in to comment.