diff --git a/server/services/src/main/java/org/zanata/rest/editor/dto/ReviewData.java b/server/services/src/main/java/org/zanata/rest/editor/dto/ReviewData.java
index 272f5b8c074..6bc765a03dd 100644
--- a/server/services/src/main/java/org/zanata/rest/editor/dto/ReviewData.java
+++ b/server/services/src/main/java/org/zanata/rest/editor/dto/ReviewData.java
@@ -73,4 +73,34 @@ public void setStatus(ContentState status) {
this.status = status;
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ReviewData that = (ReviewData) o;
+
+ if (transUnitId != null ? !transUnitId.equals(that.transUnitId) :
+ that.transUnitId != null) return false;
+ if (revision != null ? !revision.equals(that.revision) :
+ that.revision != null) return false;
+ if (comment != null ? !comment.equals(that.comment) :
+ that.comment != null)
+ return false;
+ if (reviewCriteriaId != null ?
+ !reviewCriteriaId.equals(that.reviewCriteriaId) :
+ that.reviewCriteriaId != null) return false;
+ return status == that.status;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = transUnitId != null ? transUnitId.hashCode() : 0;
+ result = 31 * result + (revision != null ? revision.hashCode() : 0);
+ result = 31 * result + (comment != null ? comment.hashCode() : 0);
+ result = 31 * result +
+ (reviewCriteriaId != null ? reviewCriteriaId.hashCode() : 0);
+ result = 31 * result + (status != null ? status.hashCode() : 0);
+ return result;
+ }
}
diff --git a/server/services/src/main/java/org/zanata/rest/editor/service/TranslationReviewService.java b/server/services/src/main/java/org/zanata/rest/editor/service/TranslationReviewService.java
index cd03907115c..1875c54752b 100644
--- a/server/services/src/main/java/org/zanata/rest/editor/service/TranslationReviewService.java
+++ b/server/services/src/main/java/org/zanata/rest/editor/service/TranslationReviewService.java
@@ -1,8 +1,6 @@
package org.zanata.rest.editor.service;
import com.google.common.collect.Lists;
-import net.customware.gwt.dispatch.shared.ActionException;
-import org.omg.PortableInterceptor.ACTIVE;
import org.zanata.common.EntityStatus;
import org.zanata.common.LocaleId;
import org.zanata.dao.ReviewCriteriaDAO;
@@ -24,10 +22,9 @@
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
+import javax.validation.constraints.NotNull;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
-import java.util.List;
-
@Path(TranslationReviewResource.SERVICE_PATH)
@RequestScoped
@@ -35,22 +32,38 @@ public class TranslationReviewService implements TranslationReviewResource {
private static final org.slf4j.Logger log =
org.slf4j.LoggerFactory.getLogger(TranslationReviewService.class);
- @Inject
private TextFlowTargetDAO textFlowTargetDAO;
- @Inject
private LocaleService localeServiceImpl;
- @Inject
private ZanataIdentity identity;
- @Inject
private ReviewCriteriaDAO reviewCriteriaDAO;
- @Inject
- @Authenticated
private HAccount authenticatedAccount;
- @Inject
private TextFlowTargetReviewCommentsDAO textFlowTargetReviewCommentsDAO;
+ @Inject
+ public TranslationReviewService(
+ TextFlowTargetDAO textFlowTargetDAO,
+ LocaleService localeServiceImpl,
+ ZanataIdentity identity,
+ ReviewCriteriaDAO reviewCriteriaDAO,
+ TextFlowTargetReviewCommentsDAO textFlowTargetReviewCommentsDAO,
+ @Authenticated HAccount authenticatedAccount) {
+
+ this.textFlowTargetDAO = textFlowTargetDAO;
+ this.localeServiceImpl = localeServiceImpl;
+ this.identity =identity;
+ this.reviewCriteriaDAO = reviewCriteriaDAO;
+ this.textFlowTargetReviewCommentsDAO = textFlowTargetReviewCommentsDAO;
+ this.authenticatedAccount = authenticatedAccount;
+ }
+
@Override
- public Response put(String localeId, ReviewData data) {
+ public Response put(String localeId, @NotNull ReviewData data) {
+ if (data == null) {
+ return Response.status(
+ Response.Status.BAD_REQUEST)
+ .entity(Lists.newArrayList("data is invalid"))
+ .build();
+ }
HLocale locale =
localeServiceImpl.getByLocaleId(localeId);
if (locale == null) {
diff --git a/server/services/src/main/java/org/zanata/rest/editor/service/resource/TranslationReviewResource.java b/server/services/src/main/java/org/zanata/rest/editor/service/resource/TranslationReviewResource.java
index db003dd2113..f19aeba6db3 100644
--- a/server/services/src/main/java/org/zanata/rest/editor/service/resource/TranslationReviewResource.java
+++ b/server/services/src/main/java/org/zanata/rest/editor/service/resource/TranslationReviewResource.java
@@ -2,6 +2,7 @@
import org.zanata.rest.editor.dto.ReviewData;
+import javax.validation.constraints.NotNull;
import javax.ws.rs.Consumes;
import javax.ws.rs.PUT;
import javax.ws.rs.PathParam;
@@ -39,5 +40,5 @@ public interface TranslationReviewResource {
@Consumes({ MediaType.APPLICATION_JSON,
MediaType.APPLICATION_JSON })
Response put(@PathParam("localeId") String localeId,
- ReviewData data);
+ @NotNull ReviewData data);
}
diff --git a/server/services/src/test/java/org/zanata/rest/editor/dto/ReviewDataTest.java b/server/services/src/test/java/org/zanata/rest/editor/dto/ReviewDataTest.java
new file mode 100644
index 00000000000..7a0d6e349b8
--- /dev/null
+++ b/server/services/src/test/java/org/zanata/rest/editor/dto/ReviewDataTest.java
@@ -0,0 +1,67 @@
+package org.zanata.rest.editor.dto;
+
+import org.junit.Test;
+import org.zanata.common.ContentState;
+
+import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
+
+/**
+ * @author Alex Eng aeng@redhat.com
+ **/
+public class ReviewDataTest {
+
+ @Test
+ public void transUnitIdTest() {
+ Long id = 10L;
+ ReviewData data = new ReviewData();
+ data.setTransUnitId(id);
+ assertThat(data.getTransUnitId()).isEqualTo(id);
+ }
+
+ @Test
+ public void revisionTest() {
+ int revision = 10;
+ ReviewData data = new ReviewData();
+ data.setRevision(revision);
+ assertThat(data.getRevision()).isEqualTo(revision);
+ }
+
+ @Test
+ public void commentTest() {
+ String comment = "comment";
+ ReviewData data = new ReviewData();
+ data.setComment(comment);
+ assertThat(data.getComment()).isEqualTo(comment);
+ }
+
+ @Test
+ public void criteriaIdTest() {
+ Long id = 10L;
+ ReviewData data = new ReviewData();
+ data.setReviewCriteriaId(id);
+ assertThat(data.getReviewCriteriaId()).isEqualTo(id);
+ }
+
+ @Test
+ public void statusTest() {
+ ContentState status = ContentState.Approved;
+ ReviewData data = new ReviewData();
+ data.setStatus(status);
+ assertThat(data.getStatus()).isEqualTo(status);
+ }
+
+ @Test
+ public void equalTest() {
+ ContentState status = ContentState.Approved;
+ ReviewData data = new ReviewData();
+ data.setStatus(status);
+ data.setReviewCriteriaId(1L);
+
+ ReviewData data2 = new ReviewData();
+ data2.setStatus(status);
+ data2.setReviewCriteriaId(1L);
+
+ assertThat(data).isEqualTo(data2);
+ assertThat(data.hashCode()).isEqualTo(data2.hashCode());
+ }
+}
diff --git a/server/services/src/test/java/org/zanata/rest/editor/service/TranslationReviewServiceTest.java b/server/services/src/test/java/org/zanata/rest/editor/service/TranslationReviewServiceTest.java
new file mode 100644
index 00000000000..df1c403871a
--- /dev/null
+++ b/server/services/src/test/java/org/zanata/rest/editor/service/TranslationReviewServiceTest.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2018, Red Hat, Inc. and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.zanata.rest.editor.service;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.zanata.common.ContentState;
+import org.zanata.common.ContentType;
+import org.zanata.common.EntityStatus;
+import org.zanata.common.IssuePriority;
+import org.zanata.common.LocaleId;
+import org.zanata.dao.ReviewCriteriaDAO;
+import org.zanata.dao.TextFlowTargetDAO;
+import org.zanata.dao.TextFlowTargetReviewCommentsDAO;
+import org.zanata.model.HAccount;
+import org.zanata.model.HDocument;
+import org.zanata.model.HLocale;
+import org.zanata.model.HPerson;
+import org.zanata.model.HProject;
+import org.zanata.model.HProjectIteration;
+import org.zanata.model.HTextFlow;
+import org.zanata.model.HTextFlowTarget;
+import org.zanata.model.ReviewCriteria;
+import org.zanata.rest.editor.dto.ReviewData;
+import org.zanata.security.ZanataIdentity;
+import org.zanata.service.LocaleService;
+
+import javax.ws.rs.core.Response;
+
+import static org.assertj.core.api.Java6Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * @author Alex Eng aeng@redhat.com
+ **/
+public class TranslationReviewServiceTest {
+ private TranslationReviewService service;
+
+ @Mock
+ private TextFlowTargetDAO textFlowTargetDAO;
+
+ @Mock
+ private LocaleService localeServiceImpl;
+
+ @Mock
+ private ZanataIdentity identity;
+
+ @Mock
+ private ReviewCriteriaDAO reviewCriteriaDAO;
+
+ @Mock
+ private TextFlowTargetReviewCommentsDAO textFlowTargetReviewCommentsDAO;
+
+ @Mock
+ private HAccount authenticatedAccount;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ service = new TranslationReviewService(
+ textFlowTargetDAO,
+ localeServiceImpl,
+ identity,
+ reviewCriteriaDAO,
+ textFlowTargetReviewCommentsDAO,
+ authenticatedAccount);
+ }
+
+ @Test
+ public void testNullData() {
+ Response response = service.put(null, null);
+ assertThat(response.getStatus())
+ .isEqualTo(Response.Status.BAD_REQUEST.getStatusCode());
+ }
+
+ @Test
+ public void testNullLocale() {
+ String locale = "de";
+ ReviewData data = new ReviewData();
+ when(localeServiceImpl.getByLocaleId(locale)).thenReturn(null);
+
+ Response response = service.put(locale, data);
+ assertThat(response.getStatus())
+ .isEqualTo(Response.Status.BAD_REQUEST.getStatusCode());
+ }
+
+ @Test
+ public void testNullTft() {
+ String locale = "de";
+ LocaleId localeId = new LocaleId(locale);
+ HLocale hLocale = new HLocale(localeId);
+ ReviewData data = new ReviewData();
+ data.setTransUnitId(1L);
+
+ when(localeServiceImpl.getByLocaleId(locale)).thenReturn(hLocale);
+ when(textFlowTargetDAO
+ .getTextFlowTarget(data.getTransUnitId(), localeId))
+ .thenReturn(null);
+
+ Response response = service.put(locale, data);
+ assertThat(response.getStatus())
+ .isEqualTo(Response.Status.BAD_REQUEST.getStatusCode());
+ }
+
+ @Test
+ public void testNullTftUntranslated() {
+ String locale = "de";
+ ReviewData data = new ReviewData();
+ data.setTransUnitId(1L);
+
+ HTextFlowTarget tft =
+ buildTft(locale, EntityStatus.ACTIVE, ContentState.New);
+ HLocale hLocale = tft.getLocale();
+
+ when(localeServiceImpl.getByLocaleId(locale)).thenReturn(hLocale);
+ when(textFlowTargetDAO.getTextFlowTarget(data.getTransUnitId(),
+ hLocale.getLocaleId())).thenReturn(tft);
+
+ Response response = service.put(locale, data);
+ assertThat(response.getStatus())
+ .isEqualTo(Response.Status.BAD_REQUEST.getStatusCode());
+ }
+
+ @Test
+ public void testNonActiveProjectVersion() {
+ String locale = "de";
+ ReviewData data = new ReviewData();
+ data.setTransUnitId(1L);
+
+ HTextFlowTarget tft = buildTft(locale, EntityStatus.READONLY,
+ ContentState.Translated);
+ HLocale hLocale = tft.getLocale();
+
+ when(localeServiceImpl.getByLocaleId(locale)).thenReturn(hLocale);
+ when(textFlowTargetDAO.getTextFlowTarget(data.getTransUnitId(),
+ hLocale.getLocaleId())).thenReturn(tft);
+
+ Response response = service.put(locale, data);
+ assertThat(response.getStatus())
+ .isEqualTo(Response.Status.FORBIDDEN.getStatusCode());
+ }
+
+ @Test
+ public void testReviewCriteriaNull() {
+ String locale = "de";
+ ReviewData data = new ReviewData();
+ data.setTransUnitId(1L);
+ data.setReviewCriteriaId(1L);
+
+ HTextFlowTarget tft = buildTft(locale, EntityStatus.ACTIVE,
+ ContentState.Translated);
+ HLocale hLocale = tft.getLocale();
+
+ when(localeServiceImpl.getByLocaleId(locale)).thenReturn(hLocale);
+ when(textFlowTargetDAO.getTextFlowTarget(data.getTransUnitId(),
+ hLocale.getLocaleId())).thenReturn(tft);
+ when(reviewCriteriaDAO.findById(data.getReviewCriteriaId())).thenReturn(null);
+
+ Response response = service.put(locale, data);
+ assertThat(response.getStatus())
+ .isEqualTo(Response.Status.BAD_REQUEST.getStatusCode());
+ }
+
+ @Test
+ public void testPut() {
+ String locale = "de";
+ ReviewData data = new ReviewData();
+ data.setTransUnitId(1L);
+ data.setReviewCriteriaId(1L);
+
+ HTextFlowTarget tft = buildTft(locale, EntityStatus.ACTIVE,
+ ContentState.Translated);
+ HLocale hLocale = tft.getLocale();
+
+ ReviewCriteria reviewCriteria = new ReviewCriteria(IssuePriority.Major,
+ true, "description");
+
+ HPerson person = new HPerson();
+ person.setName("name");
+
+ when(authenticatedAccount.getPerson()).thenReturn(person);
+ when(localeServiceImpl.getByLocaleId(locale)).thenReturn(hLocale);
+ when(textFlowTargetDAO.getTextFlowTarget(data.getTransUnitId(),
+ hLocale.getLocaleId())).thenReturn(tft);
+ when(reviewCriteriaDAO.findById(data.getReviewCriteriaId()))
+ .thenReturn(reviewCriteria);
+
+ Response response = service.put(locale, data);
+
+ verify(textFlowTargetReviewCommentsDAO).makePersistent(any());
+ verify(textFlowTargetReviewCommentsDAO).flush();
+
+ assertThat(response.getStatus())
+ .isEqualTo(Response.Status.OK.getStatusCode());
+ assertThat(response.getEntity()).isNotNull();
+ assertThat((ReviewData)response.getEntity()).isEqualTo(data);
+ }
+
+ private HTextFlowTarget buildTft(String localeId, EntityStatus status,
+ ContentState contentState) {
+ HProject project = new HProject();
+ project.setStatus(status);
+
+ HProjectIteration version = new HProjectIteration();
+ version.setStatus(status);
+ version.setProject(project);
+
+ HDocument doc =
+ new HDocument("", ContentType.PO, new HLocale(LocaleId.EN_US));
+ doc.setProjectIteration(version);
+ HLocale hLocale = new HLocale(new LocaleId(localeId));
+ HTextFlow tf = new HTextFlow(doc, "resId", "content");
+
+ HTextFlowTarget tft = new HTextFlowTarget(tf, hLocale);
+ tft.setState(contentState);
+ return tft;
+ }
+}