From 716af8eb6a51ae6df74350c70256fb3932aec770 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Thu, 1 Jun 2017 10:20:30 +1000 Subject: [PATCH 001/116] ZNTA-1865 - can merge translation from TM --- .../shared/model/TransMemoryQuery.java | 9 +- .../shared/model/TransMemoryResultItem.java | 9 +- .../shared/rest/dto/HasTMMergeCriteria.java | 39 ++++++ .../rest/dto/TransMemoryMergeRequest.java | 20 ++- .../action/MergeTranslationsManager.java | 59 ++++++++- .../handle/MergeTranslationsTaskHandle.java | 6 +- .../main/java/org/zanata/dao/TextFlowDAO.java | 35 +++++ .../rest/service/ProjectVersionService.java | 100 ++++++++++++-- .../org/zanata/service/LocaleService.java | 8 ++ .../service/MergeTranslationsService.java | 8 ++ .../service/TransMemoryMergeService.java | 10 ++ .../service/TranslationMemoryService.java | 4 +- .../service/impl/LocaleServiceImpl.java | 20 +++ .../impl/MergeTranslationsServiceImpl.java | 122 ++++++++++++++++-- .../impl/TransMemoryMergeServiceImpl.java | 57 +++++++- .../impl/TranslationMemoryServiceImpl.java | 116 +++++++++++++---- .../util/TransMemoryMergeStatusResolver.java | 14 +- .../rest/service/ProjectVersionTest.java | 3 + .../MergeTranslationsServiceImplTest.java | 4 + .../impl/TransMemoryMergeServiceImplTest.java | 33 +++-- .../TranslationMemoryServiceImplTest.java | 3 +- .../TransMemoryMergeStatusResolverTest.java | 4 +- .../presenter/TransMemoryPresenterTest.java | 7 +- 23 files changed, 602 insertions(+), 88 deletions(-) create mode 100644 server/gwt-editor/src/main/java/org/zanata/webtrans/shared/rest/dto/HasTMMergeCriteria.java diff --git a/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/model/TransMemoryQuery.java b/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/model/TransMemoryQuery.java index 87a0281741..2acad9ac03 100644 --- a/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/model/TransMemoryQuery.java +++ b/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/model/TransMemoryQuery.java @@ -41,6 +41,7 @@ public class TransMemoryQuery implements IsSerializable, Serializable { private Condition project; private Condition document; private Condition res; + private List fromVersionIds; private Condition includeOwnTranslation = new Condition(true, null); @SuppressWarnings("unused") @@ -67,11 +68,13 @@ public TransMemoryQuery(List queries, SearchType searchType) { } public TransMemoryQuery(List queries, SearchType searchType, - Condition project, Condition document, Condition res) { + Condition project, Condition document, Condition res, + List fromVersionIds) { this(queries, searchType); this.project = project; this.document = document; this.res = res; + this.fromVersionIds = fromVersionIds; } public TransMemoryQuery(String query, SearchType searchType, @@ -110,6 +113,10 @@ public SearchType getSearchType() { return searchType; } + public List getFromVersionIds() { + return fromVersionIds; + } + @Override public String toString() { return "TransMemoryQuery{" + "searchType=" + searchType + ", queries=" diff --git a/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/model/TransMemoryResultItem.java b/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/model/TransMemoryResultItem.java index 8876facc41..b62cef488c 100644 --- a/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/model/TransMemoryResultItem.java +++ b/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/model/TransMemoryResultItem.java @@ -54,6 +54,7 @@ public enum MatchType { // The optional origin identifiers for this result (i.e. A Trans memory name) private List origins; private ArrayList sourceIdList = new ArrayList(); + private Long fromVersionId; // for GWT @SuppressWarnings("unused") @@ -65,14 +66,17 @@ private TransMemoryResultItem() { * @param targetContents * @param relevanceScore * @param similarityPercent + * @param fromVersionId */ public TransMemoryResultItem(ArrayList sourceContents, ArrayList targetContents, MatchType matchType, - double relevanceScore, double similarityPercent) { + double relevanceScore, double similarityPercent, + Long fromVersionId) { super(relevanceScore, similarityPercent); this.sourceContents = sourceContents; this.targetContents = targetContents; this.matchType = matchType; + this.fromVersionId = fromVersionId; this.origins = new ArrayList(); } @@ -134,4 +138,7 @@ public void addSourceId(Long sourceId) { this.sourceIdList.add(sourceId); } + public Long getFromVersionId() { + return fromVersionId; + } } diff --git a/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/rest/dto/HasTMMergeCriteria.java b/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/rest/dto/HasTMMergeCriteria.java new file mode 100644 index 0000000000..5ba6520d6b --- /dev/null +++ b/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/rest/dto/HasTMMergeCriteria.java @@ -0,0 +1,39 @@ +/* + * Copyright 2017, 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.webtrans.shared.rest.dto; + +import java.util.List; + +import org.zanata.webtrans.shared.model.ProjectIterationId; +import org.zanata.webtrans.shared.rpc.MergeRule; + +public interface HasTMMergeCriteria { + int getThresholdPercent(); + + MergeRule getDifferentProjectRule(); + + MergeRule getDifferentDocumentRule(); + + MergeRule getDifferentContextRule(); + + MergeRule getImportedMatchRule(); + +} diff --git a/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/rest/dto/TransMemoryMergeRequest.java b/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/rest/dto/TransMemoryMergeRequest.java index 20e26ef448..a1955445c3 100644 --- a/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/rest/dto/TransMemoryMergeRequest.java +++ b/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/rest/dto/TransMemoryMergeRequest.java @@ -20,6 +20,9 @@ */ package org.zanata.webtrans.shared.rest.dto; +import java.util.Collections; +import java.util.List; + import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.zanata.common.LocaleId; import org.zanata.webtrans.shared.auth.EditorClientId; @@ -30,7 +33,7 @@ /** * @author Patrick Huang pahuang@redhat.com */ -public class TransMemoryMergeRequest { +public class TransMemoryMergeRequest implements HasTMMergeCriteria { @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD", justification = "For future implement") public EditorClientId editorClientId; @@ -48,6 +51,7 @@ public class TransMemoryMergeRequest { public MergeRule differentDocumentRule; public MergeRule differentContextRule; public MergeRule importedMatchRule; + private List fromProjectVersions; public TransMemoryMergeRequest( EditorClientId editorClientId, @@ -71,23 +75,37 @@ public TransMemoryMergeRequest( public TransMemoryMergeRequest() { } + @Override public int getThresholdPercent() { return thresholdPercent; } + @Override public MergeRule getDifferentProjectRule() { return differentProjectRule; } + @Override public MergeRule getDifferentDocumentRule() { return differentDocumentRule; } + @Override public MergeRule getDifferentContextRule() { return differentContextRule; } + @Override public MergeRule getImportedMatchRule() { return importedMatchRule; } + + public void setFromProjectVersions( + List fromProjectVersions) { + this.fromProjectVersions = fromProjectVersions; + } + + public List getFromProjectVersions() { + return fromProjectVersions; + } } diff --git a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java index 24d763ffd7..3c1b31d32d 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java @@ -1,14 +1,23 @@ package org.zanata.action; import java.io.Serializable; +import java.util.List; +import java.util.Objects; + import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import javax.enterprise.context.Dependent; import javax.inject.Inject; -import javax.inject.Named; + +import org.zanata.async.AsyncTaskHandle; import org.zanata.async.AsyncTaskHandleManager; import org.zanata.async.handle.MergeTranslationsTaskHandle; +import org.zanata.common.LocaleId; +import org.zanata.model.HLocale; +import org.zanata.model.HProjectIteration; import org.zanata.security.ZanataIdentity; import org.zanata.service.MergeTranslationsService; +import org.zanata.webtrans.shared.model.ProjectIterationId; +import org.zanata.webtrans.shared.rest.dto.TransMemoryMergeRequest; /** * Manages tasks to copy translations from one existing version to another. @@ -88,6 +97,26 @@ public boolean isRunning(String projectSlug, String versionSlug) { return handle != null && !handle.isDone(); } + public boolean start(HProjectIteration version, HLocale hLocale, + TransMemoryMergeRequest mergeRequest) { + MergeTranslationTaskKey key = + new MergeTranslationTaskKey(version.getId(), + hLocale.getLocaleId()); + AsyncTaskHandle handleByKey = + asyncTaskHandleManager.getHandleByKey(key); + if (handleByKey == null || handleByKey.isCancelled() + || handleByKey.isDone()) { + MergeTranslationsTaskHandle handle = new MergeTranslationsTaskHandle(); + + handle.setTriggeredBy(identity.getAccountUsername()); + asyncTaskHandleManager.registerTaskHandle(handle, key); + mergeTranslationsServiceImpl.startMergeTranslations(version, hLocale, + mergeRequest, handle); + return true; + } + return false; + } + /** * Key used for copy version task */ @@ -148,4 +177,32 @@ public Key(final String projectSlug, final String versionSlug) { this.versionSlug = versionSlug; } } + + + static class MergeTranslationTaskKey implements Serializable { + + private static final long serialVersionUID = 5671982177725183233L; + private final Long versionId; + private final LocaleId localeId; + + public MergeTranslationTaskKey(Long versionId, LocaleId localeId) { + this.versionId = versionId; + this.localeId = localeId; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MergeTranslationTaskKey that = (MergeTranslationTaskKey) o; + return Objects.equals(versionId, that.versionId) && + Objects.equals(localeId, that.localeId); + } + + @Override + public int hashCode() { + return Objects + .hash(versionId, localeId); + } + } } diff --git a/server/zanata-war/src/main/java/org/zanata/async/handle/MergeTranslationsTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/handle/MergeTranslationsTaskHandle.java index ec8274470c..566db11d82 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/handle/MergeTranslationsTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/handle/MergeTranslationsTaskHandle.java @@ -29,16 +29,16 @@ */ public class MergeTranslationsTaskHandle extends AsyncTaskHandle { - private int totalTranslations; + private long totalTranslations; private String cancelledBy; private long cancelledTime; private String triggeredBy; - public int getTotalTranslations() { + public long getTotalTranslations() { return this.totalTranslations; } - public void setTotalTranslations(final int totalTranslations) { + public void setTotalTranslations(final long totalTranslations) { this.totalTranslations = totalTranslations; } diff --git a/server/zanata-war/src/main/java/org/zanata/dao/TextFlowDAO.java b/server/zanata-war/src/main/java/org/zanata/dao/TextFlowDAO.java index a09ab117fa..e262e1ddbd 100644 --- a/server/zanata-war/src/main/java/org/zanata/dao/TextFlowDAO.java +++ b/server/zanata-war/src/main/java/org/zanata/dao/TextFlowDAO.java @@ -310,6 +310,41 @@ public int getSourceByMatchedContextCount(Long sourceVersionId, return count == null ? 0 : count.intValue(); } + public long getUntranslatedOrFuzzyTextFlowCountInVersion(Long targetVersionId, HLocale targetLocale) { + String queryString = + "select count(*) from HTextFlow tf left join " + + "tf.targets tfts WITH index(tfts) =:locale" + + " WHERE (tf.obsolete=0 AND tf.document.projectIteration.id=:targetVersionId ) AND" + + " ( EXISTS ( FROM HTextFlowTarget WHERE ((textFlow=tf AND locale.id=:locale) AND state = :untranslatedState)) OR (:locale not in indices(tf.targets) ))"; + Query query = getSession().createQuery(queryString) + .setParameter("locale", targetLocale.getId()) + .setParameter("targetVersionId", targetVersionId) + .setParameter("untranslatedState", ContentState.New) + .setCacheable(true) + .setComment("TextFlowDAO.getUntranslatedOrFuzzyTextFlowCountInVersion"); + Long count = (Long) query.uniqueResult(); + return count == null ? 0 : count; + } + + public List getUntranslatedOrFuzzyTextFlowsInVersion( + Long targetVersionId, + HLocale targetLocale, int startIndex, int maxCount) { + String queryString = + "select distinct tf from HTextFlow tf left join " + + "tf.targets tfts WITH index(tfts) =:locale" + + " WHERE (tf.obsolete=0 AND tf.document.projectIteration.id=:targetVersionId ) AND" + + " ( EXISTS ( FROM HTextFlowTarget WHERE ((textFlow=tf AND locale.id=:locale) AND state = :untranslatedState)) OR (:locale not in indices(tf.targets) ))"; + + Query query = getSession().createQuery(queryString) + .setParameter("locale", targetLocale.getId()) + .setParameter("targetVersionId", targetVersionId) + .setParameter("untranslatedState", ContentState.New) + .setFirstResult(startIndex).setMaxResults(maxCount) + .setCacheable(true) + .setComment("TextFlowDAO.getUntranslatedOrFuzzyTextFlowsInVersion"); + return query.list(); + } + /** * Generate query string for text flows that have matching document id and * content between the given source and target version diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java index 493440991f..fea33f139f 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java @@ -6,12 +6,15 @@ import static org.zanata.webtrans.server.rpc.GetTransUnitsNavigationService.TextFlowResultTransformer; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import javax.inject.Inject; import javax.inject.Named; import javax.ws.rs.DefaultValue; +import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.EntityTag; import javax.ws.rs.core.GenericEntity; @@ -22,8 +25,10 @@ import org.apache.commons.lang.StringUtils; import org.apache.deltaspike.jpa.api.transaction.Transactional; import org.zanata.ApplicationConfiguration; +import org.zanata.action.MergeTranslationsManager; import org.zanata.common.ContentState; import org.zanata.common.EntityStatus; +import org.zanata.common.LocaleId; import org.zanata.common.ProjectType; import org.zanata.dao.DocumentDAO; import org.zanata.dao.ProjectDAO; @@ -42,7 +47,11 @@ import org.zanata.rest.dto.TransUnitStatus; import org.zanata.rest.dto.User; import org.zanata.rest.dto.resource.ResourceMeta; +import org.zanata.rest.editor.service.TransMemoryMergeManager; import org.zanata.rest.editor.service.UserService; +import org.zanata.webtrans.shared.model.ProjectIterationId; +import org.zanata.webtrans.shared.rest.dto.TransMemoryMergeRequest; +import org.zanata.webtrans.shared.rpc.MergeRule; import org.zanata.webtrans.shared.search.FilterConstraints; import org.zanata.security.ZanataIdentity; import org.zanata.service.ConfigurationService; @@ -86,6 +95,8 @@ public class ProjectVersionService implements ProjectVersionResource { private ApplicationConfiguration applicationConfiguration; @Context private UriInfo uri; + @Inject + private MergeTranslationsManager mergeTranslationsManager; @Override public Response head(@PathParam("projectSlug") String projectSlug, @@ -112,21 +123,13 @@ public Response put(@PathParam("projectSlug") String projectSlug, return projTypeError; } HProject hProject = projectDAO.getBySlug(projectSlug); - if (hProject == null) { - return Response.status(Response.Status.NOT_FOUND) - .entity("Project \'" + projectSlug + "\' not found.") - .build(); - } else if (Objects.equal(hProject.getStatus(), OBSOLETE)) { - // Project is Obsolete - return Response.status(Response.Status.NOT_FOUND) - .entity("Project \'" + projectSlug + "\' not found.") - .build(); - } else if (Objects.equal(hProject.getStatus(), READONLY)) { - // Project is ReadOnly - return Response.status(Response.Status.FORBIDDEN) - .entity("Project \'" + projectSlug + "\' is read-only.") - .build(); + + Optional projectResponse = + getResponseIfProjectIsNotActive(hProject, projectSlug); + if (projectResponse.isPresent()) { + return projectResponse.get(); } + HProjectIteration hProjectVersion = projectIterationDAO.getBySlug(projectSlug, versionSlug); if (hProjectVersion == null) { @@ -179,6 +182,26 @@ public Response put(@PathParam("projectSlug") String projectSlug, return response.tag(etag).build(); } + private Optional getResponseIfProjectIsNotActive( + HProject hProject, String projectSlug) { + if (hProject == null) { + return Optional.of(Response.status(Response.Status.NOT_FOUND) + .entity("Project \'" + projectSlug + "\' not found.") + .build()); + } else if (Objects.equal(hProject.getStatus(), OBSOLETE)) { + // Project is Obsolete + return Optional.of(Response.status(Response.Status.NOT_FOUND) + .entity("Project \'" + projectSlug + "\' not found.") + .build()); + } else if (Objects.equal(hProject.getStatus(), READONLY)) { + // Project is ReadOnly + return Optional.of(Response.status(Response.Status.FORBIDDEN) + .entity("Project \'" + projectSlug + "\' is read-only.") + .build()); + } + return Optional.empty(); + } + @Override public Response sampleConfiguration( @PathParam("projectSlug") String projectSlug, @@ -308,6 +331,55 @@ public Response getTransUnitStatus( return Response.ok(entity).build(); } + @POST + @Path(VERSION_SLUG_TEMPLATE + "/tm-merge") + public Response prefillWithTM(@PathParam("projectSlug") String projectSlug, + @PathParam("versionSlug") String versionSlug, + TransMemoryMergeRequest mergeRequest) { + int percent = mergeRequest.getThresholdPercent(); + if (percent != 80 && percent != 90 && percent != 100) { + return Response.status(Response.Status.BAD_REQUEST) + .entity("{\"error\":\"percentThreshold must be 80, 90 or 100\"}") + .build(); + } + // here we reuse the same DTO but some of the settings are fixed + mergeRequest.differentProjectRule = MergeRule.FUZZY; + + HProject hProject = projectDAO.getBySlug(projectSlug); + + Optional projectResponse = + getResponseIfProjectIsNotActive(hProject, projectSlug); + if (projectResponse.isPresent()) { + return projectResponse.get(); + } + HProjectIteration version = + projectIterationDAO.getBySlug(hProject, versionSlug); + if (version == null || version.getStatus() == OBSOLETE) { + return Response.status(Response.Status.NOT_FOUND) + .entity("Project version \'" + projectSlug + ":" + + versionSlug + "\' not found.") + .build(); + } else if (version.getStatus() == READONLY) { + return Response.status(Response.Status.FORBIDDEN) + .entity("Project version \'" + projectSlug + ":" + + versionSlug + "\' is readonly.") + .build(); + } + LocaleId localeId = mergeRequest.localeId; + HLocale hLocale = localeServiceImpl.getByLocaleId(localeId); + if (hLocale == null) { + return Response.status(Response.Status.NOT_FOUND).build(); + } + + // TODO pahuang check security + boolean started = mergeTranslationsManager + .start(version, hLocale, mergeRequest); + if (!started) { + throw new UnsupportedOperationException("There is already version merge operation in progress"); + } + return Response.accepted().build(); + } + @VisibleForTesting protected HProjectIteration retrieveAndCheckIteration(String projectSlug, String versionSlug, boolean writeOperation) { diff --git a/server/zanata-war/src/main/java/org/zanata/service/LocaleService.java b/server/zanata-war/src/main/java/org/zanata/service/LocaleService.java index d0cb1f9c52..bd0e8595f8 100644 --- a/server/zanata-war/src/main/java/org/zanata/service/LocaleService.java +++ b/server/zanata-war/src/main/java/org/zanata/service/LocaleService.java @@ -33,6 +33,8 @@ import org.zanata.common.LocaleId; import org.zanata.exception.ZanataServiceException; import org.zanata.model.HLocale; +import org.zanata.model.HProject; +import org.zanata.model.HProjectIteration; import org.zanata.model.HLocaleMember; import org.zanata.model.HTextFlowTarget; import org.zanata.rest.dto.LanguageTeamSearchResult; @@ -92,12 +94,18 @@ HLocale validateLocaleByProject(@Nonnull LocaleId locale, // TODO I don't think this method is specifically about source languages HLocale validateSourceLocale(LocaleId locale) throws ZanataServiceException; + List + getSupportedLanguageByProject(@Nonnull HProject project); + List getTranslation(@Nonnull String project, @Nonnull String iterationSlug, String username); List getSupportedLanguageByProjectIteration( @Nonnull String projectSlug, @Nonnull String iterationSlug); + List getSupportedLanguageByProjectIteration( + @Nonnull HProjectIteration version); + List getSupportedLanguageByProject(@Nonnull String project); Map getGlobalLocaleItems(); diff --git a/server/zanata-war/src/main/java/org/zanata/service/MergeTranslationsService.java b/server/zanata-war/src/main/java/org/zanata/service/MergeTranslationsService.java index d91d96f821..d9a2c0d2dc 100644 --- a/server/zanata-war/src/main/java/org/zanata/service/MergeTranslationsService.java +++ b/server/zanata-war/src/main/java/org/zanata/service/MergeTranslationsService.java @@ -21,10 +21,14 @@ package org.zanata.service; import java.io.Serializable; +import java.util.List; import java.util.concurrent.Future; import org.zanata.async.handle.MergeTranslationsTaskHandle; +import org.zanata.model.HLocale; import org.zanata.model.HProjectIteration; +import org.zanata.webtrans.shared.model.ProjectIterationId; +import org.zanata.webtrans.shared.rest.dto.TransMemoryMergeRequest; public interface MergeTranslationsService extends Serializable { //@formatter:off @@ -52,4 +56,8 @@ Future startMergeTranslations(String sourceProjectSlug, */ int getTotalProgressCount(HProjectIteration sourceVersion, HProjectIteration targetVersion); + + Future startMergeTranslations(HProjectIteration version, HLocale hLocale, + TransMemoryMergeRequest mergeRequest, + MergeTranslationsTaskHandle handle); } diff --git a/server/zanata-war/src/main/java/org/zanata/service/TransMemoryMergeService.java b/server/zanata-war/src/main/java/org/zanata/service/TransMemoryMergeService.java index 71741972cd..6cb2bd1f1e 100644 --- a/server/zanata-war/src/main/java/org/zanata/service/TransMemoryMergeService.java +++ b/server/zanata-war/src/main/java/org/zanata/service/TransMemoryMergeService.java @@ -24,7 +24,13 @@ import java.util.List; import java.util.concurrent.Future; +import org.zanata.async.handle.MergeTranslationsTaskHandle; import org.zanata.async.handle.TransMemoryMergeTaskHandle; +import org.zanata.model.HLocale; +import org.zanata.model.HProjectIteration; +import org.zanata.model.HTextFlow; +import org.zanata.webtrans.shared.model.ProjectIterationId; +import org.zanata.webtrans.shared.rest.dto.HasTMMergeCriteria; import org.zanata.webtrans.shared.rest.dto.TransMemoryMergeRequest; public interface TransMemoryMergeService extends Serializable { @@ -35,4 +41,8 @@ List executeMerge( Future> executeMergeAsync(TransMemoryMergeRequest request, TransMemoryMergeTaskHandle asyncTaskHandle); + + void translateInBatch(HasTMMergeCriteria mergeCriteria, + List textFlows, + HLocale targetLocale, List fromProjectVersionIds); } diff --git a/server/zanata-war/src/main/java/org/zanata/service/TranslationMemoryService.java b/server/zanata-war/src/main/java/org/zanata/service/TranslationMemoryService.java index 02f421e2c2..ace0d38e5a 100644 --- a/server/zanata-war/src/main/java/org/zanata/service/TranslationMemoryService.java +++ b/server/zanata-war/src/main/java/org/zanata/service/TranslationMemoryService.java @@ -52,12 +52,14 @@ Optional searchBestMatchTransMemory(HTextFlow textFlow, * @param checkDocument * @param checkProject * @param thresholdPercent + * @param fromVersionIds * @return */ Optional searchBestMatchTransMemory( HTextFlow textFlow, LocaleId targetLocaleId, LocaleId sourceLocaleId, boolean checkContext, - boolean checkDocument, boolean checkProject, int thresholdPercent); + boolean checkDocument, boolean checkProject, int thresholdPercent, + List fromVersionIds); List searchTransMemory(LocaleId targetLocaleId, LocaleId sourceLocaleId, TransMemoryQuery transMemoryQuery); diff --git a/server/zanata-war/src/main/java/org/zanata/service/impl/LocaleServiceImpl.java b/server/zanata-war/src/main/java/org/zanata/service/impl/LocaleServiceImpl.java index c84ff9fd75..853a92e53e 100644 --- a/server/zanata-war/src/main/java/org/zanata/service/impl/LocaleServiceImpl.java +++ b/server/zanata-war/src/main/java/org/zanata/service/impl/LocaleServiceImpl.java @@ -27,6 +27,7 @@ import java.util.Map; import java.util.Set; import java.util.TreeMap; + import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.enterprise.context.ApplicationScoped; @@ -53,6 +54,7 @@ import org.zanata.service.LocaleService; import org.zanata.servlet.annotations.AllJavaLocales; import org.zanata.util.ComparatorUtil; + import com.google.common.collect.Maps; import com.ibm.icu.util.ULocale; @@ -318,6 +320,15 @@ public List getSupportedLanguageByProjectIteration( return getSupportedLanguageByProject(projectSlug); } + @Override + public List getSupportedLanguageByProjectIteration( + @Nonnull HProjectIteration version) { + if (version.isOverrideLocales()) { + return new ArrayList<>(version.getCustomizedLocales()); + } + return getSupportedLanguageByProject(version.getProject()); + } + @Override public List getSupportedLanguageByProject(@Nonnull String projectSlug) { @@ -328,6 +339,15 @@ public List getSupportedLanguageByProjectIteration( return localeDAO.findAllActiveAndEnabledByDefault(); } + @Override + public List + getSupportedLanguageByProject(@Nonnull HProject project) { + if (project.isOverrideLocales()) { + return new ArrayList<>(project.getCustomizedLocales()); + } + return localeDAO.findAllActiveAndEnabledByDefault(); + } + @Override public List getTranslation(@Nonnull String project, @Nonnull String iterationSlug, String username) { diff --git a/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java b/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java index 9d4cbd796a..868b593cbd 100644 --- a/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java +++ b/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java @@ -20,22 +20,26 @@ */ package org.zanata.service.impl; +import static org.zanata.events.TextFlowTargetStateEvent.TextFlowTargetStateChange; +import static org.zanata.transaction.TransactionUtilImpl.runInTransaction; + import java.util.Collection; import java.util.List; import java.util.Map; import java.util.concurrent.Future; +import java.util.stream.Collectors; + import javax.annotation.Nonnull; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Multimap; import javax.enterprise.context.RequestScoped; import javax.enterprise.event.Event; import javax.inject.Inject; import javax.inject.Named; + import org.zanata.async.Async; import org.zanata.async.AsyncTaskResult; import org.zanata.async.handle.MergeTranslationsTaskHandle; import org.zanata.common.ContentState; +import org.zanata.common.EntityStatus; import org.zanata.dao.ProjectIterationDAO; import org.zanata.dao.TextFlowDAO; import org.zanata.events.DocStatsEvent; @@ -47,19 +51,27 @@ import org.zanata.model.HSimpleComment; import org.zanata.model.HTextFlow; import org.zanata.model.HTextFlowTarget; +import org.zanata.model.ModelEntityBase; import org.zanata.model.type.TranslationSourceType; import org.zanata.security.ZanataIdentity; import org.zanata.security.annotations.Authenticated; import org.zanata.service.LocaleService; import org.zanata.service.MergeTranslationsService; +import org.zanata.service.TransMemoryMergeService; import org.zanata.service.TranslationStateCache; import org.zanata.service.VersionStateCache; import org.zanata.util.TranslationUtil; +import org.zanata.webtrans.shared.model.ProjectIterationId; +import org.zanata.webtrans.shared.rest.dto.HasTMMergeCriteria; +import org.zanata.webtrans.shared.rest.dto.TransMemoryMergeRequest; +import org.zanata.webtrans.shared.rpc.MergeRule; + import com.google.common.base.Optional; import com.google.common.base.Stopwatch; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; -import static org.zanata.events.TextFlowTargetStateEvent.TextFlowTargetStateChange; -import static org.zanata.transaction.TransactionUtilImpl.runInTransaction; +import com.google.common.collect.Multimap; // Not @Transactional, because we use runInTransaction /** @@ -95,6 +107,9 @@ public class MergeTranslationsServiceImpl implements MergeTranslationsService { @Authenticated private HAccount authenticatedAccount; + @Inject + private TransMemoryMergeService transMemoryMergeService; + /** * Batch size for find matching HTextFlow to process merging of * translations. Each TextFlow may lead to changes in multiple @@ -302,12 +317,7 @@ private void mergeTextFlowTarget(HTextFlowTarget sourceTft, */ private boolean isVersionsEmpty(HProjectIteration sourceVersion, HProjectIteration targetVersion) { - if (sourceVersion.getDocuments().isEmpty()) { - log.error("No documents in source version {}:{}", - sourceVersion.getProject().getSlug(), - sourceVersion.getSlug()); - return true; - } + if (isVersionEmpty(sourceVersion)) return true; if (targetVersion.getDocuments().isEmpty()) { log.error("No documents in target version {}:{}", targetVersion.getProject().getSlug(), @@ -317,6 +327,16 @@ private boolean isVersionsEmpty(HProjectIteration sourceVersion, return false; } + private boolean isVersionEmpty(HProjectIteration version) { + if (version.getDocuments().isEmpty()) { + log.error("No documents in version {}:{}", + version.getProject().getSlug(), + version.getSlug()); + return true; + } + return false; + } + private void prepareMergeTranslationsHandle( @Nonnull HProjectIteration sourceVersion, @Nonnull HProjectIteration targetVersion, @@ -327,6 +347,15 @@ private void prepareMergeTranslationsHandle( handle.setTotalTranslations(total); } + private void prepareMergeTranslationsHandle2( + long total, + @Nonnull MergeTranslationsTaskHandle handle) { + handle.setTriggeredBy(identity.getAccountUsername()); + // TODO pahuang what is this maxProgress? + handle.setMaxProgress((int) total); + handle.setTotalTranslations(total); + } + @Override public int getTotalProgressCount(HProjectIteration sourceVersion, HProjectIteration targetVersion) { @@ -337,6 +366,76 @@ public int getTotalProgressCount(HProjectIteration sourceVersion, return matchCount * locales.size(); } + @Async + @Override + public Future startMergeTranslations(HProjectIteration targetVersion, + HLocale hLocale, TransMemoryMergeRequest mergeRequest, + MergeTranslationsTaskHandle handle) { + // since this is async we need to reload entities + targetVersion = projectIterationDAO.findById(targetVersion.getId()); + HLocale targetLocale = localeServiceImpl.getByLocaleId(mergeRequest.localeId); + + List fromVersionIds = mergeRequest.getFromProjectVersions().stream() + .map(projectIterationId -> projectIterationDAO.getBySlug( + projectIterationId.getProjectSlug(), + projectIterationId.getIterationSlug())) + .filter(ver -> ver != null + && ver.getStatus() != EntityStatus.OBSOLETE + && localeServiceImpl + .getSupportedLanguageByProjectIteration(ver) + .contains(targetLocale)) + .map(ModelEntityBase::getId).collect(Collectors.toList()); + + // TODO pahuang do we need to check this? +// if (fromVersionIds.isEmpty()) { +// log.error("Cannot find source versions of {}", fromVersionIds); +// return AsyncTaskResult.completed(); +// } + + if (isVersionEmpty(targetVersion)) { + return AsyncTaskResult.completed(); + } + List localesInTargetVersion = localeServiceImpl + .getSupportedLanguageByProjectIteration(targetVersion); + if (!localesInTargetVersion.contains(hLocale)) { + log.error("No locales enabled in target version of [{}]", + targetVersion.userFriendlyToString()); + return AsyncTaskResult.completed(); + } + + long mergeTargetCount = textFlowDAO.getUntranslatedOrFuzzyTextFlowCountInVersion( + targetVersion.getId(), hLocale); + + Optional taskHandleOpt = + Optional.fromNullable(handle); + if (taskHandleOpt.isPresent()) { + prepareMergeTranslationsHandle2(mergeTargetCount, taskHandleOpt.get()); + } + Stopwatch overallStopwatch = Stopwatch.createStarted(); + log.info("merge translations from TM start: from {} to {}", + fromVersionIds, + targetVersion.userFriendlyToString()); + int startCount = 0; + + while (startCount < mergeTargetCount) { + List batch = textFlowDAO + .getUntranslatedOrFuzzyTextFlowsInVersion( + targetVersion.getId(), hLocale, startCount, + TEXTFLOWS_PER_BATCH); + transMemoryMergeService.translateInBatch(mergeRequest, batch, hLocale, fromVersionIds); + + if (taskHandleOpt.isPresent()) { + taskHandleOpt.get().increaseProgress(batch.size()); + } + startCount += TEXTFLOWS_PER_BATCH; + } + versionStateCacheImpl.clearVersionStatsCache(targetVersion.getId()); + log.info("merge translation from TM end: from {} to {}, {}", + mergeRequest.getFromProjectVersions(), + targetVersion.userFriendlyToString(), overallStopwatch); + return AsyncTaskResult.completed(); + } + private int getTotalMatchCount(Long sourceVersionId, Long targetVersionId) { return textFlowDAO.getSourceByMatchedContextCount(sourceVersionId, targetVersionId); @@ -390,4 +489,5 @@ public static boolean shouldMerge(HTextFlowTarget sourceTft, return useNewerTranslation && sourceTft.getLastChanged().after(targetTft.getLastChanged()); } + } diff --git a/server/zanata-war/src/main/java/org/zanata/service/impl/TransMemoryMergeServiceImpl.java b/server/zanata-war/src/main/java/org/zanata/service/impl/TransMemoryMergeServiceImpl.java index fff7ec32c8..9df290256d 100644 --- a/server/zanata-war/src/main/java/org/zanata/service/impl/TransMemoryMergeServiceImpl.java +++ b/server/zanata-war/src/main/java/org/zanata/service/impl/TransMemoryMergeServiceImpl.java @@ -63,6 +63,7 @@ import org.zanata.webtrans.shared.model.TransUnitId; import org.zanata.webtrans.shared.model.TransUnitUpdateRequest; import org.zanata.webtrans.shared.model.WorkspaceId; +import org.zanata.webtrans.shared.rest.dto.HasTMMergeCriteria; import org.zanata.webtrans.shared.rest.dto.TransMemoryMergeRequest; import org.zanata.webtrans.shared.rpc.MergeRule; import org.zanata.webtrans.shared.rpc.TransUnitUpdated; @@ -226,7 +227,8 @@ private List translateInBatch( hTextFlow, targetLocale.getLocaleId(), hTextFlow.getDocument().getLocale().getLocaleId(), checkContext, checkDocument, checkProject, - request.getThresholdPercent()); + request.getThresholdPercent(), + Collections.emptyList()); if (tmResult.isPresent()) { TransUnitUpdateRequest updateRequest = createRequest(request, targetLocale, @@ -252,7 +254,58 @@ private List translateInBatch( } } - private TransUnitUpdateRequest createRequest(TransMemoryMergeRequest action, + // TODO pahuang this duplicated most part of above method + @Override + public void translateInBatch(HasTMMergeCriteria mergeCriteria, + List textFlows, HLocale targetLocale, + List fromProjectVersions) { + + if (textFlows.isEmpty()) { + return; + } + + try { + transactionUtil.run(() -> { + + List updateRequests = Lists.newLinkedList(); + for (HTextFlow hTextFlow : textFlows) { + HTextFlowTarget hTextFlowTarget = + hTextFlow.getTargets().get(targetLocale.getId()); + boolean checkContext = + mergeCriteria.getDifferentContextRule() == + MergeRule.REJECT; + boolean checkDocument = + mergeCriteria.getDifferentDocumentRule() == + MergeRule.REJECT; + boolean checkProject = + mergeCriteria.getDifferentProjectRule() == + MergeRule.REJECT; + Optional tmResult = + translationMemoryServiceImpl.searchBestMatchTransMemory( + hTextFlow, targetLocale.getLocaleId(), + hTextFlow.getDocument().getLocale().getLocaleId(), + checkContext, checkDocument, checkProject, + mergeCriteria.getThresholdPercent(), + fromProjectVersions); + if (tmResult.isPresent()) { + TransUnitUpdateRequest updateRequest = + createRequest(mergeCriteria, targetLocale, + hTextFlow, tmResult.get(), hTextFlowTarget); + + if (updateRequest != null) { + updateRequests.add(updateRequest); + } + } + } + translationServiceImpl.translate( + targetLocale.getLocaleId(), updateRequests); + }); + } catch (Exception e) { + log.error("exception during TM merge", e); + } + } + + private TransUnitUpdateRequest createRequest(HasTMMergeCriteria action, HLocale hLocale, HTextFlow hTextFlowToBeFilled, TransMemoryResultItem tmResult, HTextFlowTarget oldTarget) { diff --git a/server/zanata-war/src/main/java/org/zanata/service/impl/TranslationMemoryServiceImpl.java b/server/zanata-war/src/main/java/org/zanata/service/impl/TranslationMemoryServiceImpl.java index 4ee741a477..8beb0f2d3c 100644 --- a/server/zanata-war/src/main/java/org/zanata/service/impl/TranslationMemoryServiceImpl.java +++ b/server/zanata-war/src/main/java/org/zanata/service/impl/TranslationMemoryServiceImpl.java @@ -21,6 +21,23 @@ package org.zanata.service.impl; import static com.google.common.collect.Collections2.filter; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import javax.annotation.Nonnull; +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.inject.Named; + import org.apache.commons.lang.StringUtils; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.index.Term; @@ -36,9 +53,6 @@ import org.apache.lucene.search.WildcardQuery; import org.hibernate.search.jpa.FullTextEntityManager; import org.hibernate.search.jpa.FullTextQuery; -import javax.enterprise.context.RequestScoped; -import javax.inject.Inject; -import javax.inject.Named; import org.zanata.common.ContentState; import org.zanata.common.EntityStatus; import org.zanata.common.LocaleId; @@ -67,21 +81,12 @@ import org.zanata.webtrans.shared.model.TransMemoryResultItem; import org.zanata.webtrans.shared.rpc.HasSearchType; import org.zanata.webtrans.shared.rpc.LuceneQuery; + import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Objects; import com.google.common.base.Predicate; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import javax.annotation.Nonnull; /** * @author Alex Eng aeng@redhat.com @@ -155,6 +160,7 @@ public TransMemoryDetails getTransMemoryDetail(HLocale hLocale, } /** + * TODO this is only used by test. Should we remove it? * This is used by CopyTrans, with ContentHash search in lucene. Returns * first entry of the matches which sort by HTextFlowTarget.lastChanged DESC * @@ -172,7 +178,8 @@ public Optional searchBestMatchTransMemory( boolean checkDocument, boolean checkProject) { TransMemoryQuery query = buildTMQuery(textFlow, HasSearchType.SearchType.CONTENT_HASH, - checkContext, checkDocument, checkProject, false); + checkContext, checkDocument, checkProject, false, + Collections.emptyList()); Collection matches = findMatchingTranslation(targetLocaleId, sourceLocaleId, query, 0, Optional.empty(), HTextFlowTarget.class); @@ -185,7 +192,6 @@ public Optional searchBestMatchTransMemory( /** * This is used by TMMerge. Returns first entry of the matches which sort by * similarityPercent, sourceContents, and contents size. - * * @param textFlow * @param targetLocaleId * @param sourceLocaleId @@ -193,15 +199,18 @@ public Optional searchBestMatchTransMemory( * @param checkDocument * @param checkProject * @param thresholdPercent + * @param fromVersionIds */ @Override public Optional searchBestMatchTransMemory( HTextFlow textFlow, LocaleId targetLocaleId, LocaleId sourceLocaleId, boolean checkContext, - boolean checkDocument, boolean checkProject, int thresholdPercent) { + boolean checkDocument, boolean checkProject, int thresholdPercent, + List fromVersionIds) { TransMemoryQuery query = buildTMQuery(textFlow, HasSearchType.SearchType.FUZZY_PLURAL, - checkContext, checkDocument, checkProject, true); + checkContext, checkDocument, checkProject, + true, fromVersionIds); List tmResults = searchTransMemory(targetLocaleId, sourceLocaleId, query); // findTMAboveThreshold @@ -232,7 +241,7 @@ public List searchTransMemory( } List results = Lists.newArrayList(matchesMap.values()); - Collections.sort(results, TransMemoryResultComparator.COMPARATOR); + Collections.sort(results, new TransMemoryResultComparator(transMemoryQuery.getFromVersionIds())); return results; } @@ -248,7 +257,8 @@ public List searchTransMemoryWithDetails( private TransMemoryQuery buildTMQuery(HTextFlow textFlow, HasSearchType.SearchType searchType, boolean checkContext, boolean checkDocument, boolean checkProject, - boolean includeOwnTranslation) { + boolean includeOwnTranslation, + List fromVersions) { TransMemoryQuery.Condition project = new TransMemoryQuery.Condition( checkProject, textFlow.getDocument().getProjectIteration() .getProject().getId().toString()); @@ -262,7 +272,7 @@ private TransMemoryQuery buildTMQuery(HTextFlow textFlow, project, document, res); } else { query = new TransMemoryQuery(textFlow.getContents(), searchType, - project, document, res); + project, document, res, fromVersions); } if (!includeOwnTranslation) { query.setIncludeOwnTranslation(false, textFlow.getId().toString()); @@ -339,9 +349,12 @@ private void processIndexMatch(TransMemoryQuery transMemoryQuery, textFlowContents, MINIMUM_SIMILARITY); return; } + Long fromVersionId = textFlowTarget.getTextFlow().getDocument() + .getProjectIteration().getId(); TransMemoryResultItem item = createOrGetResultItem(matchesMap, match, matchType, - textFlowContents, targetContents, percent); + textFlowContents, targetContents, percent, + fromVersionId); addTextFlowTargetToResultMatches(textFlowTarget, item); } else if (entity instanceof TransMemoryUnit) { TransMemoryUnit transUnit = (TransMemoryUnit) entity; @@ -360,7 +373,7 @@ private void processIndexMatch(TransMemoryQuery transMemoryQuery, } TransMemoryResultItem item = createOrGetResultItem(matchesMap, match, TransMemoryResultItem.MatchType.Imported, - sourceContents, targetContents, percent); + sourceContents, targetContents, percent, null); addTransMemoryUnitToResultMatches(item, transUnit); } } @@ -422,13 +435,13 @@ private TransMemoryResultItem createOrGetResultItem( Map matchesMap, Object[] match, TransMemoryResultItem.MatchType matchType, ArrayList sourceContents, ArrayList targetContents, - double percent) { + double percent, Long fromVersionId) { TMKey key = new TMKey(sourceContents, targetContents); TransMemoryResultItem item = matchesMap.get(key); if (item == null) { float score = (Float) match[0]; item = new TransMemoryResultItem(sourceContents, targetContents, - matchType, score, percent); + matchType, score, percent, fromVersionId); matchesMap.put(key, item); } return item; @@ -465,9 +478,16 @@ private void addTextFlowTargetToResultMatches( * NB just because this Comparator returns 0 doesn't mean the matches are * identical. */ - private static enum TransMemoryResultComparator - implements Comparator { - COMPARATOR; + private static class TransMemoryResultComparator + implements Comparator, Serializable { + + + private static final long serialVersionUID = 1L; + private final List fromVersionIds; + + public TransMemoryResultComparator(List fromVersionIds) { + this.fromVersionIds = fromVersionIds; + } @Override public int compare(TransMemoryResultItem m1, TransMemoryResultItem m2) { @@ -483,7 +503,35 @@ public int compare(TransMemoryResultItem m1, TransMemoryResultItem m2) { // sort longer string lists first (more plural forms) return result; } - return m2.getMatchType().compareTo(m1.getMatchType()); + result = m2.getMatchType().compareTo(m1.getMatchType()); + if (result != 0) { + // sort match type + return result; + } + // if TM is from TMX, getFromVersionId is null + // if fromVersionIds is empty, we have no restriction on source version + if (m2.getFromVersionId() != null && m1.getFromVersionId() != null && !fromVersionIds.isEmpty()) { + int indexOfM2 = fromVersionIds.indexOf(m2.getFromVersionId()); + int indexOfM1 = fromVersionIds.indexOf(m1.getFromVersionId()); + // sort higher when index is lower + // if index is -1, something wrong with our lucene query or index + if (indexOfM1 < 0 || indexOfM2 < 0) { + log.warn("Having TM result not from requested source versions:{}", fromVersionIds); + if (indexOfM1 < 0 && indexOfM2 >= 0) { + // m2 rank higher since it's from the defined source versions + return 1; + } else if (indexOfM2 < 0 && indexOfM1 >= 0) { + // m1 is from defined source versions + return -1; + } else { + // they are both not from defined source versions + return result; + } + + } + return Integer.compare(indexOfM1, indexOfM2); + } + return result; } private int compare(List list1, List list2) { @@ -780,6 +828,18 @@ private void buildContextQuery(BooleanQuery query, query.add(resIdQuery, BooleanClause.Occur.SHOULD); } } + if (queryParams.getFromVersionIds() != null && !queryParams.getFromVersionIds().isEmpty()) { + BooleanQuery.Builder fromVersions = new BooleanQuery.Builder(); + queryParams.getFromVersionIds().forEach(projectIterationId -> { + TermQuery fromVersionQuery = new TermQuery( + new Term(IndexFieldLabels.PROJECT_VERSION_ID_FIELD, + projectIterationId.toString())); + + + fromVersions.add(fromVersionQuery, BooleanClause.Occur.SHOULD); + }); + query.add(fromVersions.build(), BooleanClause.Occur.MUST); + } } private Query buildContentQuery(TransMemoryQuery query, diff --git a/server/zanata-war/src/main/java/org/zanata/util/TransMemoryMergeStatusResolver.java b/server/zanata-war/src/main/java/org/zanata/util/TransMemoryMergeStatusResolver.java index 42b7048bf4..d8c0ea1617 100644 --- a/server/zanata-war/src/main/java/org/zanata/util/TransMemoryMergeStatusResolver.java +++ b/server/zanata-war/src/main/java/org/zanata/util/TransMemoryMergeStatusResolver.java @@ -26,7 +26,7 @@ import org.zanata.model.HTextFlowTarget; import org.zanata.webtrans.shared.model.TransMemoryDetails; import org.zanata.webtrans.shared.model.TransMemoryResultItem; -import org.zanata.webtrans.shared.rest.dto.TransMemoryMergeRequest; +import org.zanata.webtrans.shared.rest.dto.HasTMMergeCriteria; import org.zanata.webtrans.shared.rpc.MergeRule; import com.google.common.base.Objects; @@ -64,7 +64,7 @@ public static TransMemoryMergeStatusResolver newInstance() { * @return content state to be set on auto translated target. If null means * we want to reject the auto translation via TM merge */ - public ContentState decideStatus(TransMemoryMergeRequest action, + public ContentState decideStatus(HasTMMergeCriteria action, HTextFlow tfToBeFilled, TransMemoryDetails tmDetail, TransMemoryResultItem tmResult, HTextFlowTarget oldTarget) { @@ -101,7 +101,7 @@ public ContentState decideStatus(TransMemoryMergeRequest action, * @return content state to be set on auto translated target. If null means * we want to reject the auto translation via TM merge */ - public ContentState decideStatus(TransMemoryMergeRequest action, + public ContentState decideStatus(HasTMMergeCriteria action, TransMemoryResultItem tmResult, HTextFlowTarget oldTarget) { if ((int) tmResult.getSimilarityPercent() != 100) { @@ -123,14 +123,14 @@ public ContentState decideStatus(TransMemoryMergeRequest action, return ContentState.Translated; } - private void compareTextFlowResId(TransMemoryMergeRequest action, + private void compareTextFlowResId(HasTMMergeCriteria action, HTextFlow tfToBeFilled, TransMemoryDetails tmDetail) { if (notEqual(tfToBeFilled.getResId(), tmDetail.getResId())) { setFlagsBasedOnOption(action.getDifferentContextRule()); } } - private void compareTextFlowMsgContext(TransMemoryMergeRequest action, + private void compareTextFlowMsgContext(HasTMMergeCriteria action, HTextFlow tfToBeFilled, TransMemoryDetails tmDetail) { String msgCtx = null; if (tfToBeFilled.getPotEntryData() != null) { @@ -141,7 +141,7 @@ private void compareTextFlowMsgContext(TransMemoryMergeRequest action, } } - private void compareDocId(TransMemoryMergeRequest action, HTextFlow tfToBeFilled, + private void compareDocId(HasTMMergeCriteria action, HTextFlow tfToBeFilled, TransMemoryDetails tmDetail) { if (notEqual(tfToBeFilled.getDocument().getDocId(), tmDetail.getDocId())) { @@ -149,7 +149,7 @@ private void compareDocId(TransMemoryMergeRequest action, HTextFlow tfToBeFilled } } - private void compareProjectName(TransMemoryMergeRequest action, + private void compareProjectName(HasTMMergeCriteria action, HTextFlow tfToBeFilled, TransMemoryDetails tmDetail) { if (notEqual(tfToBeFilled.getDocument().getProjectIteration() .getProject().getName(), tmDetail.getProjectName())) { diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/ProjectVersionTest.java b/server/zanata-war/src/test/java/org/zanata/rest/service/ProjectVersionTest.java index 0261c613a1..adcfd2407d 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/ProjectVersionTest.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/ProjectVersionTest.java @@ -10,6 +10,7 @@ import org.mockito.Mock; import org.zanata.ApplicationConfiguration; import org.zanata.ZanataDbunitJpaTest; +import org.zanata.action.MergeTranslationsManager; import org.zanata.i18n.Messages; import org.zanata.jpa.FullText; import org.zanata.model.HAccount; @@ -60,6 +61,8 @@ public class ProjectVersionTest extends ZanataDbunitJpaTest { @Produces @Mock UrlUtil urlUtil; @Produces @Mock IdentityManager identityManager; + @Produces @Mock MergeTranslationsManager mergeTranslationsManager; + @Override @Produces protected Session getSession() { diff --git a/server/zanata-war/src/test/java/org/zanata/service/impl/MergeTranslationsServiceImplTest.java b/server/zanata-war/src/test/java/org/zanata/service/impl/MergeTranslationsServiceImplTest.java index a946ebbbed..b1c436c71d 100644 --- a/server/zanata-war/src/test/java/org/zanata/service/impl/MergeTranslationsServiceImplTest.java +++ b/server/zanata-war/src/test/java/org/zanata/service/impl/MergeTranslationsServiceImplTest.java @@ -52,6 +52,7 @@ import org.zanata.model.type.TranslationSourceType; import org.zanata.security.ZanataIdentity; import org.zanata.security.annotations.Authenticated; +import org.zanata.service.TransMemoryMergeService; import org.zanata.service.VersionLocaleKey; import org.zanata.test.CdiUnitRunner; import org.zanata.transaction.TransactionUtilImpl; @@ -133,6 +134,9 @@ public class MergeTranslationsServiceImplTest extends ZanataDbunitJpaTest { @Produces @Mock private CacheLoader versionStatisticLoader; + @Produces @Mock + private TransMemoryMergeService transMemoryMergeService; + private UserTransaction tx; private final String projectSlug = "sample-project"; diff --git a/server/zanata-war/src/test/java/org/zanata/service/impl/TransMemoryMergeServiceImplTest.java b/server/zanata-war/src/test/java/org/zanata/service/impl/TransMemoryMergeServiceImplTest.java index 7175ba65d3..d164e75727 100644 --- a/server/zanata-war/src/test/java/org/zanata/service/impl/TransMemoryMergeServiceImplTest.java +++ b/server/zanata-war/src/test/java/org/zanata/service/impl/TransMemoryMergeServiceImplTest.java @@ -32,6 +32,7 @@ import static org.zanata.webtrans.shared.rpc.HasSearchType.SearchType.FUZZY_PLURAL; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Optional; @@ -46,7 +47,6 @@ import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.zanata.async.handle.TransMemoryMergeTaskHandle; import org.zanata.common.ContentState; @@ -140,6 +140,7 @@ public class TransMemoryMergeServiceImplTest { private final EditorClientId editorClientId = new EditorClientId("sessionId", 1); private FilterConstraints untranslatedFilter; + private List fromVersions; private TransMemoryMergeRequest prepareAction(int threshold, MergeOptions opts) { LocaleId localeId = targetLocale.getLocaleId(); @@ -173,7 +174,7 @@ private TransMemoryMergeRequest prepareAction(int threshold, private static TransMemoryResultItem tmResult(Long sourceId, int percent) { TransMemoryResultItem resultItem = new TransMemoryResultItem(tmSource, tmTarget, - MatchType.ApprovedInternal, 1D, percent); + MatchType.ApprovedInternal, 1D, percent, 1L); resultItem.addSourceId(sourceId); return resultItem; } @@ -182,7 +183,7 @@ private static TransMemoryResultItem importedTmResult(Long sourceId, int percent) { TransMemoryResultItem resultItem = new TransMemoryResultItem(tmSource, tmTarget, - MatchType.Imported, 1D, percent); + MatchType.Imported, 1D, percent, 1L); resultItem.addSourceId(sourceId); return resultItem; } @@ -201,7 +202,7 @@ private static TransMemoryDetails tmDetail() { return new TransMemoryQuery(contents, searchType, new TransMemoryQuery.Condition(false, projectSlug), new TransMemoryQuery.Condition(false, docId), - new TransMemoryQuery.Condition(false, resId)); + new TransMemoryQuery.Condition(false, resId), fromVersions); } else { TransMemoryQuery.Condition projectCondition = new TransMemoryQuery.Condition( @@ -218,13 +219,14 @@ private static TransMemoryDetails tmDetail() { opts.getDifferentResId() == MergeRule.REJECT, resId); return new TransMemoryQuery(contents, searchType, projectCondition, - documentCondition, resCondition); + documentCondition, resCondition, fromVersions); } } @Before public void setUp() throws NoSuchWorkspaceException { MockitoAnnotations.initMocks(this); + fromVersions = Collections.emptyList(); asyncTaskHandle = new TransMemoryMergeTaskHandle(); WorkspaceId workspaceId = new WorkspaceId(projectIterationId, targetLocale.getLocaleId()); @@ -275,7 +277,8 @@ public void willTranslateIfMatches() throws ActionException { when( translationMemoryService.searchBestMatchTransMemory(hTextFlow, targetLocale.getLocaleId(), sourceLocale.getLocaleId(), - false, false, false, action.getThresholdPercent())) + false, false, false, action.getThresholdPercent(), + fromVersions)) .thenReturn(matches); // When: execute the action @@ -320,7 +323,8 @@ public void willNotTranslateIfNoMatches() throws ActionException { when( translationMemoryService.searchBestMatchTransMemory(hTextFlow, targetLocale.getLocaleId(), sourceLocale.getLocaleId(), - false, false, false, action.getThresholdPercent())) + false, false, false, action.getThresholdPercent(), + fromVersions)) .thenReturn(matches); when(localeService.getByLocaleId(action.localeId)) @@ -388,22 +392,26 @@ public void canHandleMultipleTextFlows() throws ActionException { when( translationMemoryService.searchBestMatchTransMemory( textFlow100TM, targetLocale.getLocaleId(), - sourceLocale.getLocaleId(), false, false, false, 90)) + sourceLocale.getLocaleId(), false, false, false, 90, + fromVersions)) .thenReturn(tm100); when( translationMemoryService.searchBestMatchTransMemory( textFLow90TM, targetLocale.getLocaleId(), - sourceLocale.getLocaleId(), false, false, false, 90)) + sourceLocale.getLocaleId(), false, false, false, 90, + fromVersions)) .thenReturn(tm90); when( translationMemoryService.searchBestMatchTransMemory( textFlow80TM, targetLocale.getLocaleId(), - sourceLocale.getLocaleId(), false, false, false, 90)) + sourceLocale.getLocaleId(), false, false, false, 90, + fromVersions)) .thenReturn(tm80); when( translationMemoryService.searchBestMatchTransMemory( textFlowNoTM, targetLocale.getLocaleId(), - sourceLocale.getLocaleId(), false, false, false, 90)) + sourceLocale.getLocaleId(), false, false, false, 90, + fromVersions)) .thenReturn(noMatch); when(textFlowDAO.findById(tmResultSource.getId(), false)).thenReturn( @@ -483,7 +491,8 @@ public void canAutoTranslateImportedTMResults() throws Exception { when( translationMemoryService.searchBestMatchTransMemory(hTextFlow, targetLocale.getLocaleId(), sourceLocale.getLocaleId(), - false, false, false, action.getThresholdPercent())) + false, false, false, action.getThresholdPercent(), + fromVersions)) .thenReturn(match); when(transMemoryUnitDAO.findById(tuResultSource.getId())).thenReturn( tuResultSource); diff --git a/server/zanata-war/src/test/java/org/zanata/service/impl/TranslationMemoryServiceImplTest.java b/server/zanata-war/src/test/java/org/zanata/service/impl/TranslationMemoryServiceImplTest.java index c15f8eaf2d..f43883a105 100644 --- a/server/zanata-war/src/test/java/org/zanata/service/impl/TranslationMemoryServiceImplTest.java +++ b/server/zanata-war/src/test/java/org/zanata/service/impl/TranslationMemoryServiceImplTest.java @@ -3,6 +3,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.test.rule.FunctionalTestRule.reentrant; +import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Optional; @@ -210,7 +211,7 @@ private void executeFindBestTMMatch(HTextFlow textFlow, int threshold, service.searchBestMatchTransMemory(textFlow, targetLocale.getLocaleId(), sourceLocale.getLocaleId(), false, false, false, - threshold); + threshold, Collections.emptyList()); assertThat(match.isPresent()).isEqualTo(hasMatch); } // to check if any of the sourceContents contain searchString diff --git a/server/zanata-war/src/test/java/org/zanata/util/TransMemoryMergeStatusResolverTest.java b/server/zanata-war/src/test/java/org/zanata/util/TransMemoryMergeStatusResolverTest.java index 59a92e6d42..52aa5cb9d3 100644 --- a/server/zanata-war/src/test/java/org/zanata/util/TransMemoryMergeStatusResolverTest.java +++ b/server/zanata-war/src/test/java/org/zanata/util/TransMemoryMergeStatusResolverTest.java @@ -78,13 +78,13 @@ public void beforeMethod() { private static TransMemoryResultItem tmResultWithSimilarity(double percent) { return new TransMemoryResultItem(null, null, - MatchType.TranslatedInternal, 0, percent); + MatchType.TranslatedInternal, 0, percent, 1L); } private static TransMemoryResultItem tmResultWithSimilarityAndExternallyImported(double percent) { return new TransMemoryResultItem(null, null, MatchType.Imported, 0, - percent); + percent, null); } private static TransMemoryDetails tmDetail(String projectName, diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransMemoryPresenterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransMemoryPresenterTest.java index bc55120b26..e634db8928 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransMemoryPresenterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransMemoryPresenterTest.java @@ -26,6 +26,7 @@ import org.zanata.common.ProjectType; import org.zanata.model.TestFixture; import org.zanata.rest.dto.stats.ContainerTranslationStatistics; +import org.zanata.service.impl.TranslationMemoryServiceImpl; import org.zanata.webtrans.client.events.CopyDataToEditorEvent; import org.zanata.webtrans.client.events.TransMemoryShortcutCopyEvent; import org.zanata.webtrans.client.events.TransUnitSelectionEvent; @@ -156,7 +157,7 @@ public void showTMDetails() { TransMemoryResultItem object = new TransMemoryResultItem(new ArrayList(), new ArrayList(), MatchType.ApprovedInternal, 0, - 0); + 0, null); when(display.getSearchType()).thenReturn(searchType); presenter.showTMDetails(object); @@ -169,7 +170,7 @@ public void fireCopyEvent() { TransMemoryResultItem object = new TransMemoryResultItem(new ArrayList(), new ArrayList(), MatchType.ApprovedInternal, 0, - 0); + 0, null); ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(CopyDataToEditorEvent.class); @@ -512,7 +513,7 @@ public void ignoreIfNotEditorConfigOptionChange() { * it. * * @throws Exception - * @see org.zanata.webtrans.server.rpc.GetTransMemoryHandler.TransMemoryResultComparator + * @see TranslationMemoryServiceImpl.TransMemoryResultComparator */ @Test public void matchTypeEnumOrder() throws Exception { From 4a5fb71ea3ec152fdac0097c8f2e83d8bca31b7b Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Tue, 13 Jun 2017 11:39:20 +1000 Subject: [PATCH 002/116] ZNTA-1865 add test and refactor --- .../rest/dto/TransMemoryMergeRequest.java | 10 -- .../action/MergeTranslationsManager.java | 17 +-- .../org/zanata/rest/dto/VersionTMMerge.java | 87 +++++++++++ .../rest/service/ProjectVersionService.java | 14 +- .../service/MergeTranslationsService.java | 10 +- .../impl/MergeTranslationsServiceImpl.java | 25 ++-- .../rest/service/ProjectVersionTest.java | 139 +++++++++++++++++- .../test/model/CopyVersionData.dbunit.xml | 4 + 8 files changed, 251 insertions(+), 55 deletions(-) create mode 100644 server/zanata-war/src/main/java/org/zanata/rest/dto/VersionTMMerge.java diff --git a/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/rest/dto/TransMemoryMergeRequest.java b/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/rest/dto/TransMemoryMergeRequest.java index a1955445c3..155b39dc44 100644 --- a/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/rest/dto/TransMemoryMergeRequest.java +++ b/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/rest/dto/TransMemoryMergeRequest.java @@ -20,7 +20,6 @@ */ package org.zanata.webtrans.shared.rest.dto; -import java.util.Collections; import java.util.List; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -51,7 +50,6 @@ public class TransMemoryMergeRequest implements HasTMMergeCriteria { public MergeRule differentDocumentRule; public MergeRule differentContextRule; public MergeRule importedMatchRule; - private List fromProjectVersions; public TransMemoryMergeRequest( EditorClientId editorClientId, @@ -100,12 +98,4 @@ public MergeRule getImportedMatchRule() { return importedMatchRule; } - public void setFromProjectVersions( - List fromProjectVersions) { - this.fromProjectVersions = fromProjectVersions; - } - - public List getFromProjectVersions() { - return fromProjectVersions; - } } diff --git a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java index 3c1b31d32d..473205cdd1 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java @@ -1,10 +1,8 @@ package org.zanata.action; import java.io.Serializable; -import java.util.List; import java.util.Objects; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import javax.enterprise.context.Dependent; import javax.inject.Inject; @@ -12,12 +10,11 @@ import org.zanata.async.AsyncTaskHandleManager; import org.zanata.async.handle.MergeTranslationsTaskHandle; import org.zanata.common.LocaleId; -import org.zanata.model.HLocale; -import org.zanata.model.HProjectIteration; +import org.zanata.rest.dto.VersionTMMerge; import org.zanata.security.ZanataIdentity; import org.zanata.service.MergeTranslationsService; -import org.zanata.webtrans.shared.model.ProjectIterationId; -import org.zanata.webtrans.shared.rest.dto.TransMemoryMergeRequest; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; /** * Manages tasks to copy translations from one existing version to another. @@ -97,11 +94,9 @@ public boolean isRunning(String projectSlug, String versionSlug) { return handle != null && !handle.isDone(); } - public boolean start(HProjectIteration version, HLocale hLocale, - TransMemoryMergeRequest mergeRequest) { + public boolean start(Long versionId, VersionTMMerge mergeRequest) { MergeTranslationTaskKey key = - new MergeTranslationTaskKey(version.getId(), - hLocale.getLocaleId()); + new MergeTranslationTaskKey(versionId, mergeRequest.getLocaleId()); AsyncTaskHandle handleByKey = asyncTaskHandleManager.getHandleByKey(key); if (handleByKey == null || handleByKey.isCancelled() @@ -110,7 +105,7 @@ public boolean start(HProjectIteration version, HLocale hLocale, handle.setTriggeredBy(identity.getAccountUsername()); asyncTaskHandleManager.registerTaskHandle(handle, key); - mergeTranslationsServiceImpl.startMergeTranslations(version, hLocale, + mergeTranslationsServiceImpl.startMergeTranslations(versionId, mergeRequest, handle); return true; } diff --git a/server/zanata-war/src/main/java/org/zanata/rest/dto/VersionTMMerge.java b/server/zanata-war/src/main/java/org/zanata/rest/dto/VersionTMMerge.java new file mode 100644 index 0000000000..c20eb7af1a --- /dev/null +++ b/server/zanata-war/src/main/java/org/zanata/rest/dto/VersionTMMerge.java @@ -0,0 +1,87 @@ +/* + * Copyright 2017, 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.dto; + +import java.util.List; + +import org.zanata.common.LocaleId; +import org.zanata.webtrans.shared.model.ProjectIterationId; +import org.zanata.webtrans.shared.rest.dto.HasTMMergeCriteria; +import org.zanata.webtrans.shared.rpc.MergeRule; + +/** + * @author Patrick Huang pahuang@redhat.com + */ +public class VersionTMMerge implements HasTMMergeCriteria { + private LocaleId localeId; + private int thresholdPercent; + private MergeRule differentDocumentRule; + private MergeRule differentContextRule; + private MergeRule importedMatchRule; + private List fromProjectVersions; + + public VersionTMMerge(LocaleId localeId, int thresholdPercent, + MergeRule differentDocumentRule, + MergeRule differentContextRule, + MergeRule importedMatchRule, + List fromProjectVersions) { + this.localeId = localeId; + this.thresholdPercent = thresholdPercent; + this.differentDocumentRule = differentDocumentRule; + this.differentContextRule = differentContextRule; + this.importedMatchRule = importedMatchRule; + this.fromProjectVersions = fromProjectVersions; + } + + public LocaleId getLocaleId() { + return localeId; + } + + @Override + public int getThresholdPercent() { + return thresholdPercent; + } + + @Override + public MergeRule getDifferentProjectRule() { + // TM merge for version always accept TM from different project + return MergeRule.FUZZY; + } + + @Override + public MergeRule getDifferentDocumentRule() { + return differentDocumentRule; + } + + @Override + public MergeRule getDifferentContextRule() { + return differentContextRule; + } + + @Override + public MergeRule getImportedMatchRule() { + return importedMatchRule; + } + + public List getFromProjectVersions() { + return fromProjectVersions; + } +} diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java index fea33f139f..4f3e050360 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java @@ -46,6 +46,7 @@ import org.zanata.rest.dto.ProjectIteration; import org.zanata.rest.dto.TransUnitStatus; import org.zanata.rest.dto.User; +import org.zanata.rest.dto.VersionTMMerge; import org.zanata.rest.dto.resource.ResourceMeta; import org.zanata.rest.editor.service.TransMemoryMergeManager; import org.zanata.rest.editor.service.UserService; @@ -335,16 +336,13 @@ public Response getTransUnitStatus( @Path(VERSION_SLUG_TEMPLATE + "/tm-merge") public Response prefillWithTM(@PathParam("projectSlug") String projectSlug, @PathParam("versionSlug") String versionSlug, - TransMemoryMergeRequest mergeRequest) { + VersionTMMerge mergeRequest) { int percent = mergeRequest.getThresholdPercent(); - if (percent != 80 && percent != 90 && percent != 100) { + if (percent < 80 || percent > 100) { return Response.status(Response.Status.BAD_REQUEST) - .entity("{\"error\":\"percentThreshold must be 80, 90 or 100\"}") + .entity("{\"error\":\"percentThreshold must be between 80 and 100\"}") .build(); } - // here we reuse the same DTO but some of the settings are fixed - mergeRequest.differentProjectRule = MergeRule.FUZZY; - HProject hProject = projectDAO.getBySlug(projectSlug); Optional projectResponse = @@ -365,7 +363,7 @@ public Response prefillWithTM(@PathParam("projectSlug") String projectSlug, + versionSlug + "\' is readonly.") .build(); } - LocaleId localeId = mergeRequest.localeId; + LocaleId localeId = mergeRequest.getLocaleId(); HLocale hLocale = localeServiceImpl.getByLocaleId(localeId); if (hLocale == null) { return Response.status(Response.Status.NOT_FOUND).build(); @@ -373,7 +371,7 @@ public Response prefillWithTM(@PathParam("projectSlug") String projectSlug, // TODO pahuang check security boolean started = mergeTranslationsManager - .start(version, hLocale, mergeRequest); + .start(version.getId(), mergeRequest); if (!started) { throw new UnsupportedOperationException("There is already version merge operation in progress"); } diff --git a/server/zanata-war/src/main/java/org/zanata/service/MergeTranslationsService.java b/server/zanata-war/src/main/java/org/zanata/service/MergeTranslationsService.java index d9a2c0d2dc..1ba9111119 100644 --- a/server/zanata-war/src/main/java/org/zanata/service/MergeTranslationsService.java +++ b/server/zanata-war/src/main/java/org/zanata/service/MergeTranslationsService.java @@ -21,14 +21,12 @@ package org.zanata.service; import java.io.Serializable; -import java.util.List; import java.util.concurrent.Future; import org.zanata.async.handle.MergeTranslationsTaskHandle; -import org.zanata.model.HLocale; +import org.zanata.common.LocaleId; import org.zanata.model.HProjectIteration; -import org.zanata.webtrans.shared.model.ProjectIterationId; -import org.zanata.webtrans.shared.rest.dto.TransMemoryMergeRequest; +import org.zanata.rest.dto.VersionTMMerge; public interface MergeTranslationsService extends Serializable { //@formatter:off @@ -57,7 +55,7 @@ Future startMergeTranslations(String sourceProjectSlug, int getTotalProgressCount(HProjectIteration sourceVersion, HProjectIteration targetVersion); - Future startMergeTranslations(HProjectIteration version, HLocale hLocale, - TransMemoryMergeRequest mergeRequest, + Future startMergeTranslations(Long versionId, + VersionTMMerge mergeRequest, MergeTranslationsTaskHandle handle); } diff --git a/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java b/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java index 868b593cbd..07420c14ff 100644 --- a/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java +++ b/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java @@ -40,6 +40,7 @@ import org.zanata.async.handle.MergeTranslationsTaskHandle; import org.zanata.common.ContentState; import org.zanata.common.EntityStatus; +import org.zanata.common.LocaleId; import org.zanata.dao.ProjectIterationDAO; import org.zanata.dao.TextFlowDAO; import org.zanata.events.DocStatsEvent; @@ -53,6 +54,7 @@ import org.zanata.model.HTextFlowTarget; import org.zanata.model.ModelEntityBase; import org.zanata.model.type.TranslationSourceType; +import org.zanata.rest.dto.VersionTMMerge; import org.zanata.security.ZanataIdentity; import org.zanata.security.annotations.Authenticated; import org.zanata.service.LocaleService; @@ -61,10 +63,6 @@ import org.zanata.service.TranslationStateCache; import org.zanata.service.VersionStateCache; import org.zanata.util.TranslationUtil; -import org.zanata.webtrans.shared.model.ProjectIterationId; -import org.zanata.webtrans.shared.rest.dto.HasTMMergeCriteria; -import org.zanata.webtrans.shared.rest.dto.TransMemoryMergeRequest; -import org.zanata.webtrans.shared.rpc.MergeRule; import com.google.common.base.Optional; import com.google.common.base.Stopwatch; @@ -368,12 +366,14 @@ public int getTotalProgressCount(HProjectIteration sourceVersion, @Async @Override - public Future startMergeTranslations(HProjectIteration targetVersion, - HLocale hLocale, TransMemoryMergeRequest mergeRequest, + public Future startMergeTranslations(Long targetVersionId, + VersionTMMerge mergeRequest, MergeTranslationsTaskHandle handle) { // since this is async we need to reload entities - targetVersion = projectIterationDAO.findById(targetVersion.getId()); - HLocale targetLocale = localeServiceImpl.getByLocaleId(mergeRequest.localeId); + HProjectIteration targetVersion = + projectIterationDAO.findById(targetVersionId); + HLocale targetLocale = + localeServiceImpl.getByLocaleId(mergeRequest.getLocaleId()); List fromVersionIds = mergeRequest.getFromProjectVersions().stream() .map(projectIterationId -> projectIterationDAO.getBySlug( @@ -397,14 +397,14 @@ public Future startMergeTranslations(HProjectIteration targetVersion, } List localesInTargetVersion = localeServiceImpl .getSupportedLanguageByProjectIteration(targetVersion); - if (!localesInTargetVersion.contains(hLocale)) { + if (!localesInTargetVersion.contains(targetLocale)) { log.error("No locales enabled in target version of [{}]", targetVersion.userFriendlyToString()); return AsyncTaskResult.completed(); } long mergeTargetCount = textFlowDAO.getUntranslatedOrFuzzyTextFlowCountInVersion( - targetVersion.getId(), hLocale); + targetVersion.getId(), targetLocale); Optional taskHandleOpt = Optional.fromNullable(handle); @@ -420,9 +420,10 @@ public Future startMergeTranslations(HProjectIteration targetVersion, while (startCount < mergeTargetCount) { List batch = textFlowDAO .getUntranslatedOrFuzzyTextFlowsInVersion( - targetVersion.getId(), hLocale, startCount, + targetVersion.getId(), targetLocale, startCount, TEXTFLOWS_PER_BATCH); - transMemoryMergeService.translateInBatch(mergeRequest, batch, hLocale, fromVersionIds); + transMemoryMergeService.translateInBatch(mergeRequest, batch, + targetLocale, fromVersionIds); if (taskHandleOpt.isPresent()) { taskHandleOpt.get().increaseProgress(batch.size()); diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/ProjectVersionTest.java b/server/zanata-war/src/test/java/org/zanata/rest/service/ProjectVersionTest.java index adcfd2407d..ade045694c 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/ProjectVersionTest.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/ProjectVersionTest.java @@ -1,5 +1,20 @@ package org.zanata.rest.service; +import static javax.ws.rs.core.Response.Status.BAD_REQUEST; +import static javax.ws.rs.core.Response.Status.FORBIDDEN; +import static javax.ws.rs.core.Response.Status.NOT_FOUND; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.when; + +import java.util.Collections; +import java.util.List; + +import javax.enterprise.inject.Produces; +import javax.inject.Inject; +import javax.persistence.EntityManager; +import javax.ws.rs.core.Response; + import org.apache.deltaspike.core.spi.scope.window.WindowContext; import org.dbunit.operation.DatabaseOperation; import org.hibernate.Session; @@ -11,10 +26,16 @@ import org.zanata.ApplicationConfiguration; import org.zanata.ZanataDbunitJpaTest; import org.zanata.action.MergeTranslationsManager; +import org.zanata.common.EntityStatus; +import org.zanata.common.LocaleId; import org.zanata.i18n.Messages; import org.zanata.jpa.FullText; import org.zanata.model.HAccount; +import org.zanata.model.HLocale; +import org.zanata.model.HProject; +import org.zanata.model.HProjectIteration; import org.zanata.rest.dto.User; +import org.zanata.rest.dto.VersionTMMerge; import org.zanata.rest.editor.service.resource.UserResource; import org.zanata.seam.security.IdentityManager; import org.zanata.security.annotations.Authenticated; @@ -27,14 +48,7 @@ import org.zanata.test.CdiUnitRunner; import org.zanata.util.DefaultLocale; import org.zanata.util.UrlUtil; - -import javax.enterprise.inject.Produces; -import javax.inject.Inject; -import javax.persistence.EntityManager; -import javax.ws.rs.core.Response; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; +import org.zanata.webtrans.shared.rpc.MergeRule; /** * @author Alex Eng aeng@redhat.com @@ -118,4 +132,113 @@ public void getContributors2() { List userList = (List) response.getEntity(); assertThat(userList).isEmpty(); } + + @Test + @InRequestScope + public void versionTMMergeReturnsBadRequestIfMatchThresholdIsNotValid() { + String projectSlug = "sample-project"; + String versionSlug = "2.0"; + VersionTMMerge request1 = new VersionTMMerge(LocaleId.FR, 79, + MergeRule.FUZZY, MergeRule.FUZZY, MergeRule.FUZZY, + Collections.emptyList()); + assertThat(service.prefillWithTM(projectSlug, versionSlug, request1) + .getStatus()).isEqualTo(BAD_REQUEST.getStatusCode()); + + VersionTMMerge request2 = new VersionTMMerge(LocaleId.FR, 101, + MergeRule.FUZZY, MergeRule.FUZZY, MergeRule.FUZZY, + Collections.emptyList()); + assertThat(service.prefillWithTM(projectSlug, versionSlug, request2) + .getStatus()).isEqualTo(BAD_REQUEST.getStatusCode()); + } + + @Test + @InRequestScope + public void versionTMMergeReturnsNotFoundIfProjectIsNotActive() { + String projectSlug = "non-existing-project"; + String versionSlug = "2.0"; + VersionTMMerge mergeRequest = new VersionTMMerge(LocaleId.FR, 90, + MergeRule.FUZZY, MergeRule.FUZZY, MergeRule.FUZZY, + Collections.emptyList()); + + assertThat(service.prefillWithTM(projectSlug, versionSlug, mergeRequest) + .getStatus()).isEqualTo(NOT_FOUND.getStatusCode()); + } + + @Test + @InRequestScope + public void versionTMMergeReturnsNotFoundIfProjectVersionIsObsolete() { + String projectSlug = "sample-project"; + + VersionTMMerge mergeRequest = new VersionTMMerge(LocaleId.FR, 90, + MergeRule.FUZZY, MergeRule.FUZZY, MergeRule.FUZZY, + Collections.emptyList()); + + assertThat(service.prefillWithTM(projectSlug, "non-exist", mergeRequest) + .getStatus()).isEqualTo(NOT_FOUND.getStatusCode()); + } + + @Test + @InRequestScope + public void versionTMMergeReturnsForbiddenIfProjectVersionIsReadOnly() { + String projectSlug = "sample-project"; + String versionSlug = "readonly"; + + VersionTMMerge mergeRequest = new VersionTMMerge(LocaleId.FR, 90, + MergeRule.FUZZY, MergeRule.FUZZY, MergeRule.FUZZY, + Collections.emptyList()); + + assertThat(service.prefillWithTM(projectSlug, versionSlug, mergeRequest) + .getStatus()).isEqualTo(FORBIDDEN.getStatusCode()); + } + + @Test + @InRequestScope + public void versionTMMergeReturnsNotFoundIfLocaleIdCanNotBeFound() { + String projectSlug = "sample-project"; + String versionSlug = "2.0"; + + VersionTMMerge mergeRequest = new VersionTMMerge(LocaleId.FR, 90, + MergeRule.FUZZY, MergeRule.FUZZY, MergeRule.FUZZY, + Collections.emptyList()); + when(localeService.getByLocaleId(LocaleId.FR)).thenReturn(null); + + assertThat(service.prefillWithTM(projectSlug, versionSlug, mergeRequest) + .getStatus()).isEqualTo(NOT_FOUND.getStatusCode()); + } + + @Test + @InRequestScope + public void versionTMMergeThrowsExceptionIfAnotherMergeProcessIsRunning() { + String projectSlug = "sample-project"; + String versionSlug = "1.0"; + + VersionTMMerge mergeRequest = new VersionTMMerge(LocaleId.FR, 90, + MergeRule.FUZZY, MergeRule.FUZZY, MergeRule.FUZZY, + Collections.emptyList()); + + // when there is already a merge process running + when(localeService.getByLocaleId(LocaleId.FR)).thenReturn(new HLocale(LocaleId.FR)); + when(mergeTranslationsManager.start(1L, mergeRequest)).thenReturn(false); + + assertThatThrownBy(() -> { + service.prefillWithTM(projectSlug, versionSlug, mergeRequest); + }) + .hasMessage("There is already version merge operation in progress") + .isInstanceOf(UnsupportedOperationException.class); + } + + @Test + @InRequestScope + public void versionTMMergeReturnsAcceptedIfEverythingIsGood() { + String projectSlug = "sample-project"; + String versionSlug = "2.0"; + + VersionTMMerge mergeRequest = new VersionTMMerge(LocaleId.FR, 90, + MergeRule.FUZZY, MergeRule.FUZZY, MergeRule.FUZZY, + Collections.emptyList()); + + when(mergeTranslationsManager.start(2L, mergeRequest)).thenReturn(true); + assertThat(service.prefillWithTM(projectSlug, versionSlug, mergeRequest) + .getStatus()).isEqualTo(NOT_FOUND.getStatusCode()); + } } diff --git a/server/zanata-war/src/test/resources/org/zanata/test/model/CopyVersionData.dbunit.xml b/server/zanata-war/src/test/resources/org/zanata/test/model/CopyVersionData.dbunit.xml index c18b44502c..11633c2c74 100644 --- a/server/zanata-war/src/test/resources/org/zanata/test/model/CopyVersionData.dbunit.xml +++ b/server/zanata-war/src/test/resources/org/zanata/test/model/CopyVersionData.dbunit.xml @@ -19,6 +19,10 @@ creationDate="2009-09-01 20:40:46" lastChanged="2009-09-01 20:40:46" parentId="[NULL]" project_id="1" overrideLocales="TRUE" status="A" /> + + From 2e09a2976b26a74bec82478bc8aa01296c7a5555 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Tue, 13 Jun 2017 15:49:39 +1000 Subject: [PATCH 003/116] add comment to differentiate two similar APIs --- .../zanata/rest/service/ProjectIterationLocalesResource.java | 4 ++++ .../java/org/zanata/rest/service/ProjectVersionResource.java | 2 ++ .../java/org/zanata/rest/search/service/SearchService.java | 3 ++- .../org/zanata/service/impl/MergeTranslationsServiceImpl.java | 2 +- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/service/ProjectIterationLocalesResource.java b/api/zanata-common-api/src/main/java/org/zanata/rest/service/ProjectIterationLocalesResource.java index deedd6df32..e9327a9966 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/service/ProjectIterationLocalesResource.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/service/ProjectIterationLocalesResource.java @@ -50,6 +50,10 @@ public interface ProjectIterationLocalesResource extends RestResource { * * This may be the list of locales inherited from the project. * + * This also returns locale aliases. + * + * @see ProjectVersionResource#getLocales(String, String) + * * @return * OK 200 containing the list of LocaleDetails * NOT FOUND 404 if the project-version does not exist diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/service/ProjectVersionResource.java b/api/zanata-common-api/src/main/java/org/zanata/rest/service/ProjectVersionResource.java index c2e038b4de..d0066ec31e 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/service/ProjectVersionResource.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/service/ProjectVersionResource.java @@ -191,6 +191,8 @@ public Response getContributors( /** * Retrieves a full list of locales enabled in project version. * + * @see ProjectIterationLocalesResource#get() + * * @param projectSlug * Project identifier * @param versionSlug diff --git a/server/zanata-war/src/main/java/org/zanata/rest/search/service/SearchService.java b/server/zanata-war/src/main/java/org/zanata/rest/search/service/SearchService.java index 2c56c472ae..8659f46f8c 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/search/service/SearchService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/search/service/SearchService.java @@ -37,6 +37,7 @@ import org.zanata.rest.search.dto.PersonSearchResult; import org.zanata.rest.search.dto.ProjectSearchResult; import org.zanata.rest.search.dto.SearchResults; +import org.zanata.rest.service.RestResource; import org.zanata.security.ZanataIdentity; import org.zanata.security.annotations.Authenticated; import org.zanata.service.GravatarService; @@ -62,7 +63,7 @@ @Path("/search") @Produces(APPLICATION_JSON) @Transactional(readOnly = true) -public class SearchService { +public class SearchService implements RestResource { @Inject private ProjectDAO projectDAO; diff --git a/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java b/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java index 07420c14ff..f290267eda 100644 --- a/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java +++ b/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java @@ -386,7 +386,7 @@ public Future startMergeTranslations(Long targetVersionId, .contains(targetLocale)) .map(ModelEntityBase::getId).collect(Collectors.toList()); - // TODO pahuang do we need to check this? + // TODO pahuang do we need to check this? If it's empty, should we default to current project versions? // if (fromVersionIds.isEmpty()) { // log.error("Cannot find source versions of {}", fromVersionIds); // return AsyncTaskResult.completed(); From 98ca6c73f2d76f61b97bcd4228775f937dbc7afe Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Tue, 13 Jun 2017 16:58:22 +1000 Subject: [PATCH 004/116] ZNTA-1865 add versions to project search result --- .../org/zanata/rest/dto/SearchResult.java | 3 +- .../org/zanata/dao/ProjectIterationDAO.java | 31 +++++----- .../rest/search/dto/ProjectSearchResult.java | 11 ++++ .../dto/ProjectVersionSearchResult.java | 30 +++++++++ .../rest/search/service/SearchService.java | 62 +++++++++++++++---- 5 files changed, 106 insertions(+), 31 deletions(-) create mode 100644 server/zanata-war/src/main/java/org/zanata/rest/search/dto/ProjectVersionSearchResult.java diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/SearchResult.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/SearchResult.java index eaf12f0111..5a1431ab2e 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/SearchResult.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/SearchResult.java @@ -38,7 +38,8 @@ public enum SearchResultType { Project, LanguageTeam, Person, - Group; + Group, + ProjectVersion } diff --git a/server/zanata-war/src/main/java/org/zanata/dao/ProjectIterationDAO.java b/server/zanata-war/src/main/java/org/zanata/dao/ProjectIterationDAO.java index 62ef48af14..13ae0c2fbf 100644 --- a/server/zanata-war/src/main/java/org/zanata/dao/ProjectIterationDAO.java +++ b/server/zanata-war/src/main/java/org/zanata/dao/ProjectIterationDAO.java @@ -25,6 +25,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -499,23 +500,19 @@ public List searchByProjectId(Long projectId) { return q.list(); } - public List searchByProjectIdExcludingStatus( - Long projectId, EntityStatus... exclude) { - StringBuilder sb = new StringBuilder(); - sb.append("FROM HProjectIteration t WHERE t.project.id = :projectId "); - for (EntityStatus status : exclude) { - sb.append("AND t.status != :"); - sb.append(status.toString()); - } - sb.append(" order by t.creationDate DESC"); - Query q = getSession().createQuery(sb.toString()); - q.setParameter("projectId", projectId); - - for (EntityStatus status : exclude) { - q.setParameter(status.toString(), status); - } - q.setCacheable(false).setComment( - "ProjectIterationDAO.searchByProjectIdExcludeObsolete"); + public List searchByProjectsExcludeObsolete( + List projects) { + String query = + "FROM HProjectIteration t WHERE t.project.id in (:projectIds) " + + "AND t.status != :status" + + " order by t.project.id, t.creationDate DESC"; + List projectIds = projects.stream().map(HProject::getId).collect( + Collectors.toList()); + Query q = getSession().createQuery(query) + .setParameterList("projectIds", projectIds) + .setParameter("status", EntityStatus.OBSOLETE) + .setCacheable(false).setComment( + "ProjectIterationDAO.searchByProjectIdsExcludeObsolete"); return q.list(); } diff --git a/server/zanata-war/src/main/java/org/zanata/rest/search/dto/ProjectSearchResult.java b/server/zanata-war/src/main/java/org/zanata/rest/search/dto/ProjectSearchResult.java index baacf9315f..22e9b70b29 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/search/dto/ProjectSearchResult.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/search/dto/ProjectSearchResult.java @@ -20,6 +20,8 @@ */ package org.zanata.rest.search.dto; +import java.util.List; + import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.map.annotate.JsonSerialize; import org.zanata.common.EntityStatus; @@ -35,6 +37,7 @@ public class ProjectSearchResult extends SearchResult { private String title; private long contributorCount; private EntityStatus status; + private List versions; public ProjectSearchResult() { this.setType(SearchResultType.Project); @@ -63,4 +66,12 @@ public EntityStatus getStatus() { public void setStatus(final EntityStatus status) { this.status = status; } + + public List getVersions() { + return versions; + } + + public void setVersions(List versions) { + this.versions = versions; + } } diff --git a/server/zanata-war/src/main/java/org/zanata/rest/search/dto/ProjectVersionSearchResult.java b/server/zanata-war/src/main/java/org/zanata/rest/search/dto/ProjectVersionSearchResult.java new file mode 100644 index 0000000000..2d3a3c609a --- /dev/null +++ b/server/zanata-war/src/main/java/org/zanata/rest/search/dto/ProjectVersionSearchResult.java @@ -0,0 +1,30 @@ +package org.zanata.rest.search.dto; + +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.zanata.common.EntityStatus; +import org.zanata.rest.dto.SearchResult; + +/** + * @author Patrick Huang pahuang@redhat.com + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +public class ProjectVersionSearchResult extends SearchResult { + private static final long serialVersionUID = 1L; + private EntityStatus status; + + public ProjectVersionSearchResult() { + super.setType(SearchResultType.ProjectVersion); + } + + public ProjectVersionSearchResult(String slug, EntityStatus status) { + super(); + setId(slug); + this.status = status; + } + + public EntityStatus getStatus() { + return status; + } +} diff --git a/server/zanata-war/src/main/java/org/zanata/rest/search/service/SearchService.java b/server/zanata-war/src/main/java/org/zanata/rest/search/service/SearchService.java index 8659f46f8c..f6a600f7f9 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/search/service/SearchService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/search/service/SearchService.java @@ -21,6 +21,21 @@ package org.zanata.rest.search.service; +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Response; + import org.apache.commons.lang.StringUtils; import org.apache.deltaspike.jpa.api.transaction.Transactional; import org.apache.lucene.queryparser.classic.ParseException; @@ -28,14 +43,17 @@ import org.zanata.dao.LocaleDAO; import org.zanata.dao.PersonDAO; import org.zanata.dao.ProjectDAO; +import org.zanata.dao.ProjectIterationDAO; import org.zanata.dao.VersionGroupDAO; import org.zanata.model.HAccount; import org.zanata.model.HIterationGroup; import org.zanata.model.HProject; +import org.zanata.model.HProjectIteration; import org.zanata.rest.dto.SearchResult; import org.zanata.rest.search.dto.GroupSearchResult; import org.zanata.rest.search.dto.PersonSearchResult; import org.zanata.rest.search.dto.ProjectSearchResult; +import org.zanata.rest.search.dto.ProjectVersionSearchResult; import org.zanata.rest.search.dto.SearchResults; import org.zanata.rest.service.RestResource; import org.zanata.security.ZanataIdentity; @@ -43,18 +61,8 @@ import org.zanata.service.GravatarService; import org.zanata.service.LocaleService; -import javax.enterprise.context.RequestScoped; -import javax.inject.Inject; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Response; -import java.util.List; -import java.util.stream.Collectors; - -import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; /** * @author Carlos Munoz camunoz@redhat.com @@ -68,6 +76,9 @@ public class SearchService implements RestResource { @Inject private ProjectDAO projectDAO; + @Inject + private ProjectIterationDAO projectIterationDAO; + @Inject private PersonDAO personDAO; @@ -93,7 +104,8 @@ public class SearchService implements RestResource { public Response searchProjects( @QueryParam("q") @DefaultValue("") String query, @DefaultValue("1") @QueryParam("page") int page, - @DefaultValue("20") @QueryParam("sizePerPage") int sizePerPage) { + @DefaultValue("20") @QueryParam("sizePerPage") int sizePerPage, + @DefaultValue("false") @QueryParam("includeVersion") boolean includeVersion) { int offset = (validatePage(page) - 1) * validatePageSize(sizePerPage); @@ -111,12 +123,36 @@ public Response searchProjects( validatePageSize(sizePerPage), offset, false); } + + Map> projectSlugToVersions = + Maps.newHashMap(); + if (includeVersion) { + List versions = projectIterationDAO + .searchByProjectsExcludeObsolete(projects); + versions.forEach(ver -> { + String projectSlug = ver.getProject().getSlug(); + List iterations = projectSlugToVersions + .getOrDefault(projectSlug, + Lists.newLinkedList()); + iterations.add(ver); + projectSlugToVersions.put(projectSlug, iterations); + }); + } List results = projects.stream().map(p -> { ProjectSearchResult result = new ProjectSearchResult(); result.setId(p.getSlug()); result.setStatus(p.getStatus()); result.setTitle(p.getName()); result.setDescription(p.getDescription()); + if (includeVersion) { + List iterations = + projectSlugToVersions.get(p.getSlug()); + result.setVersions(iterations == null ? null : iterations + .stream() + .map(iteration -> new ProjectVersionSearchResult( + iteration.getSlug(), iteration.getStatus())) + .collect(Collectors.toList())); + } // TODO: include contributor count when data is available return result; }).collect(Collectors.toList()); From c1d5b612002b57e15de6c95fad6e82bf4b10196e Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Wed, 14 Jun 2017 13:41:15 +1000 Subject: [PATCH 005/116] ZNTA-1865 fix dto marshalling --- .../src/main/java/org/zanata/rest/dto/VersionTMMerge.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/zanata-war/src/main/java/org/zanata/rest/dto/VersionTMMerge.java b/server/zanata-war/src/main/java/org/zanata/rest/dto/VersionTMMerge.java index c20eb7af1a..d4a4f8d6ae 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/dto/VersionTMMerge.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/dto/VersionTMMerge.java @@ -51,6 +51,10 @@ public VersionTMMerge(LocaleId localeId, int thresholdPercent, this.fromProjectVersions = fromProjectVersions; } + @SuppressWarnings("unused") + public VersionTMMerge() { + } + public LocaleId getLocaleId() { return localeId; } From dbc9848b7df779b1a840d7b01c749ee81ad0673a Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Wed, 14 Jun 2017 17:08:37 +1000 Subject: [PATCH 006/116] ZNTA-1865 - fix bug and refactor --- .../main/java/org/zanata/dao/GenericDAO.java | 2 + .../org/zanata/dao/ProjectIterationDAO.java | 5 +++ .../rest/search/service/SearchService.java | 2 +- .../rest/service/ProjectVersionService.java | 2 +- .../impl/MergeTranslationsServiceImpl.java | 42 ++++++++----------- 5 files changed, 26 insertions(+), 27 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/dao/GenericDAO.java b/server/zanata-war/src/main/java/org/zanata/dao/GenericDAO.java index 7043c386d9..74ffe3588a 100644 --- a/server/zanata-war/src/main/java/org/zanata/dao/GenericDAO.java +++ b/server/zanata-war/src/main/java/org/zanata/dao/GenericDAO.java @@ -8,6 +8,8 @@ */ public interface GenericDAO { + int MAX_PARAMS_IN_IN_CLAUSE = 50; + T findById(ID id, boolean lock); void deleteAll(); diff --git a/server/zanata-war/src/main/java/org/zanata/dao/ProjectIterationDAO.java b/server/zanata-war/src/main/java/org/zanata/dao/ProjectIterationDAO.java index 13ae0c2fbf..e5f00f2923 100644 --- a/server/zanata-war/src/main/java/org/zanata/dao/ProjectIterationDAO.java +++ b/server/zanata-war/src/main/java/org/zanata/dao/ProjectIterationDAO.java @@ -51,6 +51,7 @@ import org.zanata.util.HashUtil; import org.zanata.util.StatisticsUtil; +import com.google.common.base.Preconditions; import com.google.common.collect.Lists; @RequestScoped @@ -502,6 +503,10 @@ public List searchByProjectId(Long projectId) { public List searchByProjectsExcludeObsolete( List projects) { + Preconditions.checkArgument( + !projects.isEmpty() + && projects.size() < MAX_PARAMS_IN_IN_CLAUSE, + "invalid projectIds list"); String query = "FROM HProjectIteration t WHERE t.project.id in (:projectIds) " + "AND t.status != :status" diff --git a/server/zanata-war/src/main/java/org/zanata/rest/search/service/SearchService.java b/server/zanata-war/src/main/java/org/zanata/rest/search/service/SearchService.java index f6a600f7f9..01f9652164 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/search/service/SearchService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/search/service/SearchService.java @@ -126,7 +126,7 @@ public Response searchProjects( Map> projectSlugToVersions = Maps.newHashMap(); - if (includeVersion) { + if (includeVersion && !projects.isEmpty()) { List versions = projectIterationDAO .searchByProjectsExcludeObsolete(projects); versions.forEach(ver -> { diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java index 4f3e050360..df1e67a3e9 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java @@ -369,7 +369,7 @@ public Response prefillWithTM(@PathParam("projectSlug") String projectSlug, return Response.status(Response.Status.NOT_FOUND).build(); } - // TODO pahuang check security + identity.checkPermission("modify-translation", hProject, hLocale); boolean started = mergeTranslationsManager .start(version.getId(), mergeRequest); if (!started) { diff --git a/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java b/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java index f290267eda..40420847c1 100644 --- a/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java +++ b/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java @@ -40,7 +40,6 @@ import org.zanata.async.handle.MergeTranslationsTaskHandle; import org.zanata.common.ContentState; import org.zanata.common.EntityStatus; -import org.zanata.common.LocaleId; import org.zanata.dao.ProjectIterationDAO; import org.zanata.dao.TextFlowDAO; import org.zanata.events.DocStatsEvent; @@ -345,15 +344,6 @@ private void prepareMergeTranslationsHandle( handle.setTotalTranslations(total); } - private void prepareMergeTranslationsHandle2( - long total, - @Nonnull MergeTranslationsTaskHandle handle) { - handle.setTriggeredBy(identity.getAccountUsername()); - // TODO pahuang what is this maxProgress? - handle.setMaxProgress((int) total); - handle.setTotalTranslations(total); - } - @Override public int getTotalProgressCount(HProjectIteration sourceVersion, HProjectIteration targetVersion) { @@ -375,6 +365,17 @@ public Future startMergeTranslations(Long targetVersionId, HLocale targetLocale = localeServiceImpl.getByLocaleId(mergeRequest.getLocaleId()); + if (isVersionEmpty(targetVersion)) { + return AsyncTaskResult.completed(); + } + List localesInTargetVersion = localeServiceImpl + .getSupportedLanguageByProjectIteration(targetVersion); + if (!localesInTargetVersion.contains(targetLocale)) { + log.error("No locales enabled in target version of [{}]", + targetVersion.userFriendlyToString()); + return AsyncTaskResult.completed(); + } + List fromVersionIds = mergeRequest.getFromProjectVersions().stream() .map(projectIterationId -> projectIterationDAO.getBySlug( projectIterationId.getProjectSlug(), @@ -386,20 +387,8 @@ public Future startMergeTranslations(Long targetVersionId, .contains(targetLocale)) .map(ModelEntityBase::getId).collect(Collectors.toList()); - // TODO pahuang do we need to check this? If it's empty, should we default to current project versions? -// if (fromVersionIds.isEmpty()) { -// log.error("Cannot find source versions of {}", fromVersionIds); -// return AsyncTaskResult.completed(); -// } - - if (isVersionEmpty(targetVersion)) { - return AsyncTaskResult.completed(); - } - List localesInTargetVersion = localeServiceImpl - .getSupportedLanguageByProjectIteration(targetVersion); - if (!localesInTargetVersion.contains(targetLocale)) { - log.error("No locales enabled in target version of [{}]", - targetVersion.userFriendlyToString()); + if (fromVersionIds.isEmpty()) { + log.error("Cannot find source versions of {}", fromVersionIds); return AsyncTaskResult.completed(); } @@ -409,7 +398,10 @@ public Future startMergeTranslations(Long targetVersionId, Optional taskHandleOpt = Optional.fromNullable(handle); if (taskHandleOpt.isPresent()) { - prepareMergeTranslationsHandle2(mergeTargetCount, taskHandleOpt.get()); + MergeTranslationsTaskHandle handle1 = taskHandleOpt.get(); + handle1.setTriggeredBy(identity.getAccountUsername()); + handle1.setMaxProgress((int) mergeTargetCount); + handle1.setTotalTranslations(mergeTargetCount); } Stopwatch overallStopwatch = Stopwatch.createStarted(); log.info("merge translations from TM start: from {} to {}", From 978639f34fd9892bf85929f8f78394fbb826671c Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Thu, 15 Jun 2017 10:30:25 +1000 Subject: [PATCH 007/116] ZNTA-2057 refactor async task key --- .../org/zanata/action/CopyTransManager.java | 68 +++++--------- .../org/zanata/action/CopyVersionManager.java | 62 +++++-------- .../action/MergeTranslationsManager.java | 66 ++++++-------- .../action/TranslationMemoryAction.java | 37 ++------ .../zanata/async/AsyncTaskHandleManager.java | 91 ++++++++++++++++--- .../service/TransMemoryMergeManager.java | 55 +++++------ .../AsynchronousProcessResourceService.java | 2 +- .../GetDownloadAllFilesProgressHandler.java | 2 +- .../service/TransMemoryMergeManagerTest.java | 46 +++++----- 9 files changed, 210 insertions(+), 219 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java b/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java index ab940174d7..dce02294c4 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java @@ -21,11 +21,12 @@ package org.zanata.action; import java.io.Serializable; +import java.util.List; + import javax.annotation.Nonnull; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import javax.enterprise.context.Dependent; import javax.inject.Inject; -import javax.inject.Named; + import org.zanata.async.AsyncTaskHandle; import org.zanata.async.AsyncTaskHandleManager; import org.zanata.async.handle.CopyTransTaskHandle; @@ -34,6 +35,10 @@ import org.zanata.model.HProjectIteration; import org.zanata.security.ZanataIdentity; import org.zanata.service.CopyTransService; + +import com.google.common.base.Preconditions; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; // TODO This class should be merged with the copy trans service (?) /** @@ -145,8 +150,10 @@ public void cancelCopyTrans(@Nonnull HProjectIteration iteration) { /** * Internal class to index Copy Trans processes. */ - private static final class CopyTransProcessKey implements Serializable { + private static final class CopyTransProcessKey implements + AsyncTaskHandleManager.AsyncTaskKey { private static final long serialVersionUID = -2054359069473618887L; + private static final String KEY_NAME = "copyTransKey"; private String projectSlug; private String iterationSlug; private String docId; @@ -167,46 +174,6 @@ public static CopyTransProcessKey getKey(HDocument document) { return newKey; } - @Override - public boolean equals(final Object o) { - if (o == this) - return true; - if (!(o instanceof CopyTransManager.CopyTransProcessKey)) - return false; - final CopyTransProcessKey other = (CopyTransProcessKey) o; - final Object this$projectSlug = this.getProjectSlug(); - final Object other$projectSlug = other.getProjectSlug(); - if (this$projectSlug == null ? other$projectSlug != null - : !this$projectSlug.equals(other$projectSlug)) - return false; - final Object this$iterationSlug = this.getIterationSlug(); - final Object other$iterationSlug = other.getIterationSlug(); - if (this$iterationSlug == null ? other$iterationSlug != null - : !this$iterationSlug.equals(other$iterationSlug)) - return false; - final Object this$docId = this.getDocId(); - final Object other$docId = other.getDocId(); - if (this$docId == null ? other$docId != null - : !this$docId.equals(other$docId)) - return false; - return true; - } - - @Override - public int hashCode() { - final int PRIME = 59; - int result = 1; - final Object $projectSlug = this.getProjectSlug(); - result = result * PRIME - + ($projectSlug == null ? 43 : $projectSlug.hashCode()); - final Object $iterationSlug = this.getIterationSlug(); - result = result * PRIME - + ($iterationSlug == null ? 43 : $iterationSlug.hashCode()); - final Object $docId = this.getDocId(); - result = result * PRIME + ($docId == null ? 43 : $docId.hashCode()); - return result; - } - public String getProjectSlug() { return this.projectSlug; } @@ -233,5 +200,20 @@ public void setDocId(final String docId) { private CopyTransProcessKey() { } + + @Override + public String id() { + return joinFields(KEY_NAME, projectSlug, iterationSlug, docId); + } + + @Override + public CopyTransProcessKey from(String id) { + List parts = parseId(id, KEY_NAME, 3); + CopyTransProcessKey key = new CopyTransProcessKey(); + key.projectSlug = parts.get(0); + key.iterationSlug = parts.get(1); + key.docId = parts.get(2); + return key; + } } } diff --git a/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java b/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java index 7fb1170d87..ae9a6d7795 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java @@ -1,6 +1,8 @@ package org.zanata.action; import java.io.Serializable; +import java.util.List; + import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import javax.enterprise.context.Dependent; import javax.inject.Inject; @@ -83,55 +85,28 @@ public boolean isCopyVersionRunning(String projectSlug, /** * Key used for copy version task * - * @param projectSlug - * - target project identifier - * @param versionSlug - * - target version identifier */ - public static final class CopyVersionKey implements Serializable { + public static final class CopyVersionKey implements + AsyncTaskHandleManager.AsyncTaskKey { + private static final String KEY_NAME = "copyVersion"; + private static final long serialVersionUID = 3889349239078033373L; // target project identifier private final String projectSlug; // target version identifier private final String versionSlug; + /** + * + * @param projectSlug + * - target project identifier + * @param versionSlug + * - target version identifier + */ public static CopyVersionKey getKey(String projectSlug, String versionSlug) { return new CopyVersionKey(projectSlug, versionSlug); } - @Override - public boolean equals(final Object o) { - if (o == this) - return true; - if (!(o instanceof CopyVersionManager.CopyVersionKey)) - return false; - final CopyVersionKey other = (CopyVersionKey) o; - final Object this$projectSlug = this.getProjectSlug(); - final Object other$projectSlug = other.getProjectSlug(); - if (this$projectSlug == null ? other$projectSlug != null - : !this$projectSlug.equals(other$projectSlug)) - return false; - final Object this$versionSlug = this.getVersionSlug(); - final Object other$versionSlug = other.getVersionSlug(); - if (this$versionSlug == null ? other$versionSlug != null - : !this$versionSlug.equals(other$versionSlug)) - return false; - return true; - } - - @Override - public int hashCode() { - final int PRIME = 59; - int result = 1; - final Object $projectSlug = this.getProjectSlug(); - result = result * PRIME - + ($projectSlug == null ? 43 : $projectSlug.hashCode()); - final Object $versionSlug = this.getVersionSlug(); - result = result * PRIME - + ($versionSlug == null ? 43 : $versionSlug.hashCode()); - return result; - } - public String getProjectSlug() { return this.projectSlug; } @@ -146,5 +121,16 @@ public CopyVersionKey(final String projectSlug, this.projectSlug = projectSlug; this.versionSlug = versionSlug; } + + @Override + public String id() { + return joinFields(KEY_NAME, projectSlug, versionSlug); + } + + @Override + public CopyVersionKey from(String id) { + List parts = parseId(id, KEY_NAME, 2); + return getKey(parts.get(0), parts.get(1)); + } } } diff --git a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java index 24d763ffd7..d49960b7aa 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java @@ -1,10 +1,12 @@ package org.zanata.action; import java.io.Serializable; +import java.util.List; + import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import javax.enterprise.context.Dependent; import javax.inject.Inject; -import javax.inject.Named; + import org.zanata.async.AsyncTaskHandleManager; import org.zanata.async.handle.MergeTranslationsTaskHandle; import org.zanata.security.ZanataIdentity; @@ -48,7 +50,9 @@ public class MergeTranslationsManager implements Serializable { public void start(String sourceProjectSlug, String sourceVersionSlug, String targetProjectSlug, String targetVersionSlug, boolean useNewerTranslation) { - Key key = Key.getKey(targetProjectSlug, targetVersionSlug); + MergeVersionKey + key = MergeVersionKey + .getKey(targetProjectSlug, targetVersionSlug); MergeTranslationsTaskHandle handle = new MergeTranslationsTaskHandle(); asyncTaskHandleManager.registerTaskHandle(handle, key); mergeTranslationsServiceImpl.startMergeTranslations(sourceProjectSlug, @@ -79,7 +83,7 @@ public void cancel(String projectSlug, String versionSlug) { public MergeTranslationsTaskHandle getProcessHandle(String projectSlug, String versionSlug) { return (MergeTranslationsTaskHandle) asyncTaskHandleManager - .getHandleByKey(Key.getKey(projectSlug, versionSlug)); + .getHandleByKey(MergeVersionKey.getKey(projectSlug, versionSlug)); } public boolean isRunning(String projectSlug, String versionSlug) { @@ -89,50 +93,21 @@ public boolean isRunning(String projectSlug, String versionSlug) { } /** - * Key used for copy version task + * Key used for merge version task */ - public static final class Key implements Serializable { + public static final class MergeVersionKey implements + AsyncTaskHandleManager.AsyncTaskKey { + private static final long serialVersionUID = 1L; + private static final String KEY_NAME = "mergeVersion"; // target project identifier private final String projectSlug; // target version identifier private final String versionSlug; - public static Key getKey(String projectSlug, String versionSlug) { - return new Key(projectSlug, versionSlug); + public static MergeVersionKey getKey(String projectSlug, String versionSlug) { + return new MergeVersionKey(projectSlug, versionSlug); } - @Override - public boolean equals(final Object o) { - if (o == this) - return true; - if (!(o instanceof MergeTranslationsManager.Key)) - return false; - final Key other = (Key) o; - final Object this$projectSlug = this.getProjectSlug(); - final Object other$projectSlug = other.getProjectSlug(); - if (this$projectSlug == null ? other$projectSlug != null - : !this$projectSlug.equals(other$projectSlug)) - return false; - final Object this$versionSlug = this.getVersionSlug(); - final Object other$versionSlug = other.getVersionSlug(); - if (this$versionSlug == null ? other$versionSlug != null - : !this$versionSlug.equals(other$versionSlug)) - return false; - return true; - } - - @Override - public int hashCode() { - final int PRIME = 59; - int result = 1; - final Object $projectSlug = this.getProjectSlug(); - result = result * PRIME - + ($projectSlug == null ? 43 : $projectSlug.hashCode()); - final Object $versionSlug = this.getVersionSlug(); - result = result * PRIME - + ($versionSlug == null ? 43 : $versionSlug.hashCode()); - return result; - } public String getProjectSlug() { return this.projectSlug; @@ -143,9 +118,20 @@ public String getVersionSlug() { } @java.beans.ConstructorProperties({ "projectSlug", "versionSlug" }) - public Key(final String projectSlug, final String versionSlug) { + public MergeVersionKey(final String projectSlug, final String versionSlug) { this.projectSlug = projectSlug; this.versionSlug = versionSlug; } + + @Override + public String id() { + return joinFields(KEY_NAME, projectSlug, versionSlug); + } + + @Override + public MergeVersionKey from(String id) { + List parts = parseId(id, KEY_NAME, 2); + return getKey(parts.get(0), parts.get(1)); + } } } diff --git a/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java b/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java index 7cc68305c7..e5faaf5651 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java +++ b/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java @@ -89,7 +89,7 @@ public List getAllTranslationMemories() { } public void sortTMList() { - Collections.sort(transMemoryList, tmComparator); + transMemoryList.sort(tmComparator); } public void clearTransMemory(final String transMemorySlug) { @@ -198,7 +198,10 @@ public String cancel() { * NB: Eventually this class might need to live outside if there are other * services that need to control this process. */ - private static class ClearTransMemoryProcessKey implements Serializable { + private static class ClearTransMemoryProcessKey implements + AsyncTaskHandleManager.AsyncTaskKey { + private static final String KEY_NAME = "ClearTMXKey"; + private static final long serialVersionUID = 3472355792561903500L; private String slug; @java.beans.ConstructorProperties({ "slug" }) @@ -207,34 +210,14 @@ public ClearTransMemoryProcessKey(final String slug) { } @Override - public boolean equals(final Object o) { - if (o == this) - return true; - if (!(o instanceof TranslationMemoryAction.ClearTransMemoryProcessKey)) - return false; - final ClearTransMemoryProcessKey other = - (ClearTransMemoryProcessKey) o; - if (!other.canEqual((Object) this)) - return false; - final Object this$slug = this.slug; - final Object other$slug = other.slug; - if (this$slug == null ? other$slug != null - : !this$slug.equals(other$slug)) - return false; - return true; - } - - protected boolean canEqual(final Object other) { - return other instanceof TranslationMemoryAction.ClearTransMemoryProcessKey; + public String id() { + return joinFields(KEY_NAME, slug); } @Override - public int hashCode() { - final int PRIME = 59; - int result = 1; - final Object $slug = this.slug; - result = result * PRIME + ($slug == null ? 43 : $slug.hashCode()); - return result; + public ClearTransMemoryProcessKey from(String id) { + List parts = parseId(id, KEY_NAME, 1); + return new ClearTransMemoryProcessKey(parts.get(0)); } } diff --git a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java index b91d0ccd87..df5cf93ffc 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java +++ b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java @@ -22,16 +22,21 @@ import java.io.Serializable; import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeUnit; -import com.google.common.collect.Lists; import javax.inject.Named; +import com.google.common.base.Joiner; +import com.google.common.base.Preconditions; +import com.google.common.base.Splitter; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; +import com.google.common.collect.Lists; import com.google.common.collect.Maps; + import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; /** @@ -41,22 +46,23 @@ @javax.enterprise.context.ApplicationScoped public class AsyncTaskHandleManager implements Serializable { + // TODO refactor the key to be something more useful. e.g. an interface Key with method String id for querying purpose @SuppressFBWarnings(value = "SE_BAD_FIELD") - private Map handlesByKey = Maps + private final Map handlesByKey = Maps .newConcurrentMap(); // Cache of recently completed tasks - private Cache finishedTasks = CacheBuilder + private Cache finishedTasks = CacheBuilder .newBuilder().expireAfterWrite(10, TimeUnit.MINUTES) .build(); - public synchronized void registerTaskHandle(AsyncTaskHandle handle, - Serializable key) { - if (handlesByKey.containsKey(key)) { + public synchronized > void registerTaskHandle(AsyncTaskHandle handle, + K key) { + if (handlesByKey.containsKey(key.id())) { throw new RuntimeException("Task handle with key " + key + " already exists"); } - handlesByKey.put(key, handle); + handlesByKey.put(key.id(), handle); } /** @@ -65,15 +71,16 @@ public synchronized void registerTaskHandle(AsyncTaskHandle handle, * @return An auto generated key to retreive the handle later */ public synchronized Serializable registerTaskHandle(AsyncTaskHandle handle) { - Serializable autoGenKey = UUID.randomUUID().toString(); - registerTaskHandle(handle, autoGenKey); + String autoGenKey = UUID.randomUUID().toString(); + AsyncTaskKey autoKey = key -> autoGenKey; + registerTaskHandle(handle, autoKey); return autoGenKey; } void taskFinished(AsyncTaskHandle taskHandle) { synchronized (handlesByKey) { // TODO This operation is O(n). Maybe we can do better? - for (Map.Entry entry : handlesByKey + for (Map.Entry entry : handlesByKey .entrySet()) { if (entry.getValue().equals(taskHandle)) { handlesByKey.remove(entry.getKey()); @@ -83,11 +90,18 @@ void taskFinished(AsyncTaskHandle taskHandle) { } } - public AsyncTaskHandle getHandleByKey(Serializable key) { - if (handlesByKey.containsKey(key)) { - return handlesByKey.get(key); + public > AsyncTaskHandle getHandleByKey(K key) { + if (handlesByKey.containsKey(key.id())) { + return handlesByKey.get(key.id()); + } + return finishedTasks.getIfPresent(key.id()); + } + + public AsyncTaskHandle getHandleByKeyId(String keyId) { + if (handlesByKey.containsKey(keyId)) { + return handlesByKey.get(keyId); } - return finishedTasks.getIfPresent(key); + return finishedTasks.getIfPresent(keyId); } public Collection getAllHandles() { @@ -96,4 +110,53 @@ public Collection getAllHandles() { handles.addAll(finishedTasks.asMap().values()); return handles; } + + public interface AsyncTaskKey extends Serializable { + /** + * When converting multiple fields to form id string or vice versa, we + * should use this as separator. + */ + String SEPARATOR = "-"; + + default String id() { + return UUID.randomUUID().toString(); + } + + T from(String id); + + /** + * Helper method to convert id back to a list of fields. + * + * @param id + * the id + * @param keyName + * the name for this key + * @param expectedNumOfFields + * number of fields embedded in the id + * @return list of fields + */ + default List parseId(String id, String keyName, + int expectedNumOfFields) { + String fields = id.replaceFirst(keyName + SEPARATOR, id); + List result = + Splitter.on(SEPARATOR).trimResults().splitToList(fields); + Preconditions.checkArgument(expectedNumOfFields == result.size(), + "%s for %s is invalid", id, keyName); + return result; + } + + /** + * Helper method to convert list of fields to a String as key id. + * + * @param keyName + * the name for this key + * @param fields + * key instance field values + * @return String representation of the key which can be used as id + */ + default String joinFields(String keyName, String... fields) { + return keyName + SEPARATOR + + Joiner.on(SEPARATOR).useForNull("").join(fields); + } + } } diff --git a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java index 21973c610e..7567ef59e4 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java @@ -21,12 +21,12 @@ package org.zanata.rest.editor.service; import java.io.Serializable; +import java.util.List; import java.util.Objects; import javax.enterprise.context.Dependent; import javax.inject.Inject; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zanata.async.AsyncTaskHandle; @@ -36,13 +36,9 @@ import org.zanata.model.HAccount; import org.zanata.security.annotations.Authenticated; import org.zanata.service.TransMemoryMergeService; -import org.zanata.webtrans.shared.model.DocumentId; -import org.zanata.webtrans.shared.model.ProjectIterationId; import org.zanata.webtrans.shared.rest.dto.TransMemoryMergeCancelRequest; import org.zanata.webtrans.shared.rest.dto.TransMemoryMergeRequest; -import com.google.common.base.MoreObjects; - /** * @author Patrick Huang * pahuang@redhat.com @@ -51,6 +47,7 @@ public class TransMemoryMergeManager implements Serializable { private static final Logger log = LoggerFactory.getLogger(TransMemoryMergeManager.class); + private static final long serialVersionUID = 1364316697376958035L; private final AsyncTaskHandleManager asyncTaskHandleManager; private final TransMemoryMergeService transMemoryMergeService; @@ -77,9 +74,9 @@ public TransMemoryMergeManager( * if there is already a task running */ public boolean startTransMemoryMerge(TransMemoryMergeRequest request) { - TransMemoryTaskKey key = - new TransMemoryTaskKey(request.projectIterationId, - request.documentId, request.localeId); + TMMergeForDocTaskKey key = + new TMMergeForDocTaskKey( + request.documentId.getId(), request.localeId); AsyncTaskHandle handleByKey = asyncTaskHandleManager.getHandleByKey(key); if (handleByKey == null || handleByKey.isCancelled() @@ -94,9 +91,9 @@ public boolean startTransMemoryMerge(TransMemoryMergeRequest request) { } public boolean cancelTransMemoryMerge(TransMemoryMergeCancelRequest request) { - TransMemoryTaskKey key = - new TransMemoryTaskKey(request.projectIterationId, - request.documentId, request.localeId); + TMMergeForDocTaskKey key = + new TMMergeForDocTaskKey( + request.documentId.getId(), request.localeId); AsyncTaskHandle handleByKey = asyncTaskHandleManager.getHandleByKey(key); if (handleByKey != null && !(handleByKey.isDone() || handleByKey.isCancelled())) { @@ -116,42 +113,34 @@ public boolean cancelTransMemoryMerge(TransMemoryMergeCancelRequest request) { return false; } - static class TransMemoryTaskKey implements Serializable { + static class TMMergeForDocTaskKey implements + AsyncTaskHandleManager.AsyncTaskKey { - @SuppressFBWarnings("SE_BAD_FIELD") - private final ProjectIterationId projectIterationId; - private final DocumentId documentId; + private static final long serialVersionUID = -7210004008208642L; + private static final String KEY_NAME = "TMMergeForDocKey"; + private final Long documentId; private final LocaleId localeId; - TransMemoryTaskKey(ProjectIterationId projectIterationId, - DocumentId documentId, LocaleId localeId) { - - this.projectIterationId = projectIterationId; + TMMergeForDocTaskKey(Long documentId, LocaleId localeId) { this.documentId = documentId; this.localeId = localeId; } @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - TransMemoryTaskKey that = (TransMemoryTaskKey) o; - return Objects.equals(projectIterationId, that.projectIterationId) - && Objects.equals(documentId, that.documentId) - && Objects.equals(localeId, that.localeId); + public String toString() { + return id(); } @Override - public int hashCode() { - return Objects.hash(projectIterationId, documentId, localeId); + public String id() { + return joinFields(KEY_NAME, documentId.toString(), localeId.getId()); } @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("projectIterationId", projectIterationId) - .add("documentId", documentId).add("localeId", localeId) - .toString(); + public TMMergeForDocTaskKey from(String id) { + List parts = parseId(id, KEY_NAME, 2); + return new TMMergeForDocTaskKey(Long.parseLong(parts.get(0)), + new LocaleId(parts.get(1))); } } } diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java index b3aa31f672..1a9a911c6a 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java @@ -211,7 +211,7 @@ public ProcessStatus startTranslatedDocCreationOrUpdate( @Override public ProcessStatus getProcessStatus(String processId) { AsyncTaskHandle handle = - asyncTaskHandleManager.getHandleByKey(processId); + asyncTaskHandleManager.getHandleByKeyId(processId); if (handle == null) { throw new NotFoundException( "A process was not found for id " + processId); diff --git a/server/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/GetDownloadAllFilesProgressHandler.java b/server/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/GetDownloadAllFilesProgressHandler.java index 7e2bd9400b..0ca855bdbf 100644 --- a/server/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/GetDownloadAllFilesProgressHandler.java +++ b/server/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/GetDownloadAllFilesProgressHandler.java @@ -57,7 +57,7 @@ public GetDownloadAllFilesProgressResult execute( String downloadId = ""; AsyncTaskHandle handle = - asyncTaskHandleManager.getHandleByKey(action.getProcessId()); + asyncTaskHandleManager.getHandleByKeyId(action.getProcessId()); if (handle != null) { if (handle.isDone()) { try { diff --git a/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java b/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java index 640b7baf96..6d6e7940fe 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java @@ -13,11 +13,13 @@ import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.zanata.async.AsyncTaskHandleManager; +import org.zanata.async.AsyncTaskHandleManager.AsyncTaskKey; import org.zanata.async.handle.TransMemoryMergeTaskHandle; import org.zanata.common.LocaleId; import org.zanata.common.ProjectType; import org.zanata.model.HAccount; import org.zanata.model.TestFixture; +import org.zanata.rest.editor.service.TransMemoryMergeManager.TMMergeForDocTaskKey; import org.zanata.service.TransMemoryMergeService; import org.zanata.webtrans.shared.auth.EditorClientId; import org.zanata.webtrans.shared.model.DocumentId; @@ -38,7 +40,7 @@ public class TransMemoryMergeManagerTest { @Captor private ArgumentCaptor handleCaptor; @Captor - private ArgumentCaptor taskKeyCaptor; + private ArgumentCaptor> taskKeyCaptor; private TransMemoryMergeCancelRequest cancelRequest; @Before @@ -89,9 +91,9 @@ public boolean isCancelled() { } }; - TransMemoryMergeManager.TransMemoryTaskKey taskKey = - new TransMemoryMergeManager.TransMemoryTaskKey( - request.projectIterationId, request.documentId, + TMMergeForDocTaskKey taskKey = + new TMMergeForDocTaskKey( + request.documentId.getId(), request.localeId); when(asyncTaskHandleManager.getHandleByKey(taskKey)) .thenReturn(existingHandle); @@ -118,9 +120,9 @@ public boolean isDone() { } }; - TransMemoryMergeManager.TransMemoryTaskKey taskKey = - new TransMemoryMergeManager.TransMemoryTaskKey( - request.projectIterationId, request.documentId, + TMMergeForDocTaskKey taskKey = + new TMMergeForDocTaskKey( + request.documentId.getId(), request.localeId); when(asyncTaskHandleManager.getHandleByKey(taskKey)) .thenReturn(existingHandle); @@ -139,9 +141,9 @@ public boolean isDone() { @Test public void startTMMergeWillReturnFalseIfProcessForSameRequestIsAlreadyRunning() { - TransMemoryMergeManager.TransMemoryTaskKey taskKey = - new TransMemoryMergeManager.TransMemoryTaskKey( - request.projectIterationId, request.documentId, + TMMergeForDocTaskKey taskKey = + new TMMergeForDocTaskKey( + request.documentId.getId(), request.localeId); when(asyncTaskHandleManager.getHandleByKey(taskKey)) .thenReturn(new TransMemoryMergeTaskHandle()); @@ -169,9 +171,9 @@ public boolean isDone() { } }; - TransMemoryMergeManager.TransMemoryTaskKey taskKey = - new TransMemoryMergeManager.TransMemoryTaskKey( - cancelRequest.projectIterationId, cancelRequest.documentId, + TMMergeForDocTaskKey taskKey = + new TMMergeForDocTaskKey( + cancelRequest.documentId.getId(), cancelRequest.localeId); when(asyncTaskHandleManager.getHandleByKey(taskKey)) .thenReturn(existingHandle); @@ -191,9 +193,9 @@ public boolean isCancelled() { } }; - TransMemoryMergeManager.TransMemoryTaskKey taskKey = - new TransMemoryMergeManager.TransMemoryTaskKey( - cancelRequest.projectIterationId, cancelRequest.documentId, + TMMergeForDocTaskKey taskKey = + new TMMergeForDocTaskKey( + cancelRequest.documentId.getId(), cancelRequest.localeId); when(asyncTaskHandleManager.getHandleByKey(taskKey)) .thenReturn(existingHandle); @@ -208,9 +210,9 @@ public void cancelTMMergeWillReturnFalseIfProcessForThisRequestIsNotTriggeredByT new TransMemoryMergeTaskHandle(); existingHandle.setTriggeredBy("someone else"); - TransMemoryMergeManager.TransMemoryTaskKey taskKey = - new TransMemoryMergeManager.TransMemoryTaskKey( - cancelRequest.projectIterationId, cancelRequest.documentId, + TMMergeForDocTaskKey taskKey = + new TMMergeForDocTaskKey( + cancelRequest.documentId.getId(), cancelRequest.localeId); when(asyncTaskHandleManager.getHandleByKey(taskKey)) .thenReturn(existingHandle); @@ -231,9 +233,9 @@ public boolean cancel(boolean mayInterruptIfRunning) { }; existingHandle.setTriggeredBy(authenticated.getUsername()); - TransMemoryMergeManager.TransMemoryTaskKey taskKey = - new TransMemoryMergeManager.TransMemoryTaskKey( - cancelRequest.projectIterationId, cancelRequest.documentId, + TMMergeForDocTaskKey taskKey = + new TMMergeForDocTaskKey( + cancelRequest.documentId.getId(), cancelRequest.localeId); when(asyncTaskHandleManager.getHandleByKey(taskKey)) .thenReturn(existingHandle); From a50d69c095556a80219c5aa6315923e21f6a1919 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Thu, 15 Jun 2017 14:43:13 +1000 Subject: [PATCH 008/116] ZNTA-2057 change int to long for progress fields --- .../client/view/DocumentListDisplay.java | 2 +- .../client/view/DocumentListView.java | 2 +- .../GetDownloadAllFilesProgressResult.java | 12 ++++----- .../java/org/zanata/action/ReindexAction.java | 4 +-- .../org/zanata/async/AsyncTaskHandle.java | 25 ++++++------------- .../zanata/async/AsyncTaskHandleManager.java | 7 +++++- .../AsynchronousProcessResourceService.java | 4 +-- .../GetDownloadAllFilesProgressHandler.java | 4 +-- .../org/zanata/async/AsyncTaskHandleTest.java | 1 - .../org/zanata/async/AsyncTaskITCase.java | 6 ++--- 10 files changed, 31 insertions(+), 36 deletions(-) diff --git a/server/gwt-editor/src/main/java/org/zanata/webtrans/client/view/DocumentListDisplay.java b/server/gwt-editor/src/main/java/org/zanata/webtrans/client/view/DocumentListDisplay.java index 50fcd429cc..aa1af7ed0b 100644 --- a/server/gwt-editor/src/main/java/org/zanata/webtrans/client/view/DocumentListDisplay.java +++ b/server/gwt-editor/src/main/java/org/zanata/webtrans/client/view/DocumentListDisplay.java @@ -86,7 +86,7 @@ interface Listener { void hideConfirmation(); - void updateFileDownloadProgress(int currentProgress, int maxProgress); + void updateFileDownloadProgress(long currentProgress, long maxProgress); void setDownloadInProgress(boolean inProgress); diff --git a/server/gwt-editor/src/main/java/org/zanata/webtrans/client/view/DocumentListView.java b/server/gwt-editor/src/main/java/org/zanata/webtrans/client/view/DocumentListView.java index 529dd8eb87..181a55ed3a 100644 --- a/server/gwt-editor/src/main/java/org/zanata/webtrans/client/view/DocumentListView.java +++ b/server/gwt-editor/src/main/java/org/zanata/webtrans/client/view/DocumentListView.java @@ -222,7 +222,7 @@ public void hideConfirmation() { @Override public void - updateFileDownloadProgress(int currentProgress, int maxProgress) { + updateFileDownloadProgress(long currentProgress, long maxProgress) { confirmationBox.setProgressMessage(currentProgress + " of " + maxProgress); } diff --git a/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/rpc/GetDownloadAllFilesProgressResult.java b/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/rpc/GetDownloadAllFilesProgressResult.java index 8eb684cb83..23df255aff 100644 --- a/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/rpc/GetDownloadAllFilesProgressResult.java +++ b/server/gwt-editor/src/main/java/org/zanata/webtrans/shared/rpc/GetDownloadAllFilesProgressResult.java @@ -4,26 +4,26 @@ public class GetDownloadAllFilesProgressResult implements DispatchResult { private static final long serialVersionUID = 1L; - private int currentProgress; - private int maxProgress; + private long currentProgress; + private long maxProgress; private String downloadId; @SuppressWarnings("unused") private GetDownloadAllFilesProgressResult() { } - public GetDownloadAllFilesProgressResult(int currentProgress, - int maxProgress, String downloadId) { + public GetDownloadAllFilesProgressResult(long currentProgress, + long maxProgress, String downloadId) { this.maxProgress = maxProgress; this.currentProgress = currentProgress; this.downloadId = downloadId; } - public int getCurrentProgress() { + public long getCurrentProgress() { return currentProgress; } - public int getMaxProgress() { + public long getMaxProgress() { return maxProgress; } diff --git a/server/zanata-war/src/main/java/org/zanata/action/ReindexAction.java b/server/zanata-war/src/main/java/org/zanata/action/ReindexAction.java index cf17f9c8ba..a0a0c7aed9 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/ReindexAction.java +++ b/server/zanata-war/src/main/java/org/zanata/action/ReindexAction.java @@ -148,7 +148,7 @@ public boolean isError() { return false; } - public int getReindexCount() { + public long getReindexCount() { if (searchIndexManager.getProcessHandle() == null) { return 0; } else { @@ -156,7 +156,7 @@ public int getReindexCount() { } } - public int getReindexProgress() { + public long getReindexProgress() { if (searchIndexManager.getProcessHandle() == null) { return 0; } else { diff --git a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java index f4d5c47d8e..42907c7470 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java @@ -42,13 +42,12 @@ public class AsyncTaskHandle implements Serializable { @SuppressFBWarnings("SE_BAD_FIELD") private CompletableFuture futureResult; - public int maxProgress = 100; - public int minProgress = 0; - public int currentProgress = 0; + public long maxProgress = 100; + public long currentProgress = 0; private long startTime = -1; private long finishTime = -1; - public int increaseProgress(int increaseBy) { + public long increaseProgress(long increaseBy) { currentProgress += increaseBy; return currentProgress; } @@ -95,7 +94,7 @@ public Optional getEstimatedTimeRemaining() { if (this.startTime > 0 && currentProgress > 0) { long currentTime = System.currentTimeMillis(); long timeElapsed = currentTime - this.startTime; - int remainingUnits = this.maxProgress - this.currentProgress; + long remainingUnits = this.maxProgress - this.currentProgress; return Optional .of(timeElapsed * remainingUnits / this.currentProgress); } else { @@ -151,27 +150,19 @@ void setFutureResult(final CompletableFuture futureResult) { this.futureResult = futureResult; } - public int getMaxProgress() { + public long getMaxProgress() { return this.maxProgress; } - public void setMaxProgress(final int maxProgress) { + public void setMaxProgress(final long maxProgress) { this.maxProgress = maxProgress; } - public int getMinProgress() { - return this.minProgress; - } - - public void setMinProgress(final int minProgress) { - this.minProgress = minProgress; - } - - public int getCurrentProgress() { + public long getCurrentProgress() { return this.currentProgress; } - public void setCurrentProgress(final int currentProgress) { + protected void setCurrentProgress(final long currentProgress) { this.currentProgress = currentProgress; } diff --git a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java index df5cf93ffc..9a6378b35e 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java +++ b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java @@ -34,6 +34,7 @@ import com.google.common.base.Splitter; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -106,11 +107,15 @@ public AsyncTaskHandle getHandleByKeyId(String keyId) { public Collection getAllHandles() { Collection handles = Lists.newArrayList(); - handles.addAll(handlesByKey.values()); + handles.addAll(getRunningHandles()); handles.addAll(finishedTasks.asMap().values()); return handles; } + public Collection getRunningHandles() { + return ImmutableList.copyOf(handlesByKey.values()); + } + public interface AsyncTaskKey extends Serializable { /** * When converting multiple fields to form id string or vice versa, we diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java index 1a9a911c6a..625ff924d9 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java @@ -221,8 +221,8 @@ public ProcessStatus getProcessStatus(String processId) { : ProcessStatusCode.Running); int perComplete = 100; if (handle.getMaxProgress() > 0) { - perComplete = (handle.getCurrentProgress() * 100 - / handle.getMaxProgress()); + perComplete = (int) (handle.getCurrentProgress() * 100 + / handle.getMaxProgress()); } status.setPercentageComplete(perComplete); status.setUrl("" + processId); diff --git a/server/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/GetDownloadAllFilesProgressHandler.java b/server/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/GetDownloadAllFilesProgressHandler.java index 0ca855bdbf..4430a0c003 100644 --- a/server/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/GetDownloadAllFilesProgressHandler.java +++ b/server/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/GetDownloadAllFilesProgressHandler.java @@ -52,8 +52,8 @@ public class GetDownloadAllFilesProgressHandler public GetDownloadAllFilesProgressResult execute( GetDownloadAllFilesProgress action, ExecutionContext context) throws ActionException { - int currentProgress = 0; - int maxProgress = 0; + long currentProgress = 0; + long maxProgress = 0; String downloadId = ""; AsyncTaskHandle handle = diff --git a/server/zanata-war/src/test/java/org/zanata/async/AsyncTaskHandleTest.java b/server/zanata-war/src/test/java/org/zanata/async/AsyncTaskHandleTest.java index 0cd18e35b4..d0885fc0e1 100644 --- a/server/zanata-war/src/test/java/org/zanata/async/AsyncTaskHandleTest.java +++ b/server/zanata-war/src/test/java/org/zanata/async/AsyncTaskHandleTest.java @@ -98,7 +98,6 @@ public void testIsCancelled() throws Exception { @Test public void testEstimatedTimeRemaining() throws Exception { AsyncTaskHandle handle = new AsyncTaskHandle<>(); - handle.setMinProgress(0); handle.setMaxProgress(10); AsyncTaskResult result = new AsyncTaskResult<>(); handle.setFutureResult(result); diff --git a/server/zanata-war/src/test/java/org/zanata/async/AsyncTaskITCase.java b/server/zanata-war/src/test/java/org/zanata/async/AsyncTaskITCase.java index cffcb1591b..1e8a913da6 100644 --- a/server/zanata-war/src/test/java/org/zanata/async/AsyncTaskITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/async/AsyncTaskITCase.java @@ -105,7 +105,7 @@ public void executionError() throws Exception { @Test public void progressUpdates() throws Exception { - final List progressUpdates = Lists.newArrayList(); + final List progressUpdates = Lists.newArrayList(); // Custom handle so that progress updates are recorded final AsyncTaskHandle taskHandle = @@ -113,7 +113,7 @@ public void progressUpdates() throws Exception { private static final long serialVersionUID = 1L; @Override - public void setCurrentProgress(int progress) { + public void setCurrentProgress(long progress) { super.setCurrentProgress(progress); progressUpdates.add(progress); } @@ -128,7 +128,7 @@ public void setCurrentProgress(int progress) { // Progress update calls should match the task's internal updates assertThat(taskHandle.getCurrentProgress()).isEqualTo(100); assertThat(progressUpdates.size()).isEqualTo(4); - assertThat(progressUpdates).contains(25, 50, 75, 100); + assertThat(progressUpdates).contains(25L, 50L, 75L, 100L); } From bd74bdfc6808611e9fc2f08ee1de81dfeb32db4f Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Thu, 15 Jun 2017 15:50:07 +1000 Subject: [PATCH 009/116] ZNTA-2057 refactor TransMemoryMergeTaskHandle --- .../handle/TransMemoryMergeTaskHandle.java | 25 ++----------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/async/handle/TransMemoryMergeTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/handle/TransMemoryMergeTaskHandle.java index aa5421fa0e..805ed7076c 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/handle/TransMemoryMergeTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/handle/TransMemoryMergeTaskHandle.java @@ -31,28 +31,11 @@ * @author Patrick Huang pahuang@redhat.com */ public class TransMemoryMergeTaskHandle extends AsyncTaskHandle { - private long textFlowFilled; - private long totalTextFlows; private String cancelledBy; private Long cancelledTime; private String triggeredBy; private String mergeTarget; - public long getTextFlowFilled() { - return this.textFlowFilled; - } - - public void setTextFlowFilled(final long textFlowFilled) { - this.textFlowFilled = textFlowFilled; - } - - public long getTotalTextFlows() { - return this.totalTextFlows; - } - - public void setTotalTextFlows(final long totalTextFlows) { - this.totalTextFlows = totalTextFlows; - } public String getCancelledBy() { return this.cancelledBy; @@ -84,17 +67,13 @@ public void setTMMergeTarget(ProjectIterationId projectIterationId, documentId.getDocId(), localeId); } - public String getMergeTarget() { - return mergeTarget; - } - @Override public String toString() { return MoreObjects.toStringHelper(this) .omitNullValues() .add("mergeTarget", mergeTarget) - .add("textFlowFilled", textFlowFilled) - .add("totalTextFlows", totalTextFlows) + .add("textFlowFilled", currentProgress) + .add("totalTextFlows", maxProgress) .add("cancelledBy", cancelledBy) .add("cancelledTime", cancelledTime) .add("triggeredBy", triggeredBy) From a0f87515cea08f21a45667b0ef25e4dde17114ef Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Thu, 15 Jun 2017 15:50:39 +1000 Subject: [PATCH 010/116] ZNTA-2057 - add new REST api for async task --- .../org/zanata/rest/dto/ProcessStatus.java | 9 + .../zanata/async/AsyncTaskHandleManager.java | 15 +- .../rest/service/AsyncProcessService.java | 164 ++++++++++++++++++ .../AsynchronousProcessResourceService.java | 33 +--- .../impl/TransMemoryMergeServiceImpl.java | 6 +- 5 files changed, 188 insertions(+), 39 deletions(-) create mode 100644 server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/ProcessStatus.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/ProcessStatus.java index 143c051013..41f8993548 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/ProcessStatus.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/ProcessStatus.java @@ -65,6 +65,10 @@ public enum ProcessStatusCode { /** The process has finshed with a failure */ @XmlEnumValue("Failed") Failed, + + /** The process has been cancelled */ + @XmlEnumValue("Cancelled") + Cancelled } private String url; @@ -111,6 +115,11 @@ public void setMessages(List messages) { this.messages = messages; } + public ProcessStatus addMessage(String message) { + getMessages().add(message); + return this; + } + @XmlElement public ProcessStatusCode getStatusCode() { return statusCode; diff --git a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java index 9a6378b35e..906d784ce4 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java +++ b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java @@ -34,7 +34,7 @@ import com.google.common.base.Splitter; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -107,13 +107,20 @@ public AsyncTaskHandle getHandleByKeyId(String keyId) { public Collection getAllHandles() { Collection handles = Lists.newArrayList(); - handles.addAll(getRunningHandles()); + handles.addAll(handlesByKey.values()); handles.addAll(finishedTasks.asMap().values()); return handles; } - public Collection getRunningHandles() { - return ImmutableList.copyOf(handlesByKey.values()); + public Map getAllTasks() { + ImmutableMap.Builder builder = ImmutableMap.builder(); + builder.putAll(handlesByKey); + builder.putAll(finishedTasks.asMap()); + return builder.build(); + } + + public Map getRunningTasks() { + return ImmutableMap.copyOf(handlesByKey); } public interface AsyncTaskKey extends Serializable { diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java new file mode 100644 index 0000000000..c7877c7bdd --- /dev/null +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java @@ -0,0 +1,164 @@ +/* + * Copyright 2017, 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.service; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; + +import javax.inject.Inject; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import org.jetbrains.annotations.NotNull; +import org.zanata.async.AsyncTaskHandle; +import org.zanata.async.AsyncTaskHandleManager; +import org.zanata.rest.dto.ProcessStatus; + +import com.webcohesion.enunciate.metadata.rs.TypeHint; + +/** + * This endpoint should let us control and query all async tasks. + * + * TODO AsynchronousProcessResourceService are specific for CLI push and pull + * + * @see AsynchronousProcessResourceService + * @author Patrick Huang + * pahuang@redhat.com + */ +@Path("/process") +@Produces(MediaType.APPLICATION_JSON) +public class AsyncProcessService implements RestResource { + private static final long serialVersionUID = 1L; + + @Inject + private AsyncTaskHandleManager asyncTaskHandleManager; + + @Context + private UriInfo uriInfo; + + /** + * Get an async task's status. + * + * @param keyId + * task id + * @return The following response status codes will be returned from this + * operation:
+ * OK(200) - The contents of the response will indicate the process + * identifier which may be used to query for its status or a message + * indicating what happened.
+ * INTERNAL SERVER ERROR(500) - If there is an unexpected error in + * the server while performing this operation. + */ + @Path("key/{key}") + @GET + @TypeHint(ProcessStatus.class) + public Response getAsyncProcessStatus(@PathParam("key") String keyId) { + AsyncTaskHandle handle = asyncTaskHandleManager.getHandleByKeyId(keyId); + if (handle == null) { + return Response.status(Response.Status.NOT_FOUND).build(); + } + ProcessStatus status = handleToProcessStatus(handle, + uriInfo.getRequestUri().toString()); + return Response.ok(status).build(); + } + + /** + * Get all async task's status. + * + * @param includeFinished + * whether to include finished tasks + * + * @return The following response status codes will be returned from this + * operation:
+ * OK(200) - The contents of the response will indicate all + * background processes which may be used to query for its status or + * a message indicating what happened.
+ * INTERNAL SERVER ERROR(500) - If there is an unexpected error in + * the server while performing this operation. + */ + @GET + public Response getAllAsyncProcess( + @QueryParam("includeFinished") @DefaultValue("false") boolean includeFinished) { + Map tasks; + if (includeFinished) { + tasks = asyncTaskHandleManager.getAllTasks(); + } else { + tasks = asyncTaskHandleManager.getRunningTasks(); + } + List processStatuses = tasks.entrySet().stream() + .map(taskEntry -> handleToProcessStatus(taskEntry.getValue(), + uriInfo.getBaseUri().toString() + "process/key/" + + taskEntry.getKey())) + .collect(Collectors.toList()); + return Response.ok(processStatuses).build(); + } + + @NotNull + static ProcessStatus handleToProcessStatus(AsyncTaskHandle handle, + String url) { + ProcessStatus status = new ProcessStatus(); + status.setStatusCode( + handle.isDone() ? ProcessStatus.ProcessStatusCode.Finished + : ProcessStatus.ProcessStatusCode.Running); + int perComplete = 100; + if (handle.getMaxProgress() > 0) { + perComplete = (int) (handle.getCurrentProgress() * 100 + / handle.getMaxProgress()); + } + status.setPercentageComplete(perComplete); + status.setUrl(url); + if (handle.isCancelled()) { + status.setStatusCode(ProcessStatus.ProcessStatusCode.Cancelled); + status.addMessage("Cancelled"); + } else if (handle.isDone()) { + Object result = null; + try { + result = handle.getResult(); + } catch (InterruptedException e) { + // The process was forcefully cancelled + status.setStatusCode(ProcessStatus.ProcessStatusCode.Failed); + status.addMessage(e.getMessage()); + } catch (ExecutionException e) { + // Exception thrown while running the task + status.setStatusCode(ProcessStatus.ProcessStatusCode.Failed); + status.addMessage(e.getCause().getMessage()); + } catch (Exception e) { + status.setStatusCode(ProcessStatus.ProcessStatusCode.Failed); + status.addMessage("Unknown exception:" + e.getMessage()); + } + // TODO Need to find a generic way of returning all object types. + if (result != null) { + status.addMessage(result.toString()); + } + } + return status; + } +} diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java index 625ff924d9..cd84ef8825 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java @@ -216,38 +216,7 @@ public ProcessStatus getProcessStatus(String processId) { throw new NotFoundException( "A process was not found for id " + processId); } - ProcessStatus status = new ProcessStatus(); - status.setStatusCode(handle.isDone() ? ProcessStatusCode.Finished - : ProcessStatusCode.Running); - int perComplete = 100; - if (handle.getMaxProgress() > 0) { - perComplete = (int) (handle.getCurrentProgress() * 100 - / handle.getMaxProgress()); - } - status.setPercentageComplete(perComplete); - status.setUrl("" + processId); - if (handle.isDone()) { - Object result = null; - try { - result = handle.getResult(); - } catch (InterruptedException e) { - // The process was forcefully cancelled - status.setStatusCode(ProcessStatusCode.Failed); - status.setMessages(Lists.newArrayList(e.getMessage())); - } catch (ExecutionException e) { - // Exception thrown while running the task - status.setStatusCode(ProcessStatusCode.Failed); - status.setMessages( - Lists.newArrayList(e.getCause().getMessage())); - } - // TODO Need to find a generic way of returning all object types. - // Since the only current - // scenario involves lists of strings, hardcoding to that - if (result != null && result instanceof List) { - status.getMessages().addAll((List) result); - } - } - return status; + return AsyncProcessService.handleToProcessStatus(handle, processId); } private HProjectIteration retrieveAndCheckIteration(String projectSlug, diff --git a/server/zanata-war/src/main/java/org/zanata/service/impl/TransMemoryMergeServiceImpl.java b/server/zanata-war/src/main/java/org/zanata/service/impl/TransMemoryMergeServiceImpl.java index fff7ec32c8..10bc5a2094 100644 --- a/server/zanata-war/src/main/java/org/zanata/service/impl/TransMemoryMergeServiceImpl.java +++ b/server/zanata-war/src/main/java/org/zanata/service/impl/TransMemoryMergeServiceImpl.java @@ -137,7 +137,7 @@ public List executeMerge( startTime, authenticatedAccount.getUsername(), request.editorClientId, request.documentId, total)); - asyncTaskHandle.setTotalTextFlows(total); + asyncTaskHandle.setMaxProgress(total); asyncTaskHandle.setTMMergeTarget(request.projectIterationId, request.documentId, request.localeId); @@ -155,7 +155,7 @@ public List executeMerge( UNTRANSLATED_FILTER, index, BATCH_SIZE); int processedSize = textFlowsBatch.size(); index = index + processedSize; - asyncTaskHandle.setTextFlowFilled(index); + asyncTaskHandle.increaseProgress(processedSize); List batchResult = translateInBatch(request, textFlowsBatch, targetLocale); @@ -163,7 +163,7 @@ public List executeMerge( log.debug("TM merge handle: {}", asyncTaskHandle); transMemoryMergeProgressEvent .fire(new TransMemoryMergeProgressEvent(workspaceId, total, - asyncTaskHandle.getTextFlowFilled(), + asyncTaskHandle.getCurrentProgress(), request.editorClientId, request.documentId)); } } catch (Exception e) { From 949f3d6cce3aef8c1bb8808c66f068b75825f824 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Fri, 16 Jun 2017 14:28:53 +1000 Subject: [PATCH 011/116] ZNTA-2057 - fix issues and use object as key --- .../org/zanata/action/CopyTransManager.java | 23 +++--- .../org/zanata/action/CopyVersionManager.java | 16 +++- .../action/MergeTranslationsManager.java | 16 +++- .../action/TranslationMemoryAction.java | 15 +++- .../zanata/async/AsyncTaskHandleManager.java | 77 +++++++------------ .../service/TransMemoryMergeManager.java | 16 ++-- .../rest/service/AsyncProcessService.java | 4 +- .../AsynchronousProcessResourceService.java | 20 ++--- .../server/rpc/DownloadAllFilesHandler.java | 8 +- 9 files changed, 104 insertions(+), 91 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java b/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java index dce02294c4..6609613819 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java @@ -21,7 +21,7 @@ package org.zanata.action; import java.io.Serializable; -import java.util.List; +import java.util.Objects; import javax.annotation.Nonnull; import javax.enterprise.context.Dependent; @@ -36,8 +36,6 @@ import org.zanata.security.ZanataIdentity; import org.zanata.service.CopyTransService; -import com.google.common.base.Preconditions; - import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; // TODO This class should be merged with the copy trans service (?) @@ -207,13 +205,18 @@ public String id() { } @Override - public CopyTransProcessKey from(String id) { - List parts = parseId(id, KEY_NAME, 3); - CopyTransProcessKey key = new CopyTransProcessKey(); - key.projectSlug = parts.get(0); - key.iterationSlug = parts.get(1); - key.docId = parts.get(2); - return key; + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CopyTransProcessKey that = (CopyTransProcessKey) o; + return Objects.equals(projectSlug, that.projectSlug) && + Objects.equals(iterationSlug, that.iterationSlug) && + Objects.equals(docId, that.docId); + } + + @Override + public int hashCode() { + return Objects.hash(projectSlug, iterationSlug, docId); } } } diff --git a/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java b/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java index ae9a6d7795..f597eb1521 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java @@ -1,7 +1,7 @@ package org.zanata.action; import java.io.Serializable; -import java.util.List; +import java.util.Objects; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import javax.enterprise.context.Dependent; @@ -128,9 +128,17 @@ public String id() { } @Override - public CopyVersionKey from(String id) { - List parts = parseId(id, KEY_NAME, 2); - return getKey(parts.get(0), parts.get(1)); + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CopyVersionKey that = (CopyVersionKey) o; + return Objects.equals(projectSlug, that.projectSlug) && + Objects.equals(versionSlug, that.versionSlug); + } + + @Override + public int hashCode() { + return Objects.hash(projectSlug, versionSlug); } } } diff --git a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java index d49960b7aa..f77f16742a 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java @@ -1,7 +1,7 @@ package org.zanata.action; import java.io.Serializable; -import java.util.List; +import java.util.Objects; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import javax.enterprise.context.Dependent; @@ -129,9 +129,17 @@ public String id() { } @Override - public MergeVersionKey from(String id) { - List parts = parseId(id, KEY_NAME, 2); - return getKey(parts.get(0), parts.get(1)); + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MergeVersionKey that = (MergeVersionKey) o; + return Objects.equals(projectSlug, that.projectSlug) && + Objects.equals(versionSlug, that.versionSlug); + } + + @Override + public int hashCode() { + return Objects.hash(projectSlug, versionSlug); } } } diff --git a/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java b/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java index e5faaf5651..8cd597bfa9 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java +++ b/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java @@ -22,9 +22,9 @@ import static javax.faces.application.FacesMessage.SEVERITY_ERROR; import java.io.Serializable; -import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.Objects; import java.util.concurrent.ExecutionException; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import javax.enterprise.inject.Model; @@ -215,9 +215,16 @@ public String id() { } @Override - public ClearTransMemoryProcessKey from(String id) { - List parts = parseId(id, KEY_NAME, 1); - return new ClearTransMemoryProcessKey(parts.get(0)); + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ClearTransMemoryProcessKey that = (ClearTransMemoryProcessKey) o; + return Objects.equals(slug, that.slug); + } + + @Override + public int hashCode() { + return Objects.hash(slug); } } diff --git a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java index 906d784ce4..15f69785b3 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java +++ b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java @@ -22,7 +22,6 @@ import java.io.Serializable; import java.util.Collection; -import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -30,8 +29,6 @@ import javax.inject.Named; import com.google.common.base.Joiner; -import com.google.common.base.Preconditions; -import com.google.common.base.Splitter; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.collect.ImmutableMap; @@ -47,23 +44,22 @@ @javax.enterprise.context.ApplicationScoped public class AsyncTaskHandleManager implements Serializable { - // TODO refactor the key to be something more useful. e.g. an interface Key with method String id for querying purpose @SuppressFBWarnings(value = "SE_BAD_FIELD") - private final Map handlesByKey = Maps + private final Map handlesByKey = Maps .newConcurrentMap(); // Cache of recently completed tasks - private Cache finishedTasks = CacheBuilder + private Cache finishedTasks = CacheBuilder .newBuilder().expireAfterWrite(10, TimeUnit.MINUTES) .build(); public synchronized > void registerTaskHandle(AsyncTaskHandle handle, K key) { - if (handlesByKey.containsKey(key.id())) { + if (handlesByKey.containsKey(key)) { throw new RuntimeException("Task handle with key " + key + " already exists"); } - handlesByKey.put(key.id(), handle); + handlesByKey.put(key, handle); } /** @@ -71,17 +67,17 @@ public synchronized > void registerTaskHandle(AsyncTas * @param handle The handle to register. * @return An auto generated key to retreive the handle later */ - public synchronized Serializable registerTaskHandle(AsyncTaskHandle handle) { + public synchronized AsyncTaskKey registerTaskHandle(AsyncTaskHandle handle) { String autoGenKey = UUID.randomUUID().toString(); - AsyncTaskKey autoKey = key -> autoGenKey; + AsyncTaskKey autoKey = () -> autoGenKey; registerTaskHandle(handle, autoKey); - return autoGenKey; + return autoKey; } void taskFinished(AsyncTaskHandle taskHandle) { synchronized (handlesByKey) { // TODO This operation is O(n). Maybe we can do better? - for (Map.Entry entry : handlesByKey + for (Map.Entry entry : handlesByKey .entrySet()) { if (entry.getValue().equals(taskHandle)) { handlesByKey.remove(entry.getKey()); @@ -92,17 +88,27 @@ void taskFinished(AsyncTaskHandle taskHandle) { } public > AsyncTaskHandle getHandleByKey(K key) { - if (handlesByKey.containsKey(key.id())) { - return handlesByKey.get(key.id()); + if (handlesByKey.containsKey(key)) { + return handlesByKey.get(key); } return finishedTasks.getIfPresent(key.id()); } public AsyncTaskHandle getHandleByKeyId(String keyId) { - if (handlesByKey.containsKey(keyId)) { - return handlesByKey.get(keyId); + // TODO this is O(n) can we do better? + for (Map.Entry entry : handlesByKey + .entrySet()) { + if (entry.getKey().id().equals(keyId)) { + return entry.getValue(); + } + } + for (Map.Entry entry : finishedTasks + .asMap().entrySet()) { + if (entry.getKey().id().equals(keyId)) { + return entry.getValue(); + } } - return finishedTasks.getIfPresent(keyId); + return null; } public Collection getAllHandles() { @@ -112,50 +118,25 @@ public Collection getAllHandles() { return handles; } - public Map getAllTasks() { - ImmutableMap.Builder builder = ImmutableMap.builder(); + public Map getAllTasks() { + ImmutableMap.Builder builder = ImmutableMap.builder(); builder.putAll(handlesByKey); builder.putAll(finishedTasks.asMap()); return builder.build(); } - public Map getRunningTasks() { + public Map getRunningTasks() { return ImmutableMap.copyOf(handlesByKey); } public interface AsyncTaskKey extends Serializable { /** - * When converting multiple fields to form id string or vice versa, we - * should use this as separator. + * When converting multiple fields to form id string, we + * should use this as separator (URL friendly). */ String SEPARATOR = "-"; - default String id() { - return UUID.randomUUID().toString(); - } - - T from(String id); - - /** - * Helper method to convert id back to a list of fields. - * - * @param id - * the id - * @param keyName - * the name for this key - * @param expectedNumOfFields - * number of fields embedded in the id - * @return list of fields - */ - default List parseId(String id, String keyName, - int expectedNumOfFields) { - String fields = id.replaceFirst(keyName + SEPARATOR, id); - List result = - Splitter.on(SEPARATOR).trimResults().splitToList(fields); - Preconditions.checkArgument(expectedNumOfFields == result.size(), - "%s for %s is invalid", id, keyName); - return result; - } + String id(); /** * Helper method to convert list of fields to a String as key id. diff --git a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java index 7567ef59e4..7e6eebbb9a 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java @@ -21,7 +21,6 @@ package org.zanata.rest.editor.service; import java.io.Serializable; -import java.util.List; import java.util.Objects; import javax.enterprise.context.Dependent; @@ -137,10 +136,17 @@ public String id() { } @Override - public TMMergeForDocTaskKey from(String id) { - List parts = parseId(id, KEY_NAME, 2); - return new TMMergeForDocTaskKey(Long.parseLong(parts.get(0)), - new LocaleId(parts.get(1))); + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + TMMergeForDocTaskKey that = (TMMergeForDocTaskKey) o; + return Objects.equals(documentId, that.documentId) && + Objects.equals(localeId, that.localeId); + } + + @Override + public int hashCode() { + return Objects.hash(documentId, localeId); } } } diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java index c7877c7bdd..4a7eeda33b 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java @@ -107,7 +107,7 @@ public Response getAsyncProcessStatus(@PathParam("key") String keyId) { @GET public Response getAllAsyncProcess( @QueryParam("includeFinished") @DefaultValue("false") boolean includeFinished) { - Map tasks; + Map tasks; if (includeFinished) { tasks = asyncTaskHandleManager.getAllTasks(); } else { @@ -116,7 +116,7 @@ public Response getAllAsyncProcess( List processStatuses = tasks.entrySet().stream() .map(taskEntry -> handleToProcessStatus(taskEntry.getValue(), uriInfo.getBaseUri().toString() + "process/key/" - + taskEntry.getKey())) + + taskEntry.getKey().id())) .collect(Collectors.toList()); return Response.ok(processStatuses).build(); } diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java index cd84ef8825..9c4f4cdfde 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java @@ -113,12 +113,12 @@ public ProcessStatus startSourceDocCreation(final String idNoSlash, String name = "SourceDocCreation: " + projectSlug + "-" + iterationSlug + "-" + idNoSlash; AsyncTaskHandle handle = new AsyncTaskHandle(); - Serializable taskId = asyncTaskHandleManager.registerTaskHandle(handle); + AsyncTaskHandleManager.AsyncTaskKey taskKey = asyncTaskHandleManager.registerTaskHandle(handle); documentServiceImpl .saveDocumentAsync(projectSlug, iterationSlug, resource, extensions, copytrans, true, handle); - logWhenUploadComplete(handle, name, taskId); - return getProcessStatus(taskId.toString()); // TODO Change to return 202 + logWhenUploadComplete(handle, name, taskKey.id()); + return getProcessStatus(taskKey.id()); // TODO Change to return 202 // Accepted, // with a url to get the // progress @@ -137,12 +137,12 @@ public ProcessStatus startSourceDocCreationOrUpdate(final String idNoSlash, String name = "SourceDocCreationOrUpdate: " + projectSlug + "-" + iterationSlug + "-" + idNoSlash; AsyncTaskHandle handle = new AsyncTaskHandle(); - Serializable taskId = asyncTaskHandleManager.registerTaskHandle(handle); + AsyncTaskHandleManager.AsyncTaskKey taskKey = asyncTaskHandleManager.registerTaskHandle(handle); documentServiceImpl .saveDocumentAsync(projectSlug, iterationSlug, resource, extensions, copytrans, true, handle); - logWhenUploadComplete(handle, name, taskId); - return getProcessStatus(taskId.toString()); // TODO Change to return 202 + logWhenUploadComplete(handle, name, taskKey.id()); + return getProcessStatus(taskKey.id()); // TODO Change to return 202 // Accepted, // with a url to get the // progress @@ -150,7 +150,7 @@ public ProcessStatus startSourceDocCreationOrUpdate(final String idNoSlash, private void logWhenUploadComplete( AsyncTaskHandle taskHandle, - final String taskName, final Serializable taskId) { + final String taskName, final String taskId) { taskHandle.whenTaskComplete((result, throwable) -> { if (throwable != null) { log.warn("async upload failed. id={}, job={}", taskId, taskName, @@ -199,13 +199,13 @@ public ProcessStatus startTranslatedDocCreationOrUpdate( final MergeType finalMergeType = mergeType; String taskName = "TranslatedDocUpload: "+projectSlug+"-"+iterationSlug+"-"+idNoSlash; AsyncTaskHandle handle = new AsyncTaskHandle(); - Serializable taskId = asyncTaskHandleManager.registerTaskHandle(handle); + AsyncTaskHandleManager.AsyncTaskKey taskKey = asyncTaskHandleManager.registerTaskHandle(handle); translationServiceImpl.translateAllInDocAsync(projectSlug, iterationSlug, id, locale, translatedDoc, extensions, finalMergeType, assignCreditToUploader, true, handle, TranslationSourceType.API_UPLOAD); - logWhenUploadComplete(handle, taskName, taskId); - return this.getProcessStatus(taskId.toString()); + logWhenUploadComplete(handle, taskName, taskKey.id()); + return this.getProcessStatus(taskKey.id()); } @Override diff --git a/server/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/DownloadAllFilesHandler.java b/server/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/DownloadAllFilesHandler.java index cfc1b56e98..16d695bf59 100644 --- a/server/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/DownloadAllFilesHandler.java +++ b/server/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/DownloadAllFilesHandler.java @@ -27,6 +27,8 @@ import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.inject.Named; + +import org.zanata.async.AsyncTask; import org.zanata.async.AsyncTaskHandle; import org.zanata.async.AsyncTaskHandleManager; import org.zanata.dao.ProjectIterationDAO; @@ -72,7 +74,7 @@ public DownloadAllFilesResult execute(DownloadAllFilesAction action, action.getVersionSlug()); if (identity.hasPermission(version, "download-all")) { AsyncTaskHandle handle = new AsyncTaskHandle(); - Serializable taskKey = + AsyncTaskHandleManager.AsyncTaskKey taskKey = asyncTaskHandleManager.registerTaskHandle(handle); // TODO This should be in a service and share code with the JSF // pages that do the same thing @@ -85,9 +87,7 @@ public DownloadAllFilesResult execute(DownloadAllFilesAction action, throw new ActionException(e); } - // NB Keys are currently strings, but this is tied to the - // implementation - return new DownloadAllFilesResult(true, taskKey.toString()); + return new DownloadAllFilesResult(true, taskKey.id()); } return new DownloadAllFilesResult(false, null); From 635fd270b901ff54b0b8b1c4ff2700dbc3b498fa Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Fri, 16 Jun 2017 14:56:13 +1000 Subject: [PATCH 012/116] ZNTA-2057 add new status case in client --- .../java/org/zanata/client/commands/push/PushCommand.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/client/zanata-client-commands/src/main/java/org/zanata/client/commands/push/PushCommand.java b/client/zanata-client-commands/src/main/java/org/zanata/client/commands/push/PushCommand.java index fc0c3ec288..59d3ced6ad 100644 --- a/client/zanata-client-commands/src/main/java/org/zanata/client/commands/push/PushCommand.java +++ b/client/zanata-client-commands/src/main/java/org/zanata/client/commands/push/PushCommand.java @@ -601,6 +601,10 @@ private void pushSrcDocToServer(final String docUri, final Resource srcDoc, ConsoleUtils .setProgressFeedbackMessage("Waiting for other clients ..."); break; + case Cancelled: + waitForCompletion = false; + ConsoleUtils.setProgressFeedbackMessage("Process is cancelled"); + break; } // Wait before retrying @@ -725,6 +729,10 @@ extensions, getOpts().getMergeType(), ConsoleUtils .setProgressFeedbackMessage("Waiting for other clients ..."); break; + case Cancelled: + waitForCompletion = false; + ConsoleUtils.setProgressFeedbackMessage("Process is cancelled"); + break; } // Wait before retrying From 227c5c144aee6647595d59c511e7ab998d82ccb0 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Fri, 16 Jun 2017 16:49:47 +1000 Subject: [PATCH 013/116] ZNTA-2057 - suppress findbugs warning --- .../java/org/zanata/rest/service/AsyncProcessService.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java index 4a7eeda33b..4d3cb5db77 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java @@ -43,6 +43,7 @@ import org.zanata.rest.dto.ProcessStatus; import com.webcohesion.enunciate.metadata.rs.TypeHint; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; /** * This endpoint should let us control and query all async tasks. @@ -61,6 +62,7 @@ public class AsyncProcessService implements RestResource { @Inject private AsyncTaskHandleManager asyncTaskHandleManager; + @SuppressFBWarnings("SE_BAD_FIELD") @Context private UriInfo uriInfo; @@ -77,10 +79,10 @@ public class AsyncProcessService implements RestResource { * INTERNAL SERVER ERROR(500) - If there is an unexpected error in * the server while performing this operation. */ - @Path("key/{key}") + @Path("key/{keyId}") @GET @TypeHint(ProcessStatus.class) - public Response getAsyncProcessStatus(@PathParam("key") String keyId) { + public Response getAsyncProcessStatus(@PathParam("keyId") String keyId) { AsyncTaskHandle handle = asyncTaskHandleManager.getHandleByKeyId(keyId); if (handle == null) { return Response.status(Response.Status.NOT_FOUND).build(); From 717758c4a7abba626a7a9a53f0a693ae50eea6b9 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Mon, 19 Jun 2017 09:39:47 +1000 Subject: [PATCH 014/116] ZNTA-2057 remove unused generic --- .../main/java/org/zanata/action/CopyTransManager.java | 2 +- .../java/org/zanata/action/CopyVersionManager.java | 2 +- .../org/zanata/action/MergeTranslationsManager.java | 2 +- .../org/zanata/action/TranslationMemoryAction.java | 2 +- .../java/org/zanata/async/AsyncTaskHandleManager.java | 10 +++++----- .../rest/editor/service/TransMemoryMergeManager.java | 2 +- .../service/AsynchronousProcessResourceService.java | 10 +++------- .../webtrans/server/rpc/DownloadAllFilesHandler.java | 3 +-- .../editor/service/TransMemoryMergeManagerTest.java | 4 +--- 9 files changed, 15 insertions(+), 22 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java b/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java index 6609613819..12c3a568a7 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java @@ -149,7 +149,7 @@ public void cancelCopyTrans(@Nonnull HProjectIteration iteration) { * Internal class to index Copy Trans processes. */ private static final class CopyTransProcessKey implements - AsyncTaskHandleManager.AsyncTaskKey { + AsyncTaskHandleManager.AsyncTaskKey { private static final long serialVersionUID = -2054359069473618887L; private static final String KEY_NAME = "copyTransKey"; private String projectSlug; diff --git a/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java b/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java index f597eb1521..eb5e33cfd0 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java @@ -87,7 +87,7 @@ public boolean isCopyVersionRunning(String projectSlug, * */ public static final class CopyVersionKey implements - AsyncTaskHandleManager.AsyncTaskKey { + AsyncTaskHandleManager.AsyncTaskKey { private static final String KEY_NAME = "copyVersion"; private static final long serialVersionUID = 3889349239078033373L; // target project identifier diff --git a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java index f77f16742a..83eb53b0a1 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java @@ -96,7 +96,7 @@ public boolean isRunning(String projectSlug, String versionSlug) { * Key used for merge version task */ public static final class MergeVersionKey implements - AsyncTaskHandleManager.AsyncTaskKey { + AsyncTaskHandleManager.AsyncTaskKey { private static final long serialVersionUID = 1L; private static final String KEY_NAME = "mergeVersion"; // target project identifier diff --git a/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java b/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java index 8cd597bfa9..3809bf4259 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java +++ b/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java @@ -199,7 +199,7 @@ public String cancel() { * services that need to control this process. */ private static class ClearTransMemoryProcessKey implements - AsyncTaskHandleManager.AsyncTaskKey { + AsyncTaskHandleManager.AsyncTaskKey { private static final String KEY_NAME = "ClearTMXKey"; private static final long serialVersionUID = 3472355792561903500L; private String slug; diff --git a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java index 15f69785b3..a2e95cd82a 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java +++ b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java @@ -53,7 +53,7 @@ public class AsyncTaskHandleManager implements Serializable { .newBuilder().expireAfterWrite(10, TimeUnit.MINUTES) .build(); - public synchronized > void registerTaskHandle(AsyncTaskHandle handle, + public synchronized void registerTaskHandle(AsyncTaskHandle handle, K key) { if (handlesByKey.containsKey(key)) { throw new RuntimeException("Task handle with key " + key @@ -67,9 +67,9 @@ public synchronized > void registerTaskHandle(AsyncTas * @param handle The handle to register. * @return An auto generated key to retreive the handle later */ - public synchronized AsyncTaskKey registerTaskHandle(AsyncTaskHandle handle) { + public synchronized AsyncTaskKey registerTaskHandle(AsyncTaskHandle handle) { String autoGenKey = UUID.randomUUID().toString(); - AsyncTaskKey autoKey = () -> autoGenKey; + AsyncTaskKey autoKey = () -> autoGenKey; registerTaskHandle(handle, autoKey); return autoKey; } @@ -87,7 +87,7 @@ void taskFinished(AsyncTaskHandle taskHandle) { } } - public > AsyncTaskHandle getHandleByKey(K key) { + public AsyncTaskHandle getHandleByKey(K key) { if (handlesByKey.containsKey(key)) { return handlesByKey.get(key); } @@ -129,7 +129,7 @@ public Map getRunningTasks() { return ImmutableMap.copyOf(handlesByKey); } - public interface AsyncTaskKey extends Serializable { + public interface AsyncTaskKey extends Serializable { /** * When converting multiple fields to form id string, we * should use this as separator (URL friendly). diff --git a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java index 7e6eebbb9a..442a8c13d7 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java @@ -113,7 +113,7 @@ public boolean cancelTransMemoryMerge(TransMemoryMergeCancelRequest request) { } static class TMMergeForDocTaskKey implements - AsyncTaskHandleManager.AsyncTaskKey { + AsyncTaskHandleManager.AsyncTaskKey { private static final long serialVersionUID = -7210004008208642L; private static final String KEY_NAME = "TMMergeForDocKey"; diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java index 9c4f4cdfde..df944c7311 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java @@ -20,10 +20,7 @@ */ package org.zanata.rest.service; -import java.io.Serializable; -import java.util.List; import java.util.Set; -import java.util.concurrent.ExecutionException; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.inject.Named; @@ -48,7 +45,6 @@ import org.zanata.service.DocumentService; import org.zanata.service.LocaleService; import org.zanata.service.TranslationService; -import com.google.common.collect.Lists; import javax.ws.rs.NotFoundException; import javax.ws.rs.Path; @@ -113,7 +109,7 @@ public ProcessStatus startSourceDocCreation(final String idNoSlash, String name = "SourceDocCreation: " + projectSlug + "-" + iterationSlug + "-" + idNoSlash; AsyncTaskHandle handle = new AsyncTaskHandle(); - AsyncTaskHandleManager.AsyncTaskKey taskKey = asyncTaskHandleManager.registerTaskHandle(handle); + AsyncTaskHandleManager.AsyncTaskKey taskKey = asyncTaskHandleManager.registerTaskHandle(handle); documentServiceImpl .saveDocumentAsync(projectSlug, iterationSlug, resource, extensions, copytrans, true, handle); @@ -137,7 +133,7 @@ public ProcessStatus startSourceDocCreationOrUpdate(final String idNoSlash, String name = "SourceDocCreationOrUpdate: " + projectSlug + "-" + iterationSlug + "-" + idNoSlash; AsyncTaskHandle handle = new AsyncTaskHandle(); - AsyncTaskHandleManager.AsyncTaskKey taskKey = asyncTaskHandleManager.registerTaskHandle(handle); + AsyncTaskHandleManager.AsyncTaskKey taskKey = asyncTaskHandleManager.registerTaskHandle(handle); documentServiceImpl .saveDocumentAsync(projectSlug, iterationSlug, resource, extensions, copytrans, true, handle); @@ -199,7 +195,7 @@ public ProcessStatus startTranslatedDocCreationOrUpdate( final MergeType finalMergeType = mergeType; String taskName = "TranslatedDocUpload: "+projectSlug+"-"+iterationSlug+"-"+idNoSlash; AsyncTaskHandle handle = new AsyncTaskHandle(); - AsyncTaskHandleManager.AsyncTaskKey taskKey = asyncTaskHandleManager.registerTaskHandle(handle); + AsyncTaskHandleManager.AsyncTaskKey taskKey = asyncTaskHandleManager.registerTaskHandle(handle); translationServiceImpl.translateAllInDocAsync(projectSlug, iterationSlug, id, locale, translatedDoc, extensions, finalMergeType, assignCreditToUploader, true, handle, diff --git a/server/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/DownloadAllFilesHandler.java b/server/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/DownloadAllFilesHandler.java index 16d695bf59..703a339bd7 100644 --- a/server/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/DownloadAllFilesHandler.java +++ b/server/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/DownloadAllFilesHandler.java @@ -28,7 +28,6 @@ import javax.inject.Inject; import javax.inject.Named; -import org.zanata.async.AsyncTask; import org.zanata.async.AsyncTaskHandle; import org.zanata.async.AsyncTaskHandleManager; import org.zanata.dao.ProjectIterationDAO; @@ -74,7 +73,7 @@ public DownloadAllFilesResult execute(DownloadAllFilesAction action, action.getVersionSlug()); if (identity.hasPermission(version, "download-all")) { AsyncTaskHandle handle = new AsyncTaskHandle(); - AsyncTaskHandleManager.AsyncTaskKey taskKey = + AsyncTaskHandleManager.AsyncTaskKey taskKey = asyncTaskHandleManager.registerTaskHandle(handle); // TODO This should be in a service and share code with the JSF // pages that do the same thing diff --git a/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java b/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java index 6d6e7940fe..83c994fbb9 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java @@ -3,8 +3,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; -import java.io.Serializable; - import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -40,7 +38,7 @@ public class TransMemoryMergeManagerTest { @Captor private ArgumentCaptor handleCaptor; @Captor - private ArgumentCaptor> taskKeyCaptor; + private ArgumentCaptor taskKeyCaptor; private TransMemoryMergeCancelRequest cancelRequest; @Before From 8b4a68d7d755f8e78d49abd752b92b2dfaafa2d4 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Mon, 19 Jun 2017 09:51:11 +1000 Subject: [PATCH 015/116] ZNTA-2057 add interface to task handle to identify triggerer --- .../async/UserTriggerableTaskHandle.java | 31 +++++++++++++++++++ .../async/handle/CopyTransTaskHandle.java | 6 +++- .../async/handle/CopyVersionTaskHandle.java | 6 +++- .../handle/MergeTranslationsTaskHandle.java | 6 +++- .../handle/TransMemoryMergeTaskHandle.java | 6 +++- 5 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 server/zanata-war/src/main/java/org/zanata/async/UserTriggerableTaskHandle.java diff --git a/server/zanata-war/src/main/java/org/zanata/async/UserTriggerableTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/UserTriggerableTaskHandle.java new file mode 100644 index 0000000000..b8993a31b3 --- /dev/null +++ b/server/zanata-war/src/main/java/org/zanata/async/UserTriggerableTaskHandle.java @@ -0,0 +1,31 @@ +/* + * Copyright 2017, 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.async; + +public interface UserTriggerableTaskHandle { + void setTriggeredBy(String username); + + String getTriggeredBy(); + + default boolean canCancel(String currentUser) { + return currentUser.equals(getTriggeredBy()); + } +} diff --git a/server/zanata-war/src/main/java/org/zanata/async/handle/CopyTransTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/handle/CopyTransTaskHandle.java index 87422a836f..98709acea6 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/handle/CopyTransTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/handle/CopyTransTaskHandle.java @@ -21,12 +21,14 @@ package org.zanata.async.handle; import org.zanata.async.AsyncTaskHandle; +import org.zanata.async.UserTriggerableTaskHandle; /** * @author Carlos Munoz * camunoz@redhat.com */ -public class CopyTransTaskHandle extends AsyncTaskHandle { +public class CopyTransTaskHandle extends AsyncTaskHandle implements + UserTriggerableTaskHandle { private String cancelledBy; private long cancelledTime; @@ -53,10 +55,12 @@ public void setCancelledTime(final long cancelledTime) { this.cancelledTime = cancelledTime; } + @Override public String getTriggeredBy() { return this.triggeredBy; } + @Override public void setTriggeredBy(final String triggeredBy) { this.triggeredBy = triggeredBy; } diff --git a/server/zanata-war/src/main/java/org/zanata/async/handle/CopyVersionTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/handle/CopyVersionTaskHandle.java index 0bf388f6f7..ffff868327 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/handle/CopyVersionTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/handle/CopyVersionTaskHandle.java @@ -21,6 +21,7 @@ package org.zanata.async.handle; import org.zanata.async.AsyncTaskHandle; +import org.zanata.async.UserTriggerableTaskHandle; /** * Asynchronous task handle for the copy version process. @@ -28,7 +29,8 @@ * @author Carlos Munoz * camunoz@redhat.com */ -public class CopyVersionTaskHandle extends AsyncTaskHandle { +public class CopyVersionTaskHandle extends AsyncTaskHandle implements + UserTriggerableTaskHandle { private int documentCopied; private int totalDoc; @@ -75,10 +77,12 @@ public void setCancelledTime(final long cancelledTime) { this.cancelledTime = cancelledTime; } + @Override public String getTriggeredBy() { return this.triggeredBy; } + @Override public void setTriggeredBy(final String triggeredBy) { this.triggeredBy = triggeredBy; } diff --git a/server/zanata-war/src/main/java/org/zanata/async/handle/MergeTranslationsTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/handle/MergeTranslationsTaskHandle.java index ec8274470c..b929e9bca5 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/handle/MergeTranslationsTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/handle/MergeTranslationsTaskHandle.java @@ -21,13 +21,15 @@ package org.zanata.async.handle; import org.zanata.async.AsyncTaskHandle; +import org.zanata.async.UserTriggerableTaskHandle; /** * Asynchronous task handle for the merge translations process. * * @author Alex Eng aeng@redhat.com */ -public class MergeTranslationsTaskHandle extends AsyncTaskHandle { +public class MergeTranslationsTaskHandle extends AsyncTaskHandle implements + UserTriggerableTaskHandle { private int totalTranslations; private String cancelledBy; @@ -58,10 +60,12 @@ public void setCancelledTime(final long cancelledTime) { this.cancelledTime = cancelledTime; } + @Override public String getTriggeredBy() { return this.triggeredBy; } + @Override public void setTriggeredBy(final String triggeredBy) { this.triggeredBy = triggeredBy; } diff --git a/server/zanata-war/src/main/java/org/zanata/async/handle/TransMemoryMergeTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/handle/TransMemoryMergeTaskHandle.java index 805ed7076c..063cac014f 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/handle/TransMemoryMergeTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/handle/TransMemoryMergeTaskHandle.java @@ -21,6 +21,7 @@ package org.zanata.async.handle; import org.zanata.async.AsyncTaskHandle; +import org.zanata.async.UserTriggerableTaskHandle; import org.zanata.common.LocaleId; import org.zanata.webtrans.shared.model.DocumentId; import org.zanata.webtrans.shared.model.ProjectIterationId; @@ -30,7 +31,8 @@ /** * @author Patrick Huang pahuang@redhat.com */ -public class TransMemoryMergeTaskHandle extends AsyncTaskHandle { +public class TransMemoryMergeTaskHandle extends AsyncTaskHandle implements + UserTriggerableTaskHandle { private String cancelledBy; private Long cancelledTime; private String triggeredBy; @@ -53,10 +55,12 @@ public void setCancelledTime(final long cancelledTime) { this.cancelledTime = cancelledTime; } + @Override public String getTriggeredBy() { return this.triggeredBy; } + @Override public void setTriggeredBy(final String triggeredBy) { this.triggeredBy = triggeredBy; } From 82fe345ae6382062a0439d8b4adf189196de57ca Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Mon, 19 Jun 2017 10:40:33 +1000 Subject: [PATCH 016/116] ZNTA-2057 add cancel to async REST api --- .../org/zanata/async/AsyncTaskHandle.java | 18 +++++++ .../async/handle/CopyTransTaskHandle.java | 18 ------- .../async/handle/CopyVersionTaskHandle.java | 18 ------- .../handle/MergeTranslationsTaskHandle.java | 18 ------- .../handle/TransMemoryMergeTaskHandle.java | 23 +-------- .../rest/service/AsyncProcessService.java | 51 ++++++++++++++++++- 6 files changed, 70 insertions(+), 76 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java index 42907c7470..c11f933cce 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java @@ -46,6 +46,8 @@ public class AsyncTaskHandle implements Serializable { public long currentProgress = 0; private long startTime = -1; private long finishTime = -1; + private String cancelledBy; + private long cancelledTime; public long increaseProgress(long increaseBy) { currentProgress += increaseBy; @@ -186,4 +188,20 @@ public long getFinishTime() { public void whenTaskComplete(BiConsumer action) { futureResult = futureResult.whenComplete(action); } + + public String getCancelledBy() { + return this.cancelledBy; + } + + public void setCancelledBy(final String cancelledBy) { + this.cancelledBy = cancelledBy; + } + + public long getCancelledTime() { + return this.cancelledTime; + } + + public void setCancelledTime(final long cancelledTime) { + this.cancelledTime = cancelledTime; + } } diff --git a/server/zanata-war/src/main/java/org/zanata/async/handle/CopyTransTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/handle/CopyTransTaskHandle.java index 98709acea6..3fd44b97b8 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/handle/CopyTransTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/handle/CopyTransTaskHandle.java @@ -30,8 +30,6 @@ public class CopyTransTaskHandle extends AsyncTaskHandle implements UserTriggerableTaskHandle { - private String cancelledBy; - private long cancelledTime; private String triggeredBy; private boolean prepared; @@ -39,22 +37,6 @@ public void setPrepared() { this.prepared = true; } - public String getCancelledBy() { - return this.cancelledBy; - } - - public void setCancelledBy(final String cancelledBy) { - this.cancelledBy = cancelledBy; - } - - public long getCancelledTime() { - return this.cancelledTime; - } - - public void setCancelledTime(final long cancelledTime) { - this.cancelledTime = cancelledTime; - } - @Override public String getTriggeredBy() { return this.triggeredBy; diff --git a/server/zanata-war/src/main/java/org/zanata/async/handle/CopyVersionTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/handle/CopyVersionTaskHandle.java index ffff868327..f1ddcc58a7 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/handle/CopyVersionTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/handle/CopyVersionTaskHandle.java @@ -34,8 +34,6 @@ public class CopyVersionTaskHandle extends AsyncTaskHandle implements private int documentCopied; private int totalDoc; - private String cancelledBy; - private long cancelledTime; private String triggeredBy; /** @@ -61,22 +59,6 @@ public void setTotalDoc(final int totalDoc) { this.totalDoc = totalDoc; } - public String getCancelledBy() { - return this.cancelledBy; - } - - public void setCancelledBy(final String cancelledBy) { - this.cancelledBy = cancelledBy; - } - - public long getCancelledTime() { - return this.cancelledTime; - } - - public void setCancelledTime(final long cancelledTime) { - this.cancelledTime = cancelledTime; - } - @Override public String getTriggeredBy() { return this.triggeredBy; diff --git a/server/zanata-war/src/main/java/org/zanata/async/handle/MergeTranslationsTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/handle/MergeTranslationsTaskHandle.java index b929e9bca5..fdd1c815c1 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/handle/MergeTranslationsTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/handle/MergeTranslationsTaskHandle.java @@ -32,8 +32,6 @@ public class MergeTranslationsTaskHandle extends AsyncTaskHandle implement UserTriggerableTaskHandle { private int totalTranslations; - private String cancelledBy; - private long cancelledTime; private String triggeredBy; public int getTotalTranslations() { @@ -44,22 +42,6 @@ public void setTotalTranslations(final int totalTranslations) { this.totalTranslations = totalTranslations; } - public String getCancelledBy() { - return this.cancelledBy; - } - - public void setCancelledBy(final String cancelledBy) { - this.cancelledBy = cancelledBy; - } - - public long getCancelledTime() { - return this.cancelledTime; - } - - public void setCancelledTime(final long cancelledTime) { - this.cancelledTime = cancelledTime; - } - @Override public String getTriggeredBy() { return this.triggeredBy; diff --git a/server/zanata-war/src/main/java/org/zanata/async/handle/TransMemoryMergeTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/handle/TransMemoryMergeTaskHandle.java index 063cac014f..c1fa71a071 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/handle/TransMemoryMergeTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/handle/TransMemoryMergeTaskHandle.java @@ -33,28 +33,9 @@ */ public class TransMemoryMergeTaskHandle extends AsyncTaskHandle implements UserTriggerableTaskHandle { - private String cancelledBy; - private Long cancelledTime; private String triggeredBy; private String mergeTarget; - - public String getCancelledBy() { - return this.cancelledBy; - } - - public void setCancelledBy(final String cancelledBy) { - this.cancelledBy = cancelledBy; - } - - public long getCancelledTime() { - return this.cancelledTime; - } - - public void setCancelledTime(final long cancelledTime) { - this.cancelledTime = cancelledTime; - } - @Override public String getTriggeredBy() { return this.triggeredBy; @@ -78,8 +59,8 @@ public String toString() { .add("mergeTarget", mergeTarget) .add("textFlowFilled", currentProgress) .add("totalTextFlows", maxProgress) - .add("cancelledBy", cancelledBy) - .add("cancelledTime", cancelledTime) + .add("cancelledBy", getTriggeredBy()) + .add("cancelledTime", getCancelledTime()) .add("triggeredBy", triggeredBy) .toString(); } diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java index 4d3cb5db77..419a09f4a3 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java @@ -28,6 +28,7 @@ import javax.inject.Inject; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; +import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; @@ -40,9 +41,13 @@ import org.jetbrains.annotations.NotNull; import org.zanata.async.AsyncTaskHandle; import org.zanata.async.AsyncTaskHandleManager; +import org.zanata.async.UserTriggerableTaskHandle; +import org.zanata.exception.AuthorizationException; import org.zanata.rest.dto.ProcessStatus; +import org.zanata.security.ZanataIdentity; import com.webcohesion.enunciate.metadata.rs.TypeHint; + import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; /** @@ -62,6 +67,9 @@ public class AsyncProcessService implements RestResource { @Inject private AsyncTaskHandleManager asyncTaskHandleManager; + @Inject + private ZanataIdentity identity; + @SuppressFBWarnings("SE_BAD_FIELD") @Context private UriInfo uriInfo; @@ -117,12 +125,53 @@ public Response getAllAsyncProcess( } List processStatuses = tasks.entrySet().stream() .map(taskEntry -> handleToProcessStatus(taskEntry.getValue(), - uriInfo.getBaseUri().toString() + "process/key/" + uriInfo.getBaseUri() + "process/key/" + taskEntry.getKey().id())) .collect(Collectors.toList()); return Response.ok(processStatuses).build(); } + /** + * Cancel a specific async task. + * + * @param keyId + * task id + * + * @return The following response status codes will be returned from this + * operation:
+ * OK(200) - The contents of the response will indicate the process + * identifier which may be used to query for its status or a message + * indicating what happened.
+ * INTERNAL SERVER ERROR(500) - If there is an unexpected error in + * the server while performing this operation. + */ + @POST + @Path("cancel/key/{keyId}") + public Response cancelAsyncProcess(@PathParam("keyId") String keyId) { + AsyncTaskHandle handle = asyncTaskHandleManager.getHandleByKeyId(keyId); + if (handle == null) { + return Response.status(Response.Status.NOT_FOUND).build(); + } + if (handle.isStarted() && !handle.isCancelled() && !handle.isDone()) { + if (!identity.hasRole("admin") && handle instanceof UserTriggerableTaskHandle) { + UserTriggerableTaskHandle taskHandle = + (UserTriggerableTaskHandle) handle; + if (!taskHandle.canCancel(identity.getAccountUsername())) { + throw new AuthorizationException( + "Only the task triggerer or admin can cancel the task."); + } + } + + handle.cancel(true); + handle.setCancelledBy(identity.getAccountUsername()); + handle.setCancelledTime(System.currentTimeMillis()); + + } + ProcessStatus processStatus = handleToProcessStatus(handle, + uriInfo.getBaseUri() + "cancel/key" + keyId); + return Response.ok(processStatus).build(); + } + @NotNull static ProcessStatus handleToProcessStatus(AsyncTaskHandle handle, String url) { From d2f42d2c9059524b6ddc8f696dffdd87fa1298c2 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Mon, 19 Jun 2017 12:34:42 +1000 Subject: [PATCH 017/116] ZNTA-2057 change according to review --- .../zanata/async/AsyncTaskHandleManager.java | 2 +- .../async/UserTriggerableTaskHandle.java | 7 +- .../handle/TransMemoryMergeTaskHandle.java | 6 +- .../rest/service/AsyncProcessService.java | 76 ++++++++++++++----- 4 files changed, 65 insertions(+), 26 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java index a2e95cd82a..b3cecd95b7 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java +++ b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java @@ -91,7 +91,7 @@ public AsyncTaskHandle getHandleByKey(K key) { if (handlesByKey.containsKey(key)) { return handlesByKey.get(key); } - return finishedTasks.getIfPresent(key.id()); + return finishedTasks.getIfPresent(key); } public AsyncTaskHandle getHandleByKeyId(String keyId) { diff --git a/server/zanata-war/src/main/java/org/zanata/async/UserTriggerableTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/UserTriggerableTaskHandle.java index b8993a31b3..92f50e8530 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/UserTriggerableTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/UserTriggerableTaskHandle.java @@ -20,12 +20,15 @@ */ package org.zanata.async; +import org.zanata.security.ZanataIdentity; + public interface UserTriggerableTaskHandle { void setTriggeredBy(String username); String getTriggeredBy(); - default boolean canCancel(String currentUser) { - return currentUser.equals(getTriggeredBy()); + default boolean canCancel(ZanataIdentity identity) { + return identity != null && (identity.hasRole("admin") + || getTriggeredBy().equals(identity.getAccountUsername())); } } diff --git a/server/zanata-war/src/main/java/org/zanata/async/handle/TransMemoryMergeTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/handle/TransMemoryMergeTaskHandle.java index c1fa71a071..9703059dcd 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/handle/TransMemoryMergeTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/handle/TransMemoryMergeTaskHandle.java @@ -57,10 +57,8 @@ public String toString() { return MoreObjects.toStringHelper(this) .omitNullValues() .add("mergeTarget", mergeTarget) - .add("textFlowFilled", currentProgress) - .add("totalTextFlows", maxProgress) - .add("cancelledBy", getTriggeredBy()) - .add("cancelledTime", getCancelledTime()) + .add("currentProgress", currentProgress) + .add("maxProgress", maxProgress) .add("triggeredBy", triggeredBy) .toString(); } diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java index 419a09f4a3..aea7440c99 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java @@ -44,8 +44,13 @@ import org.zanata.async.UserTriggerableTaskHandle; import org.zanata.exception.AuthorizationException; import org.zanata.rest.dto.ProcessStatus; +import org.zanata.rest.editor.service.SuggestionsService; import org.zanata.security.ZanataIdentity; +import org.zanata.security.annotations.CheckRole; +import org.zanata.webtrans.shared.rest.dto.TransMemoryMergeCancelRequest; +import org.zanata.webtrans.shared.rest.dto.TransMemoryMergeRequest; +import com.google.common.annotations.VisibleForTesting; import com.webcohesion.enunciate.metadata.rs.TypeHint; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -54,8 +59,12 @@ * This endpoint should let us control and query all async tasks. * * TODO AsynchronousProcessResourceService are specific for CLI push and pull + * TODO org.zanata.rest.editor.service.SuggestionsService has specific methods for TM merge * * @see AsynchronousProcessResourceService + * @see SuggestionsService#merge(TransMemoryMergeRequest) + * @see SuggestionsService#cancelMerge(TransMemoryMergeCancelRequest) + * * @author Patrick Huang * pahuang@redhat.com */ @@ -74,6 +83,19 @@ public class AsyncProcessService implements RestResource { @Context private UriInfo uriInfo; + public AsyncProcessService() { + } + + // UriInfo can not be injected via constructor injection + @VisibleForTesting + AsyncProcessService(AsyncTaskHandleManager taskHandleManager, + ZanataIdentity identity, UriInfo uriInfo) { + asyncTaskHandleManager = taskHandleManager; + this.identity = identity; + this.uriInfo = uriInfo; + } + + /** * Get an async task's status. * @@ -101,7 +123,7 @@ public Response getAsyncProcessStatus(@PathParam("keyId") String keyId) { } /** - * Get all async task's status. + * Get statuses for all async tasks. This is for admin only. * * @param includeFinished * whether to include finished tasks @@ -115,7 +137,8 @@ public Response getAsyncProcessStatus(@PathParam("keyId") String keyId) { * the server while performing this operation. */ @GET - public Response getAllAsyncProcess( + @CheckRole("admin") + public Response getAllAsyncProcessStatuses( @QueryParam("includeFinished") @DefaultValue("false") boolean includeFinished) { Map tasks; if (includeFinished) { @@ -152,26 +175,41 @@ public Response cancelAsyncProcess(@PathParam("keyId") String keyId) { if (handle == null) { return Response.status(Response.Status.NOT_FOUND).build(); } - if (handle.isStarted() && !handle.isCancelled() && !handle.isDone()) { - if (!identity.hasRole("admin") && handle instanceof UserTriggerableTaskHandle) { - UserTriggerableTaskHandle taskHandle = - (UserTriggerableTaskHandle) handle; - if (!taskHandle.canCancel(identity.getAccountUsername())) { - throw new AuthorizationException( - "Only the task triggerer or admin can cancel the task."); - } - } - handle.cancel(true); - handle.setCancelledBy(identity.getAccountUsername()); - handle.setCancelledTime(System.currentTimeMillis()); + if (!taskIsRunning(handle)) { + ProcessStatus entity = handleToProcessStatus(handle, + uriInfo.getBaseUri() + "process/key/" + keyId); + return Response.ok(entity).build(); + } + if (handle instanceof UserTriggerableTaskHandle) { + UserTriggerableTaskHandle taskHandle = + (UserTriggerableTaskHandle) handle; + if (!taskHandle.canCancel(identity)) { + throw new AuthorizationException( + "Only the task owner or admin can cancel the task:" + keyId); + } + } else { + // for other type of async task, we consider them as system tasks + if (!identity.hasRole("admin")) { + throw new AuthorizationException( + "Only admin can cancel the task:" + keyId); + } } + + handle.cancel(true); + handle.setCancelledBy(identity.getAccountUsername()); + handle.setCancelledTime(System.currentTimeMillis()); + ProcessStatus processStatus = handleToProcessStatus(handle, - uriInfo.getBaseUri() + "cancel/key" + keyId); + uriInfo.getBaseUri() + "process/cancel/key/" + keyId); return Response.ok(processStatus).build(); } + private static boolean taskIsRunning(AsyncTaskHandle handle) { + return handle.isStarted() && !handle.isCancelled() && !handle.isDone(); + } + @NotNull static ProcessStatus handleToProcessStatus(AsyncTaskHandle handle, String url) { @@ -179,16 +217,16 @@ static ProcessStatus handleToProcessStatus(AsyncTaskHandle handle, status.setStatusCode( handle.isDone() ? ProcessStatus.ProcessStatusCode.Finished : ProcessStatus.ProcessStatusCode.Running); - int perComplete = 100; + int percentComplete = 100; if (handle.getMaxProgress() > 0) { - perComplete = (int) (handle.getCurrentProgress() * 100 + percentComplete = (int) (handle.getCurrentProgress() * 100 / handle.getMaxProgress()); } - status.setPercentageComplete(perComplete); + status.setPercentageComplete(percentComplete); status.setUrl(url); if (handle.isCancelled()) { status.setStatusCode(ProcessStatus.ProcessStatusCode.Cancelled); - status.addMessage("Cancelled"); + status.addMessage("Cancelled by " + handle.getCancelledBy()); } else if (handle.isDone()) { Object result = null; try { From ddc82d3fc6a6c5c60144faa09e7fc5243bdbf23e Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Mon, 19 Jun 2017 14:38:08 +1000 Subject: [PATCH 018/116] ZNTA-2057 add unit test to new async API --- .../org/zanata/async/AsyncTaskHandle.java | 4 +- .../rest/service/AsyncProcessServiceTest.java | 297 ++++++++++++++++++ 2 files changed, 299 insertions(+), 2 deletions(-) create mode 100644 server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java diff --git a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java index c11f933cce..4ada662ee6 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java @@ -54,7 +54,7 @@ public long increaseProgress(long increaseBy) { return currentProgress; } - void startTiming() { + protected void startTiming() { startTime = System.currentTimeMillis(); } @@ -148,7 +148,7 @@ public long getTimeSinceFinish() { } } - void setFutureResult(final CompletableFuture futureResult) { + protected void setFutureResult(final CompletableFuture futureResult) { this.futureResult = futureResult; } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java b/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java new file mode 100644 index 0000000000..b56d88a437 --- /dev/null +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java @@ -0,0 +1,297 @@ +/* + * Copyright 2017, 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.service; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.when; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.zanata.async.AsyncTaskHandle; +import org.zanata.async.AsyncTaskHandleManager; +import org.zanata.async.UserTriggerableTaskHandle; +import org.zanata.exception.AuthorizationException; +import org.zanata.rest.dto.ProcessStatus; +import org.zanata.security.ZanataIdentity; + +import com.google.common.collect.Maps; + +public class AsyncProcessServiceTest { + + private AsyncProcessService service; + @Mock + private UriInfo urlInfo; + @Mock + private AsyncTaskHandleManager taskHandleManager; + @Mock + private ZanataIdentity identity; + private String baseUriStr; + private String currentUsername; + + @Before + public void setUp() throws URISyntaxException { + MockitoAnnotations.initMocks(this); + service = new AsyncProcessService(taskHandleManager, identity, urlInfo); + this.baseUriStr = "http://localhost/rest/"; + currentUsername = "test-user"; + when(identity.getAccountUsername()).thenReturn(currentUsername); + } + + @Test + public void returnNotFoundIfProcessTaskIdCanNotBeFound() { + Response response = service.getAsyncProcessStatus("notFoundId"); + + assertThat(response.getStatus()).isEqualTo(404); + } + + @Test + public void canReturnSingleProcessStatus() throws URISyntaxException { + AsyncTaskHandle taskHandle = new AsyncTaskHandle(); + taskHandle.setMaxProgress(100L); + taskHandle.increaseProgress(90); + + when(taskHandleManager.getHandleByKeyId("id")).thenReturn(taskHandle); + when(urlInfo.getRequestUri()) + .thenReturn(new URI(baseUriStr + "process/id")); + Response response = service.getAsyncProcessStatus("id"); + + assertThat(response.getStatus()).isEqualTo(200); + ProcessStatus processStatus = (ProcessStatus) response.getEntity(); + assertThat(processStatus.getPercentageComplete()).isEqualTo(90); + + } + + @Test + public void canGetAllRunningTasks() throws URISyntaxException { + when(urlInfo.getBaseUri()).thenReturn(new URI(baseUriStr)); + + Map runningTasks = + Maps.newHashMap(); + + AsyncTaskHandleManager.AsyncTaskKey key = () -> "keyId"; + AsyncTaskHandle taskHandle = new AsyncTaskHandle(); + runningTasks.put(key, taskHandle); + + when(taskHandleManager.getRunningTasks()).thenReturn(runningTasks); + Response response = service.getAllAsyncProcessStatuses(false); + + assertThat(response.getStatus()).isEqualTo(200); + List statusList = + (List) response.getEntity(); + assertThat(statusList).hasSize(1); + assertThat(statusList.get(0).getUrl()) + .isEqualTo(baseUriStr + "process/key/keyId"); + } + + @Test + public void canGetAllTasksIncludingFinishedTask() + throws URISyntaxException { + when(urlInfo.getBaseUri()).thenReturn(new URI(baseUriStr)); + + Map runningTasks = + Maps.newHashMap(); + + AsyncTaskHandleManager.AsyncTaskKey key = () -> "keyId"; + AsyncTaskHandle taskHandle = new AsyncTaskHandle(); + runningTasks.put(key, taskHandle); + + when(taskHandleManager.getAllTasks()).thenReturn(runningTasks); + Response response = service.getAllAsyncProcessStatuses(true); + + assertThat(response.getStatus()).isEqualTo(200); + List statusList = + (List) response.getEntity(); + assertThat(statusList).hasSize(1); + assertThat(statusList.get(0).getUrl()) + .isEqualTo(baseUriStr + "process/key/keyId"); + } + + @Test + public void returnNotFoundIfCancelTaskCanNotBeFound() { + Response response = service.cancelAsyncProcess("notFoundId"); + + assertThat(response.getStatus()).isEqualTo(404); + } + + @Test + public void returnTaskStatusIfTaskIsNotRunning() throws URISyntaxException { + // we have a finished task + AsyncTaskHandle taskHandle = + new FinishedAsyncTaskHandle("result"); + + when(taskHandleManager.getHandleByKeyId("id")).thenReturn(taskHandle); + when(urlInfo.getRequestUri()) + .thenReturn(new URI(baseUriStr + "process/id")); + Response response = service.cancelAsyncProcess("id"); + + assertThat(response.getStatus()).isEqualTo(200); + ProcessStatus processStatus = (ProcessStatus) response.getEntity(); + assertThat(processStatus.getStatusCode()) + .isEqualTo(ProcessStatus.ProcessStatusCode.Finished); + } + + @Test + public void notAdminUserCanNotCancelSystemTask() { + AsyncTaskHandle taskHandle = new StartedAsyncTaskHandle(); + + String keyId = "id"; + when(taskHandleManager.getHandleByKeyId(keyId)).thenReturn(taskHandle); + + assertThatThrownBy(() -> service.cancelAsyncProcess(keyId)) + .isInstanceOf(AuthorizationException.class) + .hasMessage("Only admin can cancel the task:" + keyId); + } + + @Test + public void adminUserCanCancelSystemTask() { + AsyncTaskHandle taskHandle = new StartedAsyncTaskHandle(); + + String keyId = "id"; + when(taskHandleManager.getHandleByKeyId(keyId)).thenReturn(taskHandle); + when(identity.hasRole("admin")).thenReturn(true); + + Response response = service.cancelAsyncProcess(keyId); + + assertThat(response.getStatus()).isEqualTo(200); + ProcessStatus processStatus = (ProcessStatus) response.getEntity(); + assertThat(processStatus.getStatusCode()) + .isEqualTo(ProcessStatus.ProcessStatusCode.Cancelled); + assertThat(processStatus.getMessages()) + .contains("Cancelled by " + currentUsername); + } + + @Test + public void notAdminUserCanNotCancelOthersTask() { + UserTriggeredStartedAsyncTaskHandle taskHandle = + new UserTriggeredStartedAsyncTaskHandle(); + taskHandle.setTriggeredBy("someone-else"); + + String keyId = "id"; + when(taskHandleManager.getHandleByKeyId(keyId)).thenReturn(taskHandle); + + assertThatThrownBy(() -> service.cancelAsyncProcess(keyId)) + .isInstanceOf(AuthorizationException.class) + .hasMessage("Only the task owner or admin can cancel the task:" + + keyId); + } + + @Test + public void adminUserCanCancelOtherUsersTask() { + UserTriggeredStartedAsyncTaskHandle taskHandle = + new UserTriggeredStartedAsyncTaskHandle(); + taskHandle.setTriggeredBy("someone-else"); + + when(identity.hasRole("admin")).thenReturn(true); + String keyId = "id"; + when(taskHandleManager.getHandleByKeyId(keyId)).thenReturn(taskHandle); + + Response response = service.cancelAsyncProcess(keyId); + + assertThat(response.getStatus()).isEqualTo(200); + ProcessStatus processStatus = (ProcessStatus) response.getEntity(); + assertThat(processStatus.getStatusCode()) + .isEqualTo(ProcessStatus.ProcessStatusCode.Cancelled); + assertThat(processStatus.getMessages()) + .contains("Cancelled by " + currentUsername); + } + + @Test + public void sameUserCanCancelHisOwnTask() { + UserTriggeredStartedAsyncTaskHandle taskHandle = + new UserTriggeredStartedAsyncTaskHandle(); + taskHandle.setTriggeredBy(currentUsername); + + when(identity.hasRole("admin")).thenReturn(false); + String keyId = "id"; + when(taskHandleManager.getHandleByKeyId(keyId)).thenReturn(taskHandle); + + Response response = service.cancelAsyncProcess(keyId); + + assertThat(response.getStatus()).isEqualTo(200); + ProcessStatus processStatus = (ProcessStatus) response.getEntity(); + assertThat(processStatus.getStatusCode()) + .isEqualTo(ProcessStatus.ProcessStatusCode.Cancelled); + assertThat(processStatus.getMessages()) + .contains("Cancelled by " + currentUsername); + } + + private static class FinishedAsyncTaskHandle + extends AsyncTaskHandle { + private static final long serialVersionUID = 1L; + + private FinishedAsyncTaskHandle(String result) { + CompletableFuture futureResult = new CompletableFuture<>(); + futureResult.complete(result); + super.setFutureResult(futureResult); + } + } + + private static class StartedAsyncTaskHandle + extends AsyncTaskHandle { + private static final long serialVersionUID = 1L; + private boolean cancelled; + + private StartedAsyncTaskHandle() { + // move the process status to started + startTiming(); + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + this.cancelled = true; + return true; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + } + + private static class UserTriggeredStartedAsyncTaskHandle extends + StartedAsyncTaskHandle implements UserTriggerableTaskHandle { + + private static final long serialVersionUID = 1L; + private String triggerBy; + + @Override + public void setTriggeredBy(String username) { + this.triggerBy = username; + } + + @Override + public String getTriggeredBy() { + return triggerBy; + } + } +} From b1234809731f2e02663499a7945f811183e6414f Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Mon, 19 Jun 2017 15:36:26 +1000 Subject: [PATCH 019/116] ZNTA-2057 fix warnings --- .../zanata/async/AsyncTaskHandleManager.java | 25 ++++++++++--------- .../rest/service/AsyncProcessService.java | 6 ++--- .../rest/service/AsyncProcessServiceTest.java | 24 ++++++++++-------- 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java index b3cecd95b7..29caa4b0b9 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java +++ b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java @@ -43,13 +43,13 @@ @Named("asyncTaskHandleManager") @javax.enterprise.context.ApplicationScoped public class AsyncTaskHandleManager implements Serializable { - + private static final long serialVersionUID = -3209755141964141830L; @SuppressFBWarnings(value = "SE_BAD_FIELD") - private final Map handlesByKey = Maps + private final Map> handlesByKey = Maps .newConcurrentMap(); // Cache of recently completed tasks - private Cache finishedTasks = CacheBuilder + private Cache> finishedTasks = CacheBuilder .newBuilder().expireAfterWrite(10, TimeUnit.MINUTES) .build(); @@ -77,7 +77,7 @@ public synchronized AsyncTaskKey registerTaskHandle(AsyncTaskHandle handle) { void taskFinished(AsyncTaskHandle taskHandle) { synchronized (handlesByKey) { // TODO This operation is O(n). Maybe we can do better? - for (Map.Entry entry : handlesByKey + for (Map.Entry> entry : handlesByKey .entrySet()) { if (entry.getValue().equals(taskHandle)) { handlesByKey.remove(entry.getKey()); @@ -94,18 +94,19 @@ public AsyncTaskHandle getHandleByKey(K key) { return finishedTasks.getIfPresent(key); } - public AsyncTaskHandle getHandleByKeyId(String keyId) { + @SuppressWarnings("unchecked") + public AsyncTaskHandle getHandleByKeyId(String keyId) { // TODO this is O(n) can we do better? - for (Map.Entry entry : handlesByKey + for (Map.Entry> entry : handlesByKey .entrySet()) { if (entry.getKey().id().equals(keyId)) { - return entry.getValue(); + return (AsyncTaskHandle) entry.getValue(); } } - for (Map.Entry entry : finishedTasks + for (Map.Entry> entry : finishedTasks .asMap().entrySet()) { if (entry.getKey().id().equals(keyId)) { - return entry.getValue(); + return (AsyncTaskHandle) entry.getValue(); } } return null; @@ -118,14 +119,14 @@ public Collection getAllHandles() { return handles; } - public Map getAllTasks() { - ImmutableMap.Builder builder = ImmutableMap.builder(); + public Map> getAllTasks() { + ImmutableMap.Builder> builder = ImmutableMap.builder(); builder.putAll(handlesByKey); builder.putAll(finishedTasks.asMap()); return builder.build(); } - public Map getRunningTasks() { + public Map> getRunningTasks() { return ImmutableMap.copyOf(handlesByKey); } diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java index aea7440c99..bda9ad8a5a 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java @@ -113,7 +113,7 @@ public AsyncProcessService() { @GET @TypeHint(ProcessStatus.class) public Response getAsyncProcessStatus(@PathParam("keyId") String keyId) { - AsyncTaskHandle handle = asyncTaskHandleManager.getHandleByKeyId(keyId); + AsyncTaskHandle handle = asyncTaskHandleManager.getHandleByKeyId(keyId); if (handle == null) { return Response.status(Response.Status.NOT_FOUND).build(); } @@ -140,7 +140,7 @@ public Response getAsyncProcessStatus(@PathParam("keyId") String keyId) { @CheckRole("admin") public Response getAllAsyncProcessStatuses( @QueryParam("includeFinished") @DefaultValue("false") boolean includeFinished) { - Map tasks; + Map> tasks; if (includeFinished) { tasks = asyncTaskHandleManager.getAllTasks(); } else { @@ -211,7 +211,7 @@ private static boolean taskIsRunning(AsyncTaskHandle handle) { } @NotNull - static ProcessStatus handleToProcessStatus(AsyncTaskHandle handle, + static ProcessStatus handleToProcessStatus(AsyncTaskHandle handle, String url) { ProcessStatus status = new ProcessStatus(); status.setStatusCode( diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java b/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java index b56d88a437..f16f8372e1 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java @@ -76,7 +76,7 @@ public void returnNotFoundIfProcessTaskIdCanNotBeFound() { @Test public void canReturnSingleProcessStatus() throws URISyntaxException { - AsyncTaskHandle taskHandle = new AsyncTaskHandle(); + AsyncTaskHandle taskHandle = new AsyncTaskHandle<>(); taskHandle.setMaxProgress(100L); taskHandle.increaseProgress(90); @@ -95,17 +95,18 @@ public void canReturnSingleProcessStatus() throws URISyntaxException { public void canGetAllRunningTasks() throws URISyntaxException { when(urlInfo.getBaseUri()).thenReturn(new URI(baseUriStr)); - Map runningTasks = + Map> runningTasks = Maps.newHashMap(); AsyncTaskHandleManager.AsyncTaskKey key = () -> "keyId"; - AsyncTaskHandle taskHandle = new AsyncTaskHandle(); + AsyncTaskHandle taskHandle = new AsyncTaskHandle<>(); runningTasks.put(key, taskHandle); when(taskHandleManager.getRunningTasks()).thenReturn(runningTasks); Response response = service.getAllAsyncProcessStatuses(false); assertThat(response.getStatus()).isEqualTo(200); + @SuppressWarnings("unchecked") List statusList = (List) response.getEntity(); assertThat(statusList).hasSize(1); @@ -118,17 +119,18 @@ public void canGetAllTasksIncludingFinishedTask() throws URISyntaxException { when(urlInfo.getBaseUri()).thenReturn(new URI(baseUriStr)); - Map runningTasks = + Map> runningTasks = Maps.newHashMap(); AsyncTaskHandleManager.AsyncTaskKey key = () -> "keyId"; - AsyncTaskHandle taskHandle = new AsyncTaskHandle(); + AsyncTaskHandle taskHandle = new AsyncTaskHandle<>(); runningTasks.put(key, taskHandle); when(taskHandleManager.getAllTasks()).thenReturn(runningTasks); Response response = service.getAllAsyncProcessStatuses(true); assertThat(response.getStatus()).isEqualTo(200); + @SuppressWarnings("unchecked") List statusList = (List) response.getEntity(); assertThat(statusList).hasSize(1); @@ -146,7 +148,7 @@ public void returnNotFoundIfCancelTaskCanNotBeFound() { @Test public void returnTaskStatusIfTaskIsNotRunning() throws URISyntaxException { // we have a finished task - AsyncTaskHandle taskHandle = + AsyncTaskHandle taskHandle = new FinishedAsyncTaskHandle("result"); when(taskHandleManager.getHandleByKeyId("id")).thenReturn(taskHandle); @@ -162,7 +164,7 @@ public void returnTaskStatusIfTaskIsNotRunning() throws URISyntaxException { @Test public void notAdminUserCanNotCancelSystemTask() { - AsyncTaskHandle taskHandle = new StartedAsyncTaskHandle(); + AsyncTaskHandle taskHandle = new StartedAsyncTaskHandle(); String keyId = "id"; when(taskHandleManager.getHandleByKeyId(keyId)).thenReturn(taskHandle); @@ -174,7 +176,7 @@ public void notAdminUserCanNotCancelSystemTask() { @Test public void adminUserCanCancelSystemTask() { - AsyncTaskHandle taskHandle = new StartedAsyncTaskHandle(); + AsyncTaskHandle taskHandle = new StartedAsyncTaskHandle(); String keyId = "id"; when(taskHandleManager.getHandleByKeyId(keyId)).thenReturn(taskHandle); @@ -246,18 +248,18 @@ public void sameUserCanCancelHisOwnTask() { } private static class FinishedAsyncTaskHandle - extends AsyncTaskHandle { + extends AsyncTaskHandle { private static final long serialVersionUID = 1L; private FinishedAsyncTaskHandle(String result) { - CompletableFuture futureResult = new CompletableFuture<>(); + CompletableFuture futureResult = new CompletableFuture<>(); futureResult.complete(result); super.setFutureResult(futureResult); } } private static class StartedAsyncTaskHandle - extends AsyncTaskHandle { + extends AsyncTaskHandle { private static final long serialVersionUID = 1L; private boolean cancelled; From f2ad622f28e8faed268ed48eaf0cb5db5979bb86 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Mon, 19 Jun 2017 16:35:35 +1000 Subject: [PATCH 020/116] ZNTA-2057 use string as key in async handles map --- .../org/zanata/action/CopyTransManager.java | 15 -------- .../org/zanata/action/CopyVersionManager.java | 14 ------- .../action/MergeTranslationsManager.java | 14 ------- .../action/TranslationMemoryAction.java | 13 ------- .../org/zanata/async/AsyncTaskHandle.java | 4 ++ .../zanata/async/AsyncTaskHandleManager.java | 37 ++++++------------- .../service/TransMemoryMergeManager.java | 14 ------- .../rest/service/AsyncProcessService.java | 10 ++--- .../rest/service/AsyncProcessServiceTest.java | 12 +++--- 9 files changed, 25 insertions(+), 108 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java b/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java index 12c3a568a7..b721e66163 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java @@ -203,20 +203,5 @@ private CopyTransProcessKey() { public String id() { return joinFields(KEY_NAME, projectSlug, iterationSlug, docId); } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - CopyTransProcessKey that = (CopyTransProcessKey) o; - return Objects.equals(projectSlug, that.projectSlug) && - Objects.equals(iterationSlug, that.iterationSlug) && - Objects.equals(docId, that.docId); - } - - @Override - public int hashCode() { - return Objects.hash(projectSlug, iterationSlug, docId); - } } } diff --git a/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java b/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java index eb5e33cfd0..2ddf76138c 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java @@ -126,19 +126,5 @@ public CopyVersionKey(final String projectSlug, public String id() { return joinFields(KEY_NAME, projectSlug, versionSlug); } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - CopyVersionKey that = (CopyVersionKey) o; - return Objects.equals(projectSlug, that.projectSlug) && - Objects.equals(versionSlug, that.versionSlug); - } - - @Override - public int hashCode() { - return Objects.hash(projectSlug, versionSlug); - } } } diff --git a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java index 83eb53b0a1..814147dd1d 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java @@ -127,19 +127,5 @@ public MergeVersionKey(final String projectSlug, final String versionSlug) { public String id() { return joinFields(KEY_NAME, projectSlug, versionSlug); } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - MergeVersionKey that = (MergeVersionKey) o; - return Objects.equals(projectSlug, that.projectSlug) && - Objects.equals(versionSlug, that.versionSlug); - } - - @Override - public int hashCode() { - return Objects.hash(projectSlug, versionSlug); - } } } diff --git a/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java b/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java index 3809bf4259..59d357dcfd 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java +++ b/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java @@ -213,19 +213,6 @@ public ClearTransMemoryProcessKey(final String slug) { public String id() { return joinFields(KEY_NAME, slug); } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ClearTransMemoryProcessKey that = (ClearTransMemoryProcessKey) o; - return Objects.equals(slug, that.slug); - } - - @Override - public int hashCode() { - return Objects.hash(slug); - } } private static class TMComparator implements Comparator, Serializable { diff --git a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java index 4ada662ee6..6117633d20 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java @@ -49,6 +49,10 @@ public class AsyncTaskHandle implements Serializable { private String cancelledBy; private long cancelledTime; + public boolean isRunning() { + return isStarted() && !isCancelled() && !isDone(); + } + public long increaseProgress(long increaseBy) { currentProgress += increaseBy; return currentProgress; diff --git a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java index 29caa4b0b9..0c97247da0 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java +++ b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java @@ -45,21 +45,21 @@ public class AsyncTaskHandleManager implements Serializable { private static final long serialVersionUID = -3209755141964141830L; @SuppressFBWarnings(value = "SE_BAD_FIELD") - private final Map> handlesByKey = Maps + private final Map> handlesByKey = Maps .newConcurrentMap(); // Cache of recently completed tasks - private Cache> finishedTasks = CacheBuilder + private Cache> finishedTasks = CacheBuilder .newBuilder().expireAfterWrite(10, TimeUnit.MINUTES) .build(); public synchronized void registerTaskHandle(AsyncTaskHandle handle, K key) { - if (handlesByKey.containsKey(key)) { + if (handlesByKey.containsKey(key.id())) { throw new RuntimeException("Task handle with key " + key + " already exists"); } - handlesByKey.put(key, handle); + handlesByKey.put(key.id(), handle); } /** @@ -77,7 +77,7 @@ public synchronized AsyncTaskKey registerTaskHandle(AsyncTaskHandle handle) { void taskFinished(AsyncTaskHandle taskHandle) { synchronized (handlesByKey) { // TODO This operation is O(n). Maybe we can do better? - for (Map.Entry> entry : handlesByKey + for (Map.Entry> entry : handlesByKey .entrySet()) { if (entry.getValue().equals(taskHandle)) { handlesByKey.remove(entry.getKey()); @@ -88,28 +88,15 @@ void taskFinished(AsyncTaskHandle taskHandle) { } public AsyncTaskHandle getHandleByKey(K key) { - if (handlesByKey.containsKey(key)) { - return handlesByKey.get(key); - } - return finishedTasks.getIfPresent(key); + return getHandleByKeyId(key.id()); } @SuppressWarnings("unchecked") public AsyncTaskHandle getHandleByKeyId(String keyId) { - // TODO this is O(n) can we do better? - for (Map.Entry> entry : handlesByKey - .entrySet()) { - if (entry.getKey().id().equals(keyId)) { - return (AsyncTaskHandle) entry.getValue(); - } - } - for (Map.Entry> entry : finishedTasks - .asMap().entrySet()) { - if (entry.getKey().id().equals(keyId)) { - return (AsyncTaskHandle) entry.getValue(); - } + if (handlesByKey.containsKey(keyId)) { + return (AsyncTaskHandle) handlesByKey.get(keyId); } - return null; + return (AsyncTaskHandle) finishedTasks.getIfPresent(keyId); } public Collection getAllHandles() { @@ -119,14 +106,14 @@ public Collection getAllHandles() { return handles; } - public Map> getAllTasks() { - ImmutableMap.Builder> builder = ImmutableMap.builder(); + public Map> getAllTasks() { + ImmutableMap.Builder> builder = ImmutableMap.builder(); builder.putAll(handlesByKey); builder.putAll(finishedTasks.asMap()); return builder.build(); } - public Map> getRunningTasks() { + public Map> getRunningTasks() { return ImmutableMap.copyOf(handlesByKey); } diff --git a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java index 442a8c13d7..75e734960a 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java @@ -134,19 +134,5 @@ public String toString() { public String id() { return joinFields(KEY_NAME, documentId.toString(), localeId.getId()); } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - TMMergeForDocTaskKey that = (TMMergeForDocTaskKey) o; - return Objects.equals(documentId, that.documentId) && - Objects.equals(localeId, that.localeId); - } - - @Override - public int hashCode() { - return Objects.hash(documentId, localeId); - } } } diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java index bda9ad8a5a..c1775b5551 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java @@ -140,7 +140,7 @@ public Response getAsyncProcessStatus(@PathParam("keyId") String keyId) { @CheckRole("admin") public Response getAllAsyncProcessStatuses( @QueryParam("includeFinished") @DefaultValue("false") boolean includeFinished) { - Map> tasks; + Map> tasks; if (includeFinished) { tasks = asyncTaskHandleManager.getAllTasks(); } else { @@ -149,7 +149,7 @@ public Response getAllAsyncProcessStatuses( List processStatuses = tasks.entrySet().stream() .map(taskEntry -> handleToProcessStatus(taskEntry.getValue(), uriInfo.getBaseUri() + "process/key/" - + taskEntry.getKey().id())) + + taskEntry.getKey())) .collect(Collectors.toList()); return Response.ok(processStatuses).build(); } @@ -176,7 +176,7 @@ public Response cancelAsyncProcess(@PathParam("keyId") String keyId) { return Response.status(Response.Status.NOT_FOUND).build(); } - if (!taskIsRunning(handle)) { + if (!handle.isRunning()) { ProcessStatus entity = handleToProcessStatus(handle, uriInfo.getBaseUri() + "process/key/" + keyId); return Response.ok(entity).build(); @@ -206,10 +206,6 @@ public Response cancelAsyncProcess(@PathParam("keyId") String keyId) { return Response.ok(processStatus).build(); } - private static boolean taskIsRunning(AsyncTaskHandle handle) { - return handle.isStarted() && !handle.isCancelled() && !handle.isDone(); - } - @NotNull static ProcessStatus handleToProcessStatus(AsyncTaskHandle handle, String url) { diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java b/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java index f16f8372e1..6d995e1b7b 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java @@ -95,12 +95,12 @@ public void canReturnSingleProcessStatus() throws URISyntaxException { public void canGetAllRunningTasks() throws URISyntaxException { when(urlInfo.getBaseUri()).thenReturn(new URI(baseUriStr)); - Map> runningTasks = + Map> runningTasks = Maps.newHashMap(); - AsyncTaskHandleManager.AsyncTaskKey key = () -> "keyId"; + String id = "keyId"; AsyncTaskHandle taskHandle = new AsyncTaskHandle<>(); - runningTasks.put(key, taskHandle); + runningTasks.put(id, taskHandle); when(taskHandleManager.getRunningTasks()).thenReturn(runningTasks); Response response = service.getAllAsyncProcessStatuses(false); @@ -119,12 +119,12 @@ public void canGetAllTasksIncludingFinishedTask() throws URISyntaxException { when(urlInfo.getBaseUri()).thenReturn(new URI(baseUriStr)); - Map> runningTasks = + Map> runningTasks = Maps.newHashMap(); - AsyncTaskHandleManager.AsyncTaskKey key = () -> "keyId"; + String id = "keyId"; AsyncTaskHandle taskHandle = new AsyncTaskHandle<>(); - runningTasks.put(key, taskHandle); + runningTasks.put(id, taskHandle); when(taskHandleManager.getAllTasks()).thenReturn(runningTasks); Response response = service.getAllAsyncProcessStatuses(true); From 7ccff5e7de1e7cb06585bfbdb374410e954e57d5 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Mon, 19 Jun 2017 16:52:41 +1000 Subject: [PATCH 021/116] ZNTA-2057 refactor --- .../zanata/async/AsyncTaskHandleManager.java | 4 ++-- ...andle.java => UserTriggeredTaskHandle.java} | 7 ++++++- .../async/handle/CopyTransTaskHandle.java | 4 ++-- .../async/handle/CopyVersionTaskHandle.java | 4 ++-- .../handle/MergeTranslationsTaskHandle.java | 4 ++-- .../handle/TransMemoryMergeTaskHandle.java | 4 ++-- .../rest/service/AsyncProcessService.java | 8 ++++---- .../AsynchronousProcessResourceService.java | 18 +++++++++--------- .../server/rpc/DownloadAllFilesHandler.java | 4 ++-- .../rest/service/AsyncProcessServiceTest.java | 4 ++-- 10 files changed, 33 insertions(+), 28 deletions(-) rename server/zanata-war/src/main/java/org/zanata/async/{UserTriggerableTaskHandle.java => UserTriggeredTaskHandle.java} (83%) diff --git a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java index 0c97247da0..6095a12f63 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java +++ b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java @@ -67,11 +67,11 @@ public synchronized void registerTaskHandle(AsyncTaskHa * @param handle The handle to register. * @return An auto generated key to retreive the handle later */ - public synchronized AsyncTaskKey registerTaskHandle(AsyncTaskHandle handle) { + public synchronized String registerTaskHandle(AsyncTaskHandle handle) { String autoGenKey = UUID.randomUUID().toString(); AsyncTaskKey autoKey = () -> autoGenKey; registerTaskHandle(handle, autoKey); - return autoKey; + return autoGenKey; } void taskFinished(AsyncTaskHandle taskHandle) { diff --git a/server/zanata-war/src/main/java/org/zanata/async/UserTriggerableTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/UserTriggeredTaskHandle.java similarity index 83% rename from server/zanata-war/src/main/java/org/zanata/async/UserTriggerableTaskHandle.java rename to server/zanata-war/src/main/java/org/zanata/async/UserTriggeredTaskHandle.java index 92f50e8530..61ec2f60f8 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/UserTriggerableTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/UserTriggeredTaskHandle.java @@ -22,7 +22,12 @@ import org.zanata.security.ZanataIdentity; -public interface UserTriggerableTaskHandle { +/** + * Represents a task triggered by a user (as oppose to some system generated + * async tasks). For such tasks, the user takes ownership of this task and is + * allowed to cancel the task. Admin user can cancel any tasks. + */ +public interface UserTriggeredTaskHandle { void setTriggeredBy(String username); String getTriggeredBy(); diff --git a/server/zanata-war/src/main/java/org/zanata/async/handle/CopyTransTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/handle/CopyTransTaskHandle.java index 3fd44b97b8..64f7538588 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/handle/CopyTransTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/handle/CopyTransTaskHandle.java @@ -21,14 +21,14 @@ package org.zanata.async.handle; import org.zanata.async.AsyncTaskHandle; -import org.zanata.async.UserTriggerableTaskHandle; +import org.zanata.async.UserTriggeredTaskHandle; /** * @author Carlos Munoz * camunoz@redhat.com */ public class CopyTransTaskHandle extends AsyncTaskHandle implements - UserTriggerableTaskHandle { + UserTriggeredTaskHandle { private String triggeredBy; private boolean prepared; diff --git a/server/zanata-war/src/main/java/org/zanata/async/handle/CopyVersionTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/handle/CopyVersionTaskHandle.java index f1ddcc58a7..2d1b0882d1 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/handle/CopyVersionTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/handle/CopyVersionTaskHandle.java @@ -21,7 +21,7 @@ package org.zanata.async.handle; import org.zanata.async.AsyncTaskHandle; -import org.zanata.async.UserTriggerableTaskHandle; +import org.zanata.async.UserTriggeredTaskHandle; /** * Asynchronous task handle for the copy version process. @@ -30,7 +30,7 @@ * camunoz@redhat.com */ public class CopyVersionTaskHandle extends AsyncTaskHandle implements - UserTriggerableTaskHandle { + UserTriggeredTaskHandle { private int documentCopied; private int totalDoc; diff --git a/server/zanata-war/src/main/java/org/zanata/async/handle/MergeTranslationsTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/handle/MergeTranslationsTaskHandle.java index fdd1c815c1..ddf294455e 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/handle/MergeTranslationsTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/handle/MergeTranslationsTaskHandle.java @@ -21,7 +21,7 @@ package org.zanata.async.handle; import org.zanata.async.AsyncTaskHandle; -import org.zanata.async.UserTriggerableTaskHandle; +import org.zanata.async.UserTriggeredTaskHandle; /** * Asynchronous task handle for the merge translations process. @@ -29,7 +29,7 @@ * @author Alex Eng aeng@redhat.com */ public class MergeTranslationsTaskHandle extends AsyncTaskHandle implements - UserTriggerableTaskHandle { + UserTriggeredTaskHandle { private int totalTranslations; private String triggeredBy; diff --git a/server/zanata-war/src/main/java/org/zanata/async/handle/TransMemoryMergeTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/handle/TransMemoryMergeTaskHandle.java index 9703059dcd..71e566794c 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/handle/TransMemoryMergeTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/handle/TransMemoryMergeTaskHandle.java @@ -21,7 +21,7 @@ package org.zanata.async.handle; import org.zanata.async.AsyncTaskHandle; -import org.zanata.async.UserTriggerableTaskHandle; +import org.zanata.async.UserTriggeredTaskHandle; import org.zanata.common.LocaleId; import org.zanata.webtrans.shared.model.DocumentId; import org.zanata.webtrans.shared.model.ProjectIterationId; @@ -32,7 +32,7 @@ * @author Patrick Huang pahuang@redhat.com */ public class TransMemoryMergeTaskHandle extends AsyncTaskHandle implements - UserTriggerableTaskHandle { + UserTriggeredTaskHandle { private String triggeredBy; private String mergeTarget; diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java index c1775b5551..383edb7e04 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java @@ -41,7 +41,7 @@ import org.jetbrains.annotations.NotNull; import org.zanata.async.AsyncTaskHandle; import org.zanata.async.AsyncTaskHandleManager; -import org.zanata.async.UserTriggerableTaskHandle; +import org.zanata.async.UserTriggeredTaskHandle; import org.zanata.exception.AuthorizationException; import org.zanata.rest.dto.ProcessStatus; import org.zanata.rest.editor.service.SuggestionsService; @@ -182,9 +182,9 @@ public Response cancelAsyncProcess(@PathParam("keyId") String keyId) { return Response.ok(entity).build(); } - if (handle instanceof UserTriggerableTaskHandle) { - UserTriggerableTaskHandle taskHandle = - (UserTriggerableTaskHandle) handle; + if (handle instanceof UserTriggeredTaskHandle) { + UserTriggeredTaskHandle taskHandle = + (UserTriggeredTaskHandle) handle; if (!taskHandle.canCancel(identity)) { throw new AuthorizationException( "Only the task owner or admin can cancel the task:" + keyId); diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java index df944c7311..11ece3a0ba 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java @@ -109,12 +109,12 @@ public ProcessStatus startSourceDocCreation(final String idNoSlash, String name = "SourceDocCreation: " + projectSlug + "-" + iterationSlug + "-" + idNoSlash; AsyncTaskHandle handle = new AsyncTaskHandle(); - AsyncTaskHandleManager.AsyncTaskKey taskKey = asyncTaskHandleManager.registerTaskHandle(handle); + String keyId = asyncTaskHandleManager.registerTaskHandle(handle); documentServiceImpl .saveDocumentAsync(projectSlug, iterationSlug, resource, extensions, copytrans, true, handle); - logWhenUploadComplete(handle, name, taskKey.id()); - return getProcessStatus(taskKey.id()); // TODO Change to return 202 + logWhenUploadComplete(handle, name, keyId); + return getProcessStatus(keyId); // TODO Change to return 202 // Accepted, // with a url to get the // progress @@ -133,12 +133,12 @@ public ProcessStatus startSourceDocCreationOrUpdate(final String idNoSlash, String name = "SourceDocCreationOrUpdate: " + projectSlug + "-" + iterationSlug + "-" + idNoSlash; AsyncTaskHandle handle = new AsyncTaskHandle(); - AsyncTaskHandleManager.AsyncTaskKey taskKey = asyncTaskHandleManager.registerTaskHandle(handle); + String keyId = asyncTaskHandleManager.registerTaskHandle(handle); documentServiceImpl .saveDocumentAsync(projectSlug, iterationSlug, resource, extensions, copytrans, true, handle); - logWhenUploadComplete(handle, name, taskKey.id()); - return getProcessStatus(taskKey.id()); // TODO Change to return 202 + logWhenUploadComplete(handle, name, keyId); + return getProcessStatus(keyId); // TODO Change to return 202 // Accepted, // with a url to get the // progress @@ -195,13 +195,13 @@ public ProcessStatus startTranslatedDocCreationOrUpdate( final MergeType finalMergeType = mergeType; String taskName = "TranslatedDocUpload: "+projectSlug+"-"+iterationSlug+"-"+idNoSlash; AsyncTaskHandle handle = new AsyncTaskHandle(); - AsyncTaskHandleManager.AsyncTaskKey taskKey = asyncTaskHandleManager.registerTaskHandle(handle); + String keyId = asyncTaskHandleManager.registerTaskHandle(handle); translationServiceImpl.translateAllInDocAsync(projectSlug, iterationSlug, id, locale, translatedDoc, extensions, finalMergeType, assignCreditToUploader, true, handle, TranslationSourceType.API_UPLOAD); - logWhenUploadComplete(handle, taskName, taskKey.id()); - return this.getProcessStatus(taskKey.id()); + logWhenUploadComplete(handle, taskName, keyId); + return this.getProcessStatus(keyId); } @Override diff --git a/server/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/DownloadAllFilesHandler.java b/server/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/DownloadAllFilesHandler.java index 703a339bd7..2c5ca66af0 100644 --- a/server/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/DownloadAllFilesHandler.java +++ b/server/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/DownloadAllFilesHandler.java @@ -73,7 +73,7 @@ public DownloadAllFilesResult execute(DownloadAllFilesAction action, action.getVersionSlug()); if (identity.hasPermission(version, "download-all")) { AsyncTaskHandle handle = new AsyncTaskHandle(); - AsyncTaskHandleManager.AsyncTaskKey taskKey = + String keyId = asyncTaskHandleManager.registerTaskHandle(handle); // TODO This should be in a service and share code with the JSF // pages that do the same thing @@ -86,7 +86,7 @@ public DownloadAllFilesResult execute(DownloadAllFilesAction action, throw new ActionException(e); } - return new DownloadAllFilesResult(true, taskKey.id()); + return new DownloadAllFilesResult(true, keyId); } return new DownloadAllFilesResult(false, null); diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java b/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java index 6d995e1b7b..a01d6c51eb 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java @@ -39,7 +39,7 @@ import org.mockito.MockitoAnnotations; import org.zanata.async.AsyncTaskHandle; import org.zanata.async.AsyncTaskHandleManager; -import org.zanata.async.UserTriggerableTaskHandle; +import org.zanata.async.UserTriggeredTaskHandle; import org.zanata.exception.AuthorizationException; import org.zanata.rest.dto.ProcessStatus; import org.zanata.security.ZanataIdentity; @@ -281,7 +281,7 @@ public boolean isCancelled() { } private static class UserTriggeredStartedAsyncTaskHandle extends - StartedAsyncTaskHandle implements UserTriggerableTaskHandle { + StartedAsyncTaskHandle implements UserTriggeredTaskHandle { private static final long serialVersionUID = 1L; private String triggerBy; From 5989300c1af12b2f2cc8bcdeb651cfe1f0e22e91 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Mon, 19 Jun 2017 17:10:12 +1000 Subject: [PATCH 022/116] ZNTA-2057 restrict only owner or admin can view the process status --- .../rest/service/AsyncProcessService.java | 17 ++++- .../rest/service/AsyncProcessServiceTest.java | 65 ++++++++++++++++++- 2 files changed, 78 insertions(+), 4 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java index 383edb7e04..0c34640dd6 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java @@ -97,7 +97,7 @@ public AsyncProcessService() { /** - * Get an async task's status. + * Get an async task's status if user has read permission to the task. * * @param keyId * task id @@ -106,6 +106,8 @@ public AsyncProcessService() { * OK(200) - The contents of the response will indicate the process * identifier which may be used to query for its status or a message * indicating what happened.
+ * NOT FOUND(404) - if the task can not be found or user has no + * permission to view its status.
* INTERNAL SERVER ERROR(500) - If there is an unexpected error in * the server while performing this operation. */ @@ -117,6 +119,17 @@ public Response getAsyncProcessStatus(@PathParam("keyId") String keyId) { if (handle == null) { return Response.status(Response.Status.NOT_FOUND).build(); } + if (!identity.hasRole("admin")) { + if (handle instanceof UserTriggeredTaskHandle) { + String triggeredBy = + ((UserTriggeredTaskHandle) handle).getTriggeredBy(); + if (!triggeredBy.equals(identity.getAccountUsername())) { + return Response.status(Response.Status.NOT_FOUND).build(); + } + } else { + return Response.status(Response.Status.NOT_FOUND).build(); + } + } ProcessStatus status = handleToProcessStatus(handle, uriInfo.getRequestUri().toString()); return Response.ok(status).build(); @@ -229,7 +242,7 @@ static ProcessStatus handleToProcessStatus(AsyncTaskHandle handle, result = handle.getResult(); } catch (InterruptedException e) { // The process was forcefully cancelled - status.setStatusCode(ProcessStatus.ProcessStatusCode.Failed); + status.setStatusCode(ProcessStatus.ProcessStatusCode.Cancelled); status.addMessage(e.getMessage()); } catch (ExecutionException e) { // Exception thrown while running the task diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java b/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java index a01d6c51eb..75cdc778bf 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java @@ -75,8 +75,9 @@ public void returnNotFoundIfProcessTaskIdCanNotBeFound() { } @Test - public void canReturnSingleProcessStatus() throws URISyntaxException { - AsyncTaskHandle taskHandle = new AsyncTaskHandle<>(); + public void notAdminUserCanReturnHisProcessStatus() throws URISyntaxException { + UserTriggeredStartedAsyncTaskHandle taskHandle = new UserTriggeredStartedAsyncTaskHandle(); + taskHandle.setTriggeredBy(currentUsername); taskHandle.setMaxProgress(100L); taskHandle.increaseProgress(90); @@ -91,6 +92,66 @@ public void canReturnSingleProcessStatus() throws URISyntaxException { } + @Test + public void notAdminUserCanNotSeeOthersProcessStatus() throws URISyntaxException { + UserTriggeredStartedAsyncTaskHandle taskHandle = new UserTriggeredStartedAsyncTaskHandle(); + taskHandle.setTriggeredBy("somebody-else"); + + when(taskHandleManager.getHandleByKeyId("id")).thenReturn(taskHandle); + when(urlInfo.getRequestUri()) + .thenReturn(new URI(baseUriStr + "process/id")); + Response response = service.getAsyncProcessStatus("id"); + + assertThat(response.getStatus()).isEqualTo(404); + } + + + + @Test + public void adminUserCanNotSeeOthersProcessStatus() throws URISyntaxException { + UserTriggeredStartedAsyncTaskHandle taskHandle = new UserTriggeredStartedAsyncTaskHandle(); + taskHandle.setTriggeredBy("somebody-else"); + + when(identity.hasRole("admin")).thenReturn(true); + when(taskHandleManager.getHandleByKeyId("id")).thenReturn(taskHandle); + when(urlInfo.getRequestUri()) + .thenReturn(new URI(baseUriStr + "process/id")); + Response response = service.getAsyncProcessStatus("id"); + + assertThat(response.getStatus()).isEqualTo(200); + ProcessStatus processStatus = (ProcessStatus) response.getEntity(); + assertThat(processStatus.getStatusCode()).isEqualTo( + ProcessStatus.ProcessStatusCode.Running); + } + + @Test + public void notAdminUserCanNotSeeSystemProcessStatus() throws URISyntaxException { + AsyncTaskHandle taskHandle = new AsyncTaskHandle<>(); + + when(taskHandleManager.getHandleByKeyId("id")).thenReturn(taskHandle); + when(urlInfo.getRequestUri()) + .thenReturn(new URI(baseUriStr + "process/id")); + Response response = service.getAsyncProcessStatus("id"); + + assertThat(response.getStatus()).isEqualTo(404); + } + + @Test + public void adminUserCanSeeSystemProcessStatus() throws URISyntaxException { + AsyncTaskHandle taskHandle = new AsyncTaskHandle<>(); + + when(identity.hasRole("admin")).thenReturn(true); + when(taskHandleManager.getHandleByKeyId("id")).thenReturn(taskHandle); + when(urlInfo.getRequestUri()) + .thenReturn(new URI(baseUriStr + "process/id")); + Response response = service.getAsyncProcessStatus("id"); + + assertThat(response.getStatus()).isEqualTo(200); + ProcessStatus processStatus = (ProcessStatus) response.getEntity(); + assertThat(processStatus.getStatusCode()).isEqualTo( + ProcessStatus.ProcessStatusCode.Running); + } + @Test public void canGetAllRunningTasks() throws URISyntaxException { when(urlInfo.getBaseUri()).thenReturn(new URI(baseUriStr)); From e753e86ce8476996501daa1587731bee69e8a585 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Tue, 20 Jun 2017 09:47:07 +1000 Subject: [PATCH 023/116] ZNTA-2057 add arquillian test for async process API --- .../raw/AsyncProcessRawRestITCase.java | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 server/zanata-war/src/test/java/org/zanata/rest/service/raw/AsyncProcessRawRestITCase.java diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AsyncProcessRawRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AsyncProcessRawRestITCase.java new file mode 100644 index 0000000000..32e01f413c --- /dev/null +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AsyncProcessRawRestITCase.java @@ -0,0 +1,82 @@ +/* + * Copyright 2010, 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.service.raw; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.zanata.provider.DBUnitProvider.DataSetOperation; + +import javax.ws.rs.client.Invocation; +import javax.ws.rs.core.Response; + +import org.dbunit.operation.DatabaseOperation; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget; +import org.junit.Test; +import org.zanata.RestTest; +import org.zanata.rest.ResourceRequest; + +public class AsyncProcessRawRestITCase extends RestTest { + + @Override + protected void prepareDBUnitOperations() { + addBeforeTestOperation(new DataSetOperation( + "org/zanata/test/model/AccountData.dbunit.xml", + DatabaseOperation.CLEAN_INSERT)); + } + + @Test + @RunAsClient + public void notAdminCanNotGetAllProcessStatuses() throws Exception { + new ResourceRequest(getRestEndpointUrl("/process"), "GET", + getTranslatorHeaders()) { + @Override + protected Invocation.Builder + prepareRequest(ResteasyWebTarget webTarget) { + return webTarget.queryParam("includeFinished", true).request(); + } + + @Override + protected void onResponse(Response response) { + assertThat(response.getStatus(), is(401)); + } + }.run(); + } + + @Test + @RunAsClient + public void adminCanGetAllProcessStatuses() throws Exception { + new ResourceRequest(getRestEndpointUrl("/process"), "GET", + getAuthorizedEnvironment()) { + @Override + protected Invocation.Builder + prepareRequest(ResteasyWebTarget webTarget) { + return webTarget.queryParam("includeFinished", true).request(); + } + + @Override + protected void onResponse(Response response) { + assertThat(response.getStatus(), is(200)); + } + }.run(); + } + +} From c3621f115222c0a25bd8162aceebbd86b386d8d6 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Tue, 20 Jun 2017 10:45:05 +1000 Subject: [PATCH 024/116] ZNTA-2057 fix tests --- .../org/zanata/action/CopyTransManager.java | 13 ++++++++ .../org/zanata/action/CopyVersionManager.java | 17 +++++++++- .../action/MergeTranslationsManager.java | 17 +++++++++- .../action/TranslationMemoryAction.java | 19 +++++++++-- .../service/TransMemoryMergeManager.java | 33 +++++++++++++++---- .../service/TransMemoryMergeManagerTest.java | 14 ++++---- 6 files changed, 95 insertions(+), 18 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java b/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java index b721e66163..2b2b8a7011 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java @@ -203,5 +203,18 @@ private CopyTransProcessKey() { public String id() { return joinFields(KEY_NAME, projectSlug, iterationSlug, docId); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CopyTransProcessKey that = (CopyTransProcessKey) o; + return Objects.equals(id(), that.id()); + } + + @Override + public int hashCode() { + return Objects.hash(id()); + } } } diff --git a/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java b/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java index 2ddf76138c..cda5713ad6 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java @@ -94,6 +94,7 @@ public static final class CopyVersionKey implements private final String projectSlug; // target version identifier private final String versionSlug; + private final String id; /** * @@ -120,11 +121,25 @@ public CopyVersionKey(final String projectSlug, final String versionSlug) { this.projectSlug = projectSlug; this.versionSlug = versionSlug; + this.id = joinFields(KEY_NAME, projectSlug, versionSlug); } @Override public String id() { - return joinFields(KEY_NAME, projectSlug, versionSlug); + return id; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CopyVersionKey that = (CopyVersionKey) o; + return Objects.equals(id, that.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); } } } diff --git a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java index 814147dd1d..210516c1f9 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java @@ -103,6 +103,7 @@ public static final class MergeVersionKey implements private final String projectSlug; // target version identifier private final String versionSlug; + private final String id; public static MergeVersionKey getKey(String projectSlug, String versionSlug) { return new MergeVersionKey(projectSlug, versionSlug); @@ -121,11 +122,25 @@ public String getVersionSlug() { public MergeVersionKey(final String projectSlug, final String versionSlug) { this.projectSlug = projectSlug; this.versionSlug = versionSlug; + this.id = joinFields(KEY_NAME, projectSlug, versionSlug); } @Override public String id() { - return joinFields(KEY_NAME, projectSlug, versionSlug); + return id; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MergeVersionKey that = (MergeVersionKey) o; + return Objects.equals(id, that.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); } } } diff --git a/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java b/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java index 59d357dcfd..7051d12d2e 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java +++ b/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java @@ -202,16 +202,29 @@ private static class ClearTransMemoryProcessKey implements AsyncTaskHandleManager.AsyncTaskKey { private static final String KEY_NAME = "ClearTMXKey"; private static final long serialVersionUID = 3472355792561903500L; - private String slug; + private final String id; @java.beans.ConstructorProperties({ "slug" }) public ClearTransMemoryProcessKey(final String slug) { - this.slug = slug; + this.id = joinFields(KEY_NAME, slug); } @Override public String id() { - return joinFields(KEY_NAME, slug); + return id; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ClearTransMemoryProcessKey that = (ClearTransMemoryProcessKey) o; + return Objects.equals(id, that.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); } } diff --git a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java index 75e734960a..009b3e1efb 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java @@ -35,8 +35,10 @@ import org.zanata.model.HAccount; import org.zanata.security.annotations.Authenticated; import org.zanata.service.TransMemoryMergeService; +import org.zanata.webtrans.shared.model.DocumentId; import org.zanata.webtrans.shared.rest.dto.TransMemoryMergeCancelRequest; import org.zanata.webtrans.shared.rest.dto.TransMemoryMergeRequest; +import com.google.common.base.MoreObjects; /** * @author Patrick Huang @@ -75,7 +77,7 @@ public TransMemoryMergeManager( public boolean startTransMemoryMerge(TransMemoryMergeRequest request) { TMMergeForDocTaskKey key = new TMMergeForDocTaskKey( - request.documentId.getId(), request.localeId); + request.documentId, request.localeId); AsyncTaskHandle handleByKey = asyncTaskHandleManager.getHandleByKey(key); if (handleByKey == null || handleByKey.isCancelled() @@ -92,7 +94,7 @@ public boolean startTransMemoryMerge(TransMemoryMergeRequest request) { public boolean cancelTransMemoryMerge(TransMemoryMergeCancelRequest request) { TMMergeForDocTaskKey key = new TMMergeForDocTaskKey( - request.documentId.getId(), request.localeId); + request.documentId, request.localeId); AsyncTaskHandle handleByKey = asyncTaskHandleManager.getHandleByKey(key); if (handleByKey != null && !(handleByKey.isDone() || handleByKey.isCancelled())) { @@ -117,22 +119,41 @@ static class TMMergeForDocTaskKey implements private static final long serialVersionUID = -7210004008208642L; private static final String KEY_NAME = "TMMergeForDocKey"; - private final Long documentId; + private final DocumentId documentId; private final LocaleId localeId; + private final String id; - TMMergeForDocTaskKey(Long documentId, LocaleId localeId) { + TMMergeForDocTaskKey(DocumentId documentId, LocaleId localeId) { this.documentId = documentId; this.localeId = localeId; + // here we use numeric id to form the string id because it doesn't require URL encoding + this.id = joinFields(KEY_NAME, documentId.getId().toString(), localeId.getId()); } @Override public String toString() { - return id(); + return MoreObjects.toStringHelper(this) + .add("documentId", documentId) + .add("localeId", localeId) + .toString(); } @Override public String id() { - return joinFields(KEY_NAME, documentId.toString(), localeId.getId()); + return id; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + TMMergeForDocTaskKey that = (TMMergeForDocTaskKey) o; + return Objects.equals(id, that.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); } } } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java b/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java index 83c994fbb9..3801dacbaf 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java @@ -91,7 +91,7 @@ public boolean isCancelled() { TMMergeForDocTaskKey taskKey = new TMMergeForDocTaskKey( - request.documentId.getId(), + request.documentId, request.localeId); when(asyncTaskHandleManager.getHandleByKey(taskKey)) .thenReturn(existingHandle); @@ -120,7 +120,7 @@ public boolean isDone() { TMMergeForDocTaskKey taskKey = new TMMergeForDocTaskKey( - request.documentId.getId(), + request.documentId, request.localeId); when(asyncTaskHandleManager.getHandleByKey(taskKey)) .thenReturn(existingHandle); @@ -141,7 +141,7 @@ public boolean isDone() { startTMMergeWillReturnFalseIfProcessForSameRequestIsAlreadyRunning() { TMMergeForDocTaskKey taskKey = new TMMergeForDocTaskKey( - request.documentId.getId(), + request.documentId, request.localeId); when(asyncTaskHandleManager.getHandleByKey(taskKey)) .thenReturn(new TransMemoryMergeTaskHandle()); @@ -171,7 +171,7 @@ public boolean isDone() { TMMergeForDocTaskKey taskKey = new TMMergeForDocTaskKey( - cancelRequest.documentId.getId(), + cancelRequest.documentId, cancelRequest.localeId); when(asyncTaskHandleManager.getHandleByKey(taskKey)) .thenReturn(existingHandle); @@ -193,7 +193,7 @@ public boolean isCancelled() { TMMergeForDocTaskKey taskKey = new TMMergeForDocTaskKey( - cancelRequest.documentId.getId(), + cancelRequest.documentId, cancelRequest.localeId); when(asyncTaskHandleManager.getHandleByKey(taskKey)) .thenReturn(existingHandle); @@ -210,7 +210,7 @@ public void cancelTMMergeWillReturnFalseIfProcessForThisRequestIsNotTriggeredByT TMMergeForDocTaskKey taskKey = new TMMergeForDocTaskKey( - cancelRequest.documentId.getId(), + cancelRequest.documentId, cancelRequest.localeId); when(asyncTaskHandleManager.getHandleByKey(taskKey)) .thenReturn(existingHandle); @@ -233,7 +233,7 @@ public boolean cancel(boolean mayInterruptIfRunning) { TMMergeForDocTaskKey taskKey = new TMMergeForDocTaskKey( - cancelRequest.documentId.getId(), + cancelRequest.documentId, cancelRequest.localeId); when(asyncTaskHandleManager.getHandleByKey(taskKey)) .thenReturn(existingHandle); From e741ebe807f8e72ccc97084b0954b0021ca492f9 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Tue, 20 Jun 2017 12:23:58 +1000 Subject: [PATCH 025/116] ZNTA-2057 refactor --- .../org/zanata/action/CopyTransManager.java | 69 ++++++------------- .../org/zanata/action/CopyVersionManager.java | 27 ++------ .../action/MergeTranslationsManager.java | 27 ++------ .../action/TranslationMemoryAction.java | 26 ++----- .../org/zanata/async/AsyncTaskHandle.java | 21 +++++- .../zanata/async/AsyncTaskHandleManager.java | 62 ++++++++++++++--- .../zanata/async/UserTriggeredTaskHandle.java | 5 -- .../service/TransMemoryMergeManager.java | 29 ++------ .../rest/service/AsyncProcessService.java | 32 +++------ .../rest/service/AsyncProcessServiceTest.java | 6 +- .../raw/AsyncProcessRawRestITCase.java | 2 +- 11 files changed, 128 insertions(+), 178 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java b/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java index 2b2b8a7011..2352708765 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java @@ -20,6 +20,8 @@ */ package org.zanata.action; +import static org.zanata.async.AsyncTaskHandleManager.AsyncTaskKey.joinFields; + import java.io.Serializable; import java.util.Objects; @@ -148,28 +150,32 @@ public void cancelCopyTrans(@Nonnull HProjectIteration iteration) { /** * Internal class to index Copy Trans processes. */ - private static final class CopyTransProcessKey implements - AsyncTaskHandleManager.AsyncTaskKey { + private static final class CopyTransProcessKey extends + AsyncTaskHandleManager.GenericKey { private static final long serialVersionUID = -2054359069473618887L; private static final String KEY_NAME = "copyTransKey"; - private String projectSlug; - private String iterationSlug; - private String docId; + private final String projectSlug; + private final String iterationSlug; + private final String docId; + + CopyTransProcessKey(String projectSlug, + String iterationSlug, String docId) { + super(joinFields(KEY_NAME, projectSlug, iterationSlug, docId)); + this.projectSlug = projectSlug; + this.iterationSlug = iterationSlug; + this.docId = docId; + } public static CopyTransProcessKey getKey(HProjectIteration iteration) { - CopyTransProcessKey newKey = new CopyTransProcessKey(); - newKey.setProjectSlug(iteration.getProject().getSlug()); - newKey.setIterationSlug(iteration.getSlug()); - return newKey; + return new CopyTransProcessKey(iteration.getProject().getSlug(), + iteration.getSlug(), null); } public static CopyTransProcessKey getKey(HDocument document) { - CopyTransProcessKey newKey = new CopyTransProcessKey(); - newKey.setDocId(document.getDocId()); - newKey.setProjectSlug( - document.getProjectIteration().getProject().getSlug()); - newKey.setIterationSlug(document.getProjectIteration().getSlug()); - return newKey; + String projectSlug = document.getProjectIteration().getProject().getSlug(); + String versionSlug = document.getProjectIteration().getSlug(); + String docId = document.getDocId(); + return new CopyTransProcessKey(projectSlug, versionSlug, docId); } public String getProjectSlug() { @@ -183,38 +189,5 @@ public String getIterationSlug() { public String getDocId() { return this.docId; } - - public void setProjectSlug(final String projectSlug) { - this.projectSlug = projectSlug; - } - - public void setIterationSlug(final String iterationSlug) { - this.iterationSlug = iterationSlug; - } - - public void setDocId(final String docId) { - this.docId = docId; - } - - private CopyTransProcessKey() { - } - - @Override - public String id() { - return joinFields(KEY_NAME, projectSlug, iterationSlug, docId); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - CopyTransProcessKey that = (CopyTransProcessKey) o; - return Objects.equals(id(), that.id()); - } - - @Override - public int hashCode() { - return Objects.hash(id()); - } } } diff --git a/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java b/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java index cda5713ad6..dc69c4de6b 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java @@ -11,6 +11,8 @@ import org.zanata.security.ZanataIdentity; import org.zanata.service.CopyVersionService; +import static org.zanata.async.AsyncTaskHandleManager.AsyncTaskKey.joinFields; + /** * Manages copy version tasks. * @@ -86,15 +88,14 @@ public boolean isCopyVersionRunning(String projectSlug, * Key used for copy version task * */ - public static final class CopyVersionKey implements - AsyncTaskHandleManager.AsyncTaskKey { + public static final class CopyVersionKey extends + AsyncTaskHandleManager.GenericKey { private static final String KEY_NAME = "copyVersion"; private static final long serialVersionUID = 3889349239078033373L; // target project identifier private final String projectSlug; // target version identifier private final String versionSlug; - private final String id; /** * @@ -119,27 +120,9 @@ public String getVersionSlug() { @java.beans.ConstructorProperties({ "projectSlug", "versionSlug" }) public CopyVersionKey(final String projectSlug, final String versionSlug) { + super(joinFields(KEY_NAME, projectSlug, versionSlug)); this.projectSlug = projectSlug; this.versionSlug = versionSlug; - this.id = joinFields(KEY_NAME, projectSlug, versionSlug); - } - - @Override - public String id() { - return id; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - CopyVersionKey that = (CopyVersionKey) o; - return Objects.equals(id, that.id); - } - - @Override - public int hashCode() { - return Objects.hash(id); } } } diff --git a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java index 210516c1f9..92cece053d 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java @@ -12,6 +12,8 @@ import org.zanata.security.ZanataIdentity; import org.zanata.service.MergeTranslationsService; +import static org.zanata.async.AsyncTaskHandleManager.AsyncTaskKey.joinFields; + /** * Manages tasks to copy translations from one existing version to another. * @@ -95,15 +97,14 @@ public boolean isRunning(String projectSlug, String versionSlug) { /** * Key used for merge version task */ - public static final class MergeVersionKey implements - AsyncTaskHandleManager.AsyncTaskKey { + public static final class MergeVersionKey extends + AsyncTaskHandleManager.GenericKey { private static final long serialVersionUID = 1L; private static final String KEY_NAME = "mergeVersion"; // target project identifier private final String projectSlug; // target version identifier private final String versionSlug; - private final String id; public static MergeVersionKey getKey(String projectSlug, String versionSlug) { return new MergeVersionKey(projectSlug, versionSlug); @@ -120,27 +121,9 @@ public String getVersionSlug() { @java.beans.ConstructorProperties({ "projectSlug", "versionSlug" }) public MergeVersionKey(final String projectSlug, final String versionSlug) { + super(joinFields(KEY_NAME, projectSlug, versionSlug)); this.projectSlug = projectSlug; this.versionSlug = versionSlug; - this.id = joinFields(KEY_NAME, projectSlug, versionSlug); - } - - @Override - public String id() { - return id; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - MergeVersionKey that = (MergeVersionKey) o; - return Objects.equals(id, that.id); - } - - @Override - public int hashCode() { - return Objects.hash(id); } } } diff --git a/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java b/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java index 7051d12d2e..3f282aa16e 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java +++ b/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java @@ -21,6 +21,8 @@ package org.zanata.action; import static javax.faces.application.FacesMessage.SEVERITY_ERROR; +import static org.zanata.async.AsyncTaskHandleManager.AsyncTaskKey.joinFields; + import java.io.Serializable; import java.util.Comparator; import java.util.List; @@ -198,34 +200,16 @@ public String cancel() { * NB: Eventually this class might need to live outside if there are other * services that need to control this process. */ - private static class ClearTransMemoryProcessKey implements - AsyncTaskHandleManager.AsyncTaskKey { + private static class ClearTransMemoryProcessKey extends + AsyncTaskHandleManager.GenericKey { private static final String KEY_NAME = "ClearTMXKey"; private static final long serialVersionUID = 3472355792561903500L; - private final String id; @java.beans.ConstructorProperties({ "slug" }) public ClearTransMemoryProcessKey(final String slug) { - this.id = joinFields(KEY_NAME, slug); + super(joinFields(KEY_NAME, slug)); } - @Override - public String id() { - return id; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ClearTransMemoryProcessKey that = (ClearTransMemoryProcessKey) o; - return Objects.equals(id, that.id); - } - - @Override - public int hashCode() { - return Objects.hash(id); - } } private static class TMComparator implements Comparator, Serializable { diff --git a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java index 6117633d20..60d7a83407 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java @@ -23,12 +23,14 @@ import java.io.Serializable; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.function.BiConsumer; +import org.zanata.security.ZanataIdentity; + import com.google.common.base.Optional; + import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; /** @@ -108,6 +110,23 @@ public Optional getEstimatedTimeRemaining() { } } + public boolean isVisibleTo(ZanataIdentity identity) { + return isAdminOrSameUser(this, identity); + } + + public boolean canCancel(ZanataIdentity identity) { + return isAdminOrSameUser(this, identity); + } + + private static boolean isAdminOrSameUser(AsyncTaskHandle taskHandle, + ZanataIdentity identity) { + return identity != null && (identity.hasRole("admin") + || (taskHandle instanceof UserTriggeredTaskHandle + && ((UserTriggeredTaskHandle) taskHandle) + .getTriggeredBy() + .equals(identity.getAccountUsername()))); + } + /** * @return The time that the task has been executing for, or the total * execution time if the task has finished (in milliseconds). diff --git a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java index 6095a12f63..b8f20afe83 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java +++ b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java @@ -23,12 +23,16 @@ import java.io.Serializable; import java.util.Collection; import java.util.Map; +import java.util.Objects; import java.util.UUID; import java.util.concurrent.TimeUnit; import javax.inject.Named; +import org.zanata.action.TranslationMemoryAction; import com.google.common.base.Joiner; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.collect.ImmutableMap; @@ -55,23 +59,21 @@ public class AsyncTaskHandleManager implements Serializable { public synchronized void registerTaskHandle(AsyncTaskHandle handle, K key) { - if (handlesByKey.containsKey(key.id())) { - throw new RuntimeException("Task handle with key " + key - + " already exists"); - } - handlesByKey.put(key.id(), handle); + AsyncTaskHandle existingHandle = + handlesByKey.putIfAbsent(key.id(), handle); + Preconditions.checkArgument(existingHandle == null, + "Task handle with key " + key + " already exists"); } /** * Registers a task handle. * @param handle The handle to register. - * @return An auto generated key to retreive the handle later + * @return An auto generated key id to retrieve the handle later */ public synchronized String registerTaskHandle(AsyncTaskHandle handle) { - String autoGenKey = UUID.randomUUID().toString(); - AsyncTaskKey autoKey = () -> autoGenKey; - registerTaskHandle(handle, autoKey); - return autoGenKey; + GenericKey genericKey = new GenericKey(); + registerTaskHandle(handle, genericKey); + return genericKey.id(); } void taskFinished(AsyncTaskHandle taskHandle) { @@ -135,9 +137,47 @@ public interface AsyncTaskKey extends Serializable { * key instance field values * @return String representation of the key which can be used as id */ - default String joinFields(String keyName, String... fields) { + static String joinFields(String keyName, String... fields) { return keyName + SEPARATOR + Joiner.on(SEPARATOR).useForNull("").join(fields); } } + + public static class GenericKey implements AsyncTaskKey { + private static final long serialVersionUID = -8648519833116851231L; + private final String id; + + GenericKey() { + id = UUID.randomUUID().toString(); + } + + public GenericKey(String id) { + this.id = id; + } + + @Override + public String id() { + return id; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("id", id) + .toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + GenericKey that = (GenericKey) o; + return Objects.equals(id, that.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + } } diff --git a/server/zanata-war/src/main/java/org/zanata/async/UserTriggeredTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/UserTriggeredTaskHandle.java index 61ec2f60f8..4bf0d79d26 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/UserTriggeredTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/UserTriggeredTaskHandle.java @@ -20,7 +20,6 @@ */ package org.zanata.async; -import org.zanata.security.ZanataIdentity; /** * Represents a task triggered by a user (as oppose to some system generated @@ -32,8 +31,4 @@ public interface UserTriggeredTaskHandle { String getTriggeredBy(); - default boolean canCancel(ZanataIdentity identity) { - return identity != null && (identity.hasRole("admin") - || getTriggeredBy().equals(identity.getAccountUsername())); - } } diff --git a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java index 009b3e1efb..b87b7f0fdd 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java @@ -40,6 +40,8 @@ import org.zanata.webtrans.shared.rest.dto.TransMemoryMergeRequest; import com.google.common.base.MoreObjects; +import static org.zanata.async.AsyncTaskHandleManager.AsyncTaskKey.joinFields; + /** * @author Patrick Huang * pahuang@redhat.com @@ -114,20 +116,19 @@ public boolean cancelTransMemoryMerge(TransMemoryMergeCancelRequest request) { return false; } - static class TMMergeForDocTaskKey implements - AsyncTaskHandleManager.AsyncTaskKey { + static class TMMergeForDocTaskKey extends + AsyncTaskHandleManager.GenericKey { private static final long serialVersionUID = -7210004008208642L; private static final String KEY_NAME = "TMMergeForDocKey"; private final DocumentId documentId; private final LocaleId localeId; - private final String id; TMMergeForDocTaskKey(DocumentId documentId, LocaleId localeId) { + // here we use numeric id to form the string id because it doesn't require URL encoding + super(joinFields(KEY_NAME, documentId.getId().toString(), localeId.getId())); this.documentId = documentId; this.localeId = localeId; - // here we use numeric id to form the string id because it doesn't require URL encoding - this.id = joinFields(KEY_NAME, documentId.getId().toString(), localeId.getId()); } @Override @@ -137,23 +138,5 @@ public String toString() { .add("localeId", localeId) .toString(); } - - @Override - public String id() { - return id; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - TMMergeForDocTaskKey that = (TMMergeForDocTaskKey) o; - return Objects.equals(id, that.id); - } - - @Override - public int hashCode() { - return Objects.hash(id); - } } } diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java index 0c34640dd6..10c56a97b8 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java @@ -119,16 +119,8 @@ public Response getAsyncProcessStatus(@PathParam("keyId") String keyId) { if (handle == null) { return Response.status(Response.Status.NOT_FOUND).build(); } - if (!identity.hasRole("admin")) { - if (handle instanceof UserTriggeredTaskHandle) { - String triggeredBy = - ((UserTriggeredTaskHandle) handle).getTriggeredBy(); - if (!triggeredBy.equals(identity.getAccountUsername())) { - return Response.status(Response.Status.NOT_FOUND).build(); - } - } else { - return Response.status(Response.Status.NOT_FOUND).build(); - } + if (!handle.isVisibleTo(identity)) { + return Response.status(Response.Status.NOT_FOUND).build(); } ProcessStatus status = handleToProcessStatus(handle, uriInfo.getRequestUri().toString()); @@ -195,19 +187,13 @@ public Response cancelAsyncProcess(@PathParam("keyId") String keyId) { return Response.ok(entity).build(); } - if (handle instanceof UserTriggeredTaskHandle) { - UserTriggeredTaskHandle taskHandle = - (UserTriggeredTaskHandle) handle; - if (!taskHandle.canCancel(identity)) { - throw new AuthorizationException( - "Only the task owner or admin can cancel the task:" + keyId); - } - } else { - // for other type of async task, we consider them as system tasks - if (!identity.hasRole("admin")) { - throw new AuthorizationException( - "Only admin can cancel the task:" + keyId); - } + if (!handle.canCancel(identity)) { + String message = handle instanceof UserTriggeredTaskHandle + ? "Only the task owner or admin can cancel the task:" + + keyId + : "Only admin can cancel the task:" + + keyId; + throw new AuthorizationException(message); } handle.cancel(true); diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java b/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java index 75cdc778bf..a1f1fc2504 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/AsyncProcessServiceTest.java @@ -108,7 +108,7 @@ public void notAdminUserCanNotSeeOthersProcessStatus() throws URISyntaxException @Test - public void adminUserCanNotSeeOthersProcessStatus() throws URISyntaxException { + public void adminUserCanSeeOthersProcessStatus() throws URISyntaxException { UserTriggeredStartedAsyncTaskHandle taskHandle = new UserTriggeredStartedAsyncTaskHandle(); taskHandle.setTriggeredBy("somebody-else"); @@ -175,6 +175,10 @@ public void canGetAllRunningTasks() throws URISyntaxException { .isEqualTo(baseUriStr + "process/key/keyId"); } + /** + * This operation is only available to admin. + * @see org.zanata.rest.service.raw.AsyncProcessRawRestITCase + */ @Test public void canGetAllTasksIncludingFinishedTask() throws URISyntaxException { diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AsyncProcessRawRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AsyncProcessRawRestITCase.java index 32e01f413c..d107651517 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AsyncProcessRawRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AsyncProcessRawRestITCase.java @@ -56,7 +56,7 @@ public void notAdminCanNotGetAllProcessStatuses() throws Exception { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(401)); + assertThat(response.getStatus(), is(403)); } }.run(); } From c6c53e301b49eb8356a128d43cd3aead9257ed7d Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Tue, 20 Jun 2017 14:17:21 +1000 Subject: [PATCH 026/116] fix findbugs warnings --- .../org/zanata/action/CopyTransManager.java | 46 +++++-------------- .../org/zanata/action/CopyVersionManager.java | 39 ++++------------ .../action/MergeTranslationsManager.java | 30 ++---------- .../action/TranslationMemoryAction.java | 29 +++--------- .../service/TransMemoryMergeManager.java | 3 ++ 5 files changed, 35 insertions(+), 112 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java b/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java index 2352708765..3444ef6dce 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java @@ -23,7 +23,6 @@ import static org.zanata.async.AsyncTaskHandleManager.AsyncTaskKey.joinFields; import java.io.Serializable; -import java.util.Objects; import javax.annotation.Nonnull; import javax.enterprise.context.Dependent; @@ -64,7 +63,7 @@ public class CopyTransManager implements Serializable { private ZanataIdentity identity; public boolean isCopyTransRunning(@Nonnull Object target) { - CopyTransProcessKey key; + AsyncTaskHandleManager.AsyncTaskKey key; if (target instanceof HProjectIteration) { key = CopyTransProcessKey.getKey((HProjectIteration) target); } else if (target instanceof HDocument) { @@ -98,7 +97,7 @@ public void startCopyTrans(HDocument document, HCopyTransOptions options) { "Copy Trans is already running for document \'" + document.getDocId() + "\'"); } - CopyTransProcessKey key = CopyTransProcessKey.getKey(document); + AsyncTaskHandleManager.AsyncTaskKey key = CopyTransProcessKey.getKey(document); CopyTransTaskHandle handle = new CopyTransTaskHandle(); asyncTaskHandleManager.registerTaskHandle(handle, key); copyTransServiceImpl.startCopyTransForDocument(document, options, @@ -116,7 +115,7 @@ public void startCopyTrans(HProjectIteration iteration, "Copy Trans is already running for version \'" + iteration.getSlug() + "\'"); } - CopyTransProcessKey key = CopyTransProcessKey.getKey(iteration); + AsyncTaskHandleManager.AsyncTaskKey key = CopyTransProcessKey.getKey(iteration); CopyTransTaskHandle handle = new CopyTransTaskHandle(); asyncTaskHandleManager.registerTaskHandle(handle, key); copyTransServiceImpl.startCopyTransForIteration(iteration, options, @@ -125,7 +124,7 @@ public void startCopyTrans(HProjectIteration iteration, public CopyTransTaskHandle getCopyTransProcessHandle(@Nonnull Object target) { - CopyTransProcessKey key; + AsyncTaskHandleManager.AsyncTaskKey key; if (target instanceof HProjectIteration) { key = CopyTransProcessKey.getKey((HProjectIteration) target); } else if (target instanceof HDocument) { @@ -150,44 +149,21 @@ public void cancelCopyTrans(@Nonnull HProjectIteration iteration) { /** * Internal class to index Copy Trans processes. */ - private static final class CopyTransProcessKey extends - AsyncTaskHandleManager.GenericKey { - private static final long serialVersionUID = -2054359069473618887L; + private static final class CopyTransProcessKey { private static final String KEY_NAME = "copyTransKey"; - private final String projectSlug; - private final String iterationSlug; - private final String docId; - - CopyTransProcessKey(String projectSlug, - String iterationSlug, String docId) { - super(joinFields(KEY_NAME, projectSlug, iterationSlug, docId)); - this.projectSlug = projectSlug; - this.iterationSlug = iterationSlug; - this.docId = docId; - } - public static CopyTransProcessKey getKey(HProjectIteration iteration) { - return new CopyTransProcessKey(iteration.getProject().getSlug(), - iteration.getSlug(), null); + + public static AsyncTaskHandleManager.AsyncTaskKey getKey(HProjectIteration iteration) { + return new AsyncTaskHandleManager.GenericKey(joinFields(iteration.getProject().getSlug(), + iteration.getSlug(), null)); } - public static CopyTransProcessKey getKey(HDocument document) { + public static AsyncTaskHandleManager.AsyncTaskKey getKey(HDocument document) { String projectSlug = document.getProjectIteration().getProject().getSlug(); String versionSlug = document.getProjectIteration().getSlug(); String docId = document.getDocId(); - return new CopyTransProcessKey(projectSlug, versionSlug, docId); - } - - public String getProjectSlug() { - return this.projectSlug; + return new AsyncTaskHandleManager.GenericKey(joinFields(KEY_NAME, projectSlug, versionSlug, docId)); } - public String getIterationSlug() { - return this.iterationSlug; - } - - public String getDocId() { - return this.docId; - } } } diff --git a/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java b/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java index dc69c4de6b..c5236a60d4 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java @@ -1,17 +1,18 @@ package org.zanata.action; +import static org.zanata.async.AsyncTaskHandleManager.AsyncTaskKey.joinFields; + import java.io.Serializable; -import java.util.Objects; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import javax.enterprise.context.Dependent; import javax.inject.Inject; + import org.zanata.async.AsyncTaskHandleManager; import org.zanata.async.handle.CopyVersionTaskHandle; import org.zanata.security.ZanataIdentity; import org.zanata.service.CopyVersionService; -import static org.zanata.async.AsyncTaskHandleManager.AsyncTaskKey.joinFields; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; /** * Manages copy version tasks. @@ -45,7 +46,7 @@ public class CopyVersionManager implements Serializable { */ public void startCopyVersion(String projectSlug, String versionSlug, String newVersionSlug) { - CopyVersionKey key = CopyVersionKey.getKey(projectSlug, newVersionSlug); + AsyncTaskHandleManager.AsyncTaskKey key = CopyVersionKey.getKey(projectSlug, newVersionSlug); CopyVersionTaskHandle handle = new CopyVersionTaskHandle(); asyncTaskHandleManager.registerTaskHandle(handle, key); copyVersionServiceImpl.startCopyVersion(projectSlug, versionSlug, @@ -88,14 +89,8 @@ public boolean isCopyVersionRunning(String projectSlug, * Key used for copy version task * */ - public static final class CopyVersionKey extends - AsyncTaskHandleManager.GenericKey { + public static final class CopyVersionKey { private static final String KEY_NAME = "copyVersion"; - private static final long serialVersionUID = 3889349239078033373L; - // target project identifier - private final String projectSlug; - // target version identifier - private final String versionSlug; /** * @@ -104,25 +99,11 @@ public static final class CopyVersionKey extends * @param versionSlug * - target version identifier */ - public static CopyVersionKey getKey(String projectSlug, - String versionSlug) { - return new CopyVersionKey(projectSlug, versionSlug); + public static AsyncTaskHandleManager.AsyncTaskKey + getKey(String projectSlug, String versionSlug) { + return new AsyncTaskHandleManager.GenericKey( + joinFields(KEY_NAME, projectSlug, versionSlug)); } - public String getProjectSlug() { - return this.projectSlug; - } - - public String getVersionSlug() { - return this.versionSlug; - } - - @java.beans.ConstructorProperties({ "projectSlug", "versionSlug" }) - public CopyVersionKey(final String projectSlug, - final String versionSlug) { - super(joinFields(KEY_NAME, projectSlug, versionSlug)); - this.projectSlug = projectSlug; - this.versionSlug = versionSlug; - } } } diff --git a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java index 92cece053d..9f4da9b30f 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java @@ -1,7 +1,6 @@ package org.zanata.action; import java.io.Serializable; -import java.util.Objects; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import javax.enterprise.context.Dependent; @@ -52,7 +51,7 @@ public class MergeTranslationsManager implements Serializable { public void start(String sourceProjectSlug, String sourceVersionSlug, String targetProjectSlug, String targetVersionSlug, boolean useNewerTranslation) { - MergeVersionKey + AsyncTaskHandleManager.AsyncTaskKey key = MergeVersionKey .getKey(targetProjectSlug, targetVersionSlug); MergeTranslationsTaskHandle handle = new MergeTranslationsTaskHandle(); @@ -97,33 +96,12 @@ public boolean isRunning(String projectSlug, String versionSlug) { /** * Key used for merge version task */ - public static final class MergeVersionKey extends - AsyncTaskHandleManager.GenericKey { - private static final long serialVersionUID = 1L; + public static final class MergeVersionKey { private static final String KEY_NAME = "mergeVersion"; - // target project identifier - private final String projectSlug; - // target version identifier - private final String versionSlug; - public static MergeVersionKey getKey(String projectSlug, String versionSlug) { - return new MergeVersionKey(projectSlug, versionSlug); + public static AsyncTaskHandleManager.AsyncTaskKey getKey(String projectSlug, String versionSlug) { + return new AsyncTaskHandleManager.GenericKey(joinFields(KEY_NAME, projectSlug, versionSlug)); } - - public String getProjectSlug() { - return this.projectSlug; - } - - public String getVersionSlug() { - return this.versionSlug; - } - - @java.beans.ConstructorProperties({ "projectSlug", "versionSlug" }) - public MergeVersionKey(final String projectSlug, final String versionSlug) { - super(joinFields(KEY_NAME, projectSlug, versionSlug)); - this.projectSlug = projectSlug; - this.versionSlug = versionSlug; - } } } diff --git a/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java b/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java index 3f282aa16e..6b955ee823 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java +++ b/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java @@ -26,7 +26,6 @@ import java.io.Serializable; import java.util.Comparator; import java.util.List; -import java.util.Objects; import java.util.concurrent.ExecutionException; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import javax.enterprise.inject.Model; @@ -60,6 +59,7 @@ public class TranslationMemoryAction implements Serializable { org.slf4j.LoggerFactory.getLogger(TranslationMemoryAction.class); private static final long serialVersionUID = -6791743907133760028L; + private static final String KEY_NAME = "ClearTMXKey"; @Inject private FacesMessages facesMessages; @Inject @@ -71,7 +71,7 @@ public class TranslationMemoryAction implements Serializable { justification = "CDI proxies are Serializable") private AsyncTaskHandleManager asyncTaskHandleManager; private List transMemoryList; - private ClearTransMemoryProcessKey lastTaskTMKey; + private AsyncTaskHandleManager.AsyncTaskKey lastTaskTMKey; private SortingType tmSortingList = new SortingType( Lists.newArrayList(SortingType.SortOption.ALPHABETICAL, SortingType.SortOption.CREATED_DATE)); @@ -95,7 +95,7 @@ public void sortTMList() { } public void clearTransMemory(final String transMemorySlug) { - lastTaskTMKey = new ClearTransMemoryProcessKey(transMemorySlug); + lastTaskTMKey = new AsyncTaskHandleManager.GenericKey(joinFields(KEY_NAME, transMemorySlug)); AsyncTaskHandle handle = new AsyncTaskHandle(); asyncTaskHandleManager.registerTaskHandle(handle, lastTaskTMKey); translationMemoryResource @@ -161,8 +161,11 @@ public void deleteTransMemory(String transMemorySlug) { } public boolean isTransMemoryBeingCleared(String transMemorySlug) { + AsyncTaskHandleManager.GenericKey taskKey = + new AsyncTaskHandleManager.GenericKey( + joinFields(KEY_NAME, transMemorySlug)); AsyncTaskHandle handle = asyncTaskHandleManager.getHandleByKey( - new ClearTransMemoryProcessKey(transMemorySlug)); + taskKey); return handle != null && !handle.isDone(); } @@ -194,24 +197,6 @@ public String cancel() { return "cancel"; } - /** - * Represents a key to index a translation memory clear process. - * - * NB: Eventually this class might need to live outside if there are other - * services that need to control this process. - */ - private static class ClearTransMemoryProcessKey extends - AsyncTaskHandleManager.GenericKey { - private static final String KEY_NAME = "ClearTMXKey"; - private static final long serialVersionUID = 3472355792561903500L; - - @java.beans.ConstructorProperties({ "slug" }) - public ClearTransMemoryProcessKey(final String slug) { - super(joinFields(KEY_NAME, slug)); - } - - } - private static class TMComparator implements Comparator, Serializable { private SortingType sortingType; diff --git a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java index b87b7f0fdd..14f4cd46ae 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java @@ -40,6 +40,8 @@ import org.zanata.webtrans.shared.rest.dto.TransMemoryMergeRequest; import com.google.common.base.MoreObjects; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + import static org.zanata.async.AsyncTaskHandleManager.AsyncTaskKey.joinFields; /** @@ -116,6 +118,7 @@ public boolean cancelTransMemoryMerge(TransMemoryMergeCancelRequest request) { return false; } + @SuppressFBWarnings(value = "EQ_DOESNT_OVERRIDE_EQUALS", justification = "super class equals method is sufficient") static class TMMergeForDocTaskKey extends AsyncTaskHandleManager.GenericKey { From 2537239173e383dd052feda49fec7dd7fa1bbabd Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Tue, 20 Jun 2017 14:18:30 +1000 Subject: [PATCH 027/116] move inner classes out --- .../org/zanata/action/CopyTransManager.java | 20 +++--- .../org/zanata/action/CopyVersionManager.java | 10 +-- .../action/MergeTranslationsManager.java | 10 +-- .../action/TranslationMemoryAction.java | 12 ++-- .../zanata/async/AsyncTaskHandleManager.java | 68 +------------------ .../java/org/zanata/async/AsyncTaskKey.java | 32 +++++++++ .../org/zanata/async/GenericAsyncTaskKey.java | 47 +++++++++++++ .../service/TransMemoryMergeManager.java | 5 +- .../service/TransMemoryMergeManagerTest.java | 2 +- 9 files changed, 114 insertions(+), 92 deletions(-) create mode 100644 server/zanata-war/src/main/java/org/zanata/async/AsyncTaskKey.java create mode 100644 server/zanata-war/src/main/java/org/zanata/async/GenericAsyncTaskKey.java diff --git a/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java b/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java index 3444ef6dce..4790d924c9 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java @@ -20,7 +20,7 @@ */ package org.zanata.action; -import static org.zanata.async.AsyncTaskHandleManager.AsyncTaskKey.joinFields; +import static org.zanata.async.AsyncTaskKey.joinFields; import java.io.Serializable; @@ -30,6 +30,8 @@ import org.zanata.async.AsyncTaskHandle; import org.zanata.async.AsyncTaskHandleManager; +import org.zanata.async.AsyncTaskKey; +import org.zanata.async.GenericAsyncTaskKey; import org.zanata.async.handle.CopyTransTaskHandle; import org.zanata.model.HCopyTransOptions; import org.zanata.model.HDocument; @@ -63,7 +65,7 @@ public class CopyTransManager implements Serializable { private ZanataIdentity identity; public boolean isCopyTransRunning(@Nonnull Object target) { - AsyncTaskHandleManager.AsyncTaskKey key; + AsyncTaskKey key; if (target instanceof HProjectIteration) { key = CopyTransProcessKey.getKey((HProjectIteration) target); } else if (target instanceof HDocument) { @@ -97,7 +99,7 @@ public void startCopyTrans(HDocument document, HCopyTransOptions options) { "Copy Trans is already running for document \'" + document.getDocId() + "\'"); } - AsyncTaskHandleManager.AsyncTaskKey key = CopyTransProcessKey.getKey(document); + AsyncTaskKey key = CopyTransProcessKey.getKey(document); CopyTransTaskHandle handle = new CopyTransTaskHandle(); asyncTaskHandleManager.registerTaskHandle(handle, key); copyTransServiceImpl.startCopyTransForDocument(document, options, @@ -115,7 +117,7 @@ public void startCopyTrans(HProjectIteration iteration, "Copy Trans is already running for version \'" + iteration.getSlug() + "\'"); } - AsyncTaskHandleManager.AsyncTaskKey key = CopyTransProcessKey.getKey(iteration); + AsyncTaskKey key = CopyTransProcessKey.getKey(iteration); CopyTransTaskHandle handle = new CopyTransTaskHandle(); asyncTaskHandleManager.registerTaskHandle(handle, key); copyTransServiceImpl.startCopyTransForIteration(iteration, options, @@ -124,7 +126,7 @@ public void startCopyTrans(HProjectIteration iteration, public CopyTransTaskHandle getCopyTransProcessHandle(@Nonnull Object target) { - AsyncTaskHandleManager.AsyncTaskKey key; + AsyncTaskKey key; if (target instanceof HProjectIteration) { key = CopyTransProcessKey.getKey((HProjectIteration) target); } else if (target instanceof HDocument) { @@ -153,16 +155,16 @@ private static final class CopyTransProcessKey { private static final String KEY_NAME = "copyTransKey"; - public static AsyncTaskHandleManager.AsyncTaskKey getKey(HProjectIteration iteration) { - return new AsyncTaskHandleManager.GenericKey(joinFields(iteration.getProject().getSlug(), + public static AsyncTaskKey getKey(HProjectIteration iteration) { + return new GenericAsyncTaskKey(joinFields(iteration.getProject().getSlug(), iteration.getSlug(), null)); } - public static AsyncTaskHandleManager.AsyncTaskKey getKey(HDocument document) { + public static AsyncTaskKey getKey(HDocument document) { String projectSlug = document.getProjectIteration().getProject().getSlug(); String versionSlug = document.getProjectIteration().getSlug(); String docId = document.getDocId(); - return new AsyncTaskHandleManager.GenericKey(joinFields(KEY_NAME, projectSlug, versionSlug, docId)); + return new GenericAsyncTaskKey(joinFields(KEY_NAME, projectSlug, versionSlug, docId)); } } diff --git a/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java b/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java index c5236a60d4..adc0386eb2 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/CopyVersionManager.java @@ -1,6 +1,6 @@ package org.zanata.action; -import static org.zanata.async.AsyncTaskHandleManager.AsyncTaskKey.joinFields; +import static org.zanata.async.AsyncTaskKey.joinFields; import java.io.Serializable; @@ -8,6 +8,8 @@ import javax.inject.Inject; import org.zanata.async.AsyncTaskHandleManager; +import org.zanata.async.AsyncTaskKey; +import org.zanata.async.GenericAsyncTaskKey; import org.zanata.async.handle.CopyVersionTaskHandle; import org.zanata.security.ZanataIdentity; import org.zanata.service.CopyVersionService; @@ -46,7 +48,7 @@ public class CopyVersionManager implements Serializable { */ public void startCopyVersion(String projectSlug, String versionSlug, String newVersionSlug) { - AsyncTaskHandleManager.AsyncTaskKey key = CopyVersionKey.getKey(projectSlug, newVersionSlug); + AsyncTaskKey key = CopyVersionKey.getKey(projectSlug, newVersionSlug); CopyVersionTaskHandle handle = new CopyVersionTaskHandle(); asyncTaskHandleManager.registerTaskHandle(handle, key); copyVersionServiceImpl.startCopyVersion(projectSlug, versionSlug, @@ -99,9 +101,9 @@ public static final class CopyVersionKey { * @param versionSlug * - target version identifier */ - public static AsyncTaskHandleManager.AsyncTaskKey + public static AsyncTaskKey getKey(String projectSlug, String versionSlug) { - return new AsyncTaskHandleManager.GenericKey( + return new GenericAsyncTaskKey( joinFields(KEY_NAME, projectSlug, versionSlug)); } diff --git a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java index 9f4da9b30f..b77b101dcf 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java @@ -7,11 +7,13 @@ import javax.inject.Inject; import org.zanata.async.AsyncTaskHandleManager; +import org.zanata.async.AsyncTaskKey; +import org.zanata.async.GenericAsyncTaskKey; import org.zanata.async.handle.MergeTranslationsTaskHandle; import org.zanata.security.ZanataIdentity; import org.zanata.service.MergeTranslationsService; -import static org.zanata.async.AsyncTaskHandleManager.AsyncTaskKey.joinFields; +import static org.zanata.async.AsyncTaskKey.joinFields; /** * Manages tasks to copy translations from one existing version to another. @@ -51,7 +53,7 @@ public class MergeTranslationsManager implements Serializable { public void start(String sourceProjectSlug, String sourceVersionSlug, String targetProjectSlug, String targetVersionSlug, boolean useNewerTranslation) { - AsyncTaskHandleManager.AsyncTaskKey + AsyncTaskKey key = MergeVersionKey .getKey(targetProjectSlug, targetVersionSlug); MergeTranslationsTaskHandle handle = new MergeTranslationsTaskHandle(); @@ -99,8 +101,8 @@ public boolean isRunning(String projectSlug, String versionSlug) { public static final class MergeVersionKey { private static final String KEY_NAME = "mergeVersion"; - public static AsyncTaskHandleManager.AsyncTaskKey getKey(String projectSlug, String versionSlug) { - return new AsyncTaskHandleManager.GenericKey(joinFields(KEY_NAME, projectSlug, versionSlug)); + public static AsyncTaskKey getKey(String projectSlug, String versionSlug) { + return new GenericAsyncTaskKey(joinFields(KEY_NAME, projectSlug, versionSlug)); } } diff --git a/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java b/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java index 6b955ee823..7660e980dd 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java +++ b/server/zanata-war/src/main/java/org/zanata/action/TranslationMemoryAction.java @@ -21,7 +21,7 @@ package org.zanata.action; import static javax.faces.application.FacesMessage.SEVERITY_ERROR; -import static org.zanata.async.AsyncTaskHandleManager.AsyncTaskKey.joinFields; +import static org.zanata.async.AsyncTaskKey.joinFields; import java.io.Serializable; import java.util.Comparator; @@ -33,6 +33,8 @@ import javax.inject.Inject; import javax.inject.Named; import org.apache.deltaspike.jpa.api.transaction.Transactional; +import org.zanata.async.AsyncTaskKey; +import org.zanata.async.GenericAsyncTaskKey; import org.zanata.security.annotations.CheckRole; import org.zanata.async.AsyncTaskHandle; import org.zanata.async.AsyncTaskHandleManager; @@ -71,7 +73,7 @@ public class TranslationMemoryAction implements Serializable { justification = "CDI proxies are Serializable") private AsyncTaskHandleManager asyncTaskHandleManager; private List transMemoryList; - private AsyncTaskHandleManager.AsyncTaskKey lastTaskTMKey; + private AsyncTaskKey lastTaskTMKey; private SortingType tmSortingList = new SortingType( Lists.newArrayList(SortingType.SortOption.ALPHABETICAL, SortingType.SortOption.CREATED_DATE)); @@ -95,7 +97,7 @@ public void sortTMList() { } public void clearTransMemory(final String transMemorySlug) { - lastTaskTMKey = new AsyncTaskHandleManager.GenericKey(joinFields(KEY_NAME, transMemorySlug)); + lastTaskTMKey = new GenericAsyncTaskKey(joinFields(KEY_NAME, transMemorySlug)); AsyncTaskHandle handle = new AsyncTaskHandle(); asyncTaskHandleManager.registerTaskHandle(handle, lastTaskTMKey); translationMemoryResource @@ -161,8 +163,8 @@ public void deleteTransMemory(String transMemorySlug) { } public boolean isTransMemoryBeingCleared(String transMemorySlug) { - AsyncTaskHandleManager.GenericKey taskKey = - new AsyncTaskHandleManager.GenericKey( + GenericAsyncTaskKey taskKey = + new GenericAsyncTaskKey( joinFields(KEY_NAME, transMemorySlug)); AsyncTaskHandle handle = asyncTaskHandleManager.getHandleByKey( taskKey); diff --git a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java index b8f20afe83..94b22eb17b 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java +++ b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandleManager.java @@ -23,15 +23,10 @@ import java.io.Serializable; import java.util.Collection; import java.util.Map; -import java.util.Objects; -import java.util.UUID; import java.util.concurrent.TimeUnit; import javax.inject.Named; -import org.zanata.action.TranslationMemoryAction; -import com.google.common.base.Joiner; -import com.google.common.base.MoreObjects; import com.google.common.base.Preconditions; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; @@ -71,7 +66,7 @@ public synchronized void registerTaskHandle(AsyncTaskHa * @return An auto generated key id to retrieve the handle later */ public synchronized String registerTaskHandle(AsyncTaskHandle handle) { - GenericKey genericKey = new GenericKey(); + GenericAsyncTaskKey genericKey = new GenericAsyncTaskKey(); registerTaskHandle(handle, genericKey); return genericKey.id(); } @@ -119,65 +114,4 @@ public Map> getRunningTasks() { return ImmutableMap.copyOf(handlesByKey); } - public interface AsyncTaskKey extends Serializable { - /** - * When converting multiple fields to form id string, we - * should use this as separator (URL friendly). - */ - String SEPARATOR = "-"; - - String id(); - - /** - * Helper method to convert list of fields to a String as key id. - * - * @param keyName - * the name for this key - * @param fields - * key instance field values - * @return String representation of the key which can be used as id - */ - static String joinFields(String keyName, String... fields) { - return keyName + SEPARATOR - + Joiner.on(SEPARATOR).useForNull("").join(fields); - } - } - - public static class GenericKey implements AsyncTaskKey { - private static final long serialVersionUID = -8648519833116851231L; - private final String id; - - GenericKey() { - id = UUID.randomUUID().toString(); - } - - public GenericKey(String id) { - this.id = id; - } - - @Override - public String id() { - return id; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("id", id) - .toString(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - GenericKey that = (GenericKey) o; - return Objects.equals(id, that.id); - } - - @Override - public int hashCode() { - return Objects.hash(id); - } - } } diff --git a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskKey.java b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskKey.java new file mode 100644 index 0000000000..d4f2cc7364 --- /dev/null +++ b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskKey.java @@ -0,0 +1,32 @@ +package org.zanata.async; + +import java.io.Serializable; + +import com.google.common.base.Joiner; + +/** + * @author Patrick Huang pahuang@redhat.com + */ +public interface AsyncTaskKey extends Serializable { + /** + * When converting multiple fields to form id string, we + * should use this as separator (URL friendly). + */ + String SEPARATOR = "-"; + + String id(); + + /** + * Helper method to convert list of fields to a String as key id. + * + * @param keyName + * the name for this key + * @param fields + * key instance field values + * @return String representation of the key which can be used as id + */ + static String joinFields(String keyName, String... fields) { + return keyName + SEPARATOR + + Joiner.on(SEPARATOR).useForNull("").join(fields); + } +} diff --git a/server/zanata-war/src/main/java/org/zanata/async/GenericAsyncTaskKey.java b/server/zanata-war/src/main/java/org/zanata/async/GenericAsyncTaskKey.java new file mode 100644 index 0000000000..8c730ccfc7 --- /dev/null +++ b/server/zanata-war/src/main/java/org/zanata/async/GenericAsyncTaskKey.java @@ -0,0 +1,47 @@ +package org.zanata.async; + +import java.util.Objects; +import java.util.UUID; + +import com.google.common.base.MoreObjects; + +/** + * @author Patrick Huang pahuang@redhat.com + */ +public class GenericAsyncTaskKey implements AsyncTaskKey { + private static final long serialVersionUID = -8648519833116851231L; + private final String id; + + GenericAsyncTaskKey() { + id = UUID.randomUUID().toString(); + } + + public GenericAsyncTaskKey(String id) { + this.id = id; + } + + @Override + public String id() { + return id; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("id", id) + .toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + GenericAsyncTaskKey that = (GenericAsyncTaskKey) o; + return Objects.equals(id, that.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); + } +} diff --git a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java index 14f4cd46ae..be516040f9 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java @@ -30,6 +30,7 @@ import org.slf4j.LoggerFactory; import org.zanata.async.AsyncTaskHandle; import org.zanata.async.AsyncTaskHandleManager; +import org.zanata.async.GenericAsyncTaskKey; import org.zanata.async.handle.TransMemoryMergeTaskHandle; import org.zanata.common.LocaleId; import org.zanata.model.HAccount; @@ -42,7 +43,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import static org.zanata.async.AsyncTaskHandleManager.AsyncTaskKey.joinFields; +import static org.zanata.async.AsyncTaskKey.joinFields; /** * @author Patrick Huang @@ -120,7 +121,7 @@ public boolean cancelTransMemoryMerge(TransMemoryMergeCancelRequest request) { @SuppressFBWarnings(value = "EQ_DOESNT_OVERRIDE_EQUALS", justification = "super class equals method is sufficient") static class TMMergeForDocTaskKey extends - AsyncTaskHandleManager.GenericKey { + GenericAsyncTaskKey { private static final long serialVersionUID = -7210004008208642L; private static final String KEY_NAME = "TMMergeForDocKey"; diff --git a/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java b/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java index 3801dacbaf..94e641e727 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java @@ -11,7 +11,7 @@ import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.zanata.async.AsyncTaskHandleManager; -import org.zanata.async.AsyncTaskHandleManager.AsyncTaskKey; +import org.zanata.async.AsyncTaskKey; import org.zanata.async.handle.TransMemoryMergeTaskHandle; import org.zanata.common.LocaleId; import org.zanata.common.ProjectType; From aaffc27dbe85fb69b9253bd7e4f05c87e72ff53e Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Tue, 20 Jun 2017 14:19:44 +1000 Subject: [PATCH 028/116] add comment to class --- .../src/main/java/org/zanata/async/AsyncTaskKey.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskKey.java b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskKey.java index d4f2cc7364..87b2c81792 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskKey.java +++ b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskKey.java @@ -14,6 +14,9 @@ public interface AsyncTaskKey extends Serializable { */ String SEPARATOR = "-"; + /** + * @return a unique identifier for the key + */ String id(); /** From 6b5982d06bef2343c63b91f46740c0341e680306 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Wed, 21 Jun 2017 10:04:43 +1000 Subject: [PATCH 029/116] ZNTA-1865 - add javadoc to TM merge for version api --- .../rest/service/ProjectVersionService.java | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java index df1e67a3e9..2dc65787ce 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java @@ -4,24 +4,25 @@ import static org.zanata.common.EntityStatus.OBSOLETE; import static org.zanata.common.EntityStatus.READONLY; import static org.zanata.webtrans.server.rpc.GetTransUnitsNavigationService.TextFlowResultTransformer; + import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; + import javax.inject.Inject; import javax.inject.Named; import javax.ws.rs.DefaultValue; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; -import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.EntityTag; import javax.ws.rs.core.GenericEntity; import javax.ws.rs.core.Request; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; -import com.google.common.base.Objects; + import org.apache.commons.lang.StringUtils; import org.apache.deltaspike.jpa.api.transaction.Transactional; import org.zanata.ApplicationConfiguration; @@ -48,17 +49,15 @@ import org.zanata.rest.dto.User; import org.zanata.rest.dto.VersionTMMerge; import org.zanata.rest.dto.resource.ResourceMeta; -import org.zanata.rest.editor.service.TransMemoryMergeManager; import org.zanata.rest.editor.service.UserService; -import org.zanata.webtrans.shared.model.ProjectIterationId; -import org.zanata.webtrans.shared.rest.dto.TransMemoryMergeRequest; -import org.zanata.webtrans.shared.rpc.MergeRule; -import org.zanata.webtrans.shared.search.FilterConstraints; import org.zanata.security.ZanataIdentity; import org.zanata.service.ConfigurationService; import org.zanata.service.LocaleService; import org.zanata.webtrans.shared.model.DocumentId; +import org.zanata.webtrans.shared.search.FilterConstraints; + import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Objects; import com.google.common.collect.Lists; /** @@ -332,6 +331,33 @@ public Response getTransUnitStatus( return Response.ok(entity).build(); } + /** + * + * Trigger a TM merge for the target version. It will run in the background + * and pre-fill translations from TM based on user selected criteria. + * + * @param projectSlug + * The project slug/ID + * @param versionSlug + * The project version slug/ID + * @param mergeRequest + * TM merge criteria + * @return The following response status codes will be returned from this + * operation:
+ * ACCEPTED(202) - If the process is successfully triggered.
+ * UNACCEPTED(400) - If the incoming payload is invalid or there is + * already a TM merge process running for this version and target + * language.
+ * NOT FOUND(404) - If no project or version was found for the given + * project slug and version slug.
+ * FORBIDDEN(403) - If the user was not allowed to create/modify the + * project iteration. In this case an error message is contained in + * the response.
+ * UNAUTHORIZED(401) - If the user does not have the proper + * permissions to perform this operation.
+ * INTERNAL SERVER ERROR(500) - If there is an unexpected error in + * the server while performing this operation. + */ @POST @Path(VERSION_SLUG_TEMPLATE + "/tm-merge") public Response prefillWithTM(@PathParam("projectSlug") String projectSlug, From eb346f12d45a5d49b9336588236b2e43dabefe19 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Wed, 21 Jun 2017 15:50:49 +1000 Subject: [PATCH 030/116] ZNTA-1865 fix test --- .../java/org/zanata/rest/service/ProjectVersionTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/ProjectVersionTest.java b/server/zanata-war/src/test/java/org/zanata/rest/service/ProjectVersionTest.java index ade045694c..1c93326f88 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/ProjectVersionTest.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/ProjectVersionTest.java @@ -38,6 +38,7 @@ import org.zanata.rest.dto.VersionTMMerge; import org.zanata.rest.editor.service.resource.UserResource; import org.zanata.seam.security.IdentityManager; +import org.zanata.security.ZanataIdentity; import org.zanata.security.annotations.Authenticated; import org.zanata.service.ConfigurationService; import org.zanata.service.GravatarService; @@ -74,6 +75,7 @@ public class ProjectVersionTest extends ZanataDbunitJpaTest { @Produces @Mock WindowContext windowContext; @Produces @Mock UrlUtil urlUtil; @Produces @Mock IdentityManager identityManager; + @Produces @Mock ZanataIdentity identity; @Produces @Mock MergeTranslationsManager mergeTranslationsManager; @@ -223,8 +225,8 @@ public void versionTMMergeThrowsExceptionIfAnotherMergeProcessIsRunning() { assertThatThrownBy(() -> { service.prefillWithTM(projectSlug, versionSlug, mergeRequest); }) - .hasMessage("There is already version merge operation in progress") - .isInstanceOf(UnsupportedOperationException.class); + .isInstanceOf(UnsupportedOperationException.class) + .hasMessage("There is already version merge operation in progress"); } @Test From 29c8a09ed92803662387e15503d6871aac8b5696 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Wed, 21 Jun 2017 16:14:33 +1000 Subject: [PATCH 031/116] ZNTA-1865 - refactor move methods and class --- .../action/MergeTranslationsManager.java | 47 +--------- .../service/TransMemoryMergeManager.java | 54 ++++++++++- .../rest/service/ProjectVersionService.java | 10 +- .../service/MergeTranslationsService.java | 5 - .../service/TransMemoryMergeService.java | 18 ++++ .../impl/MergeTranslationsServiceImpl.java | 78 ---------------- .../impl/TransMemoryMergeServiceImpl.java | 93 +++++++++++++++++++ .../service/TransMemoryMergeManagerTest.java | 4 +- .../rest/service/ProjectVersionTest.java | 11 +-- .../impl/TransMemoryMergeServiceImplTest.java | 11 +++ 10 files changed, 190 insertions(+), 141 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java index 473205cdd1..90cb4c372a 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java @@ -1,7 +1,6 @@ package org.zanata.action; import java.io.Serializable; -import java.util.Objects; import javax.enterprise.context.Dependent; import javax.inject.Inject; @@ -9,8 +8,8 @@ import org.zanata.async.AsyncTaskHandle; import org.zanata.async.AsyncTaskHandleManager; import org.zanata.async.handle.MergeTranslationsTaskHandle; -import org.zanata.common.LocaleId; import org.zanata.rest.dto.VersionTMMerge; +import org.zanata.rest.editor.service.TransMemoryMergeManager; import org.zanata.security.ZanataIdentity; import org.zanata.service.MergeTranslationsService; @@ -94,24 +93,6 @@ public boolean isRunning(String projectSlug, String versionSlug) { return handle != null && !handle.isDone(); } - public boolean start(Long versionId, VersionTMMerge mergeRequest) { - MergeTranslationTaskKey key = - new MergeTranslationTaskKey(versionId, mergeRequest.getLocaleId()); - AsyncTaskHandle handleByKey = - asyncTaskHandleManager.getHandleByKey(key); - if (handleByKey == null || handleByKey.isCancelled() - || handleByKey.isDone()) { - MergeTranslationsTaskHandle handle = new MergeTranslationsTaskHandle(); - - handle.setTriggeredBy(identity.getAccountUsername()); - asyncTaskHandleManager.registerTaskHandle(handle, key); - mergeTranslationsServiceImpl.startMergeTranslations(versionId, - mergeRequest, handle); - return true; - } - return false; - } - /** * Key used for copy version task */ @@ -174,30 +155,4 @@ public Key(final String projectSlug, final String versionSlug) { } - static class MergeTranslationTaskKey implements Serializable { - - private static final long serialVersionUID = 5671982177725183233L; - private final Long versionId; - private final LocaleId localeId; - - public MergeTranslationTaskKey(Long versionId, LocaleId localeId) { - this.versionId = versionId; - this.localeId = localeId; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - MergeTranslationTaskKey that = (MergeTranslationTaskKey) o; - return Objects.equals(versionId, that.versionId) && - Objects.equals(localeId, that.localeId); - } - - @Override - public int hashCode() { - return Objects - .hash(versionId, localeId); - } - } } diff --git a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java index 21973c610e..7ea05bed74 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java @@ -31,9 +31,12 @@ import org.slf4j.LoggerFactory; import org.zanata.async.AsyncTaskHandle; import org.zanata.async.AsyncTaskHandleManager; +import org.zanata.async.handle.MergeTranslationsTaskHandle; import org.zanata.async.handle.TransMemoryMergeTaskHandle; import org.zanata.common.LocaleId; import org.zanata.model.HAccount; +import org.zanata.rest.dto.VersionTMMerge; +import org.zanata.security.ZanataIdentity; import org.zanata.security.annotations.Authenticated; import org.zanata.service.TransMemoryMergeService; import org.zanata.webtrans.shared.model.DocumentId; @@ -57,14 +60,18 @@ public class TransMemoryMergeManager implements Serializable { private final HAccount authenticated; + private final ZanataIdentity identity; + @Inject public TransMemoryMergeManager( AsyncTaskHandleManager asyncTaskHandleManager, TransMemoryMergeService transMemoryMergeService, - @Authenticated HAccount authenticated) { + @Authenticated HAccount authenticated, + ZanataIdentity identity) { this.asyncTaskHandleManager = asyncTaskHandleManager; this.transMemoryMergeService = transMemoryMergeService; this.authenticated = authenticated; + this.identity = identity; } /** @@ -116,6 +123,24 @@ public boolean cancelTransMemoryMerge(TransMemoryMergeCancelRequest request) { return false; } + public boolean start(Long versionId, VersionTMMerge mergeRequest) { + TransMemoryMergeManager.MergeTranslationTaskKey key = + new TransMemoryMergeManager.MergeTranslationTaskKey(versionId, mergeRequest.getLocaleId()); + AsyncTaskHandle handleByKey = + asyncTaskHandleManager.getHandleByKey(key); + if (handleByKey == null || handleByKey.isCancelled() + || handleByKey.isDone()) { + MergeTranslationsTaskHandle handle = new MergeTranslationsTaskHandle(); + + handle.setTriggeredBy(identity.getAccountUsername()); + asyncTaskHandleManager.registerTaskHandle(handle, key); + transMemoryMergeService.startMergeTranslations(versionId, + mergeRequest, handle); + return true; + } + return false; + } + static class TransMemoryTaskKey implements Serializable { @SuppressFBWarnings("SE_BAD_FIELD") @@ -154,4 +179,31 @@ public String toString() { .toString(); } } + + public static class MergeTranslationTaskKey implements Serializable { + + private static final long serialVersionUID = 5671982177725183233L; + private final Long versionId; + private final LocaleId localeId; + + public MergeTranslationTaskKey(Long versionId, LocaleId localeId) { + this.versionId = versionId; + this.localeId = localeId; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MergeTranslationTaskKey that = (MergeTranslationTaskKey) o; + return Objects.equals(versionId, that.versionId) && + Objects.equals(localeId, that.localeId); + } + + @Override + public int hashCode() { + return Objects + .hash(versionId, localeId); + } + } } diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java index 2dc65787ce..03ec0de3fc 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java @@ -26,7 +26,6 @@ import org.apache.commons.lang.StringUtils; import org.apache.deltaspike.jpa.api.transaction.Transactional; import org.zanata.ApplicationConfiguration; -import org.zanata.action.MergeTranslationsManager; import org.zanata.common.ContentState; import org.zanata.common.EntityStatus; import org.zanata.common.LocaleId; @@ -49,6 +48,7 @@ import org.zanata.rest.dto.User; import org.zanata.rest.dto.VersionTMMerge; import org.zanata.rest.dto.resource.ResourceMeta; +import org.zanata.rest.editor.service.TransMemoryMergeManager; import org.zanata.rest.editor.service.UserService; import org.zanata.security.ZanataIdentity; import org.zanata.service.ConfigurationService; @@ -96,7 +96,7 @@ public class ProjectVersionService implements ProjectVersionResource { @Context private UriInfo uri; @Inject - private MergeTranslationsManager mergeTranslationsManager; + private TransMemoryMergeManager transMemoryMergeManager; @Override public Response head(@PathParam("projectSlug") String projectSlug, @@ -388,6 +388,10 @@ public Response prefillWithTM(@PathParam("projectSlug") String projectSlug, .entity("Project version \'" + projectSlug + ":" + versionSlug + "\' is readonly.") .build(); + } else if (version.getDocuments().isEmpty()) { + return Response.status(Response.Status.BAD_REQUEST) + .entity("{\"error\":\"project version has no documents\"}") + .build(); } LocaleId localeId = mergeRequest.getLocaleId(); HLocale hLocale = localeServiceImpl.getByLocaleId(localeId); @@ -396,7 +400,7 @@ public Response prefillWithTM(@PathParam("projectSlug") String projectSlug, } identity.checkPermission("modify-translation", hProject, hLocale); - boolean started = mergeTranslationsManager + boolean started = transMemoryMergeManager .start(version.getId(), mergeRequest); if (!started) { throw new UnsupportedOperationException("There is already version merge operation in progress"); diff --git a/server/zanata-war/src/main/java/org/zanata/service/MergeTranslationsService.java b/server/zanata-war/src/main/java/org/zanata/service/MergeTranslationsService.java index 1ba9111119..368537b1b2 100644 --- a/server/zanata-war/src/main/java/org/zanata/service/MergeTranslationsService.java +++ b/server/zanata-war/src/main/java/org/zanata/service/MergeTranslationsService.java @@ -24,9 +24,7 @@ import java.util.concurrent.Future; import org.zanata.async.handle.MergeTranslationsTaskHandle; -import org.zanata.common.LocaleId; import org.zanata.model.HProjectIteration; -import org.zanata.rest.dto.VersionTMMerge; public interface MergeTranslationsService extends Serializable { //@formatter:off @@ -55,7 +53,4 @@ Future startMergeTranslations(String sourceProjectSlug, int getTotalProgressCount(HProjectIteration sourceVersion, HProjectIteration targetVersion); - Future startMergeTranslations(Long versionId, - VersionTMMerge mergeRequest, - MergeTranslationsTaskHandle handle); } diff --git a/server/zanata-war/src/main/java/org/zanata/service/TransMemoryMergeService.java b/server/zanata-war/src/main/java/org/zanata/service/TransMemoryMergeService.java index 6cb2bd1f1e..0664f311c3 100644 --- a/server/zanata-war/src/main/java/org/zanata/service/TransMemoryMergeService.java +++ b/server/zanata-war/src/main/java/org/zanata/service/TransMemoryMergeService.java @@ -29,6 +29,7 @@ import org.zanata.model.HLocale; import org.zanata.model.HProjectIteration; import org.zanata.model.HTextFlow; +import org.zanata.rest.dto.VersionTMMerge; import org.zanata.webtrans.shared.model.ProjectIterationId; import org.zanata.webtrans.shared.rest.dto.HasTMMergeCriteria; import org.zanata.webtrans.shared.rest.dto.TransMemoryMergeRequest; @@ -39,10 +40,27 @@ List executeMerge( TransMemoryMergeRequest request, TransMemoryMergeTaskHandle asyncTaskHandle); + /** + * TM merge for a single document + * @param request + * @param asyncTaskHandle + * @return + */ Future> executeMergeAsync(TransMemoryMergeRequest request, TransMemoryMergeTaskHandle asyncTaskHandle); void translateInBatch(HasTMMergeCriteria mergeCriteria, List textFlows, HLocale targetLocale, List fromProjectVersionIds); + + /** + * TM merge for a project version + * @param versionId + * @param mergeRequest + * @param handle + * @return + */ + Future startMergeTranslations(Long versionId, + VersionTMMerge mergeRequest, + MergeTranslationsTaskHandle handle); } diff --git a/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java b/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java index 40420847c1..5777d2e1fb 100644 --- a/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java +++ b/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java @@ -104,9 +104,6 @@ public class MergeTranslationsServiceImpl implements MergeTranslationsService { @Authenticated private HAccount authenticatedAccount; - @Inject - private TransMemoryMergeService transMemoryMergeService; - /** * Batch size for find matching HTextFlow to process merging of * translations. Each TextFlow may lead to changes in multiple @@ -354,81 +351,6 @@ public int getTotalProgressCount(HProjectIteration sourceVersion, return matchCount * locales.size(); } - @Async - @Override - public Future startMergeTranslations(Long targetVersionId, - VersionTMMerge mergeRequest, - MergeTranslationsTaskHandle handle) { - // since this is async we need to reload entities - HProjectIteration targetVersion = - projectIterationDAO.findById(targetVersionId); - HLocale targetLocale = - localeServiceImpl.getByLocaleId(mergeRequest.getLocaleId()); - - if (isVersionEmpty(targetVersion)) { - return AsyncTaskResult.completed(); - } - List localesInTargetVersion = localeServiceImpl - .getSupportedLanguageByProjectIteration(targetVersion); - if (!localesInTargetVersion.contains(targetLocale)) { - log.error("No locales enabled in target version of [{}]", - targetVersion.userFriendlyToString()); - return AsyncTaskResult.completed(); - } - - List fromVersionIds = mergeRequest.getFromProjectVersions().stream() - .map(projectIterationId -> projectIterationDAO.getBySlug( - projectIterationId.getProjectSlug(), - projectIterationId.getIterationSlug())) - .filter(ver -> ver != null - && ver.getStatus() != EntityStatus.OBSOLETE - && localeServiceImpl - .getSupportedLanguageByProjectIteration(ver) - .contains(targetLocale)) - .map(ModelEntityBase::getId).collect(Collectors.toList()); - - if (fromVersionIds.isEmpty()) { - log.error("Cannot find source versions of {}", fromVersionIds); - return AsyncTaskResult.completed(); - } - - long mergeTargetCount = textFlowDAO.getUntranslatedOrFuzzyTextFlowCountInVersion( - targetVersion.getId(), targetLocale); - - Optional taskHandleOpt = - Optional.fromNullable(handle); - if (taskHandleOpt.isPresent()) { - MergeTranslationsTaskHandle handle1 = taskHandleOpt.get(); - handle1.setTriggeredBy(identity.getAccountUsername()); - handle1.setMaxProgress((int) mergeTargetCount); - handle1.setTotalTranslations(mergeTargetCount); - } - Stopwatch overallStopwatch = Stopwatch.createStarted(); - log.info("merge translations from TM start: from {} to {}", - fromVersionIds, - targetVersion.userFriendlyToString()); - int startCount = 0; - - while (startCount < mergeTargetCount) { - List batch = textFlowDAO - .getUntranslatedOrFuzzyTextFlowsInVersion( - targetVersion.getId(), targetLocale, startCount, - TEXTFLOWS_PER_BATCH); - transMemoryMergeService.translateInBatch(mergeRequest, batch, - targetLocale, fromVersionIds); - - if (taskHandleOpt.isPresent()) { - taskHandleOpt.get().increaseProgress(batch.size()); - } - startCount += TEXTFLOWS_PER_BATCH; - } - versionStateCacheImpl.clearVersionStatsCache(targetVersion.getId()); - log.info("merge translation from TM end: from {} to {}, {}", - mergeRequest.getFromProjectVersions(), - targetVersion.userFriendlyToString(), overallStopwatch); - return AsyncTaskResult.completed(); - } - private int getTotalMatchCount(Long sourceVersionId, Long targetVersionId) { return textFlowDAO.getSourceByMatchedContextCount(sourceVersionId, targetVersionId); diff --git a/server/zanata-war/src/main/java/org/zanata/service/impl/TransMemoryMergeServiceImpl.java b/server/zanata-war/src/main/java/org/zanata/service/impl/TransMemoryMergeServiceImpl.java index 9df290256d..ac90df3f71 100644 --- a/server/zanata-war/src/main/java/org/zanata/service/impl/TransMemoryMergeServiceImpl.java +++ b/server/zanata-war/src/main/java/org/zanata/service/impl/TransMemoryMergeServiceImpl.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.Optional; import java.util.concurrent.Future; +import java.util.stream.Collectors; import javax.enterprise.context.RequestScoped; import javax.enterprise.event.Event; @@ -36,8 +37,11 @@ import org.slf4j.LoggerFactory; import org.zanata.async.Async; import org.zanata.async.AsyncTaskResult; +import org.zanata.async.handle.MergeTranslationsTaskHandle; import org.zanata.async.handle.TransMemoryMergeTaskHandle; import org.zanata.common.ContentState; +import org.zanata.common.EntityStatus; +import org.zanata.dao.ProjectIterationDAO; import org.zanata.dao.TextFlowDAO; import org.zanata.dao.TransMemoryUnitDAO; import org.zanata.events.TextFlowTargetUpdateContextEvent; @@ -45,16 +49,21 @@ import org.zanata.events.TransMemoryMergeProgressEvent; import org.zanata.model.HAccount; import org.zanata.model.HLocale; +import org.zanata.model.HProjectIteration; import org.zanata.model.HTextFlow; import org.zanata.model.HTextFlowTarget; +import org.zanata.model.ModelEntityBase; import org.zanata.model.tm.TransMemoryUnit; import org.zanata.model.type.EntityType; import org.zanata.model.type.TranslationSourceType; +import org.zanata.rest.dto.VersionTMMerge; +import org.zanata.security.ZanataIdentity; import org.zanata.security.annotations.Authenticated; import org.zanata.service.LocaleService; import org.zanata.service.TransMemoryMergeService; import org.zanata.service.TranslationMemoryService; import org.zanata.service.TranslationService; +import org.zanata.service.VersionStateCache; import org.zanata.transaction.TransactionUtil; import org.zanata.util.TransMemoryMergeStatusResolver; import org.zanata.util.TranslationUtil; @@ -70,11 +79,13 @@ import org.zanata.webtrans.shared.search.FilterConstraints; import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Stopwatch; import com.google.common.collect.Lists; /** * @author Sean Flanigan * sflaniga@redhat.com + * @author Patrick Huang pahuang@redhat.com */ @Named("transMemoryMergeServiceImpl") @RequestScoped @@ -111,6 +122,15 @@ public class TransMemoryMergeServiceImpl implements TransMemoryMergeService { @Inject private TransactionUtil transactionUtil; + @Inject + private ProjectIterationDAO projectIterationDAO; + + @Inject + private ZanataIdentity identity; + + @Inject + private VersionStateCache versionStateCacheImpl; + @Inject @Authenticated private HAccount authenticatedAccount; @@ -254,6 +274,79 @@ private List translateInBatch( } } + @Async + @Override + public Future startMergeTranslations(Long targetVersionId, + VersionTMMerge mergeRequest, + MergeTranslationsTaskHandle handle) { + // since this is async we need to reload entities + HProjectIteration targetVersion = + projectIterationDAO.findById(targetVersionId); + HLocale targetLocale = + localeServiceImpl.getByLocaleId(mergeRequest.getLocaleId()); + + List localesInTargetVersion = localeServiceImpl + .getSupportedLanguageByProjectIteration(targetVersion); + if (!localesInTargetVersion.contains(targetLocale)) { + log.error("No locales enabled in target version of [{}]", + targetVersion.userFriendlyToString()); + return AsyncTaskResult.completed(); + } + + List fromVersionIds = mergeRequest.getFromProjectVersions().stream() + .map(projectIterationId -> projectIterationDAO.getBySlug( + projectIterationId.getProjectSlug(), + projectIterationId.getIterationSlug())) + .filter(ver -> ver != null + && ver.getStatus() != EntityStatus.OBSOLETE + && localeServiceImpl + .getSupportedLanguageByProjectIteration(ver) + .contains(targetLocale)) + .map(ModelEntityBase::getId).collect(Collectors.toList()); + + if (fromVersionIds.isEmpty()) { + log.error("Cannot find source versions of {}", fromVersionIds); + return AsyncTaskResult.completed(); + } + + long mergeTargetCount = textFlowDAO.getUntranslatedOrFuzzyTextFlowCountInVersion( + targetVersion.getId(), targetLocale); + + com.google.common.base.Optional + taskHandleOpt = + com.google.common.base.Optional.fromNullable(handle); + if (taskHandleOpt.isPresent()) { + MergeTranslationsTaskHandle handle1 = taskHandleOpt.get(); + handle1.setTriggeredBy(identity.getAccountUsername()); + handle1.setMaxProgress((int) mergeTargetCount); + handle1.setTotalTranslations(mergeTargetCount); + } + Stopwatch overallStopwatch = Stopwatch.createStarted(); + log.info("merge translations from TM start: from {} to {}", + fromVersionIds, + targetVersion.userFriendlyToString()); + int startCount = 0; + + while (startCount < mergeTargetCount) { + List batch = textFlowDAO + .getUntranslatedOrFuzzyTextFlowsInVersion( + targetVersion.getId(), targetLocale, startCount, + BATCH_SIZE); + translateInBatch(mergeRequest, batch, + targetLocale, fromVersionIds); + + if (taskHandleOpt.isPresent()) { + taskHandleOpt.get().increaseProgress(batch.size()); + } + startCount += BATCH_SIZE; + } + versionStateCacheImpl.clearVersionStatsCache(targetVersion.getId()); + log.info("merge translation from TM end: from {} to {}, {}", + mergeRequest.getFromProjectVersions(), + targetVersion.userFriendlyToString(), overallStopwatch); + return AsyncTaskResult.completed(); + } + // TODO pahuang this duplicated most part of above method @Override public void translateInBatch(HasTMMergeCriteria mergeCriteria, diff --git a/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java b/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java index 640b7baf96..6c87137f58 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java @@ -18,6 +18,7 @@ import org.zanata.common.ProjectType; import org.zanata.model.HAccount; import org.zanata.model.TestFixture; +import org.zanata.security.ZanataIdentity; import org.zanata.service.TransMemoryMergeService; import org.zanata.webtrans.shared.auth.EditorClientId; import org.zanata.webtrans.shared.model.DocumentId; @@ -40,6 +41,7 @@ public class TransMemoryMergeManagerTest { @Captor private ArgumentCaptor taskKeyCaptor; private TransMemoryMergeCancelRequest cancelRequest; + @Mock private ZanataIdentity identity; @Before public void setUp() { @@ -47,7 +49,7 @@ public void setUp() { authenticated = new HAccount(); authenticated.setUsername("admin"); manager = new TransMemoryMergeManager(asyncTaskHandleManager, - transMemoryMergeService, authenticated); + transMemoryMergeService, authenticated, identity); WorkspaceId workspaceId = TestFixture.workspaceId(LocaleId.DE, "project", "version", ProjectType.Gettext); diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/ProjectVersionTest.java b/server/zanata-war/src/test/java/org/zanata/rest/service/ProjectVersionTest.java index 1c93326f88..430946011f 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/ProjectVersionTest.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/ProjectVersionTest.java @@ -25,17 +25,14 @@ import org.mockito.Mock; import org.zanata.ApplicationConfiguration; import org.zanata.ZanataDbunitJpaTest; -import org.zanata.action.MergeTranslationsManager; -import org.zanata.common.EntityStatus; import org.zanata.common.LocaleId; import org.zanata.i18n.Messages; import org.zanata.jpa.FullText; import org.zanata.model.HAccount; import org.zanata.model.HLocale; -import org.zanata.model.HProject; -import org.zanata.model.HProjectIteration; import org.zanata.rest.dto.User; import org.zanata.rest.dto.VersionTMMerge; +import org.zanata.rest.editor.service.TransMemoryMergeManager; import org.zanata.rest.editor.service.resource.UserResource; import org.zanata.seam.security.IdentityManager; import org.zanata.security.ZanataIdentity; @@ -77,7 +74,7 @@ public class ProjectVersionTest extends ZanataDbunitJpaTest { @Produces @Mock IdentityManager identityManager; @Produces @Mock ZanataIdentity identity; - @Produces @Mock MergeTranslationsManager mergeTranslationsManager; + @Produces @Mock TransMemoryMergeManager transMemoryMergeManager; @Override @Produces @@ -220,7 +217,7 @@ public void versionTMMergeThrowsExceptionIfAnotherMergeProcessIsRunning() { // when there is already a merge process running when(localeService.getByLocaleId(LocaleId.FR)).thenReturn(new HLocale(LocaleId.FR)); - when(mergeTranslationsManager.start(1L, mergeRequest)).thenReturn(false); + when(transMemoryMergeManager.start(1L, mergeRequest)).thenReturn(false); assertThatThrownBy(() -> { service.prefillWithTM(projectSlug, versionSlug, mergeRequest); @@ -239,7 +236,7 @@ public void versionTMMergeReturnsAcceptedIfEverythingIsGood() { MergeRule.FUZZY, MergeRule.FUZZY, MergeRule.FUZZY, Collections.emptyList()); - when(mergeTranslationsManager.start(2L, mergeRequest)).thenReturn(true); + when(transMemoryMergeManager.start(2L, mergeRequest)).thenReturn(true); assertThat(service.prefillWithTM(projectSlug, versionSlug, mergeRequest) .getStatus()).isEqualTo(NOT_FOUND.getStatusCode()); } diff --git a/server/zanata-war/src/test/java/org/zanata/service/impl/TransMemoryMergeServiceImplTest.java b/server/zanata-war/src/test/java/org/zanata/service/impl/TransMemoryMergeServiceImplTest.java index d164e75727..6a1b48d7d3 100644 --- a/server/zanata-war/src/test/java/org/zanata/service/impl/TransMemoryMergeServiceImplTest.java +++ b/server/zanata-war/src/test/java/org/zanata/service/impl/TransMemoryMergeServiceImplTest.java @@ -36,6 +36,7 @@ import java.util.List; import java.util.Optional; +import javax.enterprise.inject.Alternative; import javax.enterprise.inject.Produces; import javax.inject.Inject; @@ -52,6 +53,7 @@ import org.zanata.common.ContentState; import org.zanata.common.LocaleId; import org.zanata.common.ProjectType; +import org.zanata.dao.ProjectIterationDAO; import org.zanata.dao.TextFlowDAO; import org.zanata.dao.TransMemoryUnitDAO; import org.zanata.model.HAccount; @@ -60,11 +62,13 @@ import org.zanata.model.TestFixture; import org.zanata.model.tm.TransMemoryUnit; import org.zanata.model.type.TranslationSourceType; +import org.zanata.security.ZanataIdentity; import org.zanata.security.annotations.Authenticated; import org.zanata.service.LocaleService; import org.zanata.service.SecurityService; import org.zanata.service.TranslationMemoryService; import org.zanata.service.TranslationService; +import org.zanata.service.VersionStateCache; import org.zanata.test.CdiUnitRunner; import org.zanata.transaction.TransactionUtil; import org.zanata.transaction.TransactionUtilForUnitTest; @@ -124,6 +128,13 @@ public class TransMemoryMergeServiceImplTest { @Produces TransactionUtil transactionUtil = new TransactionUtilForUnitTest(null); + @Produces @Mock + private VersionStateCache versionStateCacheImpl; + @Produces @Mock + private ZanataIdentity identity; + @Produces @Mock + private ProjectIterationDAO projectIterationDAO; + private String projectSlug = "projectSlug"; private String versionSlug = "versionSlug"; private String docId = "pot/a.po"; From 75642f6f3d6e37a661741e683c41cc84429211e1 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Thu, 22 Jun 2017 12:15:05 +1000 Subject: [PATCH 032/116] ZNTA-1865 refactor: reduce code dep --- .../editor/service/TransMemoryMergeManager.java | 12 ++++-------- .../impl/MergeTranslationsServiceImpl.java | 4 +--- .../service/TransMemoryMergeManagerTest.java | 15 ++++++++------- .../impl/MergeTranslationsServiceImplTest.java | 7 ++----- 4 files changed, 15 insertions(+), 23 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java index 7ea05bed74..5434557b90 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java @@ -58,19 +58,15 @@ public class TransMemoryMergeManager implements Serializable { private final TransMemoryMergeService transMemoryMergeService; - private final HAccount authenticated; - private final ZanataIdentity identity; @Inject public TransMemoryMergeManager( AsyncTaskHandleManager asyncTaskHandleManager, TransMemoryMergeService transMemoryMergeService, - @Authenticated HAccount authenticated, ZanataIdentity identity) { this.asyncTaskHandleManager = asyncTaskHandleManager; this.transMemoryMergeService = transMemoryMergeService; - this.authenticated = authenticated; this.identity = identity; } @@ -92,7 +88,7 @@ public boolean startTransMemoryMerge(TransMemoryMergeRequest request) { if (handleByKey == null || handleByKey.isCancelled() || handleByKey.isDone()) { TransMemoryMergeTaskHandle handle = new TransMemoryMergeTaskHandle(); - handle.setTriggeredBy(authenticated.getUsername()); + handle.setTriggeredBy(identity.getAccountUsername()); asyncTaskHandleManager.registerTaskHandle(handle, key); transMemoryMergeService.executeMergeAsync(request, handle); return true; @@ -110,14 +106,14 @@ public boolean cancelTransMemoryMerge(TransMemoryMergeCancelRequest request) { TransMemoryMergeTaskHandle handle = (TransMemoryMergeTaskHandle) handleByKey; String triggeredBy = handle.getTriggeredBy(); - if (Objects.equals(authenticated.getUsername(), triggeredBy)) { + if (Objects.equals(identity.getAccountUsername(), triggeredBy)) { handle.cancel(true); handle.setCancelledTime(System.currentTimeMillis()); - handle.setCancelledBy(authenticated.getUsername()); + handle.setCancelledBy(identity.getAccountUsername()); log.info("task: {} cancelled by its creator", handle); return true; } else { - log.warn("{} is attempting to cancel {}", authenticated.getUsername(), handle); + log.warn("{} is attempting to cancel {}", identity.getAccountUsername(), handle); } } return false; diff --git a/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java b/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java index 5777d2e1fb..83fcddb65d 100644 --- a/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java +++ b/server/zanata-war/src/main/java/org/zanata/service/impl/MergeTranslationsServiceImpl.java @@ -89,8 +89,6 @@ public class MergeTranslationsServiceImpl implements MergeTranslationsService { @Inject private TextFlowDAO textFlowDAO; @Inject - private ZanataIdentity identity; - @Inject private VersionStateCache versionStateCacheImpl; @Inject private TranslationStateCache translationStateCacheImpl; @@ -335,7 +333,7 @@ private void prepareMergeTranslationsHandle( @Nonnull HProjectIteration sourceVersion, @Nonnull HProjectIteration targetVersion, @Nonnull MergeTranslationsTaskHandle handle) { - handle.setTriggeredBy(identity.getAccountUsername()); + handle.setTriggeredBy(authenticatedAccount.getUsername()); int total = getTotalProgressCount(sourceVersion, targetVersion); handle.setMaxProgress(total); handle.setTotalTranslations(total); diff --git a/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java b/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java index 6c87137f58..175a18931d 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java @@ -46,10 +46,9 @@ public class TransMemoryMergeManagerTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); - authenticated = new HAccount(); - authenticated.setUsername("admin"); + manager = new TransMemoryMergeManager(asyncTaskHandleManager, - transMemoryMergeService, authenticated, identity); + transMemoryMergeService, identity); WorkspaceId workspaceId = TestFixture.workspaceId(LocaleId.DE, "project", "version", ProjectType.Gettext); @@ -63,6 +62,8 @@ public void setUp() { cancelRequest = new TransMemoryMergeCancelRequest( workspaceId.getProjectIterationId(), documentId, workspaceId.getLocaleId()); + + when(identity.getAccountUsername()).thenReturn("admin"); } @Test @@ -75,7 +76,7 @@ public void setUp() { handleCaptor.capture(), taskKeyCaptor.capture()); TransMemoryMergeTaskHandle handle = handleCaptor.getValue(); assertThat(handle.getTriggeredBy()) - .isEqualTo(authenticated.getUsername()); + .isEqualTo(identity.getAccountUsername()); Mockito.verify(transMemoryMergeService).executeMergeAsync(request, handle); } @@ -104,7 +105,7 @@ public boolean isCancelled() { handleCaptor.capture(), taskKeyCaptor.capture()); TransMemoryMergeTaskHandle handle = handleCaptor.getValue(); assertThat(handle.getTriggeredBy()) - .isEqualTo(authenticated.getUsername()); + .isEqualTo(identity.getAccountUsername()); Mockito.verify(transMemoryMergeService).executeMergeAsync(request, handle); } @@ -133,7 +134,7 @@ public boolean isDone() { handleCaptor.capture(), taskKeyCaptor.capture()); TransMemoryMergeTaskHandle handle = handleCaptor.getValue(); assertThat(handle.getTriggeredBy()) - .isEqualTo(authenticated.getUsername()); + .isEqualTo(identity.getAccountUsername()); Mockito.verify(transMemoryMergeService).executeMergeAsync(request, handle); } @@ -231,7 +232,7 @@ public boolean cancel(boolean mayInterruptIfRunning) { return true; } }; - existingHandle.setTriggeredBy(authenticated.getUsername()); + existingHandle.setTriggeredBy(identity.getAccountUsername()); TransMemoryMergeManager.TransMemoryTaskKey taskKey = new TransMemoryMergeManager.TransMemoryTaskKey( diff --git a/server/zanata-war/src/test/java/org/zanata/service/impl/MergeTranslationsServiceImplTest.java b/server/zanata-war/src/test/java/org/zanata/service/impl/MergeTranslationsServiceImplTest.java index b1c436c71d..f6b664121b 100644 --- a/server/zanata-war/src/test/java/org/zanata/service/impl/MergeTranslationsServiceImplTest.java +++ b/server/zanata-war/src/test/java/org/zanata/service/impl/MergeTranslationsServiceImplTest.java @@ -103,9 +103,6 @@ public class MergeTranslationsServiceImplTest extends ZanataDbunitJpaTest { @Inject TextFlowTargetDAO textFlowTargetDAO; - @Produces @Mock - private ZanataIdentity identity; - @Produces @Mock @Authenticated HAccount authenticatedAccount; @@ -187,7 +184,7 @@ public void testMergeVersionNotExist() throws Exception { Future future = service.startMergeTranslations(projectSlug, sourceVersionSlug, projectSlug, targetVersionSlug, true, handle); - verifyZeroInteractions(identity); + verifyZeroInteractions(authenticatedAccount); // wait for the async process to finish... future.get(); // No translations were performed @@ -203,7 +200,7 @@ public void testMergeEmptyDoc() throws Exception { MergeTranslationsTaskHandle handle = new MergeTranslationsTaskHandle(); Future future = service.startMergeTranslations(projectSlug, sourceVersionSlug, projectSlug, targetVersionSlug, true, null); - verifyZeroInteractions(identity); + verifyZeroInteractions(authenticatedAccount); // wait for the async process to finish... future.get(); // No translations were performed From 494e5ea04efec894849422864f3b8a9d396ca905 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Thu, 22 Jun 2017 12:24:59 +1000 Subject: [PATCH 033/116] ZNTA-1865 move method and remove from versions list check --- .../service/TransMemoryMergeService.java | 4 - .../impl/TransMemoryMergeServiceImpl.java | 131 +++++++++--------- 2 files changed, 63 insertions(+), 72 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/service/TransMemoryMergeService.java b/server/zanata-war/src/main/java/org/zanata/service/TransMemoryMergeService.java index 0664f311c3..3119db01ee 100644 --- a/server/zanata-war/src/main/java/org/zanata/service/TransMemoryMergeService.java +++ b/server/zanata-war/src/main/java/org/zanata/service/TransMemoryMergeService.java @@ -49,10 +49,6 @@ List executeMerge( Future> executeMergeAsync(TransMemoryMergeRequest request, TransMemoryMergeTaskHandle asyncTaskHandle); - void translateInBatch(HasTMMergeCriteria mergeCriteria, - List textFlows, - HLocale targetLocale, List fromProjectVersionIds); - /** * TM merge for a project version * @param versionId diff --git a/server/zanata-war/src/main/java/org/zanata/service/impl/TransMemoryMergeServiceImpl.java b/server/zanata-war/src/main/java/org/zanata/service/impl/TransMemoryMergeServiceImpl.java index ac90df3f71..feac6bb232 100644 --- a/server/zanata-war/src/main/java/org/zanata/service/impl/TransMemoryMergeServiceImpl.java +++ b/server/zanata-war/src/main/java/org/zanata/service/impl/TransMemoryMergeServiceImpl.java @@ -211,69 +211,6 @@ public Future> executeMergeAsync(Tran return AsyncTaskResult.completed(translationResults); } - /** - * This method will run in transaction and manages its own transaction. - * - * @param request - * TM merge request - * @param textFlows - * the text flows to be filled - * @param targetLocale - * target locale - * @return translation results - */ - private List translateInBatch( - TransMemoryMergeRequest request, List textFlows, - HLocale targetLocale) { - - if (textFlows.isEmpty()) { - return Collections.emptyList(); - } - try { - return transactionUtil.call(() -> { - boolean checkContext = - request.getDifferentContextRule() == MergeRule.REJECT; - boolean checkDocument = - request.getDifferentDocumentRule() == MergeRule.REJECT; - boolean checkProject = - request.getDifferentProjectRule() == MergeRule.REJECT; - - List updateRequests = Lists.newLinkedList(); - for (HTextFlow hTextFlow : textFlows) { - HTextFlowTarget hTextFlowTarget = - hTextFlow.getTargets().get(targetLocale.getId()); - Optional tmResult = - translationMemoryServiceImpl.searchBestMatchTransMemory( - hTextFlow, targetLocale.getLocaleId(), - hTextFlow.getDocument().getLocale().getLocaleId(), - checkContext, checkDocument, checkProject, - request.getThresholdPercent(), - Collections.emptyList()); - if (tmResult.isPresent()) { - TransUnitUpdateRequest updateRequest = - createRequest(request, targetLocale, - hTextFlow, tmResult.get(), hTextFlowTarget); - - if (updateRequest != null) { - updateRequests.add(updateRequest); - textFlowTargetUpdateContextEvent - .fire(new TextFlowTargetUpdateContextEvent( - updateRequest.getTransUnitId(), - request.localeId, - request.editorClientId, - TransUnitUpdated.UpdateType.NonEditorSave)); - } - } - } - return translationServiceImpl.translate( - request.localeId, updateRequests); - }); - } catch (Exception e) { - log.error("exception during TM merge", e); - return Collections.emptyList(); - } - } - @Async @Override public Future startMergeTranslations(Long targetVersionId, @@ -304,10 +241,6 @@ public Future startMergeTranslations(Long targetVersionId, .contains(targetLocale)) .map(ModelEntityBase::getId).collect(Collectors.toList()); - if (fromVersionIds.isEmpty()) { - log.error("Cannot find source versions of {}", fromVersionIds); - return AsyncTaskResult.completed(); - } long mergeTargetCount = textFlowDAO.getUntranslatedOrFuzzyTextFlowCountInVersion( targetVersion.getId(), targetLocale); @@ -347,8 +280,70 @@ public Future startMergeTranslations(Long targetVersionId, return AsyncTaskResult.completed(); } + /** + * This method will run in transaction and manages its own transaction. + * + * @param request + * TM merge request + * @param textFlows + * the text flows to be filled + * @param targetLocale + * target locale + * @return translation results + */ + private List translateInBatch( + TransMemoryMergeRequest request, List textFlows, + HLocale targetLocale) { + + if (textFlows.isEmpty()) { + return Collections.emptyList(); + } + try { + return transactionUtil.call(() -> { + boolean checkContext = + request.getDifferentContextRule() == MergeRule.REJECT; + boolean checkDocument = + request.getDifferentDocumentRule() == MergeRule.REJECT; + boolean checkProject = + request.getDifferentProjectRule() == MergeRule.REJECT; + + List updateRequests = Lists.newLinkedList(); + for (HTextFlow hTextFlow : textFlows) { + HTextFlowTarget hTextFlowTarget = + hTextFlow.getTargets().get(targetLocale.getId()); + Optional tmResult = + translationMemoryServiceImpl.searchBestMatchTransMemory( + hTextFlow, targetLocale.getLocaleId(), + hTextFlow.getDocument().getLocale().getLocaleId(), + checkContext, checkDocument, checkProject, + request.getThresholdPercent(), + Collections.emptyList()); + if (tmResult.isPresent()) { + TransUnitUpdateRequest updateRequest = + createRequest(request, targetLocale, + hTextFlow, tmResult.get(), hTextFlowTarget); + + if (updateRequest != null) { + updateRequests.add(updateRequest); + textFlowTargetUpdateContextEvent + .fire(new TextFlowTargetUpdateContextEvent( + updateRequest.getTransUnitId(), + request.localeId, + request.editorClientId, + TransUnitUpdated.UpdateType.NonEditorSave)); + } + } + } + return translationServiceImpl.translate( + request.localeId, updateRequests); + }); + } catch (Exception e) { + log.error("exception during TM merge", e); + return Collections.emptyList(); + } + } + // TODO pahuang this duplicated most part of above method - @Override public void translateInBatch(HasTMMergeCriteria mergeCriteria, List textFlows, HLocale targetLocale, List fromProjectVersions) { From 3219cb68518cf3a615550351dde86e40cf62c233 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Thu, 22 Jun 2017 12:41:06 +1000 Subject: [PATCH 034/116] ZNTA-1865 refactor: reduce code dup --- .../impl/TransMemoryMergeServiceImpl.java | 99 ++++++------------- 1 file changed, 30 insertions(+), 69 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/service/impl/TransMemoryMergeServiceImpl.java b/server/zanata-war/src/main/java/org/zanata/service/impl/TransMemoryMergeServiceImpl.java index feac6bb232..4fc34f3c48 100644 --- a/server/zanata-war/src/main/java/org/zanata/service/impl/TransMemoryMergeServiceImpl.java +++ b/server/zanata-war/src/main/java/org/zanata/service/impl/TransMemoryMergeServiceImpl.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.Optional; import java.util.concurrent.Future; +import java.util.function.Consumer; import java.util.stream.Collectors; import javax.enterprise.context.RequestScoped; @@ -178,8 +179,17 @@ public List executeMerge( index = index + processedSize; asyncTaskHandle.setTextFlowFilled(index); + Consumer + callback = + updateRequest -> textFlowTargetUpdateContextEvent + .fire(new TextFlowTargetUpdateContextEvent( + updateRequest.getTransUnitId(), + request.localeId, + request.editorClientId, + TransUnitUpdated.UpdateType.NonEditorSave)); List batchResult = - translateInBatch(request, textFlowsBatch, targetLocale); + translateInBatch(request, textFlowsBatch, targetLocale, + Collections.emptyList(), Optional.of(callback)); finalResult.addAll(batchResult); log.debug("TM merge handle: {}", asyncTaskHandle); transMemoryMergeProgressEvent @@ -245,9 +255,8 @@ public Future startMergeTranslations(Long targetVersionId, long mergeTargetCount = textFlowDAO.getUntranslatedOrFuzzyTextFlowCountInVersion( targetVersion.getId(), targetLocale); - com.google.common.base.Optional - taskHandleOpt = - com.google.common.base.Optional.fromNullable(handle); + Optional + taskHandleOpt = Optional.ofNullable(handle); if (taskHandleOpt.isPresent()) { MergeTranslationsTaskHandle handle1 = taskHandleOpt.get(); handle1.setTriggeredBy(identity.getAccountUsername()); @@ -266,11 +275,11 @@ public Future startMergeTranslations(Long targetVersionId, targetVersion.getId(), targetLocale, startCount, BATCH_SIZE); translateInBatch(mergeRequest, batch, - targetLocale, fromVersionIds); + targetLocale, fromVersionIds, Optional.empty()); - if (taskHandleOpt.isPresent()) { - taskHandleOpt.get().increaseProgress(batch.size()); - } + taskHandleOpt.ifPresent( + mergeTranslationsTaskHandle -> mergeTranslationsTaskHandle + .increaseProgress(batch.size())); startCount += BATCH_SIZE; } versionStateCacheImpl.clearVersionStatsCache(targetVersion.getId()); @@ -284,16 +293,23 @@ public Future startMergeTranslations(Long targetVersionId, * This method will run in transaction and manages its own transaction. * * @param request - * TM merge request + * TM merge request criteria * @param textFlows * the text flows to be filled * @param targetLocale * target locale + * @param fromVersionIds + * source version ids + * @param callbackOnUpdate + * an optional callback to call when we have a + * TransUnitUpdateRequest ready * @return translation results */ private List translateInBatch( - TransMemoryMergeRequest request, List textFlows, - HLocale targetLocale) { + HasTMMergeCriteria request, List textFlows, + HLocale targetLocale, + List fromVersionIds, + Optional> callbackOnUpdate) { if (textFlows.isEmpty()) { return Collections.emptyList(); @@ -317,7 +333,7 @@ private List translateInBatch( hTextFlow.getDocument().getLocale().getLocaleId(), checkContext, checkDocument, checkProject, request.getThresholdPercent(), - Collections.emptyList()); + fromVersionIds); if (tmResult.isPresent()) { TransUnitUpdateRequest updateRequest = createRequest(request, targetLocale, @@ -325,71 +341,16 @@ private List translateInBatch( if (updateRequest != null) { updateRequests.add(updateRequest); - textFlowTargetUpdateContextEvent - .fire(new TextFlowTargetUpdateContextEvent( - updateRequest.getTransUnitId(), - request.localeId, - request.editorClientId, - TransUnitUpdated.UpdateType.NonEditorSave)); + callbackOnUpdate.ifPresent(c -> c.accept(updateRequest)); } } } return translationServiceImpl.translate( - request.localeId, updateRequests); - }); - } catch (Exception e) { - log.error("exception during TM merge", e); - return Collections.emptyList(); - } - } - - // TODO pahuang this duplicated most part of above method - public void translateInBatch(HasTMMergeCriteria mergeCriteria, - List textFlows, HLocale targetLocale, - List fromProjectVersions) { - - if (textFlows.isEmpty()) { - return; - } - - try { - transactionUtil.run(() -> { - - List updateRequests = Lists.newLinkedList(); - for (HTextFlow hTextFlow : textFlows) { - HTextFlowTarget hTextFlowTarget = - hTextFlow.getTargets().get(targetLocale.getId()); - boolean checkContext = - mergeCriteria.getDifferentContextRule() == - MergeRule.REJECT; - boolean checkDocument = - mergeCriteria.getDifferentDocumentRule() == - MergeRule.REJECT; - boolean checkProject = - mergeCriteria.getDifferentProjectRule() == - MergeRule.REJECT; - Optional tmResult = - translationMemoryServiceImpl.searchBestMatchTransMemory( - hTextFlow, targetLocale.getLocaleId(), - hTextFlow.getDocument().getLocale().getLocaleId(), - checkContext, checkDocument, checkProject, - mergeCriteria.getThresholdPercent(), - fromProjectVersions); - if (tmResult.isPresent()) { - TransUnitUpdateRequest updateRequest = - createRequest(mergeCriteria, targetLocale, - hTextFlow, tmResult.get(), hTextFlowTarget); - - if (updateRequest != null) { - updateRequests.add(updateRequest); - } - } - } - translationServiceImpl.translate( targetLocale.getLocaleId(), updateRequests); }); } catch (Exception e) { log.error("exception during TM merge", e); + return Collections.emptyList(); } } From b8f8807cc351090c4bf169e4fea0ae3a760a3001 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Thu, 22 Jun 2017 15:02:01 +1000 Subject: [PATCH 035/116] ZNTA-1865 fix up after merge --- .../java/org/zanata/async/AsyncTaskKey.java | 2 +- .../service/TransMemoryMergeManager.java | 33 ++++--------------- 2 files changed, 7 insertions(+), 28 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskKey.java b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskKey.java index 87b2c81792..9a92eb3596 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskKey.java +++ b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskKey.java @@ -28,7 +28,7 @@ public interface AsyncTaskKey extends Serializable { * key instance field values * @return String representation of the key which can be used as id */ - static String joinFields(String keyName, String... fields) { + static String joinFields(String keyName, Object... fields) { return keyName + SEPARATOR + Joiner.on(SEPARATOR).useForNull("").join(fields); } diff --git a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java index 003f5ddbce..d70a8ee6ca 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java @@ -30,6 +30,7 @@ import org.slf4j.LoggerFactory; import org.zanata.async.AsyncTaskHandle; import org.zanata.async.AsyncTaskHandleManager; +import org.zanata.async.AsyncTaskKey; import org.zanata.async.GenericAsyncTaskKey; import org.zanata.async.handle.MergeTranslationsTaskHandle; import org.zanata.async.handle.TransMemoryMergeTaskHandle; @@ -55,6 +56,8 @@ public class TransMemoryMergeManager implements Serializable { private static final Logger log = LoggerFactory.getLogger(TransMemoryMergeManager.class); private static final long serialVersionUID = 1364316697376958035L; + private static final String KEY_NAME = "TMMergeForVerKey"; + private final AsyncTaskHandleManager asyncTaskHandleManager; private final TransMemoryMergeService transMemoryMergeService; @@ -121,8 +124,7 @@ public boolean cancelTransMemoryMerge(TransMemoryMergeCancelRequest request) { } public boolean start(Long versionId, VersionTMMerge mergeRequest) { - TransMemoryMergeManager.MergeTranslationTaskKey key = - new TransMemoryMergeManager.MergeTranslationTaskKey(versionId, mergeRequest.getLocaleId()); + AsyncTaskKey key = makeKey(versionId, mergeRequest.getLocaleId()); AsyncTaskHandle handleByKey = asyncTaskHandleManager.getHandleByKey(key); if (handleByKey == null || handleByKey.isCancelled() @@ -163,30 +165,7 @@ public String toString() { } } - public static class MergeTranslationTaskKey implements Serializable { - - private static final long serialVersionUID = 5671982177725183233L; - private final Long versionId; - private final LocaleId localeId; - - public MergeTranslationTaskKey(Long versionId, LocaleId localeId) { - this.versionId = versionId; - this.localeId = localeId; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - MergeTranslationTaskKey that = (MergeTranslationTaskKey) o; - return Objects.equals(versionId, that.versionId) && - Objects.equals(localeId, that.localeId); - } - - @Override - public int hashCode() { - return Objects - .hash(versionId, localeId); - } + private static AsyncTaskKey makeKey(Long versionId, LocaleId localeId) { + return new GenericAsyncTaskKey(joinFields(KEY_NAME, versionId, localeId)); } } From 8326d7edfbcab622c067165974c4c599640dd5e3 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Thu, 22 Jun 2017 15:02:47 +1000 Subject: [PATCH 036/116] minor --- .../org/zanata/rest/editor/service/TransMemoryMergeManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java index d70a8ee6ca..d3da0254f8 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java @@ -151,7 +151,7 @@ static class TMMergeForDocTaskKey extends TMMergeForDocTaskKey(DocumentId documentId, LocaleId localeId) { // here we use numeric id to form the string id because it doesn't require URL encoding - super(joinFields(KEY_NAME, documentId.getId().toString(), localeId.getId())); + super(joinFields(KEY_NAME, documentId.getId(), localeId)); this.documentId = documentId; this.localeId = localeId; } From be4ba05c2a4a703883418b040724f80c4adb0ba1 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Thu, 22 Jun 2017 15:19:04 +1000 Subject: [PATCH 037/116] ZNTA-1865 REST api returns process status --- .../action/MergeTranslationsManager.java | 2 +- .../org/zanata/async/AsyncTaskHandle.java | 9 ++++++ .../handle/MergeTranslationsTaskHandle.java | 7 +++++ .../service/TransMemoryMergeManager.java | 28 +++++++++++-------- .../rest/service/AsyncProcessService.java | 2 +- .../rest/service/ProjectVersionService.java | 19 +++++++------ .../rest/service/ProjectVersionTest.java | 24 ++-------------- .../MergeTranslationsServiceImplTest.java | 8 ++++-- 8 files changed, 54 insertions(+), 45 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java index 2cd8a22a35..0fd57cecfb 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/MergeTranslationsManager.java @@ -57,7 +57,7 @@ public void start(String sourceProjectSlug, String sourceVersionSlug, AsyncTaskKey key = MergeVersionKey .getKey(targetProjectSlug, targetVersionSlug); - MergeTranslationsTaskHandle handle = new MergeTranslationsTaskHandle(); + MergeTranslationsTaskHandle handle = new MergeTranslationsTaskHandle(key); asyncTaskHandleManager.registerTaskHandle(handle, key); mergeTranslationsServiceImpl.startMergeTranslations(sourceProjectSlug, sourceVersionSlug, targetProjectSlug, targetVersionSlug, diff --git a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java index 60d7a83407..685a076393 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java @@ -50,6 +50,7 @@ public class AsyncTaskHandle implements Serializable { private long finishTime = -1; private String cancelledBy; private long cancelledTime; + private String keyId; public boolean isRunning() { return isStarted() && !isCancelled() && !isDone(); @@ -227,4 +228,12 @@ public long getCancelledTime() { public void setCancelledTime(final long cancelledTime) { this.cancelledTime = cancelledTime; } + + public String getKeyId() { + return keyId; + } + + public void setKeyId(String keyId) { + this.keyId = keyId; + } } diff --git a/server/zanata-war/src/main/java/org/zanata/async/handle/MergeTranslationsTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/handle/MergeTranslationsTaskHandle.java index 236bbb8070..585672721e 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/handle/MergeTranslationsTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/handle/MergeTranslationsTaskHandle.java @@ -21,6 +21,7 @@ package org.zanata.async.handle; import org.zanata.async.AsyncTaskHandle; +import org.zanata.async.AsyncTaskKey; import org.zanata.async.UserTriggeredTaskHandle; /** @@ -31,9 +32,15 @@ public class MergeTranslationsTaskHandle extends AsyncTaskHandle implements UserTriggeredTaskHandle { + private static final long serialVersionUID = -8026264371441200919L; private long totalTranslations; private String triggeredBy; + public MergeTranslationsTaskHandle( + AsyncTaskKey key) { + setKeyId(key.id()); + } + public long getTotalTranslations() { return this.totalTranslations; } diff --git a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java index d3da0254f8..3336efb8b6 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/TransMemoryMergeManager.java @@ -20,6 +20,8 @@ */ package org.zanata.rest.editor.service; +import static org.zanata.async.AsyncTaskKey.joinFields; + import java.io.Serializable; import java.util.Objects; @@ -35,18 +37,19 @@ import org.zanata.async.handle.MergeTranslationsTaskHandle; import org.zanata.async.handle.TransMemoryMergeTaskHandle; import org.zanata.common.LocaleId; +import org.zanata.rest.dto.ProcessStatus; import org.zanata.rest.dto.VersionTMMerge; +import org.zanata.rest.service.AsyncProcessService; import org.zanata.security.ZanataIdentity; import org.zanata.service.TransMemoryMergeService; import org.zanata.webtrans.shared.model.DocumentId; import org.zanata.webtrans.shared.rest.dto.TransMemoryMergeCancelRequest; import org.zanata.webtrans.shared.rest.dto.TransMemoryMergeRequest; + import com.google.common.base.MoreObjects; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import static org.zanata.async.AsyncTaskKey.joinFields; - /** * @author Patrick Huang * pahuang@redhat.com @@ -123,21 +126,24 @@ public boolean cancelTransMemoryMerge(TransMemoryMergeCancelRequest request) { return false; } - public boolean start(Long versionId, VersionTMMerge mergeRequest) { + public AsyncTaskHandle start(Long versionId, VersionTMMerge mergeRequest) { AsyncTaskKey key = makeKey(versionId, mergeRequest.getLocaleId()); - AsyncTaskHandle handleByKey = - asyncTaskHandleManager.getHandleByKey(key); + MergeTranslationsTaskHandle handleByKey = + (MergeTranslationsTaskHandle) asyncTaskHandleManager.getHandleByKey(key); if (handleByKey == null || handleByKey.isCancelled() || handleByKey.isDone()) { - MergeTranslationsTaskHandle handle = new MergeTranslationsTaskHandle(); + handleByKey = new MergeTranslationsTaskHandle(key); - handle.setTriggeredBy(identity.getAccountUsername()); - asyncTaskHandleManager.registerTaskHandle(handle, key); + handleByKey.setTriggeredBy(identity.getAccountUsername()); + asyncTaskHandleManager.registerTaskHandle(handleByKey, key); transMemoryMergeService.startMergeTranslations(versionId, - mergeRequest, handle); - return true; + mergeRequest, handleByKey); + } else { + log.warn( + "there is already a task running for version id {} and locale {}", + versionId, mergeRequest.getLocaleId()); } - return false; + return handleByKey; } @SuppressFBWarnings(value = "EQ_DOESNT_OVERRIDE_EQUALS", justification = "super class equals method is sufficient") diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java index 10c56a97b8..0bfc24c5e8 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/AsyncProcessService.java @@ -206,7 +206,7 @@ public Response cancelAsyncProcess(@PathParam("keyId") String keyId) { } @NotNull - static ProcessStatus handleToProcessStatus(AsyncTaskHandle handle, + public static ProcessStatus handleToProcessStatus(AsyncTaskHandle handle, String url) { ProcessStatus status = new ProcessStatus(); status.setStatusCode( diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java index 03ec0de3fc..b547d3ea04 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java @@ -16,6 +16,7 @@ import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.EntityTag; import javax.ws.rs.core.GenericEntity; @@ -26,6 +27,8 @@ import org.apache.commons.lang.StringUtils; import org.apache.deltaspike.jpa.api.transaction.Transactional; import org.zanata.ApplicationConfiguration; +import org.zanata.async.AsyncTaskHandle; +import org.zanata.async.handle.MergeTranslationsTaskHandle; import org.zanata.common.ContentState; import org.zanata.common.EntityStatus; import org.zanata.common.LocaleId; @@ -43,6 +46,7 @@ import org.zanata.rest.NoSuchEntityException; import org.zanata.rest.ReadOnlyEntityException; import org.zanata.rest.dto.LocaleDetails; +import org.zanata.rest.dto.ProcessStatus; import org.zanata.rest.dto.ProjectIteration; import org.zanata.rest.dto.TransUnitStatus; import org.zanata.rest.dto.User; @@ -345,9 +349,7 @@ public Response getTransUnitStatus( * @return The following response status codes will be returned from this * operation:
* ACCEPTED(202) - If the process is successfully triggered.
- * UNACCEPTED(400) - If the incoming payload is invalid or there is - * already a TM merge process running for this version and target - * language.
+ * UNACCEPTED(400) - If the incoming payload is invalid.
* NOT FOUND(404) - If no project or version was found for the given * project slug and version slug.
* FORBIDDEN(403) - If the user was not allowed to create/modify the @@ -400,12 +402,13 @@ public Response prefillWithTM(@PathParam("projectSlug") String projectSlug, } identity.checkPermission("modify-translation", hProject, hLocale); - boolean started = transMemoryMergeManager + AsyncTaskHandle handle = transMemoryMergeManager .start(version.getId(), mergeRequest); - if (!started) { - throw new UnsupportedOperationException("There is already version merge operation in progress"); - } - return Response.accepted().build(); + + ProcessStatus processStatus = AsyncProcessService + .handleToProcessStatus(handle, + uri.getBaseUri() + "process/key/" + handle.getKeyId()); + return Response.accepted(processStatus).build(); } @VisibleForTesting diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/ProjectVersionTest.java b/server/zanata-war/src/test/java/org/zanata/rest/service/ProjectVersionTest.java index 430946011f..67490088d3 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/ProjectVersionTest.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/ProjectVersionTest.java @@ -25,6 +25,7 @@ import org.mockito.Mock; import org.zanata.ApplicationConfiguration; import org.zanata.ZanataDbunitJpaTest; +import org.zanata.async.AsyncTaskHandle; import org.zanata.common.LocaleId; import org.zanata.i18n.Messages; import org.zanata.jpa.FullText; @@ -205,27 +206,6 @@ public void versionTMMergeReturnsNotFoundIfLocaleIdCanNotBeFound() { .getStatus()).isEqualTo(NOT_FOUND.getStatusCode()); } - @Test - @InRequestScope - public void versionTMMergeThrowsExceptionIfAnotherMergeProcessIsRunning() { - String projectSlug = "sample-project"; - String versionSlug = "1.0"; - - VersionTMMerge mergeRequest = new VersionTMMerge(LocaleId.FR, 90, - MergeRule.FUZZY, MergeRule.FUZZY, MergeRule.FUZZY, - Collections.emptyList()); - - // when there is already a merge process running - when(localeService.getByLocaleId(LocaleId.FR)).thenReturn(new HLocale(LocaleId.FR)); - when(transMemoryMergeManager.start(1L, mergeRequest)).thenReturn(false); - - assertThatThrownBy(() -> { - service.prefillWithTM(projectSlug, versionSlug, mergeRequest); - }) - .isInstanceOf(UnsupportedOperationException.class) - .hasMessage("There is already version merge operation in progress"); - } - @Test @InRequestScope public void versionTMMergeReturnsAcceptedIfEverythingIsGood() { @@ -236,7 +216,7 @@ public void versionTMMergeReturnsAcceptedIfEverythingIsGood() { MergeRule.FUZZY, MergeRule.FUZZY, MergeRule.FUZZY, Collections.emptyList()); - when(transMemoryMergeManager.start(2L, mergeRequest)).thenReturn(true); + when(transMemoryMergeManager.start(2L, mergeRequest)).thenReturn(new AsyncTaskHandle<>()); assertThat(service.prefillWithTM(projectSlug, versionSlug, mergeRequest) .getStatus()).isEqualTo(NOT_FOUND.getStatusCode()); } diff --git a/server/zanata-war/src/test/java/org/zanata/service/impl/MergeTranslationsServiceImplTest.java b/server/zanata-war/src/test/java/org/zanata/service/impl/MergeTranslationsServiceImplTest.java index f6b664121b..a38fb06d44 100644 --- a/server/zanata-war/src/test/java/org/zanata/service/impl/MergeTranslationsServiceImplTest.java +++ b/server/zanata-war/src/test/java/org/zanata/service/impl/MergeTranslationsServiceImplTest.java @@ -34,6 +34,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.zanata.ZanataDbunitJpaTest; +import org.zanata.action.MergeTranslationsManager; import org.zanata.async.handle.MergeTranslationsTaskHandle; import org.zanata.cache.InfinispanTestCacheContainer; import org.zanata.cdi.TestTransaction; @@ -79,6 +80,7 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verifyZeroInteractions; +import static org.zanata.action.MergeTranslationsManager.MergeVersionKey.getKey; @RunWith(CdiUnitRunner.class) @SupportDeltaspikeCore @@ -180,7 +182,8 @@ public void testMergeVersionNotExist() throws Exception { String sourceVersionSlug = "1.0"; String targetVersionSlug = "non-exist-version"; - MergeTranslationsTaskHandle handle = new MergeTranslationsTaskHandle(); + MergeTranslationsTaskHandle handle = new MergeTranslationsTaskHandle( + getKey(projectSlug, targetVersionSlug)); Future future = service.startMergeTranslations(projectSlug, sourceVersionSlug, projectSlug, targetVersionSlug, true, handle); @@ -197,7 +200,8 @@ public void testMergeEmptyDoc() throws Exception { String sourceVersionSlug = "1.0"; String targetVersionSlug = "3.0"; - MergeTranslationsTaskHandle handle = new MergeTranslationsTaskHandle(); + MergeTranslationsTaskHandle handle = new MergeTranslationsTaskHandle( + getKey(projectSlug, targetVersionSlug)); Future future = service.startMergeTranslations(projectSlug, sourceVersionSlug, projectSlug, targetVersionSlug, true, null); verifyZeroInteractions(authenticatedAccount); From cd71b534cfd4f7b3b5ad7fe5a1193c6ea6212c29 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Thu, 22 Jun 2017 16:40:55 +1000 Subject: [PATCH 038/116] ZNTA-1865 add react mount point to project version jsf page --- server/zanata-war/src/main/webapp/iteration/view.xhtml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/zanata-war/src/main/webapp/iteration/view.xhtml b/server/zanata-war/src/main/webapp/iteration/view.xhtml index 387ab3346e..cda50c2606 100644 --- a/server/zanata-war/src/main/webapp/iteration/view.xhtml +++ b/server/zanata-war/src/main/webapp/iteration/view.xhtml @@ -596,6 +596,8 @@ +
+ From 15c8694e3e030ca5ec0c9a2e2a63217f000d2e40 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Tue, 27 Jun 2017 14:39:54 +1000 Subject: [PATCH 039/116] ZNTA-2057 fix: copyTrans didn't set triggerer --- .../java/org/zanata/action/CopyTransManager.java | 2 ++ .../main/java/org/zanata/async/AsyncTaskHandle.java | 13 +++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java b/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java index 4790d924c9..1fab1f35d2 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java +++ b/server/zanata-war/src/main/java/org/zanata/action/CopyTransManager.java @@ -101,6 +101,7 @@ public void startCopyTrans(HDocument document, HCopyTransOptions options) { } AsyncTaskKey key = CopyTransProcessKey.getKey(document); CopyTransTaskHandle handle = new CopyTransTaskHandle(); + handle.setTriggeredBy(identity.getAccountUsername()); asyncTaskHandleManager.registerTaskHandle(handle, key); copyTransServiceImpl.startCopyTransForDocument(document, options, handle); @@ -119,6 +120,7 @@ public void startCopyTrans(HProjectIteration iteration, } AsyncTaskKey key = CopyTransProcessKey.getKey(iteration); CopyTransTaskHandle handle = new CopyTransTaskHandle(); + handle.setTriggeredBy(identity.getAccountUsername()); asyncTaskHandleManager.registerTaskHandle(handle, key); copyTransServiceImpl.startCopyTransForIteration(iteration, options, handle); diff --git a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java index 60d7a83407..a3eb4247cc 100644 --- a/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java +++ b/server/zanata-war/src/main/java/org/zanata/async/AsyncTaskHandle.java @@ -21,6 +21,7 @@ package org.zanata.async; import java.io.Serializable; +import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @@ -121,10 +122,14 @@ public boolean canCancel(ZanataIdentity identity) { private static boolean isAdminOrSameUser(AsyncTaskHandle taskHandle, ZanataIdentity identity) { return identity != null && (identity.hasRole("admin") - || (taskHandle instanceof UserTriggeredTaskHandle - && ((UserTriggeredTaskHandle) taskHandle) - .getTriggeredBy() - .equals(identity.getAccountUsername()))); + || triggeredBySameUser(taskHandle, identity)); + } + + private static boolean triggeredBySameUser(AsyncTaskHandle taskHandle, + ZanataIdentity identity) { + return taskHandle instanceof UserTriggeredTaskHandle && Objects.equals( + ((UserTriggeredTaskHandle) taskHandle).getTriggeredBy(), + identity.getAccountUsername()); } /** From 5266b970e89842f2f1e85e435763a698484b02f7 Mon Sep 17 00:00:00 2001 From: Sachin Pathare Date: Tue, 27 Jun 2017 06:43:57 +0000 Subject: [PATCH 040/116] Added comprehensive test for language (#402) --- .../zanata/page/languages/LanguagePage.java | 22 +++ .../page/languages/RequestToJoinPopup.java | 56 +++++++ .../feature/language/LanguageTestSuite.java | 5 +- .../feature/language/comp/LanguageCTest.java | 148 ++++++++++++++++++ 4 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 server/functional-test/src/main/java/org/zanata/page/languages/RequestToJoinPopup.java create mode 100644 server/functional-test/src/test/java/org/zanata/feature/language/comp/LanguageCTest.java diff --git a/server/functional-test/src/main/java/org/zanata/page/languages/LanguagePage.java b/server/functional-test/src/main/java/org/zanata/page/languages/LanguagePage.java index d0f00af1cd..455dafa91d 100644 --- a/server/functional-test/src/main/java/org/zanata/page/languages/LanguagePage.java +++ b/server/functional-test/src/main/java/org/zanata/page/languages/LanguagePage.java @@ -51,6 +51,9 @@ public class LanguagePage extends BasePage { private By addUserSearchButton = By.id("searchForm:searchBtn"); private By personTable = By.id("resultForm:searchResults"); private By addSelectedButton = By.id("addSelectedBtn"); + private By requestToJoinLanguage = By.xpath(".//button[contains(text(),'Request To Join')]"); + private By cancelRequest = By.xpath(".//span[contains(text(),'Cancel request')]"); + private By leaveLanguageTeam = By.xpath(".//span[contains(text(),'Leave Team')]"); public static final int IS_TRANSLATOR_COLUMN = 0; public static final int IS_REVIEWER_COLUMN = 1; public static final int IS_COORDINATOR_COLUMN = 2; @@ -234,4 +237,23 @@ public static enum TeamPermission { this.columnIndex = columnIndex; } } + + public RequestToJoinPopup requestToJoin() { + log.info("Click Request To Join"); + clickElement(requestToJoinLanguage); + return new RequestToJoinPopup(getDriver()); + } + + public LanguagePage leaveTeam() { + log.info("Click Leave Team"); + clickElement(leaveLanguageTeam); + return new LanguagePage(getDriver()); + } + + public LanguagePage cancelRequest() { + log.info("Click Cancel Request"); + clickElement(cancelRequest); + return new LanguagePage(getDriver()); + } + } diff --git a/server/functional-test/src/main/java/org/zanata/page/languages/RequestToJoinPopup.java b/server/functional-test/src/main/java/org/zanata/page/languages/RequestToJoinPopup.java new file mode 100644 index 0000000000..56148c0a92 --- /dev/null +++ b/server/functional-test/src/main/java/org/zanata/page/languages/RequestToJoinPopup.java @@ -0,0 +1,56 @@ +/* + * Copyright 2017, 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.page.languages; + +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.zanata.page.BasePage; + +/** + * @author Sachin Pathare spathare@redhat.com + */ +public class RequestToJoinPopup extends BasePage { + private static final org.slf4j.Logger log = + org.slf4j.LoggerFactory.getLogger(RequestToJoinPopup.class); + private By messageField = By.id( + "joinLanguageForm:requestToJoinLanguageMessage:input:request-join-message"); + private By sendButton = By.id("request-join-language-send-button"); + private By cancelButton = By.id("request-join-language-cancel-button"); + + public RequestToJoinPopup(WebDriver driver) { + super(driver); + } + + public RequestToJoinPopup enterMessage(String message) { + log.info("Enter message {}", message); + enterText(readyElement(messageField), message); + return new RequestToJoinPopup(getDriver()); + } + + public LanguagePage clickSend() { + log.info("Click the Send Message button"); + clickElement(sendButton); + return new LanguagePage(getDriver()); + } + +} diff --git a/server/functional-test/src/test/java/org/zanata/feature/language/LanguageTestSuite.java b/server/functional-test/src/test/java/org/zanata/feature/language/LanguageTestSuite.java index 972d44ec95..28a593883e 100644 --- a/server/functional-test/src/test/java/org/zanata/feature/language/LanguageTestSuite.java +++ b/server/functional-test/src/test/java/org/zanata/feature/language/LanguageTestSuite.java @@ -2,12 +2,15 @@ import org.junit.runner.RunWith; import org.junit.runners.Suite; +import org.zanata.feature.language.comp.LanguageCTest; @RunWith(Suite.class) @Suite.SuiteClasses({ AddLanguageTest.class, ContactLanguageTeamTest.class, - JoinLanguageTeamTest.class + JoinLanguageTeamTest.class, + //comprehensive test + LanguageCTest.class }) public class LanguageTestSuite { diff --git a/server/functional-test/src/test/java/org/zanata/feature/language/comp/LanguageCTest.java b/server/functional-test/src/test/java/org/zanata/feature/language/comp/LanguageCTest.java new file mode 100644 index 0000000000..9d61301dc2 --- /dev/null +++ b/server/functional-test/src/test/java/org/zanata/feature/language/comp/LanguageCTest.java @@ -0,0 +1,148 @@ +/* + * Copyright 2017, 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.feature.language.comp; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.subethamail.wiser.WiserMessage; +import org.zanata.feature.Trace; +import org.zanata.feature.testharness.TestPlan; +import org.zanata.feature.testharness.ZanataTestCase; +import org.zanata.page.languages.LanguagePage; +import org.zanata.page.languages.LanguagesPage; +import org.zanata.util.HasEmailRule; +import org.zanata.workflow.BasicWorkFlow; +import org.zanata.workflow.LoginWorkFlow; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Sachin Pathare spathare@redhat.com + */ +@Category(TestPlan.ComprehensiveTest.class) +public class LanguageCTest extends ZanataTestCase { + + @Rule + public final HasEmailRule emailRule = new HasEmailRule(); + + @Before + public void before() { + new BasicWorkFlow().goToHome().deleteCookiesAndRefresh(); + assertThat(new LoginWorkFlow().signIn("translator", "translator").loggedInAs()) + .isEqualTo("translator") + .as("translator is logged in"); + } + + @Trace(summary = "Translator can search for language", + testPlanIds = 5681, testCaseIds = {5786}) + @Test(timeout = MAX_SHORT_TEST_DURATION) + public void searchLanguage() throws Exception { + String language = "fr"; + LanguagesPage languagesPage = new BasicWorkFlow() + .goToHome() + .goToLanguages(); + + assertThat(languagesPage.getLanguageLocales()) + .contains(language) + .as("The language is listed"); + + } + + @Trace(summary = "Translator can request to join language team", + testPlanIds = 5681, testCaseIds = {5795, 5796}) + @Test(timeout = MAX_SHORT_TEST_DURATION) + public void requestToJoinLanguage() throws Exception { + String language = "en-US"; + LanguagePage languagePage = new BasicWorkFlow() + .goToHome() + .goToLanguages() + .gotoLanguagePage(language) + .requestToJoin() + .enterMessage("I want to join this language team") + .clickSend(); + + List messages = emailRule.getMessages(); + + assertThat(messages.size()) + .isGreaterThanOrEqualTo(1) + .as("One email was sent"); + + WiserMessage wiserMessage = messages.get(0); + + assertThat(wiserMessage.getEnvelopeReceiver()) + .isEqualTo("admin@example.com") + .as("The email recipient is the Coordinator"); + + String content = HasEmailRule.getEmailContent(wiserMessage); + + assertThat(content) + .contains("Dear Language Team Coordinator") + .contains("Zanata user \"translator\" with id \"translator\" is requesting to join ") + .as("The email is to the language team coordinator"); + + assertThat(languagePage.getNotificationMessage()) + .contains("Your message has been sent to the administrator") + .as("The user is informed the message was sent"); + + } + + @Trace(summary = "Translator can cancel request", + testPlanIds = 5681, testCaseIds = {5796}) + @Test(timeout = MAX_SHORT_TEST_DURATION) + public void cancelRequest() throws Exception { + String language = "en-US"; + LanguagePage languagePage = new BasicWorkFlow() + .goToHome() + .goToLanguages() + .gotoLanguagePage(language) + .requestToJoin() + .enterMessage("I want to join this language team") + .clickSend() + .cancelRequest(); + + assertThat(languagePage.getNotificationMessage()) + .contains("Request cancelled by translator") + .as("Request to join language team is cancel"); + } + + @Trace(summary = "Translator can leave language team", + testPlanIds = 5681, testCaseIds = {5800}) + @Test(timeout = MAX_SHORT_TEST_DURATION) + public void leaveLanguageTeam() throws Exception { + String language = "fr"; + LanguagePage languagePage = new BasicWorkFlow() + .goToHome() + .goToLanguages() + .gotoLanguagePage(language) + .leaveTeam(); + + assertThat(languagePage.getNotificationMessage()) + .contains("You have left the français language team") + .as("Leaved language team " + language); + } + +} From 4f1022dba8522a4b07f283b4ef785273435728af Mon Sep 17 00:00:00 2001 From: kgough Date: Wed, 28 Jun 2017 10:53:45 +1000 Subject: [PATCH 041/116] feat(ZNTA-2070) create storybook for editor settings options --- .../SettingsOptions/SettingsOptions.story.js | 73 +++++++++++++ .../components/SettingsOptions/index.js | 100 ++++++++++++++++++ .../app/editor/components/components.story.js | 1 + 3 files changed, 174 insertions(+) create mode 100644 server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js create mode 100644 server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js new file mode 100644 index 0000000000..98ecd91b4a --- /dev/null +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js @@ -0,0 +1,73 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { storiesOf, action } from '@kadira/storybook' +import RealSettingsOptions from '.' + +/* Wrapper class for storybook. + + * The checkbox states will be stored and updated in the live + * app. This wrapper stores the states so that we can see + * them working in storybook too. + */ +class SettingsOptions extends React.Component { + static propTypes = { + states: PropTypes.object.isRequired, + updateSettingsOption: PropTypes.func.isRequired + } + constructor (props) { + super(props) + this.state = props.states + } + updateValidationOption = (setting, checked) => { + // record the check state in the wrapper + this.setState({ [setting]: checked }) + // call the real one that was passed in + this.props.updateSettingsOption(setting, checked) + } + render () { + return ( + + ) + } +} + +const updateAction = action('updateSettingsOption') +/* + * See .storybook/README.md for info on the component storybook. + */ +storiesOf('SettingOptions', module) + .add('default', () => ( + + )) + + .add('half checked', () => ( + + )) + + .add('all checked', () => ( + + + )) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js new file mode 100644 index 0000000000..a007cb630c --- /dev/null +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js @@ -0,0 +1,100 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { Checkbox } from 'react-bootstrap' + +const settings = + ['Enter key saves immediately', + 'Syntax highlighting'] + +const layouts = + ['Suggestions diff', + 'Panel layout'] + +const SettingsOptions = ({states, updateSettingsOption}) => { + const checkboxes = settings.map((setting, index) => ( +
  • + +
  • + )) + const defaults = layouts.map((layout, index) => ( +
  • + +
  • + )) + return ( +
    +

    Editor options

    +
      + {checkboxes} +
    +
    +

    Set current layout as default

    +
      + {defaults} +
    +
    + ) +} + +SettingsOptions.propTypes = { + states: PropTypes.shape({ + 'Enter key saves immediately': PropTypes.bool.isRequired, + 'Syntax highlighting': PropTypes.bool.isRequired, + 'Suggestions diff': PropTypes.bool.isRequired, + 'Panel layout': PropTypes.bool.isRequired, + }).isRequired, + updateSettingsOption: PropTypes.func.isRequired +} + +class SettingsCheckbox extends React.Component { + static propTypes = { + setting: PropTypes.string.isRequired, + checked: PropTypes.bool.isRequired, + /* Will be called with (validation, newValue) */ + onChange: PropTypes.func.isRequired + } + + onChange = (event) => { + this.props.onChange(this.props.setting, event.target.checked) + } + + render () { + const { setting, checked } = this.props + return ( + + {setting} + + ) + } +} + +class LayoutCheckbox extends React.Component { + static propTypes = { + layout: PropTypes.string.isRequired, + checked: PropTypes.bool.isRequired, + /* Will be called with (validation, newValue) */ + onChange: PropTypes.func.isRequired + } + + onChange = (event) => { + this.props.onChange(this.props.layout, event.target.checked) + } + + render () { + const { layout, checked } = this.props + return ( + + {layout} + + ) + } +} + +export default SettingsOptions diff --git a/server/zanata-frontend/src/frontend/app/editor/components/components.story.js b/server/zanata-frontend/src/frontend/app/editor/components/components.story.js index c316cb43de..45f6f28296 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/components.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/components.story.js @@ -11,4 +11,5 @@ require('./ProgressBar/ProgressBar.story.js') require('./GlossarySearchInput/GlossarySearchInput.story.js') require('./GlossaryTerm/GlossaryTerm.story.js') require('./GlossaryTermModal/GlossaryTermModal.story.js') +require('./SettingsOptions/SettingsOptions.story.js') require('./ValidationOptions/ValidationOptions.story') From 37705c9335af3d448008245590a24ebbca947bef Mon Sep 17 00:00:00 2001 From: kgough Date: Wed, 28 Jun 2017 13:54:57 +1000 Subject: [PATCH 042/116] feat(ZNTA-2070) styling of editor settings --- .../app/editor/components/SettingsOptions/index.js | 2 +- .../frontend/app/editor/containers/Sidebar/index.css | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js index a007cb630c..bc0dd56d3b 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js @@ -34,7 +34,7 @@ const SettingsOptions = ({states, updateSettingsOption}) => { {checkboxes}
    -

    Set current layout as default

    +

    Set current layout as default:

      {defaults}
    diff --git a/server/zanata-frontend/src/frontend/app/editor/containers/Sidebar/index.css b/server/zanata-frontend/src/frontend/app/editor/containers/Sidebar/index.css index b51a623a5d..7445f94625 100644 --- a/server/zanata-frontend/src/frontend/app/editor/containers/Sidebar/index.css +++ b/server/zanata-frontend/src/frontend/app/editor/containers/Sidebar/index.css @@ -380,6 +380,17 @@ h2.validation { color: var(--Sidebar-color-text); } +.settings-options h2 { + font-weight: 500; + padding-bottom: 1rem; + } + +.settings-options p { + font-weight: 500; + color: var(--Sidebar-color-text); + font-size: 0.875rem; +} + li .checkbox { font-size: var(--Sidebar-small-text); } From e4462108ca2db395d254ebc4c30d81a68f590403 Mon Sep 17 00:00:00 2001 From: kgough Date: Wed, 28 Jun 2017 14:18:42 +1000 Subject: [PATCH 043/116] fix(ZNTA-2061) corrected colour of translation history rejected text --- .../zanata/webtrans/client/util/ContentStateToStyleUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/gwt-editor/src/main/java/org/zanata/webtrans/client/util/ContentStateToStyleUtil.java b/server/gwt-editor/src/main/java/org/zanata/webtrans/client/util/ContentStateToStyleUtil.java index 85de82e1a3..71a0ba8bd8 100644 --- a/server/gwt-editor/src/main/java/org/zanata/webtrans/client/util/ContentStateToStyleUtil.java +++ b/server/gwt-editor/src/main/java/org/zanata/webtrans/client/util/ContentStateToStyleUtil.java @@ -39,7 +39,7 @@ public static String stateToStyle(ContentState state) { case Approved: return "txt--state-highlight"; case Rejected: - return "txt--state-danger"; + return "txt--state-warning"; } return styleNames; } From 5af2c3cc2757ad3601f14adf8aa2007e45d0151c Mon Sep 17 00:00:00 2001 From: kgough Date: Wed, 28 Jun 2017 15:10:42 +1000 Subject: [PATCH 044/116] feat(ZNTA-2070) WIP SettingsOptions component --- .../components/SettingsOptions/index.js | 41 +------------------ 1 file changed, 1 insertion(+), 40 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js index bc0dd56d3b..e37b6e7230 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js @@ -6,10 +6,6 @@ const settings = ['Enter key saves immediately', 'Syntax highlighting'] -const layouts = - ['Suggestions diff', - 'Panel layout'] - const SettingsOptions = ({states, updateSettingsOption}) => { const checkboxes = settings.map((setting, index) => (
  • @@ -19,25 +15,12 @@ const SettingsOptions = ({states, updateSettingsOption}) => { onChange={updateSettingsOption} />
  • )) - const defaults = layouts.map((layout, index) => ( -
  • - -
  • - )) + return (
    -

    Editor options

      {checkboxes}
    -
    -

    Set current layout as default:

    -
      - {defaults} -
    ) } @@ -75,26 +58,4 @@ class SettingsCheckbox extends React.Component { } } -class LayoutCheckbox extends React.Component { - static propTypes = { - layout: PropTypes.string.isRequired, - checked: PropTypes.bool.isRequired, - /* Will be called with (validation, newValue) */ - onChange: PropTypes.func.isRequired - } - - onChange = (event) => { - this.props.onChange(this.props.layout, event.target.checked) - } - - render () { - const { layout, checked } = this.props - return ( - - {layout} - - ) - } -} - export default SettingsOptions From 12eda4093e0718bd8bc6be42e4288439778d7bab Mon Sep 17 00:00:00 2001 From: kgough Date: Wed, 28 Jun 2017 15:15:27 +1000 Subject: [PATCH 045/116] feat(ZNTA-2070) WIP SettingsOptions component --- .../frontend/app/editor/components/SettingsOptions/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js index e37b6e7230..ed90796db2 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js @@ -9,7 +9,7 @@ const settings = const SettingsOptions = ({states, updateSettingsOption}) => { const checkboxes = settings.map((setting, index) => (
  • - @@ -35,7 +35,7 @@ SettingsOptions.propTypes = { updateSettingsOption: PropTypes.func.isRequired } -class SettingsCheckbox extends React.Component { +class SettingOption extends React.Component { static propTypes = { setting: PropTypes.string.isRequired, checked: PropTypes.bool.isRequired, From 61b95dc19f473c4c1eabc1b271e4b8c335f8f1dd Mon Sep 17 00:00:00 2001 From: kgough Date: Wed, 28 Jun 2017 23:10:09 +1000 Subject: [PATCH 046/116] feat(ZNTA-2070) WIP add SettingsOptions and SettingOption stories to editor --- .../SettingOption/SettingOption.story.js | 12 ++++ .../editor/components/SettingOption/index.js | 32 ++++++++++ .../SettingsOptions/SettingsOptions.story.js | 63 +------------------ .../components/SettingsOptions/index.js | 40 +++--------- .../app/editor/components/components.story.js | 1 + 5 files changed, 56 insertions(+), 92 deletions(-) create mode 100644 server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js create mode 100644 server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js new file mode 100644 index 0000000000..515142975e --- /dev/null +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js @@ -0,0 +1,12 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { storiesOf, action } from '@kadira/storybook' +import SettingOption from '.' + +storiesOf('SettingOption', module) + .add('default', () => ( + + )) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js new file mode 100644 index 0000000000..d7d224699d --- /dev/null +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js @@ -0,0 +1,32 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { Checkbox } from 'react-bootstrap' + +const setting = + +class SettingOption extends React.Component { + setting: PropTypes.shape({ + id: PropTypes.any.isRequired, // I will update this to whatever I use when I wire it up + label: PropTypes.string.isRequired, + active: PropTypes.bool.isRequired + }).isRequired + /* arguments: (any: settingId, bool: active) */ + updateSetting: PropTypes.func.isRequired + } + + onChange = (event) => { + this.props.onChange(this.props.setting, event.target.checked) + } + + render () { + const { setting, checked } = this.props + return ( + + {setting} + + ) + } +} + +export default SettingOption diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js index 98ecd91b4a..c4725ff8c5 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js @@ -1,73 +1,16 @@ import React from 'react' import PropTypes from 'prop-types' import { storiesOf, action } from '@kadira/storybook' -import RealSettingsOptions from '.' +import SettingsOptions from '.' -/* Wrapper class for storybook. - - * The checkbox states will be stored and updated in the live - * app. This wrapper stores the states so that we can see - * them working in storybook too. - */ -class SettingsOptions extends React.Component { - static propTypes = { - states: PropTypes.object.isRequired, - updateSettingsOption: PropTypes.func.isRequired - } - constructor (props) { - super(props) - this.state = props.states - } - updateValidationOption = (setting, checked) => { - // record the check state in the wrapper - this.setState({ [setting]: checked }) - // call the real one that was passed in - this.props.updateSettingsOption(setting, checked) - } - render () { - return ( - - ) - } -} - -const updateAction = action('updateSettingsOption') /* * See .storybook/README.md for info on the component storybook. */ storiesOf('SettingOptions', module) .add('default', () => ( - )) + settings={{ - .add('half checked', () => ( - + }} /> )) - .add('all checked', () => ( - - - )) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js index ed90796db2..56a5144065 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js @@ -1,10 +1,9 @@ import React from 'react' import PropTypes from 'prop-types' import { Checkbox } from 'react-bootstrap' +import SettingOption from '../SettingOption' const settings = - ['Enter key saves immediately', - 'Syntax highlighting'] const SettingsOptions = ({states, updateSettingsOption}) => { const checkboxes = settings.map((setting, index) => ( @@ -26,36 +25,13 @@ const SettingsOptions = ({states, updateSettingsOption}) => { } SettingsOptions.propTypes = { - states: PropTypes.shape({ - 'Enter key saves immediately': PropTypes.bool.isRequired, - 'Syntax highlighting': PropTypes.bool.isRequired, - 'Suggestions diff': PropTypes.bool.isRequired, - 'Panel layout': PropTypes.bool.isRequired, - }).isRequired, - updateSettingsOption: PropTypes.func.isRequired -} - -class SettingOption extends React.Component { - static propTypes = { - setting: PropTypes.string.isRequired, - checked: PropTypes.bool.isRequired, - /* Will be called with (validation, newValue) */ - onChange: PropTypes.func.isRequired - } - - onChange = (event) => { - this.props.onChange(this.props.setting, event.target.checked) - } - - render () { - const { setting, checked } = this.props - return ( - - {setting} - - ) - } + settings: PropTypes.arrayOf(shape( + id: PropTypes.any.isRequired, // I will update this to whatever I use when I wire it up + label: PropTypes.string.isRequired, + active: PropTypes.bool.isRequired + )).isRequired + /* arguments: (any: settingId, bool: active) */ + updateSetting: PropTypes.func.isRequired } export default SettingsOptions diff --git a/server/zanata-frontend/src/frontend/app/editor/components/components.story.js b/server/zanata-frontend/src/frontend/app/editor/components/components.story.js index 45f6f28296..0f56d07537 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/components.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/components.story.js @@ -11,5 +11,6 @@ require('./ProgressBar/ProgressBar.story.js') require('./GlossarySearchInput/GlossarySearchInput.story.js') require('./GlossaryTerm/GlossaryTerm.story.js') require('./GlossaryTermModal/GlossaryTermModal.story.js') +require('./SettingOption/SettingOption.story.js') require('./SettingsOptions/SettingsOptions.story.js') require('./ValidationOptions/ValidationOptions.story') From bd7acd8c15e9a24a1dbde726506e2ca9f14e22a6 Mon Sep 17 00:00:00 2001 From: kgough Date: Wed, 28 Jun 2017 23:12:15 +1000 Subject: [PATCH 047/116] feat(ZNTA-2070) WIP add SettingsOptions and SettingOption stories to editor --- .../editor/components/SettingOption/SettingOption.story.js | 2 +- .../src/frontend/app/editor/components/SettingOption/index.js | 4 +++- .../components/SettingsOptions/SettingsOptions.story.js | 2 +- .../frontend/app/editor/components/SettingsOptions/index.js | 2 ++ 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js index 515142975e..f6701e5014 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js @@ -7,6 +7,6 @@ storiesOf('SettingOption', module) .add('default', () => ( )) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js index d7d224699d..d81cd3440d 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js @@ -3,8 +3,10 @@ import PropTypes from 'prop-types' import { Checkbox } from 'react-bootstrap' const setting = + /* add props here */ -class SettingOption extends React.Component { + + class SettingOption extends React.Component { setting: PropTypes.shape({ id: PropTypes.any.isRequired, // I will update this to whatever I use when I wire it up label: PropTypes.string.isRequired, diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js index c4725ff8c5..4a3ed74148 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js @@ -10,7 +10,7 @@ storiesOf('SettingOptions', module) .add('default', () => ( )) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js index 56a5144065..b11cf4a35f 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js @@ -4,6 +4,8 @@ import { Checkbox } from 'react-bootstrap' import SettingOption from '../SettingOption' const settings = +/* add props here */ + const SettingsOptions = ({states, updateSettingsOption}) => { const checkboxes = settings.map((setting, index) => ( From 1b809401b5e9064705a8fa5c31bc1c936f85e73f Mon Sep 17 00:00:00 2001 From: kgough Date: Wed, 28 Jun 2017 23:28:52 +1000 Subject: [PATCH 048/116] feat(ZNTA-2070) WIP add SettingsOptions and SettingOption stories to editor --- .../SettingOption/SettingOption.story.js | 6 ++++-- .../editor/components/SettingOption/index.js | 18 +++++++----------- .../SettingsOptions/SettingsOptions.story.js | 4 +++- .../editor/components/SettingsOptions/index.js | 5 ----- 4 files changed, 14 insertions(+), 19 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js index f6701e5014..b276f38494 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js @@ -6,7 +6,9 @@ import SettingOption from '.' storiesOf('SettingOption', module) .add('default', () => ( )) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js index d81cd3440d..307169b18e 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js @@ -2,18 +2,14 @@ import React from 'react' import PropTypes from 'prop-types' import { Checkbox } from 'react-bootstrap' -const setting = - /* add props here */ - - - class SettingOption extends React.Component { +class SettingOption extends React.Component { setting: PropTypes.shape({ - id: PropTypes.any.isRequired, // I will update this to whatever I use when I wire it up - label: PropTypes.string.isRequired, - active: PropTypes.bool.isRequired - }).isRequired - /* arguments: (any: settingId, bool: active) */ - updateSetting: PropTypes.func.isRequired + id: PropTypes.any.isRequired, // I will update this to whatever I use when I wire it up + label: PropTypes.string.isRequired, + active: PropTypes.bool.isRequired + }).isRequired + /* arguments: (any: settingId, bool: active) */ + updateSetting: PropTypes.func.isRequired } onChange = (event) => { diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js index 4a3ed74148..956830b027 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js @@ -10,7 +10,9 @@ storiesOf('SettingOptions', module) .add('default', () => ( )) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js index b11cf4a35f..e8e7e9b92a 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js @@ -1,12 +1,7 @@ import React from 'react' import PropTypes from 'prop-types' -import { Checkbox } from 'react-bootstrap' import SettingOption from '../SettingOption' -const settings = -/* add props here */ - - const SettingsOptions = ({states, updateSettingsOption}) => { const checkboxes = settings.map((setting, index) => (
  • From da9717f910b8073fb3d1c228558c11c90db5677b Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Thu, 29 Jun 2017 10:46:03 +1000 Subject: [PATCH 049/116] add new option to use an ephemeral database container --- server/docker/README.md | 4 +++- server/docker/rundb.sh | 31 +++++++++++++++++++++++++++---- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/server/docker/README.md b/server/docker/README.md index b3e4adeb4c..b52a0c0040 100644 --- a/server/docker/README.md +++ b/server/docker/README.md @@ -85,7 +85,9 @@ $ ./rundb.sh This script will start a docker container with the database. You can inspect the script file to learn the exact docker command it's running. -The container will map the mysql data directory to `$HOME/docker-volumes/zanata-mariadb`. This can be changed from the script file. +The container by default will map the mysql data directory to `$HOME/docker-volumes/zanata-mariadb`. This can be changed from the script file. + +If you give the script ```-e`` option (stands for ephemeral), it will not use any volume mapping. This means any data you save in Zanata using this mode will be lost once the container is stopped. It will also remove itself once stopped (e.g. no need to call docker rm zanatadb). This is useful for testing a fresh copy of Zanata instance. The database can be accessed via tcp via the `mysql` command or by using any database administration tool. You need to get the actual mapped port on the host by typing `docker ps`. After you have the port, you can connect locally to the database. The following is an example to accomplish this using a locally installed mysql client: diff --git a/server/docker/rundb.sh b/server/docker/rundb.sh index eca53b7768..080a0a2129 100755 --- a/server/docker/rundb.sh +++ b/server/docker/rundb.sh @@ -16,7 +16,10 @@ VOLUME_DIR=$HOME/docker-volumes/zanata-mariadb mkdir -p $VOLUME_DIR -while getopts ":n:h" opt; do +CONTAINER_NAME=zanatadb +VOLUME_OPT="-v $VOLUME_DIR:/var/lib/mysql:Z" +EPHEMERAL=false +while getopts ":n:eh" opt; do case ${opt} in n) echo "===== set docker network to $OPTARG =====" @@ -28,6 +31,17 @@ while getopts ":n:h" opt; do echo "-h : display help" exit ;; + e) + echo "===== starting an ephemeral database container ====" + if [ ! -z $(docker ps --all --quiet --filter name=$CONTAINER_NAME) ]; then + echo "removing $CONTAINER_NAME container" + docker rm -f $CONTAINER_NAME + fi + # instead of giving the container volume mapping, + # we tell it to remove itself once stopped. + VOLUME_OPT=" --rm " + EPHEMERAL=true + ;; \?) echo "Invalid option: -${OPTARG}. Use -h for help" >&2 exit 1 @@ -37,13 +51,22 @@ done ensure_docker_network -docker run --name zanatadb \ +docker run --name $CONTAINER_NAME \ -e MYSQL_USER=$DB_USERNAME -e MYSQL_PASSWORD=$DB_PASSWORD \ -e MYSQL_DATABASE=$DB_SCHEMA -e MYSQL_ROOT_PASSWORD=$DB_ROOT_PASSWORD \ -P --net=${DOCKER_NETWORK} \ - -v $VOLUME_DIR:/var/lib/mysql:Z \ + ${VOLUME_OPT} \ -d mariadb:10.1 \ --character-set-server=utf8 --collation-server=utf8_general_ci echo '' -echo 'Please use the command "docker logs zanatadb" to check that MariaDB starts correctly.' +echo "Please use the command 'docker logs $CONTAINER_NAME' to check that MariaDB starts correctly." + +if [ "$EPHEMERAL" == 'true' ] +then + echo "=====================================================================" + echo "Once MariaDB and Zanata are running, execute below commands to create an admin user" + echo "docker cp $DIR/conf/admin-user-setup.sql $CONTAINER_NAME:/tmp/" + echo "docker exec $CONTAINER_NAME /bin/sh -c 'mysql -u$DB_USERNAME -p$DB_PASSWORD $DB_SCHEMA Date: Thu, 29 Jun 2017 17:49:12 +1000 Subject: [PATCH 050/116] feat(ZNTA-2070): WIP storybook for SettingOption and SettingsOptions components --- .../SettingOption/SettingOption.story.js | 13 ++++++----- .../editor/components/SettingOption/index.js | 16 +++++++------ .../SettingsOptions/SettingsOptions.story.js | 23 ++++++++----------- .../components/SettingsOptions/index.js | 8 +++---- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js index b276f38494..eaac985aba 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js @@ -5,10 +5,11 @@ import SettingOption from '.' storiesOf('SettingOption', module) .add('default', () => ( - + )) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js index 307169b18e..363b0ecac3 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js @@ -2,18 +2,20 @@ import React from 'react' import PropTypes from 'prop-types' import { Checkbox } from 'react-bootstrap' + class SettingOption extends React.Component { - setting: PropTypes.shape({ - id: PropTypes.any.isRequired, // I will update this to whatever I use when I wire it up - label: PropTypes.string.isRequired, - active: PropTypes.bool.isRequired - }).isRequired + propTypes = { + setting: PropTypes.shape({ + id: PropTypes.any.isRequired, // I will update this to whatever I use when I wire it up + label: PropTypes.string.isRequired, + active: PropTypes.bool.isRequired + }).isRequired, /* arguments: (any: settingId, bool: active) */ updateSetting: PropTypes.func.isRequired } - onChange = (event) => { - this.props.onChange(this.props.setting, event.target.checked) + onChange = () => { + this.props.updateSetting(this.props.setting, event.target.checked) } render () { diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js index 956830b027..a316fde3fe 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js @@ -3,16 +3,13 @@ import PropTypes from 'prop-types' import { storiesOf, action } from '@kadira/storybook' import SettingsOptions from '.' -/* - * See .storybook/README.md for info on the component storybook. - */ -storiesOf('SettingOptions', module) - .add('default', () => ( - - )) - +storiesOf('SettingsOptions', module) + .add('default', () => ( + + )) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js index e8e7e9b92a..a8be8d889d 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js @@ -22,13 +22,13 @@ const SettingsOptions = ({states, updateSettingsOption}) => { } SettingsOptions.propTypes = { - settings: PropTypes.arrayOf(shape( + settings: PropTypes.shape({ id: PropTypes.any.isRequired, // I will update this to whatever I use when I wire it up label: PropTypes.string.isRequired, active: PropTypes.bool.isRequired - )).isRequired - /* arguments: (any: settingId, bool: active) */ - updateSetting: PropTypes.func.isRequired + }).isRequired, + /* arguments: (any: settingId, bool: active) */ + updateSettingsOption: PropTypes.func.isRequired } export default SettingsOptions From 75d9b3c5ccb4b8976b1f549b9ed84f1f4fdee093 Mon Sep 17 00:00:00 2001 From: kgough Date: Thu, 29 Jun 2017 18:21:01 +1000 Subject: [PATCH 051/116] feat(ZNTA-2070) SettingOption component created --- .../SettingOption/SettingOption.story.js | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js index eaac985aba..b02c1652da 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js @@ -1,7 +1,33 @@ import React from 'react' import PropTypes from 'prop-types' import { storiesOf, action } from '@kadira/storybook' -import SettingOption from '.' +import RealSettingOption from '.' + +class SettingOption extends React.Component { + static propTypes = { + setting: PropTypes.shape.isRequired, + updateSetting: PropTypes.func.isRequired + } + constructor (props) { + super(props) + this.state = props.state + } + updateSetting = (setting, checked) => { + // record the check state in the wrapper + this.setState({ [setting]: checked }) + // call the real one that was passed in + this.props.updateSetting(setting, checked) + } + render () { + return ( + + ) + } +} + +const updateAction = action('updateSetting') storiesOf('SettingOption', module) .add('default', () => ( @@ -11,5 +37,5 @@ storiesOf('SettingOption', module) label: 'Krankenwagen', active: {true} }} - updateSetting={action(updateSetting)} /> + updateSetting={action(updateAction)} /> )) From f57c8c86fb581e7bf5fa6b23727cf1cba8732a0b Mon Sep 17 00:00:00 2001 From: kgough Date: Thu, 29 Jun 2017 18:45:10 +1000 Subject: [PATCH 052/116] feat(ZNTA-2070) added working checkboxes to SettingOptoin and SettingsOptions stories - still WIP --- .../SettingsOptions/SettingsOptions.story.js | 31 ++++++++++++++- .../components/SettingsOptions/index.js | 39 +++++++++++-------- 2 files changed, 52 insertions(+), 18 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js index a316fde3fe..c0bfda9461 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js @@ -1,7 +1,33 @@ import React from 'react' import PropTypes from 'prop-types' import { storiesOf, action } from '@kadira/storybook' -import SettingsOptions from '.' +import RealSettingsOptions from '.' + +class SettingsOptions extends React.Component { + static propTypes = { + settings: PropTypes.shape.isRequired, + updateSettingsOption: PropTypes.func.isRequired + } + constructor (props) { + super(props) + this.state = props.state + } + updateSettingsOption = (settings, checked) => { + // record the check state in the wrapper + this.setState({ [settings]: checked }) + // call the real one that was passed in + this.props.updateSettingsOption(settings, checked) + } + render () { + return ( + + ) + } +} + +const updateAction = action('updateSettingsOption') storiesOf('SettingsOptions', module) .add('default', () => ( @@ -11,5 +37,6 @@ storiesOf('SettingsOptions', module) label: 'Krankenwagen', active: {true} }} - updateSetting={action(updateSetting)} /> + updateSettingsOption={action(updateAction)} /> )) + diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js index a8be8d889d..e286e61181 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js @@ -2,15 +2,31 @@ import React from 'react' import PropTypes from 'prop-types' import SettingOption from '../SettingOption' -const SettingsOptions = ({states, updateSettingsOption}) => { - const checkboxes = settings.map((setting, index) => ( -
  • +class SettingsOptions extends React.Component { + static propTypes = { + settings: PropTypes.shape({ + id: PropTypes.any.isRequired, // I will update this to whatever I use when I wire it up + label: PropTypes.string.isRequired, + active: PropTypes.bool.isRequired + }).isRequired, + /* arguments: (any: settingId, bool: active) */ + updateSettingsOption: PropTypes.func.isRequired + } + + onChange = (event) => { + this.props.onChange(this.props.setting, event.target.checked) + } + + render () { + const { setting, checked } = this.props + const checkboxes = ( +
  • + checked={true} + onChange={this.onChange} />
  • - )) + ) return (
    @@ -19,16 +35,7 @@ const SettingsOptions = ({states, updateSettingsOption}) => {
    ) -} - -SettingsOptions.propTypes = { - settings: PropTypes.shape({ - id: PropTypes.any.isRequired, // I will update this to whatever I use when I wire it up - label: PropTypes.string.isRequired, - active: PropTypes.bool.isRequired - }).isRequired, - /* arguments: (any: settingId, bool: active) */ - updateSettingsOption: PropTypes.func.isRequired + } } export default SettingsOptions From ed49ece1e9e397d66f56a51e619ca25cdda93704 Mon Sep 17 00:00:00 2001 From: kgough Date: Thu, 29 Jun 2017 18:54:51 +1000 Subject: [PATCH 053/116] feat(ZNTA-2070) fixed prop names in SettingsOptions --- .../frontend/app/editor/components/SettingOption/index.js | 1 - .../app/editor/components/SettingsOptions/index.js | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js index 363b0ecac3..3a2a98415a 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js @@ -2,7 +2,6 @@ import React from 'react' import PropTypes from 'prop-types' import { Checkbox } from 'react-bootstrap' - class SettingOption extends React.Component { propTypes = { setting: PropTypes.shape({ diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js index e286e61181..3b581b7251 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js @@ -14,17 +14,17 @@ class SettingsOptions extends React.Component { } onChange = (event) => { - this.props.onChange(this.props.setting, event.target.checked) + this.props.onChange(this.props.settings, event.target.updateSettingsOption) } render () { - const { setting, checked } = this.props + const { settings, updateSettingsOption } = this.props const checkboxes = (
  • + updateSetting={this.onChange} />
  • ) From 7dfc159c604d4cce5b506587fe1c1fc938e94b02 Mon Sep 17 00:00:00 2001 From: kgough Date: Thu, 29 Jun 2017 19:50:52 +1000 Subject: [PATCH 054/116] feat(ZNTA-2070) storybook now includes checkbox labels for SettingOption and SettingsOptions --- .../SettingOption/SettingOption.story.js | 12 ++--- .../SettingsOptions/SettingsOptions.story.js | 14 +++-- .../components/SettingsOptions/index.js | 52 ++++++++----------- 3 files changed, 35 insertions(+), 43 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js index b02c1652da..6dc17ca936 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js @@ -22,20 +22,18 @@ class SettingOption extends React.Component { return ( + states={this.state} + setting={setting}/> ) } } const updateAction = action('updateSetting') +const setting = 'HTML/XML tags' storiesOf('SettingOption', module) .add('default', () => ( + setting={setting} + updateSetting={action(updateAction)} /> )) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js index c0bfda9461..630b8ba288 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js @@ -28,15 +28,19 @@ class SettingsOptions extends React.Component { } const updateAction = action('updateSettingsOption') +const settings = + ['HTML/XML tags', + 'Java variables', + 'Leading/trailing newline (n)', + 'Positional printf (XSI extension)', + 'Printf variables', + 'Tab characters (t)', + 'XML entity reference'] storiesOf('SettingsOptions', module) .add('default', () => ( )) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js index 3b581b7251..659ea5aedb 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js @@ -2,40 +2,30 @@ import React from 'react' import PropTypes from 'prop-types' import SettingOption from '../SettingOption' -class SettingsOptions extends React.Component { - static propTypes = { - settings: PropTypes.shape({ - id: PropTypes.any.isRequired, // I will update this to whatever I use when I wire it up - label: PropTypes.string.isRequired, - active: PropTypes.bool.isRequired - }).isRequired, - /* arguments: (any: settingId, bool: active) */ - updateSettingsOption: PropTypes.func.isRequired - } - - onChange = (event) => { - this.props.onChange(this.props.settings, event.target.updateSettingsOption) - } - - render () { - const { settings, updateSettingsOption } = this.props - const checkboxes = ( -
  • - -
  • - ) +const settings = + ['HTML/XML tags', + 'Java variables', + 'Leading/trailing newline (n)', + 'Positional printf (XSI extension)', + 'Printf variables', + 'Tab characters (t)', + 'XML entity reference'] +const SettingsOptions = ({states, updateSettingOption}) => { + const checkboxes = settings.map((settings, index) => ( +
  • + +
  • + )) return ( -
    -
      - {checkboxes} -
    -
    +
    +
      + {checkboxes} +
    +
    ) - } } export default SettingsOptions From 9c62880a09221fff5d0e86b686d14b419307d8f3 Mon Sep 17 00:00:00 2001 From: kgough Date: Thu, 29 Jun 2017 20:34:39 +1000 Subject: [PATCH 055/116] feat(ZNTA-2070) WIP: default props for SettingsOptions component --- .../SettingsOptions/SettingsOptions.story.js | 19 ++++++++----- .../components/SettingsOptions/index.js | 27 ++++++++++++------- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js index 630b8ba288..f8c79874e4 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js @@ -5,29 +5,34 @@ import RealSettingsOptions from '.' class SettingsOptions extends React.Component { static propTypes = { - settings: PropTypes.shape.isRequired, - updateSettingsOption: PropTypes.func.isRequired + settings: PropTypes.shape({ + id: PropTypes.any.isRequired, // I will update this to whatever I use when I wire it up + label: PropTypes.string.isRequired, + active: PropTypes.bool.isRequired + }).isRequired, + /* arguments: (any: settingId, bool: active) */ + updateSetting: PropTypes.func.isRequired } constructor (props) { super(props) this.state = props.state } - updateSettingsOption = (settings, checked) => { + updateSettingOption = (settings, checked) => { // record the check state in the wrapper this.setState({ [settings]: checked }) // call the real one that was passed in - this.props.updateSettingsOption(settings, checked) + this.props.updateSettingOption(settings, checked) } render () { return ( ) } } -const updateAction = action('updateSettingsOption') +const updateAction = action('updateSettingOption') const settings = ['HTML/XML tags', 'Java variables', @@ -41,6 +46,6 @@ storiesOf('SettingsOptions', module) .add('default', () => ( + updateSettingOption={action(updateAction)} /> )) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js index 659ea5aedb..484a5eecfb 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js @@ -2,16 +2,15 @@ import React from 'react' import PropTypes from 'prop-types' import SettingOption from '../SettingOption' -const settings = - ['HTML/XML tags', - 'Java variables', - 'Leading/trailing newline (n)', - 'Positional printf (XSI extension)', - 'Printf variables', - 'Tab characters (t)', - 'XML entity reference'] - const SettingsOptions = ({states, updateSettingOption}) => { + const settings = + ['HTML/XML tags', + 'Java variables', + 'Leading/trailing newline (n)', + 'Positional printf (XSI extension)', + 'Printf variables', + 'Tab characters (t)', + 'XML entity reference'] const checkboxes = settings.map((settings, index) => (
  • { ) } +SettingsOptions.propTypes = { + settings: PropTypes.shape({ + id: PropTypes.any.isRequired, // I will update this to whatever I use when I wire it up + label: PropTypes.string.isRequired, + active: PropTypes.bool.isRequired + }).isRequired, + /* arguments: (any: settingId, bool: active) */ + updateSettingOption: PropTypes.func.isRequired +} + export default SettingsOptions From 5dbc59d1518213c750b7c38497d0b86fc54682ba Mon Sep 17 00:00:00 2001 From: kgough Date: Fri, 30 Jun 2017 10:38:07 +1000 Subject: [PATCH 056/116] feat(ZNTA-2070) WIP proptypes --- .../app/editor/components/SettingsOptions/index.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js index 484a5eecfb..1719328948 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js @@ -15,7 +15,7 @@ const SettingsOptions = ({states, updateSettingOption}) => {
  • + updateSetting={updateSettingOption} />
  • )) return ( @@ -37,4 +37,12 @@ SettingsOptions.propTypes = { updateSettingOption: PropTypes.func.isRequired } +SettingsOptions.defaultProps = { + settings:({ + id: 'id', + label: 'label', + active: {true} + }) +} + export default SettingsOptions From 033c8577177a1f6086cbca4b7b92567c6078cdac Mon Sep 17 00:00:00 2001 From: kgough Date: Fri, 30 Jun 2017 12:22:39 +1000 Subject: [PATCH 057/116] feat(ZNTA-2070) components refactored and fixed - SettingOption,SettingsOptions --- .../SettingOption/SettingOption.story.js | 25 +++--- .../editor/components/SettingOption/index.js | 14 ++-- .../SettingsOptions/SettingsOptions.story.js | 76 ++++++++++++++----- .../components/SettingsOptions/index.js | 43 ++++------- 4 files changed, 93 insertions(+), 65 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js index 6dc17ca936..b20938fc23 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js @@ -5,35 +5,38 @@ import RealSettingOption from '.' class SettingOption extends React.Component { static propTypes = { - setting: PropTypes.shape.isRequired, + id: PropTypes.any.isRequired, + label: PropTypes.string.isRequired, + active: PropTypes.bool.isRequired, updateSetting: PropTypes.func.isRequired } constructor (props) { super(props) - this.state = props.state + this.state = {active:props.active} } - updateSetting = (setting, checked) => { + updateSetting = (id, active) => { // record the check state in the wrapper - this.setState({ [setting]: checked }) + this.setState({ active:active }) // call the real one that was passed in - this.props.updateSetting(setting, checked) + this.props.updateSetting( id, active) } render () { return ( + id={this.props.id} + label={this.props.label} + active={this.state.active} /> ) } } -const updateAction = action('updateSetting') -const setting = 'HTML/XML tags' - storiesOf('SettingOption', module) .add('default', () => ( + id='html-xml-tags' + label='HTML/XML Tags' + active + updateSetting={action('updateSetting')} /> )) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js index 3a2a98415a..8c8a090c7f 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/index.js @@ -13,17 +13,17 @@ class SettingOption extends React.Component { updateSetting: PropTypes.func.isRequired } - onChange = () => { - this.props.updateSetting(this.props.setting, event.target.checked) + updateSetting = (event) => { + this.props.updateSetting(this.props.id, event.target.checked) } render () { - const { setting, checked } = this.props + const { label, active } = this.props return ( - - {setting} - + +  {label} + ) } } diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js index f8c79874e4..b560a9ce77 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js @@ -6,46 +6,86 @@ import RealSettingsOptions from '.' class SettingsOptions extends React.Component { static propTypes = { settings: PropTypes.shape({ - id: PropTypes.any.isRequired, // I will update this to whatever I use when I wire it up + id: PropTypes.any.isRequired, label: PropTypes.string.isRequired, active: PropTypes.bool.isRequired }).isRequired, - /* arguments: (any: settingId, bool: active) */ updateSetting: PropTypes.func.isRequired } constructor (props) { super(props) - this.state = props.state + this.state = { settings: props.settings } } - updateSettingOption = (settings, checked) => { + updateSetting = (id, active) => { // record the check state in the wrapper - this.setState({ [settings]: checked }) + this.setState(newState => ({ + settings: newState.settings.map(setting => { + if (setting.id === id) { + return { + ...setting, + active + } + } else { + return setting + } + }) + })) // call the real one that was passed in - this.props.updateSettingOption(settings, checked) + this.props.updateSetting(id, active) } render () { return ( - + ) } } -const updateAction = action('updateSettingOption') +const updateSetting = action('updateSetting') const settings = - ['HTML/XML tags', - 'Java variables', - 'Leading/trailing newline (n)', - 'Positional printf (XSI extension)', - 'Printf variables', - 'Tab characters (t)', - 'XML entity reference'] + [ + { + id: 'html-xml-tags', + label: 'HTML/XML tags', + active: false + }, + { + id: 'java-variables', + label: 'Java variables', + active: true + }, + { + id: 'leading-trailing-newline', + label: 'Leading/trailing newline (n)', + active: false + }, + { + id: 'positional-printf', + label: 'Positional printf (XSI extension)', + active: true + }, + { + id: 'printf-variables', + label: 'Printf variables', + active: false + }, + { + id: 'tab-characters', + label: 'Tab characters (t)', + active: false + }, + { + id: 'xml-entity-reference', + label: 'XML entity reference', + active: true + } + ] storiesOf('SettingsOptions', module) .add('default', () => ( + updateSetting={action('updateSetting')} /> )) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js index 1719328948..06d4e8e1e4 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/index.js @@ -2,28 +2,21 @@ import React from 'react' import PropTypes from 'prop-types' import SettingOption from '../SettingOption' -const SettingsOptions = ({states, updateSettingOption}) => { - const settings = - ['HTML/XML tags', - 'Java variables', - 'Leading/trailing newline (n)', - 'Positional printf (XSI extension)', - 'Printf variables', - 'Tab characters (t)', - 'XML entity reference'] - const checkboxes = settings.map((settings, index) => ( -
  • - -
  • +const SettingsOptions = ({settings, updateSetting}) => { + + const checkboxes = settings.map((setting, index) => ( +
  • + +
  • )) return ( -
    -
      - {checkboxes} -
    -
    +
    +
      + {checkboxes} +
    +
    ) } @@ -34,15 +27,7 @@ SettingsOptions.propTypes = { active: PropTypes.bool.isRequired }).isRequired, /* arguments: (any: settingId, bool: active) */ - updateSettingOption: PropTypes.func.isRequired -} - -SettingsOptions.defaultProps = { - settings:({ - id: 'id', - label: 'label', - active: {true} - }) + updateSetting: PropTypes.func.isRequired } export default SettingsOptions From 3d98570cd8c800d3d344b56a311dfe283879ce7c Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Fri, 30 Jun 2017 12:35:27 +1000 Subject: [PATCH 058/116] ZNTA-2056 use same analyzer to parse search query --- .../main/java/org/zanata/dao/ProjectDAO.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/dao/ProjectDAO.java b/server/zanata-war/src/main/java/org/zanata/dao/ProjectDAO.java index 8186dd3592..bb584986a6 100644 --- a/server/zanata-war/src/main/java/org/zanata/dao/ProjectDAO.java +++ b/server/zanata-war/src/main/java/org/zanata/dao/ProjectDAO.java @@ -27,7 +27,9 @@ import javax.annotation.Nullable; import org.apache.commons.lang.StringUtils; +import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.index.Term; +import org.apache.lucene.queryparser.classic.MultiFieldQueryParser; import org.apache.lucene.queryparser.classic.ParseException; import org.apache.lucene.queryparser.classic.QueryParser; import org.apache.lucene.search.BooleanClause; @@ -41,6 +43,7 @@ import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import org.zanata.common.EntityStatus; +import org.zanata.hibernate.search.Analyzers; import org.zanata.hibernate.search.CaseInsensitiveWhitespaceAnalyzer; import org.zanata.hibernate.search.IndexFieldLabels; import org.zanata.jpa.FullText; @@ -281,12 +284,14 @@ public int getQueryProjectSize(@Nonnull String searchQuery, private FullTextQuery buildSearchQuery(@Nonnull String searchQuery, boolean includeObsolete) throws ParseException { String queryText = QueryParser.escape(searchQuery); - - BooleanQuery booleanQuery = new BooleanQuery(); - booleanQuery.add(buildSearchFieldQuery(queryText, "slug"), BooleanClause.Occur.SHOULD); - booleanQuery.add(buildSearchFieldQuery(queryText, "name"), BooleanClause.Occur.SHOULD); - booleanQuery.add(buildSearchFieldQuery(queryText, "description"), BooleanClause.Occur.SHOULD); - + Analyzer sourceAnalyzer = entityManager.getSearchFactory() + .getAnalyzer(Analyzers.DEFAULT); + MultiFieldQueryParser queryParser = new MultiFieldQueryParser( + new String[]{ "slug", "name", "description" }, sourceAnalyzer); + queryParser.setDefaultOperator(QueryParser.Operator.OR); + + BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder(); + booleanQuery.add(queryParser.parse(queryText), BooleanClause.Occur.SHOULD); if (!includeObsolete) { TermQuery obsoleteStateQuery = new TermQuery(new Term(IndexFieldLabels.ENTITY_STATUS, @@ -294,7 +299,7 @@ private FullTextQuery buildSearchQuery(@Nonnull String searchQuery, booleanQuery.add(obsoleteStateQuery, BooleanClause.Occur.MUST_NOT); } - return entityManager.createFullTextQuery(booleanQuery, HProject.class); + return entityManager.createFullTextQuery(booleanQuery.build(), HProject.class); } /** From 4f686ecd35bea65077a06747a224d6ef5e3c3957 Mon Sep 17 00:00:00 2001 From: Damian Jansen Date: Sun, 2 Jul 2017 13:52:26 +1000 Subject: [PATCH 059/116] fix(test): Add Polarion ids to and improve account tests (#411) * Improve map in trace-tests * fix(test): Add Polarion ids to and improve account tests --- server/functional-test/etc/trace-tests.groovy | 11 ++- .../main/java/org/zanata/page/AbstractPage.kt | 1 + .../page/account/EnterNewPasswordPage.java | 63 +++++++++++++++ .../page/account/InactiveAccountPage.java | 14 +++- .../org/zanata/page/account/RegisterPage.java | 2 +- .../feature/account/EmailValidationTest.java | 30 +++++--- .../account/InactiveUserLoginTest.java | 19 +++-- .../account/comp/InactiveUserLoginCTest.java | 77 +++++++++++++++++++ .../feature/account/comp/RegisterCTest.java | 61 +++++++++++++++ .../feature/endtoend/UserEndToEndTest.java | 5 +- .../zanata/feature/security/SecurityTest.java | 27 ++++++- .../test/java/org/zanata/util/EmailQuery.java | 30 ++++---- .../main/webapp/account/password_reset.xhtml | 7 +- 13 files changed, 295 insertions(+), 52 deletions(-) create mode 100644 server/functional-test/src/main/java/org/zanata/page/account/EnterNewPasswordPage.java create mode 100644 server/functional-test/src/test/java/org/zanata/feature/account/comp/InactiveUserLoginCTest.java diff --git a/server/functional-test/etc/trace-tests.groovy b/server/functional-test/etc/trace-tests.groovy index 5e72783db4..bf37596de3 100644 --- a/server/functional-test/etc/trace-tests.groovy +++ b/server/functional-test/etc/trace-tests.groovy @@ -37,7 +37,7 @@ def parseDataFiles = { newData.add("[DUP]") + testSummary data.put(testId, newData) } else { - dataMap.put((testId), [id:testId, summary:testSummary, autoTest:"untested", autotestDesc:"untested", result:'untested']) + dataMap.put((testId), [id:testId, summary:testSummary, autoTest:"untested", autoTestDesc:"untested", result:'untested']) } } @@ -49,9 +49,12 @@ def parseDataFiles = { String id = "ZAN-"+it if (dataMap.containsKey(id)) { def map = dataMap.get(id) - map.put("autoTest", test.testName) - map.put("autotestDesc", test.summary) - map.put("result", test.testResult) + String autoTest = map.autoTest == "untested" ? test.testName : map.autoTest + "|" + test.testName + map.put("autoTest", autoTest) + String autoTestDescription = map.autoTestDesc == "untested" ? test.summary : map.autoTestDesc + "|" + test.summary + map.put("autoTestDesc", autoTestDescription) + String result = map.result == "untested" ? test.testResult : map.result + "|" + test.testResult + map.put("result", result) dataMap.put(id, map) } else { println("Found dangling test case " + id) diff --git a/server/functional-test/src/main/java/org/zanata/page/AbstractPage.kt b/server/functional-test/src/main/java/org/zanata/page/AbstractPage.kt index d4611720f6..640ee3f6d2 100644 --- a/server/functional-test/src/main/java/org/zanata/page/AbstractPage.kt +++ b/server/functional-test/src/main/java/org/zanata/page/AbstractPage.kt @@ -482,6 +482,7 @@ abstract class AbstractPage(val driver: WebDriver) { } else { log.warn("Unable to focus page container") } + waitForPageSilence(); } /** diff --git a/server/functional-test/src/main/java/org/zanata/page/account/EnterNewPasswordPage.java b/server/functional-test/src/main/java/org/zanata/page/account/EnterNewPasswordPage.java new file mode 100644 index 0000000000..0e0f143497 --- /dev/null +++ b/server/functional-test/src/main/java/org/zanata/page/account/EnterNewPasswordPage.java @@ -0,0 +1,63 @@ +/* + * Copyright 2017, 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.page.account; + +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.zanata.page.BasePage; + +/** + * @author Damian Jansen + * djansen@redhat.com + */ +public class EnterNewPasswordPage extends BasePage { + private static final org.slf4j.Logger log = + org.slf4j.LoggerFactory.getLogger(EnterNewPasswordPage.class); + + public EnterNewPasswordPage(WebDriver driver) { + super(driver); + } + + private By newPassworField = + By.id("passwordResetActivationForm:passwordFieldContainer:input:password"); + private By confirmPassworField = + By.id("passwordResetActivationForm:confirmPasswordFieldContainer:input:passwordConfirm"); + private By resetPasswordButton = + By.id("passwordResetActivationForm:resetPasswordButton"); + + public EnterNewPasswordPage enterNewPassword(String password) { + log.info("Enter new password {}", password); + enterText(readyElement(newPassworField), password); + return new EnterNewPasswordPage(getDriver()); + } + + public EnterNewPasswordPage enterConfirmPassword(String password) { + log.info("Enter confirm password {}", password); + enterText(readyElement(confirmPassworField), password); + return new EnterNewPasswordPage(getDriver()); + } + + public SignInPage pressChangePasswordButton() { + log.info("Press Change Password button"); + clickElement(resetPasswordButton); + return new SignInPage(getDriver()); + } +} diff --git a/server/functional-test/src/main/java/org/zanata/page/account/InactiveAccountPage.java b/server/functional-test/src/main/java/org/zanata/page/account/InactiveAccountPage.java index cd3938348d..6319e0b135 100644 --- a/server/functional-test/src/main/java/org/zanata/page/account/InactiveAccountPage.java +++ b/server/functional-test/src/main/java/org/zanata/page/account/InactiveAccountPage.java @@ -44,15 +44,21 @@ public HomePage clickResendActivationEmail() { } public InactiveAccountPage enterNewEmail(String email) { - enterText( - readyElement( - By.id("inactiveAccountForm:email:input:emailInput")), - email); + log.info("Enter new email {}", email); + enterText(readyElement( + By.id("inactiveAccountForm:email:input:emailInput")), email); return new InactiveAccountPage(getDriver()); } public HomePage clickUpdateEmail() { + log.info("Click Update button"); clickElement(By.id("inactiveAccountForm:email:input:updateEmail")); return new HomePage(getDriver()); } + + public InactiveAccountPage updateEmailFailure() { + log.info("Click Update button, expecting failure"); + clickElement(By.id("inactiveAccountForm:email:input:updateEmail")); + return new InactiveAccountPage(getDriver()); + } } diff --git a/server/functional-test/src/main/java/org/zanata/page/account/RegisterPage.java b/server/functional-test/src/main/java/org/zanata/page/account/RegisterPage.java index e06b168252..c304e59994 100644 --- a/server/functional-test/src/main/java/org/zanata/page/account/RegisterPage.java +++ b/server/functional-test/src/main/java/org/zanata/page/account/RegisterPage.java @@ -44,7 +44,7 @@ public class RegisterPage extends CorePage { public static final String MALFORMED_EMAIL_ERROR = "not a well-formed email address"; public static final String REQUIRED_FIELD_ERROR = "may not be empty"; - + public static final String EMAIL_TAKEN = "This email address is already taken."; public static final String PASSWORD_LENGTH_ERROR = "size must be between 6 and 1024"; diff --git a/server/functional-test/src/test/java/org/zanata/feature/account/EmailValidationTest.java b/server/functional-test/src/test/java/org/zanata/feature/account/EmailValidationTest.java index 81a039c39d..3bb90079de 100644 --- a/server/functional-test/src/test/java/org/zanata/feature/account/EmailValidationTest.java +++ b/server/functional-test/src/test/java/org/zanata/feature/account/EmailValidationTest.java @@ -53,25 +53,33 @@ public void before() { registerPage = new BasicWorkFlow().goToHome().goToRegistration(); } - @Trace( - summary = "The system will allow acceptable forms of an email address for registration") - @Test + @Trace(summary = "The system will allow acceptable forms of an email address for registration", + testPlanIds = 5681, testCaseIds = -1) + @Test(timeout = MAX_SHORT_TEST_DURATION) public void validEmailAcceptance() throws Exception { - registerPage = - // Shift to other field - registerPage.enterEmail("me@mydomain.com") - .enterName("Sam I Am"); + registerPage = registerPage.enterEmail("me@mydomain.com"); + registerPage.defocus(); + assertThat(registerPage.getErrors()) .as("Email validation errors are not shown").isEmpty(); } - @Trace( - summary = "The user must enter a valid email address to register with Zanata") - @Test + @Trace(summary = "The user must provide a valid email address to register with Zanata", + testPlanIds = 5681, testCaseIds = 5691) + @Test(timeout = MAX_SHORT_TEST_DURATION) public void invalidEmailRejection() throws Exception { - registerPage = registerPage.enterEmail("plaintext").registerFailure(); + registerPage = registerPage.enterEmail("notproper@").registerFailure(); + assertThat(registerPage.getErrors()) .contains(RegisterPage.MALFORMED_EMAIL_ERROR) .as("The email formation error is displayed"); + + registerPage = registerPage.clearFields() + .enterEmail("admin@example.com") + .registerFailure(); + + assertThat(registerPage.getErrors()) + .contains(RegisterPage.EMAIL_TAKEN) + .as("The user needs to provide a unique email address"); } } diff --git a/server/functional-test/src/test/java/org/zanata/feature/account/InactiveUserLoginTest.java b/server/functional-test/src/test/java/org/zanata/feature/account/InactiveUserLoginTest.java index d9b36e8170..86752638e2 100644 --- a/server/functional-test/src/test/java/org/zanata/feature/account/InactiveUserLoginTest.java +++ b/server/functional-test/src/test/java/org/zanata/feature/account/InactiveUserLoginTest.java @@ -36,6 +36,7 @@ import org.zanata.workflow.LoginWorkFlow; import org.zanata.workflow.RegisterWorkFlow; import static org.assertj.core.api.Assertions.assertThat; +import static org.zanata.util.EmailQuery.LinkType.ACTIVATE; /** * @author Carlos Munoz @@ -63,9 +64,9 @@ public void verifyAccount() throws Exception { .isEqualTo("Zanata: Account is not activated") .as("The account is inactive"); WiserMessage message = hasEmailRule.getMessages().get(0); - assertThat(EmailQuery.hasActivationLink(message)).isTrue() + assertThat(EmailQuery.hasLink(message, ACTIVATE)).isTrue() .as("The email contains the activation link"); - String activationLink = EmailQuery.getActivationLink(message); + String activationLink = EmailQuery.getLink(message, ACTIVATE); SignInPage page = new BasicWorkFlow().goToUrl(activationLink, SignInPage.class); /* @@ -80,7 +81,8 @@ public void verifyAccount() throws Exception { "The user has validated their account and logged in"); } - @Trace(summary = "The user can resend the account activation email") + @Trace(summary = "The user can resend the account activation email", + testCaseIds = 5697) @Test(timeout = MAX_SHORT_TEST_DURATION) public void resendActivationEmail() throws Exception { String usernamepassword = "tester2"; @@ -95,10 +97,10 @@ public void resendActivationEmail() throws Exception { assertThat(hasEmailRule.getMessages().size()).isEqualTo(2) .as("A second email was sent"); WiserMessage message = hasEmailRule.getMessages().get(1); - assertThat(EmailQuery.hasActivationLink(message)).isTrue() + assertThat(EmailQuery.hasLink(message, ACTIVATE)).isTrue() .as("The second email contains the activation link"); homePage = new BasicWorkFlow() - .goToUrl(EmailQuery.getActivationLink(message), HomePage.class); + .goToUrl(EmailQuery.getLink(message, ACTIVATE), HomePage.class); /* * This fails in functional test, for reasons unknown * assertThat(homePage.getNotificationMessage()) @@ -111,7 +113,8 @@ public void resendActivationEmail() throws Exception { "The user has validated their account and logged in"); } - @Trace(summary = "The user can update the account activation email") + @Trace(summary = "The user can update the account activation email address", + testCaseIds = 5696) @Test(timeout = MAX_SHORT_TEST_DURATION) public void updateActivationEmail() throws Exception { String usernamepassword = "tester3"; @@ -133,10 +136,10 @@ public void updateActivationEmail() throws Exception { assertThat(message.getEnvelopeReceiver()) .isEqualTo("newtester@example.com") .as("The new email address is used"); - assertThat(EmailQuery.hasActivationLink(message)).isTrue() + assertThat(EmailQuery.hasLink(message, ACTIVATE)).isTrue() .as("The second email contains the activation link"); SignInPage page = new BasicWorkFlow().goToUrl( - EmailQuery.getActivationLink(message), SignInPage.class); + EmailQuery.getLink(message, ACTIVATE), SignInPage.class); /* * This fails in functional test, for reasons unknown * assertThat(homePage.getNotificationMessage()) diff --git a/server/functional-test/src/test/java/org/zanata/feature/account/comp/InactiveUserLoginCTest.java b/server/functional-test/src/test/java/org/zanata/feature/account/comp/InactiveUserLoginCTest.java new file mode 100644 index 0000000000..26d41b06f9 --- /dev/null +++ b/server/functional-test/src/test/java/org/zanata/feature/account/comp/InactiveUserLoginCTest.java @@ -0,0 +1,77 @@ +/* + * Copyright 2017, 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.feature.account.comp; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.zanata.feature.Trace; +import org.zanata.feature.testharness.ZanataTestCase; +import org.zanata.feature.testharness.TestPlan.DetailedTest; +import org.zanata.page.account.InactiveAccountPage; +import org.zanata.util.HasEmailRule; +import org.zanata.workflow.LoginWorkFlow; +import org.zanata.workflow.RegisterWorkFlow; + +/** + * @author Damian Jansen + * djansen@redhat.com + */ +@Category(DetailedTest.class) +public class InactiveUserLoginCTest extends ZanataTestCase { + private static final org.slf4j.Logger log = + org.slf4j.LoggerFactory.getLogger(InactiveUserLoginCTest.class); + + @Rule + public final HasEmailRule hasEmailRule = new HasEmailRule(); + + @Trace(summary = "The user can update the account activation email address", + testCaseIds = 5696) + @Test(timeout = MAX_SHORT_TEST_DURATION) + public void updateActivationEmail() throws Exception { + String usernamepassword = "tester3"; + new RegisterWorkFlow().registerInternal(usernamepassword, + usernamepassword, usernamepassword, + usernamepassword + "@example.com"); + InactiveAccountPage inactiveAccountPage = new LoginWorkFlow() + .signInInactive(usernamepassword, usernamepassword); + + assertThat(inactiveAccountPage.getTitle()) + .isEqualTo("Zanata: Account is not activated") + .as("The account is inactive"); + + inactiveAccountPage = inactiveAccountPage + .enterNewEmail("notproper@") + .updateEmailFailure(); + + assertThat(inactiveAccountPage.getErrors()) + .contains("not a well-formed email address"); + + inactiveAccountPage = inactiveAccountPage + .enterNewEmail("admin@example.com") + .updateEmailFailure(); + + assertThat(inactiveAccountPage.getErrors()) + .contains("This email address is already taken."); + } +} diff --git a/server/functional-test/src/test/java/org/zanata/feature/account/comp/RegisterCTest.java b/server/functional-test/src/test/java/org/zanata/feature/account/comp/RegisterCTest.java index 538e283ea6..c382dd73c9 100644 --- a/server/functional-test/src/test/java/org/zanata/feature/account/comp/RegisterCTest.java +++ b/server/functional-test/src/test/java/org/zanata/feature/account/comp/RegisterCTest.java @@ -120,6 +120,58 @@ public void togglePasswordVisible() { .as("The password field did not lose the entered text"); } + @Trace(summary = "The user must provide a password to register via internal authentication", + testCaseIds = 5692) + @Test(timeout = MAX_SHORT_TEST_DURATION) + public void passwordLengthValidation() { + String longPass = makeString(1030); + assertThat(longPass.length()).isGreaterThan(1024); + + RegisterPage registerPage = homePage + .goToRegistration() + .enterName("jimmy") + .enterEmail("jimmy@jim.net") + .enterUserName("jimmy") + .enterPassword("A") + .registerFailure(); + + assertThat(registerPage.getErrors()) + .contains(RegisterPage.PASSWORD_LENGTH_ERROR) + .as("Password requires at least 6 characters"); + + registerPage = registerPage.enterPassword(longPass).registerFailure(); + + assertThat(registerPage.getErrors()) + .contains(RegisterPage.PASSWORD_LENGTH_ERROR) + .as("The user must enter a password of at most 1024 characters"); + } + + @Trace(summary = "The user must provide a name to register", + testPlanIds = 5681, testCaseIds = 5689) + @Test(timeout = ZanataTestCase.MAX_SHORT_TEST_DURATION) + public void userMustSpecifyAValidName() { + String longName = makeString(81); + assertThat(longName.length()).isGreaterThan(80); + + RegisterPage registerPage = homePage + .goToRegistration() + .enterName("A") + .enterUserName("usermustspecifyaname") + .enterEmail("userMustSpecifyAName@test.com") + .enterPassword("password") + .registerFailure(); + + assertThat(registerPage.getErrors()) + .contains(RegisterPage.USERDISPLAYNAME_LENGTH_ERROR) + .as("A name greater than 1 character must be specified"); + + registerPage = registerPage.enterName(longName).registerFailure(); + + assertThat(registerPage.getErrors()) + .contains(RegisterPage.USERDISPLAYNAME_LENGTH_ERROR) + .as("A name shorter than 81 characters is specified"); + } + @Trace(summary = "The user must provide a username to register", testPlanIds = 5681, testCaseIds = 5690) @Test(timeout = ZanataTestCase.MAX_SHORT_TEST_DURATION) @@ -163,4 +215,13 @@ private boolean containsUsernameError(List errors) { return errors.contains(RegisterPage.USERNAME_VALIDATION_ERROR) || errors.contains(RegisterPage.USERNAME_LENGTH_ERROR); } + + private String makeString(int length) { + char[] ret = new char[length]; + Random r = new Random(); + for (int i = 0; i < length; ++i) { + ret[i] = (char) (r.nextInt(26) + 'a'); + } + return String.valueOf(ret); + } } diff --git a/server/functional-test/src/test/java/org/zanata/feature/endtoend/UserEndToEndTest.java b/server/functional-test/src/test/java/org/zanata/feature/endtoend/UserEndToEndTest.java index 0d94fcfc40..2199c74d86 100644 --- a/server/functional-test/src/test/java/org/zanata/feature/endtoend/UserEndToEndTest.java +++ b/server/functional-test/src/test/java/org/zanata/feature/endtoend/UserEndToEndTest.java @@ -53,6 +53,7 @@ import java.util.List; import static org.assertj.core.api.Assertions.assertThat; +import static org.zanata.util.EmailQuery.LinkType.ACTIVATE; /** * This aim of this test is to provide a method of testing as many @@ -211,7 +212,7 @@ private SignInPage registerSuccessfully(RegisterPage registerPage) { private BasePage checkEmailAndFailToActivate() { WiserMessage message = hasEmailRule.getMessages().get(0); - String link = EmailQuery.getActivationLink(message); + String link = EmailQuery.getLink(message, ACTIVATE); boolean exceptionFound = false; BasePage basePage = null; try { @@ -225,7 +226,7 @@ private BasePage checkEmailAndFailToActivate() { private SignInPage checkEmailAndActivate() { WiserMessage message = hasEmailRule.getMessages().get(0); - String link = EmailQuery.getActivationLink(message); + String link = EmailQuery.getLink(message, ACTIVATE); SignInPage signInPage = new BasicWorkFlow().goToUrl(link.concat("?" + dswid), SignInPage.class); diff --git a/server/functional-test/src/test/java/org/zanata/feature/security/SecurityTest.java b/server/functional-test/src/test/java/org/zanata/feature/security/SecurityTest.java index 6b67058822..3552fb95b5 100644 --- a/server/functional-test/src/test/java/org/zanata/feature/security/SecurityTest.java +++ b/server/functional-test/src/test/java/org/zanata/feature/security/SecurityTest.java @@ -29,13 +29,17 @@ import org.zanata.feature.Trace; import org.zanata.feature.testharness.TestPlan.DetailedTest; import org.zanata.feature.testharness.ZanataTestCase; +import org.zanata.page.account.EnterNewPasswordPage; import org.zanata.page.account.ResetPasswordPage; +import org.zanata.page.dashboard.DashboardBasePage; import org.zanata.page.utility.HomePage; +import org.zanata.util.EmailQuery; import org.zanata.util.HasEmailRule; import org.zanata.workflow.BasicWorkFlow; import org.zanata.workflow.LoginWorkFlow; import static org.assertj.core.api.Assertions.assertThat; +import static org.zanata.util.EmailQuery.LinkType.PASSWORD_RESET; /** * @author Damian Jansen djansen@redhat.com */ public class EmailQuery { + private static final org.slf4j.Logger log = + org.slf4j.LoggerFactory.getLogger(EmailQuery.class); - private static Pattern activationLink = Pattern - .compile("<(http://.+/activate/.+)>"); - private static Pattern validateLink = Pattern - .compile("<(http://.+/validate_email/.+)>"); - - public static boolean hasActivationLink(WiserMessage emailMessage) { - Matcher matcher = activationLink.matcher(HasEmailRule.getEmailContent(emailMessage)); - return matcher.find(); + public enum LinkType { + ACTIVATE, VALIDATE_EMAIL, PASSWORD_RESET } - public static String getActivationLink(WiserMessage emailMessage) { - Matcher matcher = activationLink.matcher(HasEmailRule.getEmailContent(emailMessage)); - assert matcher.find(); - return matcher.group(1); + private static Pattern getLinkRegex(LinkType type) { + return Pattern.compile("<(http://.+/" + type.name().toLowerCase() + "/.+)>"); } - public static boolean hasEmailVerificationLink(WiserMessage emailMessage) { - Matcher matcher = validateLink.matcher(HasEmailRule.getEmailContent(emailMessage)); + public static boolean hasLink(WiserMessage emailMessage, LinkType linkType) { + log.info("Query {} has a {} link", emailMessage, linkType.name()); + Pattern linkPattern = getLinkRegex(linkType); + Matcher matcher = linkPattern.matcher(HasEmailRule.getEmailContent(emailMessage)); return matcher.find(); } - public static String getEmailVerificationLink(WiserMessage emailMessage) { - Matcher matcher = validateLink.matcher(HasEmailRule.getEmailContent(emailMessage)); + public static String getLink(WiserMessage emailMessage, LinkType linkType) { + log.info("Get {} link from email {}", linkType.name(), emailMessage); + Pattern linkPattern = getLinkRegex(linkType); + Matcher matcher = linkPattern.matcher(HasEmailRule.getEmailContent(emailMessage)); assert matcher.find(); return matcher.group(1); } diff --git a/server/zanata-war/src/main/webapp/account/password_reset.xhtml b/server/zanata-war/src/main/webapp/account/password_reset.xhtml index b23201ef6d..50c980bd91 100644 --- a/server/zanata-war/src/main/webapp/account/password_reset.xhtml +++ b/server/zanata-war/src/main/webapp/account/password_reset.xhtml @@ -35,21 +35,22 @@

    #{msgs['jsf.ResetPassword']}

    - + #{msgs['jsf.NewPassword']} - + #{msgs['jsf.ConfirmPassword']} -
    From 47de7b5e0352f84121afc645afa3c99cc25189ca Mon Sep 17 00:00:00 2001 From: kgough Date: Mon, 3 Jul 2017 10:12:34 +1000 Subject: [PATCH 060/116] feat(ZNTA-2061) fixed test --- .../webtrans/client/util/ContentStateToStyleUtilTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/util/ContentStateToStyleUtilTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/util/ContentStateToStyleUtilTest.java index 08d7b468f0..2dc7ca31fa 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/util/ContentStateToStyleUtilTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/util/ContentStateToStyleUtilTest.java @@ -16,7 +16,7 @@ public void testStateToStyle() throws Exception { assertThat(stateToStyle(NeedReview)).contains("unsure"); assertThat(stateToStyle(Translated)).contains("success"); assertThat(stateToStyle(Approved)).contains("highlight"); - assertThat(stateToStyle(Rejected)).contains("danger"); + assertThat(stateToStyle(Rejected)).contains("warning"); } @Test From bad810ba73cd93b9c4fbdc52faee1a09d0535fca Mon Sep 17 00:00:00 2001 From: kgough Date: Mon, 3 Jul 2017 11:26:39 +1000 Subject: [PATCH 061/116] feat(ZNTA-2070) added default SettingsOptions and ValidationOptions stories --- .../SettingOption/SettingOption.story.js | 4 +-- .../SettingsOptions/SettingsOptions.story.js | 32 +++++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js index b20938fc23..2f2c499538 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js @@ -35,8 +35,8 @@ class SettingOption extends React.Component { storiesOf('SettingOption', module) .add('default', () => ( )) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js index b560a9ce77..5643ee6bca 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js @@ -43,7 +43,30 @@ class SettingsOptions extends React.Component { } const updateSetting = action('updateSetting') -const settings = +const listUnchecked = + [ + { + id: 'list-item-1', + label: 'List item 1', + active: false + }, + { + id: 'list-item-2', + label: 'List item 2', + active: false + }, + { + id: 'list-item-3', + label: 'List item 3', + active: false + }, + { + id: 'list-item-4', + label: 'List item 4', + active: false + } + ] +const validations = [ { id: 'html-xml-tags', @@ -85,7 +108,12 @@ const settings = storiesOf('SettingsOptions', module) .add('default', () => ( + )) + .add('validation settings', () => ( + )) From 30e3243ac3a9d9c4db0af151dffde639972440e6 Mon Sep 17 00:00:00 2001 From: kgough Date: Mon, 3 Jul 2017 11:59:43 +1000 Subject: [PATCH 062/116] feat(ZNTA-2070) modified default SettingsOptions and ValidationOptions stories --- .../SettingOption/SettingOption.story.js | 4 +- .../SettingsOptions/SettingsOptions.story.js | 63 ++++++++++++++++++- 2 files changed, 63 insertions(+), 4 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js index 2f2c499538..03a264b222 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js @@ -35,8 +35,8 @@ class SettingOption extends React.Component { storiesOf('SettingOption', module) .add('default', () => ( )) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js index 5643ee6bca..6183c58245 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js @@ -66,6 +66,52 @@ const listUnchecked = active: false } ] +const listHalfChecked = + [ + { + id: 'list-item-1', + label: 'List item 1', + active: false + }, + { + id: 'list-item-2', + label: 'List item 2', + active: true + }, + { + id: 'list-item-3', + label: 'List item 3', + active: false + }, + { + id: 'list-item-4', + label: 'List item 4', + active: true + } + ] +const listAllChecked = + [ + { + id: 'list-item-1', + label: 'List item 1', + active: true + }, + { + id: 'list-item-2', + label: 'List item 2', + active: true + }, + { + id: 'list-item-3', + label: 'List item 3', + active: true + }, + { + id: 'list-item-4', + label: 'List item 4', + active: true + } + ] const validations = [ { @@ -106,14 +152,27 @@ const validations = ] storiesOf('SettingsOptions', module) - .add('default', () => ( + .add('default - unchecked', () => ( )) - .add('validation settings', () => ( + .add('default - half-checked', () => ( + + )) + .add('default -all checked', () => ( + + )) + .add('VALIDATION SETTINGS', () => ( +
    +

    Validation settings

    +
    )) From fe2d165fa81a5783e818b274efb74597f9c8bef3 Mon Sep 17 00:00:00 2001 From: kgough Date: Mon, 3 Jul 2017 12:20:30 +1000 Subject: [PATCH 063/116] feat(ZNTA-2070) added the rest of the SettingsOptions stories (Editor options) --- .../SettingsOptions/SettingsOptions.story.js | 59 ++++++++++++++++--- 1 file changed, 51 insertions(+), 8 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js index 6183c58245..c72933c1b4 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js @@ -112,12 +112,41 @@ const listAllChecked = active: true } ] + +const settings = + [ + { + id: 'key-saves', + label: 'Enter key saves immediately', + active: true + }, + { + id: 'syntax-highlight', + label: 'Syntax highlighting', + active: false + } + ] + +const defaults = + [ + { + id: 'suggestions-diff', + label: 'Suggestions diff', + active: false + }, + { + id: 'panel-layout', + label: 'Panel layout', + active: false + } + ] + const validations = [ { id: 'html-xml-tags', label: 'HTML/XML tags', - active: false + active: true }, { id: 'java-variables', @@ -126,13 +155,13 @@ const validations = }, { id: 'leading-trailing-newline', - label: 'Leading/trailing newline (n)', - active: false + label: 'Leading/trailing newline', + active: true }, { id: 'positional-printf', label: 'Positional printf (XSI extension)', - active: true + active: false }, { id: 'printf-variables', @@ -141,13 +170,13 @@ const validations = }, { id: 'tab-characters', - label: 'Tab characters (t)', - active: false + label: 'Tab characters', + active: true }, { id: 'xml-entity-reference', label: 'XML entity reference', - active: true + active: false } ] @@ -167,12 +196,26 @@ storiesOf('SettingsOptions', module) settings={listAllChecked} updateSetting={action('updateSetting')} /> )) + .add('EDITOR SETTINGS', () => ( +
    +

    Editor options

    + +

    Set current layouts as default:

    + +
    + )) .add('VALIDATION SETTINGS', () => (
    -

    Validation settings

    +

    Validation settings

    )) + + From ea955d671c2af8caff62f2c1ebe702027a184d17 Mon Sep 17 00:00:00 2001 From: kgough Date: Mon, 3 Jul 2017 14:35:28 +1000 Subject: [PATCH 064/116] feat(ZNTA-2070) removed wrapper class from SettingOption and SettingsOptions stories --- .../SettingOption/SettingOption.story.js | 31 +------------- .../SettingsOptions/SettingsOptions.story.js | 41 +------------------ 2 files changed, 2 insertions(+), 70 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js index 03a264b222..a4006bd623 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js @@ -1,36 +1,7 @@ import React from 'react' import PropTypes from 'prop-types' import { storiesOf, action } from '@kadira/storybook' -import RealSettingOption from '.' - -class SettingOption extends React.Component { - static propTypes = { - id: PropTypes.any.isRequired, - label: PropTypes.string.isRequired, - active: PropTypes.bool.isRequired, - updateSetting: PropTypes.func.isRequired - } - constructor (props) { - super(props) - this.state = {active:props.active} - } - updateSetting = (id, active) => { - // record the check state in the wrapper - this.setState({ active:active }) - // call the real one that was passed in - this.props.updateSetting( id, active) - } - render () { - return ( - - ) - } -} +import SettingOption from '.' storiesOf('SettingOption', module) .add('default', () => ( diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js index c72933c1b4..2498c72296 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js @@ -1,46 +1,7 @@ import React from 'react' import PropTypes from 'prop-types' import { storiesOf, action } from '@kadira/storybook' -import RealSettingsOptions from '.' - -class SettingsOptions extends React.Component { - static propTypes = { - settings: PropTypes.shape({ - id: PropTypes.any.isRequired, - label: PropTypes.string.isRequired, - active: PropTypes.bool.isRequired - }).isRequired, - updateSetting: PropTypes.func.isRequired - } - constructor (props) { - super(props) - this.state = { settings: props.settings } - } - updateSetting = (id, active) => { - // record the check state in the wrapper - this.setState(newState => ({ - settings: newState.settings.map(setting => { - if (setting.id === id) { - return { - ...setting, - active - } - } else { - return setting - } - }) - })) - // call the real one that was passed in - this.props.updateSetting(id, active) - } - render () { - return ( - - ) - } -} +import SettingsOptions from '.' const updateSetting = action('updateSetting') const listUnchecked = From 6f004d44de9fac9517f43e34e10c748dc8bf569d Mon Sep 17 00:00:00 2001 From: kgough Date: Mon, 3 Jul 2017 14:49:00 +1000 Subject: [PATCH 065/116] feat(ZNTA-2070) css styling for Editor Options and Validation Settings --- .../SettingsOptions/SettingsOptions.story.js | 13 +++++++------ .../app/editor/containers/Sidebar/index.css | 13 +++++++++++-- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js index 2498c72296..a44104a67c 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js @@ -157,25 +157,26 @@ storiesOf('SettingsOptions', module) settings={listAllChecked} updateSetting={action('updateSetting')} /> )) - .add('EDITOR SETTINGS', () => ( + .add('EDITOR OPTIONS', () => (
    -

    Editor options

    +

    Editor options

    -

    Set current layouts as default:

    +

    + Set current layouts as default:

    )) .add('VALIDATION SETTINGS', () => ( -
    -

    Validation settings

    +
    +

    Validation settings

    -
    +
    )) diff --git a/server/zanata-frontend/src/frontend/app/editor/containers/Sidebar/index.css b/server/zanata-frontend/src/frontend/app/editor/containers/Sidebar/index.css index 7445f94625..aa9899e0be 100644 --- a/server/zanata-frontend/src/frontend/app/editor/containers/Sidebar/index.css +++ b/server/zanata-frontend/src/frontend/app/editor/containers/Sidebar/index.css @@ -380,11 +380,20 @@ h2.validation { color: var(--Sidebar-color-text); } -.settings-options h2 { +.settings-heading { font-weight: 500; - padding-bottom: 1rem; } +h2.settings-heading { + padding-bottom:1rem; +} + +h3.settings-heading { + font-size: 0.875rem; + padding-bottom: 0.375rem; + padding-top: 0.75rem; +} + .settings-options p { font-weight: 500; color: var(--Sidebar-color-text); From 004a9aa2b5b30eeeb027e94872324081dda2b60a Mon Sep 17 00:00:00 2001 From: kgough Date: Mon, 3 Jul 2017 14:49:47 +1000 Subject: [PATCH 066/116] feat(ZNTA-2070) added whitespace to storybook storyname --- .../editor/components/SettingsOptions/SettingsOptions.story.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js index a44104a67c..5f28a1e21d 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js @@ -152,7 +152,7 @@ storiesOf('SettingsOptions', module) settings={listHalfChecked} updateSetting={action('updateSetting')} /> )) - .add('default -all checked', () => ( + .add('default - all checked', () => ( From 0f0d8737c2bae4466e8d19aac585d30ceb95f7fc Mon Sep 17 00:00:00 2001 From: kgough Date: Mon, 3 Jul 2017 15:05:41 +1000 Subject: [PATCH 067/116] feat(ZNTA-2070) removed redundant ValidationOptions component from editor/components --- .../ValidationOptions.story.js | 81 ------------------- .../components/ValidationOptions/index.js | 69 ---------------- .../app/editor/components/components.story.js | 1 - 3 files changed, 151 deletions(-) delete mode 100644 server/zanata-frontend/src/frontend/app/editor/components/ValidationOptions/ValidationOptions.story.js delete mode 100644 server/zanata-frontend/src/frontend/app/editor/components/ValidationOptions/index.js diff --git a/server/zanata-frontend/src/frontend/app/editor/components/ValidationOptions/ValidationOptions.story.js b/server/zanata-frontend/src/frontend/app/editor/components/ValidationOptions/ValidationOptions.story.js deleted file mode 100644 index 308ad64a45..0000000000 --- a/server/zanata-frontend/src/frontend/app/editor/components/ValidationOptions/ValidationOptions.story.js +++ /dev/null @@ -1,81 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { storiesOf, action } from '@kadira/storybook' -import RealValidationOptions from '.' - -/* Wrapper class for storybook. - - * The checkbox states will be stored and updated in the live - * app. This wrapper stores the states so that we can see - * them working in storybook too. - */ -class ValidationOptions extends React.Component { - static propTypes = { - states: PropTypes.object.isRequired, - updateValidationOption: PropTypes.func.isRequired - } - constructor (props) { - super(props) - this.state = props.states - } - updateValidationOption = (validation, checked) => { - // record the check state in the wrapper - this.setState({ [validation]: checked }) - // call the real one that was passed in - this.props.updateValidationOption(validation, checked) - } - render () { - return ( - - ) - } -} - -const updateAction = action('updateValidationOption') -/* - * See .storybook/README.md for info on the component storybook. - */ -storiesOf('ValidationOptions', module) - .add('default', () => ( - - )) - - .add('half checked', () => ( - - )) - - .add('all checked', () => ( - - )) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/ValidationOptions/index.js b/server/zanata-frontend/src/frontend/app/editor/components/ValidationOptions/index.js deleted file mode 100644 index d227c56ae5..0000000000 --- a/server/zanata-frontend/src/frontend/app/editor/components/ValidationOptions/index.js +++ /dev/null @@ -1,69 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { Checkbox } from 'react-bootstrap' - -const validations = - ['HTML/XML tags', - 'Java variables', - 'Leading/trailing newline (n)', - 'Positional printf (XSI extension)', - 'Printf variables', - 'Tab characters (t)', - 'XML entity reference'] - -const ValidationOptions = ({states, updateValidationOption}) => { - const checkboxes = validations.map((validation, index) => ( -
  • - -
  • - )) - return ( -
    -

    Validation options

    -
      - {checkboxes} -
    -
    - ) -} - -ValidationOptions.propTypes = { - states: PropTypes.shape({ - 'HTML/XML tags': PropTypes.bool.isRequired, - 'Java variables': PropTypes.bool.isRequired, - 'Leading/trailing newline (n)': PropTypes.bool.isRequired, - 'Positional printf (XSI extension)': PropTypes.bool.isRequired, - 'Printf variables': PropTypes.bool.isRequired, - 'Tab characters (t)': PropTypes.bool.isRequired, - 'XML entity reference': PropTypes.bool.isRequired - }).isRequired, - updateValidationOption: PropTypes.func.isRequired -} - -class ValidationCheckbox extends React.Component { - static propTypes = { - validation: PropTypes.string.isRequired, - checked: PropTypes.bool.isRequired, - /* Will be called with (validation, newValue) */ - onChange: PropTypes.func.isRequired - } - - onChange = (event) => { - this.props.onChange(this.props.validation, event.target.checked) - } - - render () { - const { validation, checked } = this.props - return ( - - {validation} - - ) - } -} - -export default ValidationOptions diff --git a/server/zanata-frontend/src/frontend/app/editor/components/components.story.js b/server/zanata-frontend/src/frontend/app/editor/components/components.story.js index 0f56d07537..746aae6851 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/components.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/components.story.js @@ -13,4 +13,3 @@ require('./GlossaryTerm/GlossaryTerm.story.js') require('./GlossaryTermModal/GlossaryTermModal.story.js') require('./SettingOption/SettingOption.story.js') require('./SettingsOptions/SettingsOptions.story.js') -require('./ValidationOptions/ValidationOptions.story') From e3d56ea72d8e96830bdf516cd013b4dd329d27c7 Mon Sep 17 00:00:00 2001 From: kgough Date: Mon, 3 Jul 2017 16:30:18 +1000 Subject: [PATCH 068/116] feat(ZNTA-2070) WIP storybook wrapper --- .../SettingOption/SettingOption.story.js | 31 +++++++++++++- .../SettingsOptions/SettingsOptions.story.js | 40 ++++++++++++++++++- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js index a4006bd623..d6af3ea6eb 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js @@ -1,7 +1,36 @@ import React from 'react' import PropTypes from 'prop-types' import { storiesOf, action } from '@kadira/storybook' -import SettingOption from '.' + +class SettingOption extends React.Component { + static propTypes = { + id: PropTypes.any.isRequired, + label: PropTypes.string.isRequired, + active: PropTypes.bool.isRequired, + updateSetting: PropTypes.func.isRequired + } + constructor (props) { + super(props) + this.state = {active:props.active} + } + updateSetting = (id, active) => { + // record the check state in the wrapper + this.setState({ active:active }) + // call the real one that was passed in + this.props.updateSetting( id, active) + } + render () { + return ( + + ) + } +} +const updateSetting = action('updateSetting') storiesOf('SettingOption', module) .add('default', () => ( diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js index 5f28a1e21d..016f8fca81 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js @@ -1,7 +1,45 @@ import React from 'react' import PropTypes from 'prop-types' import { storiesOf, action } from '@kadira/storybook' -import SettingsOptions from '.' + +class SettingsOptions extends React.Component { + static propTypes = { + settings: PropTypes.shape({ + id: PropTypes.any.isRequired, + label: PropTypes.string.isRequired, + active: PropTypes.bool.isRequired + }).isRequired, + updateSetting: PropTypes.func.isRequired + } + constructor (props) { + super(props) + this.state = { settings: props.settings } + } + updateSetting = (id, active) => { + // record the check state in the wrapper + this.setState(newState => ({ + settings: newState.settings.map(setting => { + if (setting.id === id) { + return { + ...setting, + active + } + } else { + return setting + } + }) + })) + // call the real one that was passed in + this.props.updateSetting(id, active) + } + render () { + return ( + + ) + } +} const updateSetting = action('updateSetting') const listUnchecked = From a6c82ecc3da6ae19de8287d84f635e7b0f63140a Mon Sep 17 00:00:00 2001 From: kgough Date: Mon, 3 Jul 2017 16:58:29 +1000 Subject: [PATCH 069/116] feat(ZNTA-2070) fixed wrapper and styling of SettingOption and SettingsOptions stories --- .../SettingOption/SettingOption.story.js | 5 ++- .../SettingsOptions/SettingsOptions.story.js | 7 ++-- .../app/editor/containers/Sidebar/index.css | 41 ++++++++++--------- 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js index d6af3ea6eb..092c250c3d 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js @@ -1,6 +1,7 @@ import React from 'react' import PropTypes from 'prop-types' import { storiesOf, action } from '@kadira/storybook' +import RealSettingOption from '.' class SettingOption extends React.Component { static propTypes = { @@ -21,15 +22,15 @@ class SettingOption extends React.Component { } render () { return ( - ) } } + const updateSetting = action('updateSetting') storiesOf('SettingOption', module) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js index 016f8fca81..2d6aae1540 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js @@ -1,6 +1,7 @@ import React from 'react' import PropTypes from 'prop-types' import { storiesOf, action } from '@kadira/storybook' +import RealSettingsOptions from '.' class SettingsOptions extends React.Component { static propTypes = { @@ -34,9 +35,9 @@ class SettingsOptions extends React.Component { } render () { return ( - + ) } } diff --git a/server/zanata-frontend/src/frontend/app/editor/containers/Sidebar/index.css b/server/zanata-frontend/src/frontend/app/editor/containers/Sidebar/index.css index aa9899e0be..65c7a322db 100644 --- a/server/zanata-frontend/src/frontend/app/editor/containers/Sidebar/index.css +++ b/server/zanata-frontend/src/frontend/app/editor/containers/Sidebar/index.css @@ -380,26 +380,6 @@ h2.validation { color: var(--Sidebar-color-text); } -.settings-heading { - font-weight: 500; - } - -h2.settings-heading { - padding-bottom:1rem; -} - -h3.settings-heading { - font-size: 0.875rem; - padding-bottom: 0.375rem; - padding-top: 0.75rem; -} - -.settings-options p { - font-weight: 500; - color: var(--Sidebar-color-text); - font-size: 0.875rem; -} - li .checkbox { font-size: var(--Sidebar-small-text); } @@ -422,6 +402,27 @@ select.settings-select { color: var(--Sidebar-color-text); } +.settings-heading { + font-weight: 500; +} + +h2.settings-heading { + padding-bottom:1rem; +} + +h3.settings-heading { + font-size: 0.875rem; + padding-bottom: 0.375rem; + padding-top: 0.75rem; +} + +.settings-options p { + font-weight: 500; + color: var(--Sidebar-color-text); + font-size: 0.875rem; +} + + /* --------------------- */ From 2bf5532255d58ac2b491e615963d27d0372717d4 Mon Sep 17 00:00:00 2001 From: kathryngo Date: Mon, 3 Jul 2017 18:07:32 +1000 Subject: [PATCH 070/116] Update SettingOption.story.js --- .../app/editor/components/SettingOption/SettingOption.story.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js index 092c250c3d..7eff456a8b 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingOption/SettingOption.story.js @@ -31,8 +31,6 @@ class SettingOption extends React.Component { } } -const updateSetting = action('updateSetting') - storiesOf('SettingOption', module) .add('default', () => ( Date: Tue, 4 Jul 2017 09:14:19 +1000 Subject: [PATCH 071/116] Update SettingOption.story.js From 748730d30c1941215227e9f23c119be5e01167cc Mon Sep 17 00:00:00 2001 From: kathryngo Date: Tue, 4 Jul 2017 09:17:55 +1000 Subject: [PATCH 072/116] Update SettingsOptions.story.js --- .../editor/components/SettingsOptions/SettingsOptions.story.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js index 2d6aae1540..9104422f44 100644 --- a/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js +++ b/server/zanata-frontend/src/frontend/app/editor/components/SettingsOptions/SettingsOptions.story.js @@ -217,6 +217,3 @@ storiesOf('SettingsOptions', module) updateSetting={action('updateSetting')} />
    )) - - - From 22cb8c576d15b36b19af324225335c1ee5e3d33f Mon Sep 17 00:00:00 2001 From: David Mason Date: Mon, 3 Jul 2017 16:17:12 +1000 Subject: [PATCH 073/116] fix(test-watch): add test-watch script to package.json This allows command `make test-watch` and `make test-watch coverage=[glob pattern]` to be run. When coverage is not specified, the default coverage pattern for all files is used. --- server/zanata-frontend/src/frontend/makefile | 10 +++++++++- server/zanata-frontend/src/frontend/package.json | 3 ++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/server/zanata-frontend/src/frontend/makefile b/server/zanata-frontend/src/frontend/makefile index 225a10ad79..13c8528387 100644 --- a/server/zanata-frontend/src/frontend/makefile +++ b/server/zanata-frontend/src/frontend/makefile @@ -58,9 +58,17 @@ test: yarn test # Run the tests on every change +# Specify coverage=path if you want to limit reported coverage scope. This is +# useful when using pattern mode to limit the tests that are run. +# e.g. make test-watch coverage="app/editor/reducers/*" +# p > app/editor/reducers/.* +# NOTE coverage uses a glob pattern (*), but test pattern uses a regex (.*) test-watch: +ifdef coverage + yarn test:watch -- --collectCoverageFrom=$(coverage) +else yarn test:watch - +endif # Run a server that implements some of the Zanata API with some dummy data. # The server runs on localhost:7878 and has 0.5 to 5s of random latency. diff --git a/server/zanata-frontend/src/frontend/package.json b/server/zanata-frontend/src/frontend/package.json index fca923fc6b..320853f503 100644 --- a/server/zanata-frontend/src/frontend/package.json +++ b/server/zanata-frontend/src/frontend/package.json @@ -14,7 +14,8 @@ "storybook-editor": "start-storybook -p 9001 -s ./dist --config-dir .storybook-editor", "storybook-frontend": "start-storybook -p 9001 -s ./dist --config-dir .storybook-frontend", "storybook-build": "build-storybook -s ./dist", - "test": "jest --coverage" + "test": "jest --coverage", + "test:watch": "jest --watch --coverage" }, "repository": { "type": "git", From 6a70d83ae75b5b24eb9453dd99c8619f04917ef3 Mon Sep 17 00:00:00 2001 From: Alex Eng Date: Tue, 4 Jul 2017 14:57:25 +1000 Subject: [PATCH 074/116] fix: handle nullable version id list --- .../zanata/service/impl/TranslationMemoryServiceImpl.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/service/impl/TranslationMemoryServiceImpl.java b/server/zanata-war/src/main/java/org/zanata/service/impl/TranslationMemoryServiceImpl.java index 8beb0f2d3c..3119974a0b 100644 --- a/server/zanata-war/src/main/java/org/zanata/service/impl/TranslationMemoryServiceImpl.java +++ b/server/zanata-war/src/main/java/org/zanata/service/impl/TranslationMemoryServiceImpl.java @@ -34,6 +34,7 @@ import java.util.Optional; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.inject.Named; @@ -485,7 +486,8 @@ private static class TransMemoryResultComparator private static final long serialVersionUID = 1L; private final List fromVersionIds; - public TransMemoryResultComparator(List fromVersionIds) { + public TransMemoryResultComparator( + @Nullable List fromVersionIds) { this.fromVersionIds = fromVersionIds; } @@ -510,7 +512,9 @@ public int compare(TransMemoryResultItem m1, TransMemoryResultItem m2) { } // if TM is from TMX, getFromVersionId is null // if fromVersionIds is empty, we have no restriction on source version - if (m2.getFromVersionId() != null && m1.getFromVersionId() != null && !fromVersionIds.isEmpty()) { + if (m2.getFromVersionId() != null && + m1.getFromVersionId() != null && fromVersionIds != null && + !fromVersionIds.isEmpty()) { int indexOfM2 = fromVersionIds.indexOf(m2.getFromVersionId()); int indexOfM1 = fromVersionIds.indexOf(m1.getFromVersionId()); // sort higher when index is lower From b72ea4a86942ed55b67fc2a00723b6673458962d Mon Sep 17 00:00:00 2001 From: Alex Eng Date: Thu, 6 Jul 2017 20:45:07 +1000 Subject: [PATCH 075/116] fix: switch yellow and white for tm diff (#414) https://zanata.atlassian.net/browse/ZNTA-2092 --- .../zanata/webtrans/client/resources/UiMessages.java | 10 +++++++--- .../webtrans/client/resources/WebTransMessages.java | 2 +- .../webtrans/client/ui/DiffColorLegendPanel.java | 2 +- .../webtrans/client/ui/DiffColorLegendPanel.ui.xml | 6 +++--- .../org/zanata/webtrans/client/ui/Highlighting.java | 6 +++--- .../zanata/webtrans/client/view/TransMemoryView.java | 6 +++++- .../zanata/webtrans/client/view/TransMemoryView.ui.xml | 2 +- 7 files changed, 21 insertions(+), 13 deletions(-) diff --git a/server/gwt-editor/src/main/java/org/zanata/webtrans/client/resources/UiMessages.java b/server/gwt-editor/src/main/java/org/zanata/webtrans/client/resources/UiMessages.java index 5384282aa7..d5393a610b 100644 --- a/server/gwt-editor/src/main/java/org/zanata/webtrans/client/resources/UiMessages.java +++ b/server/gwt-editor/src/main/java/org/zanata/webtrans/client/resources/UiMessages.java @@ -20,8 +20,6 @@ */ package org.zanata.webtrans.client.resources; -import java.util.List; - import com.google.gwt.i18n.client.LocalizableResource.DefaultLocale; import com.google.gwt.i18n.client.LocalizableResource.Generate; import com.google.gwt.i18n.client.Messages; @@ -230,7 +228,7 @@ public interface UiMessages extends Messages { @DefaultMessage("Show as Diff") String diffModeAsDiff(); - @DefaultMessage("Highlight matches") + @DefaultMessage("Highlight Diff") String diffModeAsHighlight(); @DefaultMessage("Translation that contained validation warning or error.") @@ -250,4 +248,10 @@ public interface UiMessages extends Messages { @DefaultMessage("No content") String noContent(); + + @DefaultMessage("Matching") + String matching(); + + @DefaultMessage("Not Matching") + String notMatching(); } diff --git a/server/gwt-editor/src/main/java/org/zanata/webtrans/client/resources/WebTransMessages.java b/server/gwt-editor/src/main/java/org/zanata/webtrans/client/resources/WebTransMessages.java index 36a3915fb3..55aab342df 100644 --- a/server/gwt-editor/src/main/java/org/zanata/webtrans/client/resources/WebTransMessages.java +++ b/server/gwt-editor/src/main/java/org/zanata/webtrans/client/resources/WebTransMessages.java @@ -426,7 +426,7 @@ String undoUnsuccessful(@PluralCount int unsuccessfulCount, String noMatch(); @DefaultMessage("Matching") - String noColor(); + String matching(); /** * Used for color legend in search and replace view diff --git a/server/gwt-editor/src/main/java/org/zanata/webtrans/client/ui/DiffColorLegendPanel.java b/server/gwt-editor/src/main/java/org/zanata/webtrans/client/ui/DiffColorLegendPanel.java index 46b51af25d..0973105c4f 100644 --- a/server/gwt-editor/src/main/java/org/zanata/webtrans/client/ui/DiffColorLegendPanel.java +++ b/server/gwt-editor/src/main/java/org/zanata/webtrans/client/ui/DiffColorLegendPanel.java @@ -85,7 +85,7 @@ public void show(ShortcutContext context, DiffMode diffMode) { case TM: searchOnlyLabel.setText(messages.searchOnly()); tmOnlyLabel.setText(messages.tmOnly()); - matchLabel.setText(messages.noColor()); + matchLabel.setText(messages.matching()); searchOnlyDescription.setText(messages.tmInsertTagDesc()); tmOnlyDescription.setText(messages.tmDelTagDesc()); diff --git a/server/gwt-editor/src/main/java/org/zanata/webtrans/client/ui/DiffColorLegendPanel.ui.xml b/server/gwt-editor/src/main/java/org/zanata/webtrans/client/ui/DiffColorLegendPanel.ui.xml index 2ab9fccc29..068d2fcff0 100644 --- a/server/gwt-editor/src/main/java/org/zanata/webtrans/client/ui/DiffColorLegendPanel.ui.xml +++ b/server/gwt-editor/src/main/java/org/zanata/webtrans/client/ui/DiffColorLegendPanel.ui.xml @@ -50,9 +50,9 @@ - + - + @@ -63,7 +63,7 @@ - + diff --git a/server/gwt-editor/src/main/java/org/zanata/webtrans/client/ui/Highlighting.java b/server/gwt-editor/src/main/java/org/zanata/webtrans/client/ui/Highlighting.java index 0cbb594b3d..58dde985a2 100644 --- a/server/gwt-editor/src/main/java/org/zanata/webtrans/client/ui/Highlighting.java +++ b/server/gwt-editor/src/main/java/org/zanata/webtrans/client/ui/Highlighting.java @@ -120,7 +120,7 @@ private static native String diffsToHtml(JavaScriptObject diffs) html[x] = '' + text + ''; break; case $wnd['DIFF_EQUAL']: - html[x] = '' + text + ''; + html[x] = '' + text + ''; break; } } @@ -150,12 +150,12 @@ private static native String diffsHighlight(JavaScriptObject diffs) '
    '); switch (op) { case $wnd['DIFF_INSERT']: - html[x] = text; + html[x] = '' + text + ''; break; case $wnd['DIFF_DELETE']: break; case $wnd['DIFF_EQUAL']: - html[x] = '' + text + ''; + html[x] = text; break; } } diff --git a/server/gwt-editor/src/main/java/org/zanata/webtrans/client/view/TransMemoryView.java b/server/gwt-editor/src/main/java/org/zanata/webtrans/client/view/TransMemoryView.java index 33beb8a0aa..13e38ec844 100644 --- a/server/gwt-editor/src/main/java/org/zanata/webtrans/client/view/TransMemoryView.java +++ b/server/gwt-editor/src/main/java/org/zanata/webtrans/client/view/TransMemoryView.java @@ -91,7 +91,7 @@ interface Styles extends CssResource { UiMessages messages; @UiField - InlineLabel searchOnly, tmOnly, diffLegendLabel; + InlineLabel searchOnly, tmOnly, diffLegendLabel, notMatching; @UiField FocusPanel diffLegend; @@ -235,10 +235,14 @@ private void updateDisplayMode() { if (determineDiffMode() == DiffMode.NORMAL) { tmOnly.removeStyleName("is-hidden"); searchOnly.removeStyleName("is-hidden"); + notMatching.removeStyleName("CodeMirror-searching"); + notMatching.setText(messages.matching()); diffLegendLabel.setText(messages.tmDiffHighlighting()); } else { tmOnly.addStyleName("is-hidden"); searchOnly.addStyleName("is-hidden"); + notMatching.addStyleName("CodeMirror-searching"); + notMatching.setText(messages.notMatching()); diffLegendLabel.setText(messages.tmHighlighting()); } } diff --git a/server/gwt-editor/src/main/java/org/zanata/webtrans/client/view/TransMemoryView.ui.xml b/server/gwt-editor/src/main/java/org/zanata/webtrans/client/view/TransMemoryView.ui.xml index 24df9cba3a..0a20cb89ac 100644 --- a/server/gwt-editor/src/main/java/org/zanata/webtrans/client/view/TransMemoryView.ui.xml +++ b/server/gwt-editor/src/main/java/org/zanata/webtrans/client/view/TransMemoryView.ui.xml @@ -69,7 +69,7 @@
  • - Matching + Not matching TM only Search only From 5bec377bb9a85043a6412b6fdb0df267f0805122 Mon Sep 17 00:00:00 2001 From: kgough Date: Fri, 7 Jul 2017 16:16:37 +1000 Subject: [PATCH 076/116] fix(ZNTA-2062) fixed wrapping of long document names in editor suggestions panel --- .../app/editor/containers/Root/index.css | 10 +++++-- .../SuggestionDetailsModal/index.css | 26 +++++++++---------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/editor/containers/Root/index.css b/server/zanata-frontend/src/frontend/app/editor/containers/Root/index.css index f8e55c45d8..2b97fe3842 100644 --- a/server/zanata-frontend/src/frontend/app/editor/containers/Root/index.css +++ b/server/zanata-frontend/src/frontend/app/editor/containers/Root/index.css @@ -197,8 +197,9 @@ font-weight: 600; } -li.docName { - max-width: 20em; +li.docName .row { + display: flex; + width: 12rem; } li.docName span.ellipsis { @@ -855,6 +856,11 @@ label span.n1 { max-width: 9.5em; } + li.docName .row { + display: flex; + width: 20rem; + } + #sidebartabs-pane-1 table tbody tr { display: table-row !important; } diff --git a/server/zanata-frontend/src/frontend/app/editor/containers/SuggestionDetailsModal/index.css b/server/zanata-frontend/src/frontend/app/editor/containers/SuggestionDetailsModal/index.css index b0afee3e29..29fa96a183 100644 --- a/server/zanata-frontend/src/frontend/app/editor/containers/SuggestionDetailsModal/index.css +++ b/server/zanata-frontend/src/frontend/app/editor/containers/SuggestionDetailsModal/index.css @@ -8,12 +8,12 @@ .Editor-suggestionsBody .TransUnit--suggestion .TransUnit-text--tight { padding-top: 0 !important; - font-size:1em; + font-size: 1em; } .TransUnit--suggestion .TransUnit-text--tight { - padding-top:40px !important; - font-size:1.2em; + padding-top: 40px !important; + font-size: 1.2em; } /* Based on bootstrap styles. */ @@ -68,7 +68,7 @@ -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); box-shadow: 0 1px 1px rgba(0, 0, 0, .05); background-color: #fcfcfc; - line-height:1.2em; + line-height: 1.2em; } .panel-body { @@ -86,7 +86,7 @@ margin-bottom: 0; color: inherit; font-size: 1.143em; - padding-bottom:0 + padding-bottom: 0; } .panel.panel-side { @@ -113,7 +113,7 @@ .panel-info > .panel-heading { border-bottom: solid 1px var(--brand-info); color: var(--brand-info); - background-color:#fcfcfc; + background-color: #fcfcfc; font-weight: 300; } @@ -193,14 +193,14 @@ } .TransUnit-details { - white-space:normal; + white-space: normal; word-break: break-all; - line-height:1em; + line-height: 1em; } .TransUnit-details .u-listInline { - display:inline-flex; - width:100%; + display: block; + width: 100%; } li.TransUnit-label-suggestions { @@ -208,9 +208,9 @@ li.TransUnit-label-suggestions { } span.TransUnit-details-inner { - padding-left:0.375em; - font-weight:500; - color:#444c54; + padding-left: 0.375em; + font-weight: 500; + color: #444c54; } From 529fec9bd6f30bb479153d42c12acbac95a98234 Mon Sep 17 00:00:00 2001 From: Sean Flanigan Date: Tue, 11 Jul 2017 12:16:18 +1000 Subject: [PATCH 077/116] Use Markdown licences, Maven badges for clients (#417) * Add Maven badges for Zanata clients * Use Markdown version of licence texts --- LICENSE.LESSER.txt | 502 -------------------------------------------- LICENSE.txt | 339 ------------------------------ client/README.md | 10 + client/README.txt | 2 - license-gpl.md | 361 ++++++++++++++++++++++++++++++++ license.md | 503 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 874 insertions(+), 843 deletions(-) delete mode 100644 LICENSE.LESSER.txt delete mode 100644 LICENSE.txt create mode 100644 client/README.md delete mode 100644 client/README.txt create mode 100644 license-gpl.md create mode 100644 license.md diff --git a/LICENSE.LESSER.txt b/LICENSE.LESSER.txt deleted file mode 100644 index 551cb4acb9..0000000000 --- a/LICENSE.LESSER.txt +++ /dev/null @@ -1,502 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library 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 library 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 library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index d159169d10..0000000000 --- a/LICENSE.txt +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/client/README.md b/client/README.md new file mode 100644 index 0000000000..b3a3a3adf2 --- /dev/null +++ b/client/README.md @@ -0,0 +1,10 @@ +Holds most of Zanata's client code, including the Zanata Maven Plugin and Zanata CLI, but not the python client. +It also contains client-side bindings for interacting with a Zanata server's REST API. + +[![license](https://img.shields.io/github/license/zanata/zanata-platform.svg?maxAge=3600)](https://github.com/zanata/zanata-platform/blob/master/LICENSE) + +Latest version of zanata-cli: +[![Maven Central](https://img.shields.io/maven-central/v/org.zanata/zanata-cli.svg)](https://maven-badges.herokuapp.com/maven-central/org.zanata/zanata-cli) + +Latest version of zanata-maven-plugin: +[![Maven Central](https://img.shields.io/maven-central/v/org.zanata/zanata-maven-plugin.svg)](https://maven-badges.herokuapp.com/maven-central/org.zanata/zanata-maven-plugin) diff --git a/client/README.txt b/client/README.txt deleted file mode 100644 index 9722d79443..0000000000 --- a/client/README.txt +++ /dev/null @@ -1,2 +0,0 @@ -Holds most of Zanata's client code, including the Zanata Maven Plugin and Zanata CLI, but not the python client. -It also contains REST stub for interacting with a Zanata server. diff --git a/license-gpl.md b/license-gpl.md new file mode 100644 index 0000000000..00c115f306 --- /dev/null +++ b/license-gpl.md @@ -0,0 +1,361 @@ +### GNU GENERAL PUBLIC LICENSE + +Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +### Preamble + +The licenses for most software are designed to take away your freedom +to share and change it. By contrast, the GNU General Public License is +intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + +We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, +we want its recipients to know that what they have is not the +original, so that any problems introduced by others will not reflect +on the original authors' reputations. + +Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at +all. + +The precise terms and conditions for copying, distribution and +modification follow. + +### TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +**0.** This License applies to any program or other work which +contains a notice placed by the copyright holder saying it may be +distributed under the terms of this General Public License. The +"Program", below, refers to any such program or work, and a "work +based on the Program" means either the Program or any derivative work +under copyright law: that is to say, a work containing the Program or +a portion of it, either verbatim or with modifications and/or +translated into another language. (Hereinafter, translation is +included without limitation in the term "modification".) Each licensee +is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the Program +(independent of having been made by running the Program). Whether that +is true depends on what the Program does. + +**1.** You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a +fee. + +**2.** You may modify your copy or copies of the Program or any +portion of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + +**a)** You must cause the modified files to carry prominent notices +stating that you changed the files and the date of any change. + + +**b)** You must cause any work that you distribute or publish, that in +whole or in part contains or is derived from the Program or any part +thereof, to be licensed as a whole at no charge to all third parties +under the terms of this License. + + +**c)** If the modified program normally reads commands interactively +when run, you must cause it, when started running for such interactive +use in the most ordinary way, to print or display an announcement +including an appropriate copyright notice and a notice that there is +no warranty (or else, saying that you provide a warranty) and that +users may redistribute the program under these conditions, and telling +the user how to view a copy of this License. (Exception: if the +Program itself is interactive but does not normally print such an +announcement, your work based on the Program is not required to print +an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + +**3.** You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + +**a)** Accompany it with the complete corresponding machine-readable +source code, which must be distributed under the terms of Sections 1 +and 2 above on a medium customarily used for software interchange; or, + + +**b)** Accompany it with a written offer, valid for at least three +years, to give any third party, for a charge no more than your cost of +physically performing source distribution, a complete machine-readable +copy of the corresponding source code, to be distributed under the +terms of Sections 1 and 2 above on a medium customarily used for +software interchange; or, + + +**c)** Accompany it with the information you received as to the offer +to distribute corresponding source code. (This alternative is allowed +only for noncommercial distribution and only if you received the +program in object code or executable form with such an offer, in +accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + +**4.** You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt otherwise +to copy, modify, sublicense or distribute the Program is void, and +will automatically terminate your rights under this License. However, +parties who have received copies, or rights, from you under this +License will not have their licenses terminated so long as such +parties remain in full compliance. + +**5.** You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +**6.** Each time you redistribute the Program (or any work based on +the Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + +**7.** If, as a consequence of a court judgment or allegation of +patent infringement or for any other reason (not limited to patent +issues), conditions are imposed on you (whether by court order, +agreement or otherwise) that contradict the conditions of this +License, they do not excuse you from the conditions of this License. +If you cannot distribute so as to satisfy simultaneously your +obligations under this License and any other pertinent obligations, +then as a consequence you may not distribute the Program at all. For +example, if a patent license would not permit royalty-free +redistribution of the Program by all those who receive copies directly +or indirectly through you, then the only way you could satisfy both it +and this License would be to refrain entirely from distribution of the +Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + +**8.** If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + +**9.** The Free Software Foundation may publish revised and/or new +versions of the General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Program does not specify a +version number of this License, you may choose any version ever +published by the Free Software Foundation. + +**10.** If you wish to incorporate parts of the Program into other +free programs whose distribution conditions are different, write to +the author to ask for permission. For software which is copyrighted by +the Free Software Foundation, write to the Free Software Foundation; +we sometimes make exceptions for this. Our decision will be guided by +the two goals of preserving the free status of all derivatives of our +free software and of promoting the sharing and reuse of software +generally. + +**NO WARRANTY** + +**11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +**12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +### END OF TERMS AND CONDITIONS + +### How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + +To do so, attach the following notices to the program. It is safest to +attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + one line to give the program's name and an idea of what it does. + Copyright (C) yyyy name of author + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Also add information on how to contact you by electronic and paper +mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details + type `show w'. This is free software, and you are welcome + to redistribute it under certain conditions; type `show c' + for details. + +The hypothetical commands \`show w' and \`show c' should show the +appropriate parts of the General Public License. Of course, the +commands you use may be called something other than \`show w' and +\`show c'; they could even be mouse-clicks or menu items--whatever +suits your program. + +You should also get your employer (if you work as a programmer) or +your school, if any, to sign a "copyright disclaimer" for the program, +if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright + interest in the program `Gnomovision' + (which makes passes at compilers) written + by James Hacker. + + signature of Ty Coon, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, +you may consider it more useful to permit linking proprietary +applications with the library. If this is what you want to do, use the +[GNU Lesser General Public +License](http://www.gnu.org/licenses/lgpl.html) instead of this +License. diff --git a/license.md b/license.md new file mode 100644 index 0000000000..b14d908353 --- /dev/null +++ b/license.md @@ -0,0 +1,503 @@ +### GNU LESSER GENERAL PUBLIC LICENSE + +Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + [This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + +### Preamble + +The licenses for most software are designed to take away your freedom +to share and change it. By contrast, the GNU General Public Licenses +are intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. + +This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations +below. + +When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + +To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + +For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + +We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + +To protect each distributor, we want to make it very clear that there +is no warranty for the free library. Also, if the library is modified +by someone else and passed on, the recipients should know that what +they have is not the original version, so that the original author's +reputation will not be affected by problems that might be introduced +by others. + +Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + +Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + +When a program is linked with a library, whether statically or using a +shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + +We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + +For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it +becomes a de-facto standard. To achieve this, non-free programs must +be allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + +In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + +Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + +The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + +### TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +**0.** This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). Each +licensee is addressed as "you". + +A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + +The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + +"Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control +compilation and installation of the library. + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does and +what the program that uses the Library does. + +**1.** You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a +fee. + +**2.** You may modify your copy or copies of the Library or any +portion of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + +- **a)** The modified work must itself be a software library. +- **b)** You must cause the files modified to carry prominent + notices stating that you changed the files and the date of + any change. +- **c)** You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. +- **d)** If a facility in the modified Library refers to a function + or a table of data to be supplied by an application program that + uses the facility, other than as an argument passed when the + facility is invoked, then you must make a good faith effort to + ensure that, in the event an application does not supply such + function or table, the facility still operates, and performs + whatever part of its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of + the application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + +**3.** You may opt to apply the terms of the ordinary GNU General +Public License instead of this License to a given copy of the Library. +To do this, you must alter all the notices that refer to this License, +so that they refer to the ordinary GNU General Public License, version +2, instead of to this License. (If a newer version than version 2 of +the ordinary GNU General Public License has appeared, then you can +specify that version instead if you wish.) Do not make any other +change in these notices. + +Once this change is made in a given copy, it is irreversible for that +copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + +This option is useful when you wish to copy part of the code of the +Library into a program that is not a library. + +**4.** You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + +If distribution of object code is made by offering access to copy from +a designated place, then offering equivalent access to copy the source +code from the same place satisfies the requirement to distribute the +source code, even though third parties are not compelled to copy the +source along with the object code. + +**5.** A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a work, +in isolation, is not a derivative work of the Library, and therefore +falls outside the scope of this License. + +However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. Section +6 states terms for distribution of such executables. + +When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + +If such an object file uses only numerical parameters, data structure +layouts and accessors, and small macros and small inline functions +(ten lines or less in length), then the use of the object file is +unrestricted, regardless of whether it is legally a derivative work. +(Executables containing this object code plus portions of the Library +will still fall under Section 6.) + +Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + +**6.** As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a work +containing portions of the Library, and distribute that work under +terms of your choice, provided that the terms permit modification of +the work for the customer's own use and reverse engineering for +debugging such modifications. + +You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + +- **a)** Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood that + the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) +- **b)** Use a suitable shared library mechanism for linking with + the Library. A suitable mechanism is one that (1) uses at run time + a copy of the library already present on the user's computer + system, rather than copying library functions into the executable, + and (2) will operate properly with a modified version of the + library, if the user installs one, as long as the modified version + is interface-compatible with the version that the work was + made with. +- **c)** Accompany the work with a written offer, valid for at least + three years, to give the same user the materials specified in + Subsection 6a, above, for a charge no more than the cost of + performing this distribution. +- **d)** If distribution of the work is made by offering access to + copy from a designated place, offer equivalent access to copy the + above specified materials from the same place. +- **e)** Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + +For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + +It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + +**7.** You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + +- **a)** Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other + library facilities. This must be distributed under the terms of + the Sections above. +- **b)** Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + +**8.** You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + +**9.** You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + +**10.** Each time you redistribute the Library (or any work based on +the Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + +**11.** If, as a consequence of a court judgment or allegation of +patent infringement or for any other reason (not limited to patent +issues), conditions are imposed on you (whether by court order, +agreement or otherwise) that contradict the conditions of this +License, they do not excuse you from the conditions of this License. +If you cannot distribute so as to satisfy simultaneously your +obligations under this License and any other pertinent obligations, +then as a consequence you may not distribute the Library at all. For +example, if a patent license would not permit royalty-free +redistribution of the Library by all those who receive copies directly +or indirectly through you, then the only way you could satisfy both it +and this License would be to refrain entirely from distribution of the +Library. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply, and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + +**12.** If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + +**13.** The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. Such +new versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + +**14.** If you wish to incorporate parts of the Library into other +free programs whose distribution conditions are incompatible with +these, write to the author to ask for permission. For software which +is copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + +**NO WARRANTY** + +**15.** BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +**16.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +### END OF TERMS AND CONDITIONS + +### How to Apply These Terms to Your New Libraries + +If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms +of the ordinary General Public License). + +To apply these terms, attach the following notices to the library. It +is safest to attach them to the start of each source file to most +effectively convey the exclusion of warranty; and each file should +have at least the "copyright" line and a pointer to where the full +notice is found. + + one line to give the library's name and an idea of what it does. + Copyright (C) year name of author + + This library 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 library 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 library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper +mail. + +You should also get your employer (if you work as a programmer) or +your school, if any, to sign a "copyright disclaimer" for the library, +if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in + the library `Frob' (a library for tweaking knobs) written + by James Random Hacker. + + signature of Ty Coon, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! From be8512c3d229c5eed71f4697db19b61c9f2ba123 Mon Sep 17 00:00:00 2001 From: kgough Date: Wed, 12 Jul 2017 09:34:43 +1000 Subject: [PATCH 078/116] fix(ZNTA-2107) word breaking and removal of hyphens for editor --- server/zanata-frontend/src/frontend/app/styles/style.less | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/server/zanata-frontend/src/frontend/app/styles/style.less b/server/zanata-frontend/src/frontend/app/styles/style.less index 28ab31cd77..18336855e4 100644 --- a/server/zanata-frontend/src/frontend/app/styles/style.less +++ b/server/zanata-frontend/src/frontend/app/styles/style.less @@ -6035,6 +6035,14 @@ i.i--left.i--lock, i.i--left.i--trash { padding-bottom:@spacing-base-and-a-half; } +.translationContainer pre.cm-s-default { + word-break: break-word; + word-wrap: break-word; + -webkit-hyphens: initial; + -moz-hyphens: initial; + hyphens: initial; +} + // @screen-xs variable depreciated @media (max-width: 29.375rem) { .view { From 543f946750ea61854f2d3e122523075640f7417f Mon Sep 17 00:00:00 2001 From: Damian Jansen Date: Wed, 12 Jul 2017 16:16:16 +1000 Subject: [PATCH 079/116] fix(test): Workaround flake in test suite (#419) --- .../zanata/feature/search/comp/GroupSearchCTest.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/server/functional-test/src/test/java/org/zanata/feature/search/comp/GroupSearchCTest.java b/server/functional-test/src/test/java/org/zanata/feature/search/comp/GroupSearchCTest.java index 0ab9041aef..8f537c9713 100644 --- a/server/functional-test/src/test/java/org/zanata/feature/search/comp/GroupSearchCTest.java +++ b/server/functional-test/src/test/java/org/zanata/feature/search/comp/GroupSearchCTest.java @@ -25,7 +25,6 @@ import org.junit.experimental.categories.Category; import org.zanata.feature.testharness.TestPlan; import org.zanata.feature.testharness.ZanataTestCase; -import org.zanata.page.dashboard.DashboardGroupsTab; import org.zanata.page.explore.ExplorePage; import org.zanata.page.groups.VersionGroupPage; import org.zanata.workflow.BasicWorkFlow; @@ -40,8 +39,6 @@ @Category(TestPlan.ComprehensiveTest.class) public class GroupSearchCTest extends ZanataTestCase { - private DashboardGroupsTab dashboardGroupsTab; - @Test(timeout = MAX_SHORT_TEST_DURATION) public void successfulGroupSearchAndDisplay() throws Exception { String groupID = "basic-group"; @@ -49,10 +46,10 @@ public void successfulGroupSearchAndDisplay() throws Exception { assertThat(new LoginWorkFlow().signIn("admin", "admin").loggedInAs()) .isEqualTo("admin") .as("Admin is logged in"); - dashboardGroupsTab = - new BasicWorkFlow().goToHome().goToMyDashboard().gotoGroupsTab(); - VersionGroupPage groupPage = dashboardGroupsTab + new BasicWorkFlow().goToHome() + .goToMyDashboard() + .gotoGroupsTab() .createNewGroup() .inputGroupId(groupID) .inputGroupName(groupName) @@ -80,7 +77,7 @@ public void unsuccessfulGroupSearch() throws Exception { ExplorePage explorePage = new BasicWorkFlow() .goToHome() .gotoExplore() - .enterSearch("group"); + .enterSearch("groop"); assertThat(explorePage.getGroupSearchResults().isEmpty()) .isTrue() From fba487a5a886d938f07093b94e745eb9519d6397 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Wed, 12 Jul 2017 16:24:20 +1000 Subject: [PATCH 080/116] ZNTA-2056 - index slug without analyze and support prefix search --- .../hibernate/search/IndexFieldLabels.java | 4 + .../java/org/zanata/model/SlugEntityBase.java | 8 +- .../main/java/org/zanata/dao/ProjectDAO.java | 38 ++++++---- .../java/org/zanata/dao/ProjectDAOTest.java | 74 +++++++++++++++++-- 4 files changed, 102 insertions(+), 22 deletions(-) diff --git a/server/zanata-model/src/main/java/org/zanata/hibernate/search/IndexFieldLabels.java b/server/zanata-model/src/main/java/org/zanata/hibernate/search/IndexFieldLabels.java index ae8dd9832b..b7d56cdf6a 100644 --- a/server/zanata-model/src/main/java/org/zanata/hibernate/search/IndexFieldLabels.java +++ b/server/zanata-model/src/main/java/org/zanata/hibernate/search/IndexFieldLabels.java @@ -36,4 +36,8 @@ public interface IndexFieldLabels { public static final String GLOSSARY_QUALIFIED_NAME = "glossaryEntry.glossary.qualifiedName"; String PROJECT_VERSION_ID_FIELD = "projectVersionId"; + /* + * Represents the full slug without tokenize + */ + String FULL_SLUG_FIELD = "fullSlug"; } diff --git a/server/zanata-model/src/main/java/org/zanata/model/SlugEntityBase.java b/server/zanata-model/src/main/java/org/zanata/model/SlugEntityBase.java index 6a6459aadd..58d6883339 100644 --- a/server/zanata-model/src/main/java/org/zanata/model/SlugEntityBase.java +++ b/server/zanata-model/src/main/java/org/zanata/model/SlugEntityBase.java @@ -28,7 +28,10 @@ import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import org.hibernate.annotations.NaturalId; +import org.hibernate.search.annotations.Analyze; import org.hibernate.search.annotations.Field; +import org.hibernate.search.annotations.Fields; +import org.zanata.hibernate.search.IndexFieldLabels; import org.zanata.model.validator.Slug; import com.google.common.annotations.VisibleForTesting; @@ -48,7 +51,10 @@ public abstract class SlugEntityBase extends ModelEntityBase { @Size(min = 1, max = 40) @Slug @NotNull - @Field + @Fields({ + @Field, + @Field(analyze = Analyze.NO, name = IndexFieldLabels.FULL_SLUG_FIELD) + }) private String slug; /** diff --git a/server/zanata-war/src/main/java/org/zanata/dao/ProjectDAO.java b/server/zanata-war/src/main/java/org/zanata/dao/ProjectDAO.java index bb584986a6..2309c354c0 100644 --- a/server/zanata-war/src/main/java/org/zanata/dao/ProjectDAO.java +++ b/server/zanata-war/src/main/java/org/zanata/dao/ProjectDAO.java @@ -53,6 +53,8 @@ import org.zanata.model.HProjectIteration; import org.zanata.model.ProjectRole; +import static org.zanata.hibernate.search.IndexFieldLabels.FULL_SLUG_FIELD; + @RequestScoped public class ProjectDAO extends AbstractDAOImpl { @Inject @FullText @@ -66,6 +68,11 @@ public ProjectDAO(Session session) { super(HProject.class, session); } + public ProjectDAO(FullTextEntityManager entityManager, Session session) { + super(HProject.class, session); + this.entityManager = entityManager; + } + public @Nullable HProject getBySlug(@Nonnull String slug) { if (!StringUtils.isEmpty(slug)) { @@ -283,15 +290,18 @@ public int getQueryProjectSize(@Nonnull String searchQuery, private FullTextQuery buildSearchQuery(@Nonnull String searchQuery, boolean includeObsolete) throws ParseException { - String queryText = QueryParser.escape(searchQuery); - Analyzer sourceAnalyzer = entityManager.getSearchFactory() + String escapedSearchQuery = QueryParser.escape(searchQuery); + Analyzer defaultAnalyzer = entityManager.getSearchFactory() .getAnalyzer(Analyzers.DEFAULT); - MultiFieldQueryParser queryParser = new MultiFieldQueryParser( - new String[]{ "slug", "name", "description" }, sourceAnalyzer); - queryParser.setDefaultOperator(QueryParser.Operator.OR); + MultiFieldQueryParser multiFieldQueryParser = new MultiFieldQueryParser( + new String[]{ "name", "description" }, defaultAnalyzer); + multiFieldQueryParser.setDefaultOperator(QueryParser.Operator.OR); BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder(); - booleanQuery.add(queryParser.parse(queryText), BooleanClause.Occur.SHOULD); + // for slug, we do prefix search (so people can search with '-' in it + booleanQuery.add(buildSearchFieldQuery(searchQuery, FULL_SLUG_FIELD), BooleanClause.Occur.SHOULD); + // for name and description, we split the word using the same analyzer and search as is + booleanQuery.add(multiFieldQueryParser.parse(escapedSearchQuery), BooleanClause.Occur.SHOULD); if (!includeObsolete) { TermQuery obsoleteStateQuery = new TermQuery(new Term(IndexFieldLabels.ENTITY_STATUS, @@ -299,7 +309,8 @@ private FullTextQuery buildSearchQuery(@Nonnull String searchQuery, booleanQuery.add(obsoleteStateQuery, BooleanClause.Occur.MUST_NOT); } - return entityManager.createFullTextQuery(booleanQuery.build(), HProject.class); + BooleanQuery luceneQuery = booleanQuery.build(); + return entityManager.createFullTextQuery(luceneQuery, HProject.class); } /** @@ -307,24 +318,21 @@ private FullTextQuery buildSearchQuery(@Nonnull String searchQuery, * white space. * * @param searchQuery - * - query string, will replace hypen with space and escape - * special char + * - query string, will escape special char * @param field * - lucene field */ private BooleanQuery buildSearchFieldQuery(@Nonnull String searchQuery, @Nonnull String field) throws ParseException { - BooleanQuery query = new BooleanQuery(); - - //escape special character search - searchQuery = QueryParser.escape(searchQuery); + BooleanQuery.Builder query = new BooleanQuery.Builder(); for(String searchString: searchQuery.split("\\s+")) { QueryParser parser = new QueryParser(field, new CaseInsensitiveWhitespaceAnalyzer()); - query.add(parser.parse(searchString + "*"), BooleanClause.Occur.MUST); + //escape special character search + query.add(parser.parse(QueryParser.escape(searchString) + "*"), BooleanClause.Occur.MUST); } - return query; + return query.build(); } public List findAllTranslatedProjects(HAccount account, int maxResults) { diff --git a/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOTest.java b/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOTest.java index dad28ef87c..7977964d35 100644 --- a/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOTest.java +++ b/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOTest.java @@ -4,22 +4,60 @@ import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; +import org.assertj.core.api.Assertions; import org.dbunit.operation.DatabaseOperation; import org.hibernate.Session; -import org.junit.Before; +import org.hibernate.search.jpa.FullTextEntityManager; +import org.hibernate.search.jpa.Search; +import org.jglue.cdiunit.AdditionalClasses; +import org.jglue.cdiunit.InRequestScope; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.zanata.ZanataDbunitJpaTest; +import org.zanata.action.ReindexClassOptions; +import org.zanata.async.AsyncTaskHandle; +import org.zanata.jpa.FullText; import org.zanata.model.HProject; import org.zanata.security.ZanataIdentity; +import org.zanata.service.IndexingService; +import org.zanata.service.impl.IndexingServiceImpl; +import org.zanata.test.CdiUnitRunner; +import org.zanata.util.Zanata; +import java.util.HashMap; import java.util.List; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import javax.enterprise.inject.Produces; +import javax.inject.Inject; +import javax.persistence.EntityManagerFactory; +import com.google.common.collect.Maps; + +@RunWith(CdiUnitRunner.class) +@AdditionalClasses({ IndexingServiceImpl.class}) public class ProjectDAOTest extends ZanataDbunitJpaTest { + @Produces Session produceSession() { + return getSession(); + } + @Produces @FullText FullTextEntityManager getFulltextEM() { + return Search.getFullTextEntityManager(getEm()); + } + + @Produces + @Zanata + EntityManagerFactory getEntityManagerFactory() { + return getEmf(); + } + + @Inject private ProjectDAO dao; + @Inject + private IndexingService indexingService; + @Override protected void prepareDBUnitOperations() { beforeTestOperations.add(new DataSetOperation( @@ -32,11 +70,6 @@ public static void disableSecurity() { ZanataIdentity.setSecurityEnabled(false); } - @Before - public void setup() { - dao = new ProjectDAO((Session) getEm().getDelegate()); - } - @Test public void getValidProjectBySlug() { HProject project = dao.getBySlug("sample-project"); @@ -107,4 +140,33 @@ public void getOffsetList() { dao.getOffsetList(-1, -1, false, false, false); assertThat(projects.size(), is(4)); } + + @Test + @InRequestScope + public void canDoFullTextSearch() throws Exception { + HashMap, ReindexClassOptions> indexingOptions = + Maps.newHashMap(); + ReindexClassOptions option = new ReindexClassOptions(HProject.class); + option.setSelectAll(true); + indexingOptions.put(HProject.class, option); + Future future = indexingService + .startIndexing(indexingOptions, new AsyncTaskHandle<>()); + future.get(500, TimeUnit.SECONDS); + + HProject expected = dao.getBySlug("sample-project"); + + + List result = + dao.searchProjects("sam", 10, 0, false); + Assertions.assertThat(result).contains(expected); + + List result1 = dao.searchProjects("sampl ", 10, 0, false); + Assertions.assertThat(result1).contains(expected); + + List result2 = dao.searchProjects("sample-", 10, 0, false); + Assertions.assertThat(result2).contains(expected); + + List result3 = dao.searchProjects("a project", 10, 0, false); + Assertions.assertThat(result3).contains(expected); + } } From 93a4d320f6e92f7ba05872f9e55b7f77f8053866 Mon Sep 17 00:00:00 2001 From: kgough Date: Thu, 13 Jul 2017 08:21:22 +1000 Subject: [PATCH 081/116] fix(ZNTA-2107) fixed word-breaks in Firefox --- .../zanata-frontend/src/frontend/app/styles/style.less | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/styles/style.less b/server/zanata-frontend/src/frontend/app/styles/style.less index 18336855e4..13b77c50df 100644 --- a/server/zanata-frontend/src/frontend/app/styles/style.less +++ b/server/zanata-frontend/src/frontend/app/styles/style.less @@ -906,8 +906,8 @@ pre { display: block; margin: 0 0 @spacing-heading; padding: @spacing-large-horizontal; - word-wrap: break-word; - word-break: break-all; + word-break: normal; + word-break: break-word; /*Chrome specific*/ color: @gray-dark; border: 1px solid #ccc; border-radius: @border-radius-base; @@ -6036,8 +6036,9 @@ i.i--left.i--lock, i.i--left.i--trash { } .translationContainer pre.cm-s-default { - word-break: break-word; - word-wrap: break-word; + word-wrap: normal; + word-break: normal; + word-break: break-word; /*Chrome specific*/ -webkit-hyphens: initial; -moz-hyphens: initial; hyphens: initial; From 411f50c341096bdb230a4d5cc3cc6479434ced56 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Thu, 13 Jul 2017 10:08:40 +1000 Subject: [PATCH 082/116] ZNTA-2056 split tests into separate classes --- .../org/zanata/dao/ProjectDAOCDIUnitTest.java | 99 +++++++++++++++++++ .../java/org/zanata/dao/ProjectDAOTest.java | 74 ++------------ 2 files changed, 105 insertions(+), 68 deletions(-) create mode 100644 server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOCDIUnitTest.java diff --git a/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOCDIUnitTest.java b/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOCDIUnitTest.java new file mode 100644 index 0000000000..67af05ca26 --- /dev/null +++ b/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOCDIUnitTest.java @@ -0,0 +1,99 @@ +package org.zanata.dao; + +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import javax.enterprise.inject.Produces; +import javax.inject.Inject; +import javax.persistence.EntityManagerFactory; + +import org.assertj.core.api.Assertions; +import org.dbunit.operation.DatabaseOperation; +import org.hibernate.Session; +import org.hibernate.search.jpa.FullTextEntityManager; +import org.hibernate.search.jpa.Search; +import org.jglue.cdiunit.AdditionalClasses; +import org.jglue.cdiunit.InRequestScope; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.zanata.ZanataDbunitJpaTest; +import org.zanata.action.ReindexClassOptions; +import org.zanata.async.AsyncTaskHandle; +import org.zanata.jpa.FullText; +import org.zanata.model.HProject; +import org.zanata.security.ZanataIdentity; +import org.zanata.service.IndexingService; +import org.zanata.service.impl.IndexingServiceImpl; +import org.zanata.test.CdiUnitRunner; +import org.zanata.util.Zanata; +import com.google.common.collect.Maps; + + +@RunWith(CdiUnitRunner.class) +@AdditionalClasses({ IndexingServiceImpl.class}) +public class ProjectDAOCDIUnitTest extends ZanataDbunitJpaTest { + @Produces + Session produceSession() { + return getSession(); + } + + @Produces @FullText + FullTextEntityManager getFulltextEM() { + return Search.getFullTextEntityManager(getEm()); + } + + @Produces + @Zanata + EntityManagerFactory getEntityManagerFactory() { + return getEmf(); + } + + @Inject + private ProjectDAO dao; + + @Inject + private IndexingService indexingService; + + @BeforeClass + public static void disableSecurity() { + ZanataIdentity.setSecurityEnabled(false); + } + + @Override + protected void prepareDBUnitOperations() { + beforeTestOperations.add(new DataSetOperation( + "org/zanata/test/model/ProjectsData.dbunit.xml", + DatabaseOperation.CLEAN_INSERT)); + } + + @Test + @InRequestScope + public void canDoFullTextSearch() throws Exception { + HashMap, ReindexClassOptions> indexingOptions = + Maps.newHashMap(); + ReindexClassOptions option = new ReindexClassOptions(HProject.class); + option.setSelectAll(true); + indexingOptions.put(HProject.class, option); + Future future = indexingService + .startIndexing(indexingOptions, new AsyncTaskHandle<>()); + future.get(500, TimeUnit.SECONDS); + + HProject expected = dao.getBySlug("sample-project"); + + + List result = + dao.searchProjects("sam", 10, 0, false); + Assertions.assertThat(result).contains(expected); + + List result1 = dao.searchProjects("sampl ", 10, 0, false); + Assertions.assertThat(result1).contains(expected); + + List result2 = dao.searchProjects("sample-", 10, 0, false); + Assertions.assertThat(result2).contains(expected); + + List result3 = dao.searchProjects("a project", 10, 0, false); + Assertions.assertThat(result3).contains(expected); + } +} diff --git a/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOTest.java b/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOTest.java index 7977964d35..dad28ef87c 100644 --- a/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOTest.java +++ b/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOTest.java @@ -4,60 +4,22 @@ import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; -import org.assertj.core.api.Assertions; import org.dbunit.operation.DatabaseOperation; import org.hibernate.Session; -import org.hibernate.search.jpa.FullTextEntityManager; -import org.hibernate.search.jpa.Search; -import org.jglue.cdiunit.AdditionalClasses; -import org.jglue.cdiunit.InRequestScope; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.zanata.ZanataDbunitJpaTest; -import org.zanata.action.ReindexClassOptions; -import org.zanata.async.AsyncTaskHandle; -import org.zanata.jpa.FullText; import org.zanata.model.HProject; import org.zanata.security.ZanataIdentity; -import org.zanata.service.IndexingService; -import org.zanata.service.impl.IndexingServiceImpl; -import org.zanata.test.CdiUnitRunner; -import org.zanata.util.Zanata; -import java.util.HashMap; import java.util.List; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import javax.enterprise.inject.Produces; -import javax.inject.Inject; -import javax.persistence.EntityManagerFactory; -import com.google.common.collect.Maps; - -@RunWith(CdiUnitRunner.class) -@AdditionalClasses({ IndexingServiceImpl.class}) public class ProjectDAOTest extends ZanataDbunitJpaTest { - @Produces Session produceSession() { - return getSession(); - } - @Produces @FullText FullTextEntityManager getFulltextEM() { - return Search.getFullTextEntityManager(getEm()); - } - - @Produces - @Zanata - EntityManagerFactory getEntityManagerFactory() { - return getEmf(); - } - - @Inject private ProjectDAO dao; - @Inject - private IndexingService indexingService; - @Override protected void prepareDBUnitOperations() { beforeTestOperations.add(new DataSetOperation( @@ -70,6 +32,11 @@ public static void disableSecurity() { ZanataIdentity.setSecurityEnabled(false); } + @Before + public void setup() { + dao = new ProjectDAO((Session) getEm().getDelegate()); + } + @Test public void getValidProjectBySlug() { HProject project = dao.getBySlug("sample-project"); @@ -140,33 +107,4 @@ public void getOffsetList() { dao.getOffsetList(-1, -1, false, false, false); assertThat(projects.size(), is(4)); } - - @Test - @InRequestScope - public void canDoFullTextSearch() throws Exception { - HashMap, ReindexClassOptions> indexingOptions = - Maps.newHashMap(); - ReindexClassOptions option = new ReindexClassOptions(HProject.class); - option.setSelectAll(true); - indexingOptions.put(HProject.class, option); - Future future = indexingService - .startIndexing(indexingOptions, new AsyncTaskHandle<>()); - future.get(500, TimeUnit.SECONDS); - - HProject expected = dao.getBySlug("sample-project"); - - - List result = - dao.searchProjects("sam", 10, 0, false); - Assertions.assertThat(result).contains(expected); - - List result1 = dao.searchProjects("sampl ", 10, 0, false); - Assertions.assertThat(result1).contains(expected); - - List result2 = dao.searchProjects("sample-", 10, 0, false); - Assertions.assertThat(result2).contains(expected); - - List result3 = dao.searchProjects("a project", 10, 0, false); - Assertions.assertThat(result3).contains(expected); - } } From fbefb1ba058e3af3ac90f18bd0526c6ecda871e3 Mon Sep 17 00:00:00 2001 From: Sean Flanigan Date: Thu, 13 Jul 2017 10:46:23 +1000 Subject: [PATCH 083/116] Add .gitattributes for scripts and JS files (#422) * Add .gitattributes for JS files * Ensure build/mvnw use LF --- .gitattributes | 6 +++++- server/zanata-frontend/.gitattributes | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 server/zanata-frontend/.gitattributes diff --git a/.gitattributes b/.gitattributes index 13edf646ed..72cdd367e3 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,7 +5,7 @@ # converted to the OS's native line endings. * text -# Explicitly declare text files we want to always be normalized and converted +# Explicitly declare text files we want to always be normalized and converted # to native line endings on checkout. *.c text *.css text @@ -29,6 +29,10 @@ # Declare files that will always have CRLF line endings on checkout. *.sln text eol=crlf +# Declare files that will always have LF line endings on checkout. +build text eol=lf +mvnw text eol=lf + # Denote all files that are truly binary and should not be modified. *.gif binary *.jar binary diff --git a/server/zanata-frontend/.gitattributes b/server/zanata-frontend/.gitattributes new file mode 100644 index 0000000000..e1898b8d7c --- /dev/null +++ b/server/zanata-frontend/.gitattributes @@ -0,0 +1,3 @@ +*.js text eol=lf +*.jsx text eol=lf +*.jsx.src text eol=lf From d1728b6154f2934d72cb03785ff5b15d10efffaa Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Thu, 13 Jul 2017 13:26:00 +1000 Subject: [PATCH 084/116] ZNTA-2056 use same analyzer for index and search --- .../java/org/zanata/model/SlugEntityBase.java | 6 +- .../main/java/org/zanata/dao/ProjectDAO.java | 23 ++--- .../org/zanata/dao/ProjectDAOCDIUnitTest.java | 99 ------------------- .../org/zanata/dao/ProjectDAOJPATest.java | 82 +++++++++++++++ 4 files changed, 97 insertions(+), 113 deletions(-) delete mode 100644 server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOCDIUnitTest.java create mode 100644 server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOJPATest.java diff --git a/server/zanata-model/src/main/java/org/zanata/model/SlugEntityBase.java b/server/zanata-model/src/main/java/org/zanata/model/SlugEntityBase.java index 58d6883339..5fc2e3f783 100644 --- a/server/zanata-model/src/main/java/org/zanata/model/SlugEntityBase.java +++ b/server/zanata-model/src/main/java/org/zanata/model/SlugEntityBase.java @@ -27,10 +27,14 @@ import javax.persistence.Transient; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; + +import org.apache.lucene.analysis.core.SimpleAnalyzer; import org.hibernate.annotations.NaturalId; import org.hibernate.search.annotations.Analyze; +import org.hibernate.search.annotations.Analyzer; import org.hibernate.search.annotations.Field; import org.hibernate.search.annotations.Fields; +import org.zanata.hibernate.search.CaseInsensitiveWhitespaceAnalyzer; import org.zanata.hibernate.search.IndexFieldLabels; import org.zanata.model.validator.Slug; import com.google.common.annotations.VisibleForTesting; @@ -53,7 +57,7 @@ public abstract class SlugEntityBase extends ModelEntityBase { @NotNull @Fields({ @Field, - @Field(analyze = Analyze.NO, name = IndexFieldLabels.FULL_SLUG_FIELD) + @Field(analyzer = @Analyzer(impl = CaseInsensitiveWhitespaceAnalyzer.class), name = IndexFieldLabels.FULL_SLUG_FIELD) }) private String slug; diff --git a/server/zanata-war/src/main/java/org/zanata/dao/ProjectDAO.java b/server/zanata-war/src/main/java/org/zanata/dao/ProjectDAO.java index 2309c354c0..df2ea80bea 100644 --- a/server/zanata-war/src/main/java/org/zanata/dao/ProjectDAO.java +++ b/server/zanata-war/src/main/java/org/zanata/dao/ProjectDAO.java @@ -27,9 +27,7 @@ import javax.annotation.Nullable; import org.apache.commons.lang.StringUtils; -import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.index.Term; -import org.apache.lucene.queryparser.classic.MultiFieldQueryParser; import org.apache.lucene.queryparser.classic.ParseException; import org.apache.lucene.queryparser.classic.QueryParser; import org.apache.lucene.search.BooleanClause; @@ -43,7 +41,6 @@ import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import org.zanata.common.EntityStatus; -import org.zanata.hibernate.search.Analyzers; import org.zanata.hibernate.search.CaseInsensitiveWhitespaceAnalyzer; import org.zanata.hibernate.search.IndexFieldLabels; import org.zanata.jpa.FullText; @@ -290,18 +287,13 @@ public int getQueryProjectSize(@Nonnull String searchQuery, private FullTextQuery buildSearchQuery(@Nonnull String searchQuery, boolean includeObsolete) throws ParseException { - String escapedSearchQuery = QueryParser.escape(searchQuery); - Analyzer defaultAnalyzer = entityManager.getSearchFactory() - .getAnalyzer(Analyzers.DEFAULT); - MultiFieldQueryParser multiFieldQueryParser = new MultiFieldQueryParser( - new String[]{ "name", "description" }, defaultAnalyzer); - multiFieldQueryParser.setDefaultOperator(QueryParser.Operator.OR); BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder(); // for slug, we do prefix search (so people can search with '-' in it - booleanQuery.add(buildSearchFieldQuery(searchQuery, FULL_SLUG_FIELD), BooleanClause.Occur.SHOULD); + booleanQuery.add(buildSearchFieldQuery(searchQuery, FULL_SLUG_FIELD, true), BooleanClause.Occur.SHOULD); // for name and description, we split the word using the same analyzer and search as is - booleanQuery.add(multiFieldQueryParser.parse(escapedSearchQuery), BooleanClause.Occur.SHOULD); + booleanQuery.add(buildSearchFieldQuery(searchQuery, "name", false), BooleanClause.Occur.SHOULD); + booleanQuery.add(buildSearchFieldQuery(searchQuery, "description", false), BooleanClause.Occur.SHOULD); if (!includeObsolete) { TermQuery obsoleteStateQuery = new TermQuery(new Term(IndexFieldLabels.ENTITY_STATUS, @@ -321,16 +313,21 @@ private FullTextQuery buildSearchQuery(@Nonnull String searchQuery, * - query string, will escape special char * @param field * - lucene field + * @param wildcard + * - whether append wildcard to the end */ private BooleanQuery buildSearchFieldQuery(@Nonnull String searchQuery, - @Nonnull String field) throws ParseException { + @Nonnull String field, boolean wildcard) throws ParseException { BooleanQuery.Builder query = new BooleanQuery.Builder(); for(String searchString: searchQuery.split("\\s+")) { QueryParser parser = new QueryParser(field, new CaseInsensitiveWhitespaceAnalyzer()); //escape special character search - query.add(parser.parse(QueryParser.escape(searchString) + "*"), BooleanClause.Occur.MUST); + + String escaped = QueryParser.escape(searchString); + escaped = wildcard ? escaped + "*" : escaped; + query.add(parser.parse(escaped), BooleanClause.Occur.MUST); } return query.build(); } diff --git a/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOCDIUnitTest.java b/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOCDIUnitTest.java deleted file mode 100644 index 67af05ca26..0000000000 --- a/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOCDIUnitTest.java +++ /dev/null @@ -1,99 +0,0 @@ -package org.zanata.dao; - -import java.util.HashMap; -import java.util.List; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import javax.enterprise.inject.Produces; -import javax.inject.Inject; -import javax.persistence.EntityManagerFactory; - -import org.assertj.core.api.Assertions; -import org.dbunit.operation.DatabaseOperation; -import org.hibernate.Session; -import org.hibernate.search.jpa.FullTextEntityManager; -import org.hibernate.search.jpa.Search; -import org.jglue.cdiunit.AdditionalClasses; -import org.jglue.cdiunit.InRequestScope; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.zanata.ZanataDbunitJpaTest; -import org.zanata.action.ReindexClassOptions; -import org.zanata.async.AsyncTaskHandle; -import org.zanata.jpa.FullText; -import org.zanata.model.HProject; -import org.zanata.security.ZanataIdentity; -import org.zanata.service.IndexingService; -import org.zanata.service.impl.IndexingServiceImpl; -import org.zanata.test.CdiUnitRunner; -import org.zanata.util.Zanata; -import com.google.common.collect.Maps; - - -@RunWith(CdiUnitRunner.class) -@AdditionalClasses({ IndexingServiceImpl.class}) -public class ProjectDAOCDIUnitTest extends ZanataDbunitJpaTest { - @Produces - Session produceSession() { - return getSession(); - } - - @Produces @FullText - FullTextEntityManager getFulltextEM() { - return Search.getFullTextEntityManager(getEm()); - } - - @Produces - @Zanata - EntityManagerFactory getEntityManagerFactory() { - return getEmf(); - } - - @Inject - private ProjectDAO dao; - - @Inject - private IndexingService indexingService; - - @BeforeClass - public static void disableSecurity() { - ZanataIdentity.setSecurityEnabled(false); - } - - @Override - protected void prepareDBUnitOperations() { - beforeTestOperations.add(new DataSetOperation( - "org/zanata/test/model/ProjectsData.dbunit.xml", - DatabaseOperation.CLEAN_INSERT)); - } - - @Test - @InRequestScope - public void canDoFullTextSearch() throws Exception { - HashMap, ReindexClassOptions> indexingOptions = - Maps.newHashMap(); - ReindexClassOptions option = new ReindexClassOptions(HProject.class); - option.setSelectAll(true); - indexingOptions.put(HProject.class, option); - Future future = indexingService - .startIndexing(indexingOptions, new AsyncTaskHandle<>()); - future.get(500, TimeUnit.SECONDS); - - HProject expected = dao.getBySlug("sample-project"); - - - List result = - dao.searchProjects("sam", 10, 0, false); - Assertions.assertThat(result).contains(expected); - - List result1 = dao.searchProjects("sampl ", 10, 0, false); - Assertions.assertThat(result1).contains(expected); - - List result2 = dao.searchProjects("sample-", 10, 0, false); - Assertions.assertThat(result2).contains(expected); - - List result3 = dao.searchProjects("a project", 10, 0, false); - Assertions.assertThat(result3).contains(expected); - } -} diff --git a/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOJPATest.java b/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOJPATest.java new file mode 100644 index 0000000000..a7e1cccfd0 --- /dev/null +++ b/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOJPATest.java @@ -0,0 +1,82 @@ +package org.zanata.dao; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import java.util.function.Function; + +import javax.persistence.EntityManager; + +import org.apache.lucene.queryparser.classic.ParseException; +import org.hibernate.search.jpa.Search; +import org.jglue.cdiunit.InRequestScope; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.zanata.ZanataJpaTest; +import org.zanata.model.HProject; +import org.zanata.security.ZanataIdentity; + + +public class ProjectDAOJPATest extends ZanataJpaTest { + + private ProjectDAO dao; + + @BeforeClass + public static void disableSecurity() { + ZanataIdentity.setSecurityEnabled(false); + } + + @Before + public void setUp() { + dao = new ProjectDAO(Search.getFullTextEntityManager(getEm()), getSession()); + } + + private static HProject makeProject(String slug, String name, String description, + EntityManager em) { + HProject hProject = new HProject(); + hProject.setSlug(slug); + hProject.setName(name); + hProject.setDescription(description); + em.persist(hProject); + return hProject; + } + + private void doInTransaction(Function function) { + EntityManager em = getEmf().createEntityManager(); + em.getTransaction().begin(); + function.apply(em); + em.getTransaction().commit(); + } + + @After + public void cleanUp() { + deleteAllTables(); + } + + @Test + @InRequestScope + public void canDoFullTextSearch() throws Exception { + String slug = "Sample-Project"; + // hibernate search only works with transaction in place + doInTransaction(em -> makeProject(slug, "Sample Project", "An example project", em)); + + HProject expected = dao.getBySlug(slug); + + + assertThat(searchProjects("sam")).contains(expected); + assertThat(searchProjects("SaM")).contains(expected); + assertThat(searchProjects("sampl ")).contains(expected); + assertThat(searchProjects("sample-")).contains(expected); + assertThat(searchProjects("proj")) + .as("wildcard search only for full slug") + .isEmpty(); + assertThat(searchProjects("an project")).contains(expected) + .as("search by description"); + } + + private List searchProjects(String sam) throws ParseException { + return dao.searchProjects(sam, 10, 0, false); + } +} From f652cb46aea4cdefcab572fb801d308afe1c0fe8 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Thu, 13 Jul 2017 17:00:28 +1000 Subject: [PATCH 085/116] ZNTA-2056 - add more test --- .../org/zanata/dao/ProjectDAOJPATest.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOJPATest.java b/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOJPATest.java index a7e1cccfd0..b014f2f7eb 100644 --- a/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOJPATest.java +++ b/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOJPATest.java @@ -17,6 +17,7 @@ import org.zanata.ZanataJpaTest; import org.zanata.model.HProject; import org.zanata.security.ZanataIdentity; +import com.google.common.collect.Lists; public class ProjectDAOJPATest extends ZanataJpaTest { @@ -43,10 +44,10 @@ private static HProject makeProject(String slug, String name, String description return hProject; } - private void doInTransaction(Function function) { + private void doInTransaction(Iterable> function) { EntityManager em = getEmf().createEntityManager(); em.getTransaction().begin(); - function.apply(em); + function.forEach(f -> f.apply(em)); em.getTransaction().commit(); } @@ -60,19 +61,22 @@ public void cleanUp() { public void canDoFullTextSearch() throws Exception { String slug = "Sample-Project"; // hibernate search only works with transaction in place - doInTransaction(em -> makeProject(slug, "Sample Project", "An example project", em)); + doInTransaction(Lists.newArrayList( + em -> makeProject(slug, "Sample Project", "An example project", em), + em -> makeProject("another-project", "another Project", "Another project", em) + )); HProject expected = dao.getBySlug(slug); - - assertThat(searchProjects("sam")).contains(expected); - assertThat(searchProjects("SaM")).contains(expected); - assertThat(searchProjects("sampl ")).contains(expected); - assertThat(searchProjects("sample-")).contains(expected); + assertThat(searchProjects("blah")).isEmpty(); + assertThat(searchProjects("sam")).containsExactly(expected); + assertThat(searchProjects("SaM")).containsExactly(expected); + assertThat(searchProjects("sampl ")).containsExactly(expected); + assertThat(searchProjects("sample-")).containsExactly(expected); assertThat(searchProjects("proj")) - .as("wildcard search only for full slug") + .as("wildcard search is only applied to full slug") .isEmpty(); - assertThat(searchProjects("an project")).contains(expected) + assertThat(searchProjects("an project")).containsExactly(expected) .as("search by description"); } From f5c2cf69e7d96aa827508f1d575bc15dbaf65849 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Fri, 14 Jul 2017 09:41:25 +1000 Subject: [PATCH 086/116] ZNTA-2056 update test --- .../org/zanata/dao/ProjectDAOJPATest.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOJPATest.java b/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOJPATest.java index b014f2f7eb..74d8b2acb4 100644 --- a/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOJPATest.java +++ b/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOJPATest.java @@ -3,6 +3,7 @@ import static org.assertj.core.api.Assertions.assertThat; import java.util.List; +import java.util.function.Consumer; import java.util.function.Function; import javax.persistence.EntityManager; @@ -34,20 +35,19 @@ public void setUp() { dao = new ProjectDAO(Search.getFullTextEntityManager(getEm()), getSession()); } - private static HProject makeProject(String slug, String name, String description, + private static void makeProject(String slug, String name, String description, EntityManager em) { HProject hProject = new HProject(); hProject.setSlug(slug); hProject.setName(name); hProject.setDescription(description); em.persist(hProject); - return hProject; } - private void doInTransaction(Iterable> function) { + private void doInTransaction(Consumer function) { EntityManager em = getEmf().createEntityManager(); em.getTransaction().begin(); - function.forEach(f -> f.apply(em)); + function.accept(em); em.getTransaction().commit(); } @@ -61,10 +61,13 @@ public void cleanUp() { public void canDoFullTextSearch() throws Exception { String slug = "Sample-Project"; // hibernate search only works with transaction in place - doInTransaction(Lists.newArrayList( - em -> makeProject(slug, "Sample Project", "An example project", em), - em -> makeProject("another-project", "another Project", "Another project", em) - )); + doInTransaction( + em -> { + makeProject(slug, "Sample Project", "An example project", + em); + makeProject("another-project", "another Project", + "Another project", em); + }); HProject expected = dao.getBySlug(slug); @@ -76,7 +79,7 @@ public void canDoFullTextSearch() throws Exception { assertThat(searchProjects("proj")) .as("wildcard search is only applied to full slug") .isEmpty(); - assertThat(searchProjects("an project")).containsExactly(expected) + assertThat(searchProjects("example project")).containsExactly(expected) .as("search by description"); } From d91ea8835a23aea385e5bbad1f894c2912c87161 Mon Sep 17 00:00:00 2001 From: Carlos Munoz Date: Sun, 16 Jul 2017 19:44:59 -0400 Subject: [PATCH 087/116] Improve REST API docs (#415) * code review changes * improve REST documentation for the copy trans resource * improve REST API docs for project list resource * improve REST API docs for statistics endpoint * improve REST API documentation for system version endpoint * add REST api docs for Glossary endpoint * improve REST API documentation for Translations endpoint * code review corrections --- .../java/org/zanata/common/EntityStatus.java | 13 +- .../org/zanata/rest/dto/CopyTransStatus.java | 11 ++ .../org/zanata/rest/dto/GlossaryEntry.java | 26 ++- .../org/zanata/rest/dto/GlossaryInfo.java | 9 + .../zanata/rest/dto/GlossaryLocaleInfo.java | 7 + .../org/zanata/rest/dto/GlossaryResults.java | 12 +- .../org/zanata/rest/dto/GlossaryTerm.java | 23 ++- .../main/java/org/zanata/rest/dto/Link.java | 17 ++ .../main/java/org/zanata/rest/dto/Links.java | 6 + .../org/zanata/rest/dto/LocaleDetails.java | 29 +++ .../java/org/zanata/rest/dto/Project.java | 34 ++++ .../org/zanata/rest/dto/ProjectIteration.java | 15 ++ .../org/zanata/rest/dto/QualifiedName.java | 6 +- .../java/org/zanata/rest/dto/ResultList.java | 3 + .../java/org/zanata/rest/dto/VersionInfo.java | 16 +- .../zanata/rest/dto/resource/Resource.java | 20 +-- .../dto/resource/TranslationsResource.java | 14 ++ .../stats/ContainerTranslationStatistics.java | 4 + .../rest/dto/stats/TranslationStatistics.java | 14 ++ .../BaseContributionStatistic.java | 2 + .../contribution/ContributionStatistics.java | 9 + .../stats/contribution/LocaleStatistics.java | 15 ++ .../rest/service/CopyTransResource.java | 58 +++--- .../zanata/rest/service/GlossaryResource.java | 170 ++++++++++-------- .../zanata/rest/service/ProjectsResource.java | 24 +-- .../rest/service/StatisticsResource.java | 53 +++--- .../rest/service/TranslatedDocResource.java | 100 ++++++----- .../zanata/rest/service/VersionResource.java | 16 +- .../org/zanata/rest/service/package-info.java | 1 - 29 files changed, 503 insertions(+), 224 deletions(-) delete mode 100644 server/zanata-war/src/main/java/org/zanata/rest/service/package-info.java diff --git a/api/zanata-common-api/src/main/java/org/zanata/common/EntityStatus.java b/api/zanata-common-api/src/main/java/org/zanata/common/EntityStatus.java index 62c1952196..77ba53e64d 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/common/EntityStatus.java +++ b/api/zanata-common-api/src/main/java/org/zanata/common/EntityStatus.java @@ -20,13 +20,24 @@ */ package org.zanata.common; +import com.webcohesion.enunciate.metadata.Label; + import javax.xml.bind.annotation.XmlEnum; import javax.xml.bind.annotation.XmlType; +/** + * The possible state of various entities in the system. + */ @XmlType(name = "entityStatusType") @XmlEnum(String.class) +@Label("Status") public enum EntityStatus { - ACTIVE("jsf.Active"), READONLY("jsf.ReadOnly"), OBSOLETE("jsf.Obsolete"); + /** Regular state for most entities. Means it is readable and writeable */ + ACTIVE("jsf.Active"), + /** Same as active, but cannot be modified */ + READONLY("jsf.ReadOnly"), + /** Removed from the system. An object in this state cannot be accessed. */ + OBSOLETE("jsf.Obsolete"); public static EntityStatus valueOf(char initial) { switch (initial) { diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/CopyTransStatus.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/CopyTransStatus.java index 6380218b77..3b4a46e2e4 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/CopyTransStatus.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/CopyTransStatus.java @@ -20,6 +20,9 @@ */ package org.zanata.rest.dto; +import com.webcohesion.enunciate.metadata.DocumentationExample; +import com.webcohesion.enunciate.metadata.Label; + import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; @@ -32,12 +35,17 @@ */ @XmlRootElement(name = "copyTransStatus") @XmlType(name = "copyTransStatusType") +@Label("Copy Trans Status") public class CopyTransStatus { private int percentageComplete; private boolean inProgress; + /** + * An estimated percentage of completion for the copy trans run. + */ @XmlElement(required = true) + @DocumentationExample("80") public int getPercentageComplete() { return percentageComplete; } @@ -46,6 +54,9 @@ public void setPercentageComplete(int percentageComplete) { this.percentageComplete = percentageComplete; } + /** + * True if the process is still running. False otherwise + */ @XmlElement(required = true) public boolean isInProgress() { return inProgress; diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/GlossaryEntry.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/GlossaryEntry.java index 9801098371..230cdcc2d3 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/GlossaryEntry.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/GlossaryEntry.java @@ -30,6 +30,8 @@ import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import com.webcohesion.enunciate.metadata.DocumentationExample; +import com.webcohesion.enunciate.metadata.Label; import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; import org.codehaus.jackson.annotate.JsonPropertyOrder; @@ -39,7 +41,8 @@ import org.zanata.rest.MediaTypes; /** - * + * A single glossary entry representing a single translated term in multiple + * locales. * @author Alex Eng aeng@redhat.com * **/ @@ -48,6 +51,7 @@ "description", "sourceReference", "glossaryTerms", "termsCount", "qualifiedName" }) @JsonPropertyOrder({ "id", "pos", "description", "srcLang", "sourceReference", "glossaryTerms", "termsCount", "qualifiedName" }) @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@Label("Glossary Entry") public class GlossaryEntry implements Serializable, HasMediaType { /** * @@ -78,8 +82,12 @@ public GlossaryEntry(Long id) { this.id = id; } + /** + * Unique identifier + */ @XmlElement(name = "id", namespace = Namespaces.ZANATA_OLD) @JsonProperty("id") + @DocumentationExample(value = "444555", value2 = "444556") public Long getId() { return id; } @@ -88,8 +96,12 @@ public void setId(Long id) { this.id = id; } + /** + * Glossary entry's part of speech + */ @XmlElement(name = "pos", namespace = Namespaces.ZANATA_OLD) @JsonProperty("pos") + @DocumentationExample(value = "verb", value2 = "noun") public String getPos() { return pos; } @@ -108,8 +120,13 @@ public void setDescription(String description) { this.description = description; } + /** + * Number of translated terms. A term is the glossary entry's representation + * for a specific locale + */ @XmlElement(name = "termsCount", namespace = Namespaces.ZANATA_API) @JsonProperty("termsCount") + @DocumentationExample("2") public int getTermsCount() { return termsCount; } @@ -118,6 +135,9 @@ public void setTermsCount(int termsCount) { this.termsCount = termsCount; } + /** + * The full list of glossary terms + */ @XmlElement(name = "glossary-term", namespace = Namespaces.ZANATA_OLD) @JsonProperty("glossaryTerms") public List getGlossaryTerms() { @@ -131,9 +151,13 @@ public void setGlossaryTerms(List glossaryTerms) { this.glossaryTerms = glossaryTerms; } + /** + * The source locale for this specific entry + */ @XmlAttribute(name = "src-lang") @XmlJavaTypeAdapter(type = LocaleId.class, value = LocaleIdAdapter.class) @JsonProperty("srcLang") + @DocumentationExample("en-US") public LocaleId getSrcLang() { return srcLang; } diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/GlossaryInfo.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/GlossaryInfo.java index a100494b4b..30721f72b3 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/GlossaryInfo.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/GlossaryInfo.java @@ -7,12 +7,14 @@ import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; +import com.webcohesion.enunciate.metadata.Label; import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonPropertyOrder; import org.codehaus.jackson.map.annotate.JsonSerialize; import org.zanata.common.Namespaces; /** + * Information about a specific Glossary. * @author Alex Eng aeng@redhat.com */ @XmlRootElement(name = "glossaryInfo") @@ -20,6 +22,7 @@ @JsonIgnoreProperties(ignoreUnknown = true) @JsonPropertyOrder({ "srcLocale", "transLocale"}) @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@Label("Glossary Info") public class GlossaryInfo implements Serializable { private static final long serialVersionUID = -5688873815049369490L; private GlossaryLocaleInfo srcLocale; @@ -35,6 +38,9 @@ public GlossaryInfo(GlossaryLocaleInfo srcLocale, this.transLocale = transLocale; } + /** + * The glossary's source locale + */ @XmlElement(name = "srcLocale", required = false, namespace = Namespaces.ZANATA_API) public GlossaryLocaleInfo getSrcLocale() { @@ -45,6 +51,9 @@ public void setSrcLocale(GlossaryLocaleInfo srcLocale) { this.srcLocale = srcLocale; } + /** + * The list of translated locale's available for the glossary + */ @XmlElement(name = "transLocale", required = false, namespace = Namespaces.ZANATA_API) public List getTransLocale() { diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/GlossaryLocaleInfo.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/GlossaryLocaleInfo.java index 9955495933..458a932b19 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/GlossaryLocaleInfo.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/GlossaryLocaleInfo.java @@ -5,6 +5,8 @@ import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; +import com.webcohesion.enunciate.metadata.DocumentationExample; +import com.webcohesion.enunciate.metadata.Label; import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonPropertyOrder; import org.codehaus.jackson.map.annotate.JsonSerialize; @@ -18,6 +20,7 @@ @JsonIgnoreProperties(ignoreUnknown = true) @JsonPropertyOrder({ "locale", "numberOfTerms"}) @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@Label("Glossary Locale Info") public class GlossaryLocaleInfo implements Serializable { private static final long serialVersionUID = 7486128063191358182L; private LocaleDetails locale; @@ -42,8 +45,12 @@ public void setLocale(LocaleDetails locale) { this.locale = locale; } + /** + * Number of terms available for the glossary in this locale + */ @XmlElement(name = "numberOfTerms", required = false, namespace = Namespaces.ZANATA_API) + @DocumentationExample("2") public int getNumberOfTerms() { return numberOfTerms; } diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/GlossaryResults.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/GlossaryResults.java index f67a021a3e..8aa66745cb 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/GlossaryResults.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/GlossaryResults.java @@ -10,6 +10,7 @@ import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; +import com.webcohesion.enunciate.metadata.Label; import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; import org.codehaus.jackson.annotate.JsonPropertyOrder; @@ -17,8 +18,8 @@ import org.zanata.common.Namespaces; /** - * Wrapper for list of HGlossaryEntry/GlossaryEntry and list of warning message after - * saving/update + * Wrapper for list of Glossary entries and a list of warning messages after + * saving/updating * * @author Alex Eng aeng@redhat.com */ @@ -27,6 +28,7 @@ @JsonIgnoreProperties(ignoreUnknown = true) @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) @XmlType(name = "glossaryResults", propOrder = {"glossaryEntries", "warnings"}) +@Label("Glossary Results") public class GlossaryResults implements Serializable { private static final long serialVersionUID = 7100495681284134288L; private List glossaryEntries; @@ -40,6 +42,9 @@ public GlossaryResults(List glossaryEntries, List warning this.warnings = warnings; } + /** + * The list of created / updated glossary entries + */ @JsonProperty("glossaryEntries") @XmlElementWrapper(name = "glossaryEntries", namespace = Namespaces.ZANATA_API) @XmlElementRef(namespace = Namespaces.ZANATA_API) @@ -50,6 +55,9 @@ public List getGlossaryEntries() { return glossaryEntries; } + /** + * A list of warnings generated when performing the operation + */ @JsonProperty("warnings") @XmlElementWrapper(name = "warnings", namespace = Namespaces.ZANATA_API) public List getWarnings() { diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/GlossaryTerm.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/GlossaryTerm.java index 82798e70df..079825dcc1 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/GlossaryTerm.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/GlossaryTerm.java @@ -29,6 +29,8 @@ import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import com.webcohesion.enunciate.metadata.DocumentationExample; +import com.webcohesion.enunciate.metadata.Label; import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; import org.codehaus.jackson.annotate.JsonPropertyOrder; @@ -37,15 +39,15 @@ import org.zanata.common.Namespaces; /** - * + * A single glossary term for a single locale * @author Alex Eng aeng@redhat.com * - **/ - + */ @XmlType(name = "glossaryTermType", propOrder = {"comment", "content", "locale", "lastModifiedDate", "lastModifiedBy"}) @JsonPropertyOrder({ "content", "comment", "locale", "lastModifiedDate", "lastModifiedBy" }) @JsonIgnoreProperties(ignoreUnknown = true) @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@Label("Glossary Term") public class GlossaryTerm implements Serializable { /** * @@ -66,9 +68,13 @@ public class GlossaryTerm implements Serializable { public GlossaryTerm() { } + /** + * Term's locale + */ @XmlAttribute(name = "lang", namespace = Namespaces.XML) @XmlJavaTypeAdapter(type = LocaleId.class, value = LocaleIdAdapter.class) @JsonProperty("locale") + @DocumentationExample(value = "es-ES", value2 = "ja") public LocaleId getLocale() { return locale; } @@ -77,9 +83,13 @@ public void setLocale(LocaleId locale) { this.locale = locale; } + /** + * The term's translation in the given locale + */ @XmlElement(name = "content", required = false, namespace = Namespaces.ZANATA_OLD) @JsonProperty("content") + @DocumentationExample(value = "Una casa", value2 = "家") public String getContent() { return content; } @@ -98,9 +108,13 @@ public void setComment(String comment) { this.comment = comment; } + /** + * A string which identifies the user who last modififed this entry + */ @XmlElement(name = "lastModifiedBy", required = false, namespace = Namespaces.ZANATA_API) @JsonProperty("lastModifiedBy") + @DocumentationExample("homer") public String getLastModifiedBy() { return lastModifiedBy; } @@ -109,6 +123,9 @@ public void setLastModifiedBy(String lastModifiedBy) { this.lastModifiedBy = lastModifiedBy; } + /** + * A timestamp indicating the last modification date for this entry + */ @XmlElement(name = "lastModifiedDate", required = false, namespace = Namespaces.ZANATA_API) @JsonProperty("lastModifiedDate") diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/Link.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/Link.java index 920e0f28ff..778ca9814d 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/Link.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/Link.java @@ -1,11 +1,18 @@ package org.zanata.rest.dto; +import com.webcohesion.enunciate.metadata.DocumentationExample; +import com.webcohesion.enunciate.metadata.Label; + import java.net.URI; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlType; +/** + * A single link to reference a URI + */ @XmlType(name = "linkType") +@Label("Link") public class Link { private URI href; @@ -30,7 +37,11 @@ public Link(URI href, String rel, String type) { this.type = type; } + /** + * The URI reference by this link + */ @XmlAttribute(name = "href", required = true) + @DocumentationExample(value = "http://alink.com") public URI getHref() { return href; } @@ -39,6 +50,9 @@ public void setHref(URI href) { this.href = href; } + /** + * The relationship this link holds to its parent object + */ @XmlAttribute(name = "rel", required = false) public String getRel() { return rel; @@ -48,6 +62,9 @@ public void setRel(String rel) { this.rel = rel; } + /** + * The type of link + */ @XmlAttribute(name = "type", required = true) public String getType() { return type; diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/Links.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/Links.java index e45b310a64..8f50ea375e 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/Links.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/Links.java @@ -1,11 +1,17 @@ package org.zanata.rest.dto; +import com.webcohesion.enunciate.metadata.Label; + import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlType; +/** + * A collection of links + */ @XmlType(name = "linksType", propOrder = {}) +@Label("Links") public class Links extends ArrayList { private static final long serialVersionUID = 1L; diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/LocaleDetails.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/LocaleDetails.java index a29b9770bb..28859b8de1 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/LocaleDetails.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/LocaleDetails.java @@ -29,6 +29,8 @@ import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import com.webcohesion.enunciate.metadata.DocumentationExample; +import com.webcohesion.enunciate.metadata.Label; import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonPropertyOrder; import org.codehaus.jackson.map.annotate.JsonSerialize; @@ -40,6 +42,7 @@ @JsonIgnoreProperties(ignoreUnknown = true) @JsonPropertyOrder({"localeId", "displayName", "alias", "nativeName", "enabled", "enabledByDefault", "pluralForms"}) @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@Label("Locale Details") public class LocaleDetails implements Serializable { private static final long serialVersionUID = -8133147543880728788L; @@ -68,9 +71,13 @@ public LocaleDetails(LocaleId localeId, String displayName, String alias, this.pluralForms = pluralForms; } + /** + * Unique locale identifier + */ @XmlAttribute(name = "localeId", required = true) @XmlJavaTypeAdapter(type = LocaleId.class, value = LocaleIdAdapter.class) @NotNull + @DocumentationExample(value = "es-ES", value2 = "ja") public LocaleId getLocaleId() { return localeId; } @@ -79,7 +86,11 @@ public void setLocaleId(LocaleId localeId) { this.localeId = localeId; } + /** + * Locale's display name (in English) + */ @XmlAttribute(name = "displayName", required = true) + @DocumentationExample(value = "Spanish (Spain)", value2 = "Japanese") public String getDisplayName() { return displayName; } @@ -88,7 +99,11 @@ public void setDisplayName(String displayName) { this.displayName = displayName; } + /** + * An alternative name (if present) for this locale + */ @XmlAttribute(name = "alias", required = false) + @DocumentationExample(value = "es", value2 = "ja-JP") public String getAlias() { return alias; } @@ -98,6 +113,7 @@ public void setAlias(String alias) { } @XmlAttribute(name = "nativeName", required = false) + @DocumentationExample(value = "Español", value2 = "日本語") public String getNativeName() { return nativeName; } @@ -106,6 +122,9 @@ public void setNativeName(String nativeName) { this.nativeName = nativeName; } + /** + * Indicates whether the locale is enabled in the system or not. + */ @XmlAttribute(name = "enabled", required = true) @NotNull public boolean isEnabled() { @@ -116,6 +135,11 @@ public void setEnabled(boolean enabled) { this.enabled = enabled; } + /** + * Indicates whether the locale will be used automatically by the system. + * e.g. when creating a new project, 'enabled by default' locales will + * automatically be added to the project unless specifically indicating so. + */ @XmlAttribute(name = "enabledByDefault", required = true) @NotNull public boolean isEnabledByDefault() { @@ -126,7 +150,12 @@ public void setEnabledByDefault(boolean enabledByDefault) { this.enabledByDefault = enabledByDefault; } + /** + * A string describing the formula for the locale's plural forms + */ @XmlAttribute(name = "pluralForms", required = false) + @DocumentationExample(value = "nplurals=2; plural=(n != 1)", + value2 = "nplurals=1; plural=0") public String getPluralForms() { return pluralForms; } diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/Project.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/Project.java index 4d13b427f3..9ffc48f874 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/Project.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/Project.java @@ -13,6 +13,8 @@ import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; +import com.webcohesion.enunciate.metadata.DocumentationExample; +import com.webcohesion.enunciate.metadata.Label; import org.codehaus.jackson.annotate.JsonIgnore; import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; @@ -40,6 +42,7 @@ "sourceViewURL", "sourceCheckoutURL", "links", "iterations", "status" }) @JsonIgnoreProperties(ignoreUnknown = true) @JsonSerialize(include = Inclusion.NON_NULL) +@Label("Project") public class Project implements Serializable, HasCollectionSample, HasMediaType { @@ -70,7 +73,11 @@ public Project(String id, String name, String type, String description) { this.description = description; } + /** + * The project identifier (slug) + */ @XmlAttribute(name = "id", required = true) + @DocumentationExample("my-project") public String getId() { return id; } @@ -79,8 +86,12 @@ public void setId(String id) { this.id = id; } + /** + * The project type. + */ @XmlElement(name = "defaultType", required = true, nillable = false, namespace = Namespaces.ZANATA_OLD) + @DocumentationExample("Gettext") public String getDefaultType() { return defaultType; } @@ -93,6 +104,7 @@ public void setDefaultType(String defaultType) { @Size(max = 80) @XmlElement(name = "name", required = true, namespace = Namespaces.ZANATA_OLD) + @DocumentationExample("My Project") public String getName() { return name; } @@ -104,6 +116,7 @@ public void setName(String name) { @Size(max = 80) @XmlElement(name = "description", required = false, namespace = Namespaces.ZANATA_OLD) + @DocumentationExample("This is a sample project.") public String getDescription() { return description; } @@ -112,8 +125,12 @@ public void setDescription(String description) { this.description = description; } + /** + * The url to view the project's sources. + */ @XmlElement(name = "sourceViewURL", required = false, nillable = true, namespace = Namespaces.ZANATA_API) + @DocumentationExample("http://source.view.com") public String getSourceViewURL() { return sourceViewURL; } @@ -122,8 +139,12 @@ public void setSourceViewURL(String sourceViewURL) { this.sourceViewURL = sourceViewURL; } + /** + * The url where to checkout the project's sources. + */ @XmlElement(name = "sourceCheckoutURL", required = false, nillable = true, namespace = Namespaces.ZANATA_API) + @DocumentationExample("http://source.checkout.com") public String getSourceCheckoutURL() { return sourceCheckoutURL; } @@ -132,6 +153,13 @@ public void setSourceCheckoutURL(String sourceCheckoutURL) { this.sourceCheckoutURL = sourceCheckoutURL; } + /** + * Set of links managed by this project + * + * This field is ignored in PUT/POST operations + * + * @return set of Links managed by this resource + */ @XmlElement(name = "link", namespace = Namespaces.ZANATA_API) @JsonProperty("links") public Links getLinks() { @@ -149,6 +177,9 @@ public Links getLinks(boolean createIfNull) { return links; } + /** + * A list of versions (iterations) in the project + */ @XmlElementWrapper(name = "project-iterations", namespace = Namespaces.ZANATA_OLD) @XmlElementRef(namespace = Namespaces.ZANATA_OLD) @@ -167,6 +198,9 @@ public List getIterations(boolean createIfNull) { return getIterations(); } + /** + * System state of the project + */ @XmlElement(name = "status", required = false, namespace = Namespaces.ZANATA_OLD) public EntityStatus getStatus() { diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/ProjectIteration.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/ProjectIteration.java index 50461a6ab5..eba53b691e 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/ProjectIteration.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/ProjectIteration.java @@ -29,6 +29,8 @@ import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; +import com.webcohesion.enunciate.metadata.DocumentationExample; +import com.webcohesion.enunciate.metadata.Label; import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; import org.codehaus.jackson.annotate.JsonPropertyOrder; @@ -39,12 +41,16 @@ import org.zanata.rest.MediaTypes; import org.zanata.rest.MediaTypes.Format; +/** + * Represents a Project version (or iteration). + */ @XmlType(name = "projectIterationType", propOrder = { "links", "status", "projectType" }) @XmlRootElement(name = "project-iteration") @JsonIgnoreProperties(ignoreUnknown = true) @JsonSerialize(include = Inclusion.NON_NULL) @JsonPropertyOrder({ "id", "links", "status", "projectType" }) +@Label("Project Version") public class ProjectIteration implements Serializable, HasCollectionSample, HasMediaType { @@ -64,7 +70,11 @@ public ProjectIteration(String id) { this.id = id; } + /** + * Version identifier (slug) + */ @XmlAttribute(name = "id", required = true) + @DocumentationExample("my-iteration") public String getId() { return id; } @@ -107,8 +117,13 @@ public void setStatus(EntityStatus status) { this.status = status; } + /** + * The type of project version. This type could be overriding the project's + * original type. + */ @XmlElement(name = "projectType", required = false, namespace = Namespaces.ZANATA_OLD) + @DocumentationExample("Podir") public String getProjectType() { return projectType; } diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/QualifiedName.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/QualifiedName.java index cbf04aa5af..7101eb832c 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/QualifiedName.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/QualifiedName.java @@ -4,6 +4,8 @@ import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; +import com.webcohesion.enunciate.metadata.DocumentationExample; +import com.webcohesion.enunciate.metadata.Label; import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; import org.codehaus.jackson.map.annotate.JsonSerialize; @@ -11,7 +13,7 @@ import org.zanata.rest.MediaTypes; /** - * Object Glossary qualified name. Usage: + * Describes a qualified system name. Usage: * {@link GlossaryEntry#getQualifiedName()} * {@link org.zanata.rest.service.GlossaryResource} * @@ -20,6 +22,7 @@ @XmlRootElement(name = "qualifiedName") @JsonIgnoreProperties(ignoreUnknown = true) @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@Label("Qualified Name") public class QualifiedName implements Serializable, HasMediaType { private static final long serialVersionUID = 934216980812012602L; private String name; @@ -34,6 +37,7 @@ public QualifiedName(String name) { @XmlElement(name = "name", required = false, namespace = Namespaces.ZANATA_API) @JsonProperty("name") + @DocumentationExample("global/default") public String getName() { return name; } diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/ResultList.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/ResultList.java index 7a705ecc37..b39842c846 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/ResultList.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/ResultList.java @@ -4,16 +4,19 @@ import java.util.ArrayList; import java.util.List; +import com.webcohesion.enunciate.metadata.Label; import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonPropertyOrder; import org.codehaus.jackson.map.annotate.JsonSerialize; /** + * A list of results * @author Alex Eng aeng@redhat.com */ @JsonPropertyOrder({ "results", "totalCount" }) @JsonIgnoreProperties(ignoreUnknown = true) @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@Label("Result List") public class ResultList implements Serializable { private static final long serialVersionUID = -2149554068631922866L; diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/VersionInfo.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/VersionInfo.java index 2f099ecd83..b5182d9812 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/VersionInfo.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/VersionInfo.java @@ -6,19 +6,22 @@ import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; +import com.webcohesion.enunciate.metadata.DocumentationExample; +import com.webcohesion.enunciate.metadata.Label; import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonTypeName; import org.codehaus.jackson.map.annotate.JsonSerialize; import org.zanata.common.Namespaces; /** - * Holds version info + * Holds system version information */ @XmlRootElement(name = "versionInfo") @XmlType(name = "versionType", propOrder = { "versionNo", "buildTimeStamp", "scmDescribe" }) @JsonTypeName(value = "versionType") @JsonIgnoreProperties(ignoreUnknown = true) @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@Label("Version Info") public final class VersionInfo implements Serializable { private static final long serialVersionUID = 1L; private String versionNo; @@ -43,16 +46,27 @@ public VersionInfo(VersionInfo other) { this(other.versionNo, other.buildTimeStamp, other.scmDescribe); } + /** + * Version number + */ @XmlElement(name = "versionNo", namespace = Namespaces.ZANATA_OLD) + @DocumentationExample("4.0.0") public String getVersionNo() { return versionNo; } + /** + * ISO8601 timestamp for when the current system version was built + */ @XmlElement(name = "buildTimeStamp", namespace = Namespaces.ZANATA_OLD) + @DocumentationExample("20170225-1448") public String getBuildTimeStamp() { return buildTimeStamp; } + /** + * Identifier for the current version in source control + */ @XmlElement(name = "scmDescribe", namespace = Namespaces.ZANATA_API) public String getScmDescribe() { return scmDescribe; diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/resource/Resource.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/resource/Resource.java index 4a7b63192b..047ed55dc6 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/resource/Resource.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/resource/Resource.java @@ -1,21 +1,19 @@ package org.zanata.rest.dto.resource; -import java.util.ArrayList; -import java.util.List; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlElementWrapper; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; - -import com.webcohesion.enunciate.metadata.DocumentationExample; -import com.webcohesion.enunciate.metadata.rs.ResourceLabel; +import com.webcohesion.enunciate.metadata.Label; import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; import org.codehaus.jackson.annotate.JsonPropertyOrder; import org.codehaus.jackson.map.annotate.JsonSerialize; import org.zanata.common.Namespaces; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import java.util.ArrayList; +import java.util.List; + /** * A series of text flows to be translated and sharing common metadata. */ @@ -24,7 +22,7 @@ @JsonPropertyOrder({ "name", "contentType", "lang", "extensions", "textFlows" }) @JsonIgnoreProperties(ignoreUnknown = true) @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) -@ResourceLabel("Resource") +@Label("Resource") public class Resource extends AbstractResourceMeta { private static final long serialVersionUID = 1L; diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/resource/TranslationsResource.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/resource/TranslationsResource.java index c90fdce691..8a4a98f8e8 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/resource/TranslationsResource.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/resource/TranslationsResource.java @@ -10,6 +10,7 @@ import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; +import com.webcohesion.enunciate.metadata.Label; import org.codehaus.jackson.annotate.JsonIgnore; import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; @@ -31,6 +32,7 @@ @JsonPropertyOrder({ "links", "extensions", "textFlowTargets" }) @JsonIgnoreProperties(ignoreUnknown = true) @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@Label("Translations") public class TranslationsResource implements Serializable, HasSample, Extensible { @@ -40,6 +42,9 @@ public class TranslationsResource implements Serializable, private List textFlowTargets; private Integer revision; + /** + * Any provided extensions + */ @XmlElementWrapper(name = "extensions", required = false, namespace = Namespaces.ZANATA_OLD) @XmlElement(name = "extension", namespace = Namespaces.ZANATA_OLD) @@ -60,6 +65,9 @@ public ExtensionSet getExtensions( return extensions; } + /** + * The text flow targets (i.e. translated text) + */ @XmlElementWrapper(name = "targets", required = false, namespace = Namespaces.ZANATA_OLD) @XmlElement(name = "text-flow-target", namespace = Namespaces.ZANATA_API) @@ -71,6 +79,9 @@ public List getTextFlowTargets() { return textFlowTargets; } + /** + * A collection of links provided with the translations. + */ @XmlElement(name = "links", namespace = Namespaces.ZANATA_OLD) public Links getLinks() { return links; @@ -87,6 +98,9 @@ public Links getLinks(boolean createIfNull) { return links; } + /** + * Revision number for the translations + */ @XmlAttribute() public Integer getRevision() { return revision; diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/stats/ContainerTranslationStatistics.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/stats/ContainerTranslationStatistics.java index 1b38fbbc90..97cb9c0562 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/stats/ContainerTranslationStatistics.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/stats/ContainerTranslationStatistics.java @@ -29,6 +29,8 @@ import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; +import com.webcohesion.enunciate.metadata.DocumentationExample; +import com.webcohesion.enunciate.metadata.Label; import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonPropertyOrder; import org.zanata.rest.dto.Link; @@ -45,6 +47,7 @@ @XmlRootElement(name = "containerStats") @JsonIgnoreProperties(ignoreUnknown = true) @JsonPropertyOrder({ "id", "refs", "stats", "detailedStats" }) +@Label("Container Translation Statistics") public class ContainerTranslationStatistics implements Serializable { private static final long serialVersionUID = 1L; private String id; @@ -60,6 +63,7 @@ public ContainerTranslationStatistics() { * etc). */ @XmlAttribute + @DocumentationExample("my-project") public String getId() { return id; } diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/stats/TranslationStatistics.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/stats/TranslationStatistics.java index f029125bf5..8f47fb3b82 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/stats/TranslationStatistics.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/stats/TranslationStatistics.java @@ -29,6 +29,8 @@ import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.XmlType; +import com.webcohesion.enunciate.metadata.DocumentationExample; +import com.webcohesion.enunciate.metadata.Label; import org.codehaus.jackson.annotate.JsonIgnore; import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonPropertyOrder; @@ -53,6 +55,7 @@ @JsonPropertyOrder({ "total", "untranslated", "needReview", "translated", "approved", "rejected", "readyForReview", "fuzzy", "unit", "locale", "lastTranslated" }) +@Label("Translation Statistics") public class TranslationStatistics implements Serializable { private static final long serialVersionUID = 1L; private StatUnit unit; @@ -111,6 +114,7 @@ public TranslationStatistics(TransUnitWords wordCount, String locale) { * Number of untranslated elements. */ @XmlAttribute + @DocumentationExample("25") public long getUntranslated() { return translationCount.getUntranslated(); } @@ -147,6 +151,7 @@ public long getNeedReview() { * @return */ @XmlAttribute + @DocumentationExample("50") public long getFuzzy() { return translationCount.getNeedReview(); } @@ -179,6 +184,7 @@ public long getTranslatedAndApproved() { * @return number of translated but not yet approved elements. */ @XmlAttribute + @DocumentationExample("30") public long getTranslatedOnly() { return translationCount.getTranslated(); } @@ -191,6 +197,7 @@ public void setTranslatedOnly(long translatedOnly) { * @return Number of approved elements. */ @XmlAttribute + @DocumentationExample("80") public long getApproved() { return translationCount.getApproved(); } @@ -200,6 +207,7 @@ public void setApproved(long approved) { } @XmlAttribute + @DocumentationExample("10") public long getRejected() { return translationCount.getRejected(); } @@ -242,6 +250,7 @@ public void setUnit(StatUnit unit) { * Locale for the translation statistics. */ @XmlAttribute + @DocumentationExample("es-ES") public String getLocale() { return locale; } @@ -250,7 +259,11 @@ public void setLocale(String locale) { this.locale = locale; } + /** + * Last translation information. Includes date and user. + */ @XmlAttribute + @DocumentationExample("31/12/15 23:59 by homer") public String getLastTranslated() { return lastTranslated; } @@ -341,6 +354,7 @@ public String toString() { return sb.toString(); } + @Label("Stats Unit") public enum StatUnit { /** Statistics are measured in words. */ WORD, diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/stats/contribution/BaseContributionStatistic.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/stats/contribution/BaseContributionStatistic.java index 8ea3827ac2..615b07da74 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/stats/contribution/BaseContributionStatistic.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/stats/contribution/BaseContributionStatistic.java @@ -1,5 +1,6 @@ package org.zanata.rest.dto.stats.contribution; +import com.webcohesion.enunciate.metadata.Label; import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; import org.codehaus.jackson.annotate.JsonPropertyOrder; @@ -15,6 +16,7 @@ @JsonIgnoreProperties(ignoreUnknown = true) @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) @JsonPropertyOrder({ "approved", "rejected", "translated", "needReview" }) +@Label("Base Contribution Statistics") public class BaseContributionStatistic implements Serializable { private static final long serialVersionUID = 6615374806881888982L; diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/stats/contribution/ContributionStatistics.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/stats/contribution/ContributionStatistics.java index dd34f696bb..dec1e83020 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/stats/contribution/ContributionStatistics.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/stats/contribution/ContributionStatistics.java @@ -4,15 +4,20 @@ import java.util.ArrayList; import java.util.List; +import com.webcohesion.enunciate.metadata.DocumentationExample; +import com.webcohesion.enunciate.metadata.Label; import org.codehaus.jackson.annotate.JsonProperty; import org.codehaus.jackson.annotate.JsonPropertyOrder; import org.codehaus.jackson.map.annotate.JsonSerialize; /** + * Contains information about translations contributed by a single user. + * * @author Alex Eng aeng@redhat.com */ @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) @JsonPropertyOrder({ "username", "contributions" }) +@Label("Contribution Statistics") public class ContributionStatistics implements Serializable { private static final long serialVersionUID = -6328249224235406066L; @@ -29,7 +34,11 @@ public ContributionStatistics(String username, this.contributions = contributions; } + /** + * User name responsible for the contributions. + */ @JsonProperty("username") + @DocumentationExample("bart") public String getUsername() { return username; } diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/stats/contribution/LocaleStatistics.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/stats/contribution/LocaleStatistics.java index 60a38b7a8e..da99d8ec06 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/stats/contribution/LocaleStatistics.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/stats/contribution/LocaleStatistics.java @@ -2,16 +2,21 @@ import java.io.Serializable; +import com.webcohesion.enunciate.metadata.DocumentationExample; +import com.webcohesion.enunciate.metadata.Label; import org.codehaus.jackson.annotate.JsonProperty; import org.codehaus.jackson.annotate.JsonPropertyOrder; import org.codehaus.jackson.map.annotate.JsonSerialize; import org.zanata.common.LocaleId; /** + * Contains translation statistics for a single locale. + * * @author Alex Eng aeng@redhat.com */ @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) @JsonPropertyOrder({ "locale", "translation-stats", "review-stats" }) +@Label("Locale Statistics") public class LocaleStatistics implements Serializable { private static final long serialVersionUID = 711345550950903773L; @@ -36,16 +41,26 @@ public LocaleStatistics(LocaleId locale, private BaseContributionStatistic reviewStats; + /** + * Locale code for for the stats + */ @JsonProperty("locale") + @DocumentationExample(value = "es-ES", value2 = "ja") public LocaleId getLocale() { return locale; } + /** + * Contains translation statistics only. + */ @JsonProperty("translation-stats") public BaseContributionStatistic getTranslationStats() { return translationStats; } + /** + * Contains review statistics only. + */ @JsonProperty("review-stats") public BaseContributionStatistic getReviewStats() { return reviewStats; diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/service/CopyTransResource.java b/api/zanata-common-api/src/main/java/org/zanata/rest/service/CopyTransResource.java index 4138bcbbbf..70be790686 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/service/CopyTransResource.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/service/CopyTransResource.java @@ -29,6 +29,8 @@ import javax.ws.rs.core.MediaType; import com.webcohesion.enunciate.metadata.rs.ResourceLabel; +import com.webcohesion.enunciate.metadata.rs.ResponseCode; +import com.webcohesion.enunciate.metadata.rs.StatusCodes; import org.zanata.rest.dto.CopyTransStatus; import com.webcohesion.enunciate.metadata.rs.TypeHint; @@ -55,26 +57,23 @@ public interface CopyTransResource extends RestResource { * Project version identifier * @param docId * Document Id to copy translations into. - * @return The following response status codes will be returned from this - * operation:
    - * OK(200) - Translation copy was started for the given document. - * The status of the process is also returned in the response - * contents.
    - * UNAUTHORIZED(401) - If the user does not have the proper - * permissions to perform this operation.
    - * INTERNAL SERVER ERROR(500) - If there is an unexpected error in - * the server while performing this operation. Translation copy will - * not start in this case. */ @POST @Path("/proj/{projectSlug}/iter/{iterationSlug}/doc/{docId:.+}") // /copytrans/proj/{projectSlug}/iter/{iterationSlug}/doc/{docId} - @TypeHint(CopyTransStatus.class) - public - CopyTransStatus startCopyTrans( - @PathParam("projectSlug") String projectSlug, - @PathParam("iterationSlug") String iterationSlug, - @PathParam("docId") String docId); + @TypeHint(CopyTransStatus.class) + @StatusCodes({ + @ResponseCode(code = 200, + condition = "Translation copy was started for the given document. " + + "The status of the process is also returned in the response's body."), + @ResponseCode(code = 500, + condition = "If there is an unexpected error in the server while performing this operation") + }) + public + CopyTransStatus startCopyTrans( + @PathParam("projectSlug") String projectSlug, + @PathParam("iterationSlug") String iterationSlug, + @PathParam("docId") String docId); /** * Retrieves the status for a Translation copy process for a document. @@ -85,22 +84,21 @@ CopyTransStatus startCopyTrans( * Project version identifier * @param docId * Document Id - * @return The following response status codes will be returned from this - * operation:
    - * OK(200) - A Translation copy process was found, and its status - * will be returned in the body of the response.
    - * NOT_FOUND(404) - If there is no record of a recent translation - * copy process for the specified document. INTERNAL SERVER - * ERROR(500) - If there is an unexpected error in the server while - * performing this operation. */ @GET @Path("/proj/{projectSlug}/iter/{iterationSlug}/doc/{docId:.+}") // /copytrans/proj/{projectSlug}/iter/{iterationSlug}/doc/{docId} - @TypeHint(CopyTransStatus.class) - public - CopyTransStatus getCopyTransStatus( - @PathParam("projectSlug") String projectSlug, - @PathParam("iterationSlug") String iterationSlug, - @PathParam("docId") String docId); + @TypeHint(CopyTransStatus.class) + @StatusCodes({ + @ResponseCode(code = 200, + condition = "A translation copy process was found, and its " + + "status will be returned in the body of the response"), + @ResponseCode(code = 500, + condition = "If there is an unexpected error in the server while performing this operation") + }) + public + CopyTransStatus getCopyTransStatus( + @PathParam("projectSlug") String projectSlug, + @PathParam("iterationSlug") String iterationSlug, + @PathParam("docId") String docId); } diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/service/GlossaryResource.java b/api/zanata-common-api/src/main/java/org/zanata/rest/service/GlossaryResource.java index 0700c025e1..8f1f0e38cc 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/service/GlossaryResource.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/service/GlossaryResource.java @@ -37,6 +37,8 @@ import javax.ws.rs.core.Response; import com.webcohesion.enunciate.metadata.rs.ResourceLabel; +import com.webcohesion.enunciate.metadata.rs.ResponseCode; +import com.webcohesion.enunciate.metadata.rs.StatusCodes; import org.jboss.resteasy.annotations.providers.multipart.MultipartForm; import org.zanata.common.LocaleId; import org.zanata.rest.GlossaryFileUploadForm; @@ -50,7 +52,7 @@ import com.webcohesion.enunciate.metadata.rs.TypeHint; /** - * Glossary management via REST + * Glossary management * @author Alex Eng aeng@redhat.com * **/ @@ -63,6 +65,10 @@ MediaTypes.APPLICATION_ZANATA_GLOSSARY_XML, MediaTypes.APPLICATION_ZANATA_GLOSSARY_JSON }) @ResourceLabel("Glossary") +@StatusCodes({ + @ResponseCode(code = 500, + condition = "If there is an unexpected error in the server while performing this operation") +}) public interface GlossaryResource extends RestResource { public static final String SERVICE_PATH = "/glossary"; @@ -78,13 +84,6 @@ public interface GlossaryResource extends RestResource { /** * Return default global glossary qualifiedName - * - * @return The following response status codes will be returned from this - * operation:
    - * OK(200) - List of Global glossary qualified names used in the system. - * e.g {@link #GLOBAL_QUALIFIED_NAME} - * INTERNAL SERVER ERROR(500) - If there is an unexpected error in - * the server while performing this operation. */ @GET @Path("/qualifiedName") @@ -92,6 +91,10 @@ public interface GlossaryResource extends RestResource { MediaTypes.APPLICATION_ZANATA_GLOSSARY_JSON, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @TypeHint(QualifiedName.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Returns the qualified name " + + "for the system-wide glossary"), + }) public Response getQualifiedName(); /** @@ -99,12 +102,6 @@ public interface GlossaryResource extends RestResource { * * @param qualifiedName * Qualified name of glossary, default to {@link #GLOBAL_QUALIFIED_NAME} - * - * @return The following response status codes will be returned from this - * operation:
    - * OK(200) - Global glossary info in the system. - * INTERNAL SERVER ERROR(500) - If there is an unexpected error in - * the server while performing this operation. */ @GET @Path("/info") @@ -112,12 +109,19 @@ public interface GlossaryResource extends RestResource { MediaTypes.APPLICATION_ZANATA_GLOSSARY_JSON, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @TypeHint(GlossaryInfo.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Returns the global glossary " + + "information"), + }) public Response getInfo( @DefaultValue(GLOBAL_QUALIFIED_NAME) @QueryParam("qualifiedName") String qualifiedName); /** - * Returns Glossary entries for the given source and translation locale with - * paging + * Returns a subset of Glossary entries for the given source and translation + * locale as indicated by the paging parameters. + * + * @see {@link org.zanata.rest.dto.GlossaryEntry} for details on the result + * list's contents. * * @param srcLocale * Source locale - Required (default value: en-US). @@ -135,19 +139,18 @@ public Response getInfo( * See {@link org.zanata.common.GlossarySortField} * @param qualifiedName * Qualified name of glossary, default to {@link #GLOBAL_QUALIFIED_NAME} - * @return The following response status codes will be returned from this - * operation:
    - * OK(200) - Response containing all Glossary entries for the given - * locale. - * Bad request(400) - If page or sizePerPage is negative value, or sizePerPage is more than 1000. - * INTERNAL SERVER ERROR(500) - If there is an unexpected - * error in the server while performing this operation. */ @GET @Path("/entries") @Produces({ MediaTypes.APPLICATION_ZANATA_GLOSSARY_JSON, MediaType.APPLICATION_JSON }) @TypeHint(ResultList.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Response containing Glossary " + + "entries for the given locale."), + @ResponseCode(code = 400, condition = "If page or sizePerPage are " + + "negative, or sizePerPage is greater than 1000"), + }) public Response getEntries( @DefaultValue("en-US") @QueryParam("srcLocale") LocaleId srcLocale, @QueryParam("transLocale") LocaleId transLocale, @@ -160,6 +163,9 @@ public Response getEntries( /** * Returns Glossary entries based on a fuzzy text search. * + * @see {@link org.zanata.rest.dto.GlossaryEntry} for details on the result + * list's contents. + * * @param srcLocale * Source locale * @param transLocale @@ -172,23 +178,20 @@ public Response getEntries( * @param projectSlug * (optional) Project slug if a project glossary should be searched * in addition to the global glossary. - * @return The following response status codes will be returned from this - * operation:
    - * OK(200) - Response containing all Glossary entries for the given - * locale. - * Bad request(400) - * - When maxResults is not strictly positive or is more than 1000. - * - When searchText is missing - * - When transLocale is missing - * - When there is an error parsing the searchText - * INTERNAL SERVER ERROR(500) - If there is an unexpected - * error in the server while performing this operation. */ @GET @Path("/search") @Produces({ MediaTypes.APPLICATION_ZANATA_GLOSSARY_JSON, MediaType.APPLICATION_JSON }) @TypeHint(ResultList.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Response containing Glossary " + + "entries for the given search parameters."), + @ResponseCode(code = 400, condition = "When maxResults is not strictly positive or is more than 1000"), + @ResponseCode(code = 400, condition = "When searchText is missing"), + @ResponseCode(code = 400, condition = "When transLocale is missing"), + @ResponseCode(code = 400, condition = "When there is an error parsing the searchText"), + }) Response search( @DefaultValue("en-US") @QueryParam("srcLocale") LocaleId srcLocale, @CheckForNull @QueryParam("transLocale") LocaleId transLocale, @@ -204,7 +207,7 @@ Response search( * @param locale include locale-specific detail for this locale * @param termIds id for glossary terms in the default locale, found in * results of {@link #search(LocaleId, LocaleId, int, String, String)} - * @return source and target glossary details. + * @return Source and target glossary details. */ @GET @Path("/details/{locale}") @@ -213,111 +216,122 @@ Response search( // TODO when GWT is removed, move the GlossaryDetails class to this module // and add the type hint. // @TypeHint(GlossaryDetails[].class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Details successfully found") + }) Response getDetails( @CheckForNull @PathParam("locale") LocaleId locale, @CheckForNull @QueryParam("termIds") List termIds); /** - * Download all glossary entries as file + * Download all glossary entries as a file * - * @param fileType - po or cvs (case insensitive). Default - csv - * @param locales - optional comma separated list of languages required. + * @param fileType 'po' or 'csv' (case insensitive) are currently supported + * @param locales optional comma separated list of languages required. * @param qualifiedName * Qualified name of glossary, default to {@link #GLOBAL_QUALIFIED_NAME} + * @return A file stream with the glossary contents in the specified format */ @GET @Path("/file") @Produces(MediaType.APPLICATION_OCTET_STREAM) + @StatusCodes({ + @ResponseCode(code = 200, condition = "File is successfully built " + + "and served") + }) public Response downloadFile( @DefaultValue("csv") @QueryParam("fileType") String fileType, @QueryParam("locales") String locales, @DefaultValue(GLOBAL_QUALIFIED_NAME) @QueryParam("qualifiedName") String qualifiedName); /** - * Create or update glossary entry. - * GlossaryTerm with locale different from {@param locale} will be ignored. + * Create or update glossary entries. + * Glossary Terms with a locale different from the given locale parameter + * will be ignored. * * @param glossaryEntries The glossary entries to create/update * @param qualifiedName - * Qualified name of glossary, default to {@link #GLOBAL_QUALIFIED_NAME} + * Qualified name of glossary, defaults to {@link #GLOBAL_QUALIFIED_NAME} * @param locale - * The translation locale to create/update - * - * @return The following response status codes will be returned from this - * operation:
    - * OK(200) - If the glossary entry were successfully created/updated. - * UNAUTHORIZED(401) - If the user does not have the proper - * permissions to perform this operation.
    - * INTERNAL SERVER ERROR(500) - If there is an unexpected error in - * the server while performing this operation. + * Locale to which the given glossary entries belong */ @POST @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @Path("/entries") @TypeHint(GlossaryResults.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "The glossary entries were " + + "successfully created or updated"), + @ResponseCode(code = 401, condition = "The user does not have the proper" + + " permissions to perform this operation") + }) public Response post(List glossaryEntries, @QueryParam("locale") String locale, @DefaultValue(GLOBAL_QUALIFIED_NAME) @QueryParam("qualifiedName") String qualifiedName); /** - * Upload glossary file (po, cvs) - * - * @param form {@link org.zanata.rest.GlossaryFileUploadForm} + * Upload glossary file (currently supported formats: po, csv) * - * @return The following response status codes will be returned from this - * operation:
    - * CREATED(201) - If files successfully uploaded. - * UNAUTHORIZED(401) - If the user does not have the proper - * permissions to perform this operation.
    - * INTERNAL SERVER ERROR(500) - If there is an unexpected error in - * the server while performing this operation. * + * @param form Multi-part form with the following named parts:
    + * file: The file contents
    + * srcLocale: Source locale for the glossary entries
    + * transLocale: Translation locale for the glossary entries
    + * fileName: The name of the file being uploaded
    + * qualifiedName: The qualified name for the glossary
    */ @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.APPLICATION_JSON) @POST @TypeHint(GlossaryResults.class) + @StatusCodes({ + @ResponseCode(code = 201, condition = "Files successfully uploaded"), + @ResponseCode(code = 401, condition = "The user does not have the proper" + + " permissions to perform this operation") + }) public Response upload(@MultipartForm GlossaryFileUploadForm form); /** * - * Delete glossary which given id. + * Delete a glossary entry. * * @param id id for source glossary term * @param qualifiedName - * Qualified name of glossary, default to {@link #GLOBAL_QUALIFIED_NAME} - * @return The following response status codes will be returned from this - * operation:
    - * OK(200) - If the glossary entry were successfully deleted. - * UNAUTHORIZED(401) - If the user does not have the proper - * permissions to perform this operation.
    - * INTERNAL SERVER ERROR(500) - If there is an unexpected error in - * the server while performing this operation. + * Qualified name of glossary, defaults to {@link #GLOBAL_QUALIFIED_NAME} + * @return the removed glossary entry */ @DELETE @Produces(MediaType.APPLICATION_JSON) @Path("/entries/{id}") @TypeHint(GlossaryEntry.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "The glossary entry was successfully deleted"), + @ResponseCode(code = 401, condition = "The user does not have the proper" + + " permissions to perform this operation") + }) public Response deleteEntry(@PathParam("id") Long id, @DefaultValue(GLOBAL_QUALIFIED_NAME) @QueryParam("qualifiedName") String qualifiedName); /** - * Delete all glossary terms. + * Delete all entries in a glossary. * * @param qualifiedName - * Qualified name of glossary, default to {@link #GLOBAL_QUALIFIED_NAME} + * Qualified name of glossary, defaults to {@link #GLOBAL_QUALIFIED_NAME} + * + * @return The number of deleted glossary entries + * + * @responseExample * - * @return The following response status codes will be returned from this - * operation:
    - * OK(200) - If the glossary entries were successfully deleted. - * UNAUTHORIZED(401) - If the user does not have the proper - * permissions to perform this operation.
    - * INTERNAL SERVER ERROR(500) - If there is an unexpected error in - * the server while performing this operation. + * TODO Need to define a 'produces' header */ @DELETE @TypeHint(Integer.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "The glossary was deleted"), + @ResponseCode(code = 401, condition = "The user does not have the proper" + + " permissions to perform this operation") + }) public Response deleteAllEntries( @DefaultValue(GLOBAL_QUALIFIED_NAME) @QueryParam("qualifiedName") String qualifiedName); diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/service/ProjectsResource.java b/api/zanata-common-api/src/main/java/org/zanata/rest/service/ProjectsResource.java index 1f42452fd6..0f3e55a6fe 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/service/ProjectsResource.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/service/ProjectsResource.java @@ -29,6 +29,8 @@ import javax.ws.rs.core.Response; import com.webcohesion.enunciate.metadata.rs.ResourceLabel; +import com.webcohesion.enunciate.metadata.rs.ResponseCode; +import com.webcohesion.enunciate.metadata.rs.StatusCodes; import org.zanata.rest.MediaTypes; import org.zanata.rest.dto.Project; @@ -49,22 +51,20 @@ public interface ProjectsResource extends RestResource { public static final String SERVICE_PATH = "/projects"; /** - * Retrieves a full list of projects in the system. The result is - * - * @return The following response status codes will be returned from this - * operation:
    - * OK(200) - Response containing a full list of projects. The list - * will be wrapped in a "projects" element, and all its child - * elements will be "project"s.
    - * INTERNAL SERVER ERROR(500) - If there is an unexpected error in - * the server while performing this operation. + * Retrieves a full list of projects in the system. */ @GET @Produces({ MediaTypes.APPLICATION_ZANATA_PROJECTS_XML, MediaTypes.APPLICATION_ZANATA_PROJECTS_JSON, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) - @TypeHint(Project[].class) - public - Response get(); + @TypeHint(Project[].class) + @StatusCodes({ + @ResponseCode(code = 200, + condition = "Response containing a full list of projects."), + @ResponseCode(code = 500, + condition = "If there is an unexpected error in the server while performing this operation") + }) + public + Response get(); } diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/service/StatisticsResource.java b/api/zanata-common-api/src/main/java/org/zanata/rest/service/StatisticsResource.java index dd11254e4e..3343bc336e 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/service/StatisticsResource.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/service/StatisticsResource.java @@ -29,8 +29,9 @@ import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; - import com.webcohesion.enunciate.metadata.rs.ResourceLabel; +import com.webcohesion.enunciate.metadata.rs.ResponseCode; +import com.webcohesion.enunciate.metadata.rs.StatusCodes; import org.zanata.rest.dto.ProjectStatisticsMatrix; import org.zanata.rest.dto.stats.ContainerTranslationStatistics; import org.zanata.rest.dto.stats.contribution.ContributionStatistics; @@ -69,18 +70,18 @@ public interface StatisticsResource extends RestResource { * Locale statistics to be fetched. If this is empty, all locale * statistics will be returned. This parameter may be specified * multiple times if multiple locales are to be fetched. - * @return The following response status codes will be returned from this - * operation:
    - * OK(200) - Response containing translation statistics for the - * specified parameters.
    - * NOT FOUND(404) - If a project iteration could not be found for - * the given parameters.
    - * INTERNAL SERVER ERROR(500) - If there is an unexpected error in - * the server while performing this operation. */ @GET @Path("/proj/{projectSlug}/iter/{iterationSlug}") @TypeHint(ContainerTranslationStatistics.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Contains translation statistics" + + " for the specified parameters"), + @ResponseCode(code = 404, condition = "A project iteration could " + + "not be found for the given parameters"), + @ResponseCode(code = 500, + condition = "If there is an unexpected error in the server while performing this operation") + }) public ContainerTranslationStatistics getStatistics( @@ -106,18 +107,18 @@ public interface StatisticsResource extends RestResource { * Locale statistics to be fetched. If this is empty, all locale * statistics will be returned. This parameter may be specified * multiple times if multiple locales are to be fetched. - * @return The following response status codes will be returned from this - * operation:
    - * OK(200) - Response containing translation statistics for the - * specified parameters.
    - * NOT FOUND(404) - If a document could not be found for the given - * parameters.
    - * INTERNAL SERVER ERROR(500) - If there is an unexpected error in - * the server while performing this operation. */ @GET @Path("/proj/{projectSlug}/iter/{iterationSlug}/doc/{docId:.*}") @TypeHint(ContainerTranslationStatistics.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Contains translation statistics" + + " for the specified parameters"), + @ResponseCode(code = 404, condition = "A document could " + + "not be found for the given parameters"), + @ResponseCode(code = 500, + condition = "If there is an unexpected error in the server while performing this operation") + }) public ContainerTranslationStatistics getStatistics( @@ -139,23 +140,21 @@ public interface StatisticsResource extends RestResource { * username of contributor * @param dateRange * date range from..to (yyyy-mm-dd..yyyy-mm-dd) - * * @param includeAutomatedEntry * whether to include automatic entries of translation into statistic - * - * @return The following response status codes will be returned from this - * operation:
    - * OK(200) - Response containing contribution statistics for the - * specified parameters.
    - * BAD REQUEST(400) - If dateRange param is invalid.
    - * NOT FOUND(404) - If a version or user could not be found.
    - * INTERNAL SERVER ERROR(500) - If there is an unexpected error in - * the server while performing this operation. */ @GET @Path("/project/{projectSlug}/version/{versionSlug}/contributor/{username}/{dateRange}") @TypeHint(ContributionStatistics.class) @Produces({ MediaType.APPLICATION_JSON }) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Contains contribution statistics" + + " for the specified parameters"), + @ResponseCode(code = 404, condition = "A project version could " + + "not be found for the given parameters"), + @ResponseCode(code = 500, + condition = "If there is an unexpected error in the server while performing this operation") + }) public ContributionStatistics getContributionStatistics( @PathParam("projectSlug") String projectSlug, diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/service/TranslatedDocResource.java b/api/zanata-common-api/src/main/java/org/zanata/rest/service/TranslatedDocResource.java index af48c7d7c4..2f4b40419f 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/service/TranslatedDocResource.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/service/TranslatedDocResource.java @@ -39,6 +39,8 @@ import javax.ws.rs.core.Response; import com.webcohesion.enunciate.metadata.rs.ResourceLabel; +import com.webcohesion.enunciate.metadata.rs.ResponseCode; +import com.webcohesion.enunciate.metadata.rs.StatusCodes; import org.jboss.resteasy.util.HttpHeaderNames; import org.zanata.common.LocaleId; import org.zanata.rest.dto.resource.TranslationsResource; @@ -60,6 +62,10 @@ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @ResourceLabel("Translated Documents") +@StatusCodes({ + @ResponseCode(code = 500, + condition = "If there is an unexpected error in the server while performing this operation") +}) public interface TranslatedDocResource extends RestResource { @SuppressWarnings("deprecation") public static final String SERVICE_PATH = @@ -85,29 +91,27 @@ public interface TranslatedDocResource extends RestResource { * An Entity tag identifier. Based on this identifier (if * provided), the server will decide if it needs to send a * response to the client or not (See return section). - * @return The following response status codes will be returned from this - * operation:
    - * OK(200) - Successfully retrieved translations. The data will be - * contained in the response.
    - * NOT FOUND(404) - If a project, project iteration or document - * could not be found with the given parameters. Also if no - * translations are found for the given document and locale.
    - * INTERNAL SERVER ERROR(500) - If there is an unexpected error in - * the server while performing this operation.
    - * NOT_MODIFIED(304) - If the provided ETag matches the server's - * stored ETag, it will reply with this code, indicating that the - * last received response is still valid and should be reused. */ @GET @Path(RESOURCE_SLUG_TEMPLATE + "/translations/{locale}") // /r/{id}/translations/{locale} - @TypeHint(TranslationsResource.class) - public - Response getTranslations(@PathParam("id") String idNoSlash, - @PathParam("locale") LocaleId locale, - @QueryParam("ext") Set extensions, - @QueryParam("skeletons") boolean createSkeletons, - @HeaderParam(HttpHeaderNames.IF_NONE_MATCH) String eTag); + @TypeHint(TranslationsResource.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Successfully retrieved translations. " + + "The translation data will be contained in the response."), + @ResponseCode(code = 404, condition = "The project, version, or document could" + + " not be found with the given parameters. Also, if no translations are" + + " found for the given document and locale."), + @ResponseCode(code = 304, condition = "If the provided ETag matches the server's" + + " stored ETag, indicating that the last received response is still valid" + + " and should be reused."), + }) + public + Response getTranslations(@PathParam("id") String idNoSlash, + @PathParam("locale") LocaleId locale, + @QueryParam("ext") Set extensions, + @QueryParam("skeletons") boolean skeletons, + @HeaderParam(HttpHeaderNames.IF_NONE_MATCH) String eTag); /** * Deletes a set of translations for a given locale. Also deletes any @@ -122,22 +126,21 @@ Response getTranslations(@PathParam("id") String idNoSlash, * (','). * @param locale * The locale for which to get translations. - * @return The following response status codes will be returned from this - * operation:
    - * OK(200) - Successfully deleted the translations.
    - * NOT FOUND(404) - If a project, project iteration or document - * could not be found with the given parameters. UNAUTHORIZED(401) - - * If the user does not have the proper permissions to perform this - * operation.
    - * INTERNAL SERVER ERROR(500) - If there is an unexpected error in - * the server while performing this operation. */ @DELETE @Path(RESOURCE_SLUG_TEMPLATE + "/translations/{locale}") + @TypeHint(TypeHint.NO_CONTENT.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Successfully deleted the translations."), + @ResponseCode(code = 404, condition = "If a project, project iteration or document" + + " could not be found with the given parameters."), + @ResponseCode(code = 401, condition = "If the user does not have the proper" + + " permissions to perform this operation."), + }) // /r/{id}/translations/{locale} - public - Response deleteTranslations(@PathParam("id") String idNoSlash, - @PathParam("locale") LocaleId locale); + public + Response deleteTranslations(@PathParam("id") String idNoSlash, + @PathParam("locale") LocaleId locale); /** * Updates the translations for a document and a locale. @@ -162,27 +165,26 @@ Response deleteTranslations(@PathParam("id") String idNoSlash, * Auto will check the history of your translations and will not * overwrite any translations for which it detects a previous * value is being pushed. - * @return The following response status codes will be returned from this - * operation:
    - * OK(200) - Translations were successfully updated.
    - * NOT FOUND(404) - If a project, project iteration or document - * could not be found with the given parameters.
    - * UNAUTHORIZED(401) - If the user does not have the proper - * permissions to perform this operation.
    - * BAD REQUEST(400) - If there are problems with the parameters - * passed. i.e. Merge type is not one of the accepted types. This - * response should have a content message indicating a reason.
    - * INTERNAL SERVER ERROR(500) - If there is an unexpected error in - * the server while performing this operation. */ @PUT @Path(RESOURCE_SLUG_TEMPLATE + "/translations/{locale}") + @StatusCodes({ + @ResponseCode(code = 200, condition = "Translations were successfully updated."), + @ResponseCode(code = 404, condition = "If a project, project iteration or document" + + " could not be found with the given parameters."), + @ResponseCode(code = 401, condition = "If the user does not have the proper" + + " permissions to perform this operation."), + @ResponseCode(code = 400, condition = "If there are problems with the passed parameters." + + " e.g. Merge type is not one of the accepted types. This response should have a" + + " content message indicating a reason.", + type = @TypeHint(String.class)) + }) // /r/{id}/translations/{locale} - public - Response putTranslations(@PathParam("id") String idNoSlash, - @PathParam("locale") LocaleId locale, - TranslationsResource messageBody, - @QueryParam("ext") Set extensions, - @QueryParam("merge") @DefaultValue("auto") String merge); + public + Response putTranslations(@PathParam("id") String idNoSlash, + @PathParam("locale") LocaleId locale, + TranslationsResource messageBody, + @QueryParam("ext") Set extensions, + @QueryParam("merge") @DefaultValue("auto") String merge); } diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/service/VersionResource.java b/api/zanata-common-api/src/main/java/org/zanata/rest/service/VersionResource.java index ee8ca1d23e..166840a848 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/service/VersionResource.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/service/VersionResource.java @@ -28,6 +28,8 @@ import javax.ws.rs.core.Response; import com.webcohesion.enunciate.metadata.rs.ResourceLabel; +import com.webcohesion.enunciate.metadata.rs.ResponseCode; +import com.webcohesion.enunciate.metadata.rs.StatusCodes; import com.webcohesion.enunciate.metadata.rs.TypeHint; import org.zanata.rest.MediaTypes; import org.zanata.rest.dto.VersionInfo; @@ -44,18 +46,18 @@ public interface VersionResource extends RestResource { /** * Retrieve Version information for the application. - * - * @return The following response status codes will be returned from this - * operation:
    - * OK(200) - Response with the system's version information in the - * content.
    - * INTERNAL SERVER ERROR(500) - If there is an unexpected error in - * the server while performing this operation. */ @GET @Produces({ MediaTypes.APPLICATION_ZANATA_VERSION_XML, MediaTypes.APPLICATION_ZANATA_VERSION_JSON }) @TypeHint(VersionInfo.class) + @StatusCodes({ + @ResponseCode(code = 200, + condition = "Response with the system's version information in " + + "the body"), + @ResponseCode(code = 500, + condition = "If there is an unexpected error in the server while performing this operation") + }) public Response get(); } diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/package-info.java b/server/zanata-war/src/main/java/org/zanata/rest/service/package-info.java deleted file mode 100644 index 7771b124ab..0000000000 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package org.zanata.rest.service; From 11d53875e1feb782190df29a6dbc201eedf7d10c Mon Sep 17 00:00:00 2001 From: Ding-Yi Chen Date: Tue, 18 Jul 2017 15:55:20 +1000 Subject: [PATCH 088/116] enable(build): enable victims (#424) --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 079ba5b36b..b4977324d4 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -204,8 +204,8 @@ timestamps { -DskipFuncTests \ -DskipArqTests \ -Dmaven.test.failure.ignore \ + -Dvictims \ """ - // TODO add -Dvictims def surefireTestReports = 'target/surefire-reports/TEST-*.xml' From 8ea283a2602dc5b4d95bc53bf3aab528cd09bd6f Mon Sep 17 00:00:00 2001 From: Alex Eng Date: Wed, 19 Jul 2017 16:22:10 +1000 Subject: [PATCH 089/116] fix: include dswid for glossary and language page (#426) https://zanata.atlassian.net/browse/ZNTA-2064 --- .../src/frontend/app/components/Nav/index.jsx | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/components/Nav/index.jsx b/server/zanata-frontend/src/frontend/app/components/Nav/index.jsx index 234ea8d2db..b56049801e 100644 --- a/server/zanata-frontend/src/frontend/app/components/Nav/index.jsx +++ b/server/zanata-frontend/src/frontend/app/components/Nav/index.jsx @@ -10,11 +10,9 @@ const dswid = getDswid() /** * Item properties: * - * - link: path to use for JSF pages, or when internalLink is not specified - * OR a key in props.links to look up the path to use. - * (FIXME inconsistent and error-prone, split this into 2 properties) - * - internalLink: path to use when the Nav component is part of the main - * frontend app + * - link: URL path for the page. + * - jsPage: indicator for ReactJS page. Force to use href for their links. + * */ const items = [ { @@ -28,7 +26,7 @@ const items = [ { icon: 'search', link: '/explore' + dswid, - internalLink: '/explore', + jsPage: true, title: 'Explore', auth: 'public', id: 'nav_search' @@ -61,7 +59,7 @@ const items = [ small: true, icon: 'user', link: '/profile' + dswid, - internalLink: '/profile', + jsPage: true, title: 'Profile', auth: 'loggedin', id: 'nav_profile' @@ -69,7 +67,7 @@ const items = [ { icon: 'glossary', link: '/glossary' + dswid, - internalLink: '/glossary', + jsPage: true, title: 'Glossary', auth: 'loggedin', id: 'nav_glossary' @@ -77,7 +75,7 @@ const items = [ { icon: 'language', link: '/languages' + dswid, - internalLink: '/languages', + jsPage: true, title: 'Languages', auth: 'loggedin', id: 'nav_language' @@ -151,14 +149,12 @@ const Nav = ({ : (links.context + item.link) } else { // react pages, /app/index.xhtml - link = item.internalLink - ? item.internalLink - : (links[item.link] - ? (links.context + links[item.link]) - : (links.context + item.link)) + link = links[item.link] + ? (links.context + links[item.link]) + : (links.context + item.link) } - const useHref = isJsfPage || !item.internalLink + const useHref = isJsfPage || !item.jsPage let linkWithoutDswid = link.replace(dswid, '') /** From b0bc650fae72df8de6f831aad29f79332a3ea357 Mon Sep 17 00:00:00 2001 From: Sean Flanigan Date: Thu, 20 Jul 2017 09:47:10 +1000 Subject: [PATCH 090/116] Remove some trailing comments (#427) --- .../org/zanata/provider/DBUnitProvider.java | 8 +-- .../compat/AccountRawCompatibilityITCase.java | 6 +- ...rojectIterationRawCompatibilityITCase.java | 18 ++++-- .../compat/ProjectRawCompatibilityITCase.java | 15 +++-- .../compat/StatisticsCompatibilityITCase.java | 17 +++-- .../TranslationsCompatibilityITCase.java | 62 ++++++++++++------- .../TranslationsRawCompatibilityITCase.java | 48 ++++++++------ .../service/raw/AccountRawRestITCase.java | 6 +- .../rest/service/raw/FileRawRestITCase.java | 10 +-- .../service/raw/GlossaryRawRestITCase.java | 6 +- .../raw/ProjectIterationRawRestITCase.java | 18 ++++-- .../service/raw/ProjectRawRestITCase.java | 21 ++++--- .../raw/ProjectVersionRawRestITCase.java | 18 ++++-- .../rest/service/raw/ProjectsRestITCase.java | 3 +- .../service/raw/StatisticsRawRestITCase.java | 4 +- .../raw/TranslationResourceRestITCase.java | 36 ++++++----- .../service/raw/VersionRawRestITCase.java | 6 +- 17 files changed, 190 insertions(+), 112 deletions(-) diff --git a/server/zanata-war/src/test/java/org/zanata/provider/DBUnitProvider.java b/server/zanata-war/src/test/java/org/zanata/provider/DBUnitProvider.java index 904118a838..3ec3de3128 100644 --- a/server/zanata-war/src/test/java/org/zanata/provider/DBUnitProvider.java +++ b/server/zanata-war/src/test/java/org/zanata/provider/DBUnitProvider.java @@ -275,8 +275,8 @@ protected void disableReferentialIntegrity(IDatabaseConnection con) { try { con.getConnection() .prepareStatement("set referential_integrity FALSE") - .execute(); // HSQL - // DB + // HSQLDB + .execute(); } catch (Exception ex) { throw new RuntimeException(ex); } @@ -294,8 +294,8 @@ protected void enableReferentialIntegrity(IDatabaseConnection con) { try { con.getConnection() .prepareStatement("set referential_integrity TRUE") - .execute(); // HSQL - // DB + // HSQLDB + .execute(); } catch (Exception ex) { throw new RuntimeException(ex); } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/compat/AccountRawCompatibilityITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/compat/AccountRawCompatibilityITCase.java index e4e95a306f..bc6a331127 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/compat/AccountRawCompatibilityITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/compat/AccountRawCompatibilityITCase.java @@ -74,7 +74,8 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); // Ok + // Ok + assertThat(response.getStatus(), is(200)); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, Account.class); Account account = jsonUnmarshal(entityString, Account.class); @@ -107,7 +108,8 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); // Ok + // Ok + assertThat(response.getStatus(), is(200)); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, Account.class); Account account = jaxbUnmarshal(entityString, Account.class); diff --git a/server/zanata-war/src/test/java/org/zanata/rest/compat/ProjectIterationRawCompatibilityITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/compat/ProjectIterationRawCompatibilityITCase.java index 9328b173be..05442fcf6d 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/compat/ProjectIterationRawCompatibilityITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/compat/ProjectIterationRawCompatibilityITCase.java @@ -76,7 +76,8 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) throws IOException { - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); // 200 + // 200 + assertThat(response.getStatus(), is(Status.OK.getStatusCode())); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, ProjectIteration.class); @@ -102,7 +103,8 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); // 200 + // 200 + assertThat(response.getStatus(), is(Status.OK.getStatusCode())); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, ProjectIteration.class); @@ -140,8 +142,9 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { + // 201 assertThat(response.getStatus(), - is(Status.CREATED.getStatusCode())); // 201 + is(Status.CREATED.getStatusCode())); } }.run(); @@ -160,7 +163,8 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); // 200 + // 200 + assertThat(response.getStatus(), is(Status.OK.getStatusCode())); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, ProjectIteration.class); ProjectIteration it = @@ -197,8 +201,9 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { + // 201 assertThat(response.getStatus(), - is(Status.CREATED.getStatusCode())); // 201 + is(Status.CREATED.getStatusCode())); } }.run(); @@ -216,7 +221,8 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); // 200 + // 200 + assertThat(response.getStatus(), is(Status.OK.getStatusCode())); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, ProjectIteration.class); diff --git a/server/zanata-war/src/test/java/org/zanata/rest/compat/ProjectRawCompatibilityITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/compat/ProjectRawCompatibilityITCase.java index 9c80717e9d..09fd9523cb 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/compat/ProjectRawCompatibilityITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/compat/ProjectRawCompatibilityITCase.java @@ -94,7 +94,8 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) throws IOException { - assertThat(response.getStatus(), is(200)); // Ok + // Ok + assertThat(response.getStatus(), is(200)); assertHeaderPresent(response, HttpHeaders.ETAG); } }.run(); @@ -114,7 +115,8 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); // Ok + // Ok + assertThat(response.getStatus(), is(200)); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, Project.class); Project project = jsonUnmarshal(entityString, Project.class); @@ -141,7 +143,8 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); // Ok + // Ok + assertThat(response.getStatus(), is(200)); List projects = jsonParse(response); Project sampleProject = null; @@ -176,7 +179,8 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); // Ok + // Ok + assertThat(response.getStatus(), is(200)); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, Projects.class); Projects projects = jaxbUnmarshal(entityString, Projects.class); @@ -227,7 +231,8 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { assertThat(response.getStatus(), - is(Status.CREATED.getStatusCode())); // 201 + // 201 + is(Status.CREATED.getStatusCode())); } }.run(); } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/compat/StatisticsCompatibilityITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/compat/StatisticsCompatibilityITCase.java index badf0426d5..3b2720497d 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/compat/StatisticsCompatibilityITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/compat/StatisticsCompatibilityITCase.java @@ -89,9 +89,8 @@ public void getStatisticsForIteration() throws Exception { int mssgStatCount = 0; assertThat(stats.getStats().size(), greaterThan(0)); - assertThat(stats.getDetailedStats().size(), greaterThan(0)); // Has - // document - // stats + // Has document stats + assertThat(stats.getDetailedStats().size(), greaterThan(0)); for (TranslationStatistics langStats : stats.getStats()) { assertThat( langStats.getTotal(), @@ -172,11 +171,10 @@ public void getStatisticsForIterationAndLocale() throws Exception { statsResource.getStatistics("sample-project", "1.0", true, false, new String[] { "as" }); - assertThat(stats.getStats().size(), is(1)); // Just one locale and no - // word level stats - assertThat(stats.getDetailedStats().size(), greaterThan(0)); // Has - // document - // stats + // Just one locale and no word level stats + assertThat(stats.getStats().size(), is(1)); + // Has document stats + assertThat(stats.getDetailedStats().size(), greaterThan(0)); for (TranslationStatistics langStats : stats.getStats()) { assertThat( langStats.getTotal(), @@ -209,7 +207,8 @@ public void getStatisticsForDocumentAndLocale() throws Exception { statsResource.getStatistics("sample-project", "1.0", "my/path/document.txt", true, new String[] { "as" }); - assertThat(stats.getStats().size(), is(2)); // Just one locale + // Just one locale + assertThat(stats.getStats().size(), is(2)); for (TranslationStatistics langStats : stats.getStats()) { assertThat( langStats.getTotal(), diff --git a/server/zanata-war/src/test/java/org/zanata/rest/compat/TranslationsCompatibilityITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/compat/TranslationsCompatibilityITCase.java index dcce1edbc3..5223304998 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/compat/TranslationsCompatibilityITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/compat/TranslationsCompatibilityITCase.java @@ -95,7 +95,8 @@ public void postResource() throws Exception { sourceDocClient.post(res, new StringSet(PoHeader.ID + ";" + SimpleComment.ID), true); - assertThat(response.getStatus(), is(Status.CREATED.getStatusCode())); // 201 + // 201 + assertThat(response.getStatus(), is(Status.CREATED.getStatusCode())); response.close(); // Verify that it was created successfully @@ -108,8 +109,8 @@ public void postResource() throws Exception { assertThat(createdResource.getType(), is(res.getType())); assertThat(createdResource.getContentType(), is(res.getContentType())); assertThat(createdResource.getLang(), is(res.getLang())); - assertThat(createdResource.getRevision(), is(1)); // Created, so - // revision 1 + // Created, so revision 1 + assertThat(createdResource.getRevision(), is(1)); // Extensions assertThat(createdResource.getExtensions(true).size(), @@ -125,7 +126,8 @@ public void postResource() throws Exception { assertThat(createdTf.getContents().get(0), is(tf1.getContents().get(0))); assertThat(createdTf.getId(), is(tf1.getId())); assertThat(createdTf.getLang(), is(tf1.getLang())); - assertThat(createdTf.getRevision(), is(1)); // Create, so revision 1 + // Create, so revision 1 + assertThat(createdTf.getRevision(), is(1)); // Text Flow extensions assertThat(createdTf.getExtensions(true).size(), is(1)); @@ -151,7 +153,8 @@ public void doublePostResource() throws Exception { sourceDocClient.post(res, new StringSet(PoHeader.ID + ";" + SimpleComment.ID), true); - assertThat(response.getStatus(), is(Status.CREATED.getStatusCode())); // 201 + // 201 + assertThat(response.getStatus(), is(Status.CREATED.getStatusCode())); response.close(); // Post Twice (should conflict) @@ -159,7 +162,8 @@ public void doublePostResource() throws Exception { sourceDocClient.post(res, new StringSet(PoHeader.ID + ";" + SimpleComment.ID), true); - assertThat(response.getStatus(), is(Status.CONFLICT.getStatusCode())); // 409 + // 409 + assertThat(response.getStatus(), is(Status.CONFLICT.getStatusCode())); response.close(); } @@ -183,7 +187,8 @@ public void putResource() throws Exception { sourceDocClient.putResource(res.getName(), res, new StringSet( PoHeader.ID + ";" + SimpleComment.ID), false); - assertThat(response.getStatus(), is(Status.CREATED.getStatusCode())); // 201 + // 201 + assertThat(response.getStatus(), is(Status.CREATED.getStatusCode())); response.close(); // Verify that it was created successfully @@ -196,8 +201,8 @@ public void putResource() throws Exception { assertThat(createdResource.getType(), is(res.getType())); assertThat(createdResource.getContentType(), is(res.getContentType())); assertThat(createdResource.getLang(), is(res.getLang())); - assertThat(createdResource.getRevision(), is(1)); // Created, so - // revision 1 + // Created, so revision 1 + assertThat(createdResource.getRevision(), is(1)); // Extensions assertThat(createdResource.getExtensions(true).size(), @@ -213,7 +218,8 @@ public void putResource() throws Exception { assertThat(createdTf.getContents().get(0), is(tf1.getContents().get(0))); assertThat(createdTf.getId(), is(tf1.getId())); assertThat(createdTf.getLang(), is(tf1.getLang())); - assertThat(createdTf.getRevision(), is(1)); // Create, so revision 1 + // Create, so revision 1 + assertThat(createdTf.getRevision(), is(1)); // Text Flow extensions assertThat(createdTf.getExtensions(true).size(), is(1)); @@ -273,21 +279,24 @@ public void deleteResource() throws Exception { sourceDocClient.putResource(res.getName(), res, new StringSet( PoHeader.ID + ";" + SimpleComment.ID), false); - assertThat(response.getStatus(), is(Status.CREATED.getStatusCode())); // 201 + // 201 + assertThat(response.getStatus(), is(Status.CREATED.getStatusCode())); response.close(); // Delete the resource Response deleteResponse = sourceDocClient.deleteResource(res.getName()); - assertThat(deleteResponse.getStatus(), is(Status.OK.getStatusCode())); // 200 + // 200 + assertThat(deleteResponse.getStatus(), is(Status.OK.getStatusCode())); deleteResponse.close(); // try to fetch it again Response getResponse = sourceDocClient.getResource(res.getName(), null); + // 404 assertThat(getResponse.getStatus(), - is(Status.NOT_FOUND.getStatusCode())); // 404 + is(Status.NOT_FOUND.getStatusCode())); getResponse.close(); } @@ -301,7 +310,8 @@ public void getResourceMeta() throws Exception { new StringSet(SimpleComment.ID)); ResourceMeta resMeta = getResourceMetaFromResponse(response); - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); // 200 + // 200 + assertThat(response.getStatus(), is(Status.OK.getStatusCode())); assertThat(resMeta.getName(), is("my/path/document-2.txt")); assertThat(resMeta.getType(), is(ResourceType.FILE)); assertThat(resMeta.getLang(), is(LocaleId.EN_US)); @@ -323,7 +333,8 @@ public void putResourceMeta() throws Exception { Response putResponse = sourceDocClient.putResourceMeta("my,path,document-2.txt", resMeta, null); - assertThat(putResponse.getStatus(), is(Status.OK.getStatusCode())); // 200 + // 200 + assertThat(putResponse.getStatus(), is(Status.OK.getStatusCode())); putResponse.close(); // Fetch again @@ -331,12 +342,14 @@ public void putResourceMeta() throws Exception { sourceDocClient.getResourceMeta("my,path,document-2.txt", null); ResourceMeta newResMeta = getResourceMetaFromResponse(getResponse); - assertThat(getResponse.getStatus(), is(Status.OK.getStatusCode())); // 200 + // 200 + assertThat(getResponse.getStatus(), is(Status.OK.getStatusCode())); assertThat(newResMeta.getName(), is(resMeta.getName())); assertThat(newResMeta.getContentType(), is(resMeta.getContentType())); assertThat(newResMeta.getLang(), is(resMeta.getLang())); assertThat(newResMeta.getType(), is(resMeta.getType())); - assertThat(newResMeta.getRevision(), is(1)); // Created, so revision 1 + // Created, so revision 1 + assertThat(newResMeta.getRevision(), is(1)); } @Test @@ -351,7 +364,8 @@ LocaleId.EN_US, new StringSet(SimpleComment.ID), false, null); TranslationsResource transRes = getTransResourceFromResponse(response); - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); // 200 + // 200 + assertThat(response.getStatus(), is(Status.OK.getStatusCode())); assertThat(transRes.getTextFlowTargets().size(), greaterThanOrEqualTo(3)); @@ -397,7 +411,8 @@ LocaleId.EN_US, new StringSet(SimpleComment.ID), false, null); TranslationsResource transRes = getTransResourceFromResponse(response); - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); // 200 + // 200 + assertThat(response.getStatus(), is(Status.OK.getStatusCode())); assertThat(transRes.getTextFlowTargets().size(), greaterThanOrEqualTo(3)); @@ -423,7 +438,8 @@ LocaleId.EN_US, new StringSet(SimpleComment.ID), false, LocaleId.EN_US, transRes, new StringSet( SimpleComment.ID), "auto"); - assertThat(putResponse.getStatus(), is(Status.OK.getStatusCode())); // 200 + // 200 + assertThat(putResponse.getStatus(), is(Status.OK.getStatusCode())); putResponse.close(); // Retrieve the translations once more to make sure they were changed @@ -433,7 +449,8 @@ LocaleId.EN_US, transRes, new StringSet( LocaleId.EN_US, new StringSet(SimpleComment.ID), false, null); transRes = getTransResourceFromResponse(response); - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); // 200 + // 200 + assertThat(response.getStatus(), is(Status.OK.getStatusCode())); assertThat(transRes.getTextFlowTargets().size(), greaterThanOrEqualTo(3)); @@ -472,7 +489,8 @@ public void deleteTranslations() throws Exception { translationsClient.deleteTranslations("my,path,document-3.txt", LocaleId.EN_US); - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); // 200 + // 200 + assertThat(response.getStatus(), is(Status.OK.getStatusCode())); response.close(); // try to fetch them again diff --git a/server/zanata-war/src/test/java/org/zanata/rest/compat/TranslationsRawCompatibilityITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/compat/TranslationsRawCompatibilityITCase.java index d1e5c0b269..000c0ea977 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/compat/TranslationsRawCompatibilityITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/compat/TranslationsRawCompatibilityITCase.java @@ -164,8 +164,9 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { + // 201 assertThat(response.getStatus(), - is(Status.CREATED.getStatusCode())); // 201 + is(Status.CREATED.getStatusCode())); } }.run(); @@ -175,7 +176,8 @@ protected void onResponse(Response response) { sourceDocClient.getResource(res.getName(), new StringSet( PoHeader.ID + ";" + SimpleComment.ID)); - assertThat(resourceResponse.getStatus(), is(Status.OK.getStatusCode())); // 200 + // 200 + assertThat(resourceResponse.getStatus(), is(Status.OK.getStatusCode())); Resource createdResource = getResourceFromResponse(resourceResponse); @@ -183,8 +185,8 @@ protected void onResponse(Response response) { assertThat(createdResource.getType(), is(res.getType())); assertThat(createdResource.getContentType(), is(res.getContentType())); assertThat(createdResource.getLang(), is(res.getLang())); - assertThat(createdResource.getRevision(), is(1)); // Created, so - // revision 1 + // Created, so revision 1 + assertThat(createdResource.getRevision(), is(1)); // Extensions assertThat(createdResource.getExtensions(true).size(), @@ -200,7 +202,8 @@ protected void onResponse(Response response) { assertThat(createdTf.getContents(), is(tf1.getContents())); assertThat(createdTf.getId(), is(tf1.getId())); assertThat(createdTf.getLang(), is(tf1.getLang())); - assertThat(createdTf.getRevision(), is(1)); // Create, so revision 1 + // Create, so revision 1 + assertThat(createdTf.getRevision(), is(1)); // Text Flow extensions assertThat(createdTf.getExtensions(true).size(), is(1)); @@ -245,8 +248,9 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { + // 201 assertThat(response.getStatus(), - is(Status.CREATED.getStatusCode())); // 201 + is(Status.CREATED.getStatusCode())); } }.run(); @@ -261,8 +265,8 @@ protected void onResponse(Response response) { assertThat(createdResource.getType(), is(res.getType())); assertThat(createdResource.getContentType(), is(res.getContentType())); assertThat(createdResource.getLang(), is(res.getLang())); - assertThat(createdResource.getRevision(), is(1)); // Created, so - // revision 1 + // Created, so revision 1 + assertThat(createdResource.getRevision(), is(1)); // Extensions assertThat(createdResource.getExtensions(true).size(), @@ -278,7 +282,8 @@ protected void onResponse(Response response) { assertThat(createdTf.getContents(), is(tf1.getContents())); assertThat(createdTf.getId(), is(tf1.getId())); assertThat(createdTf.getLang(), is(tf1.getLang())); - assertThat(createdTf.getRevision(), is(1)); // Create, so revision 1 + // Create, so revision 1 + assertThat(createdTf.getRevision(), is(1)); // Text Flow extensions assertThat(createdTf.getExtensions(true).size(), is(1)); @@ -302,7 +307,8 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); // 200 + // 200 + assertThat(response.getStatus(), is(Status.OK.getStatusCode())); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, ResourceMeta.class); @@ -347,8 +353,9 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { + // 200 assertThat(response.getStatus(), - is(Status.OK.getStatusCode())); // 200 + is(Status.OK.getStatusCode())); } }.run(); @@ -358,13 +365,14 @@ protected void onResponse(Response response) { null); ResourceMeta newResMeta = getResourceMetaFromResponse(getResponse); - assertThat(getResponse.getStatus(), is(Status.OK.getStatusCode())); // 200 + // 200 + assertThat(getResponse.getStatus(), is(Status.OK.getStatusCode())); assertThat(newResMeta.getName(), is(resMeta.getName())); assertThat(newResMeta.getContentType(), is(resMeta.getContentType())); assertThat(newResMeta.getLang(), is(resMeta.getLang())); assertThat(newResMeta.getType(), is(resMeta.getType())); - assertThat(newResMeta.getRevision(), greaterThan(1)); // Updated so - // higher revision + // Updated so higher revision + assertThat(newResMeta.getRevision(), greaterThan(1)); } @Test @@ -382,7 +390,8 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); // 200 + // 200 + assertThat(response.getStatus(), is(Status.OK.getStatusCode())); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, TranslationsResource.class); @@ -445,7 +454,8 @@ LocaleId.EN_US, new StringSet(SimpleComment.ID), false, null); final TranslationsResource transRes = getTransResourceFromResponse(response); - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); // 200 + // 200 + assertThat(response.getStatus(), is(Status.OK.getStatusCode())); assertThat(transRes.getTextFlowTargets().size(), greaterThanOrEqualTo(3)); @@ -486,7 +496,8 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); // 200 + // 200 + assertThat(response.getStatus(), is(Status.OK.getStatusCode())); } }.run(); @@ -497,7 +508,8 @@ protected void onResponse(Response response) { LocaleId.EN_US, new StringSet(SimpleComment.ID), false, null); TranslationsResource updatedTransRes = getTransResourceFromResponse(response); - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); // 200 + // 200 + assertThat(response.getStatus(), is(Status.OK.getStatusCode())); assertThat(updatedTransRes.getTextFlowTargets().size(), greaterThanOrEqualTo(3)); diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AccountRawRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AccountRawRestITCase.java index 2c4c3cae37..45635f5474 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AccountRawRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AccountRawRestITCase.java @@ -97,7 +97,8 @@ protected void onResponse(Response response) { assertThat(account.getEmail(), is("root@localhost")); assertThat(account.getApiKey(), is("b6d7044e9ee3b2447c28fb7c50d86d98")); - assertThat(account.getRoles().size(), is(1)); // 1 roles + // 1 role + assertThat(account.getRoles().size(), is(1)); } }.run(); } @@ -127,7 +128,8 @@ protected void onResponse(Response response) { assertThat(account.getEmail(), is("root@localhost")); assertThat(account.getApiKey(), is("b6d7044e9ee3b2447c28fb7c50d86d98")); - assertThat(account.getRoles().size(), is(1)); // 1 role + // 1 role + assertThat(account.getRoles().size(), is(1)); } }.run(); } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/FileRawRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/FileRawRestITCase.java index 4e9240bb9e..26034674db 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/FileRawRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/FileRawRestITCase.java @@ -76,7 +76,8 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); // Ok + // Ok + assertThat(response.getStatus(), is(200)); assertHeaderValue(response, "Content-Disposition", "attachment; filename=\"document.txt.po\""); assertHeaderValue(response, HttpHeaders.CONTENT_TYPE, @@ -106,7 +107,8 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); // Ok + // Ok + assertThat(response.getStatus(), is(200)); assertHeaderValue(response, "Content-Disposition", "attachment; filename=\"document-2.txt.po\""); assertHeaderValue(response, HttpHeaders.CONTENT_TYPE, @@ -141,9 +143,9 @@ private static void assertPoFileCorrect(String poFileContents) { containsString("PO-Revision-Date:")); assertThat(message.getMsgstr(), containsString("Language-Team:")); + // Generator is Zanata assertThat(message.getMsgstr(), - containsString("X-Generator: Zanata")); // Generator is - // Zanata + containsString("X-Generator: Zanata")); assertThat(message.getMsgstr(), containsString("Plural-Forms:")); } } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/GlossaryRawRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/GlossaryRawRestITCase.java index c17b4d21cb..c19187e82e 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/GlossaryRawRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/GlossaryRawRestITCase.java @@ -176,7 +176,8 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus()).isEqualTo(200); // Ok + // OK + assertThat(response.getStatus()).isEqualTo(200); } }.run(); } @@ -196,7 +197,8 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus()).isEqualTo(401); // Unauthorized + // Unauthorized + assertThat(response.getStatus()).isEqualTo(401); } }.run(); } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectIterationRawRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectIterationRawRestITCase.java index bf33b716e2..3c82e23fdd 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectIterationRawRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectIterationRawRestITCase.java @@ -72,7 +72,8 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); // Ok + // OK + assertThat(response.getStatus(), is(200)); assertHeaderPresent(response, HttpHeaders.ETAG); } }.run(); @@ -93,7 +94,8 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); // Ok + // OK + assertThat(response.getStatus(), is(200)); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, ProjectIteration.class); @@ -120,7 +122,8 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); // Ok + // OK + assertThat(response.getStatus(), is(200)); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, ProjectIteration.class); ProjectIteration iteration = @@ -212,7 +215,8 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { assertThat(response.getStatus(), - is(Response.Status.NOT_FOUND.getStatusCode())); // 404 + // 404 + is(Response.Status.NOT_FOUND.getStatusCode())); } }.run(); } @@ -243,7 +247,8 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(201)); // Created + // Created + assertThat(response.getStatus(), is(201)); } }.run(); } @@ -337,7 +342,8 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(201)); // Created + // Created + assertThat(response.getStatus(), is(201)); } }.run(); } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectRawRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectRawRestITCase.java index 82f9665203..aee042ee76 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectRawRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectRawRestITCase.java @@ -82,7 +82,8 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); // Ok + // OK + assertThat(response.getStatus(), is(200)); assertHeaderPresent(response, HttpHeaders.ETAG); } }.run(); @@ -102,7 +103,8 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); // Ok + // OK + assertThat(response.getStatus(), is(200)); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, Project.class); @@ -201,7 +203,8 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); // Ok + // OK + assertThat(response.getStatus(), is(200)); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, Project.class); @@ -256,7 +259,8 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(201)); // Created + // Created + assertThat(response.getStatus(), is(201)); } }.run(); } @@ -395,7 +399,8 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(201)); // Created + // Created + assertThat(response.getStatus(), is(201)); } }.run(); } @@ -412,7 +417,8 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); // Ok + // OK + assertThat(response.getStatus(), is(200)); String entityString = response.readEntity(String.class); assertThat(entityString, @@ -438,7 +444,8 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); // Ok + // OK + assertThat(response.getStatus(), is(200)); String entityString = response.readEntity(String.class); assertThat(entityString, diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectVersionRawRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectVersionRawRestITCase.java index 972efc2ccf..4d672cbcfe 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectVersionRawRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectVersionRawRestITCase.java @@ -62,7 +62,8 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); // Ok + // OK + assertThat(response.getStatus(), is(200)); assertHeaderPresent(response, HttpHeaders.ETAG); } }.run(); @@ -82,7 +83,8 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); // Ok + // OK + assertThat(response.getStatus(), is(200)); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, ProjectIteration.class); @@ -108,7 +110,8 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); // Ok + // Ok + assertThat(response.getStatus(), is(200)); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, ProjectIteration.class); @@ -198,7 +201,8 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { assertThat(response.getStatus(), - is(Response.Status.NOT_FOUND.getStatusCode())); // 404 + // 404 + is(Response.Status.NOT_FOUND.getStatusCode())); } }.run(); } @@ -228,7 +232,8 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(201)); // Created + // Created + assertThat(response.getStatus(), is(201)); } }.run(); } @@ -317,7 +322,8 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(201)); // Created + // Created + assertThat(response.getStatus(), is(201)); } }.run(); } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectsRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectsRestITCase.java index 127573ef02..df68baf176 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectsRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectsRestITCase.java @@ -69,7 +69,8 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); // Ok + // OK + assertThat(response.getStatus(), is(200)); String entityString = response.readEntity(String.class); Project[] projects = jsonUnmarshal(entityString, Project[].class); Assertions.assertThat(projects.length).isGreaterThan(0); diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/StatisticsRawRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/StatisticsRawRestITCase.java index 835b63a769..60e815d7cb 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/StatisticsRawRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/StatisticsRawRestITCase.java @@ -223,7 +223,7 @@ protected void onResponse(Response response) { public void getDocumentStatisticsXmlWithDetails() throws Exception { // Ok // assertThat(stats.getDetailedStats().size(), greaterThan(0)); - // // No detailed stats (maybe later) + // No detailed stats (maybe later) // make sure counts are sane // Results returned only for specified locales // make sure counts are sane @@ -417,7 +417,7 @@ protected void onResponse(Response response) { public void getDocumentStatisticsJsonWithDetails() throws Exception { // Ok // assertThat(stats.getDetailedStats().size(), greaterThan(0)); - // // No detailed stats (maybe later) + // No detailed stats (maybe later) // make sure counts are sane // Results returned only for specified locales // make sure counts are sane diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/TranslationResourceRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/TranslationResourceRestITCase.java index 898a924b4c..e8bf60b3f2 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/TranslationResourceRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/TranslationResourceRestITCase.java @@ -138,8 +138,8 @@ public void createPoResourceWithPoHeader() { // @formatter:on Response postResponse = - getSourceDocResource().post(sr, null, true); // new - // StringSet(PoHeader.ID)); + getSourceDocResource().post(sr, null, true); + // new StringSet(PoHeader.ID)); assertThat(postResponse.getStatus(), is(Status.CREATED.getStatusCode())); doGetandAssertThatResourceListContainsNItems(1); @@ -505,10 +505,12 @@ public void put1Delete1Put1() throws Exception { expectDocs(true, false, doc1); tft1.setRevision(1); expectTarget1(target1); - deleteDoc1(); // doc1 becomes obsolete + // doc1 becomes obsolete + deleteDoc1(); getZero(); dontExpectTarget1(); - putDoc1(false); // doc1 resurrected, rev 1 + // doc1 resurrected, rev 1 + putDoc1(false); doc1.setRevision(1); tf1.setRevision(1); tft1.setTextFlowRevision(1); @@ -530,7 +532,8 @@ public void put1Put1Again() throws Exception { tft1.setRevision(1); expectDocs(true, false, doc1); expectTarget1(target1); - putDoc1(false); // docRev still 1 + // docRev still 1 + putDoc1(false); doc1.setRevision(1); tf1.setRevision(1); tft1.setTextFlowRevision(1); @@ -556,10 +559,12 @@ public void put1Delete1Put1a() throws Exception { expectDocs(true, false, doc1); tft1.setRevision(1); expectTarget1(target1); - deleteDoc1(); // doc1 becomes obsolete + // doc1 becomes obsolete + deleteDoc1(); getZero(); dontExpectTarget1(); - Resource doc1a = putDoc1a(false); // doc1 resurrected, rev 2 + // doc1 resurrected, rev 2 + Resource doc1a = putDoc1a(false); doc1a.setRevision(2); TextFlow tf1a = doc1a.getTextFlows().get(0); tf1a.setRevision(doc1a.getRevision()); @@ -608,7 +613,8 @@ public void put1Put1aPut1() throws Exception { expectDocs(true, false, doc1a); dontExpectTarget1(); expectTarget1a(target1a); - putDoc1(false); // same as original doc1, but different doc rev + // same as original doc1, but different doc rev + putDoc1(false); doc1.setRevision(3); expectDocs(true, false, doc1); // target 1 should be resurrected @@ -621,7 +627,8 @@ public void put1Put1aPut1() throws Exception { public void generatedPoHeaders() throws Exception { LocaleId de_DE = new LocaleId("de"); getZero(); - publishTranslations(); // push some translations (with no headers) + // push some translations (with no headers) + publishTranslations(); // Get the translations with PO headers Response response = getTransResource() @@ -690,9 +697,8 @@ public void headersBeforeTranslating() throws Exception { "gettext"), true, null); TranslationsResource translations = getTranslationsResourceFromResponse(response); - assertThat(translations.getTextFlowTargets().size(), is(0)); // Expecting - // no - // translations + // Expecting no translations + assertThat(translations.getTextFlowTargets().size(), is(0)); // Make sure the headers are populated PoTargetHeader header = @@ -730,7 +736,8 @@ public void headersFromOriginalPush() throws Exception { // Future Date for the PO Revision Date Header Calendar poRevDate = Calendar.getInstance(); - poRevDate.add(Calendar.YEAR, 1); // 1 year in the future + // 1 year in the future + poRevDate.add(Calendar.YEAR, 1); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mmZ"); // Add initial headers to the translations @@ -738,9 +745,10 @@ public void headersFromOriginalPush() throws Exception { transHeader.getEntries().add( new HeaderEntry(HeaderFields.KEY_LastTranslator, "Test User ")); + // Date in the future transHeader.getEntries().add( new HeaderEntry(HeaderFields.KEY_PoRevisionDate, dateFormat - .format(poRevDate.getTime()))); // Date in the future + .format(poRevDate.getTime()))); entity.getExtensions(true).add(transHeader); // Push the translations diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/VersionRawRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/VersionRawRestITCase.java index 91abf708a3..0ab97941d5 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/VersionRawRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/VersionRawRestITCase.java @@ -64,7 +64,8 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); // Ok + // OK + assertThat(response.getStatus(), is(200)); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, VersionInfo.class); } @@ -83,7 +84,8 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); // Ok + // OK + assertThat(response.getStatus(), is(200)); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, VersionInfo.class); } From a7cbc38c7f2c8ddf293a82a892257fb8dee6c99f Mon Sep 17 00:00:00 2001 From: Damian Jansen Date: Thu, 20 Jul 2017 14:41:43 +1000 Subject: [PATCH 091/116] fix(ZNTA-2114): Broken help icons and links (#423) --- .../webapp/WEB-INF/layout/dashboard/settings.xhtml | 10 ++++++---- .../webapp/WEB-INF/layout/language/settings-tab.xhtml | 2 +- .../main/webapp/WEB-INF/layout/project/edit_form.xhtml | 4 ++-- .../layout/project/settings-tab-translation.xhtml | 4 ++-- .../WEB-INF/layout/project/settings-tab-webhook.xhtml | 3 ++- .../main/webapp/WEB-INF/layout/version/edit_form.xhtml | 4 ++-- .../webapp/WEB-INF/layout/version/settings-tab.xhtml | 6 +++--- .../webapp/resources/zanata/multi-file-upload.xhtml | 10 +++++----- 8 files changed, 23 insertions(+), 20 deletions(-) diff --git a/server/zanata-war/src/main/webapp/WEB-INF/layout/dashboard/settings.xhtml b/server/zanata-war/src/main/webapp/WEB-INF/layout/dashboard/settings.xhtml index 75655e8e2f..41178b1411 100644 --- a/server/zanata-war/src/main/webapp/WEB-INF/layout/dashboard/settings.xhtml +++ b/server/zanata-war/src/main/webapp/WEB-INF/layout/dashboard/settings.xhtml @@ -277,13 +277,15 @@

    - - + and Maven plugin - - + .

    diff --git a/server/zanata-war/src/main/webapp/WEB-INF/layout/language/settings-tab.xhtml b/server/zanata-war/src/main/webapp/WEB-INF/layout/language/settings-tab.xhtml index 50eac089a2..567f2f3ca6 100644 --- a/server/zanata-war/src/main/webapp/WEB-INF/layout/language/settings-tab.xhtml +++ b/server/zanata-war/src/main/webapp/WEB-INF/layout/language/settings-tab.xhtml @@ -79,7 +79,7 @@ #{languageAction.examplePluralForms} - + #{msgs['jsf.ProjectType']}

    #{msgs['jsf.ProjectType.title']} - +

    diff --git a/server/zanata-war/src/main/webapp/WEB-INF/layout/project/settings-tab-translation.xhtml b/server/zanata-war/src/main/webapp/WEB-INF/layout/project/settings-tab-translation.xhtml index e8ac471f00..20964a4a8c 100644 --- a/server/zanata-war/src/main/webapp/WEB-INF/layout/project/settings-tab-translation.xhtml +++ b/server/zanata-war/src/main/webapp/WEB-INF/layout/project/settings-tab-translation.xhtml @@ -77,10 +77,10 @@

    #{msgs['jsf.CopyTrans']}

    #{msgs['jsf.Copytrans.message']} - - +

    diff --git a/server/zanata-war/src/main/webapp/WEB-INF/layout/project/settings-tab-webhook.xhtml b/server/zanata-war/src/main/webapp/WEB-INF/layout/project/settings-tab-webhook.xhtml index f3c3e2213f..66f4a71adf 100644 --- a/server/zanata-war/src/main/webapp/WEB-INF/layout/project/settings-tab-webhook.xhtml +++ b/server/zanata-war/src/main/webapp/WEB-INF/layout/project/settings-tab-webhook.xhtml @@ -73,8 +73,9 @@ #{msgs['jsf.project.WebHooks']} - + diff --git a/server/zanata-war/src/main/webapp/WEB-INF/layout/version/edit_form.xhtml b/server/zanata-war/src/main/webapp/WEB-INF/layout/version/edit_form.xhtml index f2a75d52d3..fbfd8f0392 100644 --- a/server/zanata-war/src/main/webapp/WEB-INF/layout/version/edit_form.xhtml +++ b/server/zanata-war/src/main/webapp/WEB-INF/layout/version/edit_form.xhtml @@ -91,9 +91,9 @@ class="heading--secondary l--push-all-0">#{msgs['jsf.projectType']}

    #{msgs['jsf.ProjectType.title']} - +

    diff --git a/server/zanata-war/src/main/webapp/WEB-INF/layout/version/settings-tab.xhtml b/server/zanata-war/src/main/webapp/WEB-INF/layout/version/settings-tab.xhtml index 6db79dfd82..5a2b760377 100644 --- a/server/zanata-war/src/main/webapp/WEB-INF/layout/version/settings-tab.xhtml +++ b/server/zanata-war/src/main/webapp/WEB-INF/layout/version/settings-tab.xhtml @@ -259,10 +259,10 @@ value="requireTranslationReview"/>

    #{msgs['jsf.iteration.requireReview.message']} - + title="#{msgs['jsf.iteration.requireReview.help']}"> +

    diff --git a/server/zanata-war/src/main/webapp/resources/zanata/multi-file-upload.xhtml b/server/zanata-war/src/main/webapp/resources/zanata/multi-file-upload.xhtml index 027eafcce4..856d75d784 100644 --- a/server/zanata-war/src/main/webapp/resources/zanata/multi-file-upload.xhtml +++ b/server/zanata-war/src/main/webapp/resources/zanata/multi-file-upload.xhtml @@ -149,7 +149,7 @@ site: http://www.fsf.org. value="#{msgs['jsf.upload.ClientUploadInstructions']}" escape="false"> + value="<a href="http://docs.zanata.org/en/release/client/commands/push/">"/>

    @@ -190,7 +190,7 @@ site: http://www.fsf.org. - + @@ -230,10 +230,10 @@ site: http://www.fsf.org.
  • + +
  • + + #{msgs['jsf.iteration.TMMerge']} + + +
  • +
  • diff --git a/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java b/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java index 55a475869f..fd52ace7fd 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/editor/service/TransMemoryMergeManagerTest.java @@ -1,8 +1,11 @@ package org.zanata.rest.editor.service; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import org.assertj.core.util.Lists; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -10,13 +13,15 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.zanata.async.AsyncTaskHandle; import org.zanata.async.AsyncTaskHandleManager; import org.zanata.async.AsyncTaskKey; +import org.zanata.async.handle.MergeTranslationsTaskHandle; import org.zanata.async.handle.TransMemoryMergeTaskHandle; import org.zanata.common.LocaleId; import org.zanata.common.ProjectType; -import org.zanata.model.HAccount; import org.zanata.model.TestFixture; +import org.zanata.rest.dto.VersionTMMerge; import org.zanata.security.ZanataIdentity; import org.zanata.rest.editor.service.TransMemoryMergeManager.TMMergeForDocTaskKey; import org.zanata.service.TransMemoryMergeService; @@ -34,10 +39,13 @@ public class TransMemoryMergeManagerTest { private AsyncTaskHandleManager asyncTaskHandleManager; @Mock private TransMemoryMergeService transMemoryMergeService; - private HAccount authenticated; private TransMemoryMergeRequest request; + @Mock + private MergeTranslationsTaskHandle taskHandle; + @Captor + private ArgumentCaptor docTMMergeHandleCaptor; @Captor - private ArgumentCaptor handleCaptor; + private ArgumentCaptor versionTMMergeHandleCaptor; @Captor private ArgumentCaptor taskKeyCaptor; private TransMemoryMergeCancelRequest cancelRequest; @@ -66,6 +74,15 @@ public void setUp() { when(identity.getAccountUsername()).thenReturn("admin"); } + @Test + public void canCheckIfTaskIsRunning() { + assertThat(TransMemoryMergeManager.taskIsNotRunning(null)).isTrue(); + when(taskHandle.isCancelled()).thenReturn(true); + assertThat(TransMemoryMergeManager.taskIsNotRunning(taskHandle)).isTrue(); + when(taskHandle.isDone()).thenReturn(true); + assertThat(TransMemoryMergeManager.taskIsNotRunning(taskHandle)).isTrue(); + } + @Test public void startTMMergeWillReturnTrueIfNoProcessForThisRequestIsAlreadyRunning() { @@ -73,8 +90,8 @@ public void setUp() { assertThat(result).isTrue(); Mockito.verify(asyncTaskHandleManager).registerTaskHandle( - handleCaptor.capture(), taskKeyCaptor.capture()); - TransMemoryMergeTaskHandle handle = handleCaptor.getValue(); + docTMMergeHandleCaptor.capture(), taskKeyCaptor.capture()); + TransMemoryMergeTaskHandle handle = docTMMergeHandleCaptor.getValue(); assertThat(handle.getTriggeredBy()) .isEqualTo(identity.getAccountUsername()); Mockito.verify(transMemoryMergeService).executeMergeAsync(request, @@ -102,8 +119,8 @@ public boolean isCancelled() { assertThat(result).isTrue(); Mockito.verify(asyncTaskHandleManager).registerTaskHandle( - handleCaptor.capture(), taskKeyCaptor.capture()); - TransMemoryMergeTaskHandle handle = handleCaptor.getValue(); + docTMMergeHandleCaptor.capture(), taskKeyCaptor.capture()); + TransMemoryMergeTaskHandle handle = docTMMergeHandleCaptor.getValue(); assertThat(handle.getTriggeredBy()) .isEqualTo(identity.getAccountUsername()); Mockito.verify(transMemoryMergeService).executeMergeAsync(request, @@ -131,8 +148,8 @@ public boolean isDone() { assertThat(result).isTrue(); Mockito.verify(asyncTaskHandleManager).registerTaskHandle( - handleCaptor.capture(), taskKeyCaptor.capture()); - TransMemoryMergeTaskHandle handle = handleCaptor.getValue(); + docTMMergeHandleCaptor.capture(), taskKeyCaptor.capture()); + TransMemoryMergeTaskHandle handle = docTMMergeHandleCaptor.getValue(); assertThat(handle.getTriggeredBy()) .isEqualTo(identity.getAccountUsername()); Mockito.verify(transMemoryMergeService).executeMergeAsync(request, @@ -245,4 +262,44 @@ public boolean cancel(boolean mayInterruptIfRunning) { assertThat(result).isTrue(); } + @Test + public void + startTMMergeForVersionIfNoProcessForThisRequestIsAlreadyRunning() { + VersionTMMerge versionTMMerge = + new VersionTMMerge(LocaleId.FR, 80, MergeRule.FUZZY, + MergeRule.FUZZY, MergeRule.FUZZY, + Lists.newArrayList()); + long versionId = 1L; + AsyncTaskHandle result = manager.start(versionId, versionTMMerge); + + Mockito.verify(asyncTaskHandleManager).registerTaskHandle( + versionTMMergeHandleCaptor.capture(), taskKeyCaptor.capture()); + MergeTranslationsTaskHandle handle = versionTMMergeHandleCaptor.getValue(); + assertThat(result).isSameAs(handle); + assertThat(handle.getTriggeredBy()) + .isEqualTo(identity.getAccountUsername()); + Mockito.verify(transMemoryMergeService).startMergeTranslations( + versionId, versionTMMerge, + handle); + } + + @Test + public void + startTMMergeForVersionIfProcessForThisRequestIsAlreadyRunning() { + long versionId = 1L; + LocaleId localeId = LocaleId.FR; + when(asyncTaskHandleManager.getHandleByKey(TransMemoryMergeManager.makeKey( + versionId, localeId))).thenReturn(taskHandle); + VersionTMMerge versionTMMerge = + new VersionTMMerge(localeId, 80, MergeRule.FUZZY, + MergeRule.FUZZY, MergeRule.FUZZY, + Lists.newArrayList()); + + assertThatThrownBy(() -> manager.start(versionId, versionTMMerge)) + .isInstanceOf(UnsupportedOperationException.class) + .hasMessage("there is already a task running for version and locale"); + + Mockito.verifyZeroInteractions(transMemoryMergeService); + } + } From b718b7e62749704c739c13d3dc736af93d46d1b4 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Thu, 20 Jul 2017 16:21:28 +1000 Subject: [PATCH 097/116] externlize jest config so that tests can be run in IDE --- .../src/frontend/jest.config.json | 31 ++++++++++++++++ .../zanata-frontend/src/frontend/package.json | 35 ++----------------- 2 files changed, 33 insertions(+), 33 deletions(-) create mode 100644 server/zanata-frontend/src/frontend/jest.config.json diff --git a/server/zanata-frontend/src/frontend/jest.config.json b/server/zanata-frontend/src/frontend/jest.config.json new file mode 100644 index 0000000000..cce5ed2ee0 --- /dev/null +++ b/server/zanata-frontend/src/frontend/jest.config.json @@ -0,0 +1,31 @@ +{ + "collectCoverageFrom": [ + "app/**/*.{js,jsx}", + "!**/node_modules/**", + "!app/**/*.story.js" + ], + "coverageReporters": [ + "cobertura", + "html", + "lcov", + "text" + ], + "moduleNameMapper": { + "^.+\\.(css)$": "./__tests__/mock/mockCss.js" + }, + "transform": { + ".*": "./node_modules/babel-jest" + }, + "testPathIgnorePatterns": [ + "/node_modules/", + "/__tests__/mock" + ], + "unmockedModulePathPatterns": [ + "/node_modules", + "/app" + ], + "moduleFileExtensions": [ + "js", + "jsx" + ] +} diff --git a/server/zanata-frontend/src/frontend/package.json b/server/zanata-frontend/src/frontend/package.json index 106ba0090c..a9221cd0c2 100644 --- a/server/zanata-frontend/src/frontend/package.json +++ b/server/zanata-frontend/src/frontend/package.json @@ -14,8 +14,8 @@ "storybook-editor": "start-storybook -p 9001 -s ./dist --config-dir .storybook-editor", "storybook-frontend": "start-storybook -p 9001 -s ./dist --config-dir .storybook-frontend", "storybook-build": "build-storybook -s ./dist", - "test": "jest --coverage", - "test:watch": "jest --watch --coverage" + "test": "jest --coverage --config jest.config.json", + "test:watch": "jest --watch --coverage --config jest.config.json" }, "repository": { "type": "git", @@ -133,36 +133,5 @@ "svg-sprite": "1.3.6", "text-diff": "1.0.1", "webfontloader": "1.6.24" - }, - "jest": { - "collectCoverageFrom": [ - "app/**/*.{js,jsx}", - "!**/node_modules/**", - "!app/**/*.story.js" - ], - "coverageReporters": [ - "cobertura", - "html", - "lcov", - "text" - ], - "moduleNameMapper": { - "^.+\\.(css)$": "./__tests__/mock/mockCss.js" - }, - "transform": { - ".*": "./node_modules/babel-jest" - }, - "testPathIgnorePatterns": [ - "/node_modules/", - "/__tests__/mock" - ], - "unmockedModulePathPatterns": [ - "/node_modules", - "/app" - ], - "moduleFileExtensions": [ - "js", - "jsx" - ] } } From c3bb614de03980a5d61afee852559e391bac6223 Mon Sep 17 00:00:00 2001 From: Alex Eng Date: Fri, 21 Jul 2017 07:53:44 +1000 Subject: [PATCH 098/116] fix: invalid data type --- .../src/main/resources/db/changelogs/db.changelog-4.2.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/zanata-war/src/main/resources/db/changelogs/db.changelog-4.2.xml b/server/zanata-war/src/main/resources/db/changelogs/db.changelog-4.2.xml index e60873b80f..94248aee0e 100644 --- a/server/zanata-war/src/main/resources/db/changelogs/db.changelog-4.2.xml +++ b/server/zanata-war/src/main/resources/db/changelogs/db.changelog-4.2.xml @@ -163,6 +163,6 @@ Alter TransMemory description, limit max length UPDATE TransMemory SET description=SUBSTRING(description,1,100); + newDataType="varchar(100)"/> From 07c22bb6e92f038511f98b162ed6eea929b3fe74 Mon Sep 17 00:00:00 2001 From: Alex Eng Date: Fri, 21 Jul 2017 09:54:41 +1000 Subject: [PATCH 099/116] fix: validate project name to be alphanumeric (#428) https://zanata.atlassian.net/browse/ZNTA-197 --- .../java/org/zanata/action/ProjectHome.java | 32 +++++++++++++++++++ .../src/main/resources/messages.properties | 1 + .../WEB-INF/layout/project/edit_form.xhtml | 5 ++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/server/zanata-war/src/main/java/org/zanata/action/ProjectHome.java b/server/zanata-war/src/main/java/org/zanata/action/ProjectHome.java index 86cded07c3..27b900523b 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/ProjectHome.java +++ b/server/zanata-war/src/main/java/org/zanata/action/ProjectHome.java @@ -688,6 +688,28 @@ public void initialize() { } } + public void onProjectNameChange(ValueChangeEvent e) { + if (!isValidName((String) e.getNewValue())) { + String componentId = e.getComponent().getId(); + facesMessages.addToControl(componentId, + msgs.get("jsf.project.name.validation.alphanumeric")); + } + } + + /** + * Check the name by removing any whitespaces in the string and + * make sure it contains at least an alphanumeric char + */ + public boolean isValidName(String name) { + String trimmedName = StringUtils.deleteWhitespace(name); + for (char c : trimmedName.toCharArray()) { + if (Character.isDigit(c) || Character.isLetter(c)) { + return true; + } + } + return false; + } + public void verifySlugAvailable(ValueChangeEvent e) { String slug = (String) e.getNewValue(); validateSlug(slug, e.getComponent().getId()); @@ -740,6 +762,11 @@ public String update() { && !getSlug().equals(getInputSlugValue())) { getInstance().setSlug(getInputSlugValue()); } + if (!isValidName(getInstance().getName())) { + facesMessages.addGlobal(SEVERITY_ERROR, + msgs.get("jsf.project.name.validation.alphanumeric")); + return null; + } boolean softDeleted = false; if (getInstance().getStatus() == EntityStatus.OBSOLETE) { softDeleted = true; @@ -768,6 +795,11 @@ public String persist() { return null; } getInstance().setSlug(getInputSlugValue()); + if (!isValidName(getInstance().getName())) { + facesMessages.addGlobal(SEVERITY_ERROR, + msgs.get("jsf.project.name.validation.alphanumeric")); + return null; + } if (StringUtils.isEmpty(selectedProjectType) || selectedProjectType.equals("null")) { facesMessages.addGlobal(SEVERITY_ERROR, diff --git a/server/zanata-war/src/main/resources/messages.properties b/server/zanata-war/src/main/resources/messages.properties index 1524ebb278..062206b4a9 100644 --- a/server/zanata-war/src/main/resources/messages.properties +++ b/server/zanata-war/src/main/resources/messages.properties @@ -331,6 +331,7 @@ jsf.project.WebhookName=Webhook name jsf.project.WebhookType.label=Type jsf.project.InvalidUrl=Invalid URL: {0} jsf.project.DuplicateUrl=Same URL is already in the list. {0} +jsf.project.name.validation.alphanumeric=Project name must contain at least one alphanumeric character jsf.webhook.response.state={0}% {1} jsf.webhook.test.label=Test webhook jsf.webhook.test.tooltip=Fire a test event diff --git a/server/zanata-war/src/main/webapp/WEB-INF/layout/project/edit_form.xhtml b/server/zanata-war/src/main/webapp/WEB-INF/layout/project/edit_form.xhtml index 003785f997..9e53d7c958 100644 --- a/server/zanata-war/src/main/webapp/WEB-INF/layout/project/edit_form.xhtml +++ b/server/zanata-war/src/main/webapp/WEB-INF/layout/project/edit_form.xhtml @@ -47,7 +47,10 @@ #{msgs['jsf.ProjectName']} + value="#{projectHome.instance.name}" + valueChangeListener="#{projectHome.onProjectNameChange}"> + + From 36e3196614350e18eeb232f1d222a6ba646c7d74 Mon Sep 17 00:00:00 2001 From: Alex Eng Date: Fri, 21 Jul 2017 10:34:27 +1000 Subject: [PATCH 100/116] fix: handle exception when pull with project without content (#431) https://zanata.atlassian.net/browse/ZNTA-2098 --- .../org/zanata/client/commands/pull/RawPullCommand.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/client/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/RawPullCommand.java b/client/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/RawPullCommand.java index 91dff421fb..d3cb8652ff 100644 --- a/client/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/RawPullCommand.java +++ b/client/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/RawPullCommand.java @@ -232,9 +232,9 @@ public void run() throws IOException { private void pullDocForLocale(RawPullStrategy strat, String qualifiedDocName, String localDocName, String fileExtension, LocaleMapping locMapping, LocaleId locale) throws IOException { + Response response = null; try { - Response response = - fileResourceClient.downloadTranslationFile(getOpts() + response = fileResourceClient.downloadTranslationFile(getOpts() .getProj(), getOpts() .getProjectVersion(), locale.getId(), fileExtension, qualifiedDocName); @@ -264,6 +264,10 @@ private void pullDocForLocale(RawPullStrategy strat, } else { throw e; } + } finally { + if (response != null) { + response.close(); + } } } } From 52558cae9d1af44f117de912c1876f9a9a8bc02d Mon Sep 17 00:00:00 2001 From: Alex Eng Date: Fri, 21 Jul 2017 11:28:22 +1000 Subject: [PATCH 101/116] Query param doc (#412) * WIP: handle encoded doc id in rest api * feat: new resource endpoint for docId as query param * refactor: change api path to /resource refactor: change query param to docId test: include old and new endpoint test * fix: fix unit test --- .../main/java/org/zanata/rest/RestUtil.java | 19 +- .../service/AsynchronousProcessResource.java | 135 +++++++++-- .../rest/service/SourceDocResource.java | 163 ++++++++++++- .../rest/service/TranslatedDocResource.java | 111 ++++++++- .../MockAsynchronousProcessResource.java | 20 +- .../rest/service/MockSourceDocResource.java | 30 ++- .../service/MockTranslatedDocResource.java | 22 +- .../client/commands/pull/PullCommand.java | 15 +- .../client/commands/push/PushCommand.java | 45 ++-- .../org/zanata/client/MockServerRule.java | 27 ++- .../client/commands/push/PushCommandTest.java | 15 +- .../rest/client/AsyncProcessClient.java | 65 ++++- .../rest/client/SourceDocResourceClient.java | 60 ++++- .../rest/client/TransDocResourceClient.java | 35 ++- .../rest/client/AsyncProcessClientTest.java | 9 +- .../client/SourceDocResourceClientTest.java | 2 - .../org/zanata/util/ZanataRestCaller.java | 15 +- .../editor/service/StatisticsService.java | 4 +- .../AsynchronousProcessResourceService.java | 70 ++++-- .../rest/service/ProjectVersionService.java | 3 +- .../service/SourceDocResourceService.java | 102 ++++++-- .../service/TranslatedDocResourceService.java | 69 ++++-- .../org/zanata/rest/service/URIHelper.java | 38 --- .../org/zanata/rest/service/ZPathService.java | 64 +---- .../service/raw/AsyncResourceRestITCase.java | 121 +++++++++- .../raw/ResourceServiceRestITCase.java | 195 +++++++++++++-- .../SourceAndTranslationResourceRestBase.java | 222 +++++++++++++++++- .../raw/TranslationResourceRestITCase.java | 134 ++++++----- 28 files changed, 1424 insertions(+), 386 deletions(-) delete mode 100644 server/zanata-war/src/main/java/org/zanata/rest/service/URIHelper.java diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/RestUtil.java b/api/zanata-common-api/src/main/java/org/zanata/rest/RestUtil.java index 521199db32..ac63dfe8c2 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/RestUtil.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/RestUtil.java @@ -1,13 +1,24 @@ package org.zanata.rest; +import javax.ws.rs.core.Response; + public class RestUtil { - public static String convertToDocumentURIId(String id) { + public static String convertToDocumentURIId(String docId) { // NB this currently prevents us from allowing ',' in file names - if (id.startsWith("/")) { - return id.substring(1).replace('/', ','); + if (docId.startsWith("/")) { + return docId.substring(1).replace('/', ','); } - return id.replace('/', ','); + return docId.replace('/', ','); + } + + public static String convertFromDocumentURIId(String docIdWithNoSlash) { + return docIdWithNoSlash.replace(',', '/'); + } + + public static boolean isNotFound(Response response) { + return response.getStatus() == + Response.Status.NOT_FOUND.getStatusCode(); } } diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/service/AsynchronousProcessResource.java b/api/zanata-common-api/src/main/java/org/zanata/rest/service/AsynchronousProcessResource.java index 9787da262e..1a9bff5ce9 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/service/AsynchronousProcessResource.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/service/AsynchronousProcessResource.java @@ -34,6 +34,8 @@ import javax.ws.rs.core.MediaType; import com.webcohesion.enunciate.metadata.rs.ResourceLabel; +import com.webcohesion.enunciate.metadata.rs.ResponseCode; +import com.webcohesion.enunciate.metadata.rs.StatusCodes; import org.zanata.common.LocaleId; import org.zanata.rest.dto.ProcessStatus; import org.zanata.rest.dto.resource.Resource; @@ -52,6 +54,10 @@ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @ResourceLabel("Asynchronous Process") +@StatusCodes({ + @ResponseCode(code = 500, + condition = "If there is an unexpected error in the server while performing this operation") +}) public interface AsynchronousProcessResource extends RestResource { public static final String SERVICE_PATH = "/async"; @@ -79,18 +85,16 @@ public interface AsynchronousProcessResource extends RestResource { * Boolean value that indicates whether reasonably close * translations from other projects should be found to initially * populate this document's translations. - * @return The following response status codes will be returned from this - * operation:
    - * OK(200) - The contents of the response will indicate the process - * identifier which may be used to query for its status or a message - * indicating what happened.
    - * INTERNAL SERVER ERROR(500) - If there is an unexpected error in - * the server while performing this operation. */ @POST @Path("/projects/p/{projectSlug}/iterations/i/{iterationSlug}/r") /* Same as SourceDocResourceService.SERVICE_PATH */ @TypeHint(ProcessStatus.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "The contents of the response will indicate the process" + + " identifier which may be used to query for its status or a message" + + " indicating what happened.") + }) @Deprecated public ProcessStatus startSourceDocCreation( @PathParam("id") String idNoSlash, @@ -123,19 +127,20 @@ public ProcessStatus startSourceDocCreation( * Boolean value that indicates whether reasonably close * translations from other projects should be found to initially * populate this document's translations. - * @return The following response status codes will be returned from this - * operation:
    - * OK(200) - The contents of the response will indicate the process - * identifier which may be used to query for its status or a message - * indicating what happened.
    - * INTERNAL SERVER ERROR(500) - If there is an unexpected error in - * the server while performing this operation. + * + * Deprecated. Use {@link #startSourceDocCreationOrUpdateWithDocId} */ + @Deprecated @PUT - @Path("/projects/p/{projectSlug}/iterations/i/{iterationSlug}/r" + @Path("/projects/p/{projectSlug}/iterations/i/{iterationSlug}" + SourceDocResource.RESOURCE_SLUG_TEMPLATE) /* Same as SourceDocResourceService.SERVICE_PATH */ @TypeHint(ProcessStatus.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "The contents of the response will indicate the process" + + " identifier which may be used to query for its status or a message" + + " indicating what happened.") + }) public ProcessStatus startSourceDocCreationOrUpdate( @PathParam("id") String idNoSlash, @PathParam("projectSlug") String projectSlug, @@ -143,6 +148,37 @@ public ProcessStatus startSourceDocCreationOrUpdate( Resource resource, @QueryParam("ext") Set extensions, @QueryParam("copyTrans") @DefaultValue("true") boolean copytrans); + /** + * Attempts to starts the creation or update of a source document. NOTE: + * Still experimental. + * + * @param docId + * The document identifier. + * @param projectSlug + * Project identifier. + * @param iterationSlug + * Project Iteration identifier. + * @param resource + * The document information. + * @param extensions + * The document extensions to save with the document (e.g. + * "gettext", "comment"). This parameter allows multiple values + * e.g. "ext=gettext&ext=comment". + */ + @PUT + @Path("/projects/p/{projectSlug}/iterations/i/{iterationSlug}/resource") + @TypeHint(ProcessStatus.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "The contents of the response will indicate the process" + + " identifier which may be used to query for its status or a message" + + " indicating what happened.") + }) + public ProcessStatus startSourceDocCreationOrUpdateWithDocId( + @PathParam("projectSlug") String projectSlug, + @PathParam("iterationSlug") String iterationSlug, + Resource resource, @QueryParam("ext") Set extensions, + @QueryParam("docId") @DefaultValue("") String docId); + /** * Attempts to start the translation of a document. NOTE: Still * experimental. @@ -175,18 +211,19 @@ public ProcessStatus startSourceDocCreationOrUpdate( * @param assignCreditToUploader * The translator field for all uploaded translations will * be set to the user who performs the upload. - * @return The following response status codes will be returned from this - * operation:
    - * OK(200) - The contents of the response will indicate the process - * identifier which may be used to query for its status or a message - * indicating what happened.
    - * INTERNAL SERVER ERROR(500) - If there is an unexpected error in - * the server while performing this operation. + * + * Deprecated. Use {@link #startTranslatedDocCreationOrUpdateWithDocId} */ + @Deprecated @PUT @Path("/projects/p/{projectSlug}/iterations/i/{iterationSlug}/r/{id}/translations/{locale}") /* Same as TranslatedDocResource.putTranslations */ @TypeHint(ProcessStatus.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "The contents of the response will indicate the process" + + " identifier which may be used to query for its status or a message" + + " indicating what happened.") + }) public ProcessStatus startTranslatedDocCreationOrUpdate( @PathParam("id") String idNoSlash, @@ -198,6 +235,54 @@ ProcessStatus startTranslatedDocCreationOrUpdate( @QueryParam("merge") String merge, @QueryParam("assignCreditToUploader") @DefaultValue("false") boolean assignCreditToUploader); + /** + * Attempts to start the translation of a document. NOTE: Still + * experimental. + * + * @param docId + * The document identifier. + * @param projectSlug + * Project identifier. + * @param iterationSlug + * Project Iteration identifier. + * @param locale + * The locale for which to get translations. + * @param translatedDoc + * The translations to modify. + * @param extensions + * The document extensions to save with the document (e.g. + * "gettext", "comment"). This parameter allows multiple values + * e.g. "ext=gettext&ext=comment". + * @param merge + * Indicates how to deal with existing translations (valid + * options: 'auto', 'import'). Import will overwrite all current + * values with the values being pushed (even empty ones), while + * Auto will check the history of your translations and will not + * overwrite any translations for which it detects a previous + * value is being pushed. + * @param assignCreditToUploader + * The translator field for all uploaded translations will + * be set to the user who performs the upload. + */ + @PUT + @Path("/projects/p/{projectSlug}/iterations/i/{iterationSlug}/resource/translations/{locale}") + /* Same as TranslatedDocResource.putTranslations */ + @TypeHint(ProcessStatus.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "The contents of the response will indicate the process" + + " identifier which may be used to query for its status or a message" + + " indicating what happened.") + }) + public ProcessStatus startTranslatedDocCreationOrUpdateWithDocId( + @PathParam("projectSlug") String projectSlug, + @PathParam("iterationSlug") String iterationSlug, + @PathParam("locale") LocaleId locale, + TranslationsResource translatedDoc, + @QueryParam("docId") @DefaultValue("") String docId, + @QueryParam("ext") Set extensions, + @QueryParam("merge") String merge, + @QueryParam("assignCreditToUploader") @DefaultValue("false") boolean assignCreditToUploader); + /** * Obtains the status of a previously started process. * @@ -215,6 +300,12 @@ ProcessStatus startTranslatedDocCreationOrUpdate( @GET @Path("/{processId}") @TypeHint(ProcessStatus.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = + "On normal circumstances. The response data will have" + + " all information about the status of the running process"), + @ResponseCode(code = 404, condition = "If such a process Id is not found on the server.") + }) public ProcessStatus getProcessStatus( @PathParam("processId") String processId); diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/service/SourceDocResource.java b/api/zanata-common-api/src/main/java/org/zanata/rest/service/SourceDocResource.java index 2a5561cc18..828f24d5b6 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/service/SourceDocResource.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/service/SourceDocResource.java @@ -58,15 +58,17 @@ @ResourceLabel("Source Documents") public interface SourceDocResource extends RestResource { @SuppressWarnings("deprecation") - String SERVICE_PATH = - ProjectIterationResource.SERVICE_PATH + "/r"; + String SERVICE_PATH = ProjectIterationResource.SERVICE_PATH; + String RESOURCE_PATH = "/r"; + String DOCID_RESOURCE_PATH = "/resource"; + String RESOURCE_SLUG_REGEX = "[\\-_a-zA-Z0-9]+([a-zA-Z0-9_\\-,{.}]*[a-zA-Z0-9]+)?"; String RESOURCE_NAME_REGEX = // as above, with ',' replaced by '/' "[\\-_a-zA-Z0-9]+([a-zA-Z0-9_\\-/{.}]*[a-zA-Z0-9]+)?"; - String RESOURCE_SLUG_TEMPLATE = "/{id:" - + RESOURCE_SLUG_REGEX + "}"; + String RESOURCE_SLUG_TEMPLATE = + RESOURCE_PATH + "/{id:" + RESOURCE_SLUG_REGEX + "}"; /** * Returns header information for a Project's iteration source strings. @@ -81,6 +83,7 @@ public interface SourceDocResource extends RestResource { * the server while performing this operation. */ @HEAD + @Path(RESOURCE_PATH) public Response head(); /** @@ -102,6 +105,7 @@ public interface SourceDocResource extends RestResource { * the server while performing this operation. */ @GET + @Path(RESOURCE_PATH) @TypeHint(ResourceMeta[].class) Response get(@QueryParam("ext") Set extensions); @@ -129,6 +133,7 @@ public interface SourceDocResource extends RestResource { * the server while performing this operation. */ @POST + @Path(RESOURCE_PATH) public Response post(Resource resource, @QueryParam("ext") Set extensions, @QueryParam("copyTrans") @DefaultValue("true") boolean copytrans); @@ -153,7 +158,9 @@ public Response post(Resource resource, * parameters.
    * INTERNAL SERVER ERROR(500) - If there is an unexpected error in * the server while performing this operation. + * Deprecated. Use {@link #getResourceWithDocId} */ + @Deprecated @GET @Path(RESOURCE_SLUG_TEMPLATE) // /r/{id} @@ -162,6 +169,30 @@ public Response post(Resource resource, Response getResource(@PathParam("id") String idNoSlash, @QueryParam("ext") Set extensions); + /** + * Retrieves information for a source Document. + * + * @param docId + * The document identifier. + * @param extensions + * The document extensions to fetch along with the document (e.g. + * "gettext", "comment"). This parameter allows multiple values + * e.g. "ext=gettext&ext=comment". + * @return The following response status codes will be returned from this + * operation:
    + * OK(200) - Response with the document's information.
    + * NOT FOUND(404) - If a document could not be found with the given + * parameters.
    + * INTERNAL SERVER ERROR(500) - If there is an unexpected error in + * the server while performing this operation. + */ + @GET + @TypeHint(Resource.class) + @Path(DOCID_RESOURCE_PATH) + public + Response getResourceWithDocId(@QueryParam("docId") @DefaultValue("") String docId, + @QueryParam("ext") Set extensions); + /** * Creates or modifies a source Document. * @@ -194,7 +225,10 @@ Response getResource(@PathParam("id") String idNoSlash, * permissions to perform this operation.
    * INTERNAL SERVER ERROR(500) - If there is an unexpected error in * the server while performing this operation. + * + * Deprecated. Use {@link #putResourceWithDocId} */ + @Deprecated @PUT @Path(RESOURCE_SLUG_TEMPLATE) // /r/{id} @@ -206,6 +240,44 @@ Response getResource(@PathParam("id") String idNoSlash, @QueryParam("ext") Set extensions, @QueryParam("copyTrans") @DefaultValue("true") boolean copytrans); + + /** + * Creates or modifies a source Document. + * + * @param docId + * The document identifier. + * @param resource + * The document information. + * @param extensions + * The document extensions to save with the document (e.g. + * "gettext", "comment"). This parameter allows multiple values + * e.g. "ext=gettext&ext=comment". + * @param copytrans + * Boolean value that indicates whether reasonably close + * translations from other projects should be found to initially + * populate this document's translations. + * @return The following response status codes will be returned from this + * operation:
    + * CREATED(201) - If a new document was successfully created.
    + * OK(200) - If an already existing document was modified.
    + * NOT FOUND(404) - If a project or project iteration could not be + * found with the given parameters.
    + * FORBIDDEN(403) - If the user is not allowed to modify the + * project, project iteration or document. This might be due to the + * project or iteration being in Read-Only mode.
    + * UNAUTHORIZED(401) - If the user does not have the proper + * permissions to perform this operation.
    + * INTERNAL SERVER ERROR(500) - If there is an unexpected error in + * the server while performing this operation. + */ + @PUT + @Path(DOCID_RESOURCE_PATH) + public Response putResourceWithDocId( + Resource resource, + @QueryParam("docId") @DefaultValue("") String docId, + @QueryParam("ext") Set extensions, + @QueryParam("copyTrans") @DefaultValue("true") boolean copytrans); + /** * Delete a source Document. The system keeps the history of this document however. * @@ -227,13 +299,39 @@ Response getResource(@PathParam("id") String idNoSlash, * permissions to perform this operation.
    * INTERNAL SERVER ERROR(500) - If there is an unexpected error in * the server while performing this operation. + * + * Deprecated. Use {@link #deleteResourceWithDocId} */ + @Deprecated @DELETE @Path(RESOURCE_SLUG_TEMPLATE) // /r/{id} public Response deleteResource(@PathParam("id") String idNoSlash); + /** + * Delete a source Document. The system keeps the history of this document however. + * + * @param docId + * The document identifier. + * @return The following response status codes will be returned from this + * operation:
    + * OK(200) - If The document was successfully deleted.
    + * NOT FOUND(404) - If a project or project iteration could not be + * found with the given parameters.
    + * FORBIDDEN(403) - If the user is not allowed to modify the + * project, project iteration or document. This might be due to the + * project or iteration being in Read-Only mode.
    + * UNAUTHORIZED(401) - If the user does not have the proper + * permissions to perform this operation.
    + * INTERNAL SERVER ERROR(500) - If there is an unexpected error in + * the server while performing this operation. + */ + @DELETE + @Path(DOCID_RESOURCE_PATH) + public Response deleteResourceWithDocId( + @QueryParam("docId") @DefaultValue("") String docId); + /** * Retrieves meta-data information for a source Document. * @@ -255,7 +353,10 @@ Response getResource(@PathParam("id") String idNoSlash, * could not be found with the given parameters.
    * INTERNAL SERVER ERROR(500) - If there is an unexpected error in * the server while performing this operation. + * + * Deprecated. Use {@link #getResourceMetaWithDocId} */ + @Deprecated @GET @Path(RESOURCE_SLUG_TEMPLATE + "/meta") // /r/{id}/meta @@ -264,6 +365,31 @@ Response getResource(@PathParam("id") String idNoSlash, Response getResourceMeta(@PathParam("id") String idNoSlash, @QueryParam("ext") Set extensions); + /** + * Retrieves meta-data information for a source Document. + * + * @param docId + * The document identifier. + * @param extensions + * The document extensions to retrieve with the document's + * meta-data (e.g. "gettext", "comment"). This parameter allows + * multiple values e.g. "ext=gettext&ext=comment". + * @return The following response status codes will be returned from this + * operation:
    + * OK(200) - If the Document's meta-data was found. The data will be + * contained in the response.
    + * NOT FOUND(404) - If a project, project iteration or document + * could not be found with the given parameters.
    + * INTERNAL SERVER ERROR(500) - If there is an unexpected error in + * the server while performing this operation. + */ + @GET + @Path(DOCID_RESOURCE_PATH + "/meta") + @TypeHint(ResourceMeta.class) + public Response getResourceMetaWithDocId( + @QueryParam("docId") @DefaultValue("") String docId, + @QueryParam("ext") Set extensions); + /** * Modifies an existing source document's meta-data. * @@ -288,7 +414,9 @@ Response getResourceMeta(@PathParam("id") String idNoSlash, * permissions to perform this operation.
    * INTERNAL SERVER ERROR(500) - If there is an unexpected error in * the server while performing this operation. + * Deprecated. Use {@link #putResourceMetaWithDocId} */ + @Deprecated @PUT @Path(RESOURCE_SLUG_TEMPLATE + "/meta") // /r/{id}/meta @@ -297,4 +425,31 @@ Response putResourceMeta(@PathParam("id") String idNoSlash, ResourceMeta messageBody, @QueryParam("ext") Set extensions); + /** + * Modifies an existing source document's meta-data. + * + * @param docId + * The document identifier. + * @param messageBody + * The document's meta-data. + * @param extensions + * The document extensions to save with the document (e.g. + * "gettext", "comment"). This parameter allows multiple values + * e.g. "ext=gettext&ext=comment". + * @return The following response status codes will be returned from this + * operation:
    + * OK(200) - If the Document's meta-data was successfully modified.
    + * NOT FOUND(404) - If a document was not found using the given + * parameters.
    + * UNAUTHORIZED(401) - If the user does not have the proper + * permissions to perform this operation.
    + * INTERNAL SERVER ERROR(500) - If there is an unexpected error in + * the server while performing this operation. + */ + @PUT + @Path(DOCID_RESOURCE_PATH + "/meta") + public Response putResourceMetaWithDocId(ResourceMeta messageBody, + @QueryParam("docId") @DefaultValue("") String docId, + @QueryParam("ext") Set extensions); + } diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/service/TranslatedDocResource.java b/api/zanata-common-api/src/main/java/org/zanata/rest/service/TranslatedDocResource.java index 2f4b40419f..a30ea6dbf1 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/service/TranslatedDocResource.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/service/TranslatedDocResource.java @@ -21,6 +21,7 @@ package org.zanata.rest.service; +import static org.zanata.rest.service.SourceDocResource.DOCID_RESOURCE_PATH; import static org.zanata.rest.service.SourceDocResource.RESOURCE_SLUG_TEMPLATE; import java.util.Set; @@ -68,8 +69,7 @@ }) public interface TranslatedDocResource extends RestResource { @SuppressWarnings("deprecation") - public static final String SERVICE_PATH = - ProjectIterationResource.SERVICE_PATH + "/r"; + public static final String SERVICE_PATH = ProjectIterationResource.SERVICE_PATH; /** * Retrieves a set of translations for a given locale. @@ -91,6 +91,7 @@ public interface TranslatedDocResource extends RestResource { * An Entity tag identifier. Based on this identifier (if * provided), the server will decide if it needs to send a * response to the client or not (See return section). + * Deprecated. Use {@link #getTranslationsWithDocId} */ @GET @Path(RESOURCE_SLUG_TEMPLATE + "/translations/{locale}") @@ -106,6 +107,7 @@ public interface TranslatedDocResource extends RestResource { " stored ETag, indicating that the last received response is still valid" + " and should be reused."), }) + @Deprecated public Response getTranslations(@PathParam("id") String idNoSlash, @PathParam("locale") LocaleId locale, @@ -113,6 +115,43 @@ Response getTranslations(@PathParam("id") String idNoSlash, @QueryParam("skeletons") boolean skeletons, @HeaderParam(HttpHeaderNames.IF_NONE_MATCH) String eTag); + /** + * Retrieves a set of translations for a given locale. + * + * @param docId + * The document identifier. + * @param locale + * The locale for which to get translations. + * @param extensions + * The translation extensions to retrieve (e.g. "comment"). This + * parameter allows multiple values. + * @param createSkeletons + * Indicates whether to generate untranslated entries or not. + * @param eTag + * An Entity tag identifier. Based on this identifier (if + * provided), the server will decide if it needs to send a + * response to the client or not (See return section). + */ + @GET + @Path(DOCID_RESOURCE_PATH + "/translations/{locale}") + @TypeHint(TranslationsResource.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Successfully retrieved translations. " + + "The translation data will be contained in the response."), + @ResponseCode(code = 404, condition = "The project, version, or document could" + + " not be found with the given parameters. Also, if no translations are" + + " found for the given document and locale."), + @ResponseCode(code = 304, condition = "If the provided ETag matches the server's" + + " stored ETag, indicating that the last received response is still valid" + + " and should be reused."), + }) + public Response getTranslationsWithDocId( + @PathParam("locale") LocaleId locale, + @QueryParam("docId") @DefaultValue("") String docId, + @QueryParam("ext") Set extensions, + @QueryParam("skeletons") boolean createSkeletons, + @HeaderParam(HttpHeaderNames.IF_NONE_MATCH) String eTag); + /** * Deletes a set of translations for a given locale. Also deletes any * extensions recorded for the translations in question. The system will @@ -126,7 +165,9 @@ Response getTranslations(@PathParam("id") String idNoSlash, * (','). * @param locale * The locale for which to get translations. + * Deprecated. Use {@link #deleteTranslationsWithDocId} */ + @Deprecated @DELETE @Path(RESOURCE_SLUG_TEMPLATE + "/translations/{locale}") @TypeHint(TypeHint.NO_CONTENT.class) @@ -142,6 +183,30 @@ Response getTranslations(@PathParam("id") String idNoSlash, Response deleteTranslations(@PathParam("id") String idNoSlash, @PathParam("locale") LocaleId locale); + /** + * Deletes a set of translations for a given locale. Also deletes any + * extensions recorded for the translations in question. The system will + * keep history of the translations. + * + * @param docId + * The document identifier. + * @param locale + * The locale for which to get translations. + */ + @DELETE + @Path(DOCID_RESOURCE_PATH + "/translations/{locale}") + @TypeHint(TypeHint.NO_CONTENT.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Successfully deleted the translations."), + @ResponseCode(code = 404, condition = "If a project, project iteration or document" + + " could not be found with the given parameters."), + @ResponseCode(code = 401, condition = "If the user does not have the proper" + + " permissions to perform this operation."), + }) + public Response deleteTranslationsWithDocId( + @PathParam("locale") LocaleId locale, + @QueryParam("docId") @DefaultValue("") String docId); + /** * Updates the translations for a document and a locale. * @@ -165,7 +230,9 @@ Response deleteTranslations(@PathParam("id") String idNoSlash, * Auto will check the history of your translations and will not * overwrite any translations for which it detects a previous * value is being pushed. + * Deprecated. Use {@link #putTranslationsWithDocId} */ + @Deprecated @PUT @Path(RESOURCE_SLUG_TEMPLATE + "/translations/{locale}") @StatusCodes({ @@ -187,4 +254,44 @@ Response putTranslations(@PathParam("id") String idNoSlash, @QueryParam("ext") Set extensions, @QueryParam("merge") @DefaultValue("auto") String merge); + /** + * Updates the translations for a document and a locale. + * + * @param docId + * The document identifier. + * @param locale + * The locale for which to get translations. + * @param messageBody + * The translations to modify. + * @param extensions + * The translation extension types to modify (e.g. "comment"). + * This parameter allows multiple values. + * @param merge + * Indicates how to deal with existing translations (valid + * options: 'auto', 'import'). Import will overwrite all current + * values with the values being pushed (even empty ones), while + * Auto will check the history of your translations and will not + * overwrite any translations for which it detects a previous + * value is being pushed. + */ + @PUT + @Path(DOCID_RESOURCE_PATH + "/translations/{locale}") + @StatusCodes({ + @ResponseCode(code = 200, condition = "Translations were successfully updated."), + @ResponseCode(code = 404, condition = "If a project, project iteration or document" + + " could not be found with the given parameters."), + @ResponseCode(code = 401, condition = "If the user does not have the proper" + + " permissions to perform this operation."), + @ResponseCode(code = 400, condition = "If there are problems with the passed parameters." + + " e.g. Merge type is not one of the accepted types. This response should have a" + + " content message indicating a reason.", + type = @TypeHint(String.class)) + }) + public Response putTranslationsWithDocId( + @PathParam("locale") LocaleId locale, + TranslationsResource messageBody, + @QueryParam("docId") @DefaultValue("") String docId, + @QueryParam("ext") Set extensions, + @QueryParam("merge") @DefaultValue("auto") String merge); + } diff --git a/client/stub-server/src/main/java/org/zanata/rest/service/MockAsynchronousProcessResource.java b/client/stub-server/src/main/java/org/zanata/rest/service/MockAsynchronousProcessResource.java index b59074a6c8..fa5d4a5290 100644 --- a/client/stub-server/src/main/java/org/zanata/rest/service/MockAsynchronousProcessResource.java +++ b/client/stub-server/src/main/java/org/zanata/rest/service/MockAsynchronousProcessResource.java @@ -40,7 +40,6 @@ public class MockAsynchronousProcessResource implements private static final long serialVersionUID = 8841332691985560066L; @Override - @SuppressWarnings("deprecation") // TODO: remove this test when parent method is removed public ProcessStatus startSourceDocCreation(String idNoSlash, String projectSlug, String iterationSlug, Resource resource, @@ -52,6 +51,14 @@ public ProcessStatus startSourceDocCreation(String idNoSlash, public ProcessStatus startSourceDocCreationOrUpdate(String idNoSlash, String projectSlug, String iterationSlug, Resource resource, Set extensions, @DefaultValue("true") boolean copytrans) { + return startSourceDocCreationOrUpdateWithDocId(projectSlug, + iterationSlug, resource, extensions, idNoSlash); + } + + @Override + public ProcessStatus startSourceDocCreationOrUpdateWithDocId( + String projectSlug, String iterationSlug, Resource resource, + Set extensions, String docId) { ProcessStatus processStatus = new ProcessStatus(); processStatus.setStatusCode(ProcessStatus.ProcessStatusCode.Running); processStatus.setPercentageComplete(50); @@ -64,6 +71,17 @@ public ProcessStatus startTranslatedDocCreationOrUpdate(String idNoSlash, String projectSlug, String iterationSlug, LocaleId locale, TranslationsResource translatedDoc, Set extensions, String merge, @DefaultValue("false") boolean myTrans) { + return startTranslatedDocCreationOrUpdateWithDocId(projectSlug, + iterationSlug, locale, translatedDoc, idNoSlash, extensions, + merge, myTrans); + } + + @Override + public ProcessStatus startTranslatedDocCreationOrUpdateWithDocId( + String projectSlug, String iterationSlug, LocaleId locale, + TranslationsResource translatedDoc, String docId, + Set extensions, + String merge, boolean assignCreditToUploader) { ProcessStatus processStatus = new ProcessStatus(); processStatus.setStatusCode(ProcessStatus.ProcessStatusCode.Running); processStatus.setPercentageComplete(50); diff --git a/client/stub-server/src/main/java/org/zanata/rest/service/MockSourceDocResource.java b/client/stub-server/src/main/java/org/zanata/rest/service/MockSourceDocResource.java index 9da43d3a3a..071cd19c62 100644 --- a/client/stub-server/src/main/java/org/zanata/rest/service/MockSourceDocResource.java +++ b/client/stub-server/src/main/java/org/zanata/rest/service/MockSourceDocResource.java @@ -66,30 +66,58 @@ public Response post(Resource resource, Set extensions, @Override public Response getResource(String idNoSlash, Set extensions) { + return getResourceWithDocId(idNoSlash, extensions); + } + + @Override + public Response getResourceWithDocId(String docId, Set extensions) { MockResourceUtil.validateExtensions(extensions); - return Response.ok(new Resource(idNoSlash)).build(); + return Response.ok(new Resource(docId)).build(); } @Override public Response putResource(String idNoSlash, Resource resource, Set extensions, @DefaultValue("true") boolean copyTrans) { + return putResourceWithDocId(resource, idNoSlash, extensions, copyTrans); + } + + @Override + public Response putResourceWithDocId(Resource resource, String docId, + Set extensions, boolean copytrans) { MockResourceUtil.validateExtensions(extensions); return Response.ok(resource.getName()).build(); } @Override public Response deleteResource(String idNoSlash) { + return deleteResourceWithDocId(idNoSlash); + } + + @Override + public Response deleteResourceWithDocId(String docId) { return Response.ok().build(); } @Override public Response getResourceMeta(String idNoSlash, Set extensions) { + return getResourceMetaWithDocId(idNoSlash, extensions); + } + + @Override + public Response getResourceMetaWithDocId(String docId, + Set extensions) { return MockResourceUtil.notUsedByClient(); } @Override public Response putResourceMeta(String idNoSlash, ResourceMeta resourceMeta, Set extensions) { + return putResourceMetaWithDocId(resourceMeta, idNoSlash, extensions); + } + + @Override + public Response putResourceMetaWithDocId(ResourceMeta messageBody, + String docId, Set extensions) { return MockResourceUtil.notUsedByClient(); } } diff --git a/client/stub-server/src/main/java/org/zanata/rest/service/MockTranslatedDocResource.java b/client/stub-server/src/main/java/org/zanata/rest/service/MockTranslatedDocResource.java index f0e18ce148..07c11594b0 100644 --- a/client/stub-server/src/main/java/org/zanata/rest/service/MockTranslatedDocResource.java +++ b/client/stub-server/src/main/java/org/zanata/rest/service/MockTranslatedDocResource.java @@ -44,14 +44,26 @@ public class MockTranslatedDocResource implements TranslatedDocResource { public Response getTranslations(String idNoSlash, LocaleId locale, Set extensions, boolean createSkeletons, @HeaderParam("If-None-Match") String eTag) { + return getTranslationsWithDocId(locale, idNoSlash, extensions, + createSkeletons, eTag); + } + + @Override + public Response getTranslationsWithDocId(LocaleId locale, String docId, + Set extensions, boolean createSkeletons, String eTag) { MockResourceUtil.validateExtensions(extensions); TranslationsResource transResource = new TranslationsResource(); - transResource.getTextFlowTargets().add(new TextFlowTarget(idNoSlash)); + transResource.getTextFlowTargets().add(new TextFlowTarget(docId)); return Response.ok(transResource).build(); } @Override public Response deleteTranslations(String idNoSlash, LocaleId locale) { + return deleteTranslationsWithDocId(locale, idNoSlash); + } + + @Override + public Response deleteTranslationsWithDocId(LocaleId locale, String docId) { return MockResourceUtil.notUsedByClient(); } @@ -59,6 +71,14 @@ public Response deleteTranslations(String idNoSlash, LocaleId locale) { public Response putTranslations(String idNoSlash, LocaleId locale, TranslationsResource messageBody, Set extensions, @DefaultValue("auto") String merge) { + return putTranslationsWithDocId(locale, messageBody, idNoSlash, + extensions, merge); + } + + @Override + public Response putTranslationsWithDocId(LocaleId locale, + TranslationsResource messageBody, String docId, Set extensions, + String merge) { // used by PublicanPush only MockResourceUtil.validateExtensions(extensions); return Response.ok().build(); diff --git a/client/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/PullCommand.java b/client/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/PullCommand.java index ca35680c71..c243778be5 100644 --- a/client/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/PullCommand.java +++ b/client/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/PullCommand.java @@ -10,7 +10,6 @@ import java.util.SortedSet; import java.util.TreeSet; -import javax.ws.rs.NotFoundException; import javax.ws.rs.client.ResponseProcessingException; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; @@ -26,7 +25,6 @@ import org.zanata.client.exceptions.ConfigException; import org.zanata.common.LocaleId; import org.zanata.common.io.FileDetails; -import org.zanata.rest.RestUtil; import org.zanata.rest.client.RestClientFactory; import org.zanata.rest.dto.resource.Resource; import org.zanata.rest.dto.resource.TranslationsResource; @@ -225,12 +223,9 @@ && getOpts().getPullType() == PushPullType.Source) { try { Resource doc = null; String localDocName = unqualifiedDocName(qualifiedDocName); - // TODO follow a Link instead of generating the URI - String docUri = - RestUtil.convertToDocumentURIId(qualifiedDocName); boolean createSkeletons = getOpts().getCreateSkeletons(); if (strat.needsDocToWriteTrans() || pullSrc || createSkeletons) { - doc = sourceDocResourceClient.getResource(docUri, + doc = sourceDocResourceClient.getResource(qualifiedDocName, strat.getExtensions()); doc.setName(localDocName); } @@ -247,7 +242,7 @@ && getOpts().getPullType() == PushPullType.Source) { locMapping); if (shouldPullThisLocale(optionalStats, localDocName, locale)) { - pullDocForLocale(strat, doc, localDocName, docUri, + pullDocForLocale(strat, doc, localDocName, qualifiedDocName, createSkeletons, locMapping, transFile); } else { skippedLocales.add(locale); @@ -290,7 +285,7 @@ && getOpts().getPullType() == PushPullType.Source) { @VisibleForTesting protected void pullDocForLocale(PullStrategy strat, Resource doc, - String localDocName, String docUri, boolean createSkeletons, + String localDocName, String docId, boolean createSkeletons, LocaleMapping locMapping, File transFile) throws IOException { LocaleId locale = new LocaleId(locMapping.getLocale()); @@ -313,7 +308,7 @@ protected void pullDocForLocale(PullStrategy strat, Resource doc, Response transResponse; try { - transResponse = transDocResourceClient.getTranslations(docUri, + transResponse = transDocResourceClient.getTranslations(docId, locale, strat.getExtensions(), createSkeletons, eTag); } catch (ResponseProcessingException e) { @@ -352,7 +347,7 @@ protected void pullDocForLocale(PullStrategy strat, Resource doc, .getLocalFileMD5())) { transResponse = transDocResourceClient.getTranslations( - docUri, locale, + docId, locale, strat.getExtensions(), createSkeletons, null); // rewrite the target document diff --git a/client/zanata-client-commands/src/main/java/org/zanata/client/commands/push/PushCommand.java b/client/zanata-client-commands/src/main/java/org/zanata/client/commands/push/PushCommand.java index 59d3ced6ad..13079c862b 100644 --- a/client/zanata-client-commands/src/main/java/org/zanata/client/commands/push/PushCommand.java +++ b/client/zanata-client-commands/src/main/java/org/zanata/client/commands/push/PushCommand.java @@ -15,7 +15,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.ws.rs.NotFoundException; import javax.ws.rs.client.ResponseProcessingException; import org.apache.commons.lang3.StringUtils; @@ -396,8 +395,6 @@ private void pushCurrentModule() throws IOException, RuntimeException { for (final String localDocName : docsToPush) { try { final String qualifiedDocName = qualifiedDocName(localDocName); - final String docUri = - RestUtil.convertToDocumentURIId(qualifiedDocName); final Resource srcDoc; if (strat.isTransOnly()) { srcDoc = null; @@ -407,7 +404,7 @@ private void pushCurrentModule() throws IOException, RuntimeException { debug(srcDoc); if (pushSource()) { - pushSrcDocToServer(docUri, srcDoc, extensions); + pushSrcDocToServer(qualifiedDocName, srcDoc, extensions); } } @@ -427,7 +424,7 @@ public void visit(LocaleMapping locale, localDocName, locale); return; } - pushTargetDocToServer(docUri, locale, + pushTargetDocToServer(qualifiedDocName, locale, qualifiedDocName, targetDoc, extensions); } @@ -553,20 +550,17 @@ private void deleteSourceDocsFromServer(List qualifiedDocNames) { } } - private void pushSrcDocToServer(final String docUri, final Resource srcDoc, + private void pushSrcDocToServer(final String docId, final Resource srcDoc, final StringSet extensions) { if (!getOpts().isDryRun()) { log.info("pushing source doc [name={} size={}] to server", srcDoc.getName(), srcDoc.getTextFlows().size()); ConsoleUtils.startProgressFeedback(); - // NB: Copy trans is set to false as using copy trans in this manner - // is deprecated. - // see PushCommand.copyTransForDocument ProcessStatus status = - asyncProcessClient.startSourceDocCreationOrUpdate(docUri, + asyncProcessClient.startSourceDocCreationOrUpdateWithDocId( getOpts().getProj(), getOpts().getProjectVersion(), - srcDoc, extensions, false); + srcDoc, extensions, docId); boolean waitForCompletion = true; @@ -594,10 +588,10 @@ private void pushSrcDocToServer(final String docUri, final Resource srcDoc, // try to submit the process again status = asyncProcessClient - .startSourceDocCreationOrUpdate(docUri, + .startSourceDocCreationOrUpdateWithDocId( getOpts().getProj(), getOpts() .getProjectVersion(), - srcDoc, extensions, false); + srcDoc, extensions, docId); ConsoleUtils .setProgressFeedbackMessage("Waiting for other clients ..."); break; @@ -672,7 +666,7 @@ public List splitIntoBatch(TranslationsResource doc, return targetDocList; } - private void pushTargetDocToServer(final String docUri, + private void pushTargetDocToServer(final String docId, LocaleMapping locale, final String localDocName, TranslationsResource targetDoc, final StringSet extensions) { if (!getOpts().isDryRun()) { @@ -685,12 +679,13 @@ private void pushTargetDocToServer(final String docUri, ConsoleUtils.startProgressFeedback(); ProcessStatus status = - asyncProcessClient.startTranslatedDocCreationOrUpdate( - docUri, getOpts().getProj(), getOpts() - .getProjectVersion(), - new LocaleId(locale.getLocale()), targetDoc, - extensions, getOpts().getMergeType(), - getOpts().isMyTrans()); + asyncProcessClient + .startTranslatedDocCreationOrUpdateWithDocId( + getOpts().getProj(), getOpts() + .getProjectVersion(), + new LocaleId(locale.getLocale()), targetDoc, + docId, extensions, getOpts().getMergeType(), + getOpts().isMyTrans()); boolean waitForCompletion = true; @@ -719,11 +714,12 @@ extensions, getOpts().getMergeType(), // try to submit the process again status = asyncProcessClient - .startTranslatedDocCreationOrUpdate(docUri, + .startTranslatedDocCreationOrUpdateWithDocId( getOpts().getProj(), getOpts() .getProjectVersion(), - new LocaleId(locale.getLocale()), - targetDoc, extensions, + new LocaleId( + locale.getLocale()), + targetDoc, docId, extensions, getOpts().getMergeType(), getOpts().isMyTrans()); ConsoleUtils @@ -759,8 +755,7 @@ extensions, getOpts().getMergeType(), private void deleteSourceDocFromServer(String qualifiedDocName) { if (!getOpts().isDryRun()) { log.info("deleting resource {} from server", qualifiedDocName); - String docUri = RestUtil.convertToDocumentURIId(qualifiedDocName); - sourceDocResourceClient.deleteResource(docUri); + sourceDocResourceClient.deleteResource(qualifiedDocName); } else { log.info( "deleting resource {} from server (skipped due to dry run)", diff --git a/client/zanata-client-commands/src/test/java/org/zanata/client/MockServerRule.java b/client/zanata-client-commands/src/test/java/org/zanata/client/MockServerRule.java index 31b5076e1e..65313a52d8 100644 --- a/client/zanata-client-commands/src/test/java/org/zanata/client/MockServerRule.java +++ b/client/zanata-client-commands/src/test/java/org/zanata/client/MockServerRule.java @@ -175,17 +175,17 @@ public PushCommand createPushCommand() { Collections.emptyList()); // this assumes async push is always success when( - asyncClient.startSourceDocCreationOrUpdate( - anyString(), - eq(pushOpts.getProj()), eq(pushOpts.getProjectVersion()), + asyncClient.startSourceDocCreationOrUpdateWithDocId( + eq(pushOpts.getProj()), + eq(pushOpts.getProjectVersion()), any(Resource.class), anySetOf(String.class), - eq(false))) + anyString())) .thenReturn(running); when( - asyncClient.startTranslatedDocCreationOrUpdate( - docIdCaptor.capture(), eq(pushOpts.getProj()), + asyncClient.startTranslatedDocCreationOrUpdateWithDocId( + eq(pushOpts.getProj()), eq(pushOpts.getProjectVersion()), localeIdCaptor.capture(), - transResourceCaptor.capture(), + transResourceCaptor.capture(), docIdCaptor.capture(), extensionCaptor.capture(), eq(pushOpts.getMergeType()), eq(pushOpts.isMyTrans()))) .thenReturn(running); @@ -221,17 +221,18 @@ public ArgumentCaptor getTransResourceCaptor() { } public void verifyPushSource() { - verify(asyncClient).startSourceDocCreationOrUpdate( - docIdCaptor.capture(), eq(pushOpts.getProj()), + verify(asyncClient).startSourceDocCreationOrUpdateWithDocId( + eq(pushOpts.getProj()), eq(pushOpts.getProjectVersion()), resourceCaptor.capture(), - extensionCaptor.capture(), eq(false)); + extensionCaptor.capture(), docIdCaptor.capture()); } public void verifyPushTranslation() { - verify(asyncClient).startTranslatedDocCreationOrUpdate( - docIdCaptor.capture(), eq(pushOpts.getProj()), + verify(asyncClient).startTranslatedDocCreationOrUpdateWithDocId( + eq(pushOpts.getProj()), eq(pushOpts.getProjectVersion()), localeIdCaptor.capture(), - transResourceCaptor.capture(), extensionCaptor.capture(), + transResourceCaptor.capture(), docIdCaptor.capture(), + extensionCaptor.capture(), eq(pushOpts.getMergeType()), eq(pushOpts.isMyTrans())); } diff --git a/client/zanata-client-commands/src/test/java/org/zanata/client/commands/push/PushCommandTest.java b/client/zanata-client-commands/src/test/java/org/zanata/client/commands/push/PushCommandTest.java index a71a9e66a9..5a361f34d4 100644 --- a/client/zanata-client-commands/src/test/java/org/zanata/client/commands/push/PushCommandTest.java +++ b/client/zanata-client-commands/src/test/java/org/zanata/client/commands/push/PushCommandTest.java @@ -179,14 +179,14 @@ private void push(boolean pushTrans, boolean mapLocale) throws Exception { mockStatus.setStatusCode(ProcessStatus.ProcessStatusCode.Finished); mockStatus.setMessages(new ArrayList()); when( - asyncProcessClient.startSourceDocCreationOrUpdate( - eq("RPM"), anyString(), anyString(), - any(Resource.class), eq(extensionSet), eq(false))) + asyncProcessClient.startSourceDocCreationOrUpdateWithDocId( + anyString(), anyString(), any(Resource.class), + eq(extensionSet), eq("RPM"))) .thenReturn(mockStatus); when( - asyncProcessClient.startSourceDocCreationOrUpdate( - eq("sub,RPM"), anyString(), anyString(), - any(Resource.class), eq(extensionSet), eq(false))) + asyncProcessClient.startSourceDocCreationOrUpdateWithDocId( + anyString(), anyString(), any(Resource.class), + eq(extensionSet), eq("sub/RPM"))) .thenReturn(mockStatus); when(asyncProcessClient.getProcessStatus(anyString())) .thenReturn(mockStatus); @@ -208,10 +208,11 @@ private void push(boolean pushTrans, boolean mapLocale) throws Exception { } when( asyncProcessClient - .startTranslatedDocCreationOrUpdate(eq("RPM"), + .startTranslatedDocCreationOrUpdateWithDocId( anyString(), anyString(), eq(expectedLocale), any(TranslationsResource.class), + eq("RPM"), eq(extensionSet), eq("auto"), eq(false))). thenReturn(mockStatus); // when(mockTranslationResources.putTranslations(eq("RPM"), diff --git a/client/zanata-rest-client/src/main/java/org/zanata/rest/client/AsyncProcessClient.java b/client/zanata-rest-client/src/main/java/org/zanata/rest/client/AsyncProcessClient.java index a5c2d93e22..97d4068a5b 100644 --- a/client/zanata-rest-client/src/main/java/org/zanata/rest/client/AsyncProcessClient.java +++ b/client/zanata-rest-client/src/main/java/org/zanata/rest/client/AsyncProcessClient.java @@ -32,6 +32,7 @@ import javax.ws.rs.core.Response; import org.zanata.common.LocaleId; +import org.zanata.rest.RestUtil; import org.zanata.rest.dto.ProcessStatus; import org.zanata.rest.dto.resource.Resource; import org.zanata.rest.dto.resource.TranslationsResource; @@ -53,8 +54,6 @@ public class AsyncProcessClient implements AsynchronousProcessResource { } @Override - @SuppressWarnings("deprecation") - // TODO: remove this test when parent method is removed public ProcessStatus startSourceDocCreation(String idNoSlash, String projectSlug, String iterationSlug, Resource resource, Set extensions, @DefaultValue("true") boolean copytrans) { @@ -63,6 +62,7 @@ public ProcessStatus startSourceDocCreation(String idNoSlash, } @Override + @Deprecated public ProcessStatus startSourceDocCreationOrUpdate(String idNoSlash, String projectSlug, String iterationSlug, Resource resource, Set extensions, @DefaultValue("true") boolean copytrans) { @@ -82,6 +82,34 @@ public ProcessStatus startSourceDocCreationOrUpdate(String idNoSlash, } @Override + public ProcessStatus startSourceDocCreationOrUpdateWithDocId( + String projectSlug, String iterationSlug, Resource resource, + Set extensions, String docId) { + Client client = factory.getClient(); + WebTarget webResource = client.target(baseUri) + .path(AsynchronousProcessResource.SERVICE_PATH) + .path("projects").path("p").path(projectSlug) + .path("iterations").path("i").path(iterationSlug) + .path("resource"); + Response response = webResource + .queryParam("docId", docId) + .queryParam("ext", extensions.toArray()) + .request(MediaType.APPLICATION_XML_TYPE) + .put(Entity.xml(resource)); + if (RestUtil.isNotFound(response)) { + response.close(); + // fallback to old endpoint + String idNoSlash = RestUtil.convertToDocumentURIId(docId); + return startSourceDocCreationOrUpdate(idNoSlash, projectSlug, + iterationSlug, resource, extensions, false); + } else { + response.bufferEntity(); + return response.readEntity(ProcessStatus.class); + } + } + + @Override + @Deprecated public ProcessStatus startTranslatedDocCreationOrUpdate(String idNoSlash, String projectSlug, String iterationSlug, LocaleId locale, TranslationsResource translatedDoc, Set extensions, @@ -104,6 +132,39 @@ public ProcessStatus startTranslatedDocCreationOrUpdate(String idNoSlash, return response.readEntity(ProcessStatus.class); } + @Override + public ProcessStatus startTranslatedDocCreationOrUpdateWithDocId( + String projectSlug, String iterationSlug, LocaleId locale, + TranslationsResource translatedDoc, String docId, + Set extensions, + String merge, boolean assignCreditToUploader) { + Client client = factory.getClient(); + WebTarget webResource = client.target(baseUri) + .path(AsynchronousProcessResource.SERVICE_PATH) + .path("projects").path("p").path(projectSlug) + .path("iterations").path("i").path(iterationSlug) + .path("resource") + .path("translations").path(locale.toString()); + Response response = webResource + .queryParam("docid", docId) + .queryParam("ext", extensions.toArray()) + .queryParam("merge", merge) + .queryParam("assignCreditToUploader", String.valueOf(assignCreditToUploader)) + .request(MediaType.APPLICATION_XML_TYPE) + .put(Entity.xml(translatedDoc)); + if (RestUtil.isNotFound(response)) { + // fallback to old endpoint + response.close(); + String idNoSlash = RestUtil.convertToDocumentURIId(docId); + return startTranslatedDocCreationOrUpdate(idNoSlash, projectSlug, + iterationSlug, locale, translatedDoc, extensions, merge, + assignCreditToUploader); + } else { + response.bufferEntity(); + return response.readEntity(ProcessStatus.class); + } + } + @Override public ProcessStatus getProcessStatus(String processId) { return factory.getClient().target(baseUri) diff --git a/client/zanata-rest-client/src/main/java/org/zanata/rest/client/SourceDocResourceClient.java b/client/zanata-rest-client/src/main/java/org/zanata/rest/client/SourceDocResourceClient.java index e41a2cb5e3..e9bb04cd6c 100644 --- a/client/zanata-rest-client/src/main/java/org/zanata/rest/client/SourceDocResourceClient.java +++ b/client/zanata-rest-client/src/main/java/org/zanata/rest/client/SourceDocResourceClient.java @@ -32,6 +32,7 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import org.zanata.rest.RestUtil; import org.zanata.rest.dto.resource.Resource; import org.zanata.rest.dto.resource.ResourceMeta; @@ -61,7 +62,7 @@ public class SourceDocResourceClient { public List getResourceMeta(Set extensions) { Client client = factory.getClient(); - WebTarget webResource = getBaseServiceResource(client); + WebTarget webResource = getBaseServiceResource(client).path("r"); if (extensions != null) { webResource.queryParam("ext", extensions.toArray()); } @@ -74,38 +75,71 @@ private WebTarget getBaseServiceResource(Client client) { .path("projects").path("p") .path(project) .path("iterations").path("i") - .path(projectVersion) - .path("r"); + .path(projectVersion); } - public Resource getResource(String idNoSlash, Set extensions) { + public Resource getResource(String docId, Set extensions) { Client client = factory.getClient(); WebTarget webResource = getBaseServiceResource(client) - .path(idNoSlash) + .path("resource") + .queryParam("docId", docId) .queryParam("ext", extensions.toArray()); - return webResource.request(MediaType.APPLICATION_XML_TYPE) - .get(Resource.class); + Response response = webResource.request(MediaType.APPLICATION_XML_TYPE) + .get(); + if (RestUtil.isNotFound(response)) { + // fallback to old endpoint + response.close(); + String idNoSlash = RestUtil.convertToDocumentURIId(docId); + webResource = + getBaseServiceResource(client) + .path("r") + .path(idNoSlash) + .queryParam("ext", extensions.toArray()); + return webResource.request(MediaType.APPLICATION_XML_TYPE) + .get(Resource.class); + } + return response.readEntity(Resource.class); } - public String putResource(String idNoSlash, Resource resource, + public String putResource(String docId, Resource resource, Set extensions, boolean copyTrans) { Client client = factory.getClient(); - WebTarget webResource = getBaseServiceResource(client) - .path(idNoSlash) + WebTarget webResource = getBaseServiceResource(client).path("resource") + .queryParam("docId", docId) .queryParam("ext", extensions.toArray()) .queryParam("copyTrans", String.valueOf(copyTrans)); Response response = webResource.request(MediaType.APPLICATION_XML_TYPE) .put(Entity.entity(resource, MediaType.APPLICATION_XML_TYPE)); + if (RestUtil.isNotFound(response)) { + // fallback to old endpoint + response.close(); + String idNoSlash = RestUtil.convertToDocumentURIId(docId); + webResource = getBaseServiceResource(client) + .path("r") + .path(idNoSlash) + .queryParam("ext", extensions.toArray()) + .queryParam("copyTrans", String.valueOf(copyTrans)); + response = webResource.request(MediaType.APPLICATION_XML_TYPE) + .put(Entity.entity(resource, MediaType.APPLICATION_XML_TYPE)); + } response.bufferEntity(); return response.readEntity(String.class); } - public String deleteResource(String idNoSlash) { + public String deleteResource(String docId) { Client client = factory.getClient(); WebTarget webResource = getBaseServiceResource(client); - return webResource.path(idNoSlash).request().delete(String.class); + Response response = + webResource.path("resource").queryParam("docId", docId).request() + .delete(); + if (RestUtil.isNotFound(response)) { + response.close(); + String idNoSlash = RestUtil.convertToDocumentURIId(docId); + return webResource.path("r").path(idNoSlash).request() + .delete(String.class); + } + return response.readEntity(String.class); } - } diff --git a/client/zanata-rest-client/src/main/java/org/zanata/rest/client/TransDocResourceClient.java b/client/zanata-rest-client/src/main/java/org/zanata/rest/client/TransDocResourceClient.java index cc10fc86e2..d59a390ee5 100644 --- a/client/zanata-rest-client/src/main/java/org/zanata/rest/client/TransDocResourceClient.java +++ b/client/zanata-rest-client/src/main/java/org/zanata/rest/client/TransDocResourceClient.java @@ -30,6 +30,7 @@ import javax.ws.rs.core.Response; import org.zanata.common.LocaleId; +import org.zanata.rest.RestUtil; /** * This "implements" caller methods to endpoints in TranslatedDocResource. @@ -51,21 +52,34 @@ public class TransDocResourceClient { baseUri = factory.getBaseUri(); } - public Response getTranslations( - String idNoSlash, - LocaleId locale, - Set extensions, - boolean createSkeletons, - String eTag) { + public Response getTranslations(String docId, LocaleId locale, + Set extensions, boolean createSkeletons, String eTag) { Client client = factory.getClient(); - return getBaseServiceResource(client) - .path(idNoSlash) - .path("translations").path(locale.getId()) + Response response = getBaseServiceResource(client) + .path("resource") + .path("translations") + .path(locale.getId()) + .queryParam("docId", docId) .queryParam("ext", extensions.toArray()) .queryParam("skeletons", String.valueOf(createSkeletons)) .request(MediaType.APPLICATION_XML_TYPE) .header(HttpHeaders.IF_NONE_MATCH, eTag) .get(); + if (RestUtil.isNotFound(response)) { + // fallback to old endpoint + response.close(); + String idNoSlash = RestUtil.convertToDocumentURIId(docId); + response = getBaseServiceResource(client) + .path("r") + .path(idNoSlash) + .path("translations").path(locale.getId()) + .queryParam("ext", extensions.toArray()) + .queryParam("skeletons", String.valueOf(createSkeletons)) + .request(MediaType.APPLICATION_XML_TYPE) + .header(HttpHeaders.IF_NONE_MATCH, eTag) + .get(); + } + return response; } private WebTarget getBaseServiceResource(Client client) { @@ -73,8 +87,7 @@ private WebTarget getBaseServiceResource(Client client) { .path("projects").path("p") .path(project) .path("iterations").path("i") - .path(projectVersion) - .path("r"); + .path(projectVersion); } } diff --git a/client/zanata-rest-client/src/test/java/org/zanata/rest/client/AsyncProcessClientTest.java b/client/zanata-rest-client/src/test/java/org/zanata/rest/client/AsyncProcessClientTest.java index bf9730be0c..5a39d4984d 100644 --- a/client/zanata-rest-client/src/test/java/org/zanata/rest/client/AsyncProcessClientTest.java +++ b/client/zanata-rest-client/src/test/java/org/zanata/rest/client/AsyncProcessClientTest.java @@ -50,11 +50,11 @@ public void setUp() throws Exception { @Test public void testStartSourceDocCreationOrUpdate() throws Exception { ProcessStatus processStatus = - client.startSourceDocCreationOrUpdate("message", + client.startSourceDocCreationOrUpdateWithDocId( "about-fedora", "master", new Resource("message"), Sets.newHashSet("gettext"), - false); + "message"); assertThat(processStatus.getStatusCode(), Matchers.equalTo( ProcessStatus.ProcessStatusCode.Running)); @@ -63,10 +63,11 @@ public void testStartSourceDocCreationOrUpdate() throws Exception { @Test public void testStartTranslatedDocCreationOrUpdate() throws Exception { ProcessStatus processStatus = - client.startTranslatedDocCreationOrUpdate("message", + client.startTranslatedDocCreationOrUpdateWithDocId( "about-fedora", "master", LocaleId.DE, - new TranslationsResource(), Sets.newHashSet("gettext"), + new TranslationsResource(), "message", + Sets.newHashSet("gettext"), "auto", false); assertThat(processStatus.getStatusCode(), Matchers.equalTo( diff --git a/client/zanata-rest-client/src/test/java/org/zanata/rest/client/SourceDocResourceClientTest.java b/client/zanata-rest-client/src/test/java/org/zanata/rest/client/SourceDocResourceClientTest.java index eb4e1619b3..b6a1cebe00 100644 --- a/client/zanata-rest-client/src/test/java/org/zanata/rest/client/SourceDocResourceClientTest.java +++ b/client/zanata-rest-client/src/test/java/org/zanata/rest/client/SourceDocResourceClientTest.java @@ -54,7 +54,6 @@ public void setUp() throws URISyntaxException { @Test public void testGetResourceMeta() { List resourceMeta = client.getResourceMeta(null); - assertThat(resourceMeta, Matchers.hasSize(2)); } @@ -62,7 +61,6 @@ public void testGetResourceMeta() { public void testGetResource() { Resource resource = client.getResource("test", Sets.newHashSet("gettext", "comment")); - assertThat(resource.getName(), Matchers.equalTo("test")); } diff --git a/server/functional-test/src/test/java/org/zanata/util/ZanataRestCaller.java b/server/functional-test/src/test/java/org/zanata/util/ZanataRestCaller.java index 776e158947..c8102aa7b7 100644 --- a/server/functional-test/src/test/java/org/zanata/util/ZanataRestCaller.java +++ b/server/functional-test/src/test/java/org/zanata/util/ZanataRestCaller.java @@ -136,9 +136,9 @@ public ContainerTranslationStatistics getStatistics(String projectSlug, } public void putSourceDocResource(String projectSlug, String iterationSlug, - String idNoSlash, Resource resource, boolean copytrans) { + String id, Resource resource, boolean copytrans) { restClientFactory.getSourceDocResourceClient(projectSlug, iterationSlug) - .putResource(idNoSlash, resource, Collections.emptySet(), + .putResource(id, resource, Collections.emptySet(), copytrans); } @@ -204,9 +204,10 @@ public void asyncPushSource(String projectSlug, String iterationSlug, AsyncProcessClient asyncProcessClient = restClientFactory.getAsyncProcessClient(); ProcessStatus processStatus = - asyncProcessClient.startSourceDocCreationOrUpdate( - sourceResource.getName(), projectSlug, iterationSlug, - sourceResource, Sets.newHashSet(), false); + asyncProcessClient.startSourceDocCreationOrUpdateWithDocId( + projectSlug, iterationSlug, + sourceResource, Sets.newHashSet(), + sourceResource.getName()); processStatus = waitUntilFinished(asyncProcessClient, processStatus.getUrl()); log.info("finished async source push ({}-{}): {}", projectSlug, iterationSlug, processStatus.getStatusCode()); @@ -249,9 +250,9 @@ public void asyncPushTarget(String projectSlug, String iterationSlug, AsyncProcessClient asyncProcessClient = restClientFactory.getAsyncProcessClient(); ProcessStatus processStatus = - asyncProcessClient.startTranslatedDocCreationOrUpdate(docId, + asyncProcessClient.startTranslatedDocCreationOrUpdateWithDocId( projectSlug, iterationSlug, localeId, transResource, - Collections. emptySet(), mergeType, + docId, Collections. emptySet(), mergeType, assignCreditToUploader); processStatus = waitUntilFinished(asyncProcessClient, processStatus.getUrl()); log.info("finished async translation({}-{}) push: {}", projectSlug, diff --git a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/StatisticsService.java b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/StatisticsService.java index 94580ad173..ba411d3b1d 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/editor/service/StatisticsService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/editor/service/StatisticsService.java @@ -32,10 +32,10 @@ import org.zanata.common.LocaleId; import org.zanata.dao.DocumentDAO; import org.zanata.model.HDocument; +import org.zanata.rest.RestUtil; import org.zanata.rest.dto.stats.ContainerTranslationStatistics; import org.zanata.rest.dto.stats.TranslationStatistics; import org.zanata.rest.dto.stats.TranslationStatistics.StatUnit; -import org.zanata.rest.service.URIHelper; import org.zanata.rest.editor.service.resource.StatisticResource; import com.google.common.collect.Lists; @@ -56,7 +56,7 @@ public Response getDocumentStatistics( @PathParam("versionSlug") String versionSlug, @PathParam("docId") String docId, @PathParam("localeId") String localeId) { - docId = URIHelper.convertFromDocumentURIId(docId); + docId = RestUtil.convertFromDocumentURIId(docId); HDocument doc = documentDAO.getByProjectIterationAndDocId(projectSlug, versionSlug, docId); if (doc == null) { diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java index 11ece3a0ba..2b039bff87 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/AsynchronousProcessResourceService.java @@ -24,6 +24,8 @@ import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.inject.Named; + +import org.apache.commons.lang3.StringUtils; import org.apache.deltaspike.jpa.api.transaction.Transactional; import org.zanata.async.AsyncTaskHandle; import org.zanata.async.AsyncTaskHandleManager; @@ -38,6 +40,7 @@ import org.zanata.model.type.TranslationSourceType; import org.zanata.rest.NoSuchEntityException; import org.zanata.rest.ReadOnlyEntityException; +import org.zanata.rest.RestUtil; import org.zanata.rest.dto.ProcessStatus; import org.zanata.rest.dto.resource.Resource; import org.zanata.rest.dto.resource.TranslationsResource; @@ -46,8 +49,10 @@ import org.zanata.service.LocaleService; import org.zanata.service.TranslationService; +import javax.ws.rs.BadRequestException; import javax.ws.rs.NotFoundException; import javax.ws.rs.Path; + import static org.zanata.rest.dto.ProcessStatus.ProcessStatusCode; /** @@ -65,6 +70,7 @@ public class AsynchronousProcessResourceService implements AsynchronousProcessResource { private static final org.slf4j.Logger log = org.slf4j.LoggerFactory .getLogger(AsynchronousProcessResourceService.class); + private static final long serialVersionUID = -5915271018788588841L; @Inject private LocaleService localeServiceImpl; @@ -79,8 +85,6 @@ public class AsynchronousProcessResourceService @Inject private ProjectIterationDAO projectIterationDAO; @Inject - private ResourceUtils resourceUtils; - @Inject private ZanataIdentity identity; @Override @@ -92,7 +96,7 @@ public ProcessStatus startSourceDocCreation(final String idNoSlash, retrieveAndCheckIteration(projectSlug, iterationSlug, true); // Check permission identity.checkPermission(hProjectIteration, "import-template"); - resourceUtils.validateExtensions(extensions); // gettext, comment + ResourceUtils.validateExtensions(extensions); // gettext, comment HDocument document = documentDAO .getByDocIdAndIteration(hProjectIteration, resource.getName()); // already existing non-obsolete document. @@ -108,7 +112,7 @@ public ProcessStatus startSourceDocCreation(final String idNoSlash, } String name = "SourceDocCreation: " + projectSlug + "-" + iterationSlug + "-" + idNoSlash; - AsyncTaskHandle handle = new AsyncTaskHandle(); + AsyncTaskHandle handle = new AsyncTaskHandle<>(); String keyId = asyncTaskHandleManager.registerTaskHandle(handle); documentServiceImpl .saveDocumentAsync(projectSlug, iterationSlug, @@ -125,23 +129,41 @@ public ProcessStatus startSourceDocCreationOrUpdate(final String idNoSlash, final String projectSlug, final String iterationSlug, final Resource resource, final Set extensions, final boolean copytrans) { + String docId = RestUtil.convertFromDocumentURIId(idNoSlash); + return startSourceDocCreationOrUpdateProcess(projectSlug, + iterationSlug, resource, extensions, docId, copytrans); + } + + @Override + public ProcessStatus startSourceDocCreationOrUpdateWithDocId( + String projectSlug, String iterationSlug, Resource resource, + Set extensions, String docId) { + boolean copyTrans = false; + return startSourceDocCreationOrUpdateProcess(projectSlug, + iterationSlug, resource, extensions, docId, copyTrans); + } + + private ProcessStatus startSourceDocCreationOrUpdateProcess( + String projectSlug, String iterationSlug, Resource resource, + Set extensions, String docId, boolean copyTrans) { + if (StringUtils.isBlank(docId)) { + throw new BadRequestException("missing id"); + } HProjectIteration hProjectIteration = retrieveAndCheckIteration(projectSlug, iterationSlug, true); - resourceUtils.validateExtensions(extensions); // gettext, comment + ResourceUtils.validateExtensions(extensions); // gettext, comment // Check permission identity.checkPermission(hProjectIteration, "import-template"); String name = "SourceDocCreationOrUpdate: " + projectSlug + "-" - + iterationSlug + "-" + idNoSlash; + + iterationSlug + "-" + docId; AsyncTaskHandle handle = new AsyncTaskHandle(); String keyId = asyncTaskHandleManager.registerTaskHandle(handle); documentServiceImpl .saveDocumentAsync(projectSlug, iterationSlug, resource, - extensions, copytrans, true, handle); + extensions, copyTrans, true, handle); logWhenUploadComplete(handle, name, keyId); return getProcessStatus(keyId); // TODO Change to return 202 - // Accepted, - // with a url to get the - // progress + // Accepted, with a url to get the progress } private void logWhenUploadComplete( @@ -176,12 +198,27 @@ public ProcessStatus startTranslatedDocCreationOrUpdate( final TranslationsResource translatedDoc, final Set extensions, final String merge, final boolean assignCreditToUploader) { + final String id = RestUtil.convertFromDocumentURIId(idNoSlash); + return startTranslatedDocCreationOrUpdateWithDocId(projectSlug, + iterationSlug, locale, translatedDoc, id, extensions, merge, + assignCreditToUploader); + } + + @Override + public ProcessStatus startTranslatedDocCreationOrUpdateWithDocId( + String projectSlug, String iterationSlug, LocaleId locale, + TranslationsResource translatedDoc, String docId, + Set extensions, + String merge, boolean assignCreditToUploader) { // check security (cannot be on @Restrict as it refers to method // parameters) identity.checkPermission("modify-translation", this.localeServiceImpl.getByLocaleId(locale), this.getSecuredIteration(projectSlug, iterationSlug) .getProject()); + if (StringUtils.isBlank(docId)) { + throw new BadRequestException("missing docId"); + } MergeType mergeType; try { mergeType = MergeType.valueOf(merge.toUpperCase()); @@ -191,20 +228,21 @@ public ProcessStatus startTranslatedDocCreationOrUpdate( status.getMessages().add("bad merge type " + merge); return status; } - final String id = URIHelper.convertFromDocumentURIId(idNoSlash); final MergeType finalMergeType = mergeType; - String taskName = "TranslatedDocUpload: "+projectSlug+"-"+iterationSlug+"-"+idNoSlash; - AsyncTaskHandle handle = new AsyncTaskHandle(); + String taskName = "TranslatedDocUpload: "+projectSlug+"-"+iterationSlug+"-"+ + docId; + AsyncTaskHandle handle = new AsyncTaskHandle<>(); String keyId = asyncTaskHandleManager.registerTaskHandle(handle); translationServiceImpl.translateAllInDocAsync(projectSlug, - iterationSlug, id, locale, translatedDoc, extensions, - finalMergeType, assignCreditToUploader, true, handle, - TranslationSourceType.API_UPLOAD); + iterationSlug, docId, locale, translatedDoc, extensions, + finalMergeType, assignCreditToUploader, true, handle, + TranslationSourceType.API_UPLOAD); logWhenUploadComplete(handle, taskName, keyId); return this.getProcessStatus(keyId); } @Override + @SuppressWarnings("rawtypes") public ProcessStatus getProcessStatus(String processId) { AsyncTaskHandle handle = asyncTaskHandleManager.getHandleByKeyId(processId); diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java index b547d3ea04..89889ba541 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/ProjectVersionService.java @@ -45,6 +45,7 @@ import org.zanata.model.HTextFlow; import org.zanata.rest.NoSuchEntityException; import org.zanata.rest.ReadOnlyEntityException; +import org.zanata.rest.RestUtil; import org.zanata.rest.dto.LocaleDetails; import org.zanata.rest.dto.ProcessStatus; import org.zanata.rest.dto.ProjectIteration; @@ -306,7 +307,7 @@ public Response getTransUnitStatus( if (StringUtils.isEmpty(noSlashDocId)) { return Response.status(Response.Status.NOT_FOUND).build(); } - String docId = URIHelper.convertFromDocumentURIId(noSlashDocId); + String docId = RestUtil.convertFromDocumentURIId(noSlashDocId); HDocument document = documentDAO .getByProjectIterationAndDocId(projectSlug, versionSlug, docId); if (document == null) { diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/SourceDocResourceService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/SourceDocResourceService.java index f4f878fc00..7c1016679a 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/SourceDocResourceService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/SourceDocResourceService.java @@ -35,9 +35,13 @@ import javax.ws.rs.core.GenericEntity; import javax.ws.rs.core.Request; import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriInfo; import javax.inject.Inject; import javax.inject.Named; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import org.apache.commons.lang3.StringUtils; import org.apache.deltaspike.jpa.api.transaction.Transactional; import org.zanata.common.EntityStatus; import org.zanata.common.LocaleId; @@ -51,6 +55,7 @@ import org.zanata.model.HTextFlow; import org.zanata.rest.NoSuchEntityException; import org.zanata.rest.ReadOnlyEntityException; +import org.zanata.rest.RestUtil; import org.zanata.rest.dto.resource.Resource; import org.zanata.rest.dto.resource.ResourceMeta; import org.zanata.rest.dto.resource.TextFlow; @@ -69,10 +74,13 @@ public class SourceDocResourceService implements SourceDocResource { private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SourceDocResourceService.class); + private static final long serialVersionUID = 7787405987851272827L; @Context + @SuppressFBWarnings(value = "SE_BAD_FIELD") private Request request; @Context + @SuppressFBWarnings(value = "SE_BAD_FIELD") private UriInfo uri; /** @@ -141,7 +149,7 @@ public Response post(Resource resource, Set extensions, boolean copytrans) { identity.checkPermission(getSecuredIteration(), "import-template"); HProjectIteration hProjectIteration = retrieveAndCheckIteration(true); - resourceUtils.validateExtensions(extensions); // gettext, comment + ResourceUtils.validateExtensions(extensions); // gettext, comment String resourceName = resource.getName(); if (!Pattern.matches(SourceDocResource.RESOURCE_NAME_REGEX, resourceName)) { @@ -176,20 +184,30 @@ public Response post(Resource resource, Set extensions, @Override public Response getResource(String idNoSlash, Set extensions) { + String id = RestUtil.convertFromDocumentURIId(idNoSlash); + return getResourceWithDocId(id, extensions); + } + + @Override + public Response getResourceWithDocId(String docId, Set extensions) { log.debug("start get resource"); - String id = URIHelper.convertFromDocumentURIId(idNoSlash); + if (StringUtils.isBlank(docId)) { + return Response.status(Response.Status.BAD_REQUEST) + .entity("missing id").build(); + } HProjectIteration hProjectIteration = retrieveAndCheckIteration(false); - resourceUtils.validateExtensions(extensions); - final Set extSet = new HashSet(extensions); + ResourceUtils.validateExtensions(extensions); + final Set extSet = new HashSet<>(extensions); EntityTag etag = eTagUtils.generateETagForDocument(hProjectIteration, - id, extSet); + docId, extSet); Response.ResponseBuilder response = request.evaluatePreconditions(etag); if (response != null) { return response.build(); } HDocument doc = - documentDAO.getByDocIdAndIteration(hProjectIteration, id); + documentDAO.getByDocIdAndIteration(hProjectIteration, docId); if (doc == null || doc.isObsolete()) { + // TODO: return Problem DTO, https://tools.ietf.org/html/rfc7807 return Response.status(Response.Status.NOT_FOUND) .entity("document not found").build(); } @@ -215,20 +233,33 @@ public Response getResource(String idNoSlash, Set extensions) { @Override public Response putResource(String idNoSlash, Resource resource, Set extensions, boolean copytrans) { + String id = RestUtil.convertFromDocumentURIId(idNoSlash); + return putResourceWithDocId(resource, id, extensions, copytrans); + } + + @Override + public Response putResourceWithDocId(Resource resource, String docId, + Set extensions, boolean copytrans) { identity.checkPermission(getSecuredIteration(), "import-template"); log.debug("start put resource"); - String id = URIHelper.convertFromDocumentURIId(idNoSlash); + if (StringUtils.isBlank(docId)) { + return Response.status(Response.Status.BAD_REQUEST) + .entity("missing docId").build(); + } Response.ResponseBuilder response; HProjectIteration hProjectIteration = retrieveAndCheckIteration(true); - resourceUtils.validateExtensions(extensions); + ResourceUtils.validateExtensions(extensions); HDocument document = - this.documentDAO.getByDocIdAndIteration(hProjectIteration, id); + this.documentDAO.getByDocIdAndIteration(hProjectIteration, + docId); if (document == null || document.isObsolete()) { - response = Response.created(uri.getAbsolutePath()); + response = Response.created( + UriBuilder.fromUri(uri.getAbsolutePath()) + .queryParam("docId", docId).build()); } else { response = Response.ok(); } - resource.setName(id); + resource.setName(docId); document = this.documentServiceImpl.saveDocument(projectSlug, iterationSlug, resource, extensions, copytrans); EntityTag etag = eTagUtils.generateETagForDocument(hProjectIteration, @@ -239,34 +270,53 @@ public Response putResource(String idNoSlash, Resource resource, @Override public Response deleteResource(String idNoSlash) { + String id = RestUtil.convertFromDocumentURIId(idNoSlash); + return deleteResourceWithDocId(id); + } + + @Override + public Response deleteResourceWithDocId(String docId) { identity.checkPermission(getSecuredIteration(), "import-template"); - String id = URIHelper.convertFromDocumentURIId(idNoSlash); + if (StringUtils.isBlank(docId)) { + return Response.status(Response.Status.BAD_REQUEST) + .entity("missing id").build(); + } HProjectIteration hProjectIteration = retrieveAndCheckIteration(true); EntityTag etag = eTagUtils.generateETagForDocument(hProjectIteration, - id, new HashSet()); + docId, new HashSet()); Response.ResponseBuilder response = request.evaluatePreconditions(etag); if (response != null) { return response.build(); } HDocument document = - documentDAO.getByDocIdAndIteration(hProjectIteration, id); + documentDAO.getByDocIdAndIteration(hProjectIteration, docId); documentServiceImpl.makeObsolete(document); return Response.ok().build(); } @Override public Response getResourceMeta(String idNoSlash, Set extensions) { + String id = RestUtil.convertFromDocumentURIId(idNoSlash); + return getResourceMetaWithDocId(id, extensions); + } + + @Override + public Response getResourceMetaWithDocId(String docId, + Set extensions) { log.debug("start to get resource meta"); - String id = URIHelper.convertFromDocumentURIId(idNoSlash); + if (StringUtils.isBlank(docId)) { + return Response.status(Response.Status.BAD_REQUEST) + .entity("missing id").build(); + } HProjectIteration hProjectIteration = retrieveAndCheckIteration(false); EntityTag etag = eTagUtils.generateETagForDocument(hProjectIteration, - id, extensions); + docId, extensions); Response.ResponseBuilder response = request.evaluatePreconditions(etag); if (response != null) { return response.build(); } HDocument doc = - documentDAO.getByDocIdAndIteration(hProjectIteration, id); + documentDAO.getByDocIdAndIteration(hProjectIteration, docId); if (doc == null) { return Response.status(Response.Status.NOT_FOUND) .entity("document not found").build(); @@ -283,12 +333,22 @@ public Response getResourceMeta(String idNoSlash, Set extensions) { @Override public Response putResourceMeta(String idNoSlash, ResourceMeta messageBody, Set extensions) { + String id = RestUtil.convertFromDocumentURIId(idNoSlash); + return putResourceMetaWithDocId(messageBody, id , extensions); + } + + @Override + public Response putResourceMetaWithDocId(ResourceMeta messageBody, + String docId, Set extensions) { identity.checkPermission(getSecuredIteration(), "import-template"); + if (StringUtils.isBlank(docId)) { + return Response.status(Response.Status.BAD_REQUEST) + .entity("missing id").build(); + } log.debug("start to put resource meta"); - String id = URIHelper.convertFromDocumentURIId(idNoSlash); HProjectIteration hProjectIteration = retrieveAndCheckIteration(true); EntityTag etag = eTagUtils.generateETagForDocument(hProjectIteration, - id, extensions); + docId, extensions); Response.ResponseBuilder response = request.evaluatePreconditions(etag); if (response != null) { return response.build(); @@ -296,7 +356,7 @@ public Response putResourceMeta(String idNoSlash, ResourceMeta messageBody, log.debug("pass evaluation"); log.debug("put resource meta: {}", messageBody); HDocument document = - documentDAO.getByDocIdAndIteration(hProjectIteration, id); + documentDAO.getByDocIdAndIteration(hProjectIteration, docId); if (document == null) { return Response.status(Response.Status.NOT_FOUND).build(); } @@ -310,7 +370,7 @@ public Response putResourceMeta(String idNoSlash, ResourceMeta messageBody, document.getRevision() + 1); if (changed) { documentDAO.flush(); - etag = eTagUtils.generateETagForDocument(hProjectIteration, id, + etag = eTagUtils.generateETagForDocument(hProjectIteration, docId, extensions); } log.debug("put resource meta successfully"); diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/TranslatedDocResourceService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/TranslatedDocResourceService.java index cc1a4299ab..844656a04f 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/TranslatedDocResourceService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/TranslatedDocResourceService.java @@ -20,7 +20,6 @@ */ package org.zanata.rest.service; -import java.util.HashSet; import java.util.List; import java.util.Set; import javax.enterprise.context.RequestScoped; @@ -40,12 +39,11 @@ import javax.inject.Named; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import org.apache.commons.lang3.StringUtils; import org.apache.deltaspike.jpa.api.transaction.Transactional; -import org.zanata.ApplicationConfiguration; import org.zanata.common.LocaleId; import org.zanata.common.MergeType; import org.zanata.dao.DocumentDAO; -import org.zanata.dao.ProjectDAO; import org.zanata.dao.ProjectIterationDAO; import org.zanata.dao.TextFlowTargetDAO; import org.zanata.model.HDocument; @@ -53,9 +51,9 @@ import org.zanata.model.HProjectIteration; import org.zanata.model.HTextFlowTarget; import org.zanata.model.type.TranslationSourceType; +import org.zanata.rest.RestUtil; import org.zanata.rest.dto.resource.TranslationsResource; import org.zanata.security.ZanataIdentity; -import org.zanata.service.CopyTransService; import org.zanata.service.LocaleService; import org.zanata.service.TranslationService; import com.google.common.base.Optional; @@ -71,6 +69,7 @@ public class TranslatedDocResourceService implements TranslatedDocResource { private static final org.slf4j.Logger log = org.slf4j.LoggerFactory .getLogger(TranslatedDocResourceService.class); + private static final long serialVersionUID = -5855787114970845084L; // security actions // private static final String ACTION_IMPORT_TEMPLATE = "import-template"; @@ -96,20 +95,19 @@ public class TranslatedDocResourceService implements TranslatedDocResource { @Context private MediaType requestContentType; @Context + @SuppressFBWarnings("SE_BAD_FIELD") private HttpHeaders headers; @Context + @SuppressFBWarnings("SE_BAD_FIELD") private Request request; @Context + @SuppressFBWarnings("SE_BAD_FIELD") private UriInfo uri; @Inject private ZanataIdentity identity; @Inject - private ApplicationConfiguration applicationConfiguration; - @Inject private ProjectIterationDAO projectIterationDAO; @Inject - private ProjectDAO projectDAO; - @Inject private DocumentDAO documentDAO; @Inject private TextFlowTargetDAO textFlowTargetDAO; @@ -118,8 +116,6 @@ public class TranslatedDocResourceService implements TranslatedDocResource { @Inject private ETagUtils eTagUtils; @Inject - private CopyTransService copyTransServiceImpl; - @Inject private RestSlugValidator restSlugValidator; @Inject private TranslationService translationServiceImpl; @@ -129,8 +125,19 @@ public class TranslatedDocResourceService implements TranslatedDocResource { @Override public Response getTranslations(String idNoSlash, LocaleId locale, Set extensions, boolean skeletons, String eTag) { + String id = RestUtil.convertFromDocumentURIId(idNoSlash); + return getTranslationsWithDocId(locale, id, extensions, skeletons, eTag); + } + + @Override + public Response getTranslationsWithDocId(LocaleId locale, String docId, + Set extensions, boolean createSkeletons, String eTag) { log.debug("start to get translation"); - String id = URIHelper.convertFromDocumentURIId(idNoSlash); + if (StringUtils.isBlank(docId)) { + // TODO: return Problem DTO, https://tools.ietf.org/html/rfc7807 + return Response.status(Response.Status.BAD_REQUEST) + .entity("missing id").build(); + } HProjectIteration hProjectIteration = restSlugValidator .retrieveAndCheckIteration(projectSlug, iterationSlug, false); HLocale hLocale = restSlugValidator.validateTargetLocale(locale, @@ -138,7 +145,7 @@ public Response getTranslations(String idNoSlash, LocaleId locale, ResourceUtils.validateExtensions(extensions); // Check Etag header EntityTag generatedEtag = eTagUtils.generateETagForTranslatedDocument( - hProjectIteration, id, hLocale); + hProjectIteration, docId, hLocale); List requestedEtagHeaders = headers.getRequestHeader(HttpHeaders.IF_NONE_MATCH); if (requestedEtagHeaders != null && !requestedEtagHeaders.isEmpty()) { @@ -151,7 +158,7 @@ public Response getTranslations(String idNoSlash, LocaleId locale, return response.build(); } HDocument document = - documentDAO.getByDocIdAndIteration(hProjectIteration, id); + documentDAO.getByDocIdAndIteration(hProjectIteration, docId); if (document == null || document.isObsolete()) { return Response.status(Status.NOT_FOUND).build(); } @@ -162,7 +169,7 @@ public Response getTranslations(String idNoSlash, LocaleId locale, boolean foundData = resourceUtils.transferToTranslationsResource( translationResource, document, hLocale, extensions, hTargets, Optional. absent()); - if (!foundData && !skeletons) { + if (!foundData && !createSkeletons) { return Response.status(Status.NOT_FOUND).build(); } // TODO lastChanged @@ -172,21 +179,30 @@ public Response getTranslations(String idNoSlash, LocaleId locale, @Override public Response deleteTranslations(String idNoSlash, LocaleId locale) { + String id = RestUtil.convertFromDocumentURIId(idNoSlash); + return deleteTranslationsWithDocId(locale, id); + } + + @Override + public Response deleteTranslationsWithDocId(LocaleId locale, String docId) { identity.checkPermission(getSecuredIteration().getProject(), "modify-translation"); - String id = URIHelper.convertFromDocumentURIId(idNoSlash); + if (StringUtils.isBlank(docId)) { + return Response.status(Response.Status.BAD_REQUEST) + .entity("missing id").build(); + } HProjectIteration hProjectIteration = restSlugValidator .retrieveAndCheckIteration(projectSlug, iterationSlug, true); HLocale hLocale = restSlugValidator.validateTargetLocale(locale, projectSlug, iterationSlug); EntityTag etag = eTagUtils.generateETagForTranslatedDocument( - hProjectIteration, id, hLocale); + hProjectIteration, docId, hLocale); ResponseBuilder response = request.evaluatePreconditions(etag); if (response != null) { return response.build(); } HDocument document = - documentDAO.getByDocIdAndIteration(hProjectIteration, id); + documentDAO.getByDocIdAndIteration(hProjectIteration, docId); if (document == null || document.isObsolete()) { return Response.status(Status.NOT_FOUND).build(); } @@ -205,12 +221,24 @@ public Response deleteTranslations(String idNoSlash, LocaleId locale) { public Response putTranslations(String idNoSlash, LocaleId locale, TranslationsResource messageBody, Set extensions, String merge) { + String id = RestUtil.convertFromDocumentURIId(idNoSlash); + return putTranslationsWithDocId(locale, messageBody, id, extensions, merge); + } + + @Override + public Response putTranslationsWithDocId(LocaleId locale, + TranslationsResource messageBody, String docId, Set extensions, + String merge) { // check security (cannot be on @Restrict as it refers to method // parameters) identity.checkPermission("modify-translation", this.localeServiceImpl.getByLocaleId(locale), this.getSecuredIteration().getProject()); log.debug("start put translations"); + if (StringUtils.isBlank(docId)) { + return Response.status(Response.Status.BAD_REQUEST) + .entity("missing id").build(); + } MergeType mergeType; try { mergeType = MergeType.valueOf(merge.toUpperCase()); @@ -218,13 +246,12 @@ public Response putTranslations(String idNoSlash, LocaleId locale, return Response.status(Status.BAD_REQUEST) .entity("bad merge type " + merge).build(); } - String id = URIHelper.convertFromDocumentURIId(idNoSlash); HProjectIteration hProjectIteration = projectIterationDAO.getBySlug(projectSlug, iterationSlug); HLocale hLocale = restSlugValidator.validateTargetLocale(locale, projectSlug, iterationSlug); EntityTag etag = eTagUtils.generateETagForTranslatedDocument( - hProjectIteration, id, hLocale); + hProjectIteration, docId, hLocale); ResponseBuilder response = request.evaluatePreconditions(etag); if (response != null) { return response.build(); @@ -233,12 +260,12 @@ public Response putTranslations(String idNoSlash, LocaleId locale, boolean assignCreditToUploader = false; // Translate List warnings = this.translationServiceImpl.translateAllInDoc( - projectSlug, iterationSlug, id, locale, messageBody, extensions, + projectSlug, iterationSlug, docId, locale, messageBody, extensions, mergeType, assignCreditToUploader, TranslationSourceType.API_UPLOAD); // Regenerate etag in case it has changed etag = eTagUtils.generateETagForTranslatedDocument(hProjectIteration, - id, hLocale); + docId, hLocale); log.debug("successful put translation"); // TODO lastChanged StringBuilder sb = new StringBuilder(); diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/URIHelper.java b/server/zanata-war/src/main/java/org/zanata/rest/service/URIHelper.java deleted file mode 100644 index f49a4d43d2..0000000000 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/URIHelper.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.zanata.rest.service; - -import org.zanata.rest.RestUtil; - -/** - * @see {@link ZPathService} - */ -public final class URIHelper { - - private URIHelper() { - } - - public static String getProject(String projectSlug) { - return "/projects/p/" + projectSlug; - } - - public static String getIteration(String projectSlug, String iterationSlug) { - return getProject(projectSlug) + "/iterations/i/" + iterationSlug; - } - - public static String getDocument(String projectSlug, String iterationSlug, - String documentId) { - return getIteration(projectSlug, iterationSlug) + "/r/" - + RestUtil.convertToDocumentURIId(documentId); - } - - public static String convertFromDocumentURIId(String uriId) { - return uriId.replace(',', '/'); - } - - /** - * @deprecated Use {@link RestUtil#convertToDocumentURIId(String)} instead - */ - public static String convertToDocumentURIId(String id) { - return RestUtil.convertToDocumentURIId(id); - } - -} diff --git a/server/zanata-war/src/main/java/org/zanata/rest/service/ZPathService.java b/server/zanata-war/src/main/java/org/zanata/rest/service/ZPathService.java index ad003ca916..8d3d825dd6 100644 --- a/server/zanata-war/src/main/java/org/zanata/rest/service/ZPathService.java +++ b/server/zanata-war/src/main/java/org/zanata/rest/service/ZPathService.java @@ -21,20 +21,11 @@ package org.zanata.rest.service; import java.io.Serializable; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; import java.text.MessageFormat; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.inject.Inject; import javax.inject.Named; -import org.zanata.dao.ProjectDAO; import org.zanata.model.HDocument; -import org.zanata.model.HProject; import org.zanata.model.HProjectIteration; -import org.zanata.model.validator.SlugValidator; -import org.zanata.rest.RestUtil; /** * Service that provides static services to build, parse and interpret Zanata @@ -49,12 +40,6 @@ // TODO this should probably be Transactional (and not Dependent) public class ZPathService implements Serializable { - /* - * Public ZPaths. Used for rest resource path declaration. - */ - public static final String PROJECT_ZPATH = "/proj/" - + RestConstants.SLUG_PATTERN; - /* * Private ZPaths. Mainly used for generation. */ @@ -62,31 +47,7 @@ public class ZPathService implements Serializable { private static final String PROJECT_ITER_ZPATH_PRIVATE = PROJECT_ZPATH_PRIVATE + "/iterations/i/{1}"; private static final String DOCUMENT_ZPATH_PRIVATE = - PROJECT_ITER_ZPATH_PRIVATE + "/r/{2}"; - - /* - * Internal utilities based on the public ZPaths - */ - private static final Pattern PROJECT_ZPATH_PATTERN = Pattern - .compile(PROJECT_ZPATH); - - @Inject - private ProjectDAO projectDAO; - - public HProject resolveProject(String zPath) { - Matcher projMatcher = PROJECT_ZPATH_PATTERN.matcher(zPath); - if (projMatcher.matches()) { - String projectSlug = projMatcher.group(1); // Group 1, project slug - return projectDAO.getBySlug(projectSlug); - } else { - return null; - } - } - - public String generatePathForProject(HProject project) { - MessageFormat mssgFormat = new MessageFormat(PROJECT_ZPATH_PRIVATE); - return mssgFormat.format(project.getSlug()); - } + PROJECT_ITER_ZPATH_PRIVATE + "/resource?docId={2}"; public String generatePathForProjectIteration(HProjectIteration iteration) { MessageFormat mssgFormat = @@ -96,27 +57,10 @@ public String generatePathForProjectIteration(HProjectIteration iteration) { } public String generatePathForDocument(HDocument document) { - String docIdNoSlash = null; - try { - docIdNoSlash = - URLEncoder.encode(RestUtil.convertToDocumentURIId(document - .getDocId()), "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - MessageFormat mssgFormat = new MessageFormat(DOCUMENT_ZPATH_PRIVATE); - return mssgFormat.format(new Object[] { + return mssgFormat.format(new Object[]{ document.getProjectIteration().getProject().getSlug(), - document.getProjectIteration().getSlug(), docIdNoSlash }); - } - - public Object resolve(String zPath) { - Matcher projMatcher = PROJECT_ZPATH_PATTERN.matcher(zPath); - if (projMatcher.matches()) { - return resolveProject(zPath); - } - - return null; + document.getProjectIteration().getSlug(), document + .getDocId()}); } } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AsyncResourceRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AsyncResourceRestITCase.java index 60e77a0f34..7e13f4cfa0 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AsyncResourceRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AsyncResourceRestITCase.java @@ -71,7 +71,8 @@ protected void prepareDBUnitOperations() { @Test @RunAsClient - public void testPutGetResourceWithExtension() throws Exception { + @Deprecated + public void testPutGetResourceWithExtensionDeprecate() throws Exception { final Resource resource = resourceTestFactory.getTextFlowTest(); final AtomicReference processId = new AtomicReference<>(null); new ResourceRequest( @@ -141,7 +142,78 @@ protected void onResponse(Response response) { @Test @RunAsClient - public void testPutGetTranslationWithExtension() throws Exception { + public void testPutGetResourceWithExtension() throws Exception { + final Resource resource = resourceTestFactory.getTextFlowTest(); + final AtomicReference processId = new AtomicReference<>(null); + new ResourceRequest( + getRestEndpointUrl( + "async/projects/p/sample-project/iterations/i/1.0/resource"), + "PUT", getAuthorizedEnvironment()) { + + @Override + protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { + return webTarget.queryParam("docId", resource.getName()). + queryParam("ext", "gettext"). + queryParam("ext", "comment"). + queryParam("copyTrans", false).request(); + } + + @Override + public void invoke(Invocation.Builder builder) { + Entity entity = Entity + .entity(jaxbMarhsal(resource), MediaType.APPLICATION_XML_TYPE); + Response response = builder.buildPut(entity).invoke(); + onResponse(response); + } + + + @Override + protected void onResponse(Response response) { + assertThat(response.getStatus(), is(200)); + String entityString = response.readEntity(String.class); + + assertJaxbUnmarshal(entityString, ProcessStatus.class); + ProcessStatus status = + jaxbUnmarshal(entityString, ProcessStatus.class); + assertThat(status.getUrl(), is(notNullValue())); + processId.set(status.getUrl()); + } + }.run(); + waitAtMost(Duration.TEN_SECONDS).catchUncaughtExceptions() + .pollInterval(Duration.ONE_SECOND) + .until(asyncPushFinishCallable(processId.get())); + new ResourceRequest( + getRestEndpointUrl( + "projects/p/sample-project/iterations/i/1.0/r/" + + resource.getName()), + "GET", getAuthorizedEnvironment()) { + + @Override + protected Invocation.Builder prepareRequest( + ResteasyWebTarget webTarget) { + return webTarget.queryParam("ext", "gettext"). + queryParam("ext", "comment").request(); + } + + @Override + protected void onResponse(Response response) { + assertThat(response.getStatus(), is(200)); + String entityString = response.readEntity(String.class); + Resource get = jaxbUnmarshal(entityString, Resource.class); + Resource base = resourceTestFactory.getTextFlowTest(); + ResourceTestUtil.clearRevs(base); + ResourceTestUtil.clearRevs(get); + log.debug("expect:" + base.toString()); + log.debug("actual:" + get.toString()); + assertThat(get.toString(), is(base.toString())); + } + }.run(); + } + + @Test + @RunAsClient + @Deprecated + public void testPutGetTranslationWithExtensionDeprecate() throws Exception { final TranslationsResource resource = translationTestFactory.getTextFlowTargetCommentTest(); final AtomicReference processId = new AtomicReference<>(null); @@ -183,6 +255,51 @@ protected void onResponse(Response response) { .until(asyncPushFinishCallable(processId.get())); } + @Test + @RunAsClient + public void testPutGetTranslationWithExtension() throws Exception { + final TranslationsResource resource = + translationTestFactory.getTextFlowTargetCommentTest(); + final AtomicReference processId = new AtomicReference<>(null); + new ResourceRequest( + getRestEndpointUrl( + "async/projects/p/sample-project/iterations/i/1.0/resource/translations/en"), + "PUT", getAuthorizedEnvironment()) { + + @Override + protected Invocation.Builder prepareRequest( + ResteasyWebTarget webTarget) { + return webTarget.queryParam("docId", "my/path/document.txt"). + queryParam("ext", "gettext"). + queryParam("ext", "comment"). + queryParam("merge", "auto").request(); + } + + @Override + public void invoke(Invocation.Builder builder) { + Entity entity = Entity + .entity(jaxbMarhsal(resource), + MediaType.APPLICATION_XML_TYPE); + Response response = builder.buildPut(entity).invoke(); + onResponse(response); + } + + @Override + protected void onResponse(Response response) { + assertThat(response.getStatus(), is(200)); + String entityString = response.readEntity(String.class); + assertJaxbUnmarshal(entityString, ProcessStatus.class); + ProcessStatus status = + jaxbUnmarshal(entityString, ProcessStatus.class); + assertThat(status.getUrl(), is(notNullValue())); + processId.set(status.getUrl()); + } + }.run(); + waitAtMost(Duration.TEN_SECONDS).catchUncaughtExceptions() + .pollInterval(Duration.ONE_SECOND) + .until(asyncPushFinishCallable(processId.get())); + } + private Callable asyncPushFinishCallable(final String processId) { return new Callable() { diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ResourceServiceRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ResourceServiceRestITCase.java index d5c9f89a12..e6c4905631 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ResourceServiceRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ResourceServiceRestITCase.java @@ -49,7 +49,8 @@ public void setUp() { @Test @RunAsClient - public void testPutGetResourceWithExtension() { + @SuppressWarnings("deprecation") + public void testPutGetResourceWithExtensionDeprecated() { log.debug("put resource:" + sr.toString()); getSourceDocResource().putResource(sr.getName(), sr, new StringSet( "gettext;comment"), false); @@ -64,7 +65,23 @@ public void testPutGetResourceWithExtension() { @Test @RunAsClient - public void testPutGetNoExtensionResource() { + public void testPutGetResourceWithExtension() { + log.debug("put resource:" + sr.toString()); + getSourceDocResource().putResourceWithDocId(sr, sr.getName(), new StringSet( + "gettext;comment"), false); + Resource get = getResourceFromResponse( + getSourceDocResource().getResourceWithDocId( + sr.getName(), + new StringSet("gettext;comment"))); + ResourceTestUtil.clearRevs(sr); + ResourceTestUtil.clearRevs(get); + assertThat(get, equalTo(sr)); + } + + @Test + @RunAsClient + @SuppressWarnings("deprecation") + public void testPutGetNoExtensionResourceDeprecated() { log.debug("put resource:" + sr.toString()); getSourceDocResource().putResource(sr.getName(), sr, null, false); Resource get = getResourceFromResponse( @@ -78,14 +95,31 @@ public void testPutGetNoExtensionResource() { assertThat(get.toString(), is(base.toString())); } + @Test + @RunAsClient + public void testPutGetNoExtensionResource() { + log.debug("put resource:" + sr.toString()); + getSourceDocResource() + .putResourceWithDocId(sr, sr.getName(), null, false); + Resource get = getResourceFromResponse( + getSourceDocResource().getResourceWithDocId(sr.getName(), + new StringSet("gettext;comment"))); + Resource base = resourceTestFactory.getTextFlowTest(); + ResourceTestUtil.clearRevs(base); + ResourceTestUtil.clearRevs(get); + log.debug("expect:" + base.toString()); + log.debug("actual:" + get.toString()); + assertThat(get.toString(), is(base.toString())); + } + @Test @RunAsClient public void testPutNoExtensionGetResource() { log.debug("put resource:" + sr.toString()); - getSourceDocResource().putResource(sr.getName(), sr, new StringSet( + getSourceDocResource().putResourceWithDocId(sr, sr.getName(), new StringSet( "gettext;comment"), false); Resource get = getResourceFromResponse( - getSourceDocResource().getResource(sr.getName(), null)); + getSourceDocResource().getResourceWithDocId(sr.getName(), null)); Resource base = resourceTestFactory.getTextFlowTest(); ResourceTestUtil.clearRevs(base); ResourceTestUtil.clearRevs(get); @@ -96,7 +130,8 @@ public void testPutNoExtensionGetResource() { @Test @RunAsClient - public void testPutGetResource() { + @SuppressWarnings("deprecation") + public void testPutGetResourceDeprecated() { getSourceDocResource().putResource(sr.getName(), sr, null, false); Resource base = resourceTestFactory.getTextFlowTest(); Resource get = getResourceFromResponse( @@ -106,13 +141,26 @@ public void testPutGetResource() { assertThat(get.toString(), is(base.toString())); } + @Test + @RunAsClient + public void testPutGetResource() { + getSourceDocResource() + .putResourceWithDocId(sr, sr.getName(), null, false); + Resource base = resourceTestFactory.getTextFlowTest(); + Resource get = getResourceFromResponse( + getSourceDocResource().getResourceWithDocId(sr.getName(), null)); + ResourceTestUtil.clearRevs(base); + ResourceTestUtil.clearRevs(get); + assertThat(get.toString(), is(base.toString())); + } + @Test @RunAsClient public void testPostGetResource() { getSourceDocResource().post(sr, null, true); Resource base = resourceTestFactory.getTextFlowTest(); Resource get = getResourceFromResponse( - getSourceDocResource().getResource(sr.getName(), null)); + getSourceDocResource().getResourceWithDocId(sr.getName(), null)); ResourceTestUtil.clearRevs(base); ResourceTestUtil.clearRevs(get); assertThat(get.toString(), is(base.toString())); @@ -120,7 +168,8 @@ public void testPostGetResource() { @Test @RunAsClient - public void testPostGetResourceWithExtension() { + @SuppressWarnings("deprecation") + public void testPostGetResourceWithExtensionDeprecated() { getSourceDocResource().post(sr, new StringSet("gettext;comment"), true); Resource get = getResourceFromResponse( getSourceDocResource().getResource(sr.getName(), @@ -132,13 +181,43 @@ public void testPostGetResourceWithExtension() { assertThat(get.toString(), is(sr.toString())); } + @Test + @RunAsClient + public void testPostGetResourceWithExtension() { + getSourceDocResource().post(sr, new StringSet("gettext;comment"), true); + Resource get = getResourceFromResponse( + getSourceDocResource().getResourceWithDocId(sr.getName(), + new StringSet("gettext;comment"))); + ResourceTestUtil.clearRevs(sr); + ResourceTestUtil.clearRevs(get); + log.debug("expect:" + sr.toString()); + log.debug("actual:" + get.toString()); + assertThat(get.toString(), is(sr.toString())); + } + + @Test + @RunAsClient + @SuppressWarnings("deprecation") + public void testPostGetNoExtensionResourceDeprecated() { + log.debug("post resource:" + sr.toString()); + getSourceDocResource().post(sr, new StringSet("gettext;comment"), true); + Resource get = getResourceFromResponse( + getSourceDocResource().getResource(sr.getName(), null)); + Resource base = resourceTestFactory.getTextFlowTest(); + ResourceTestUtil.clearRevs(base); + ResourceTestUtil.clearRevs(get); + log.debug("expect:" + base.toString()); + log.debug("actual:" + get.toString()); + assertThat(get.toString(), is(base.toString())); + } + @Test @RunAsClient public void testPostNoExtensionGetResource() { log.debug("post resource:" + sr.toString()); getSourceDocResource().post(sr, null, true); Resource get = getResourceFromResponse( - getSourceDocResource().getResource(sr.getName(), + getSourceDocResource().getResourceWithDocId(sr.getName(), new StringSet("gettext;comment"))); Resource base = resourceTestFactory.getTextFlowTest(); ResourceTestUtil.clearRevs(base); @@ -156,7 +235,7 @@ public void testPostGetNoExtensionResource() { log.debug("post resource:" + sr.toString()); getSourceDocResource().post(sr, new StringSet("gettext;comment"), true); Resource get = getResourceFromResponse( - getSourceDocResource().getResource(sr.getName(), null)); + getSourceDocResource().getResourceWithDocId(sr.getName(), null)); Resource base = resourceTestFactory.getTextFlowTest(); ResourceTestUtil.clearRevs(base); ResourceTestUtil.clearRevs(get); @@ -167,7 +246,8 @@ public void testPostGetNoExtensionResource() { @Test @RunAsClient - public void testPutGetResourceMeta() { + @SuppressWarnings("deprecation") + public void testPutGetResourceMetaDeprecated() { log.debug("test put get resource meta service"); Resource res = resourceTestFactory.getTextFlowTest(); getSourceDocResource().putResource(res.getName(), res, new StringSet( @@ -186,19 +266,41 @@ public void testPutGetResourceMeta() { assertThat(sr, equalTo(get)); } + @Test + @RunAsClient + public void testPutGetResourceMeta() { + log.debug("test put get resource meta service"); + Resource res = resourceTestFactory.getTextFlowTest(); + getSourceDocResource().putResourceWithDocId(res, res.getName(), new StringSet( + "gettext;comment"), false); + ResourceMeta sr = resourceTestFactory.getPoHeaderResourceMeta(); + getSourceDocResource().putResourceMetaWithDocId(sr, sr.getName(), new StringSet( + "gettext;comment")); + log.debug("get resource meta"); + Response resourceGetResponse = + getSourceDocResource() + .getResourceMetaWithDocId(sr.getName(), new StringSet( + "gettext;comment")); + ResourceMeta get = getResourceMetaFromResponse(resourceGetResponse); + ResourceTestUtil.clearRevs(sr); + ResourceTestUtil.clearRevs(get); + assertThat(sr, equalTo(get)); + } + @Test @RunAsClient public void testPutNoExtensionGetResourceMeta() { log.debug("test put get resource meta service"); Resource res = resourceTestFactory.getTextFlowTest(); - getSourceDocResource().putResource(res.getName(), res, null, false); + getSourceDocResource() + .putResourceWithDocId(res, res.getName(), null, false); ResourceMeta sr = resourceTestFactory.getPoHeaderResourceMeta(); ResourceMeta base = resourceTestFactory.getResourceMeta(); - getSourceDocResource().putResourceMeta(sr.getName(), sr, null); + getSourceDocResource().putResourceMetaWithDocId(sr, sr.getName(), null); log.debug("get resource meta"); Response resourceGetResponse = getSourceDocResource() - .getResourceMeta(sr.getName(), new StringSet( + .getResourceMetaWithDocId(sr.getName(), new StringSet( "gettext;comment")); ResourceMeta get = getResourceMetaFromResponse(resourceGetResponse); ResourceTestUtil.clearRevs(base); @@ -208,7 +310,8 @@ public void testPutNoExtensionGetResourceMeta() { @Test @RunAsClient - public void testPutGetNoExtensionResourceMeta() { + @SuppressWarnings("deprecation") + public void testPutGetNoExtensionResourceMetaDeprecated() { log.debug("test put get resource meta service"); Resource res = resourceTestFactory.getTextFlowTest(); getSourceDocResource().putResource(res.getName(), res, null, false); @@ -227,7 +330,29 @@ public void testPutGetNoExtensionResourceMeta() { @Test @RunAsClient - public void testDeleteResource() { + public void testPutGetNoExtensionResourceMeta() { + log.debug("test put get resource meta service"); + Resource res = resourceTestFactory.getTextFlowTest(); + getSourceDocResource() + .putResourceWithDocId(res, res.getName(), null, false); + ResourceMeta sr = resourceTestFactory.getPoHeaderResourceMeta(); + ResourceMeta base = resourceTestFactory.getResourceMeta(); + getSourceDocResource() + .putResourceMetaWithDocId(sr, sr.getName(), new StringSet( + "gettext;comment")); + log.debug("get resource meta"); + Response resourceGetResponse = + getSourceDocResource().getResourceMetaWithDocId(sr.getName(), null); + ResourceMeta get = getResourceMetaFromResponse(resourceGetResponse); + ResourceTestUtil.clearRevs(base); + ResourceTestUtil.clearRevs(get); + assertThat(get, equalTo(base)); + } + + @Test + @RunAsClient + @SuppressWarnings("deprecation") + public void testDeleteResourceDeprecated() { Resource rs1 = resourceTestFactory.getTextFlowTest2(); getSourceDocResource().post(rs1, null, true); Response resourceGetResponse = @@ -244,7 +369,25 @@ public void testDeleteResource() { @Test @RunAsClient - public void testPostGetResourceWithUnderscoreInFileNameWithExtension() { + public void testDeleteResource() { + Resource rs1 = resourceTestFactory.getTextFlowTest2(); + getSourceDocResource().post(rs1, null, true); + Response resourceGetResponse = + getSourceDocResource().deleteResourceWithDocId(rs1.getName()); + assertThat(resourceGetResponse.getStatus(), + is(Status.OK.getStatusCode())); + + Resource rs2 = resourceTestFactory.getTextFlowTest(); + Response resourceGetResponse2 = + getSourceDocResource().deleteResourceWithDocId(rs2.getName()); + assertThat(resourceGetResponse2.getStatus(), + is(Status.NOT_FOUND.getStatusCode())); + } + + @Test + @RunAsClient + @SuppressWarnings("deprecation") + public void testPostGetResourceWithUnderscoreInFileNameWithExtensionDeprecated() { Resource resource = new Resource("_test1.file-a"); resource.setContentType(sr.getContentType()); resource.setExtensions(sr.getExtensions()); @@ -263,4 +406,24 @@ public void testPostGetResourceWithUnderscoreInFileNameWithExtension() { assertThat(got, is(expected)); } + @Test + @RunAsClient + public void testPostGetResourceWithUnderscoreInFileNameWithExtension() { + Resource resource = new Resource("_test1.file-a"); + resource.setContentType(sr.getContentType()); + resource.setExtensions(sr.getExtensions()); + resource.setLang(sr.getLang()); + resource.setType(sr.getType()); + getSourceDocResource().post(resource, new StringSet("gettext;comment"), false); + Resource get = getResourceFromResponse( + getSourceDocResource().getResourceWithDocId(resource.getName(), + new StringSet("gettext;comment"))); + ResourceTestUtil.clearRevs(resource); + ResourceTestUtil.clearRevs(get); + String expected = RawRestTestUtils.jaxbMarhsal(resource); + log.debug("expect:" + expected); + String got = RawRestTestUtils.jaxbMarhsal(get); + log.debug("actual:" + got); + assertThat(got, is(expected)); + } } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/SourceAndTranslationResourceRestBase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/SourceAndTranslationResourceRestBase.java index 37b9c56d30..fd6e4b31ae 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/SourceAndTranslationResourceRestBase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/SourceAndTranslationResourceRestBase.java @@ -53,8 +53,10 @@ * href="mailto:pahuang@redhat.com">pahuang@redhat.com */ public abstract class SourceAndTranslationResourceRestBase extends RestTest { - protected static final String RESOURCE_PATH = + protected static final String DEPRECATED_BASE_PATH = "/projects/p/sample-project/iterations/i/1.0/r/"; + protected static final String BASE_PATH = + "/projects/p/sample-project/iterations/i/1.0/resource"; private SourceDocResource sourceDocResource; private TranslatedDocResource translatedDocResource; @@ -100,7 +102,7 @@ public SourceDocResource getSourceDocResource() { @Override public Response head() { return new ResourceRequest( - getRestEndpointUrl(RESOURCE_PATH), + getRestEndpointUrl(DEPRECATED_BASE_PATH), "HEAD", getAuthorizedEnvironment()) { @Override protected Invocation.Builder prepareRequest( @@ -117,7 +119,7 @@ protected void onResponse(Response response) { @Override public Response get(final Set extensions) { return new ResourceRequest( - getRestEndpointUrl(RESOURCE_PATH), + getRestEndpointUrl(DEPRECATED_BASE_PATH), "GET", getAuthorizedEnvironment()) { @Override protected Invocation.Builder prepareRequest( @@ -138,7 +140,7 @@ public Response post(final Resource resource, final Set extensions, @DefaultValue("true") final boolean copytrans) { return new ResourceRequest( - getRestEndpointUrl(RESOURCE_PATH), + getRestEndpointUrl(DEPRECATED_BASE_PATH), "POST", getAuthorizedEnvironment()) { @Override protected Invocation.Builder prepareRequest( @@ -168,7 +170,7 @@ protected void onResponse(Response response) { public Response getResource(String idNoSlash, final Set extensions) { return new ResourceRequest( - getRestEndpointUrl(RESOURCE_PATH + idNoSlash), + getRestEndpointUrl(DEPRECATED_BASE_PATH + idNoSlash), "GET", getAuthorizedEnvironment()) { @Override protected Invocation.Builder prepareRequest( @@ -184,13 +186,34 @@ protected void onResponse(Response response) { }.runWithResult(); } + @Override + public Response getResourceWithDocId(String docId, + Set extensions) { + return new ResourceRequest( + getRestEndpointUrl(BASE_PATH), + "GET", getAuthorizedEnvironment()) { + @Override + protected Invocation.Builder prepareRequest( + ResteasyWebTarget webTarget) { + return addExtensionToRequest(extensions, webTarget). + queryParam("docId", docId). + request().header(HttpHeaders.ACCEPT, + MediaType.APPLICATION_XML_TYPE); + } + + @Override + protected void onResponse(Response response) { + } + }.runWithResult(); + } + @Override public Response putResource(String idNoSlash, final Resource resource, final Set extensions, @DefaultValue("true") final boolean copytrans) { return new ResourceRequest( - getRestEndpointUrl(RESOURCE_PATH + idNoSlash), + getRestEndpointUrl(DEPRECATED_BASE_PATH + idNoSlash), "PUT", getAuthorizedEnvironment()) { @Override protected Invocation.Builder prepareRequest( @@ -215,10 +238,41 @@ protected void onResponse(Response response) { }.runWithResult(); } + @Override + public Response putResourceWithDocId(Resource resource, + String docId, + Set extensions, boolean copytrans) { + return new ResourceRequest( + getRestEndpointUrl(BASE_PATH), + "PUT", getAuthorizedEnvironment()) { + @Override + protected Invocation.Builder prepareRequest( + ResteasyWebTarget webTarget) { + return addExtensionToRequest(extensions, webTarget) + .queryParam("docId", docId) + .queryParam("copyTrans", + String.valueOf(copytrans)).request(); + } + + @Override + public Response invokeWithResponse( + Invocation.Builder builder) { + Entity entity = Entity + .entity(jaxbMarhsal(resource), + MediaType.APPLICATION_XML_TYPE); + return builder.buildPut(entity).invoke(); + } + + @Override + protected void onResponse(Response response) { + } + }.runWithResult(); + } + @Override public Response deleteResource(String idNoSlash) { return new ResourceRequest( - getRestEndpointUrl(RESOURCE_PATH + idNoSlash), + getRestEndpointUrl(DEPRECATED_BASE_PATH + idNoSlash), "DELETE", getAuthorizedEnvironment()) { @Override protected Invocation.Builder prepareRequest( @@ -232,17 +286,55 @@ protected void onResponse(Response response) { }.runWithResult(); } + @Override + public Response deleteResourceWithDocId(String docId) { + return new ResourceRequest(getRestEndpointUrl(BASE_PATH), + "DELETE", getAuthorizedEnvironment()) { + @Override + protected Invocation.Builder prepareRequest( + ResteasyWebTarget webTarget) { + return webTarget.queryParam("docId", docId).request(); + } + + @Override + protected void onResponse(Response response) { + } + }.runWithResult(); + } + @Override public Response getResourceMeta(String idNoSlash, final Set extensions) { return new ResourceRequest( getRestEndpointUrl( - RESOURCE_PATH + idNoSlash + "/meta"), + DEPRECATED_BASE_PATH + idNoSlash + "/meta"), + "GET", getAuthorizedEnvironment()) { + @Override + protected Invocation.Builder prepareRequest( + ResteasyWebTarget webTarget) { + return addExtensionToRequest(extensions, webTarget) + .request().header(HttpHeaders.ACCEPT, + MediaType.APPLICATION_XML_TYPE); + } + + @Override + protected void onResponse(Response response) { + } + }.runWithResult(); + } + + @Override + public Response getResourceMetaWithDocId(String docId, + Set extensions) { + return new ResourceRequest( + getRestEndpointUrl( + BASE_PATH + "/meta"), "GET", getAuthorizedEnvironment()) { @Override protected Invocation.Builder prepareRequest( ResteasyWebTarget webTarget) { return addExtensionToRequest(extensions, webTarget) + .queryParam("docId", docId) .request().header(HttpHeaders.ACCEPT, MediaType.APPLICATION_XML_TYPE); } @@ -259,7 +351,7 @@ public Response putResourceMeta(String idNoSlash, final Set extensions) { return new ResourceRequest( getRestEndpointUrl( - RESOURCE_PATH + idNoSlash + "/meta"), + DEPRECATED_BASE_PATH + idNoSlash + "/meta"), "PUT", getAuthorizedEnvironment()) { @Override protected Invocation.Builder prepareRequest( @@ -282,6 +374,36 @@ protected void onResponse(Response response) { } }.runWithResult(); } + + @Override + public Response putResourceMetaWithDocId(ResourceMeta messageBody, + String docId, Set extensions) { + return new ResourceRequest( + getRestEndpointUrl( + BASE_PATH + "/meta"), + "PUT", getAuthorizedEnvironment()) { + @Override + protected Invocation.Builder prepareRequest( + ResteasyWebTarget webTarget) { + return addExtensionToRequest(extensions, webTarget) + .queryParam("docId", docId) + .request(); + } + + @Override + public Response invokeWithResponse( + Invocation.Builder builder) { + Entity entity = Entity + .entity(jaxbMarhsal(messageBody), + MediaType.APPLICATION_XML_TYPE); + return builder.buildPut(entity).invoke(); + } + + @Override + protected void onResponse(Response response) { + } + }.runWithResult(); + } }; } return sourceDocResource; @@ -296,12 +418,37 @@ public Response getTranslations(String idNoSlash, LocaleId locale, final Set extensions, final boolean createSkeletons, String eTag) { return new ResourceRequest( - getRestEndpointUrl(RESOURCE_PATH + idNoSlash + "/translations/" + locale), + getRestEndpointUrl(DEPRECATED_BASE_PATH + idNoSlash + "/translations/" + locale), + "GET", getAuthorizedEnvironment()) { + @Override + protected Invocation.Builder prepareRequest( + ResteasyWebTarget webTarget) { + return addExtensionToRequest(extensions, webTarget) + .queryParam("skeletons", + String.valueOf(createSkeletons)) + .request().header(HttpHeaders.ACCEPT, + MediaType.APPLICATION_XML_TYPE); + } + + @Override + protected void onResponse(Response response) { + } + }.runWithResult(); + } + + @Override + public Response getTranslationsWithDocId(LocaleId locale, + String docId, + Set extensions, boolean createSkeletons, + String eTag) { + return new ResourceRequest( + getRestEndpointUrl(BASE_PATH + "/translations/" + locale), "GET", getAuthorizedEnvironment()) { @Override protected Invocation.Builder prepareRequest( ResteasyWebTarget webTarget) { return addExtensionToRequest(extensions, webTarget) + .queryParam("docId", docId) .queryParam("skeletons", String.valueOf(createSkeletons)) .request().header(HttpHeaders.ACCEPT, @@ -318,7 +465,7 @@ protected void onResponse(Response response) { public Response deleteTranslations(String idNoSlash, LocaleId locale) { return new ResourceRequest( - getRestEndpointUrl(RESOURCE_PATH + idNoSlash + "/translations/" + locale), + getRestEndpointUrl(DEPRECATED_BASE_PATH + idNoSlash + "/translations/" + locale), "DELETE", getAuthorizedEnvironment()) { @Override protected Invocation.Builder prepareRequest( @@ -332,17 +479,68 @@ protected void onResponse(Response response) { }.runWithResult(); } + @Override + public Response deleteTranslationsWithDocId(LocaleId locale, + String docId) { + return new ResourceRequest( + getRestEndpointUrl(BASE_PATH + "/translations/" + locale), + "DELETE", getAuthorizedEnvironment()) { + @Override + protected Invocation.Builder prepareRequest( + ResteasyWebTarget webTarget) { + return webTarget.queryParam("docId", docId).request(); + } + + @Override + protected void onResponse(Response response) { + } + }.runWithResult(); + } + @Override public Response putTranslations(String idNoSlash, LocaleId locale, final TranslationsResource messageBody, final Set extensions, @DefaultValue("auto") final String merge) { return new ResourceRequest( - getRestEndpointUrl(RESOURCE_PATH + idNoSlash + "/translations/" + locale), + getRestEndpointUrl(DEPRECATED_BASE_PATH + idNoSlash + "/translations/" + locale), + "PUT", getAuthorizedEnvironment()) { + @Override + protected Invocation.Builder prepareRequest( + ResteasyWebTarget webTarget) { + return addExtensionToRequest(extensions, webTarget) + .queryParam("merge", merge).request() + .header(HttpHeaders.ACCEPT, + MediaType.APPLICATION_XML_TYPE); + } + + @Override + public Response invokeWithResponse( + Invocation.Builder builder) { + Entity entity = Entity + .entity(jaxbMarhsal(messageBody), + MediaType.APPLICATION_XML_TYPE); + return builder.buildPut(entity).invoke(); + } + + @Override + protected void onResponse(Response response) { + } + }.runWithResult(); + } + + @Override + public Response putTranslationsWithDocId(LocaleId locale, + TranslationsResource messageBody, String docId, + Set extensions, + String merge) { + return new ResourceRequest( + getRestEndpointUrl(BASE_PATH + "/translations/" + locale), "PUT", getAuthorizedEnvironment()) { @Override protected Invocation.Builder prepareRequest( ResteasyWebTarget webTarget) { return addExtensionToRequest(extensions, webTarget) + .queryParam("docId", docId) .queryParam("merge", merge).request() .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_XML_TYPE); diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/TranslationResourceRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/TranslationResourceRestITCase.java index e8bf60b3f2..705bd11823 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/TranslationResourceRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/TranslationResourceRestITCase.java @@ -26,7 +26,6 @@ import org.zanata.common.LocaleId; import org.zanata.common.MergeType; import org.zanata.common.ResourceType; -import org.zanata.rest.RestUtil; import org.zanata.rest.StringSet; import org.zanata.rest.dto.extensions.comment.SimpleComment; import org.zanata.rest.dto.extensions.gettext.HeaderEntry; @@ -43,6 +42,7 @@ import org.zanata.rest.service.ResourceUtils; import com.google.common.collect.Lists; +import org.zanata.util.UrlUtil; public class TranslationResourceRestITCase extends SourceAndTranslationResourceRestBase { private static final Logger log = LoggerFactory @@ -88,7 +88,7 @@ public void createResourceWithContentUsingPost() { postResponse = getSourceDocResource().post(sr, null, true); Response resourceGetResponse = - getSourceDocResource().getResource("my.txt", null); + getSourceDocResource().getResourceWithDocId("my.txt", null); assertThat(resourceGetResponse.getStatus(), is(Status.OK.getStatusCode())); Resource gotSr = getResourceFromResponse(resourceGetResponse); assertThat(gotSr.getTextFlows().size(), is(1)); @@ -105,11 +105,12 @@ public void createResourceWithContentUsingPut() { sr.getTextFlows().add(stf); Response response = - getSourceDocResource().putResource("my.txt", sr, null, false); + getSourceDocResource() + .putResourceWithDocId(sr, "my.txt", null, false); assertThat(response.getStatus(), is(Status.CREATED.getStatusCode())); Response resourceGetResponse = - getSourceDocResource().getResource("my.txt", null); + getSourceDocResource().getResourceWithDocId("my.txt", null); assertThat(resourceGetResponse.getStatus(), is(Status.OK.getStatusCode())); Resource gotSr = getResourceFromResponse(resourceGetResponse); assertThat(gotSr.getTextFlows().size(), is(1)); @@ -121,7 +122,6 @@ public void createResourceWithContentUsingPut() { @RunAsClient public void createPoResourceWithPoHeader() { String docName = "my.txt"; - String docUri = RestUtil.convertToDocumentURIId(docName); Resource sr = createSourceResource(docName); TextFlow stf = new TextFlow("tf1", LocaleId.EN, "tf1"); @@ -144,7 +144,7 @@ public void createPoResourceWithPoHeader() { doGetandAssertThatResourceListContainsNItems(1); Response resourceGetResponse = - getSourceDocResource().getResource(docUri, null); + getSourceDocResource().getResourceWithDocId(docName, null); // , new StringSet(PoHeader.ID)); assertThat(resourceGetResponse.getStatus(), is(Status.OK.getStatusCode())); Resource gotSr = getResourceFromResponse(resourceGetResponse); @@ -181,13 +181,14 @@ public void publishTranslations() { LocaleId de_DE = new LocaleId("de"); Response response = getTransResource() - .putTranslations("my.txt", de_DE, entity, null, + .putTranslationsWithDocId(de_DE, entity, "my.txt", null, "auto"); assertThat(response.getStatus(), is(Status.OK.getStatusCode())); Response getResponse = - getTransResource().getTranslations("my.txt", de_DE, null, false, + getTransResource() + .getTranslationsWithDocId(de_DE, "my.txt", null, false, null); assertThat(getResponse.getStatus(), is(Status.OK.getStatusCode())); TranslationsResource entity2 = @@ -199,13 +200,14 @@ public void publishTranslations() { // push an empty document response = getTransResource() - .putTranslations("my.txt", de_DE, entity, null, + .putTranslationsWithDocId(de_DE, entity, "my.txt", null, MergeType.IMPORT.toString()); assertThat(response.getStatus(), is(Status.OK.getStatusCode())); getResponse = - getTransResource().getTranslations("my.txt", de_DE, null, false, - null); + getTransResource() + .getTranslationsWithDocId(de_DE, "my.txt", null, false, + null); assertThat(getResponse.getStatus(), is(Status.OK.getStatusCode())); } @@ -214,7 +216,7 @@ public void publishTranslations() { public void getDocumentThatDoesntExist() { Response clientResponse = getSourceDocResource() - .getResource("my,doc,does,not,exist.txt", null); + .getResourceWithDocId("my,doc,does,not,exist.txt", null); assertThat(clientResponse.getStatus(), is(Status.NOT_FOUND.getStatusCode())); } @@ -222,12 +224,12 @@ public void getDocumentThatDoesntExist() { @RunAsClient public void getDocument() throws Exception { String docName = "my/path/document.txt"; - String docUri = RestUtil.convertToDocumentURIId(docName); Resource resource = createSourceDoc(docName, false); - getSourceDocResource().putResource(docUri, resource, null, false); + getSourceDocResource().putResourceWithDocId(resource, docName, null, + false); Response response = - getSourceDocResource().getResourceMeta(docUri, null); + getSourceDocResource().getResourceMetaWithDocId(docName, null); assertThat(response.getStatus(), is(Status.OK.getStatusCode())); ResourceMeta doc = getResourceMetaFromResponse(response); assertThat(doc.getName(), is(docName)); @@ -252,16 +254,16 @@ public void getDocument() throws Exception { public void getDocumentWithResources() throws Exception { LocaleId nbLocale = new LocaleId("de"); String docName = "my/path/document.txt"; - String docUri = RestUtil.convertToDocumentURIId(docName); Resource resource = createSourceDoc(docName, true); - getSourceDocResource().putResource(docUri, resource, null, false); + getSourceDocResource().putResourceWithDocId(resource, docName, null, + false); TranslationsResource trans = createTargetDoc(); getTransResource() - .putTranslations(docUri, nbLocale, trans, null, "auto"); + .putTranslationsWithDocId(nbLocale, trans, docName, null, "auto"); { Response response = - getSourceDocResource().getResource(docUri, null); + getSourceDocResource().getResourceWithDocId(docName, null); assertThat(response.getStatus(), is(Status.OK.getStatusCode())); Resource doc = getResourceFromResponse(response); @@ -270,7 +272,8 @@ public void getDocumentWithResources() throws Exception { Response response = getTransResource() - .getTranslations(docUri, nbLocale, null, false, + .getTranslationsWithDocId(nbLocale, docName, null, + false, null); assertThat(response.getStatus(), is(Status.OK.getStatusCode())); @@ -292,17 +295,16 @@ public void getDocumentWithResources() throws Exception { @RunAsClient public void putNewDocument() { String docName = "my/fancy/document.txt"; - String docUrl = RestUtil.convertToDocumentURIId(docName); Resource doc = createSourceDoc(docName, false); Response response = getSourceDocResource() - .putResource(docUrl, doc, null, false); + .putResourceWithDocId(doc, docName, null, false); assertThat(response.getStatus(), is(Status.CREATED.getStatusCode())); assertThat(response.getMetadata().getFirst("Location").toString(), - endsWith(RESOURCE_PATH + docUrl)); + endsWith(BASE_PATH + "?docId=" + UrlUtil.encodeString(docName))); Response documentResponse = - getSourceDocResource().getResource(docUrl, null); + getSourceDocResource().getResourceWithDocId(docName, null); assertThat(documentResponse.getStatus(), is(Status.OK.getStatusCode())); @@ -325,7 +327,6 @@ public void putNewDocument() { @RunAsClient public void putDocWithDuplicateTextFlowIds() throws Exception { String docName = "testDoc"; - String docUrl = RestUtil.convertToDocumentURIId(docName); Resource doc = createSourceDoc(docName, false); List textFlows = doc.getTextFlows(); @@ -335,7 +336,8 @@ public void putDocWithDuplicateTextFlowIds() throws Exception { textFlows.add(textFlow); } Response response = - getSourceDocResource().putResource(docUrl, doc, null, false); + getSourceDocResource() + .putResourceWithDocId(doc, docName, null, false); assertThat(response.getStatus(), is(Status.BAD_REQUEST.getStatusCode())); String message = response.readEntity(String.class); assertThat(message, containsString("tf1")); @@ -345,7 +347,6 @@ public void putDocWithDuplicateTextFlowIds() throws Exception { @RunAsClient public void putNewDocumentWithResources() throws Exception { String docName = "my/fancy/document.txt"; - String docUrl = RestUtil.convertToDocumentURIId(docName); Resource doc = createSourceDoc(docName, false); List textFlows = doc.getTextFlows(); @@ -366,14 +367,14 @@ public void putNewDocumentWithResources() throws Exception { // m.marshal(doc, System.out); Response response = getSourceDocResource() - .putResource(docUrl, doc, null, false); + .putResourceWithDocId(doc, docName, null, false); assertThat(response.getStatus(), is(Status.CREATED.getStatusCode())); assertThat(response.getMetadata().getFirst("Location").toString(), - endsWith(RESOURCE_PATH + docUrl)); + endsWith(BASE_PATH + "?docId=" + UrlUtil.encodeString(docName))); Response documentResponse = - getSourceDocResource().getResource(docUrl, null); + getSourceDocResource().getResourceWithDocId(docName, null); assertThat(documentResponse.getStatus(), is(Status.OK.getStatusCode())); @@ -391,12 +392,14 @@ public void putNewDocumentWithResources() throws Exception { textFlow = doc.getTextFlows().get(0); textFlow.setId("tf2"); - response = getSourceDocResource().putResource(docUrl, doc, null, false); + response = getSourceDocResource().putResourceWithDocId(doc, docName, + null, false); // this WAS testing for status 205 assertThat(response.getStatus(), is(200)); - documentResponse = getSourceDocResource().getResource(docUrl, null); + documentResponse = getSourceDocResource() + .getResourceWithDocId(docName, null); assertThat(documentResponse.getStatus(), is(Status.OK.getStatusCode())); doc = getResourceFromResponse(documentResponse); @@ -632,7 +635,7 @@ public void generatedPoHeaders() throws Exception { // Get the translations with PO headers Response response = getTransResource() - .getTranslations("my.txt", de_DE, new StringSet( + .getTranslationsWithDocId(de_DE, "my.txt", new StringSet( "gettext"), true, null); TranslationsResource translations = getTranslationsResourceFromResponse(response); @@ -693,7 +696,7 @@ public void headersBeforeTranslating() throws Exception { // Get the translations with PO headers Response response = getTransResource() - .getTranslations("my.txt", de_DE, new StringSet( + .getTranslationsWithDocId(de_DE, "my.txt", new StringSet( "gettext"), true, null); TranslationsResource translations = getTranslationsResourceFromResponse(response); @@ -753,15 +756,15 @@ public void headersFromOriginalPush() throws Exception { // Push the translations Response putResponse = - getTransResource().putTranslations("my.txt", de_DE, entity, - new StringSet("gettext"), "auto"); + getTransResource().putTranslationsWithDocId(de_DE, entity, + "my.txt", new StringSet("gettext"), "auto"); assertThat(putResponse.getStatus(), is(Status.OK.getStatusCode())); // Get the translations with PO headers Response transResponse = getTransResource() - .getTranslations("my.txt", de_DE, new StringSet( + .getTranslationsWithDocId(de_DE, "my.txt", new StringSet( "gettext"), false, null); TranslationsResource translations = getTranslationsResourceFromResponse(transResponse); @@ -805,14 +808,14 @@ public void headersAfterTranslating() throws Exception { Response putResponse = getTransResource() - .putTranslations("my.txt", de_DE, entity, null, + .putTranslationsWithDocId(de_DE, entity, "my.txt", null, "auto"); assertThat(putResponse.getStatus(), is(Status.OK.getStatusCode())); // Get the translations with PO headers Response response = getTransResource() - .getTranslations("my.txt", de_DE, new StringSet( + .getTranslationsWithDocId(de_DE, "my.txt", new StringSet( "gettext"), false, null); TranslationsResource translations = getTranslationsResourceFromResponse(response); @@ -826,15 +829,15 @@ public void headersAfterTranslating() throws Exception { putResponse = getTransResource() - .putTranslations("my.txt", de_DE, translations, - null, "auto"); + .putTranslationsWithDocId(de_DE, translations, + "my.txt", null, "auto"); assertThat(putResponse.getStatus(), is(Status.OK.getStatusCode())); // Fetch the translations again response = getTransResource() - .getTranslations("my.txt", de_DE, new StringSet( + .getTranslationsWithDocId(de_DE, "my.txt", new StringSet( "gettext"), false, null); translations = getTranslationsResourceFromResponse(response); @@ -878,13 +881,13 @@ private void expectResourceMetas(boolean checkRevs, entityString, ResourceMeta[].class)); assertThat(actualDocs, notNullValue()); Map expectedDocs = - new HashMap(); + new HashMap<>(); for (AbstractResourceMeta doc : docs) { expectedDocs.put(doc.getName(), doc); } // Set actualDocVals = new TreeSet(); Map actualDocsMap = - new HashMap(); + new HashMap<>(); for (ResourceMeta doc : actualDocs) { actualDocsMap.put(doc.getName(), doc); log.debug("actual doc: " + doc.toString()); @@ -898,7 +901,7 @@ private void expectResourceMetas(boolean checkRevs, private void expectResources(boolean checkRevs, Resource... docs) { for (Resource expectedDoc : docs) { Response response = - getSourceDocResource().getResource(expectedDoc.getName(), + getSourceDocResource().getResourceWithDocId(expectedDoc.getName(), extGettextComment); assertThat(response.getStatus(), is(200)); Resource actualDoc = getResourceFromResponse(response); @@ -922,7 +925,8 @@ protected void createExtensionSets(Resource resource) { private void dontExpectTarget(String id, LocaleId locale) { Response response = getTransResource() - .getTranslations(id, locale, null, false, null); + .getTranslationsWithDocId(locale, id, null, false, + null); assertThat(response.getStatus(), is(404)); } @@ -930,7 +934,7 @@ private void expectTarget(boolean checkRevs, String id, LocaleId locale, TranslationsResource expectedDoc) { Response response = getTransResource() - .getTranslations(id, locale, extGettextComment, + .getTranslationsWithDocId(locale, id, extGettextComment, false, null); assertThat(response.getStatus(), is(200)); TranslationsResource actualDoc = getTranslationsResourceFromResponse(response); @@ -1033,11 +1037,11 @@ private TextFlowTarget newTextFlowTarget(String id, String targetContent, return target; } - SimpleComment getOrAddComment(TextFlow tf) { + private SimpleComment getOrAddComment(TextFlow tf) { return tf.getExtensions(true).findOrAddByType(SimpleComment.class); } - SimpleComment getOrAddComment(TextFlowTarget tft) { + private SimpleComment getOrAddComment(TextFlowTarget tft) { return tft.getExtensions(true).findOrAddByType(SimpleComment.class); } @@ -1067,7 +1071,7 @@ private Resource putPo1() { log.debug("{}", doc); Response response = getSourceDocResource() - .putResource(id, doc, extGettextComment, false); + .putResourceWithDocId(doc, id, extGettextComment, false); assertThat(response.getStatus(), isOneOf(200, 201)); return doc; } @@ -1086,7 +1090,7 @@ private TranslationsResource putPoTarget1() { tr.getExtensions(true).add(targetHeader); getTransResource() - .putTranslations(id, DE, tr, extGettextComment, "auto"); + .putTranslationsWithDocId(DE, tr, id, extGettextComment, "auto"); return tr; } @@ -1098,7 +1102,7 @@ private Resource putDoc1(boolean putTarget) { newTextFlow("FOOD", "Slime Mould", "slime mould comment")); Response response = getSourceDocResource() - .putResource(id, doc, extComment, false); + .putResourceWithDocId(doc, id, extComment, false); assertThat(response.getStatus(), isOneOf(200, 201)); if (putTarget) @@ -1113,7 +1117,7 @@ protected TranslationsResource putTarget1() { TextFlowTarget target = newTextFlowTarget("FOOD", "Sauerkraut", null); tr.getTextFlowTargets().add(target); getTransResource() - .putTranslations(id, DE, tr, extGettextComment, "auto"); + .putTranslationsWithDocId(DE, tr, id, extGettextComment, "auto"); return tr; } @@ -1131,7 +1135,7 @@ private Resource putDoc1a(boolean putTarget) { String id = DOC1_NAME; Resource doc = newDoc(id, newTextFlow("HELLO", "Hello World", null)); Response response = getSourceDocResource() - .putResource(id, doc, extComment, false); + .putResourceWithDocId(doc, id, extComment, false); assertThat(response.getStatus(), isOneOf(200, 201)); if (putTarget) @@ -1148,18 +1152,16 @@ protected TranslationsResource putTarget1a() { "bon jour comment"); tr.getTextFlowTargets().add(target); getTransResource() - .putTranslations(id, FR, tr, extGettextComment, "auto"); + .putTranslationsWithDocId(FR, tr, id, extGettextComment, "auto"); return tr; } private void dontExpectTarget1a() { - String id = DOC1_NAME; - dontExpectTarget(id, FR); + dontExpectTarget(DOC1_NAME, FR); } private void expectTarget1a(TranslationsResource target1a) { - String id = DOC1_NAME; - expectTarget(true, id, FR, target1a); + expectTarget(true, DOC1_NAME, FR, target1a); } private void deleteDoc1() { @@ -1171,14 +1173,13 @@ private void deleteDoc2() { } protected void deleteDoc(String id) { - Response response = getSourceDocResource().deleteResource(id); + Response response = getSourceDocResource().deleteResourceWithDocId(id); assertThat(response.getStatus(), is(200)); } private Resource postDoc2(boolean putTarget) { - String id = DOC2_NAME; Resource doc = - newDoc(id, newTextFlow("HELLO", "Hello World", "hello comment")); + newDoc(DOC2_NAME, newTextFlow("HELLO", "Hello World", "hello comment")); Response response = getSourceDocResource().post(doc, extComment, true); assertThat(response.getStatus(), is(201)); @@ -1189,24 +1190,21 @@ private Resource postDoc2(boolean putTarget) { } protected TranslationsResource putTarget2() { - String id = DOC2_NAME; TranslationsResource tr = new TranslationsResource(); TextFlowTarget target = newTextFlowTarget("HELLO", "Bonjour le Monde", null); tr.getTextFlowTargets().add(target); getTransResource() - .putTranslations(id, FR, tr, extGettextComment, "auto"); + .putTranslationsWithDocId(FR, tr, DOC2_NAME, extGettextComment, "auto"); return tr; } private void dontExpectTarget2() { - String id = DOC2_NAME; - dontExpectTarget(id, FR); + dontExpectTarget(DOC2_NAME, FR); } private void expectTarget2(TranslationsResource target2) { - String id = DOC2_NAME; - expectTarget(true, id, FR, target2); + expectTarget(true, DOC2_NAME, FR, target2); } } From 8decf5b154a9087c10ebe1e41bfc931cad3075c0 Mon Sep 17 00:00:00 2001 From: kgough Date: Fri, 21 Jul 2017 11:32:01 +1000 Subject: [PATCH 102/116] fix(ZNTA-2105) button-off styling for validations in frontend --- server/zanata-frontend/src/frontend/app/styles/style.less | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/server/zanata-frontend/src/frontend/app/styles/style.less b/server/zanata-frontend/src/frontend/app/styles/style.less index 931e030688..aa1bafb094 100644 --- a/server/zanata-frontend/src/frontend/app/styles/style.less +++ b/server/zanata-frontend/src/frontend/app/styles/style.less @@ -6649,6 +6649,12 @@ table.tmx-table .badge .n1 { -moz-hyphens: initial; hyphens: initial; } + +.new-zanata .button--group input[type=radio]:checked+.button--Off { + background-color: @color-dark !important; + color: #f2f2f2; +} + // @screen-xs variable depreciated @media (max-width: 29.375rem) { .view { From 1e7515ea7873fa499d7eb41c03d468631928a657 Mon Sep 17 00:00:00 2001 From: kgough Date: Fri, 21 Jul 2017 13:31:14 +1000 Subject: [PATCH 103/116] fix(ZNTA-2105) changed colour of new version icon --- server/zanata-frontend/src/frontend/app/styles/style.less | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/zanata-frontend/src/frontend/app/styles/style.less b/server/zanata-frontend/src/frontend/app/styles/style.less index 931e030688..cb5cbe95b9 100644 --- a/server/zanata-frontend/src/frontend/app/styles/style.less +++ b/server/zanata-frontend/src/frontend/app/styles/style.less @@ -6649,6 +6649,11 @@ table.tmx-table .badge .n1 { -moz-hyphens: initial; hyphens: initial; } + +.panel__header a#new-version-link i.i.i--add:not(.i--large) { + color: @color-light; +} + // @screen-xs variable depreciated @media (max-width: 29.375rem) { .view { From a77ce22cddad620995a51b68a26b8a8779db8993 Mon Sep 17 00:00:00 2001 From: Alex Eng Date: Fri, 21 Jul 2017 16:24:48 +1000 Subject: [PATCH 104/116] refactor: replace method with common-util (#435) https://zanata.atlassian.net/browse/ZNTA-510 --- .../src/main/java/org/zanata/CommonUtil.gwt.xml | 1 + .../zanata/webtrans/client/view/TransMemoryView.java | 12 ++---------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/common/zanata-common-util/src/main/java/org/zanata/CommonUtil.gwt.xml b/common/zanata-common-util/src/main/java/org/zanata/CommonUtil.gwt.xml index 118c114830..8305e55c63 100644 --- a/common/zanata-common-util/src/main/java/org/zanata/CommonUtil.gwt.xml +++ b/common/zanata-common-util/src/main/java/org/zanata/CommonUtil.gwt.xml @@ -3,6 +3,7 @@ + diff --git a/server/gwt-editor/src/main/java/org/zanata/webtrans/client/view/TransMemoryView.java b/server/gwt-editor/src/main/java/org/zanata/webtrans/client/view/TransMemoryView.java index 13e38ec844..d652170541 100644 --- a/server/gwt-editor/src/main/java/org/zanata/webtrans/client/view/TransMemoryView.java +++ b/server/gwt-editor/src/main/java/org/zanata/webtrans/client/view/TransMemoryView.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import java.util.List; +import org.zanata.util.ShortString; import org.zanata.webtrans.client.keys.ShortcutContext; import org.zanata.webtrans.client.resources.UiMessages; import org.zanata.webtrans.client.ui.DiffColorLegendPanel; @@ -344,7 +345,7 @@ public void onClick(ClickEvent event) { Anchor infoCell = new Anchor(); if (item.getMatchType() == MatchType.Imported) { String originStr = Joiner.on(", ").join(item.getOrigins()); - infoCell.setText(shorten(originStr, 10)); + infoCell.setText(ShortString.shorten(originStr, 10)); infoCell.setTitle(originStr); } else { infoCell.setStyleName("i i--info txt--lead"); @@ -362,15 +363,6 @@ public void onClick(ClickEvent event) { } } - // TODO: Replace with ShortString::shorten when gwt can resolve the module - private String shorten(String s, int maxLength) { - String ellipsis = "…"; - if (s.length() <= maxLength) { - return s; - } - return s.substring(0, maxLength - ellipsis.length()) + ellipsis; - } - private static boolean odd(int n) { return n % 2 != 0; } From 452586308cc9e764e8f64585fcefb33f14c15adc Mon Sep 17 00:00:00 2001 From: Alex Eng Date: Mon, 24 Jul 2017 08:52:34 +1000 Subject: [PATCH 105/116] fix: fix broken functional-test --- .../main/java/org/zanata/rest/client/AsyncProcessClient.java | 2 +- .../src/test/java/org/zanata/util/ZanataRestCaller.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/zanata-rest-client/src/main/java/org/zanata/rest/client/AsyncProcessClient.java b/client/zanata-rest-client/src/main/java/org/zanata/rest/client/AsyncProcessClient.java index 97d4068a5b..8d80f9b104 100644 --- a/client/zanata-rest-client/src/main/java/org/zanata/rest/client/AsyncProcessClient.java +++ b/client/zanata-rest-client/src/main/java/org/zanata/rest/client/AsyncProcessClient.java @@ -146,7 +146,7 @@ public ProcessStatus startTranslatedDocCreationOrUpdateWithDocId( .path("resource") .path("translations").path(locale.toString()); Response response = webResource - .queryParam("docid", docId) + .queryParam("docId", docId) .queryParam("ext", extensions.toArray()) .queryParam("merge", merge) .queryParam("assignCreditToUploader", String.valueOf(assignCreditToUploader)) diff --git a/server/functional-test/src/test/java/org/zanata/util/ZanataRestCaller.java b/server/functional-test/src/test/java/org/zanata/util/ZanataRestCaller.java index c8102aa7b7..62afd20c9a 100644 --- a/server/functional-test/src/test/java/org/zanata/util/ZanataRestCaller.java +++ b/server/functional-test/src/test/java/org/zanata/util/ZanataRestCaller.java @@ -160,9 +160,9 @@ public static TextFlow buildTextFlow(String resId, String... contents) { } public void postTargetDocResource(String projectSlug, String iterationSlug, - String idNoSlash, LocaleId localeId, + String docId, LocaleId localeId, TranslationsResource translationsResource, String mergeType) { - asyncPushTarget(projectSlug, iterationSlug, idNoSlash, localeId, + asyncPushTarget(projectSlug, iterationSlug, docId, localeId, translationsResource, mergeType, false); } From 8466ce8086e78ab4abcd42b24a55decee2653edc Mon Sep 17 00:00:00 2001 From: Alex Eng Date: Mon, 24 Jul 2017 10:30:16 +1000 Subject: [PATCH 106/116] chore: migrate css and js from assets into repo https://zanata.atlassian.net/browse/ZNTA-2111 --- .../main/webapp/webtrans/Application.xhtml | 8 +- server/pom.xml | 7 - server/zanata-war/pom.xml | 5 - .../org/zanata/WebAssetsConfiguration.java | 91 - .../org/zanata/servlet/UrlRewriteConfig.java | 11 - .../webapp/WEB-INF/template/scripts.xhtml | 2 +- .../webapp/WEB-INF/template/template.xhtml | 9 +- .../WEB-INF/template/template_nobanner.xhtml | 6 +- .../zanata-war/src/main/webapp/a/index.xhtml | 3 +- .../google_password_reset_request.xhtml | 2 +- .../webapp/account/inactive_account.xhtml | 2 +- .../src/main/webapp/account/login.xhtml | 2 +- .../main/webapp/account/password_reset.xhtml | 2 +- .../account/password_reset_request.xhtml | 3 +- .../src/main/webapp/account/register.xhtml | 2 +- .../src/main/webapp/editor/index.xhtml | 3 +- .../resources/assets/css/application.css | 1956 ++++ .../webapp/resources/assets/css/style.css | 9012 +++++++++++++++++ .../assets/fonts/zanata-v6/selection.json | 1343 +++ .../assets/fonts/zanata-v6/zanata.eot | Bin 0 -> 12924 bytes .../assets/fonts/zanata-v6/zanata.svg | 63 + .../assets/fonts/zanata-v6/zanata.ttf | Bin 0 -> 12764 bytes .../assets/fonts/zanata-v6/zanata.woff | Bin 0 -> 12839 bytes .../resources/assets/img/fedora-logo.svg | 24 + .../resources/assets/img/google-logo.svg | 36 + .../resources/assets/img/logo/logo-text.svg | 11 + .../webapp/resources/assets/img/logo/logo.ico | Bin 0 -> 40299 bytes .../webapp/resources/assets/img/logo/logo.png | Bin 0 -> 14068 bytes .../webapp/resources/assets/img/logo/logo.svg | 13 + .../resources/assets/img/openid-logo.svg | 15 + .../resources/assets/img/yahoo-logo.svg | 28 + .../main/webapp/resources/assets/script.js | 2581 +++++ 32 files changed, 15105 insertions(+), 135 deletions(-) delete mode 100644 server/zanata-war/src/main/java/org/zanata/WebAssetsConfiguration.java create mode 100644 server/zanata-war/src/main/webapp/resources/assets/css/application.css create mode 100644 server/zanata-war/src/main/webapp/resources/assets/css/style.css create mode 100755 server/zanata-war/src/main/webapp/resources/assets/fonts/zanata-v6/selection.json create mode 100755 server/zanata-war/src/main/webapp/resources/assets/fonts/zanata-v6/zanata.eot create mode 100755 server/zanata-war/src/main/webapp/resources/assets/fonts/zanata-v6/zanata.svg create mode 100755 server/zanata-war/src/main/webapp/resources/assets/fonts/zanata-v6/zanata.ttf create mode 100755 server/zanata-war/src/main/webapp/resources/assets/fonts/zanata-v6/zanata.woff create mode 100644 server/zanata-war/src/main/webapp/resources/assets/img/fedora-logo.svg create mode 100644 server/zanata-war/src/main/webapp/resources/assets/img/google-logo.svg create mode 100644 server/zanata-war/src/main/webapp/resources/assets/img/logo/logo-text.svg create mode 100644 server/zanata-war/src/main/webapp/resources/assets/img/logo/logo.ico create mode 100644 server/zanata-war/src/main/webapp/resources/assets/img/logo/logo.png create mode 100644 server/zanata-war/src/main/webapp/resources/assets/img/logo/logo.svg create mode 100644 server/zanata-war/src/main/webapp/resources/assets/img/openid-logo.svg create mode 100644 server/zanata-war/src/main/webapp/resources/assets/img/yahoo-logo.svg create mode 100644 server/zanata-war/src/main/webapp/resources/assets/script.js diff --git a/server/gwt-editor/src/main/webapp/webtrans/Application.xhtml b/server/gwt-editor/src/main/webapp/webtrans/Application.xhtml index 79c7a1cebc..7db1107817 100644 --- a/server/gwt-editor/src/main/webapp/webtrans/Application.xhtml +++ b/server/gwt-editor/src/main/webapp/webtrans/Application.xhtml @@ -19,13 +19,13 @@ #{msgs['jsf.PageTitle']} - + - - + + diff --git a/server/pom.xml b/server/pom.xml index b0dac85393..32f5af39e7 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -654,13 +654,6 @@ 2.2.1 - - - org.zanata - zanata-assets - ${zanata.assets.version} - - org.zanata zanata-frontend diff --git a/server/zanata-war/pom.xml b/server/zanata-war/pom.xml index bfecfafae2..a6707deb12 100644 --- a/server/zanata-war/pom.xml +++ b/server/zanata-war/pom.xml @@ -856,11 +856,6 @@ - - org.zanata - zanata-assets - - org.zanata zanata-frontend diff --git a/server/zanata-war/src/main/java/org/zanata/WebAssetsConfiguration.java b/server/zanata-war/src/main/java/org/zanata/WebAssetsConfiguration.java deleted file mode 100644 index 9932ea6541..0000000000 --- a/server/zanata-war/src/main/java/org/zanata/WebAssetsConfiguration.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2015, 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; - -import org.apache.commons.lang.StringUtils; -import javax.annotation.PostConstruct; -import javax.inject.Named; - -import javax.faces.application.ResourceHandler; -import javax.faces.context.FacesContext; -import java.util.AbstractMap; -import java.util.Collections; -import java.util.Set; - -/** - * Utility component for accessing zanata-assets resources from JSF/HTML page. - * - * Usage in JSF/HTML page: - * Rendered URL from example above is: {@link #DEFAULT_WEB_ASSETS_URL}/img/logo/logo.ico - * - * {@link #DEFAULT_WEB_ASSETS_URL} can be overridden in system property {@link #ASSETS_PROPERTY_KEY} - * - * - * @author Alex Eng aeng@redhat.com - */ - -@Named("assets") -@javax.enterprise.context.ApplicationScoped -public class WebAssetsConfiguration extends AbstractMap { - - /** - * system property for zanata assets url - */ - private final static String ASSETS_PROPERTY_KEY = "zanata.assets.url"; - - /** - * Default url for zanata-assets, http://{zanata.url}/javax.faces.resource/jars/assets - */ - private final static String DEFAULT_WEB_ASSETS_URL = String.format("%s%s/%s/%s", - FacesContext.getCurrentInstance().getExternalContext() - .getRequestContextPath(), - ResourceHandler.RESOURCE_IDENTIFIER, "jars", "assets"); - - private String webAssetsUrlBase; - - @PostConstruct - public void postConstruct() { - String assetsProperty = System.getProperty(ASSETS_PROPERTY_KEY); - - /** - * Try with system property of {@link #ASSETS_PROPERTY_KEY} if exists, - * otherwise {@link #DEFAULT_WEB_ASSETS_URL} - */ - webAssetsUrlBase = - StringUtils.isEmpty(assetsProperty) ? DEFAULT_WEB_ASSETS_URL - : assetsProperty; - } - - private String getWebAssetsUrl(String resource) { - return webAssetsUrlBase + "/" + resource; - } - - @Override - public String get(Object key) { - return getWebAssetsUrl((String) key); - } - - @Override - public Set> entrySet() { - return Collections.emptySet(); - } -} diff --git a/server/zanata-war/src/main/java/org/zanata/servlet/UrlRewriteConfig.java b/server/zanata-war/src/main/java/org/zanata/servlet/UrlRewriteConfig.java index f4fa67b2f8..895d67bb3b 100644 --- a/server/zanata-war/src/main/java/org/zanata/servlet/UrlRewriteConfig.java +++ b/server/zanata-war/src/main/java/org/zanata/servlet/UrlRewriteConfig.java @@ -138,17 +138,6 @@ public Configuration getConfiguration(final ServletContext context) { .addRule(Join.path("/iteration/view/{projectSlug}/{iterationSlug}/{section}").to("/iteration/view.xhtml")) .where("section").matches(".*") - /* JSF serves zanata-assets with suffix of .xhtml only. - This is to make sure any reference to zanata-assets - without .xhtml can access the resource. - e.g. jars/assets/style.css forwards to - jars/assets/style.css.xhtml - */ - .addRule(Join.pathNonBinding("/javax.faces.resource/jars/assets/{path}") - .to("/javax.faces.resource/jars/assets/{path}.xhtml")) - .when(Direction.isInbound()) - .where("path").matches(".*(? - + diff --git a/server/zanata-war/src/main/webapp/WEB-INF/template/template.xhtml b/server/zanata-war/src/main/webapp/WEB-INF/template/template.xhtml index 2181eacdf4..b2f25717cd 100755 --- a/server/zanata-war/src/main/webapp/WEB-INF/template/template.xhtml +++ b/server/zanata-war/src/main/webapp/WEB-INF/template/template.xhtml @@ -28,13 +28,14 @@ - - - + + - + - + + + + + + + + + + diff --git a/server/zanata-war/src/main/webapp/resources/assets/img/google-logo.svg b/server/zanata-war/src/main/webapp/resources/assets/img/google-logo.svg new file mode 100644 index 0000000000..85dc345de7 --- /dev/null +++ b/server/zanata-war/src/main/webapp/resources/assets/img/google-logo.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + diff --git a/server/zanata-war/src/main/webapp/resources/assets/img/logo/logo-text.svg b/server/zanata-war/src/main/webapp/resources/assets/img/logo/logo-text.svg new file mode 100644 index 0000000000..d37fbc38fe --- /dev/null +++ b/server/zanata-war/src/main/webapp/resources/assets/img/logo/logo-text.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/server/zanata-war/src/main/webapp/resources/assets/img/logo/logo.ico b/server/zanata-war/src/main/webapp/resources/assets/img/logo/logo.ico new file mode 100644 index 0000000000000000000000000000000000000000..efe19e4349211e9465e30d53ec3678b06c58382f GIT binary patch literal 40299 zcmeFa2UJ$cvM9U>l9LD`84(O1U;vSf0+J*r0f~a-pduncz(~$H=cEJy5s)N7a?VMD zARr)0kPNSz@teyyI_J!}=lyT}Yt3G(r+fF;T~%FGT~%GXaS#Lz!9++%5KuE9Cl4UV z6$C*T7{0%gA&4dDJ9FmyI~#(8P=W#Af#Wk(5u^-EI0@bX2+;FeKd2A{%=>RV)lmrH zt}}xEGgukU2-aXSqSBv&BzGqv?|MP$Nk$TCf)V+uc!aJi3AxpkfJp2jf1ckOhp-N$ zAT|A|$Utv0;?tRcXjg?I+NJ(TMpG2BJ&=Yh1DJt7!`l&yoa{|OCcyl_H*N?q97Bj8 zhu-)imH=lLfVtC`f>d@VBmHpfei*yq$bs%eq#FDd@x7n;l_z4{k%)A?e}T3;mW8p~ znTR|Mzlj_GIKsPAkZQP26pW4(M7k#lnQZk%NV+2sRzPFbPzL%gEQ9IDPF(~N0@jNL z$5(|Q2O*t3U=C_Nz#ReR$H4cd-`24(kcPh7n}W7CKj#@@27basjfZ0aj!4uyXqSRD z-a)+sS`CKMknP{*qwfMfj@^_*fTkcAa7O8~#`qTWGG(h`GIL;4|% z5x|4`aI_5A566JHcY#bxU>iQ&2}p2L6k5i4MuZs9stx2=3V6BFmx{JGzYo9|%S77+ zGSuB0pM<1>HH5%6eBMSN;9I5Gt_VxsG^5 z6wZY*0rX_RF(`T=&9Fc?{b|TNpw%3Xg%99;4wzrOtMVH!_WF_#jlm3L3xyNT1-iBc z=Dx0vK#s#PK!!&LQju&Rx1rY9y=?`%e}8~ZKY@IL^uxL@8Cma2L_7g5N5I=G0B>d> z9Vz(PTnJ=u9gr_6$T;Aq30RXGptS(J7XnxT-`BgRL%$>ap-~=$5CA%9e(3(^^)EO8 z4FLlv!k|F=x%U7Y`~Uj+nSJ~ZXhLhsK!|%15lUEK8)b)n1*<*~IRy60wWe_7yI1+u z$e;H^9R&I=19UeS_<&kq|33hDpJ9P*pv!fjKN#2~8DK*RP*BQ&?F9SF3e0V7k4NNC z{r_&AaSOo(HpL9s_#S8rKE6cXodgBi9h5DG?TMV<>`7x3`fgN3iB$Fkk$K!7$=D2ny-Jg9vT07h(d& zbpB?Sf5Q#v*aZBa*|VML$O_bpA7K3S71&l5pkuQTH_(~(ra0u-zJbtJ!WiHXD3s7A zbtE7S!{2=}wC`};P%nV5w1#tmezxzy0x)45vJcjun&0DvGRX7ZRAd6>Bfvly6M?W} z4=;JLGa}y-ifc}Q#Xw0& zJ={lt&iwtqb;cmHK)(J!9?N?^@Vo!tj~~Kribg_zWru*@%Y(3iJQ^UM_rr(n_C(|& z^vy7?0Vvfkh?xM-TcKSA{^U=z!7)%KKt3D$V<{AVSVJB(#v+x64k1)vIP@_% zaNhn0$lhrWM-tMuKTg}@O)@eF_ej^im~Q`E*zS!-eEw1nU{4fzBKN^iXq%ue?8U{P z-h05h&Gz1Vwd|(@v_T&3m z8`_AfV8jE=`+e=84bK;O5C>TQbNIghf#)2!#{rHRl}pG8@Eb7)1;S9|jTix&RSVAx zzp_0)(g61Zlo6OGfx-de9x}lH={@-;AvUOfR9zd1u-Akk>+izQchg)EM{qXX^J&nY z@3-+k;`;F&b$Z4g7uc#z=(~TVXFuXZ zy+hff&P8xfqhLc_2YB1|bT0v|%5R=9R(f4k!lNmM_ohG!u7J6!XRu>aLNlnwBQ%RQ-x-Oqe0j5&ebT7|j=WRMQ+ zISMbThWr3DM*Wp-`H>FDBRC%Ho5r8{69^mnU4Z)wj88#KGx#nPp+@2Sv4;5rD5HNz z*C3xjK4iN;8S$<2M~HrewI|OMktskU=a1ule24KRfcqKh@Q>?7z3;`A z;H=!4{HK@@0sD&{tkVM6kZveXm|y8nLF)&5n(Iegzj_C8;W) z{wN6S?RiG@u^^OA@yGLg-lF}OYYo7m#24JTg;9f$l8SX=1pVvY8hJp|6 zDD>s9!1g4lp^m{b0w{%mra$TVukiiY4|NpS$WVyuyZpL={Dh!A0lc*Wda{>;1N3ym z0&u;9eek#TjJW7q#%M8NX^j8#FdO9=Q@ zDOg||_Vt0^{tn)9knbGGKum!ze$gC{occR+|J||RT#LVV22V!3Kx|M0;?8Ms7TbVv z4vbG=*^7-pAN&o(12rHP^M0R-Tmfr>Il@0Z)$Rx(IBy#br6au{zc>N%o&R;shw&Gn z!x5Z^dSToO;~AK*foBF(O!s4r`Zff|b|#|lf^UU=wIPU8`S))ikZ$m;&KRt-8^&KC z4xa9aL)ibc!2d-DR^YSIM0HU9;8sOK>E1M^>mPI?G8 zICE9O^+O#)#q+R+{O?Rc0{#Nl-~I`lMef7=CESM)2jmr4%Mi$^=@eM}Paft6z^Gh0 z%$vbN3KA~VuRIV#0IvzG8|41~hjvsO)*uhG4s3$M5Agn@S8(pK-8)MIxDfVlZ6v-U z^5?NXKmzj%kk2s31kbfFKXv5gGvqq3rFBr>;6C5ab5#Cz|K5jqfDN((bN}N9>M_i3 zL-?=&-QWHTn5bO-5r7cV4Q)Mn>O({k=zlp%-}ciD+u!wl6Uamtlw0tO3UTep0pJ5U z8_oY@0buX5!ki5%?*i8W;Q#(zdml`gx4;7h<~1SRFwaaHV~>c#yd1EB+o(PBC)xp> z5H8RaQ!r=m=}AD$U>~F(;s$#5`DeKs)cBv(-@nn9{bpBw(|2Hd9{w;E(hYOLFdqu( zhV&owFh}^Bqmg8=Ki2m4383Rgy5T#d59$)k4}y7rc!2G3L7mef3~&xE|2yYVn3LN- zANcQA&O-llALBbRNIRq(>N&|RRfMB990>xx_barokiMVMjiP-|zxRC)`VMoif;n*D z3-bQJKVbj%kNH)5&j*6ihBVZL?|sjLd;Ir2?tb9=+chD`VL;C`qy^#v{^l*DasQb8 z?eBN0R-x{~b%VLV`+tXR$TuL982G*DU(vh&cZk0+3dtiQ+uJX2&%o~o|MCIy4T7}n z?Wbg94Sa9>WgHD+6=RgVKz?-x$m{aY5P%q;4#vXJzU`;+uiB9QrWm9Mz=OO;`8M32 z!QbBp=obcdd^uP}j2D z_VB}42xW8sQjcKH7}&!PkS0hQ(21n|bfDT$uX+=aCWr(28!)aI_1n*C=p(>--$0oA zY5c1;^ufTNjwoK)yU&O6cW^C#`2bs01Zje_fp+uH&XJJUAO@a*>-?4O|A=JIN2elR z;GDmrd;f0`c6BHc4q!pLVO$60@Rxc7co_)i?de4V@)3R$0CWEEG=OjMKu%v_?6F6G z0^<0G0l#}pTE-& zc>J??0N%3%G%TR>2ecpmf?n7S`2=H57`s6oKKSAZas$M^d%ojWH1F?+yo7h4VjK}g zFdzB?2nQAzSN-7udhrm_zo$RR$QQ8hpw9i_f%njWe;b81eNPvXk;Fd?`0WMyK6n;{ zHXOo$_+Xq*>THBu0C9fL-;n`4#{hfOuPMIwT^ePN;MwO74~QfF$F8R!V=zYh!vOFC z{VLcS)lfJ0VgmRr{(tUVL%QMJITQ|*|D;HELS&j_k#rb${;Sw+KmSo}$X9TmDGk7e zdh{nd1noM|g+@pdTra>=18D_g|MUQz4?)QZ#C}V_PBDT(5axcm4^n}2=u8#=$<|kFG&lU_PTO34J%i z6|n~0P&c8CAdxta94qlhtbv@`AWrC0pdSAndVe+++I6rOR^eSIfaebnu!DQ|1K_+p ze-G}0{b9hq7q~A#jIsdlD!>Bn9#(;$Ni@N|i3)$j0qEfXgt4bz0N&4N`MZ6Pb_f&D zUkq}zEc?jW(`kV74dfGQ?+zsX^?l{i0OUp8_xxBzAhP~82#EoCgApi~zq2?0opnIE z;dgDIt5!cb-|gK!1MAwm+XV3g-Ot>=zMr)V+z}xVcW*XD!|}hJ8~)pL!+j3v0e<++ zuX3~B?MdFA&H!0M8i0M1{29%tzP-O^0Dl(%*17th?#F+{_q{y>@_1lR+QJwRh5N^P z?|VPUnL&7P4j5nctMT8@%f|g_X#KzO<-eob``3bsOMt%A{HuEl(7ytm`UrUr=fQhf zK!-(tTqEio#-qUYB*L8aew_cUHr(&<&Iib;Jl=o54TXPy{VozA1va@3@*Lua_8i#% z=>21U)`s6rz#97go3`b5o+l$+@XY)(y!-pg0S$ofB~S+-?a-G3+IuVg_u`cOLx0+a zXEhkZ{5NzT%KkU`BN33UpCa7X32i6L&7)|CbHV#(VAC(`8}=`oARf7og7Kf~&)yya z-#5Uwi(mR06d_P|!QQ+9Y|#u#XTGm{8QvF1jr(_NXosPlg?jgQ>4*9PWe(191wV^% z_tW6)4Df)vI6z-Y;T+T%?zcAh8>0V!b`*RdOL73W>o;2dy>-Ai2FQC8?7gSIimzbY z*c*4?JlMy!;2wJYp6~s>PvP3(eKIh=tLty-42tgkHOP^j0eI%1EdOmefNx#U1^~X6 zg7qhYIvAF{Hn`&s_V5U3Z$a7aw-ZorK)z-R{1)-=?$!OY{;Cbm`tsoW>-w+aV%QIH z@Bbb06v_?m0Z1n-u)U`j-|ac%2g(P-^9ERR8PM5Z+V@}4_wV$BHCV#98_IXT93b6* zw{tL04Df$~^g&u-4P^%DgLZ7MfHv$yjoI6$;O{|zd{e*w4F^15{9k(jjczEL^t(+5 z`U~!~o`p!^*%QcK3Eo=-d$$DWa6fpT0X+Qz3v9zau+CCA2E>rcaL)fVf`0(~-9Jac z`-4MJ-r$_`v-_2(Y2~p94)ljG9^Z?}K^yj=e*b?_7x*LCfbJMjetJ&&e?ikfIRD|m zKOFdn1OIT~9}fJ(fqyvg4+sAL#{qYFS#d%Ty>2Ou}IOvPT- zIqSYROTBWLJi2R1EI^OhMKn${;e+w)$IWS-}nXUov-jdBVVlzDh*$^_D{O+SEx8k6K5?nR2FmT&c5^ zj6gw`g4MP`R?f26s> z@`_Q?@>1>q`Z&JeZ6%4bGRSpriQqfB+h4|_uxqsndzkCVLbnQau73-=qQ|75d(c}q zOI#xO@*3u?SbDWNCTxquv|`#3ZuzUj2t&Vce4YKttK6L_-Gk|I9FHDr<$7V<#X#@` zo8k+^%keqNJ^S9)rZE=rCsi}P`SPwL6f57MD$SNCE%Ys0_KyFA;^2)>wsB!yM1ci_ zJV{m77B~85Zl@6$ZC$W9_nhgJo!-)_K>3F|j=sdzWmzN+k^e|c7JOiyW- zGsPF{s;}aHlKEuD`wzdK&m7vhDMn;mWiD13kdp5E zDXuY8CZOa#hIiB!u6;hU>*=K`p>W%|vdAl|qpuSR72|l*S6am{VJ=7!)k-E^DgKb@ zbUI~7FQE6>2N_>UZwf9sYl(T&8YT+y%N<;3BuSVTb40r72D+>zlEW5Hd{URp<)_DN zeI)<&(Dv&kQ+ttzkM$^?TQh8;>Dqr)3gBC%8`F38K89IvpG2Ajm*cqe`bnyRl{Zuz z+4B<bWNNF+(?dRb}ygm`IQ>O>q@nx8(6ADApulQejBfx zaRXoTj@j!J<9)PCxA?%$RMb*cyyaNZ&R3;URCYm~LBl9RXp{8R8pR{@kW(ef?Z{Cw zmYUl)PuX!tGIp2`DCGLRi_#z3kg>k^N$PGtKGGSYBO+^bP&I`;xMqxi+(Odj8P!Y7 z^J&YiXE_(WWK;qw1IuIr=_ahT9%Aoae(_;YS}?oG%8m<9Jo(d5(DN5Bh-j*BU%HJ> z!f=#@J__5S3%7UVo$(j+qrELaKK_!~qgLGX zWZ}cg_(&7$9SU+zne`&-qHfkWrZ>up-Lf=yD)91o*F&I7wftcpkV|} zwmCQ=0+r<^@|*O5Auklod&+2{nt6|3)#!^UDeG@@M>xpGb>p6*ADkxqh>mkp{^S}RA>Wv9#OM6h3>3J_g_^#y}2GW?-p6%!IYjAmxaF`|U1E(|=qC(Cu=GPM| zPgg=L3KU%TM|0=8N|Ly!r&koOLk|h z=KB^p3X4R_AdT&QG(^l3pGjw1JWf|+VUEkjROI@-?4A(p7yMq2A0!*kF%J}FwY5wK z4cKYYBY2?%$JJUyaobtFHf&$=@+znpl&&NN$)Tik8#H}Fn{}6}T?<8BRz=C^BF;|oXz(ntv7FTH^wi22bGeJA`zhhZ znB`{jX+Gbah@xyN?SW@(m1tP#1(heqzR*uM?~!PQkxr}g1#_I}&+QI{1am&>B7lOKm~L~gRYtJ`68!N66! z!9}$}zmBmw?K4Uy97vv#a~L=(S}g97uhx+VtOu!f^XW*MG5noo&*sy_`i^KY`ikE6 zrDC0|MRV-6^G#yh(%C#IpS5Ji)Y5&;Jz4Ivt*`oT6(z-r>Xe@&bL^HjA)UQ z*KZ%^8KwvDn8c%K^>s0(@*hNTyWoo-X7N80a4XGlLNtXgz&}%5j7VfYk9vtBzEKf5 zPn{J+gsGSoWscnAJ(%w+%H;8>%9;LiV^z`93a_VWH1x>_U6PJ=xO4|JHBOLfj>-kH!T2IJ?&{kmK8ZPx{IB&aRGDfDA<$4P0jHYs5`Q#ZkP9XNa^-j7% zBG$wbt!!>bl>VYZ-9bAh;W0ZGQR=pKnz!nLJ|92i+?=a??A(KWfGt*p^XX`2-=XEI zxzy=o%^HJ%OnV%*`}&nzJ`;`mzq!P#9x!oCeXb`719>m*=7Yup1$N?@lfAV(>FaO+FjmW9p2ihrv7pGg5`w}Vzy#G z5dn&RzZS8@uZNhdWckI>L(Z$BVX%2oS3Qa%YHiOR5pdfk`Q+GV@)3#4Swo*2T@s|> zetFC2qoRGXAno}(*wW}3O8C#V{Tl9#Tsda{qMm@+UQ@*|LSxAPy3c$0Guj?A?{r6l z{Dzn_Eryl@@^-h)#qcCRL4%?@>>`aWW}KNIViRhA^-Wbpcp_sv|dYr>3P9Js1_R&`^Xah+;C zdJ)&8ny?XV`U2C9Q=B=e1D0hogvUKIYTp%pykehlG@1Aj* z5YstHcl0Jz2YLPZS&36DEzg{*aKb3F(MUL(Cl+0t*vM2AbF#;)y2`glW^tae7VEJi zWNhV<-wJiQJ9IVMnUvp#%&jNfFL>gABbIDVrftknUi%&y%abKd|3m6=%6Cs{Q)PY- zMt0Hj@UK3J;3Od`lO61R?~`=w?mL|dei&TZEZPaa64;HxVPXf=O-IGjhoJAv5||B zR;5wdhM`kO`ZV%l%~a>n7Gy|>vYrHzkUgFs$zusO>EwFwSuaRw7YoNX(T}DeJVoT3 zg9y2It!uV%uaDVuiqh+(VG7S7V}8WiZehk~OR3@Ow}QNNDxpsiX&IHZLJw)~Q>*b` zUDXazm%DVVc&ni#q$}<1@E0E%BE#HP8)8K)*SK8=Jgn@NZ>4x%*e=}84=_EV&^xi~ z-LN?{KMg%+h{8TFHqD#N@PZ$!(?gD_e+9?Z?NiM&nU!Oslfq27E)5M?4L5brZlLKl zbZFPjtXe$|*1z|xI59F~i$G)D;mJdJmH4-otBkey8sYCbO#+Pv7R&lhES{CXuy{q` zt?ut0ku97S)^Itr!)@z@P189d2*;bm6X-2p39S5sa$CPTtRE2 z)cfjgZuYJ1ienSjK7NMJlK7y?O=~+bn4CSCs?DE0u z{JZ*|JB-hy#kIELt|XQ#F>xNB6~Hmm7a2>yubXk8YEO=q3B(F}eQB3ixp=n2T#4Y_ zdC9KoHk%gO;q9Xq_}SLczR42L_`-{@Z@4mD%6aZ^vm>%moAF!8b5BFvQ1$%#&Hbil z)_A3b+!1<_H+b*I?=M^;q%N1q-g)gGZ-JY2y#({j{aaQ{K5L;#EPY$U55JB)qzt>; z%}n+Lq>r0J|aW#28V^~P3F+tF5> zz`&(rR2mg(ryV#_5(kCH@LngMJ~{3-@vLsrNoKJyez`OB2@C#O$O==g$YB>=?3lZ9 zZR$o3gi8)eYn`rovwelNto$k=R!naQW|Vk)-NWeT%&}HS$k`m~>TZg5vk{S|vTZ+~ zXm)5KQ;=3(n71FNX#>k@CUbv}e?U(!+E98d_w9sjDZ+XQLnIT^k5lhm`T6NIOHaP#KfKH9bJFg7o|$km~*JCHi=)yTXf3Q9_`UaU5V(ZCK1ipamAyK`lmIPF@!&)vh64}DdwEvaycC4Ga1$%4)v2} zlI*=qENf?K(`=W!o)aS;hl#7N9DFp#KrbMoTk7x%TWwIO^^VXh;}uE}wMMR_bxF2Q z(+!$@9x&_jb4EX{_D&tAPrM@f&f!-UOG&aGghc{Q!PC@jR1T%*{aBCoYOhkCyAYmD z)`kA_r{Os%=+>8|#XN{wpB{oA^@jxca^o!_oQ($Z{Ez;TLmBGj3Hv%ls%$p@#cD{ z;v;(+Q zLgH>5xr}|sh0fC}vF5Ajv3u1VZ~r{MYNYu^I+H)DU|D@FZ-|onAXUzQ-o3HK#S{L9 zYdabyXU86PAudYxugxEJX@AbLHRU*Tr8YxGx%v>Mn*3=SKEk?PUlmE2N9>eu6*)vI zOY2D{FYw{k-ws3HdCytcXk^lMVmYKM1Zk!gV7l-4ZGwUqQ~jE{;hp%-O*GQm{4#Q- zIvn^8isbcpPTTVq*0k&sOmUU?cGwi=+_p9L;TQW&o=PtwXH35GSSOY=+paW!aZ^uQ z$Ga2HF=c6bf6JWZdQa8miDWrEtMszl-7;Seg&981^LxiF*K#(`r(d!6a7{GvDyK+exy<`)u06 z9`YA&qY-|(C~iJk-y0HzDWBb*NU}X&AIq;pT+Dj^;iz6iAb*iuM{u-Ik|h41k-(uV z%UgjD$IODQZ64jECFwt^jdxM^w)Mr@4%R!1qN>qSTCXs`8Ec72=d0XhqRrW*=H-uay4$ z8{L6MXVt2)6G7L^sk5JnoRC{q=)kLO*B5u`Ktc>{@>Lky z8-WveDtM-Nm!4f7t6=6#TS~p@WA_R1i}N{FeSJ}@&upBfe*SL1u%E8icDWSM=+UV( zJ}%6ucw;*P!nrNU;9m9Z(dsAbL6NImJuQTs6egFJ^_31OR*oH5p6ci{xjNz!XKI#t z+zF9T7D!%GUc9()T$@B*Zng#*o5<2cUA9Z$kAhKZ8$GT@RYHN7UM4|;wn}w3V{_5Rgb?4;+juW+Qak3%xQA%v|b|U1jR~k4Rt4Pd7WGp?P2=&lkf%%YE4S zXy_Dc#73hhTsi8Z#m9wz3)JCD%~?{)ZnF25FX?1SIgbiqe%@?E+Wk*buN4$d(AE9*OxnzeELaPr)wg}KKt?}lF%4_ROV_xyL zJlxx8b?E}Lv}|k5MCK~tg|jsgN9y@9uU)ZS6~VJRGC-g=t06-%y7DT;UM7nxxA7gC zaIB!^MVw(_DK7qW1br^yx*{%4zM(5uZGW9>&TQ6G44P|9lF#bc7iKxPL!B8tTiUy? zhxb=K;&qZ3`%*jCbSy&xxfDia6-OcDT4;XtED<7G_?hPMV_T7jZV{(?ZO~31L~yP# zep&FxF=t2%x594kFXVJ-Q}rQR1dZ;ni-;-O!6LW!8|yOm zhT787)&>$&$z)1K6<(*F(wuC1`C6A~-Eq5GxzLJj94+qNB_dm)ndk4~Do7M`&nYL! zW4CTk2-+L#au{wmXa)(dlVYJ^VZ5O!0U08+Z&7zPvr>-}mM15S&z^qkZT*FZi;P8l zk>=<`b?4V~C-1&=o^>w!T&?v@2MYPXl-P!sVPVCtNm4UeyKT`FLoqA=Shk2@+xYs<){e#Jl(ODr?ZQj^-*PSWbFJQTB&rIH^ zlkBM$my_MX=Mpk4ock7&Rb+Vk$T>cm{>iux!cRC!yvhBYdoef@jIff>R8lG@^9*Ab zXbu*g&0ll5X3n~P@7`tS9Wt&oeP$O~f!3hN3w+m?dP%v~3%1W52#i%?nipCR$95!$ zp%^4DURd-s*4^Q1u&U|JNM_ba!<);U3py%A-I&?W%z6=6ZM#y8lc|@Uf;HmHYxgAM zWLH~!dm_wUDN?5G?u!hyMUW zjI-WA`fbFkydZfyvCE9@jmK5;yd>2=Wu`7}kKe3$Y#6rE(NF66{%RUWXxf8g2-*b! zJqu$GVMGAE$=Q&;J;AELb<|+yD&l(8S9_I^aEABsVQ1%Xje>106%~wcWmv(_c1G9e zUX#tW6HZhpo|!iqo1Hf0QEwY0&YU1n@P8P=C7jY}vRHDnyC8hr-Qa}ke7F5HXa5Jm zC^7QPFOR3(7ch`6>mvVqRL?}A#eMb3BW^3Xh5mV32! zu3|8VhR4V~K}$#lSBhy;Uq&f>EqaZZq2j@`=rz(aBn*OastkT>^Ynx*iIoral^@X; zaF*20FE?XTWDIhbW>qJAjrQs5?qJ70fK6JA#*_W_?u50Dg;c6IqnCQX zN4G_N6~mH2nnke$V+su9MtN0?o==|XkdQnEI(B-|irE2li_E;cOAgaaoLiN681A9( zMpmhZtrsztXY%p8gq)pK-5+1b@e%Igl{xatR_vWMa{pvdt`>c#T%-1x6jv5g?^9N) zw>UFJ6v;xwf?ML;N5;J~%H7ahj`Kv1hV~a+-pY2*Y7mysKA4h3Op0bX%8WtbCM888 ziGJ8=h3f(3*r(cTM|v3tM+|S?4-3l6zWCijy#ih(PgwhXD{Rkyyp$ICL_mBjew8(N zL%eP2qeYpkSE0_yu{PC%o2I681+qqFx4RZt^n7>r#>j;C9fHIRkH=)I<))gEdu^r}HSO#d!pAAxDyz3J;36piu?ber$hi#oOHVe$> zs|~;q-0Hb|-&RqZJ$v`i%j#mja3=L8eERvdV^XWvztIskEJ(8+UUAB2yA`LZpiy zn|WnP%KPneH`~!FVV5X9jkAYv7y>E?)|b77+TAQ)x2x@z2@e;4Wj43XmCU30LWgbp z@-#M6iF}Z;9k$q3mGQ*=H|J&3GMWyr&~-+6GOa6@I(2ZMNpu}!p47QZCNh@tROGBV z&R0Y7&@&{~rW02Yw7{wXY7QAYYp!9tPscbv)GPu2LFam{=pk3*)YnSMH zCiN$m*KMh~nyIM0L~rOE(9#QU&ZARUC_9H3_i==AR z_F}?D)3oEA!X(^BA8c)?QaSZVFE5XJ29K!uj$0d8$j^@^Qax>%P~ty4_Qi}dN6EjQ zO>JbTSVwhqf`idfcKnX4g`8Z=Q%bh&1Y$&k_7)S}ma1g`u35Z-CiSU?>-xJh1JWt3 zF3o|08XJkRpZTq@5=gR@)!0jK`c|GXW+gDA7e1EV*0Y_=N1@P;?;B6+)LJNU8GqyH zQ8s6_Z;W@; z?sdH2?hCNN5xkY0HCoV-A*)a(*J@CvV-|KNU~rxxbx5!L{Hg6OY$P`-`_yMe(_9bF z``h$yH-tzuIX$C zxNB1;x$Y?^+UjjBYuK@GBPA-fR!)(hKh@0c2xKLbe?0X#QA3z&?ZygKNoRW zqU!VAUxlwQIWuja`1*9J@y^BR@DkUkrC7xxd` zazt!fabBMb?Wlqj)Y8h?W)ef@9O-9YFRm@RsNmWje2dmhrKGWlFXKFUu&cIpWk>o_ z2;O-P!Wig%*j(g>(eVnRawXOo3}N3x#AuO`weAv`?c3Qsl~2eu@^^2c zm5-ehGv762(5+?sRx`Bww&JJ={?f&)6Lx6}G~m=@z47^jXSYS9jzXoszz*i=^Z{lq zq8v4i`xs zLOYNH!R7}t9GOH`S3O!4bW8*K$ATf-Al7gvJ})aZ&F z+04e}WTtEom)Bh1L~2E%k?x3y^f4MfbJ5DP9@TwUOl|bSPoZIM=>*1mS>}6etdA|3 z_`AK1=8Li9TT+~S&D{GunNMiw4S(8aW>ql@?4_e?>o?T7B0m>?v;apsYEr|hfr$jN~#j}Hjz%cOYB@%xMxJ4v2jrjT>gCe0D8 zkj4xlStD$wKabCfM&goxOo~{0o05=6@1)b_nAoQRZw{9D3JsNjaM?G?RcN+p3frzS z%PUQr@vAakdR%I14q>hp*N27G?Jz=GH1mzhHF5*^;@M(pTQ1aVIgP6DBEo`;6`wjT zR_aAeTo->NtFNY$hd+yXO|nk7q6b5j?j|};q0EJ2#WSxQ9>n{n3QFX?FZ0oFust}S z-=(>VC+&l0!&|<)$ROi%n~OK?#F-n;CJYwI8j4GF^{lBrxu$1=fzlJ>)+mI?FINlcnRqH%1#{DQ2SRq9tcwdK_0C zG4-LAnp?HuV^|ZUJ7Oz#lcCQ?j)a~aOOW6z7RxqaTV5P!G3FyE3E83$H7G&5sW8(yWN+NnvC{n*Ak0 zdZ=n=^36Whw=z`F=iMfKJk#TBlXz@^zj`qf=fv}T2di%CuRY3){zzt+1HI$vYZ`|b z#1}f%dvGazO9FCL>()$LabHjpmg%Q6PX^E-qU1^6lKBtPwq12;?<)>E#l7&9BtmL} z=}gC)GgnT0%aA(}_4UP^4R?;%t|?ZSR>td{ujm4|s&=gp%*u$8hb&$@8-+M1tf*@F zl5K0bo$@aK9r(~{KjM1O#gyHx7{xk z`^CkH7SHQcq9)TiyDZ&iU1HTY1L872lfT&P4xk&G$ktcAZCpK`4|*-<9t*o zqkSk^-&Z_2z0@fIyiZCk=O44zoq+GfiEu<#Pz2=8#g4nR>#XQyiyW?vhaUo7_z0Z_I5sE_=24J@ZLE z=6hc`B>sALeW&>i{f_0_`Z-@NxwgmHA>(xZWu03jOKah?cMcK+>wOHVnG)`}o;H5@ z@qwk|C8W}m>5x;nh;`DvSwW_ANE%7%F`vf;PO+Wpi;qIlaSx3XIZnMk6lxHsm3*9S z$Yz6FPAX=o%5IkBjq+QxIm-CC_g`^`ho6%eiG^7XfG$caE^|W4RbCDM_AGug@Mu7_Y9A-Kky_USEQM`>V7oJiydyV$J8YWt0&PYyX$ zn%t~vC_h?WX{wxFJD7b=jDNkqEA(yh3BI!QKCZ%)RT0Agv$dAHClxgU6zmaUc?9oh z6koD#u5pY4*YX)NxvwH2IW)?uN8U}(2|km5_E}Evjj0v?i}Pli#x!F%%kcrUy9t}@ z4iw%=D=umx*Y$^6E24@Rr8k0Ia6f%jly#Jubk=w;BCm{lS)U{ z2SOb5D2s9_DoAtpqH#f9CPzwJqk^T>{TcfWo5e(9`3ke#hvr$HBU|AVZXn3Sz~E6FNRXo-3g7sXuef3Zo%xdYB}Gm7}j{a*%m+l6#A zeWg1b6lkw;%RRU<)bwJLI8K~=b&fA7|D%CD!oX_6Wh=b9?jpj~yQRo{@Hk!6R;Pd8 zuJwx-=f34JnTBFqtZ)@%9=zFsp;qF1$Hct=yNfcEvFY`y+NHYpB3pC#q?Tk{nLOci zNLqxVnU&D8qY_bqdK>nmiNzA8qS9uIK%H)4LeCx3`~3^cJ3-|iJo4#2WtjEEoL`#X z?k35b%BkQMwzn)YL3fdknr5{1GrM^&rS%(onfjtV$4i+9-GrE;&fhGwUXLqmtgUz# zN|7O7%tD48GYu_!`0YgXgzW=tz%q_K2~A_fr8ZC?qf}}I8Quw-ZJCh^pWgZ14A)Sf zEq55?TW(WH5Oa=MJFLE{HeQh7)?uN`bt-v9QI;5yc=}BW^L9Lu3i%-=dH3v)P2O*O z^aZyckndN8m{)y0@!LvLAceM^2NM*RLxRxAcFG-9jGczzz;@r~?ajK5=>gqn{)NVquy%6sv zu>PD@UuJn^2b?t~g>HGDboV-pN&M`)xq)5KMzQN?E=SEcr+*#W zK`(bTnXAz=mNDUM2)4mXpt+5QpG((dt}`nx8+n)4 z^j`PAEfMkwm^eaysqrAvCnE-@-?@a|mXt%s2|nhdP9D&NoSaUkNmpnH(p-P~a)j&M z(^QUzT!QWb7qOV&&4}X`8c$<&;~sx(en6&@6Cj&%@joZ2oXHQ7Bh;-`4-?ie&-$@MUy;l<5^Je3y z;@DSlz6+%iA3ke7d@gFZrsp3!@|f31WyJ=c?~n>{O-c$~DF+T)qF<%t-G-}}F3!!5 z-nG9J5mh9yh&1SLmpXFeyp}?HE`I$CrHSWGH}T_%$~!u$xh~p;M*LZ%r#6V)^;_2+f<2FTb)a5>w znSHTKDwQBU&M_uYZp+Jj*R5JFFutyNaW^oc(~|l|*^& zu-VKog-(SE`h-p<+XMWU)2$4C0%FNM5g5MO9$d@}dh97`9oUGv23r!wT(xjl#PJ7_ zr70C^yMt~~i%Yo%o;zFuPhIQ_H?!=c1f3&Ct}!xh+b!l{(>Uj*dPUDvRZdBmAIyrq z84^dX5p5|3LjJ4jte3mG7sn*~hUCA#l6ZZHvON1i;xlGBS-yi?b#^*ljKb23FPD_; zg$J9}g2sKDpP87Hdw;sAxYEN%)cVH$vD0oM(e}Iv?Gm~|@ zU$c#xr`d$iy^gpcQ2e%y6j=D11-GZGePugbcXV!}Q%g&SbWD`XRs<*H@0{K+itKUb zNMsV9DiyME{7{rCH9OryXR?l1H_l)nBbmG*>F7*|1?`78_T}*t33MbWEq#iG`FuRI zH<-jOaFl*ud;2^2ogK4t795S+tV}+e6ibtxJ$yEjq$!}0v zwdU8zIbkGJANIsC>SDxK;q{=Ry_F;w5@xf?hOkJ|vGNG;Fp}{cSFm_+UVf`Sxv%fT z*9Up+g*Y`jmzU*O*PpBtq$Sk!gubeX;<@6Dn}g)=GN+u*NC-|M2J*RP7f$6~ZL>gH z?IHY{;_Q-7mZVZlJ-(bdm(=29l%>&H`U4WCxsT5`8eg;C+1Vz@>R64Mw>ZxCYR6#) z`vlE;ZsVgfx~1p@i|(S8b*;3T8buq*<+IdbE+4p=u+|T0K1m(;jMi%=jjPVP?s7<# z@67$rXGyl{gA)43ZpWPZmR<*pLP3eBm0%Gmr<>xIVQNqLB7=la%&p{mlaJD!L;LW# z4-d+=S7fJ;l&%svoxi6%6)l__TOTj;=@FP1L^&3>cM(}=k!eV z2WoWGXGrbmchU=`f~H$r1pCuhMjBZtJ(iT14-yIUPZ``j;644)&}t>!8JsqUVlE4L z$YZ|aZm_nAOJuhSwCBEB{Gpj#EpX7`N%TlI)`PrpxwnVPEWZXWd!DJG=LpMd9W!#i zAakvcv~kjri$wzMNFc?u0&?#D2AWIP!uWfM&D9GvBW)NGbg{%AD>{`*I-?qEn@#ZY zY6H*Jrh=;- z>CXP7gbRnqNRkvz*H4`gE9$41q}gC#1pg1-vkvn*w6k2kE$R z3p{sj2}*RVvoJ9YAK>L?CR;uH*%w>fY>gH3IPH?@r7C0Ppn5>CM#Ykn`a!LT7Y35Y_Oumvs zZ-ok5*Xw)(a+xE1bfNBwTQ8qQ?i{#7XcKAssqL8T<-#=u#tTonU*LEw>e$~%vb?2? zATCdC8~B{e3+v$t&N^qIYic&V-1$^Oa3MTn{;L{ws@sL^`#y)A^1Wl-1~{_5;)MjN z4>iOP2yxkBpD-*|y!~c*QOry%kWv37hnd;A@TJQ*30i}PPma|cx5(=>(8wI4B9x$M zxWBwbV<6LP9bTBjBbq7BbW~fD^0TLFb6&sPso@poVeUBr&ST^At&Bo%HgA?sw>lbq z)d}Gs`x-F8lk)iTpd{{2g~}|OKBBu^G&tt7CB)YGT-IZ}5wVgs9h&2eR+%Xuo^`_U zDF4VDi(84~>X#%bfS~ z71O!<=AzI;WiBP7c0H9C#`5@53>uB zwJs(zRy%izn4UQjXKhoEM&yCva#X8VujWGNtGD*};(c#Vr5$vPKA%Xy|DkL4V3bXP z#W(2(OzI`Uv@KX&pC8|{S$M2uZIr?Ae*y*~`Q5;8NWLd~BmJskm+Zbw@_G*y;X1C( zEk&76!#c05s;P92i30#u*htFzLL42?6D{GWQ|)j1*5RDsQ~SG%DvsZ3^e_hqwR9V)5}ufKs>=4%1Hia(Re2Ru6jRHs!T5&$sV;g8jz zzeI#rpvubtr?V@ab~3+B%q!7SWIB@XSHpo~`2FLnh~%~Ak)P?7c-&;Kw;6RkV-npm zwgc!%#(Rq2{yh2XhRr`Q2$Pndh-bKmkYur%_+Rcv_%8rJToDTZ!%tX;8S}LWYXEl< ziW3Lq%A3V?H;I~V#SSa|+f66`_EXf5|84}f{6QWch!M-GBq+(+OL#kU*_YFjPCS1y z-SB8zbfhK_;K|SDvn#cCGNa>`Zi0za$Of^TS`9Mx_cSP9nE20K5dT!iXh!-8iuU6w zJKs3uUNmi4`~A)s|8v-BrPQy(vs7AkGL)MyBJ+ZuB?4B&*rj$3u;Y}JlXEnkdc|ZK zcwZ~r0gVyu2>d zci05FaA;$6yD|u{;;(Mm{CQj_Ej$D}MGe%RUH+}JXmd$bKBk++IR8{8M?3&rAx4h2Z6*W?Vk`Qg{7OHVB8 zG|@j*Ujgg0WBlC1pt!nO)Y@O0L$TNb`u6+pjOe^E08pUWDJLL7f1^OCry32uuBuW{Qxpo2d_<9Gsd^X$8Zwi5uv|T@y8ed;Fflly{85OYecP+H7P)qN6>_Yt*h!tMvo2c zyqc~#{w7-f{bg$T?pds~5heX(v|mOv&LGg}klxh&f>%v<@-m`7mFwi_QBrOawf2`} zC#iwpMk*f{c3x&F-zoeK-1bn6R}!@2RLNMKrp{cB8st zEb~kJQ`CTeyAYEga{$UDWK|hNlaQjzT7|bX%f*KSA!PdN6`#;;7ha*PUpYpJ1XiSF1S^-m&G_8vu{ zu`D<8VG&z5mj7@Tl0CjVXc6bkNz#c6Qpx?WumufaQ9V-Lq_~h zJhVpC9j|lhqGQSFnU8gGJrU`Uxl)dbQXdF%li*x`w+S3eD*!1HQ2C~WTlW;C3G+ET9XVg1DEs)0rSWS1fg7G4^A<6;_` zKb%%CzD6l4{U3vw7U!*tj4Zzy2}O{1Q6jhRIVxIqLss=Bs+H*u4n!7vyshab(e zX7Irr34nW2wCn{bC-*i{Qh=5nMV7-93Z72`JAZ8kv-WF)7imrQJC@2%wu5`LiDw_ zzkfXSZ*K|^nj--)_oCq!)KFljFl{*2&$8@rBX!sF^vWDwhnra#IN7CD4}da&sC0L) zne@z^m#ACT|5b^E*B{Il0}hl$ zEK-M~BESqgt4^X}C$11iXDt=!d4ttbbrq*y{N@m9-1JA;(+ z+SQO?n5x-d!_jf`5t*9%U*tYKUQ1h7!=)*mLb4gvUv?XU%wA0CKAjgE@fNF@qh&u|AJPF~Zd3?>C@mTqYJYiZ9*O5IHR{FQcV(>{XI=tmA z@Hg+o+m#7hMpbIaieEXfN(qP8AuH1*G(5jJV>A{ny%o6*|Dp0mD7w`@dwRi3SoVPk z1hIte^pV+p%M1W;FQ+Y^g0RU!!pwqPC)-eEDNMoO~3)7zqMg zcaVkp-iI0;b`#91M{(qtsNfUSZ`}gdSoo5xq)@0A4e7elbV8>tI-A@%AIp;J z6Orbtf_|uY;Pd|u%zoG40XFjasc5qDm&^gc)I~=icK!#L@{SPsCezl9N^~RbE;|!m zf`7H}UE60MUNTgt)0cC8L65f^-pKFJxH%k$VO;5>I;cgX*Ccn20h3@8goA- z=!di-$}AEdP6Ij?W|ZUc$CT>8w6rg|JcU4OkLV?7+`T!r5qT_5HPwoNhoHJ*9ROeo-$L+*?0pXoLP&=y zc3x;E7dD@jhX&HHPBW`xh>6G9Z-AEt>_}uZ5X4P~XI#~kuDSJk1W%2Sa(qYBDIWsO zo*o=W{f{37cBbd1U9{{{?B+XNmZe-#X}v3+CwBOe;qVjj_oe>%?^Ybo@E2NRKx)o(Be&R9+Aj1K{e z*Jb4|(BKYZFxsiTL8dIe3R#+_$g-R#(k~@3$Xb@4^3s>!>wjy-F$;XjtQoK>25kHN zVKrDjOSoweZLvrvOE8^z5NbMY>Cmd0&%iNu^JTN)PJCFCZzL%5c>Cz%*SFHBlOLlm zXI`jo+c*JRpqItNkBw{^EgM~UN8-Gk+mV9qv6PycvZNp44T=n#{Mx$T|1~y{xi2NU zOt{#ZBR*|q3zC(uWv8Q!Xng?lRFecG2_eLh+i76?S4`k@vQ6-Kux@~L1ZF4-SqT-P zn_uWe-OjiXro$@{PvObx@MF#LgQT&+&_fv8+JT^O=`iwmUX@jHi(d1CxA6qFF(i5k zl%GXIPh8E%tW>NC0L-Dng=ZoR_7l9aats+5PCtdMz9|wdz`F5oDT|E8jv`O~gvEg0 z+Np`NsnfQ{hhS27I;P9bd8U{@W*@4pjSb;nkF{hP)2 zB4hR6WmR<;_KdM(Ry1@eQk;EOEgcy=VO;=Vrc5gyCA)pEs4+aBf|Y_A&tW1Y?7jkL znKx+O(%b3zz6tNW3=YXYO|#zsD+)Q_h{ww4*~l|qqKDr)joKW~ro*!di7JHqXP^UY{IWIx zFrTI^dlsgvJ4JhA?HvNJfHlZrxFqk|HjHjMb<5s!mifl+%nSsqFf;=QSTEtCzyJGO zYS|V*;5!Mwv(AU0!u%TwjG#gJQ@IZ`_PfS(Si|vnrmi$JZbCCn`d_8~?M7Qny42W^ z_+xzlC{Uf$cKMrd66$M&Wgx)_RywND&|>nJ4W*&o7gij%))zJzvVOn}*J74700d2Z z^i1I;bZE;_a!y|7Y;z{6F#kpZ{U{h+PC2<#5j}aLq0ds>B>4gTu%<7)bTNaeWsCIz zfLX_zFGTV_l02T%jFSX_)0|Kw65dX+D7*$czGcx-<1ynU0Rw^2IS7~q3E+Tx8^?o;)xjN_GGM_mpF@ z>*alhTx`b~8Q`LMYbgk-iG-h~AJ-LF7{OUN$T0@2EHop=AnrqO!lg}U(4E&%lS4+p zhoH5D7z5!>Gw6`;0-XSKgAicS^ASpho_OY>$QmjuJI};i6v>cQ?KRm00NjNMKX#;? zypI3^tqnzSeo`O}0BF9Tz^+?qXwT)XcVu z8e^&@qKQWTpkSysc7C$z67qnaWfuT|eAkqpyG1%y;j=eY2s_ zAfQ>^;2@`lkeODEJw*N57bU^lOkZMVi~;vG?o~MY>Gss+FC(#W>s3gjm6O$8g|&=e zeDWi)hZ??)uIu!1EtgyJboK%Ovr_{B&s%0l0^A%AIBSw14g3q4haaF}`78Li#Y@6s zz>CMzT8VCx7S_QfFPcHR@sF$e}5XBos*vjE4u-JdoX$N z>E!jyjOzqU%6bzw^=wDL+4J=0pRX8}l8XB$rtmnk#ekOvW>^fE>bM{AeUne5DA;9yR^nHB(O(5%%{vQQxtJYw7zcvJ&2#C&Nxi6PiyIK0-3i(A zgy)1zi|H6g)>kNz;CTA6_%;iMi>KAC$~VasE9asM4j9=(})vv5o}Uaok| z6(zisqUtm}P4Cda%IdY`#%k=EW`uFkz%_52(!qk6w)sLR|p!h zs#L(wM#6`Hmk1(fBi9x87ie~T1L{AfCmq(Z4^nfTB|99AHS07?tw>R(@hnqjL)Gb2 zvF3jc0C4yI<5^dJ*L?usk(x69X!7JvfO0Ut$6E&N(43@#&4&`Q94XP*FYv_pgks8j zv})duR4|0!gjOs3jEL|dU=wM4(jR_!1G@J9&UE-u7r>?aJebyw)c_Lfe<=~I$72Lu zX~|)|83KaD5+LY*3TEE>tTr$r=s7q5fI0QdtXyi|;z>9Rjb`!Ekkrp9jtF}es%%EY zhL@_MF2n7g;>&-iB({)7b>=L=Rw@Y}f?N=lj586x<=H)$KQeW`uqmC}t0OgQeI|Kw z&Lx-oc-iHVcpNylK(%EL5U9|?ORR}!Z%i`*Tmu0l84ZOWL3W=zPaAVE(2KP#I626(tRtX5H?>#>W(TvF7}VR-(Iww147C5`V%2KNl9oc~ri8HI3*2b5xo;;E3yI!jB-A&gj#ajyth6wQ7}5 z-bUTX?d(Xhqm}IOdf4HdlW$_jC;csJKmadHnC2vpi9nzw8Fe60jQ>{ncvvZwye^&| zoB+TqJFCD+L$4k~PS=By+f`2sU)9A*gKp-x54#<+=!@^{;Dq<)R{Z%L@7Wa;QHn9a zmQhUJh>a&UQ`w)p=92KyF7f5Of6A=VNhUkT8YB>h_J(t3UDBKGyeYpS$hjE-ik@O6CeTWgIa>$ zL5is%^58*^aoTK9v2tS2R#M_utPWh=gG-nWkyK=ffqpFW*vdCK%nIplwh(9g$L8Xjx)^YqLFQw zG)hKxK|tMo3fy#gpBwR@KP0(5P2x~WiI-FqgaA?z>|@d+ z2AZ_Vk7WUS?rD8tIt?hCBt}umuek*e>ioU|O_)}tNuy(0fAlppZvOGm4LmM8oLBI} zpBd*NeO*ZYZl2(KuGZ#>pvl6Zfr%#r0Mr10fH!r4*s!;;xLxa0~mKLoRxGC`nSb!7@kx*286|~h4!8V;Q!8UFEWr2lwmmnnp1mO_&=_}X# z9^$7=dgK@gU}BZ>8j>PQVJr{aq7}Xx2#~S^x|b_xaOZClUC*ZfY{s$6{u~(4@t?GA z%js$`a4)3ZKjS;++N|22O*Q`B^Tt(J9IxM)q}&D&(b+9pkfc##;{X|U9&)<3DWTwB zDWvvLgP|7`McT<@sV$Rgyg#{(mHYRapZN5CWmVP z+>jfH0D^d?py+A}mG+_`-G8aJZHt|-0U*@@nf%j<V4ygh%OG_Xk?fsL*R@@re5EN~ z$w1&n)To}N0ZRg*;Mer$&MOhfwIf9eOuO6$0MV>2nB%23hn<55XdwJ^&xcgd2r;j5 zry^5KV4^#ef%+H(kTZe34waG}C7ATHky;5`vjsjkHGzr-1TrfNu{21-YQW*k!N4pE zZtp|GPAkm-Cu?oe27p>wq~ik4Qta_u4#V@+kXuhgJiA+4B5?e>4F>x%mM1*|o>+3i zG60!D91HN{UFZeg!_GUa_PyBTUq!GQ$gmnn&i*Nz4>b@7zDIxVxZXk`-4zV90ic2v zMt)Hxn!3CTIps^yN-v1B`A{6XIa-dxWcf{ZP!=fjv^)qL*c1wIR*=Oovm!%MXBY4ah2fZzWXttuW&1${X!x@C$D0A>$GAJsvZEbolW z_!qz-<$O&3ZnDQ$Uqt{sPQtv?db`r;2e;03f_8c z5s`=_8mtw^bHY+Wwki_&4Ufn7nxAwu<;o|*KnpOS zu5dwaE4#1-x~3FESS|p8O=K!B8>}KJFj%o|p2Lt6ISOD3MQXF%nCPp}7kIDf*ZZ6sc z=kJ*4yj)=kMLP~DMN3AaC|hxEJ!bu{Kqy|zFQKsf3(b0D1HJPOQ0pKlZ!T{Qk!K{B zGZZ?4!>R-V220*-Bv|@?G$6kq(_FCuAk!m|diyd>{h<*ubsqr_xYhuJqcG2p#zWTv zZ`#A*9(O3-#K`EQ?6w1RSVFW-qMOEDGHGc`^0`I;e22mE(_9NfW)H_iVGw{G zLvX>BBY02@vf>A^7DWf^;!$?S%Q#DfwhyRsV#_!7vhB@_*n(8jH$RB#E-TYj%Y z<2am3&FmcJ@eN0cwc$_}w$zlotk>bfl9WSMDG1LNj5rFyWAgPzs+Qj4FG0x+iuI|KxGcR_(^?g+WI=I1x7nOxgBGXV2FajD`-&XPb*($mCUVrudx9@F9+@WZ4QXy06T&m)1xmI z1lLeFihPEhk>tc!i;E2aq6W{d$L4@24vhWIM~&)tq|)D)(5)ATL{)3oV{^dffXxA$ z12zY24%i&9Ibd_Z=77xsn*%lnY!28QusL9Jz~;a~$btU{*5?!>&%=c900000NkvXX Hu0mjfLSZO~ literal 0 HcmV?d00001 diff --git a/server/zanata-war/src/main/webapp/resources/assets/img/logo/logo.png b/server/zanata-war/src/main/webapp/resources/assets/img/logo/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..fad5b9da92532de38948b5a8393b890219ed1127 GIT binary patch literal 14068 zcmVun6hdcgw%Y<|M&oLO@s-{6!XVMWKCUBpB2*T zv!<=8hmckYB}-2d7e<&c_dEYH*;AJ5&L33Skv(NaJp{GyF(vqyxIn^$xz&8J;n`(% zJ2-y>2$Uu2>F*$*On}@O`-_VuOqi>jKQa``mu<}o#dmT3hNB@Rh%W?h^$Fsl2@~c9 zD~etVWp$gfOB1_y{-(!NmJ)o2>B24I;t3PxWGe|@iq8Bi3;ok^{$^8xMIt2-Cd_f> zjr^I4du?_8T~mU@LW~AZ6c<#OFsGQO_Bd?stH=1Qb*si@!e+e9_aO zSUv-a)w95l2mPM@%#VLZ|0cicckKVr`R0`Dg&&qJ9xh?_w(*rcsfwR9btO0F-z6mo zs!PD5o@$Hpy#p!DC5!vA6vY?23jE65AjvO*6!U_lypN2>MfhtR0@@e&ci-dR{Q{D@ z34v_e4(HXRHA;WS{tf-x0RA7p`Xzow0*^{4WuNK8<7MPc+=Efk-=MJeWCV+TkW=1S zJb=Qivz&Lk;sZN_oRqus@0=2p#(zS`xWjaCBjAyge?mwZfsQ&IojQtuv<8o@EZw1V zr-J|xyBYLn6uGbnrW9MC)CO&E_}v_-zsG+||0fmwu+O5XiatB}bLh`7J=%(ZL0uCW ze|-ng#NJGN@7LQ~~P@1TP;-zPG_#8@>9)?bS9jh}0w58}Yzp^(jy=jrY z%y}q`;!EMLMb1GFI0WPCFlWA> z72VQ)%UA3Lf$*8=6wiR9%|+*5+u$q~o{!<6kW5t=AOzHP2n6#%ispbPb~cPzu(x=i zg{5!w#w<9=A8h?iM`3R~1o?CNwdnM|$hr7-AC05PQGC;HOTFP+q$#`gpgKbm z^ssZY9j}Xw*JLdC9T=HTmywP%|Lnso^@4LsosclfSUybCHXV(~DN z>L$4ME#Hyofa(ZzZ4l6PFi>9sul%PrMOMNxz=~`BfT818JcvHrqX8-oh7ubg5Pb?m z+uQI>UxA>oxxwj!!s*kgucW{L@AGdM9n8UK?;gfW5SHOaJ!cG`c@ljL32n=lv$SAm z{Q+^bBQl_Ch(%sZvHr(YoV@Cvg(GC5js9>SB%#d8nzm9nMg|_N6QYl7Z^5YGL#!A4 z1ICn#!eNG3HadTaS-pO7*gYy(!J;hepe%);e5bQ0+QQmV^b6si zDioG#^SDfK3Nym_kv?0#Y`duVckqozY{areLoUoxsU~6`yFWhPQB;IRk(sbaqES%9 z4QWAXd;<<0y#gb|Zb&<|`_2^=|F#d%q;vyPlZCn%hq4Yr^5;mMt!08DlKeK43Jb)> zW50Yf{`vy8%brD!{ZnjifqpM3&nN$GJpQ={iC6f4WE3O8&+y}C;m9(5wm!kPvSF-u zcN>@NK8e_%=isdso1(36_boXBi+-y_#lPi!1u4}XU6DxLfY)pVI_}5lsBhpK?IDby z{tx#doC$?BhcYoxs;6|+NTG<{l=)SM;LkV%0pl8+(t8jAA{T%5N0?VH!(TU~26$NH z;1Ez?fXRlp5CDheb`g$fg-xi~mqanlSM_nun;x&vMvRW)==9UsTRRlJf=O(RoVTAX z?jN;meUZx%AfCYQ`4$fDEXVJfmKp7AHjm`moW*P!c&tIHb9jg-bk&MA5IM z;uX%vhtzNIt$Uec?kWM3KYR*CD0g5w5=1aqnF_m!!*9#zfKiI$-(nQ?PvMqknLqL% z%V9;)uhsCMNssxljdh*_*=_llLikivLsDKqRpW*D>t;I&qp+F^?SKfzUrp{q5N2Sz z?-DG+Y_eL?%Sn-d9;#~ZKtZL01vTrl!5cjRYX>NrqE#XoY++!~-ZgH9@CMj*p2=z{ z!VIv&>LUfsx4qJ1Z2E0AYVi+p{BtmPa3`GiIEC#xkksW3ElWE@1$s)bjLFXlx(?YkkR4`{i>8@8sgxOuB^TwW%r`J(8@ zk>VQC7PCz}uBr{;x-&@~kIwg<)#(B8QXqt2OWhY?9lf#2-9jAG0A`z{CU+CKY>B52 zxd%Z;Qd&i+k7X**Ov0QkH_2lQSB161O2X#|rk}yP2}1E{Fn+%K3RkpeP*NVlTES{P zHL&6tYFH3E9VX80E*!dTH?SX8eG{z6BOKP)-2@?RB}Q6*cja?bu;@UxO(~#!!_r7A z7OJpojB@XJ^ZN+LPREFj>Q~?%mF==YqU`C3*WtaM$0u&D)Nry~%&mm=_(-i|FzR0*y?OXfk&I_~ew$lZ5# zDi8*g|1biMJ1r}@C$dgY3pA6t0$LOb!eZ0$uK5~X6e<3NZ5UpeULd3)ojhDa?%L;# z)dwab5Nu)d24;c)?I*}vFhDqc%7{lzTYN<5Z?9pO(z?%G!60n0by#}|rUhYBqXD|M z0eO)q3^w%pqc4e~pG_HrL~0@Z0Ak*`)yB;1fp6tJQ)>f^qK(~wjBgQ^gs-A7OicLM zyg(R?*MMi~+3t=8V%KBp^Ob3lsNNlTA9CL9nxW2*IVQ{d#gLCP)Ns`GxLfaWF3Lf6 zH5xp_Wum5~1Ox(pxe(mO%1o=@A5cFKdA}n^j6YziK5ni_N$MDu5*W@R)b#B{e)+k~ z0ss`36wdGD0-^Q|76@-~cS?X$eWi(?4et_=j2rH=L=gCQW;j17tA^?}ihjSd3xupl zD5)io7j|zoyQt>RI8(69=y7y5MOd0xk7@B=-R=Cjb9!UpBW`N%RU8Hv2sMqh)7)yL zLLEvhGQk& zTwTn)D98$eDAwwYT;`mMK@(z9JcQkW-vkhdqitFPk;@$m0!1|^GF2hY(qb%KlGG{~ zQ@*#eE{G>~HX{4mSSj76BclKUakN5$LDgu|=!3Bp-5d!5-pGB1v<9ho>Qn9ohhCJ6 z5Zz~{HqnTOT^wmilNU$Mb=c?p$cs zbnZh#`i7yWT|uIP!FL=0xu34cDz2)}_D7T50s#c#Xpu@h3)ykbP|l%+Dk1F$o?QW^ z9^{w5fs)02oeuyb-+L^(U{QVc_|NLIC(fzQE~pehAdXh5;S>!degv=ffFpDWebI-w zD`c^0!RS-YcK%y)y20xoFVC7Zzdn1yZ2d?9L7@NwakNGyrU^sseJH6q#@+-Wl=up& zVV?B>y%wOXa`v|25i^EnPhQyQ{7sJrAXqGbKpd^;>c`jM64N_vO_lXVu7>hu+qs{+ zU%A_YMgeC8mO)@-EL*fRUyGv89lU z`wJXrue^CFQ2mu~vQr{MJCMxL~ImI`>)E1d@bV?Ub4 ziht<>z|KIBDi#VL5Xa7gMNCsqD}%xs`;8gD)QK6@9r_)6D2)2>Zq#b4 zW~qSy0uc=~ZY=V%K^@Brg0UdijsO!>QLeB*0F3$2!!7*B118Mh2E)f)i=Rv*lKqoM zKL!Ln`X3CV-@6TgV39t3DD()#m@$nRtE<2lyWUbi@GL!>bPu>akE|FdOZImDhw^(N z^Y81dym?%lzf=CgdKmN35`6imoWB1~2mM(O#D)Pd;_X`y2~Xc-@_ejNzFnbXP)u3fnt+81+-qwuV~!#Fs7!|gY9UA zau57+UpI_J5&}zdJsSfiK0sT60P6_w(pwYLc>C`T2&iVz8y+jV3_Mj+@B!E$_8N#z z0g`HNG&u^$;Uy)mrvb`$_8b%T%YSP&+(9774j>Q|EzyZR=>P$>{@$3g8E(nBh&gfF z0ify8i-Ey|6V8XiN*{vMIvofS!Z9*78c>569Uf(hU*zK?qa?5A))J&N!0G~L^WlGV zQj18(fFP!G{aXP7miv$WXl@%q|8$PtEIk-H;w+fFFprRw0fCS!%edM=_B&sr6Uk4Q z<{LrfJ#Ip|Y#u`K+N|}rU~l|V>E$}<00H&>pY%P{&hWprqYwMso1Z)dCe9g+(^g-I z-G>=AP=pQ%!%fuRM}iW!Zh)>6uo8;q?PnhVATh^Kd~2I3?gRwH@h7hT#MzBNfb{~% z{bVg%KIAl3%;OILO@W{rTr%`HnDE&%#I&NDBxuGiS0N5+aSY4*nL8j9?n5m+KJ_P! zY8l(X6B%e90FdN|+gIq&8i6219zp>TWd41`A@@)BIFLmI$6azH(u^O#tu?heyHIcm z+@>jjFR5RkSUt<44p|vDW+0mlP@lCC04VP>@=Zsov_TyRkU>=sPX+#yZ0Gei@#x#Y zE*v#|2zbMDp)|f-a0%Se1z;n@KKU*SqvY#&QPx=`6HqGbp^!vdOaifQcvRJsZH^z| zmA4MVPu?%-m;+1(f<{u&f6E5xT!Q!}(L!``-oJ`eb_*>Y5bBL@?Qi+`Nt`+XKbW4% zG|&E122xJKgY&E-oBVN;Pw(6$60iaYbS}Z8lm3eH*f?Y&uN5ssC+-_im$1#gmUqf< zhrm>h#Xw)|5<7(dk8#_XzWcREottz7%m#uKm!JpS{^FT1X?`vdo>=EV2$a~o?@xKZ z_5*mU?XhFPFW<+t4&cX?YL;6Nmn8ByDW-f9--;pk=`H*;tARjoAzpFU@i6|gXYqz= zOrV72cA`#Tw|+mV^wRn++tkWPEhwmN=2BCd%H{%QT6;pobq>gNJbLK*^p+B5pV_)u z4Fr1U;E$&t0k3^bx&(_D(@PW#?UnZjlnJ)t%h1X*PWuB`bQ6fJh7ne#Hca_M;e%*I z(D29F%5bt82>Les{O6}$n=BY^6a_;YRhW@ciy@G1ndG{Djn2lu*jL$eT~Sy9bt9sEXnGIpPJK+rgIaO2~r!uSO*W1V0b zV;G7$fjK;X>i56;{_x~;&@?jaW{YTGvV0uBsF~6n`Bf_!fN$|A05a6}%b!E;qWw92 zGdlo*PBlK|Z%4w|8N(2%E7?sK+62bt{RIn4lW+c=6{H5(A{w9?mxQ!)9(6NHbtJ0_ zfp_HZiB22kQqW+%S{%^eZ+qZzfW<)2SSNU){2y31c^i4*zv}6M;1lrV`Dc3~Dx81w z(Mj-a?q1j<8VJZ!_`En-;XDCjOdM=#u%ep&h(14XDRvpJdrm;Gf6^JP0)kYXpcmZx z>Oja}G#&vo$tMs4NF8Rz;W7?*xbUhpDdYo^AYn~3;8&mIlRC$VH}eY=R32^xw;3k@ zHBJn`74;@*x_7bx5Txn^-Pt7KxLJ>a9~YhwyHKPD?JppYo%MW^yuW{%AYe^2fSZK5 zk;n)HESU_Hw830D0M@iK2nhB|=7d%PfzBuB(c@rvaq10FQu9t@dLX(7X}6DyYjAqB zS3hW8IXWF6Ft;{9?en0ziAN!jy*$0)e^~$kF)kEfeE=x-Kk!!ev>+HGLg&miUjgOlf4N$QgNjzL;O7u>^e;rF`U~L;o zt7JOr))|de?qdTWNTmn+!A(z{$!mJdwN&3w-8OjX%^|=~IVu$m7+h4tG2VbOn@a>e z)hdZFzxoarLIaT*Bz3AyXc`0rU6W2|6%h1eKR>@x5-ZPIdGk%0Ukp2LjN%0Xy_3&^ zft>)w$E6d%T7k+(Ci@A#ttE9am+Cc}YKn~k``KPi9xgM1pc}k8;~`cg5_1K+9~<{X zVvJ+KUpB69l1E~!`IHyAMbH5?0y*`2nCBY#RY+z~S8yp*u@FYSAM9&gz&uTYUU2`o z3$eTMvk3iLsCwg$2Y6!gl?J^1`x_trry}Us?OY-Ns-gMSFJWv&H}hO#0xl+CB8ME* zO)!d}wg}kYIvdO`JP=O5;s_dI;U*#N)|TJ6PhST9iqQj-ogtIRK(!ZhVFMBef@UA` zs}3>G6(-mI9`lY39S%{ckQ30hfmi+$ILA`#Lf%}0o{+boh?}^ITb;kSdM@-lXaMlt z88ILk<(bF@h@OCv?{8duNRqeUNc!>SeR=BH2i5JIzWjRAwzL?_CFlqkbjLMlcR*;_ zHj($Yq8EAl%jba3_2=pQ2PW^Qi9UpT3Q1zF!^AILS(~jRH_b|-=kZ{yvG9d_`!@r+7gSZfa{L@O|Z}j_*w2|$X?$O2cr)J{Z?wCe@#U+gME?SnZ5$wWibPi zg+z-CTj_qKn#)W8)kXsH5c9r!AUcFg3xhfU$S1JJf&)V=rAyFU!LSEBR(v%{hza?y z7S>>qu;+;BcXO`#r=|g|6$tUmbGeYcC_?fn_nHU*v3t0X7$|g+7_%m>v*k|(GWfW(eD%dA51WWw(Fgbdz>1w0fw#~pu10i-3xp;EAQXsMapSW2#WwrTz8HY#|OCqfM5LpGR<&L9EG+*Bd~?` zaOtvb@bX)?84&vSu+4K2P^NJM07-e;%n0BSZUA766qtRjWa(kZq4-L){91XSCoc-Q zqTk;l0LbNB3cz{_@SJ&H+!uX_UkaeSn=#HmxV{seuc-RB7W&6NXWN(f5Bk`v+r(>S zxIR$#jENzv#<2#V%*Yr3@I~+ErU~!Xs()GCc6ec$5uyKnwtF6M44zvG;Ez6OVhRws zj~f6;%7+=@{6#e<;uPCjG3D1<=)bVcfY6^l&wj1ufc!SUB4F%M69E868K1*wq;EfEx%R?Kd-!bmjR)FR~tVUv-uH$)S+hPvj4|rAqW+Ga9b){GU8SX*8T-b z6B~uxcWWDcD&Gd3@Y9c@^LMlFgMsWsy`3)KWMUC8auK&FCfuC|6Dsy~rSmiO zSG88K{aWMttKY))kDdnn7=QMl`nLFN%;>2hcvuj=xAXeXQOWIoHe-;8-pjPT6WB`4`AT za*XSoKl)b;{eKezAFWKW6;;myeOQWT=x_h=^8BiPByhq*5CkKrZAdUX$-FOLu;?HN za@Y&V6oHg27*U+;vZ{X%?D4AH)<3yb;U}Q1g*!(K*-mw8|Q zyqrB)af_Rnftf7~!&{`6LTTL=5&E}Mwf2Oo;D}QX0e<41^!DG!G0%xNdNU7RNODDZ z9EQy>x#l6MGda#OzvK$%r(&k0Y9jP+ZKYRYQ*xDePjKUuUs_S3@)S2s4O}y31&N`A z2OE$@0Dd{(3ILGgi6Zn*Yo%8{G%j1=waurK!vJ71muE%ypE4^#m>g##81JGE)-lRN z=-(>w%Nt$^7hQKO@SF6rH`{NwsiN{BM;h=bD|+0waG?Y1%D}6jXx@H~b$*g~4l0TW z{aZd5-S_1;hXUVizTF-7yo@Q|oAP#UtMz>HUFM&JCo+%=y_K~B)lE=PeXN74{$oYx zpT>i#OMCa>*z>oSz(?9`^zh*rw*Shd3t(9njrxw*f8=r!x(LKoj&y!+?0hIoY!;z^ zE3K-a@-qy1@h`wv;B#+hJ~K$A=g>m8_T`!LZdc4b>bQh4Y?>+hgyU}HNK9J<*FTN> zOA9?ec`@Td|AzD#MRhq$hwABbY_)ZZbtIXOtTC%(DnSQ^{x68oKaG)ZPdEZ6op~6? zo z8COAC_1!qW{r3i^n@@g)OWI5t0Fv?@PUaqHaX~|##YZ0yTY*w^3CodeYglXv#HNY2 ze;UOpPb3V-a4Y;dKlIlvn^H$Eo3-g0hva$IFV^LRXvsRj2Gj=ly=`xwqzz^(y+qHy z^}^qO{Wowd{5g;7-<%cJ97-ApeDZ&am{l7@%t+wjMuBCt#^`Ofym>TlEvd^%zFIhX zD}|}aOWp#$A|GAB4d##Cz@=^8&;r!1wf>|gEIyc6UR>H?mQ6OLbMxfaMbAG?#^2Bv z&*D`0OO5$vxdH%af|f`6NGd=9c|8h5mO4!cUq2Fk<@M zz=!Ye9C6R|^Zz%vy(F2gLgZ@uoZR?XJ@GC1HJ4=}rO5$@u@&7cKd+*i{*33q3*6k? z_A9FT1bwz2@Ei4Y&$cKE|0RXX;9OD!^m`~-+}Caejw!tQ<2u5rS6bipQ}RUNFP*3j zS)8xWd=~T-+?k>4-zMJ(Ur1}uxn1j^`koC>GCG7CL53*>%aXM@TjbBU*khCE`KMWx zF4ca9=gV*8kOJ6yrB}Pcf2Dw%Z%kvIvit0Jk~HMNiR6%^IsOQNx`Qk${7LesBKL1& z@iv4Y@U--Q9Rz{BT;=?}a39)z$b~wt3xI5ZB6|+aWpNWaY$yh54_Fh;#Qr5jKH5v? zR=+}C}SnJ)MCmXwmUmajMJxohX?{$*ECoXLixqk=l z8*Qo?KJg-G8x^>(YkK|-R!`jjx!hhRY==hlVf&sh<2uW0d5L5&PPwUDPeEVX98hnB zkQya06H|Zfd{g&3uw zYg&M)_b15@Ls0vQMFWBb*dBd{WpKyyXS4zW?(6wCM8t}RU--X*d|{UL(|@fNJ=7by z)dAQVDRn)b_#Z4gpZuyr5Y)!e_h2_ubOqYhvhqe1xaIMaq2=MA&aQKQPxN;fNv`82 z8OP>iVz=A>#A!9QU;UC>=xmp<$KvoQAjPL)YjC?L5VrBb^+cD#755(xyABA^+y4M? zqw%E2v#yxB1_$r@I^*O6$^?EVpU{<0@)iuR$Bo4~g^)U*q8z~xY)eNcya+BGa`a9h z;Ep-}U0xP7y^*Z*6~C7tONC3Egnm@~*h0Ex{HmWe+8~@$-kIqZ1l0uH98oAt^B#Jt zXTzy~{~hRLANS1p@A3kSKE<<(1i{2M(~IF9a}a8O#O81lKVVS+_Lr?92JOyh20~Jv zL9kn+7Yapvpj8kkuK6grBcPir3xA~17r?ogvINK8zq;5yqrd4IE)V6(q@#x?7#nHN zkS}rslxcYojBnJdz5)nZypM%T-hts`_69eaq&~-$Lt@$T&kpy~ab1yLUcoC*PSyf` zWLyKg+S8tku}?dbzN;t{wgLhY=CqD`tF_iTrs+}nf4ow{?9w`V`+o`JD|r-c_(Qgmiw;AW(d7V{v7?N`u zh9l4R8A2FyA0F*kU z>Grbt%xHQoT>;EKEH!v=(uK$>oQ|x*Z9-_YNw|v(S8&qp0mnVtq+sn=WUjRyUG%dA zTw|nPj$#p9S83}PDc9mN>)y)Szqz9qD;B;`{tsO2IFBA2Q7BA;K-sdbB*N;jLiY%+ zDK1?HN&6K%wa2-uKgxTt23tXu*lZy~sta^X`bwXW8~y&B_~w(@=y8Tqiy7y=H1QiU z>27w!GhI@BCKjbPaINdOCimavVxeSMQ2mi-HJq`ef^rQ^s4!bUJ}cSs8vq?&e9;|F zxcG3GIOj=>XjW%>$AIxYLUkKaNb?`Iex7qG_QEuD0naopIrOs*ik2J=t~8DlQagzx zjyCyB_Tk|CJFDSzgDdVj9`YBAA;ME8cMO=mU}^jpoFcr!#&xadxo?TqXI@?h*IMqJ z-WcAj;u`8wDo|Rt1-$ZQCY?nm;IsK=_Z%Mxp#cx;2g1*mGf>_$O!YWO(|P>hqjDW zCdD2zu?x^M2?9m~L9$~oV<=Y0BgBTxq>ceA_Dbq1C=4HOZ4E1Wzy9LV_@=Psb=y%o z?MlcfBf&)81wqzJ#@3)Wa+!%|vNtpeTo?%gddJ`xoTbnG^bwl0%&3k5TZyG4u$y$0 zCC{t3_Izsjapkf!s{NGPU+k0r1s#Copf7p9$ynZ4s(p#Mnwdisbo2I276*+6g1!t0 zE*^9Yj9>6F);_+~fgqk4Ab@i1rjLY^FlXock;qKQlQNURU#^uNoo~3r8(8|kth!zQYyH&{8G=UN4Xm^ z)<`-mpuB6y#bxv6>QtuRXTI$TjazYy27*2e2xtjMQFRFA$u_yZbx0r((&j;ag|V|B zgX=q?W-Vy%{@Hb{4j^)IvD?QC7Fbh_H*bT=2$15#C^Xn3;t_y>&Qn&`~g9_H(2(>pBhr z>!+)eSTx!Gu>WsZME#YQrvI+v>qz*q`;?>g^?=w&LsEf;QPac*%)f55(HWarDAa*~ zrVb}Ae2oNKUBw|_dkAA=+eNDJga@JX|6*8l#1wv`xx&F)v)matDsX90L0Ox@c_M*2sAxH(_+R!7%67TYjG*ccH6r@N|q; zfCb~rjVfB{Ab=ypKILAUow=Ee!bT3ky{`|%m0dyXtvjDXz&bxTJK$5EPOsI6J09_c zU{pH9x=mQ=xEwFo#jtghNn#2^&8y zO>EWIx@pb@fiiTwlE{NCUS%2_!=W@opE0UC1)>)Vhi+FS5W9!t4^`;)!56#j)A`740;Y=%EjJD z*okDKhW4)?tNaDk$0B`rvEk2>-jbXS!)A054$Q-7`GTa)H8v7R3W@}^?~yQcgN?67 zmdPCholJBrl8MG3naHoiokk{NAP|s$#qa*T;VF$it+?2^8-49+G?N|FG@}Px7+Xuv z9bd6If@dc?24>9|=p2Gm{&pmcoBb4tyD|Ulp@E21zo}?Z@ISgO{;T`;FLsoNV`zc42Y&6yc}_+MXWu zRIJ*6V@fW{Kp?&bqk&r;aB0l$7*OQV4Xzn>BIGT29m!iiWQ;OV^UnXBt<;NMZJwoP zNxVr3k+zSPZ4syWN=?v!07&Nj9Z+-rBC|I1275256wA7?we?hSg_ZPU@ zypfCO!kbf-*7VA5Fun>O@P9hw3Yj@$(8wyhZ`9ei4AzJ2xAksUCQ5EFTE~Xigjodw z=0pOi8=i~?rZFWWXBZKjdYc3SDOO<*csTC@D5{!*HJiW$v&`5tAepRz!Bw7spveN5~aq*#SL;qj778NE0Z*XhMB00Q0ld z?O%lB*~yA(PQ-9CVKiB&xwnCy7N{Syl*AckcIz-jFYW_5W!K`Hb2clkI!&~cEhkY| zqUh@B!r^S04lF$kTZHosr+V&=MTkngY^J~$IoBaqY!BATGY<&*LDM;dlJG)SS8>9? zkuE^G#Insq!qT)cGkYNA^G!eONnD1hk_!iPnFLcN-h?(+aJI)!5dT$8$BUMzx zvFDtD)~G&QT+>@Pm=mnYxTht=lq8do>A-~&6-b-C&LNv$&7L~cfuKkKgAusz0$;2K z!E=jk3Wdpf1r~cJ+jLx9Sj)vh`9YL--e}#MMPuPDQ>ZCbBM1bKg3l3q;LM&nBnD$w zxb69~VbZ)M4IpYU0FYP+ssukN9LdS%i(P{K+Rx1{4mMXT)I&+_Cma|lg)-%Gn`^`w zId#}C2{7HE?=gqL!;`Ov(H~61t;auPPncbwJz-9LcERHM>_E&?AYf~|{n63FiJWd8 zoX!fV6?PE5WGM+7r%h1jK*ikhH59Qt2XadGvM~_w;1KjprWf6yU%x|PcfP~> z`$;@2Z!S9gqI&i#0{}e6e^#G85rLr4LLf+`0RGqr;Y3ci(I4)E11oPZnJb&jva|1z z1SJH67#^cp;c#N4yA7{kTgQ*-E#EsC-uHwPE$^WqsD9 z`HfEB+>r!=tfD2>06|Dk<8F2cU_$>l~ zY%UNq?3k1v77pYFBf$o2>#$JVhU2R`%W!2%Pku8-1{w|`g%A`T!0-KMoJu^fLmP1T zS&Bz600s{JBMcpNCA?7j6h>Qb!njWo@WyAGvL`P}hWGQ@=I|{7!Cdo!fQgJQL!p?+ zy~2UqV6>dk7kd;PYn?8EZD)z=Ivo&_1SbT6H3$k-Sl5tHtKbQ?(u#Bv@@faLRL96P zigq~qQS`zWyNY!+ypbSGT3Cy3`0sG-*miPu=J52EpE!q))3*o&Ri*(!Qc8XcUhjVk z2Xak;u=-T2%zr{4;0#q8jXj7gWk`YoYcmElBp)e1W5iHL`iT(G%J4ybgXON?=rC0G z{U)vPO05mvt@t@*Mo^1Umgs z_;a?TQWh3P5s3$#kiz>0=QPUkcLxN;<^Vx*v(zTMj@Jw4af=Pk>5K)!`$^SBuMIeG zP=y|R(!EPjYf}+J(n%S>P0`tQEbVFPD4|ABVgH6W`aAu9_UH83JOAINj5z`)U!*>J z^1`HpnhONfMaU|yuFsN;1p?N=!KF0}EQPtMHgF7v*Kelg{@tx+qa{H@;|q96$Lr(` z*Jn>!U=JWLV%s!{fdmt4!BZ=?{ z0Ra{wp`dajio_H_iL&G9?&R9vW9MWXI_yt8fq)fZLy6T)lR}tl(}EL`K;*?6z0vJr zm!<##<>)+tfI0r+&8Qe1#1`qPE#6Dgb3|4srg=Z}0s>trD83v@u#P0m#YSo{)D{b> zzmZa~NDVp)1XcPBKzo3Icm~Yz7jDIM@>3xYKC^B25}j32$MXULHa8H8D=cah=5`>! zhfPugEHx0DaXJVDG9&b)4Fp6fE?k0+zX(J9a4F+4bm(4E_Xjum@&E$1Oh&DB$PNi% z9S4HQ9}x(~(Y7L;l(S4Yb$c0)MC2igFTL5D0Rk!_5>P;4)f&_loQQf4Cv(1+e1L%M zkdPNaUbv5NkW4Y6$Oh$yFf|CLsJofCCW{Xc#Pl&>0)k|i&#L+*H8?RDdki`G2OA9P z9ZwB(>G;oZkgJDqj!d$gioL*xVjrb-R44e6ItPrICyIt`p2KG?w!+10k)k}6%{!Pa zpu&J4hCtBHuE8`W8$T0@u%#?4BMXLyVMzHO+*vS>ZOBQb2m%atJ94Y5CMmyRF>N6P zmpz1=cdTEv?N4?M+S5K{Abh2ais?b@U$HAr3Y%=b=Q<}HrXjboOE1`(a&#wfTSgo)Ox54$D7#IZQ$MIqM6sPUh zvf&$gps04>=IEfwXftb>1=MxOww#T}Q_Sge>i2L+WOo#Tz*vmz(qD;AAP`WB*ciGn zVLPM=l5#!1{U+lP!{}gBN3ixHSm~OOV6<6OErX&fYK6A2d5f3T&J> zv7<%-4a$VnpYg3%jR04O$8AuKEz>bB)YmUwas-~|D6CtoX&DIgeGwS-jS>&LurvSx z^I%`qAt=ysF)IH&gb$eybL2|=^=o{SG>URG73N?w`w6|azyliB^C< z45Mzvhx!{<-|));l+u2L36B&ihr-~&oigTrNqD}&_{*sQvSxvxL1{RgBOY*J?Xhg| zR`x`dpA*pWu3|za0eKvP!ZdsU7oYCsT4d67|) zq!T8Lqh+yn6EV=JP(|8(-rDogVgJr#z5?n{1{m~)rXnOOz9~<$-_xHlFu{KlkZ)%H z#~VAJX${h6kq{|cZ{~e>S)(3`R zT}5r!|4^FPfa$Jy4<)oa+$a=!h~g#>3b`0h4T1P zEExXE_A>|*CM?5@h+vX(3xdJ>C^&PD=(q?ImWf8K+>+Som?Cr$7ekmZVZww76DCZU mFk!-k2@@tvm@r`-vi}GF*%P&&aW;kk0000 + + + diff --git a/server/zanata-war/src/main/webapp/resources/assets/img/openid-logo.svg b/server/zanata-war/src/main/webapp/resources/assets/img/openid-logo.svg new file mode 100644 index 0000000000..dda0ad9df6 --- /dev/null +++ b/server/zanata-war/src/main/webapp/resources/assets/img/openid-logo.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + diff --git a/server/zanata-war/src/main/webapp/resources/assets/img/yahoo-logo.svg b/server/zanata-war/src/main/webapp/resources/assets/img/yahoo-logo.svg new file mode 100644 index 0000000000..ab0e0eb5e9 --- /dev/null +++ b/server/zanata-war/src/main/webapp/resources/assets/img/yahoo-logo.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + diff --git a/server/zanata-war/src/main/webapp/resources/assets/script.js b/server/zanata-war/src/main/webapp/resources/assets/script.js new file mode 100644 index 0000000000..65a05558d7 --- /dev/null +++ b/server/zanata-war/src/main/webapp/resources/assets/script.js @@ -0,0 +1,2581 @@ +/*! zanata-assets - v0.1.0 - 2017-02-02 +* http://zanata.org/ +* Copyright (c) 2017 Red Hat; Licensed MIT */ +;(function () { + 'use strict'; + + /** + * @preserve FastClick: polyfill to remove click delays on browsers with touch UIs. + * + * @codingstandard ftlabs-jsv2 + * @copyright The Financial Times Limited [All Rights Reserved] + * @license MIT License (see LICENSE.txt) + */ + + /*jslint browser:true, node:true*/ + /*global define, Event, Node*/ + + + /** + * Instantiate fast-clicking listeners on the specified layer. + * + * @constructor + * @param {Element} layer The layer to listen on + * @param {Object} [options={}] The options to override the defaults + */ + function FastClick(layer, options) { + var oldOnClick; + + options = options || {}; + + /** + * Whether a click is currently being tracked. + * + * @type boolean + */ + this.trackingClick = false; + + + /** + * Timestamp for when click tracking started. + * + * @type number + */ + this.trackingClickStart = 0; + + + /** + * The element being tracked for a click. + * + * @type EventTarget + */ + this.targetElement = null; + + + /** + * X-coordinate of touch start event. + * + * @type number + */ + this.touchStartX = 0; + + + /** + * Y-coordinate of touch start event. + * + * @type number + */ + this.touchStartY = 0; + + + /** + * ID of the last touch, retrieved from Touch.identifier. + * + * @type number + */ + this.lastTouchIdentifier = 0; + + + /** + * Touchmove boundary, beyond which a click will be cancelled. + * + * @type number + */ + this.touchBoundary = options.touchBoundary || 10; + + + /** + * The FastClick layer. + * + * @type Element + */ + this.layer = layer; + + /** + * The minimum time between tap(touchstart and touchend) events + * + * @type number + */ + this.tapDelay = options.tapDelay || 200; + + /** + * The maximum time for a tap + * + * @type number + */ + this.tapTimeout = options.tapTimeout || 700; + + if (FastClick.notNeeded(layer)) { + return; + } + + // Some old versions of Android don't have Function.prototype.bind + function bind(method, context) { + return function() { return method.apply(context, arguments); }; + } + + + var methods = ['onMouse', 'onClick', 'onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel']; + var context = this; + for (var i = 0, l = methods.length; i < l; i++) { + context[methods[i]] = bind(context[methods[i]], context); + } + + // Set up event handlers as required + if (deviceIsAndroid) { + layer.addEventListener('mouseover', this.onMouse, true); + layer.addEventListener('mousedown', this.onMouse, true); + layer.addEventListener('mouseup', this.onMouse, true); + } + + layer.addEventListener('click', this.onClick, true); + layer.addEventListener('touchstart', this.onTouchStart, false); + layer.addEventListener('touchmove', this.onTouchMove, false); + layer.addEventListener('touchend', this.onTouchEnd, false); + layer.addEventListener('touchcancel', this.onTouchCancel, false); + + // Hack is required for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2) + // which is how FastClick normally stops click events bubbling to callbacks registered on the FastClick + // layer when they are cancelled. + if (!Event.prototype.stopImmediatePropagation) { + layer.removeEventListener = function(type, callback, capture) { + var rmv = Node.prototype.removeEventListener; + if (type === 'click') { + rmv.call(layer, type, callback.hijacked || callback, capture); + } else { + rmv.call(layer, type, callback, capture); + } + }; + + layer.addEventListener = function(type, callback, capture) { + var adv = Node.prototype.addEventListener; + if (type === 'click') { + adv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) { + if (!event.propagationStopped) { + callback(event); + } + }), capture); + } else { + adv.call(layer, type, callback, capture); + } + }; + } + + // If a handler is already declared in the element's onclick attribute, it will be fired before + // FastClick's onClick handler. Fix this by pulling out the user-defined handler function and + // adding it as listener. + if (typeof layer.onclick === 'function') { + + // Android browser on at least 3.2 requires a new reference to the function in layer.onclick + // - the old one won't work if passed to addEventListener directly. + oldOnClick = layer.onclick; + layer.addEventListener('click', function(event) { + oldOnClick(event); + }, false); + layer.onclick = null; + } + } + + /** + * Windows Phone 8.1 fakes user agent string to look like Android and iPhone. + * + * @type boolean + */ + var deviceIsWindowsPhone = navigator.userAgent.indexOf("Windows Phone") >= 0; + + /** + * Android requires exceptions. + * + * @type boolean + */ + var deviceIsAndroid = navigator.userAgent.indexOf('Android') > 0 && !deviceIsWindowsPhone; + + + /** + * iOS requires exceptions. + * + * @type boolean + */ + var deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent) && !deviceIsWindowsPhone; + + + /** + * iOS 4 requires an exception for select elements. + * + * @type boolean + */ + var deviceIsIOS4 = deviceIsIOS && (/OS 4_\d(_\d)?/).test(navigator.userAgent); + + + /** + * iOS 6.0-7.* requires the target element to be manually derived + * + * @type boolean + */ + var deviceIsIOSWithBadTarget = deviceIsIOS && (/OS [6-7]_\d/).test(navigator.userAgent); + + /** + * BlackBerry requires exceptions. + * + * @type boolean + */ + var deviceIsBlackBerry10 = navigator.userAgent.indexOf('BB10') > 0; + + /** + * Determine whether a given element requires a native click. + * + * @param {EventTarget|Element} target Target DOM element + * @returns {boolean} Returns true if the element needs a native click + */ + FastClick.prototype.needsClick = function(target) { + switch (target.nodeName.toLowerCase()) { + + // Don't send a synthetic click to disabled inputs (issue #62) + case 'button': + case 'select': + case 'textarea': + if (target.disabled) { + return true; + } + + break; + case 'input': + + // File inputs need real clicks on iOS 6 due to a browser bug (issue #68) + if ((deviceIsIOS && target.type === 'file') || target.disabled) { + return true; + } + + break; + case 'label': + case 'iframe': // iOS8 homescreen apps can prevent events bubbling into frames + case 'video': + return true; + } + + return (/\bneedsclick\b/).test(target.className); + }; + + + /** + * Determine whether a given element requires a call to focus to simulate click into element. + * + * @param {EventTarget|Element} target Target DOM element + * @returns {boolean} Returns true if the element requires a call to focus to simulate native click. + */ + FastClick.prototype.needsFocus = function(target) { + switch (target.nodeName.toLowerCase()) { + case 'textarea': + return true; + case 'select': + return !deviceIsAndroid; + case 'input': + switch (target.type) { + case 'button': + case 'checkbox': + case 'file': + case 'image': + case 'radio': + case 'submit': + return false; + } + + // No point in attempting to focus disabled inputs + return !target.disabled && !target.readOnly; + default: + return (/\bneedsfocus\b/).test(target.className); + } + }; + + + /** + * Send a click event to the specified element. + * + * @param {EventTarget|Element} targetElement + * @param {Event} event + */ + FastClick.prototype.sendClick = function(targetElement, event) { + var clickEvent, touch; + + // On some Android devices activeElement needs to be blurred otherwise the synthetic click will have no effect (#24) + if (document.activeElement && document.activeElement !== targetElement) { + document.activeElement.blur(); + } + + touch = event.changedTouches[0]; + + // Synthesise a click event, with an extra attribute so it can be tracked + clickEvent = document.createEvent('MouseEvents'); + clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null); + clickEvent.forwardedTouchEvent = true; + targetElement.dispatchEvent(clickEvent); + }; + + FastClick.prototype.determineEventType = function(targetElement) { + + //Issue #159: Android Chrome Select Box does not open with a synthetic click event + if (deviceIsAndroid && targetElement.tagName.toLowerCase() === 'select') { + return 'mousedown'; + } + + return 'click'; + }; + + + /** + * @param {EventTarget|Element} targetElement + */ + FastClick.prototype.focus = function(targetElement) { + var length; + + // Issue #160: on iOS 7, some input elements (e.g. date datetime month) throw a vague TypeError on setSelectionRange. These elements don't have an integer value for the selectionStart and selectionEnd properties, but unfortunately that can't be used for detection because accessing the properties also throws a TypeError. Just check the type instead. Filed as Apple bug #15122724. + if (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time' && targetElement.type !== 'month') { + length = targetElement.value.length; + targetElement.setSelectionRange(length, length); + } else { + targetElement.focus(); + } + }; + + + /** + * Check whether the given target element is a child of a scrollable layer and if so, set a flag on it. + * + * @param {EventTarget|Element} targetElement + */ + FastClick.prototype.updateScrollParent = function(targetElement) { + var scrollParent, parentElement; + + scrollParent = targetElement.fastClickScrollParent; + + // Attempt to discover whether the target element is contained within a scrollable layer. Re-check if the + // target element was moved to another parent. + if (!scrollParent || !scrollParent.contains(targetElement)) { + parentElement = targetElement; + do { + if (parentElement.scrollHeight > parentElement.offsetHeight) { + scrollParent = parentElement; + targetElement.fastClickScrollParent = parentElement; + break; + } + + parentElement = parentElement.parentElement; + } while (parentElement); + } + + // Always update the scroll top tracker if possible. + if (scrollParent) { + scrollParent.fastClickLastScrollTop = scrollParent.scrollTop; + } + }; + + + /** + * @param {EventTarget} targetElement + * @returns {Element|EventTarget} + */ + FastClick.prototype.getTargetElementFromEventTarget = function(eventTarget) { + + // On some older browsers (notably Safari on iOS 4.1 - see issue #56) the event target may be a text node. + if (eventTarget.nodeType === Node.TEXT_NODE) { + return eventTarget.parentNode; + } + + return eventTarget; + }; + + + /** + * On touch start, record the position and scroll offset. + * + * @param {Event} event + * @returns {boolean} + */ + FastClick.prototype.onTouchStart = function(event) { + var targetElement, touch, selection; + + // Ignore multiple touches, otherwise pinch-to-zoom is prevented if both fingers are on the FastClick element (issue #111). + if (event.targetTouches.length > 1) { + return true; + } + + targetElement = this.getTargetElementFromEventTarget(event.target); + touch = event.targetTouches[0]; + + if (deviceIsIOS) { + + // Only trusted events will deselect text on iOS (issue #49) + selection = window.getSelection(); + if (selection.rangeCount && !selection.isCollapsed) { + return true; + } + + if (!deviceIsIOS4) { + + // Weird things happen on iOS when an alert or confirm dialog is opened from a click event callback (issue #23): + // when the user next taps anywhere else on the page, new touchstart and touchend events are dispatched + // with the same identifier as the touch event that previously triggered the click that triggered the alert. + // Sadly, there is an issue on iOS 4 that causes some normal touch events to have the same identifier as an + // immediately preceeding touch event (issue #52), so this fix is unavailable on that platform. + // Issue 120: touch.identifier is 0 when Chrome dev tools 'Emulate touch events' is set with an iOS device UA string, + // which causes all touch events to be ignored. As this block only applies to iOS, and iOS identifiers are always long, + // random integers, it's safe to to continue if the identifier is 0 here. + if (touch.identifier && touch.identifier === this.lastTouchIdentifier) { + event.preventDefault(); + return false; + } + + this.lastTouchIdentifier = touch.identifier; + + // If the target element is a child of a scrollable layer (using -webkit-overflow-scrolling: touch) and: + // 1) the user does a fling scroll on the scrollable layer + // 2) the user stops the fling scroll with another tap + // then the event.target of the last 'touchend' event will be the element that was under the user's finger + // when the fling scroll was started, causing FastClick to send a click event to that layer - unless a check + // is made to ensure that a parent layer was not scrolled before sending a synthetic click (issue #42). + this.updateScrollParent(targetElement); + } + } + + this.trackingClick = true; + this.trackingClickStart = event.timeStamp; + this.targetElement = targetElement; + + this.touchStartX = touch.pageX; + this.touchStartY = touch.pageY; + + // Prevent phantom clicks on fast double-tap (issue #36) + if ((event.timeStamp - this.lastClickTime) < this.tapDelay) { + event.preventDefault(); + } + + return true; + }; + + + /** + * Based on a touchmove event object, check whether the touch has moved past a boundary since it started. + * + * @param {Event} event + * @returns {boolean} + */ + FastClick.prototype.touchHasMoved = function(event) { + var touch = event.changedTouches[0], boundary = this.touchBoundary; + + if (Math.abs(touch.pageX - this.touchStartX) > boundary || Math.abs(touch.pageY - this.touchStartY) > boundary) { + return true; + } + + return false; + }; + + + /** + * Update the last position. + * + * @param {Event} event + * @returns {boolean} + */ + FastClick.prototype.onTouchMove = function(event) { + if (!this.trackingClick) { + return true; + } + + // If the touch has moved, cancel the click tracking + if (this.targetElement !== this.getTargetElementFromEventTarget(event.target) || this.touchHasMoved(event)) { + this.trackingClick = false; + this.targetElement = null; + } + + return true; + }; + + + /** + * Attempt to find the labelled control for the given label element. + * + * @param {EventTarget|HTMLLabelElement} labelElement + * @returns {Element|null} + */ + FastClick.prototype.findControl = function(labelElement) { + + // Fast path for newer browsers supporting the HTML5 control attribute + if (labelElement.control !== undefined) { + return labelElement.control; + } + + // All browsers under test that support touch events also support the HTML5 htmlFor attribute + if (labelElement.htmlFor) { + return document.getElementById(labelElement.htmlFor); + } + + // If no for attribute exists, attempt to retrieve the first labellable descendant element + // the list of which is defined here: http://www.w3.org/TR/html5/forms.html#category-label + return labelElement.querySelector('button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea'); + }; + + + /** + * On touch end, determine whether to send a click event at once. + * + * @param {Event} event + * @returns {boolean} + */ + FastClick.prototype.onTouchEnd = function(event) { + var forElement, trackingClickStart, targetTagName, scrollParent, touch, targetElement = this.targetElement; + + if (!this.trackingClick) { + return true; + } + + // Prevent phantom clicks on fast double-tap (issue #36) + if ((event.timeStamp - this.lastClickTime) < this.tapDelay) { + this.cancelNextClick = true; + return true; + } + + if ((event.timeStamp - this.trackingClickStart) > this.tapTimeout) { + return true; + } + + // Reset to prevent wrong click cancel on input (issue #156). + this.cancelNextClick = false; + + this.lastClickTime = event.timeStamp; + + trackingClickStart = this.trackingClickStart; + this.trackingClick = false; + this.trackingClickStart = 0; + + // On some iOS devices, the targetElement supplied with the event is invalid if the layer + // is performing a transition or scroll, and has to be re-detected manually. Note that + // for this to function correctly, it must be called *after* the event target is checked! + // See issue #57; also filed as rdar://13048589 . + if (deviceIsIOSWithBadTarget) { + touch = event.changedTouches[0]; + + // In certain cases arguments of elementFromPoint can be negative, so prevent setting targetElement to null + targetElement = document.elementFromPoint(touch.pageX - window.pageXOffset, touch.pageY - window.pageYOffset) || targetElement; + targetElement.fastClickScrollParent = this.targetElement.fastClickScrollParent; + } + + targetTagName = targetElement.tagName.toLowerCase(); + if (targetTagName === 'label') { + forElement = this.findControl(targetElement); + if (forElement) { + this.focus(targetElement); + if (deviceIsAndroid) { + return false; + } + + targetElement = forElement; + } + } else if (this.needsFocus(targetElement)) { + + // Case 1: If the touch started a while ago (best guess is 100ms based on tests for issue #36) then focus will be triggered anyway. Return early and unset the target element reference so that the subsequent click will be allowed through. + // Case 2: Without this exception for input elements tapped when the document is contained in an iframe, then any inputted text won't be visible even though the value attribute is updated as the user types (issue #37). + if ((event.timeStamp - trackingClickStart) > 100 || (deviceIsIOS && window.top !== window && targetTagName === 'input')) { + this.targetElement = null; + return false; + } + + this.focus(targetElement); + this.sendClick(targetElement, event); + + // Select elements need the event to go through on iOS 4, otherwise the selector menu won't open. + // Also this breaks opening selects when VoiceOver is active on iOS6, iOS7 (and possibly others) + if (!deviceIsIOS || targetTagName !== 'select') { + this.targetElement = null; + event.preventDefault(); + } + + return false; + } + + if (deviceIsIOS && !deviceIsIOS4) { + + // Don't send a synthetic click event if the target element is contained within a parent layer that was scrolled + // and this tap is being used to stop the scrolling (usually initiated by a fling - issue #42). + scrollParent = targetElement.fastClickScrollParent; + if (scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) { + return true; + } + } + + // Prevent the actual click from going though - unless the target node is marked as requiring + // real clicks or if it is in the whitelist in which case only non-programmatic clicks are permitted. + if (!this.needsClick(targetElement)) { + event.preventDefault(); + this.sendClick(targetElement, event); + } + + return false; + }; + + + /** + * On touch cancel, stop tracking the click. + * + * @returns {void} + */ + FastClick.prototype.onTouchCancel = function() { + this.trackingClick = false; + this.targetElement = null; + }; + + + /** + * Determine mouse events which should be permitted. + * + * @param {Event} event + * @returns {boolean} + */ + FastClick.prototype.onMouse = function(event) { + + // If a target element was never set (because a touch event was never fired) allow the event + if (!this.targetElement) { + return true; + } + + if (event.forwardedTouchEvent) { + return true; + } + + // Programmatically generated events targeting a specific element should be permitted + if (!event.cancelable) { + return true; + } + + // Derive and check the target element to see whether the mouse event needs to be permitted; + // unless explicitly enabled, prevent non-touch click events from triggering actions, + // to prevent ghost/doubleclicks. + if (!this.needsClick(this.targetElement) || this.cancelNextClick) { + + // Prevent any user-added listeners declared on FastClick element from being fired. + if (event.stopImmediatePropagation) { + event.stopImmediatePropagation(); + } else { + + // Part of the hack for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2) + event.propagationStopped = true; + } + + // Cancel the event + event.stopPropagation(); + event.preventDefault(); + + return false; + } + + // If the mouse event is permitted, return true for the action to go through. + return true; + }; + + + /** + * On actual clicks, determine whether this is a touch-generated click, a click action occurring + * naturally after a delay after a touch (which needs to be cancelled to avoid duplication), or + * an actual click which should be permitted. + * + * @param {Event} event + * @returns {boolean} + */ + FastClick.prototype.onClick = function(event) { + var permitted; + + // It's possible for another FastClick-like library delivered with third-party code to fire a click event before FastClick does (issue #44). In that case, set the click-tracking flag back to false and return early. This will cause onTouchEnd to return early. + if (this.trackingClick) { + this.targetElement = null; + this.trackingClick = false; + return true; + } + + // Very odd behaviour on iOS (issue #18): if a submit element is present inside a form and the user hits enter in the iOS simulator or clicks the Go button on the pop-up OS keyboard the a kind of 'fake' click event will be triggered with the submit-type input element as the target. + if (event.target.type === 'submit' && event.detail === 0) { + return true; + } + + permitted = this.onMouse(event); + + // Only unset targetElement if the click is not permitted. This will ensure that the check for !targetElement in onMouse fails and the browser's click doesn't go through. + if (!permitted) { + this.targetElement = null; + } + + // If clicks are permitted, return true for the action to go through. + return permitted; + }; + + + /** + * Remove all FastClick's event listeners. + * + * @returns {void} + */ + FastClick.prototype.destroy = function() { + var layer = this.layer; + + if (deviceIsAndroid) { + layer.removeEventListener('mouseover', this.onMouse, true); + layer.removeEventListener('mousedown', this.onMouse, true); + layer.removeEventListener('mouseup', this.onMouse, true); + } + + layer.removeEventListener('click', this.onClick, true); + layer.removeEventListener('touchstart', this.onTouchStart, false); + layer.removeEventListener('touchmove', this.onTouchMove, false); + layer.removeEventListener('touchend', this.onTouchEnd, false); + layer.removeEventListener('touchcancel', this.onTouchCancel, false); + }; + + + /** + * Check whether FastClick is needed. + * + * @param {Element} layer The layer to listen on + */ + FastClick.notNeeded = function(layer) { + var metaViewport; + var chromeVersion; + var blackberryVersion; + var firefoxVersion; + + // Devices that don't support touch don't need FastClick + if (typeof window.ontouchstart === 'undefined') { + return true; + } + + // Chrome version - zero for other browsers + chromeVersion = +(/Chrome\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1]; + + if (chromeVersion) { + + if (deviceIsAndroid) { + metaViewport = document.querySelector('meta[name=viewport]'); + + if (metaViewport) { + // Chrome on Android with user-scalable="no" doesn't need FastClick (issue #89) + if (metaViewport.content.indexOf('user-scalable=no') !== -1) { + return true; + } + // Chrome 32 and above with width=device-width or less don't need FastClick + if (chromeVersion > 31 && document.documentElement.scrollWidth <= window.outerWidth) { + return true; + } + } + + // Chrome desktop doesn't need FastClick (issue #15) + } else { + return true; + } + } + + if (deviceIsBlackBerry10) { + blackberryVersion = navigator.userAgent.match(/Version\/([0-9]*)\.([0-9]*)/); + + // BlackBerry 10.3+ does not require Fastclick library. + // https://github.com/ftlabs/fastclick/issues/251 + if (blackberryVersion[1] >= 10 && blackberryVersion[2] >= 3) { + metaViewport = document.querySelector('meta[name=viewport]'); + + if (metaViewport) { + // user-scalable=no eliminates click delay. + if (metaViewport.content.indexOf('user-scalable=no') !== -1) { + return true; + } + // width=device-width (or less than device-width) eliminates click delay. + if (document.documentElement.scrollWidth <= window.outerWidth) { + return true; + } + } + } + } + + // IE10 with -ms-touch-action: none or manipulation, which disables double-tap-to-zoom (issue #97) + if (layer.style.msTouchAction === 'none' || layer.style.touchAction === 'manipulation') { + return true; + } + + // Firefox version - zero for other browsers + firefoxVersion = +(/Firefox\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1]; + + if (firefoxVersion >= 27) { + // Firefox 27+ does not have tap delay if the content is not zoomable - https://bugzilla.mozilla.org/show_bug.cgi?id=922896 + + metaViewport = document.querySelector('meta[name=viewport]'); + if (metaViewport && (metaViewport.content.indexOf('user-scalable=no') !== -1 || document.documentElement.scrollWidth <= window.outerWidth)) { + return true; + } + } + + // IE11: prefixed -ms-touch-action is no longer supported and it's recomended to use non-prefixed version + // http://msdn.microsoft.com/en-us/library/windows/apps/Hh767313.aspx + if (layer.style.touchAction === 'none' || layer.style.touchAction === 'manipulation') { + return true; + } + + return false; + }; + + + /** + * Factory method for creating a FastClick object + * + * @param {Element} layer The layer to listen on + * @param {Object} [options={}] The options to override the defaults + */ + FastClick.attach = function(layer, options) { + return new FastClick(layer, options); + }; + + + if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) { + + // AMD. Register as an anonymous module. + define(function() { + return FastClick; + }); + } else if (typeof module !== 'undefined' && module.exports) { + module.exports = FastClick.attach; + module.exports.FastClick = FastClick; + } else { + window.FastClick = FastClick; + } +}()); + +; + + + +window.Modernizr = (function( window, document, undefined ) { + + var version = '2.6.2', + + Modernizr = {}, + + enableClasses = true, + + docElement = document.documentElement, + + mod = 'modernizr', + modElem = document.createElement(mod), + mStyle = modElem.style, + + inputElem , + + + toString = {}.toString, + + prefixes = ' -webkit- -moz- -o- -ms- '.split(' '), + + + + omPrefixes = 'Webkit Moz O ms', + + cssomPrefixes = omPrefixes.split(' '), + + domPrefixes = omPrefixes.toLowerCase().split(' '), + + ns = {'svg': 'http://www.w3.org/2000/svg'}, + + tests = {}, + inputs = {}, + attrs = {}, + + classes = [], + + slice = classes.slice, + + featureName, + + + injectElementWithStyles = function( rule, callback, nodes, testnames ) { + + var style, ret, node, docOverflow, + div = document.createElement('div'), + body = document.body, + fakeBody = body || document.createElement('body'); + + if ( parseInt(nodes, 10) ) { + while ( nodes-- ) { + node = document.createElement('div'); + node.id = testnames ? testnames[nodes] : mod + (nodes + 1); + div.appendChild(node); + } + } + + style = ['­',''].join(''); + div.id = mod; + (body ? div : fakeBody).innerHTML += style; + fakeBody.appendChild(div); + if ( !body ) { + fakeBody.style.background = ''; + fakeBody.style.overflow = 'hidden'; + docOverflow = docElement.style.overflow; + docElement.style.overflow = 'hidden'; + docElement.appendChild(fakeBody); + } + + ret = callback(div, rule); + if ( !body ) { + fakeBody.parentNode.removeChild(fakeBody); + docElement.style.overflow = docOverflow; + } else { + div.parentNode.removeChild(div); + } + + return !!ret; + + }, + _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp; + + if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) { + hasOwnProp = function (object, property) { + return _hasOwnProperty.call(object, property); + }; + } + else { + hasOwnProp = function (object, property) { + return ((property in object) && is(object.constructor.prototype[property], 'undefined')); + }; + } + + + if (!Function.prototype.bind) { + Function.prototype.bind = function bind(that) { + + var target = this; + + if (typeof target != "function") { + throw new TypeError(); + } + + var args = slice.call(arguments, 1), + bound = function () { + + if (this instanceof bound) { + + var F = function(){}; + F.prototype = target.prototype; + var self = new F(); + + var result = target.apply( + self, + args.concat(slice.call(arguments)) + ); + if (Object(result) === result) { + return result; + } + return self; + + } else { + + return target.apply( + that, + args.concat(slice.call(arguments)) + ); + + } + + }; + + return bound; + }; + } + + function setCss( str ) { + mStyle.cssText = str; + } + + function setCssAll( str1, str2 ) { + return setCss(prefixes.join(str1 + ';') + ( str2 || '' )); + } + + function is( obj, type ) { + return typeof obj === type; + } + + function contains( str, substr ) { + return !!~('' + str).indexOf(substr); + } + + function testProps( props, prefixed ) { + for ( var i in props ) { + var prop = props[i]; + if ( !contains(prop, "-") && mStyle[prop] !== undefined ) { + return prefixed == 'pfx' ? prop : true; + } + } + return false; + } + + function testDOMProps( props, obj, elem ) { + for ( var i in props ) { + var item = obj[props[i]]; + if ( item !== undefined) { + + if (elem === false) return props[i]; + + if (is(item, 'function')){ + return item.bind(elem || obj); + } + + return item; + } + } + return false; + } + + function testPropsAll( prop, prefixed, elem ) { + + var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1), + props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' '); + + if(is(prefixed, "string") || is(prefixed, "undefined")) { + return testProps(props, prefixed); + + } else { + props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' '); + return testDOMProps(props, prefixed, elem); + } + } tests['touch'] = function() { + var bool; + + if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) { + bool = true; + } else { + injectElementWithStyles(['@media (',prefixes.join('touch-enabled),('),mod,')','{#modernizr{top:9px;position:absolute}}'].join(''), function( node ) { + bool = node.offsetTop === 9; + }); + } + + return bool; + }; + tests['csstransforms3d'] = function() { + + var ret = !!testPropsAll('perspective'); + + if ( ret && 'webkitPerspective' in docElement.style ) { + + injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function( node, rule ) { + ret = node.offsetLeft === 9 && node.offsetHeight === 3; + }); + } + return ret; + }; + tests['fontface'] = function() { + var bool; + + injectElementWithStyles('@font-face {font-family:"font";src:url("https://")}', function( node, rule ) { + var style = document.getElementById('smodernizr'), + sheet = style.sheet || style.styleSheet, + cssText = sheet ? (sheet.cssRules && sheet.cssRules[0] ? sheet.cssRules[0].cssText : sheet.cssText || '') : ''; + + bool = /src/i.test(cssText) && cssText.indexOf(rule.split(' ')[0]) === 0; + }); + + return bool; + }; + + tests['svg'] = function() { + return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect; + }; + for ( var feature in tests ) { + if ( hasOwnProp(tests, feature) ) { + featureName = feature.toLowerCase(); + Modernizr[featureName] = tests[feature](); + + classes.push((Modernizr[featureName] ? '' : 'no-') + featureName); + } + } + + + + Modernizr.addTest = function ( feature, test ) { + if ( typeof feature == 'object' ) { + for ( var key in feature ) { + if ( hasOwnProp( feature, key ) ) { + Modernizr.addTest( key, feature[ key ] ); + } + } + } else { + + feature = feature.toLowerCase(); + + if ( Modernizr[feature] !== undefined ) { + return Modernizr; + } + + test = typeof test == 'function' ? test() : test; + + if (typeof enableClasses !== "undefined" && enableClasses) { + docElement.className += ' ' + (test ? '' : 'no-') + feature; + } + Modernizr[feature] = test; + + } + + return Modernizr; + }; + + + setCss(''); + modElem = inputElem = null; + + ;(function(window, document) { + var options = window.html5 || {}; + + var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i; + + var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i; + + var supportsHtml5Styles; + + var expando = '_html5shiv'; + + var expanID = 0; + + var expandoData = {}; + + var supportsUnknownElements; + + (function() { + try { + var a = document.createElement('a'); + a.innerHTML = ''; + supportsHtml5Styles = ('hidden' in a); + + supportsUnknownElements = a.childNodes.length == 1 || (function() { + (document.createElement)('a'); + var frag = document.createDocumentFragment(); + return ( + typeof frag.cloneNode == 'undefined' || + typeof frag.createDocumentFragment == 'undefined' || + typeof frag.createElement == 'undefined' + ); + }()); + } catch(e) { + supportsHtml5Styles = true; + supportsUnknownElements = true; + } + + }()); function addStyleSheet(ownerDocument, cssText) { + var p = ownerDocument.createElement('p'), + parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement; + + p.innerHTML = 'x'; + return parent.insertBefore(p.lastChild, parent.firstChild); + } + + function getElements() { + var elements = html5.elements; + return typeof elements == 'string' ? elements.split(' ') : elements; + } + + function getExpandoData(ownerDocument) { + var data = expandoData[ownerDocument[expando]]; + if (!data) { + data = {}; + expanID++; + ownerDocument[expando] = expanID; + expandoData[expanID] = data; + } + return data; + } + + function createElement(nodeName, ownerDocument, data){ + if (!ownerDocument) { + ownerDocument = document; + } + if(supportsUnknownElements){ + return ownerDocument.createElement(nodeName); + } + if (!data) { + data = getExpandoData(ownerDocument); + } + var node; + + if (data.cache[nodeName]) { + node = data.cache[nodeName].cloneNode(); + } else if (saveClones.test(nodeName)) { + node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode(); + } else { + node = data.createElem(nodeName); + } + + return node.canHaveChildren && !reSkip.test(nodeName) ? data.frag.appendChild(node) : node; + } + + function createDocumentFragment(ownerDocument, data){ + if (!ownerDocument) { + ownerDocument = document; + } + if(supportsUnknownElements){ + return ownerDocument.createDocumentFragment(); + } + data = data || getExpandoData(ownerDocument); + var clone = data.frag.cloneNode(), + i = 0, + elems = getElements(), + l = elems.length; + for(;i> 1) : parseInt(o.left, 10) + mid) + 'px', + top: (o.top == 'auto' ? tp.y-ep.y + (target.offsetHeight >> 1) : parseInt(o.top, 10) + mid) + 'px' + }) + } + + el.setAttribute('role', 'progressbar') + self.lines(el, self.opts) + + if (!useCssAnimations) { + // No CSS animation support, use setTimeout() instead + var i = 0 + , start = (o.lines - 1) * (1 - o.direction) / 2 + , alpha + , fps = o.fps + , f = fps/o.speed + , ostep = (1-o.opacity) / (f*o.trail / 100) + , astep = f/o.lines + + ;(function anim() { + i++; + for (var j = 0; j < o.lines; j++) { + alpha = Math.max(1 - (i + (o.lines - j) * astep) % f * ostep, o.opacity) + + self.opacity(el, j * o.direction + start, alpha, o) + } + self.timeout = self.el && setTimeout(anim, ~~(1000/fps)) + })() + } + return self + }, + + /** + * Stops and removes the Spinner. + */ + stop: function() { + var el = this.el + if (el) { + clearTimeout(this.timeout) + if (el.parentNode) el.parentNode.removeChild(el) + this.el = undefined + } + return this + }, + + /** + * Internal method that draws the individual lines. Will be overwritten + * in VML fallback mode below. + */ + lines: function(el, o) { + var i = 0 + , start = (o.lines - 1) * (1 - o.direction) / 2 + , seg + + function fill(color, shadow) { + return css(createEl(), { + position: 'absolute', + width: (o.length+o.width) + 'px', + height: o.width + 'px', + background: color, + boxShadow: shadow, + transformOrigin: 'left', + transform: 'rotate(' + ~~(360/o.lines*i+o.rotate) + 'deg) translate(' + o.radius+'px' +',0)', + borderRadius: (o.corners * o.width>>1) + 'px' + }) + } + + for (; i < o.lines; i++) { + seg = css(createEl(), { + position: 'absolute', + top: 1+~(o.width/2) + 'px', + transform: o.hwaccel ? 'translate3d(0,0,0)' : '', + opacity: o.opacity, + animation: useCssAnimations && addAnimation(o.opacity, o.trail, start + i * o.direction, o.lines) + ' ' + 1/o.speed + 's linear infinite' + }) + + if (o.shadow) ins(seg, css(fill('#000', '0 0 4px ' + '#000'), {top: 2+'px'})) + + ins(el, ins(seg, fill(o.color, '0 0 1px rgba(0,0,0,.1)'))) + } + return el + }, + + /** + * Internal method that adjusts the opacity of a single line. + * Will be overwritten in VML fallback mode below. + */ + opacity: function(el, i, val) { + if (i < el.childNodes.length) el.childNodes[i].style.opacity = val + } + + }) + + + function initVML() { + + /* Utility function to create a VML tag */ + function vml(tag, attr) { + return createEl('<' + tag + ' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">', attr) + } + + // No CSS transforms but VML support, add a CSS rule for VML elements: + sheet.addRule('.spin-vml', 'behavior:url(#default#VML)') + + Spinner.prototype.lines = function(el, o) { + var r = o.length+o.width + , s = 2*r + + function grp() { + return css( + vml('group', { + coordsize: s + ' ' + s, + coordorigin: -r + ' ' + -r + }), + { width: s, height: s } + ) + } + + var margin = -(o.width+o.length)*2 + 'px' + , g = css(grp(), {position: 'absolute', top: margin, left: margin}) + , i + + function seg(i, dx, filter) { + ins(g, + ins(css(grp(), {rotation: 360 / o.lines * i + 'deg', left: ~~dx}), + ins(css(vml('roundrect', {arcsize: o.corners}), { + width: r, + height: o.width, + left: o.radius, + top: -o.width>>1, + filter: filter + }), + vml('fill', {color: o.color, opacity: o.opacity}), + vml('stroke', {opacity: 0}) // transparent stroke to fix color bleeding upon opacity change + ) + ) + ) + } + + if (o.shadow) + for (i = 1; i <= o.lines; i++) + seg(i, -2, 'progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)') + + for (i = 1; i <= o.lines; i++) seg(i) + return ins(el, g) + } + + Spinner.prototype.opacity = function(el, i, val, o) { + var c = el.firstChild + o = o.shadow && o.lines || 0 + if (c && i+o < c.childNodes.length) { + c = c.childNodes[i+o]; c = c && c.firstChild; c = c && c.firstChild + if (c) c.opacity = val + } + } + } + + var probe = css(createEl('group'), {behavior: 'url(#default#VML)'}) + + if (!vendor(probe, 'transform') && probe.adj) initVML() + else useCssAnimations = vendor(probe, 'animation') + + return Spinner + +})); + +/*! + * Bootstrap v3.0.3 + * + * Copyright 2013 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ + ++function(a){"use strict";var b=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};b.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'
    ',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},b.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d);var e=this.options.trigger.split(" ");for(var f=e.length;f--;){var g=e[f];if(g=="click")this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if(g!="manual"){var h=g=="hover"?"mouseenter":"focus",i=g=="hover"?"mouseleave":"blur";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&typeof b.delay=="number"&&(b.delay={show:b.delay,hide:b.delay}),b},b.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},b.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);clearTimeout(c.timeout),c.hoverState="in";if(!c.options.delay||!c.options.delay.show)return c.show();c.timeout=setTimeout(function(){c.hoverState=="in"&&c.show()},c.options.delay.show)},b.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);clearTimeout(c.timeout),c.hoverState="out";if(!c.options.delay||!c.options.delay.hide)return c.hide();c.timeout=setTimeout(function(){c.hoverState=="out"&&c.hide()},c.options.delay.hide)},b.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);if(b.isDefaultPrevented())return;var c=this.tip();this.setContent(),this.options.animation&&c.addClass("fade");var d=typeof this.options.placement=="function"?this.options.placement.call(this,c[0],this.$element[0]):this.options.placement,e=/\s?auto?\s?/i,f=e.test(d);f&&(d=d.replace(e,"")||"top"),c.detach().css({top:0,left:0,display:"block"}).addClass(d),this.options.container?c.appendTo(this.options.container):c.insertAfter(this.$element);var g=this.getPosition(),h=c[0].offsetWidth,i=c[0].offsetHeight;if(f){var j=this.$element.parent(),k=d,l=document.documentElement.scrollTop||document.body.scrollTop,m=this.options.container=="body"?window.innerWidth:j.outerWidth(),n=this.options.container=="body"?window.innerHeight:j.outerHeight(),o=this.options.container=="body"?0:j.offset().left;d=d=="bottom"&&g.top+g.height+i-l>n?"top":d=="top"&&g.top-l-i<0?"bottom":d=="right"&&g.right+h>m?"left":d=="left"&&g.left-h 0 || + $target.hasClass('js-form--search'); + + if (!formSearchInProgress && !formSearchInputMouseDown) { + $('.js-form--search__input').blur(); + } + } + + var appendCheckboxes = function (el, callback) { + + var $elCheckboxes; + + el = el || 'body'; + $elCheckboxes = $(el).find('.js-form__checkbox'); + + $.each($elCheckboxes, function () { + var $this = $(this); + + if (!$this.find('.form__checkbox__item').length) { + $this + .append(''); + setCheckRadioStatus($this); + } + + }); + + if (typeof callback === 'function') { + callback(); + } + + }; + + var appendRadios = function (el, callback) { + + var $elRadios; + + el = el || 'body', + $elRadios = $(el).find('.js-form__radio'); + + $.each($elRadios, function () { + var $this = $(this); + + if (!$this.find('.form__radio__item').length) { + $this + .append(''); + setCheckRadioStatus($this); + } + + }); + + if (typeof callback === 'function') { + callback(); + } + + }; + + var enableInputLoading = function(el, callback) { + var $el = el ? $(el).find('.js-form__input--load') : + $('.js-form__input--load'), + $elParent = $(el).parent(), + $loader = $('') + .addClass('js-loader form__loader loader loader--mini'); + + // Add a loader if there isn't one + if (!$elParent.find('.js-loader').length) { + $el.addClass('form__input--load'); + $elParent.addClass('js-form__load form__load').append($loader); + } + + if (typeof callback === 'function') { + callback(); + } + }; + + var activateInputLoading = function(el) { + enableInputLoading(el, function() { + var $elParent = $(el).parent(), + $loader = $elParent.find('.js-loader'); + + zanata.loader.activate($loader); + $elParent.addClass('is-loading'); + }); + }; + + var deactivateInputLoading = function(el) { + enableInputLoading(el, function() { + var $elParent = $(el).parent(), + $loader = $elParent.find('.js-loader'); + + zanata.loader.deactivate($loader); + $elParent.removeClass('is-loading'); + }); + }; + + + // Form Clear + + var clearFormInit = function() { + + $('.js-form__input--clear').addClass('form__input--clear') + .parent().addClass('form__clear js-form__clear') + .append(''); + + clearFormBindings(); + }; + + var clearFormBindings = function() { + + $('.js-form__button--clear').on('click', function (e) { + e.preventDefault(); + $(this).prev('.js-form__input--clear').val('').focus(); + $(this).addClass('is-hidden'); + }); + + $('.js-form__input--clear').on('keyup', function () { + var $this = $(this), + val = $this.val(), + $clearButton = $this.next('.js-form__button--clear'); + + if (val !== '') { + $clearButton.removeClass('is-hidden'); + } else { + $clearButton.addClass('is-hidden'); + } + }); + + }; + + var radioBindings = function(el) { + el = el || 'body'; + $(el).on('click', '.js-form__radio', function (e) { + setCheckRadio($(this)); + e.preventDefault(); + }); + + $(el).on('change', '.js-form__radio__input', function (e) { + var $parent = $(this).parents('.js-form__radio'); + removeRadioStatus($parent); + setCheckRadioStatus($parent); + }); + + $(el).on('disable', '.js-form__radio__input', function (e) { + var $parent = $(this).parents('.js-form__radio'); + toggleDisableCheckRadio($parent, true); + }); + + $(el).on('enable', '.js-form__radio__input', function (e) { + var $parent = $(this).parents('.js-form__radio'); + toggleDisableCheckRadio($parent, false); + }); + }; + + var checkboxBindings = function(el) { + el = el || 'body'; + $(el).on('click', '.js-form__checkbox', function (e) { + + if ($(this).hasClass('is-disabled')) { + return false; + } + + var directClick = e.target === e.currentTarget; + var tagName = e.target.tagName.toLowerCase(); + var clickOnButton = tagName === 'button'; + var clickOnAnchor = tagName === 'a'; + var clickOnTextbox = tagName === 'input' && e.target.type === 'text'; + var clickOnSubmit = tagName === 'input' && e.target.type === 'submit'; + + var clickOnClickHandler = clickOnButton || clickOnAnchor || + clickOnTextbox || clickOnSubmit; + + if (directClick || !clickOnClickHandler) { + e.preventDefault(); + setCheckRadio($(this)); + } + }); + + $(el).on('change', '.js-form__checkbox__input', function (e) { + var $parent = $(this).parents('.js-form__checkbox'); + setCheckRadioStatus($parent); + }); + + $(el).on('disable', '.js-form__checkbox__input', function (e) { + var $parent = $(this).parents('.js-form__checkbox'); + toggleDisableCheckRadio($parent, true); + }); + + $(el).on('enable', '.js-form__checkbox__input', function (e) { + var $parent = $(this).parents('.js-form__checkbox'); + toggleDisableCheckRadio($parent, false); + }); + + }; + + var init = function (el) { + + el = el || 'body'; + + appendCheckboxes(el, checkboxBindings(el)); + appendRadios(el, radioBindings(el)); + enableInputLoading(); + clearFormInit(el); + + $('.js-form-password-parent') + .on('click', '.js-form-password-toggle', function (e) { + + var $passwordInput = $(this) + .parents('.js-form-password-parent') + .find('.js-form-password-input'); + + e.preventDefault(); + + if ($passwordInput.attr('type') === 'password') { + $passwordInput.attr({ + 'type': 'text', + 'autocapitalize': 'off', + 'autocomplete': 'off', + 'autocorrect': 'off', + 'spellcheck': 'false' + }); + $(this).text('Hide'); + } + else { + $passwordInput.attr('type', 'password'); + $(this).text('Show'); + } + + $passwordInput.focus(); + }); + + $('.js-form--search__input, .js-form--search__button').on('click', + function (e) { + e.stopPropagation(); + } + ); + + $('.js-form--search__input, .js-form--search__button').on('focus', + function () { + $(this).parents('.js-form--search').addClass('is-active'); + } + ); + + $('.js-form--search__input, .js-form--search__button').on('blur', + function (e) { + if (!formSearchInProgress) { + $(this).parents('.js-form--search').removeClass('is-active'); + } + } + ); + + $('.js-form--search').on('mousedown', function(e) { + formSearchInputMouseDown = + $(e.target).hasClass('js-form--search__input'); + updateSearchProgressFlag(e); + }); + + $(document).on('mouseup', function(e) { + updateSearchProgressFlag(e); + // Reset mouse down + formSearchInputMouseDown = false; + }); + + $('.js-form__input--copyable') + .on('mouseup', function () { + var $this = $(this), + thisItem = $this[0]; + if (thisItem.selectionStart === thisItem.selectionEnd) { + $this.select(); + } + }); + + }; + + // public API + return { + init: init, + appendCheckboxes: appendCheckboxes, + appendRadios: appendRadios, + checkboxBindings: checkboxBindings, + radioBindings: radioBindings, + activateInputLoading: activateInputLoading, + deactivateInputLoading: deactivateInputLoading + }; + +})(jQuery); + +jQuery(function () { + zanata.form.init(); +}); + +'use strict'; + +zanata.createNS('zanata.loader'); + +zanata.loader = (function ($) { + + var activate = function (el) { + var $el = $(el), + $label = $el.find('.loader__label'); + + if ($label.length > 0) { + $label.append('' + + ''); + } + else { + $el.append('' + + ''); + } + + $el.addClass('is-active'); + }; + + var deactivate = function (el) { + var $el = $(el); + + $el.find('.loader__spinner').remove(); + $el.removeClass('is-active'); + }; + + var init = function () { + + $(document).on('click', '.js-loader, .loader', function (e) { + // If it is not active + e.preventDefault(); + if (!$(this).hasClass('is-active')) { + activate(this); + } + }); + + }; + + // public API + return { + init: init, + activate: activate, + deactivate: deactivate + }; + +})(jQuery); + +jQuery(function () { + zanata.loader.init(); +}); + + +'use strict'; + +zanata.createNS('zanata.messages'); + +zanata.messages = (function ($) { + + var hide = function (el, e) { + var $el = $(el); + if (e) e.preventDefault(); + if ($el.hasClass('is-active')) { + $el.removeClass('is-active'); + setTimeout(function () { + $el.remove(); + }, 300); + } + else { + $el.addClass('is-removed'); + setTimeout(function () { + $el.remove(); + }, 300); + } + }; + + var activate = function (el) { + $(el).addClass('is-active'); + updatePosition(el); + }; + + var deactivate = function (el) { + $(el).removeClass('is-active'); + }; + + var updatePosition = function (el, elPositionFromTop) { + var $el = $(el), + elPosFromTop = ''; + + if (typeof elPositionFromTop !== 'undefined') { + elPosFromTop = elPositionFromTop; + } + else if($el.length > 0) { + elPosFromTop = $el.offset().top; + } + else { + return; + } + + // Stop negative values setting the position to fixed + if (elPosFromTop < 0) elPosFromTop = 0; + + if ($(window).scrollTop() > elPosFromTop) { + $el.addClass('is-fixed'); + } else { + $el.removeClass('is-fixed'); + } + }; + + var init = function () { + + if ($('.message--global').length > 0) { + var messageGlobalTop = $('.message--global').offset().top; + } + + $(document).on('click', '.js-message-remove', function (e) { + var $el = $(this).parents('.message--removable'); + hide($el, e); + }); + + $(window).scroll(function (){ + updatePosition('.message--global', messageGlobalTop); + }); + }; + + // public API + return { + init: init, + hide: hide, + activate: activate, + deactivate: deactivate, + updatePosition: updatePosition + }; + +})(jQuery); + +jQuery(function () { + zanata.messages.init(); +}); + +'use strict'; + +zanata.createNS('zanata.modal'); + +zanata.modal = (function ($) { + + var show = function (el) { + var $el = $(el); + $el.addClass('is-active').scrollTop(0); + $('body').addClass('is-modal').css('padding-right', getScrollBarWidth()); + }; + + var hide = function (el) { + var $el = $(el); + $el.removeClass('is-active'); + $('body').removeClass('is-modal').removeAttr('style'); + }; + + var init = function () { + + $(document).on('click', '[data-toggle="modal"]', function () { + var modalTarget = $(this).attr('data-target'); + $(modalTarget).trigger('show.zanata.modal'); + }); + + $(document).on('click', '.is-modal', function (e) { + if ($(e.target).not('.modal__dialog') && + !$(e.target).parents('.modal__dialog').length) { + $('.modal.is-active').trigger('hide.zanata.modal'); + } + }); + + $(document).on('keyup', function (e) { + if (e.keyCode === 27) { + e.stopPropagation(); + $('.modal.is-active').trigger('hide.zanata.modal'); + } + }); + + $(document).on('click', '[data-dismiss="modal"]', function () { + $(this).parents('.modal.is-active').trigger('hide.zanata.modal'); + }); + + $(document).on('hide.zanata.modal', function (e) { + hide(e.target); + }); + + $(document).on('show.zanata.modal', function (e) { + show(e.target); + }); + + }; + + function getScrollBarWidth () { + var $outer = $('
    ').css({visibility: 'hidden', width: 100, + overflow: 'scroll'}).appendTo('body'), + widthWithScroll = $('
    ').css({width: '100%'}) + .appendTo($outer).outerWidth(); + $outer.remove(); + return 100 - widthWithScroll; + } + + // public API + return { + init: init, + show: show, + hide: hide + }; + +})(jQuery); + +jQuery(function () { + zanata.modal.init(); +}); + +'use strict'; + +zanata.createNS('zanata.panel'); + +zanata.panel = (function ($) { + + var init = function () { + var $panelBody = $('.js-panel__body'); + var resizeTimeout; + function resizePanels() { + var windowHeight = $(window).height(); + $.each($panelBody, function(i) { + var $this = $(this); + var $panel = $this.parents('.js-panel'); + var panelFromTop = $panelBody[i].getBoundingClientRect().top; + var footerHeight = $('.js-footer').height(); + var panelHeight = Math.floor( + // Minus 2 to account for rounding errors + windowHeight - panelFromTop - footerHeight - 2 + ); + $this.css('height', panelHeight); + }); + } + if ($panelBody.length > 0) { + $(window).resize(function(event) { + clearTimeout(resizeTimeout); + resizeTimeout = setTimeout(resizePanels, 0); + }); + resizePanels(); + } + }; + + // public API + return { + init: init + }; + +})(jQuery); + +jQuery(function () { + zanata.panel.init(); +}); + +(function ($) { + 'use strict'; + $(document).on('click', '.js-reveal__show', function () { + var $revealTarget = $($(this).attr('data-target')), + $revealTargetInput = $revealTarget.find('.js-reveal__target__input'), + $revealParent = $(this).parents('.js-reveal'); + $(this).addClass('is-hidden'); + $revealParent.addClass('is-active'); + $revealTarget.toggleClass('is-active'); + setTimeout(function () { + $revealTargetInput.focus(); + }, 100); + }); + $(document).on('click', '.js-reveal__toggle', function (e) { + var $revealTarget = $($(this).attr('data-target')), + $revealTargetInput = $revealTarget.find('.js-reveal__target__input'), + $revealParent = $(this).parents('.js-reveal'), + $revealText = $(this).find('.js-reveal__toggle__text'), + revealTextValue = $revealText.text(), + revealToggleValue = $revealText.attr('data-toggle-value'), + revealTitle = $(this).attr('title') || + $(this).attr('data-original-title'), + revealToggleTitle = $(this).attr('data-toggle-title'); + + // Label need to register the click so it applies to the checkbox or radio + // it is attached to + if (!$(e.target).is('label')) { + e.preventDefault(); + } + $(this).toggleClass('is-active'); + $revealParent.toggleClass('is-active'); + $revealTarget.toggleClass('is-active is-hidden'); + if (revealToggleTitle && revealTitle) { + $(this).attr('data-toggle-title', revealTitle); + zanata.tooltip.refresh($(this), revealToggleTitle); + } + if (revealTextValue && revealToggleValue) { + $revealText.text(revealToggleValue); + $revealText.attr('data-toggle-value', revealTextValue); + } + setTimeout(function () { + $revealTargetInput.focus(); + }, 100); + }); + + $(document).on('click', '.js-reveal__reset', function () { + var $revealTarget = $($(this).attr('data-target')), + $revealTargetInput = $revealTarget.find('.js-reveal__target__input'); + $revealTargetInput.val('').focus(); + $(this).addClass('is-hidden'); + }); + $(document).on('click', '.js-reveal__cancel', function () { + var $revealTarget = $($(this).attr('data-target')), + $revealTargetInput = $revealTarget.find('.js-reveal__target__input'), + $revealParent = $(this).parents('.js-reveal'); + $revealTarget.removeClass('is-active'); + $revealTargetInput.blur(); + $revealTargetInput.val(''); + $revealParent.find('.js-reveal__reset').addClass('is-hidden'); + $revealParent.find('.js-reveal__show').removeClass('is-hidden').focus(); + }); + $(document).on('keyup', '.js-reveal__target__input', function (e) { + var $revealParent = $(this).parents('.js-reveal'), + $revealReset = $revealParent.find('.js-reveal__reset'), + $revealCancel = $revealParent.find('.js-reveal__cancel'); + if ($(this).val() !== '') { + $revealReset.removeClass('is-hidden'); + } + else { + $revealReset.addClass('is-hidden'); + } + if (e.keyCode === 27) { + $revealCancel.click(); + } + }); + +})(jQuery); + +jQuery(function () { + 'use strict'; + + var pathname = window.location.pathname; + + // Check the url, see which links match and make them active + jQuery('#nav-user a, #nav-main a, #nav-main-side a, #nav-footer a') + .each(function () { + var navLink = jQuery(this) + .attr('href') + .replace(/\//g, '') + .replace(/\./g, ''); + if (pathname.toLowerCase().indexOf(navLink) >= 0) { + jQuery(this).addClass('is-active'); + } + }); + +}); + +'use strict'; + +zanata.createNS('zanata.tabs'); + +zanata.tabs = (function ($) { + + var activate = function (el) { + + var $this = $(el), + targetHash = $this.attr('href'), + targetID = targetHash.replace('#', ''), + $parent = $this.closest('.js-tabs'); + // data-content attribute should have a selector for the + // content container for the tab + if($this.is('[data-content]')) { + targetHash = $this.attr('data-content'); + } + if (!$this.parent().hasClass('is-active')) { + // Remove all is-active classes + $parent + .find('> .js-tabs-content > li, > .js-tabs-nav > li > a') + .removeClass('is-active'); + // Add relevant is-active classes + $this.blur().addClass('is-active'); + // Add hashed class so we can remove ID to change the hash + $(targetHash) + .addClass('is-active'); + // When changing tabs check for panels and resize to fit browser + if ($(targetHash).find('.js-panel__body').length > 0) { + zanata.panel.init(); + } + } + + }; + + var init = function () { + + $('.js-tabs').on('click', '.js-tabs-nav > li > a', function (e) { + e.preventDefault(); + activate(this); + }); + + }; + + // public API + return { + init: init, + activate: activate + }; + +})(jQuery); + +jQuery(function () { + zanata.tabs.init(); +}); + +'use strict'; + +zanata.createNS('zanata.tooltip'); + +zanata.tooltip = (function ($) { + + // Private methods + var init = function (el) { + $(el).tooltip({ + placement: 'auto bottom', + container: 'body', + delay: { + show: '500', + hide: '100' + } + }); + }; + + var refresh = function (el, newTitle) { + $(el) + .tooltip('hide') + .attr('data-original-title', newTitle) + .tooltip('fixTitle') + .tooltip('show'); + }; + + // public API + return { + init: init, + refresh: refresh + }; + +})(jQuery); From 0d2a71cdb51f97609d796f89085c578842bae51c Mon Sep 17 00:00:00 2001 From: Earl Floden Date: Mon, 24 Jul 2017 13:31:19 +1000 Subject: [PATCH 107/116] fix(ZNTA-2121): correct usages of this.state in setState --- .../frontend/app/components/Sidebar/index.jsx | 4 ++-- .../app/containers/Glossary/NewEntryModal.js | 19 ++++++++----------- .../containers/Languages/NewLanguageModal.js | 14 +++++++------- .../UserProfile/RecentContributions.jsx | 6 +++--- .../app/editor/containers/Sidebar/index.js | 2 +- .../scripts/codemods/stateful.template.js | 5 +++-- 6 files changed, 24 insertions(+), 26 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/components/Sidebar/index.jsx b/server/zanata-frontend/src/frontend/app/components/Sidebar/index.jsx index cea77f8c0c..9b08a96c73 100644 --- a/server/zanata-frontend/src/frontend/app/components/Sidebar/index.jsx +++ b/server/zanata-frontend/src/frontend/app/components/Sidebar/index.jsx @@ -17,8 +17,8 @@ class Sidebar extends Component { } toggleDisplay () { - this.setState({display: !this.state.display}) - this.setState({arrow: !this.state.arrow}) + this.setState(prevState => ({display: !prevState.display})) + this.setState(prevState => ({arrow: !prevState.arrow})) } /* eslint-disable react/jsx-no-bind, no-return-assign */ render () { diff --git a/server/zanata-frontend/src/frontend/app/containers/Glossary/NewEntryModal.js b/server/zanata-frontend/src/frontend/app/containers/Glossary/NewEntryModal.js index 3b7f72057b..7157a20727 100644 --- a/server/zanata-frontend/src/frontend/app/containers/Glossary/NewEntryModal.js +++ b/server/zanata-frontend/src/frontend/app/containers/Glossary/NewEntryModal.js @@ -8,6 +8,7 @@ import { glossaryToggleNewEntryModal, glossaryCreateNewEntry } from '../../actions/glossary-actions' +import update from 'immutability-helper' class NewEntryModal extends Component { static propTypes = { @@ -26,17 +27,13 @@ class NewEntryModal extends Component { } handleContentChanged = (e) => { - const { entry } = this.state - const { srcTerm } = entry - this.setState({ - entry: { - ...entry, - srcTerm: { - ...srcTerm, - content: e.target.value - } - } - }) + const content = e.target.value + this.setState(prevState => ({ + entry: update(prevState.entry, + {srcTerm: + {content: {$set: content}} + }) + })) } handlePosChanged = (e) => { diff --git a/server/zanata-frontend/src/frontend/app/containers/Languages/NewLanguageModal.js b/server/zanata-frontend/src/frontend/app/containers/Languages/NewLanguageModal.js index 05cf3e54b5..ccd51e0f08 100644 --- a/server/zanata-frontend/src/frontend/app/containers/Languages/NewLanguageModal.js +++ b/server/zanata-frontend/src/frontend/app/containers/Languages/NewLanguageModal.js @@ -67,21 +67,21 @@ class NewLanguageModal extends Component { } updateField = (field, e) => { - this.setState({ + this.setState(prevState => ({ details: { - ...this.state.details, + ...prevState.details, [field]: e.target.value } - }) + })) } updateCheckbox = (field) => { - this.setState({ + this.setState(prevState => ({ details: { - ...this.state.details, - [field]: !this.state.details[field] + ...prevState.details, + [field]: !prevState.details[field] } - }) + })) } validateDetails = () => { diff --git a/server/zanata-frontend/src/frontend/app/containers/UserProfile/RecentContributions.jsx b/server/zanata-frontend/src/frontend/app/containers/UserProfile/RecentContributions.jsx index a951c10219..d08949e6f4 100644 --- a/server/zanata-frontend/src/frontend/app/containers/UserProfile/RecentContributions.jsx +++ b/server/zanata-frontend/src/frontend/app/containers/UserProfile/RecentContributions.jsx @@ -34,9 +34,9 @@ class RecentContributions extends React.Component { } onToggleShowDateRange = () => { - this.setState({ - showDateRange: !this.state.showDateRange - }) + this.setState(prevState => ({ + showDateRange: !prevState.showDateRange + })) } onDateRangeChanged = (dateRange) => { diff --git a/server/zanata-frontend/src/frontend/app/editor/containers/Sidebar/index.js b/server/zanata-frontend/src/frontend/app/editor/containers/Sidebar/index.js index 0715580698..7849a0c477 100644 --- a/server/zanata-frontend/src/frontend/app/editor/containers/Sidebar/index.js +++ b/server/zanata-frontend/src/frontend/app/editor/containers/Sidebar/index.js @@ -38,7 +38,7 @@ class Sidebar extends Component { // } // // mediaQueryChanged () { - // this.setState({docked: this.state.mql.matches}) + // this.setState(prevState => ({docked: prevState.mql.matches})) // } setOpen = (open) => { diff --git a/server/zanata-frontend/src/frontend/scripts/codemods/stateful.template.js b/server/zanata-frontend/src/frontend/scripts/codemods/stateful.template.js index 9eb6a98e70..245f7651af 100644 --- a/server/zanata-frontend/src/frontend/scripts/codemods/stateful.template.js +++ b/server/zanata-frontend/src/frontend/scripts/codemods/stateful.template.js @@ -25,8 +25,9 @@ class COMPONENT_NAME_HERE extends Component { } onClick = () => { - const clicks = this.state.clicks + 1 - this.setState({ clicks }) + this.setState(prevState => ({ + clicks: prevState.clicks + 1 + })) this.props.onClick(`The cow says ${this.props.noise}`) } From 6785e7ddfdd018987804ed8c2a957019f37e5cf6 Mon Sep 17 00:00:00 2001 From: Alex Eng Date: Mon, 24 Jul 2017 15:13:43 +1000 Subject: [PATCH 108/116] fix: update member page when add/remove mainainers (#437) https://zanata.atlassian.net/browse/ZNTA-666 --- .../main/webapp/WEB-INF/layout/project/settings-tab.xhtml | 8 ++++---- server/zanata-war/src/main/webapp/project/project.xhtml | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/server/zanata-war/src/main/webapp/WEB-INF/layout/project/settings-tab.xhtml b/server/zanata-war/src/main/webapp/WEB-INF/layout/project/settings-tab.xhtml index f3b6c07bfa..481e9ba36a 100644 --- a/server/zanata-war/src/main/webapp/WEB-INF/layout/project/settings-tab.xhtml +++ b/server/zanata-war/src/main/webapp/WEB-INF/layout/project/settings-tab.xhtml @@ -119,9 +119,9 @@ + render="settings-permissions-form">
  • @@ -137,8 +137,8 @@ actionBean="#{projectHome.maintainerAutocomplete}" maxlength="80" minlength="3" id="maintainerAutocomplete" fetchValue="#{result.account.username}" - render="settings-permissions-form,maintainers-size, maintainers-form" - oncomplete="zanata.form.appendCheckboxes(getUserRoleId());focusCurrentActiveInput()" + render="settings-permissions-form" + oncomplete="resetProjectMembers();zanata.form.appendCheckboxes(getUserRoleId());focusCurrentActiveInput()" placeholder="#{msgs['jsf.SearchUsers']}"> diff --git a/server/zanata-war/src/main/webapp/project/project.xhtml b/server/zanata-war/src/main/webapp/project/project.xhtml index 2a7ece00db..291014b4b2 100644 --- a/server/zanata-war/src/main/webapp/project/project.xhtml +++ b/server/zanata-war/src/main/webapp/project/project.xhtml @@ -96,6 +96,10 @@ render="versions_form" action="#{projectHomeAction.setPageRendered(true)}"/> + +
    From b9a3853ef1adfda4e3933406afcf3c832b755378 Mon Sep 17 00:00:00 2001 From: Alex Eng Date: Tue, 25 Jul 2017 08:03:18 +1000 Subject: [PATCH 109/116] fix: update project#description dto size (#440) https://zanata.atlassian.net/browse/ZNTA-330 --- .../src/main/java/org/zanata/rest/dto/Project.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/Project.java b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/Project.java index 9ffc48f874..227f0740ee 100644 --- a/api/zanata-common-api/src/main/java/org/zanata/rest/dto/Project.java +++ b/api/zanata-common-api/src/main/java/org/zanata/rest/dto/Project.java @@ -113,7 +113,7 @@ public void setName(String name) { this.name = name; } - @Size(max = 80) + @Size(max = 100) @XmlElement(name = "description", required = false, namespace = Namespaces.ZANATA_OLD) @DocumentationExample("This is a sample project.") From b95e8fabfc8a2d89fd3391a103ec1bb44104a600 Mon Sep 17 00:00:00 2001 From: Alex Eng Date: Tue, 25 Jul 2017 08:03:44 +1000 Subject: [PATCH 110/116] fix: sort language by display name in project/version page (#438) https://zanata.atlassian.net/browse/ZNTA-658 --- .../java/org/zanata/action/ProjectHome.java | 19 +++++++++---------- .../java/org/zanata/action/VersionHome.java | 19 +++++++++---------- .../java/org/zanata/util/ComparatorUtil.java | 2 +- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/action/ProjectHome.java b/server/zanata-war/src/main/java/org/zanata/action/ProjectHome.java index 27b900523b..aa903485e9 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/ProjectHome.java +++ b/server/zanata-war/src/main/java/org/zanata/action/ProjectHome.java @@ -30,6 +30,7 @@ import java.util.Map; import java.util.ResourceBundle; import java.util.Set; +import java.util.stream.Collectors; import javax.annotation.Nullable; import javax.enterprise.inject.Any; import javax.enterprise.inject.Model; @@ -205,16 +206,14 @@ public List getDisabledLocales() { * already in the project. */ private List findActiveNotEnabledLocales() { - Collection filtered = Collections2 - .filter(localeDAO.findAllActive(), new Predicate() { - - @Override - public boolean apply(HLocale input) { - // only include those not already in the project - return !getEnabledLocales().contains(input); - } - }); - return Lists.newArrayList(filtered); + List activeLocales = localeDAO.findAllActive(); + // only include those not already in the project + List filteredList = activeLocales.stream() + .filter(hLocale -> !getEnabledLocales().contains(hLocale)) + .collect( + Collectors.toList()); + Collections.sort(filteredList, ComparatorUtil.LOCALE_COMPARATOR); + return filteredList; } private Map roleRestrictions; diff --git a/server/zanata-war/src/main/java/org/zanata/action/VersionHome.java b/server/zanata-war/src/main/java/org/zanata/action/VersionHome.java index 42abb0e932..c4627c5f3a 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/VersionHome.java +++ b/server/zanata-war/src/main/java/org/zanata/action/VersionHome.java @@ -79,6 +79,7 @@ import java.util.List; import java.util.Map; import java.util.ResourceBundle; +import java.util.stream.Collectors; @Named("versionHome") @ViewScoped @@ -946,16 +947,14 @@ public List getDisabledLocales() { * already in the project. */ private List findActiveNotEnabledLocales() { - Collection filtered = Collections2 - .filter(localeDAO.findAllActive(), new Predicate() { - - @Override - public boolean apply(HLocale input) { - // only include those not already in the project - return !getEnabledLocales().contains(input); - } - }); - return Lists.newArrayList(filtered); + List activeLocales = localeDAO.findAllActive(); + // only include those not already in the project version + List filteredList = activeLocales.stream() + .filter(hLocale -> !getEnabledLocales().contains(hLocale)) + .collect( + Collectors.toList()); + Collections.sort(filteredList, ComparatorUtil.LOCALE_COMPARATOR); + return filteredList; } private Map selectedDisabledLocales = Maps.newHashMap(); diff --git a/server/zanata-war/src/main/java/org/zanata/util/ComparatorUtil.java b/server/zanata-war/src/main/java/org/zanata/util/ComparatorUtil.java index b58a4034af..18ddea58c0 100644 --- a/server/zanata-war/src/main/java/org/zanata/util/ComparatorUtil.java +++ b/server/zanata-war/src/main/java/org/zanata/util/ComparatorUtil.java @@ -43,7 +43,7 @@ public class ComparatorUtil { new Comparator() { @Override public int compare(HLocale hLocale, HLocale hLocale2) { - return hLocale.retrieveDisplayName().compareTo( + return hLocale.retrieveDisplayName().compareToIgnoreCase( hLocale2.retrieveDisplayName()); } }; From 61c9d432f6f9faa9df132ebe8e8a3de9e5eccc99 Mon Sep 17 00:00:00 2001 From: Alex Eng Date: Tue, 25 Jul 2017 08:03:56 +1000 Subject: [PATCH 111/116] fix: disable button when no roles is selected (#439) https://zanata.atlassian.net/browse/ZNTA-274 --- .../org/zanata/action/LanguageAction.java | 9 +++++ .../layout/language/search_user_modal.xhtml | 33 +++++++++++++------ 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/action/LanguageAction.java b/server/zanata-war/src/main/java/org/zanata/action/LanguageAction.java index 0833edbe3c..7bc21da35d 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/LanguageAction.java +++ b/server/zanata-war/src/main/java/org/zanata/action/LanguageAction.java @@ -207,6 +207,15 @@ public void addSelected() { resetLocale(); } + public boolean isAnySelected() { + for (SelectablePerson selectablePerson : getSearchResults()) { + if (selectablePerson.isSelected()) { + return true; + } + } + return false; + } + public String getPluralsPlaceholder() { String pluralForms = resourceUtils .getPluralForms(new LocaleId(language), false, true); diff --git a/server/zanata-war/src/main/webapp/WEB-INF/layout/language/search_user_modal.xhtml b/server/zanata-war/src/main/webapp/WEB-INF/layout/language/search_user_modal.xhtml index 7854ec2101..a7d731dc9b 100644 --- a/server/zanata-war/src/main/webapp/WEB-INF/layout/language/search_user_modal.xhtml +++ b/server/zanata-war/src/main/webapp/WEB-INF/layout/language/search_user_modal.xhtml @@ -33,26 +33,30 @@ -
    - -
    + + + + + + + + +
    From b0ca278509a23ea8c06c3cfc46c29003262a5855 Mon Sep 17 00:00:00 2001 From: kgough Date: Tue, 25 Jul 2017 09:48:45 +1000 Subject: [PATCH 112/116] fix(ZNTA-2087) used css variable and fixed hover colour for buttonOff element --- server/zanata-frontend/src/frontend/app/styles/style.less | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server/zanata-frontend/src/frontend/app/styles/style.less b/server/zanata-frontend/src/frontend/app/styles/style.less index 4da9a1715f..2dd2a9f6fc 100644 --- a/server/zanata-frontend/src/frontend/app/styles/style.less +++ b/server/zanata-frontend/src/frontend/app/styles/style.less @@ -6650,9 +6650,10 @@ table.tmx-table .badge .n1 { hyphens: initial; } -.new-zanata .button--group input[type=radio]:checked+.button--Off { +.new-zanata .button--group input[type=radio]:checked+.button--Off, +.new-zanata .button--group input[type=radio]:checked+.button--Off:hover { background-color: @color-dark !important; - color: #f2f2f2; + color: @gray-lighter; } .panel__header a#new-version-link i.i.i--add:not(.i--large) { From 2b9360ceac7396a5322fcad2ac629e02c4b3cd21 Mon Sep 17 00:00:00 2001 From: Alex Eng Date: Tue, 25 Jul 2017 19:29:19 +1000 Subject: [PATCH 113/116] fix: update page when remove group maintainer (#446) https://zanata.atlassian.net/browse/ZNTA-182 --- .../main/java/org/zanata/action/VersionGroupHome.java | 9 ++++++++- .../main/java/org/zanata/security/SecurityFunctions.java | 7 +++++-- .../src/main/java/org/zanata/util/UrlUtil.java | 4 ++++ .../WEB-INF/layout/version-group/settings-tab.xhtml | 1 - 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/server/zanata-war/src/main/java/org/zanata/action/VersionGroupHome.java b/server/zanata-war/src/main/java/org/zanata/action/VersionGroupHome.java index 6af3e22c07..f1110bf5ed 100644 --- a/server/zanata-war/src/main/java/org/zanata/action/VersionGroupHome.java +++ b/server/zanata-war/src/main/java/org/zanata/action/VersionGroupHome.java @@ -60,6 +60,7 @@ import com.google.common.base.Predicate; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; +import org.zanata.util.UrlUtil; /** * @author Alex Eng aeng@redhat.com @@ -94,6 +95,8 @@ public class VersionGroupHome extends SlugHome private VersionAutocomplete versionAutocomplete; @Inject private GroupLocaleAutocomplete localeAutocomplete; + @Inject + private UrlUtil urlUtil; private AbstractListFilter maintainerFilter = new InMemoryListFilter() { @@ -223,10 +226,14 @@ public void removeMaintainer(HPerson maintainer) { } else { getInstance().removeMaintainer(maintainer); maintainerFilter.reset(); - update(); + super.update(); conversationScopeMessages.setMessage(FacesMessage.SEVERITY_INFO, msgs.format("jsf.MaintainerRemoveFromGroup", maintainer.getName())); + if (maintainer.equals(authenticatedAccount.getPerson())) { + urlUtil.redirectToInternal( + urlUtil.groupUrl(getInstance().getSlug())); + } } } diff --git a/server/zanata-war/src/main/java/org/zanata/security/SecurityFunctions.java b/server/zanata-war/src/main/java/org/zanata/security/SecurityFunctions.java index 6c5e40416e..6e1e556117 100644 --- a/server/zanata-war/src/main/java/org/zanata/security/SecurityFunctions.java +++ b/server/zanata-war/src/main/java/org/zanata/security/SecurityFunctions.java @@ -500,8 +500,11 @@ public boolean canDownloadFiles(HProjectIteration projectIteration) { */ @GrantsPermission(actions = "update") public boolean canUpdateVersionGroup(HIterationGroup group) { - return isLoggedIn() - && authenticatedAccount.get().getPerson().isMaintainer(group); + if (isLoggedIn()) { + HPerson person = authenticatedAccount.get().getPerson(); + return group.getMaintainers().contains(person); + } + return false; } @GrantsPermission(actions = "insert") diff --git a/server/zanata-war/src/main/java/org/zanata/util/UrlUtil.java b/server/zanata-war/src/main/java/org/zanata/util/UrlUtil.java index 720f053c2d..abf6c74dae 100644 --- a/server/zanata-war/src/main/java/org/zanata/util/UrlUtil.java +++ b/server/zanata-war/src/main/java/org/zanata/util/UrlUtil.java @@ -138,6 +138,10 @@ public String projectUrl(String projectSlug) { return contextPath + "/project/view/" + projectSlug + dswidQuery; } + public String groupUrl(String groupSlug) { + return contextPath + "/version-group/view/" + groupSlug + dswidQuery; + } + /** * Get add-version url with dswid parameter */ diff --git a/server/zanata-war/src/main/webapp/WEB-INF/layout/version-group/settings-tab.xhtml b/server/zanata-war/src/main/webapp/WEB-INF/layout/version-group/settings-tab.xhtml index 2838740e7f..f46e3fcff6 100644 --- a/server/zanata-war/src/main/webapp/WEB-INF/layout/version-group/settings-tab.xhtml +++ b/server/zanata-war/src/main/webapp/WEB-INF/layout/version-group/settings-tab.xhtml @@ -223,7 +223,6 @@ styleClass="button--link l--float-right reveal__target" action="#{versionGroupHome.removeMaintainer(maintainer)}" onbegin="jQuery('#remove-maintainer-#{status.index}').addClass('is-hidden')" - execute="@this" render="settings-maintainers-form,maintainers-size,maintainers-list,maintainers-form" title="#{msgs['jsf.group.RemoveMaintainer.title']}"> #{msgs['jsf.group.RemoveMaintainer.sr.label']} From 10575d631e2ddea3335c7bb7034574ed6d05de65 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Wed, 26 Jul 2017 10:24:45 +1000 Subject: [PATCH 114/116] fix checkstyle --- .../src/main/webapp/resources/assets/css/style.css | 10 +++++----- .../resources/assets/fonts/zanata-v6/selection.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/server/zanata-war/src/main/webapp/resources/assets/css/style.css b/server/zanata-war/src/main/webapp/resources/assets/css/style.css index 5d789d6995..4811d80ffe 100644 --- a/server/zanata-war/src/main/webapp/resources/assets/css/style.css +++ b/server/zanata-war/src/main/webapp/resources/assets/css/style.css @@ -3386,11 +3386,11 @@ All icons also need the class `.i` added to them. Use to display icons to the far side of text, either left or right. Usually used in a list.
      -
    • Text
    • -
    • Text
    • -
    • - Text -
    • +
    • Text
    • +
    • Text
    • +
    • + Text +
    */ diff --git a/server/zanata-war/src/main/webapp/resources/assets/fonts/zanata-v6/selection.json b/server/zanata-war/src/main/webapp/resources/assets/fonts/zanata-v6/selection.json index 07c3d62255..9c154f99f3 100755 --- a/server/zanata-war/src/main/webapp/resources/assets/fonts/zanata-v6/selection.json +++ b/server/zanata-war/src/main/webapp/resources/assets/fonts/zanata-v6/selection.json @@ -1340,4 +1340,4 @@ "UntitledProject": "MzAzZWE0YTEwNjhkNTQ4NjkxYmQ4YTlmZjRlYjNiNTAjMSMxNDc2MDU4MzgwIyMj" } } -} \ No newline at end of file +} From 78a61ec914b59c97c790417c2a9868303da7f3b2 Mon Sep 17 00:00:00 2001 From: Damian Jansen Date: Thu, 27 Jul 2017 10:49:54 +1000 Subject: [PATCH 115/116] fix(ZNTA-2132): Incorrect tooltip for export project/version tmx (#447) * fix(ZNTA-2132): Incorrect tooltip for export version tmx * fix(ZNTA-2132): Incorrect tooltip for export project tmx --- server/zanata-war/src/main/resources/messages.properties | 2 ++ server/zanata-war/src/main/webapp/iteration/view.xhtml | 2 +- server/zanata-war/src/main/webapp/project/project.xhtml | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/server/zanata-war/src/main/resources/messages.properties b/server/zanata-war/src/main/resources/messages.properties index 062206b4a9..4c00f44624 100644 --- a/server/zanata-war/src/main/resources/messages.properties +++ b/server/zanata-war/src/main/resources/messages.properties @@ -376,6 +376,7 @@ jsf.NoPeople=No people are assigned to this project jsf.project.RoleRestrictions=Role Restrictions jsf.project.ProjectRestrictedToFollowingRoles=This project has restricted access for the following User roles: jsf.ExportTMXProject=Export project to TMX +jsf.iteration.ExportTMXProjectInfo=Export all translations in this project to TMX jsf.ConfirmExportTMXProject=Are you sure you want to export this project to TMX? jsf.project.SourceCode=Source Code jsf.project.HomePage=Home Page @@ -653,6 +654,7 @@ jsf.pager.NextPage=Next jsf.pager.PreviousPage=Previous jsf.iteration.ExportTMXIter=Export Version to TMX +jsf.iteration.ExportTMXIterInfo=Export all translations in this version to TMX jsf.iteration.ExportTMX.Language=Export {0} Documents to TMX jsf.iteration.files.NoFiles=No Files Available diff --git a/server/zanata-war/src/main/webapp/iteration/view.xhtml b/server/zanata-war/src/main/webapp/iteration/view.xhtml index ab3ecd58f6..6eebb8ab94 100644 --- a/server/zanata-war/src/main/webapp/iteration/view.xhtml +++ b/server/zanata-war/src/main/webapp/iteration/view.xhtml @@ -471,7 +471,7 @@
  • #{msgs['jsf.iteration.ExportTMXIter']} diff --git a/server/zanata-war/src/main/webapp/project/project.xhtml b/server/zanata-war/src/main/webapp/project/project.xhtml index 291014b4b2..152c28fc36 100644 --- a/server/zanata-war/src/main/webapp/project/project.xhtml +++ b/server/zanata-war/src/main/webapp/project/project.xhtml @@ -257,7 +257,7 @@ role="content" aria-labelledby="dropdownContent">
  • #{msgs['jsf.ExportTMXProject']} From db460eb679aa1f66c1164ef58fa5df49071c9e2b Mon Sep 17 00:00:00 2001 From: Alex Eng Date: Fri, 28 Jul 2017 09:49:56 +1000 Subject: [PATCH 116/116] refactor: replace hamcrest with assertJ (#452) https://zanata.atlassian.net/browse/ZNTA-1344 --- server/functional-test/pom.xml | 11 - .../feature/glossary/GlossaryAdminTest.java | 6 +- .../zanata/feature/rest/CopyTransTest.java | 6 - .../versionGroup/VersionGroupUrlTest.java | 25 +- server/zanata-model/pom.xml | 9 - .../java/org/zanata/model/HTextFlowTest.java | 16 +- .../org/zanata/model/SlugEntityBaseTest.java | 19 +- .../org/zanata/model/StatusCountTest.java | 14 +- .../test/java/org/zanata/tmx/TMXUtilTest.java | 29 +- server/zanata-war/pom.xml | 12 - .../arquillian/DeploymentsSanityTest.java | 2 - .../config/DatabaseBackedConfigTest.java | 64 ++- .../java/org/zanata/dao/DocumentDAOTest.java | 21 +- .../java/org/zanata/dao/GlossaryDAOTest.java | 25 +- .../java/org/zanata/dao/LocaleDAOTest.java | 26 +- .../org/zanata/dao/LocaleMemberDAOITCase.java | 13 +- .../java/org/zanata/dao/ProjectDAOTest.java | 37 +- .../java/org/zanata/dao/TextFlowDAOTest.java | 38 +- .../zanata/dao/TextFlowStreamingDAOTest.java | 19 +- ...extFlowTargetReviewCommentsDAOJPATest.java | 23 +- .../dao/TransMemoryStreamingDAOTest.java | 5 +- .../SequentialConnectionIdGeneratorTest.java | 17 +- .../org/zanata/file/DocumentUploadTest.java | 11 +- .../zanata/file/DocumentUploadUtilTest.java | 109 ++--- .../org/zanata/file/GlobalDocumentIdTest.java | 19 +- .../zanata/file/SourceDocumentUploadTest.java | 36 +- .../org/zanata/limits/LeakyBucketTest.java | 16 +- .../zanata/model/CacheReliabilityTest.java | 32 +- .../org/zanata/model/DocumentJPATest.java | 45 +- .../zanata/model/HDocumentHistoryJPATest.java | 29 +- .../zanata/model/HGlossaryEntryJPATest.java | 7 +- .../zanata/model/HTextFlowHistoryJPATest.java | 45 +- .../org/zanata/model/HTextFlowJPATest.java | 59 +-- .../model/HTextFlowTargetHistoryJPATest.java | 27 +- .../org/zanata/model/TransMemoryJPATest.java | 30 +- .../compat/AccountRawCompatibilityITCase.java | 78 ++- ...rojectIterationRawCompatibilityITCase.java | 26 +- .../compat/ProjectRawCompatibilityITCase.java | 42 +- .../compat/StatisticsCompatibilityITCase.java | 103 ++-- .../TranslationsCompatibilityITCase.java | 221 +++++---- .../TranslationsRawCompatibilityITCase.java | 227 +++++---- .../zanata/rest/service/FileServiceTest.java | 12 +- .../rest/service/ResourceUtilsParamTest.java | 13 +- .../rest/service/ResourceUtilsTest.java | 93 ++-- .../zanata/rest/service/RestUtilsTest.java | 5 +- .../rest/service/TranslatorCreditTest.java | 11 +- .../service/raw/AccountRawRestITCase.java | 43 +- .../raw/AnonymousUserRawRestITCase.java | 30 +- .../raw/AsyncProcessRawRestITCase.java | 7 +- .../service/raw/AsyncResourceRestITCase.java | 35 +- .../rest/service/raw/FileRawRestITCase.java | 27 +- .../raw/ProjectIterationRawRestITCase.java | 41 +- .../service/raw/ProjectRawRestITCase.java | 89 ++-- .../raw/ProjectVersionRawRestITCase.java | 43 +- .../rest/service/raw/ProjectsRestITCase.java | 9 +- .../raw/ResourceServiceRestITCase.java | 62 ++- .../service/raw/StatisticsRawRestITCase.java | 160 +++---- .../raw/TranslationResourceRestITCase.java | 217 ++++----- .../service/raw/VersionRawRestITCase.java | 7 +- .../zanata/search/ContentCriterionTest.java | 15 +- .../FilterConstraintToQueryJpaTest.java | 45 +- .../search/FilterConstraintToQueryTest.java | 47 +- .../service/impl/ActivityServiceImplTest.java | 25 +- .../service/impl/CopyTransWorkTest.java | 61 ++- .../service/impl/DocumentServiceImplTest.java | 24 +- .../impl/GlossarySearchServiceImplTest.java | 13 +- .../impl/LockManagerServiceImplTest.java | 19 +- .../impl/TextFlowSearchServiceImplTest.java | 5 +- .../impl/TransMemoryMergeServiceImplTest.java | 61 ++- .../impl/TranslationFileServiceImplTest.java | 8 +- .../TranslationMergeServiceFactoryTest.java | 9 +- .../impl/TranslationServiceImplTest.java | 62 ++- .../impl/TranslationStateCacheImplTest.java | 11 +- .../impl/TranslationUpdatedManagerTest.java | 11 +- .../impl/UserAccountServiceImplTest.java | 40 +- .../impl/VersionGroupServiceImplTest.java | 28 +- .../impl/VersionStateCacheImplTest.java | 7 +- .../java/org/zanata/test/LambdaMatcher.java | 32 -- .../java/org/zanata/tmx/TMXParserTest.java | 139 +++--- .../java/org/zanata/util/FileUtilTest.java | 11 +- .../org/zanata/util/QueryBuilderTest.java | 43 +- .../TransMemoryMergeStatusResolverTest.java | 25 +- .../webtrans/client/EventProcessorTest.java | 11 +- .../client/history/HistoryTokenTests.java | 452 ++++++++---------- .../client/presenter/AppPresenterTest.java | 80 ++-- .../ChangeReferenceLangPresenterTest.java | 12 +- .../client/presenter/ComparingPairTest.java | 27 +- .../DocumentListOptionsPresenterTest.java | 25 +- .../presenter/DocumentListPresenterTest.java | 170 +++---- .../presenter/EditorKeyShortcutsTest.java | 40 +- .../presenter/EditorOptionsPresenterTest.java | 39 +- .../ForceReviewCommentPresenterTest.java | 12 +- .../GlossaryDetailsPresenterTest.java | 7 +- .../presenter/GlossaryPresenterTest.java | 32 +- .../presenter/KeyShortcutPresenterTest.java | 43 +- .../presenter/OptionsPresenterTest.java | 15 +- .../presenter/PathDocumentFilterTest.java | 37 +- .../presenter/SearchResultsPresenterTest.java | 65 ++- .../presenter/SideMenuPresenterTest.java | 16 +- .../SourceContentsPresenterTest.java | 24 +- .../TargetContentsPresenterTest.java | 64 ++- .../presenter/TransFilterPresenterTest.java | 85 ++-- .../TransMemoryDetailsPresenterTest.java | 8 +- .../presenter/TransMemoryPresenterTest.java | 27 +- .../TransUnitNavigationPresenterTest.java | 15 +- .../presenter/TransUnitReplaceInfoTest.java | 52 +- .../TransUnitsTablePresenterTest.java | 22 +- .../TranslationHistoryPresenterTest.java | 25 +- .../presenter/TranslationPresenterTest.java | 41 +- .../presenter/UserConfigHolderTest.java | 35 +- .../WorkspaceUsersPresenterTest.java | 28 +- .../service/DistinctColorListImplTest.java | 24 +- .../GetTransUnitActionContextTest.java | 37 +- .../HistoryEventHandlerServiceTest.java | 8 +- .../ModalNavigationStateHolderTest.java | 87 ++-- .../NavigationServiceIntegrationTest.java | 120 +++-- .../service/NavigationServiceUnitTest.java | 78 ++- .../client/service/SaveEventQueueTest.java | 69 ++- .../service/SinglePageDataModelImplTest.java | 46 +- .../service/TransUnitSaveServiceTest.java | 65 ++- .../TranslatorInteractionServiceTest.java | 19 +- .../service/UserOptionsServiceTest.java | 105 ++-- .../service/UserSessionServiceTest.java | 16 +- .../client/service/ValidationServiceTest.java | 8 +- .../server/TranslationWorkspaceImplTest.java | 36 +- .../TranslationWorkspaceManagerImplTest.java | 47 +- .../rpc/ActivateWorkspaceHandlerTest.java | 27 +- .../rpc/AddReviewCommentHandlerTest.java | 7 +- .../rpc/GetDocumentListHandlerTest.java | 14 +- .../rpc/GetGlossaryDetailsHandlerTest.java | 12 +- .../server/rpc/GetGlossaryHandlerJpaTest.java | 24 +- .../GetProjectTransUnitListsHandlerTest.java | 40 +- .../rpc/GetTargetForLocaleHandlerTest.java | 9 +- .../rpc/GetTransMemoryDetailsHandlerTest.java | 5 +- .../server/rpc/GetTransMemoryHandlerTest.java | 16 +- .../rpc/GetTransUnitListHandlerTest.java | 55 ++- .../rpc/GetTranslationHistoryHandlerTest.java | 59 +-- .../rpc/GetTranslatorListHandlerTest.java | 13 +- .../server/rpc/LoadOptionsHandlerTest.java | 25 +- .../rpc/PreviewReplaceTextHandlerTest.java | 13 +- .../rpc/PublishWorkspaceChatHandlerTest.java | 11 +- .../server/rpc/RemoteLoggingHandlerTest.java | 5 +- .../server/rpc/ReplaceTextHandlerTest.java | 12 +- .../RevertTransUnitUpdatesHandlerTest.java | 9 +- .../server/rpc/SaveOptionsHandlerTest.java | 16 +- .../server/rpc/TransUnitEditHandlerTest.java | 12 +- .../util/StringNotEmptyPredicateTest.java | 11 +- .../validation/HtmlXmlTagValidationTests.java | 81 ++-- .../JavaVariablesValidationTest.java | 79 ++- .../NewlineLeadTrailValidationTests.java | 70 +-- .../PrintfVariablesValidationTest.java | 69 ++- .../PrintfXSIExtensionValidationTest.java | 64 ++- .../shared/validation/TabValidationTest.java | 28 +- .../validation/XMLEntityValidationTests.java | 37 +- .../org/zanata/xml/StreamSerializerTest.java | 13 +- 155 files changed, 2839 insertions(+), 3515 deletions(-) delete mode 100644 server/zanata-war/src/test/java/org/zanata/test/LambdaMatcher.java diff --git a/server/functional-test/pom.xml b/server/functional-test/pom.xml index 92679a5b9e..3ab2629fff 100644 --- a/server/functional-test/pom.xml +++ b/server/functional-test/pom.xml @@ -350,17 +350,6 @@ test - - org.hamcrest - hamcrest-core - compile - - - org.hamcrest - hamcrest-library - compile - - org.jetbrains.kotlin kotlin-stdlib diff --git a/server/functional-test/src/test/java/org/zanata/feature/glossary/GlossaryAdminTest.java b/server/functional-test/src/test/java/org/zanata/feature/glossary/GlossaryAdminTest.java index 225f250d4d..64b46aa5e5 100644 --- a/server/functional-test/src/test/java/org/zanata/feature/glossary/GlossaryAdminTest.java +++ b/server/functional-test/src/test/java/org/zanata/feature/glossary/GlossaryAdminTest.java @@ -20,7 +20,6 @@ */ package org.zanata.feature.glossary; -import org.hamcrest.Matchers; import org.junit.Test; import org.junit.experimental.categories.Category; import org.zanata.feature.Trace; @@ -29,7 +28,8 @@ import org.zanata.workflow.ClientWorkFlow; import java.io.File; import java.util.List; -import static org.hamcrest.MatcherAssert.assertThat; + +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.util.MavenHome.mvn; /** @@ -59,6 +59,6 @@ public void testGlossaryView() { List result = clientWorkFlow.callWithTimeout(projectRootPath, mvn() + " -e -U --batch-mode zanata:glossary-push -Dglossary.lang=hi -Dzanata.file=compendium.csv -Dzanata.userConfig=" + userConfigPath); - assertThat(clientWorkFlow.isPushSuccessful(result), Matchers.is(true)); + assertThat(clientWorkFlow.isPushSuccessful(result)).isTrue(); } } diff --git a/server/functional-test/src/test/java/org/zanata/feature/rest/CopyTransTest.java b/server/functional-test/src/test/java/org/zanata/feature/rest/CopyTransTest.java index 71de407217..e4eb69fdb9 100644 --- a/server/functional-test/src/test/java/org/zanata/feature/rest/CopyTransTest.java +++ b/server/functional-test/src/test/java/org/zanata/feature/rest/CopyTransTest.java @@ -20,7 +20,6 @@ */ package org.zanata.feature.rest; -import org.hamcrest.Matchers; import org.junit.Ignore; import org.junit.Test; import org.zanata.common.LocaleId; @@ -28,7 +27,6 @@ import org.zanata.rest.dto.resource.TranslationsResource; import org.zanata.util.ZanataRestCaller; -import static org.hamcrest.MatcherAssert.assertThat; import static org.zanata.util.ZanataRestCaller.*; /** @@ -66,8 +64,6 @@ public void testPushTranslationAndCopyTrans() { restCaller.asyncPushTarget(projectSlug, iterationSlug, docId, new LocaleId("pl"), transResource, "import", false); - assertThat(true, Matchers.is(true)); - // create another version restCaller.createProjectAndVersion(projectSlug, "2", projectType); restCaller.asyncPushSource(projectSlug, "2", sourceResource, false); @@ -110,8 +106,6 @@ void testPushTranslationRepeatedly() { localeId, transResource, "auto", false); restCaller.runCopyTrans(projectSlug, iterationSlug, docId); - assertThat(true, Matchers.is(true)); - // create some obsolete text flows Resource updatedSource = buildSourceResource(docId); TranslationsResource updatedTransResource = buildTranslationResource(); diff --git a/server/functional-test/src/test/java/org/zanata/feature/versionGroup/VersionGroupUrlTest.java b/server/functional-test/src/test/java/org/zanata/feature/versionGroup/VersionGroupUrlTest.java index d9e61bd81d..629f8aad94 100644 --- a/server/functional-test/src/test/java/org/zanata/feature/versionGroup/VersionGroupUrlTest.java +++ b/server/functional-test/src/test/java/org/zanata/feature/versionGroup/VersionGroupUrlTest.java @@ -20,7 +20,6 @@ */ package org.zanata.feature.versionGroup; -import org.assertj.core.api.Assertions; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -31,9 +30,7 @@ import org.zanata.workflow.BasicWorkFlow; import org.zanata.workflow.LoginWorkFlow; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; /** * Tests relating to custom urls handled in the page. @@ -53,7 +50,7 @@ public class VersionGroupUrlTest extends ZanataTestCase { @Before public void before() { - Assertions.assertThat( + assertThat( new LoginWorkFlow().signIn("admin", "admin").loggedInAs()) .isEqualTo("admin") .as("Admin is logged in"); @@ -66,7 +63,7 @@ public void testUrlChangeUpdatesActiveElements() { } private void testBasicGroupUrl(VersionGroupPage versionGroupPage) { - assertThat(versionGroupPage.isLanguagesTabActive(), is(true)); + assertThat(versionGroupPage.isLanguagesTabActive()).isTrue(); } @Test(timeout = ZanataTestCase.MAX_SHORT_TEST_DURATION) @@ -81,26 +78,26 @@ public void testTabClicksChangeUrl() { private void testLanguageTabClick(VersionGroupPage versionGroupPage) { versionGroupPage.clickLanguagesTab(); - assertThat(versionGroupPage.getUrl(), - containsString("/version-group/view/test-group/languages")); + assertThat(versionGroupPage.getUrl()) + .contains("/version-group/view/test-group/languages"); } private void testProjectTabClick(VersionGroupPage versionGroupPage) { versionGroupPage.clickProjectsTab(); - assertThat(versionGroupPage.getUrl(), - containsString("/version-group/view/test-group/projects")); + assertThat(versionGroupPage.getUrl()). + contains("/version-group/view/test-group/projects"); } private void testMaintainersTabClick(VersionGroupPage versionGroupPage) { versionGroupPage.clickMaintainersTab(); - assertThat(versionGroupPage.getUrl(), - containsString("/version-group/view/test-group/maintainers")); + assertThat(versionGroupPage.getUrl()). + contains("/version-group/view/test-group/maintainers"); } private void testSettingsTabClick(VersionGroupPage versionGroupPage) { versionGroupPage.clickSettingsTab(); - assertThat(versionGroupPage.getUrl(), - containsString("/version-group/view/test-group/settings")); + assertThat(versionGroupPage.getUrl()). + contains("/version-group/view/test-group/settings"); } private VersionGroupPage createVersionGroup() { diff --git a/server/zanata-model/pom.xml b/server/zanata-model/pom.xml index f3416fb96a..2ab790f93f 100644 --- a/server/zanata-model/pom.xml +++ b/server/zanata-model/pom.xml @@ -101,15 +101,6 @@ jaxrs-api - - - org.hamcrest - hamcrest-core - - - org.hamcrest - hamcrest-library - javax.xml.stream stax-api diff --git a/server/zanata-model/src/test/java/org/zanata/model/HTextFlowTest.java b/server/zanata-model/src/test/java/org/zanata/model/HTextFlowTest.java index d1debcc95a..b9b7d554a8 100644 --- a/server/zanata-model/src/test/java/org/zanata/model/HTextFlowTest.java +++ b/server/zanata-model/src/test/java/org/zanata/model/HTextFlowTest.java @@ -21,12 +21,10 @@ package org.zanata.model; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; - -import org.hamcrest.Matchers; import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; + /** * @author Patrick Huang pahuang@redhat.com @@ -37,20 +35,20 @@ public void testSetContents() throws Exception { HTextFlow textFlow = new HTextFlow(); textFlow.setContents("a", "b"); - assertThat(textFlow.getContents(), contains("a", "b")); + assertThat(textFlow.getContents()).contains("a", "b"); textFlow.setContents("a"); - assertThat(textFlow.getContents(), contains("a")); + assertThat(textFlow.getContents()).contains("a"); // check that content1 is nulled out (after having been non-null // earlier) - assertThat(textFlow.getContent1(), Matchers.nullValue()); + assertThat(textFlow.getContent1()).isNull(); // set original value textFlow.setContents("a", "b"); - assertThat(textFlow.getContents(), contains("a", "b")); + assertThat(textFlow.getContents()).contains("a", "b"); // set same value textFlow.setContents("a", "b"); - assertThat(textFlow.getContents(), contains("a", "b")); + assertThat(textFlow.getContents()).contains("a", "b"); } } diff --git a/server/zanata-model/src/test/java/org/zanata/model/SlugEntityBaseTest.java b/server/zanata-model/src/test/java/org/zanata/model/SlugEntityBaseTest.java index da971b7a11..46a2a945ce 100644 --- a/server/zanata-model/src/test/java/org/zanata/model/SlugEntityBaseTest.java +++ b/server/zanata-model/src/test/java/org/zanata/model/SlugEntityBaseTest.java @@ -20,14 +20,11 @@ */ package org.zanata.model; -import org.assertj.core.api.Assertions; import org.junit.Test; import java.util.Date; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalTo; +import static org.assertj.core.api.Assertions.assertThat; /** * @author Patrick Huang @@ -92,23 +89,23 @@ public void toStringAndEqualsTest() { entity.setVersionNum(2); entity.setCreationDate(now); entity.setLastChanged(now); - assertThat(entity.toString(), - containsString("[id=1,versionNum=2], slug=abc)")); + assertThat(entity.toString()). + contains("[id=1,versionNum=2], slug=abc)"); SlugEntityBase other = new SlugClass("abc"); other.setCreationDate(now); other.setLastChanged(now); - assertThat(entity.equals(other), equalTo(false)); + assertThat(entity.equals(other)).isFalse(); other.setId(entity.getId()); other.setVersionNum(entity.getVersionNum()); - assertThat(entity, equalTo(other)); - assertThat(entity.hashCode(), equalTo(other.hashCode())); + assertThat(entity).isEqualTo(other); + assertThat(entity.hashCode()).isEqualTo(other.hashCode()); } @Test public void changeToDeletedSlug() { SlugEntityBase slugEntityBase = new SlugClass("abc"); String newSlug = slugEntityBase.changeToDeletedSlug(); - Assertions.assertThat(newSlug).isEqualTo("abc" + DELETED_SUFFIX); + assertThat(newSlug).isEqualTo("abc" + DELETED_SUFFIX); } @Test @@ -117,7 +114,7 @@ public void canChangeToDeletedSlugWithSuffixInPlaceIfOldSlugIsTooLong() { SlugEntityBase slugEntityBase = new SlugClass("abcdefghijklmnopqrstuvwxyz1234567890"); String newSlug = slugEntityBase.changeToDeletedSlug(); - Assertions.assertThat(newSlug) + assertThat(newSlug) .isEqualTo("abcdefghijklmnopqrstuvwxyz1" + DELETED_SUFFIX) .hasSize(40); } diff --git a/server/zanata-model/src/test/java/org/zanata/model/StatusCountTest.java b/server/zanata-model/src/test/java/org/zanata/model/StatusCountTest.java index 3bd8fe9788..1a3c4c19dc 100644 --- a/server/zanata-model/src/test/java/org/zanata/model/StatusCountTest.java +++ b/server/zanata-model/src/test/java/org/zanata/model/StatusCountTest.java @@ -23,8 +23,7 @@ import org.junit.Test; import org.zanata.common.ContentState; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.assertj.core.api.Assertions.assertThat; /** * @author Patrick Huang {\\b Special} text"), - equalTo("Special text")); + removeFormattingMarkup( + "{\\b Special} text")) + .isEqualTo("Special text"); assertThat( - removeFormattingMarkup("{\\cf7 Special} text"), - equalTo("Special text")); + removeFormattingMarkup("{\\cf7 Special} text")). + isEqualTo("Special text"); assertThat( - removeFormattingMarkup("<B>Special</B> text"), - equalTo("Special text")); + removeFormattingMarkup("<B>Special</B> text")). + isEqualTo("Special text"); assertThat( removeFormattingMarkup("The <i><b>" - + "big</b> black</i> cat."), - equalTo("The big black cat.")); + + "big</b> black</i> cat.")). + isEqualTo("The big black cat."); assertThat( removeFormattingMarkup("The icon <img src=\"testNode.gif\"/>represents " - + "a conditional node."), - equalTo("The icon represents a conditional node.")); + + "a conditional node.")). + isEqualTo("The icon represents a conditional node."); } @Test @@ -39,8 +39,7 @@ public void extractPlainTextContentWithNestedFootnote() throws Exception { + "\\s15\\widctlpar \\f4\\fs20" + "{\\cs16\\super \\chftn } An elephant is a very " + "large animal.}} are big. "; - assertThat( - removeFormattingMarkup(segXML), - equalTo("Elephants are big.")); + assertThat(removeFormattingMarkup(segXML)) + .isEqualTo("Elephants are big."); } } diff --git a/server/zanata-war/pom.xml b/server/zanata-war/pom.xml index a6707deb12..3fd07b8369 100644 --- a/server/zanata-war/pom.xml +++ b/server/zanata-war/pom.xml @@ -1402,18 +1402,6 @@ provided - - org.hamcrest - hamcrest-core - test - - - - org.hamcrest - hamcrest-library - test - - javax.activation activation diff --git a/server/zanata-war/src/test/java/org/zanata/arquillian/DeploymentsSanityTest.java b/server/zanata-war/src/test/java/org/zanata/arquillian/DeploymentsSanityTest.java index 0083d1a177..b06de384b9 100644 --- a/server/zanata-war/src/test/java/org/zanata/arquillian/DeploymentsSanityTest.java +++ b/server/zanata-war/src/test/java/org/zanata/arquillian/DeploymentsSanityTest.java @@ -21,8 +21,6 @@ package org.zanata.arquillian; import static org.assertj.core.api.Assertions.assertThat; -import static org.hamcrest.Matchers.anyOf; -import static org.hamcrest.Matchers.containsString; import java.io.File; import java.util.Arrays; diff --git a/server/zanata-war/src/test/java/org/zanata/config/DatabaseBackedConfigTest.java b/server/zanata-war/src/test/java/org/zanata/config/DatabaseBackedConfigTest.java index 18002839b5..d1769bfce9 100644 --- a/server/zanata-war/src/test/java/org/zanata/config/DatabaseBackedConfigTest.java +++ b/server/zanata-war/src/test/java/org/zanata/config/DatabaseBackedConfigTest.java @@ -31,9 +31,7 @@ import javax.enterprise.inject.Produces; import javax.inject.Inject; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.nullValue; +import static org.assertj.core.api.Assertions.assertThat; /** * Tests for the Database backed config store. @@ -66,117 +64,117 @@ protected void prepareDBUnitOperations() { @Test @InRequestScope public void getHomeContent() { - assertThat(databaseBackedConfig.getHomeContent(), - equalTo("This is the home content")); + assertThat(databaseBackedConfig.getHomeContent()) + .isEqualTo("This is the home content"); } @Test @InRequestScope public void getAdminEmailAddress() { - assertThat(databaseBackedConfig.getAdminEmailAddress(), - equalTo("lcroft@redhat.com")); + assertThat(databaseBackedConfig.getAdminEmailAddress()) + .isEqualTo("lcroft@redhat.com"); } @Test @InRequestScope public void getAdminFromAddress() { - assertThat(databaseBackedConfig.getFromEmailAddress(), - equalTo("aloy@redhat.com")); + assertThat(databaseBackedConfig.getFromEmailAddress()) + .isEqualTo("aloy@redhat.com"); } @Test @InRequestScope public void getDomain() { - assertThat(databaseBackedConfig.getDomain(), equalTo("redhat.com")); + assertThat(databaseBackedConfig.getDomain()).isEqualTo("redhat.com"); } @Test @InRequestScope public void getShouldLogEvents() { - assertThat(databaseBackedConfig.getShouldLogEvents(), equalTo("true")); + assertThat(databaseBackedConfig.getShouldLogEvents()).isEqualTo("true"); } @Test @InRequestScope public void getEmailLogLevel() { - assertThat(databaseBackedConfig.getEmailLogLevel(), equalTo("INFO")); + assertThat(databaseBackedConfig.getEmailLogLevel()).isEqualTo("INFO"); } @Test @InRequestScope public void getHelpUrl() { - assertThat(databaseBackedConfig.getHelpUrl(), equalTo("http://zanata.org/help")); + assertThat(databaseBackedConfig.getHelpUrl()).isEqualTo("http://zanata.org/help"); } @Test @InRequestScope public void getServerHost() { - assertThat(databaseBackedConfig.getServerHost(), equalTo("http://localhost:8080")); + assertThat(databaseBackedConfig.getServerHost()).isEqualTo("http://localhost:8080"); } @Test @InRequestScope public void getLogEventsDestinationEmailAddress() { - assertThat(databaseBackedConfig.getLogEventsDestinationEmailAddress(), - equalTo("tihocan@redhat.com")); + assertThat(databaseBackedConfig.getLogEventsDestinationEmailAddress()) + .isEqualTo("tihocan@redhat.com"); } @Test @InRequestScope public void getRegistrationUrl() { - assertThat(databaseBackedConfig.getRegistrationUrl(), - equalTo("http://zanata.org/register")); + assertThat(databaseBackedConfig.getRegistrationUrl()) + .isEqualTo("http://zanata.org/register"); } @Test @InRequestScope public void getPiwikUrl() { - assertThat(databaseBackedConfig.getPiwikUrl(), - equalTo("http://zanata.org/piwik")); + assertThat(databaseBackedConfig.getPiwikUrl()) + .isEqualTo("http://zanata.org/piwik"); } @Test @InRequestScope public void getPiwikSiteId() { - assertThat(databaseBackedConfig.getPiwikSiteId(), equalTo("47")); + assertThat(databaseBackedConfig.getPiwikSiteId()).isEqualTo("47"); } @Test @InRequestScope public void getTermsOfUseUrl() { - assertThat(databaseBackedConfig.getTermsOfUseUrl(), - equalTo("http://zanata.org/terms")); + assertThat(databaseBackedConfig.getTermsOfUseUrl()) + .isEqualTo("http://zanata.org/terms"); } @Test @InRequestScope public void getMaxConcurrentRequestsPerApiKey() { - assertThat(databaseBackedConfig.getMaxConcurrentRequestsPerApiKey(), - equalTo("9")); + assertThat(databaseBackedConfig.getMaxConcurrentRequestsPerApiKey()) + .isEqualTo("9"); } @Test @InRequestScope public void getMaxActiveRequestsPerApiKey() { - assertThat(databaseBackedConfig.getMaxActiveRequestsPerApiKey(), equalTo("8")); + assertThat(databaseBackedConfig.getMaxActiveRequestsPerApiKey()).isEqualTo("8"); } @Test @InRequestScope public void getMaxFilesPerUpload() { - assertThat(databaseBackedConfig.getMaxFilesPerUpload(), equalTo("7")); + assertThat(databaseBackedConfig.getMaxFilesPerUpload()).isEqualTo("7"); } @Test @InRequestScope public void isDisplayUserEmail() { - assertThat(databaseBackedConfig.isDisplayUserEmail(), equalTo(true)); + assertThat(databaseBackedConfig.isDisplayUserEmail()).isTrue(); } @Test @InRequestScope public void getPermittedEmailDomains() { - assertThat(databaseBackedConfig.getPermittedEmailDomains(), equalTo("horizon.com")); + assertThat(databaseBackedConfig.getPermittedEmailDomains()).isEqualTo("horizon.com"); } @Test @@ -184,19 +182,19 @@ public void getPermittedEmailDomains() { public void getNonExistentValue() throws Exception { // Prematurely clean out data, assert missing value is null cleanDataAfterTest(); - assertThat(databaseBackedConfig.getAdminEmailAddress(), nullValue()); + assertThat(databaseBackedConfig.getAdminEmailAddress()).isNull(); } @Test @InRequestScope public void autoAcceptTranslatorIsFalseIfNull() { - assertThat(databaseBackedConfig.isAutoAcceptTranslators(), equalTo(false)); + assertThat(databaseBackedConfig.isAutoAcceptTranslators()).isFalse(); } @Test @InRequestScope public void getGravatarRating() { - assertThat(databaseBackedConfig.getMaxGravatarRating(), equalTo("R")); + assertThat(databaseBackedConfig.getMaxGravatarRating()).isEqualTo("R"); } @Test @@ -204,6 +202,6 @@ public void getGravatarRating() { public void gravatarRatingDefaultsToGeneral() { // Prematurely clean out data, assert missing value is null cleanDataAfterTest(); - assertThat(databaseBackedConfig.getMaxGravatarRating(), equalTo("G")); + assertThat(databaseBackedConfig.getMaxGravatarRating()).isEqualTo("G"); } } diff --git a/server/zanata-war/src/test/java/org/zanata/dao/DocumentDAOTest.java b/server/zanata-war/src/test/java/org/zanata/dao/DocumentDAOTest.java index 6ffb76d1bc..9f370771e9 100644 --- a/server/zanata-war/src/test/java/org/zanata/dao/DocumentDAOTest.java +++ b/server/zanata-war/src/test/java/org/zanata/dao/DocumentDAOTest.java @@ -20,10 +20,6 @@ */ package org.zanata.dao; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.not; - import javax.annotation.Nullable; import org.dbunit.operation.DatabaseOperation; @@ -39,6 +35,8 @@ import com.google.common.base.Function; +import static org.assertj.core.api.Assertions.assertThat; + /** * @author Carlos Munoz camunoz@redhat.com @@ -95,9 +93,8 @@ public void repeatableDocumentStateHash() throws Exception { String unchangedHash = documentDAO.getTranslatedDocumentStateHash(PROJECT_SLUG, ITERATION_SLUG, DOC_ID, as); - assertThat( - "Translated Document state hash function not repeatable", - unchangedHash, equalTo(docHash)); + assertThat(unchangedHash).isEqualTo(docHash) + .as("Translated Document state hash function not repeatable"); } } @@ -120,13 +117,11 @@ private void testHashChange(Function mutator, documentDAO.getTranslatedDocumentStateHash(PROJECT_SLUG, ITERATION_SLUG, DOC_ID, as); if (expectHashChange) { - assertThat( - "Translated document hash must change when something is changed", - changedDocHash, not(equalTo(docHash))); + assertThat(changedDocHash).isNotEqualTo(docHash) + .as("Translated document hash must change when something is changed"); } else { - assertThat( - "Translated document hash must not change when nothing is changed", - changedDocHash, equalTo(docHash)); + assertThat(changedDocHash).isEqualTo(docHash) + .as("Translated document hash must not change when nothing is changed"); } } diff --git a/server/zanata-war/src/test/java/org/zanata/dao/GlossaryDAOTest.java b/server/zanata-war/src/test/java/org/zanata/dao/GlossaryDAOTest.java index 9504b59d16..e6e5b2b127 100644 --- a/server/zanata-war/src/test/java/org/zanata/dao/GlossaryDAOTest.java +++ b/server/zanata-war/src/test/java/org/zanata/dao/GlossaryDAOTest.java @@ -1,10 +1,7 @@ package org.zanata.dao; -import java.util.Calendar; -import java.util.Date; import java.util.List; import com.google.common.collect.Lists; -import com.google.inject.matcher.Matchers; import org.dbunit.operation.DatabaseOperation; import org.hibernate.Session; @@ -20,10 +17,8 @@ import org.zanata.security.ZanataIdentity; import org.zanata.util.DateUtil; import org.zanata.util.GlossaryUtil; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.not; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; + +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -58,7 +53,7 @@ public void testGetEntryById() { log.debug("testGetEntryById"); HGlossaryEntry entry = dao.getEntryById(1L); Assert.assertNotNull(entry); - assertThat(entry.getGlossaryTerms().size(), is(3)); + assertThat(entry.getGlossaryTerms().size()).isEqualTo(3); } @Test @@ -66,7 +61,7 @@ public void testGetTermByLocaleId() { log.debug("testGetTermByLocaleId"); List entryList = dao.getEntriesByLocale(LocaleId.EN_US, 0, 1, "", null, GlossaryUtil.GLOBAL_QUALIFIED_NAME); - assertThat(entryList.size(), is(1)); + assertThat(entryList.size()).isEqualTo(1); } @Test @@ -78,7 +73,7 @@ public void testGetTermByLocaleId2() { GlossarySortField.getByField(GlossarySortField.DESCRIPTION)); List entryList = dao.getEntriesByLocale(LocaleId.EN_US, 0, 1, "", sortFields, GlossaryUtil.GLOBAL_QUALIFIED_NAME); - assertThat(entryList.size(), is(1)); + assertThat(entryList.size()).isEqualTo(1); } @Test @@ -89,7 +84,7 @@ public void testGetTermByLocaleId3() { List sortFields = Lists.newArrayList(POS); List entryList = dao.getEntriesByLocale(LocaleId.EN_US, 0, 1, "", sortFields, GlossaryUtil.GLOBAL_QUALIFIED_NAME); - assertThat(entryList.size(), is(1)); + assertThat(entryList.size()).isEqualTo(1); } @Test @@ -106,7 +101,7 @@ public void testGetTermEntryAndLocale() { public void testGetTermByGlossaryEntryId() { log.debug("testGetTermByGlossaryEntry"); List termList = dao.getTermByEntryId(1L); - assertThat(termList.size(), is(3)); + assertThat(termList.size()).isEqualTo(3); } @Test @@ -115,7 +110,7 @@ public void testGetEntryBySrcContentLocale() { HGlossaryEntry entry = dao.getEntryByContentHash("hash", GlossaryUtil.GLOBAL_QUALIFIED_NAME); Assert.assertNotNull(entry); - assertThat(entry.getSrcLocale().getLocaleId(), is(LocaleId.EN_US)); + assertThat(entry.getSrcLocale().getLocaleId()).isEqualTo(LocaleId.EN_US); } @Test @@ -129,7 +124,7 @@ public void testGetEntriesByLocale() { sortFields.add(pos); List result = dao.getEntriesByLocale(LocaleId.EN_US, 0, 100, "", sortFields, GlossaryUtil.GLOBAL_QUALIFIED_NAME); - assertThat(result.get(0).getPos(), is("pos 1")); + assertThat(result.get(0).getPos()).isEqualTo("pos 1"); } @Test @@ -144,6 +139,6 @@ public void testSrcTermDateUpdatedWhenEntryModified() { String srcDate = DateUtil.formatShortDate(srcTerm.getLastChanged()); String entryDate = DateUtil.formatShortDate(entry.getLastChanged()); - assertThat(srcDate, is(entryDate)); + assertThat(srcDate).isEqualTo(entryDate); } } diff --git a/server/zanata-war/src/test/java/org/zanata/dao/LocaleDAOTest.java b/server/zanata-war/src/test/java/org/zanata/dao/LocaleDAOTest.java index abb1247b74..ccd2cc8bb0 100644 --- a/server/zanata-war/src/test/java/org/zanata/dao/LocaleDAOTest.java +++ b/server/zanata-war/src/test/java/org/zanata/dao/LocaleDAOTest.java @@ -3,15 +3,9 @@ import java.util.List; import static java.util.Collections.emptyList; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.IsNot.not; -import static org.hamcrest.core.IsNull.nullValue; +import static org.assertj.core.api.Assertions.assertThat; import org.dbunit.operation.DatabaseOperation; -import org.hamcrest.CoreMatchers; -import org.hamcrest.Matchers; import org.hibernate.Session; import org.junit.Before; import org.junit.BeforeClass; @@ -58,9 +52,9 @@ public void createLocale() { dao.flush(); dao.clear(); HLocale loadedLocale = dao.findById(id); - assertThat(loadedLocale.getLocaleId().getId(), is("en-ENABLED")); - assertThat("still active", loadedLocale.isActive()); - assertThat("still enabled by default", loadedLocale.isEnabledByDefault()); + assertThat(loadedLocale.getLocaleId().getId()).isEqualTo("en-ENABLED"); + assertThat(loadedLocale.isActive()).isTrue().as("still active"); + assertThat(loadedLocale.isEnabledByDefault()).isTrue().as("still enabled by default"); } @Test @@ -68,23 +62,23 @@ public void findByLocaleReturnsCorrectLocale() { String id = "de"; HLocale hl = dao.findByLocaleId(new LocaleId(id)); assert hl != null; - assertThat(hl.getLocaleId().getId(), is(id)); + assertThat(hl.getLocaleId().getId()).isEqualTo(id); } @Test public void findByLocaleIdReturnsNullForNonexistentLocale() { String id = "nonexistentLocaleId"; HLocale hl = dao.findByLocaleId(new LocaleId(id)); - assertThat(hl, is(nullValue())); + assertThat(hl).isNull(); } @Test public void testFind() { List results = dao.find(0, 1, "a", emptyList(), true); - assertThat(results.size(), is(1)); + assertThat(results.size()).isEqualTo(1); results = dao.find(0, 10, "a", emptyList(), true); - assertThat(results.size(), is(4)); + assertThat(results.size()).isEqualTo(4); } @Test @@ -92,14 +86,14 @@ public void testFindWithSort() { List sortFields1 = Lists.newArrayList( LocaleSortField.getByField(LocaleSortField.LOCALE)); List results1 = dao.find(0, 10, "e", sortFields1, true); // 5 results - assertThat(results1.get(0).getLocaleId(), is(LocaleId.DE)); + assertThat(results1.get(0).getLocaleId()).isEqualTo(LocaleId.DE); List sortFields2 = Lists.newArrayList( LocaleSortField.getByField(LocaleSortField.MEMBER)); List results2 = dao.find(0, 10, "e", sortFields2, true); // 5 results //first result of results2 can be ES or TE - assertThat(results1.get(0), not(Matchers.equalTo(results2.get(0)))); + assertThat(results1.get(0)).isNotEqualTo(results2.get(0)); } } diff --git a/server/zanata-war/src/test/java/org/zanata/dao/LocaleMemberDAOITCase.java b/server/zanata-war/src/test/java/org/zanata/dao/LocaleMemberDAOITCase.java index 0447b5c5ff..5dd7b399da 100644 --- a/server/zanata-war/src/test/java/org/zanata/dao/LocaleMemberDAOITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/dao/LocaleMemberDAOITCase.java @@ -1,8 +1,5 @@ package org.zanata.dao; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.notNullValue; - import javax.persistence.EntityManager; import org.dbunit.operation.DatabaseOperation; @@ -15,6 +12,8 @@ import org.zanata.provider.DBUnitProvider.DataSetOperation; import org.zanata.security.ZanataIdentity; +import static org.assertj.core.api.Assertions.assertThat; + public class LocaleMemberDAOITCase extends ArquillianTest { @Inject @@ -45,8 +44,8 @@ public void failSaveWhenNotLoggedIn() throws Exception { HLocale locale = entityManager.find(HLocale.class, new Long(1)); HAccount account = entityManager.find(HAccount.class, new Long(1)); - assertThat(locale, notNullValue()); - assertThat(account, notNullValue()); + assertThat(locale).isNotNull(); + assertThat(account).isNotNull(); HLocaleMember newMember = new HLocaleMember(account.getPerson(), locale, true, true, true); @@ -64,8 +63,8 @@ public void testSave() throws Exception { HLocale locale = entityManager.find(HLocale.class, new Long(1)); HAccount account = entityManager.find(HAccount.class, new Long(1)); - assertThat(locale, notNullValue()); - assertThat(account, notNullValue()); + assertThat(locale).isNotNull(); + assertThat(account).isNotNull(); HLocaleMember newMember = new HLocaleMember(account.getPerson(), locale, true, true, true); diff --git a/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOTest.java b/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOTest.java index dad28ef87c..13e2fab2aa 100644 --- a/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOTest.java +++ b/server/zanata-war/src/test/java/org/zanata/dao/ProjectDAOTest.java @@ -1,21 +1,18 @@ package org.zanata.dao; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.MatcherAssert.assertThat; - import org.dbunit.operation.DatabaseOperation; import org.hibernate.Session; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import org.junit.runner.RunWith; import org.zanata.ZanataDbunitJpaTest; import org.zanata.model.HProject; import org.zanata.security.ZanataIdentity; import java.util.List; +import static org.assertj.core.api.Assertions.assertThat; + public class ProjectDAOTest extends ZanataDbunitJpaTest { private ProjectDAO dao; @@ -40,71 +37,71 @@ public void setup() { @Test public void getValidProjectBySlug() { HProject project = dao.getBySlug("sample-project"); - assertThat(project, notNullValue()); - assertThat(project.getName(), is("Sample Project")); + assertThat(project).isNotNull(); + assertThat(project.getName()).isEqualTo("Sample Project"); } @Test public void getValidProjectById() { HProject project = dao.findById(1l, false); - assertThat(project, notNullValue()); - assertThat(project.getName(), is("Sample Project")); + assertThat(project).isNotNull(); + assertThat(project.getName()).isEqualTo("Sample Project"); } @Test public void getActiveIterations() { - assertThat(dao.getActiveIterations("current-project").size(), is(1)); + assertThat(dao.getActiveIterations("current-project").size()).isEqualTo(1); } @Test public void getReadOnlyIterations() { - assertThat(dao.getReadOnlyIterations("current-project").size(), is(1)); + assertThat(dao.getReadOnlyIterations("current-project").size()).isEqualTo(1); } @Test public void getObsoleteIterations() { - assertThat(dao.getObsoleteIterations("current-project").size(), is(1)); + assertThat(dao.getObsoleteIterations("current-project").size()).isEqualTo(1); } @Test public void getFilterProjectSizeAll() { - assertThat(dao.getFilterProjectSize(false, false, false), is(4)); + assertThat(dao.getFilterProjectSize(false, false, false)).isEqualTo(4); } @Test public void getFilterProjectSizeOnlyActive() { - assertThat(dao.getFilterProjectSize(false, true, true), is(2)); + assertThat(dao.getFilterProjectSize(false, true, true)).isEqualTo(2); } @Test public void getFilterProjectSizeOnlyReadOnly() { - assertThat(dao.getFilterProjectSize(true, false, true), is(1)); + assertThat(dao.getFilterProjectSize(true, false, true)).isEqualTo(1); } @Test public void getFilterProjectSizeOnlyObsolete() { - assertThat(dao.getFilterProjectSize(true, true, false), is(1)); + assertThat(dao.getFilterProjectSize(true, true, false)).isEqualTo(1); } @Test public void getFilterProjectSizeOnlyActiveAndReadOnly() { - assertThat(dao.getFilterProjectSize(false, false, true), is(3)); + assertThat(dao.getFilterProjectSize(false, false, true)).isEqualTo(3); } @Test public void getFilterProjectSizeOnlyActiveAndObsolete() { - assertThat(dao.getFilterProjectSize(false, true, false), is(3)); + assertThat(dao.getFilterProjectSize(false, true, false)).isEqualTo(3); } @Test public void getFilterProjectSizeOnlyObsoleteAndReadOnly() { - assertThat(dao.getFilterProjectSize(true, false, false), is(2)); + assertThat(dao.getFilterProjectSize(true, false, false)).isEqualTo(2); } @Test public void getOffsetList() { List projects = dao.getOffsetList(-1, -1, false, false, false); - assertThat(projects.size(), is(4)); + assertThat(projects.size()).isEqualTo(4); } } diff --git a/server/zanata-war/src/test/java/org/zanata/dao/TextFlowDAOTest.java b/server/zanata-war/src/test/java/org/zanata/dao/TextFlowDAOTest.java index 2525938b07..65e29ac585 100644 --- a/server/zanata-war/src/test/java/org/zanata/dao/TextFlowDAOTest.java +++ b/server/zanata-war/src/test/java/org/zanata/dao/TextFlowDAOTest.java @@ -1,13 +1,9 @@ package org.zanata.dao; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; import java.util.List; import java.util.Map; import com.google.common.collect.Lists; -import org.assertj.core.api.Assertions; import org.dbunit.operation.DatabaseOperation; -import org.hamcrest.Matchers; import org.hibernate.Session; import org.junit.Before; import org.junit.Ignore; @@ -20,6 +16,8 @@ import org.zanata.webtrans.shared.search.FilterConstraints; import org.zanata.webtrans.shared.model.DocumentId; +import static org.assertj.core.api.Assertions.assertThat; + public class TextFlowDAOTest extends ZanataDbunitJpaTest { private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TextFlowDAOTest.class); @@ -88,11 +86,11 @@ public void canGetAllUntranslatedTextFlowForADocument() { .excludeFuzzy().excludeTranslated().build(); List result = dao.getTextFlowByDocumentIdWithConstraints( new DocumentId(1L, ""), deLocale, untranslated, 0, 10); - assertThat(result.size(), is(0)); + assertThat(result.size()).isEqualTo(0); HLocale frLocale = getEm().find(HLocale.class, 6L); result = dao.getTextFlowByDocumentIdWithConstraints( new DocumentId(1L, ""), frLocale, untranslated, 0, 10); - assertThat(result.size(), is(1)); + assertThat(result.size()).isEqualTo(1); } @Test @@ -102,7 +100,7 @@ public void canGetTextFlowWithNullTarget() { .excludeFuzzy().excludeTranslated().build(); List result = dao.getTextFlowByDocumentIdWithConstraints( new DocumentId(4L, ""), deLocale, untranslated, 0, 10); - assertThat(result, Matchers.hasSize(1)); + assertThat(result).hasSize(1); } @Test @@ -114,7 +112,7 @@ public void canGetTextFlowsByStatusNotNew() { documentId2, enUSLocale, FilterConstraints.builder().keepAll().excludeNew().build(), 0, 10); - assertThat(result, Matchers.hasSize(3)); + assertThat(result).hasSize(3); } @Test @@ -126,7 +124,7 @@ public void canGetTextFlowsByStatusNotFuzzy() { FilterConstraints.builder().keepAll().excludeFuzzy().build(); List result = dao.getTextFlowByDocumentIdWithConstraints( documentId, frLocale, notFuzzy, 0, 10); - assertThat(result, Matchers.hasSize(1)); + assertThat(result).hasSize(1); } @Test @@ -138,7 +136,7 @@ public void canGetTextFlowsByStatusNotTranslatedNotNew() { .keepAll().excludeTranslated().excludeNew().build(); List result = dao.getTextFlowByDocumentIdWithConstraints( documentId, esLocale, notNewOrTranslated, 0, 10); - assertThat(result, Matchers.hasSize(1)); + assertThat(result).hasSize(1); } @Test @@ -150,7 +148,7 @@ public void canGetTextFlowsByStatusNotFuzzyNotNew() { .excludeFuzzy().excludeNew().build(); List result = dao.getTextFlowByDocumentIdWithConstraints( documentId, deLocale, notNewOrFuzzy, 0, 10); - assertThat(result, Matchers.hasSize(1)); + assertThat(result).hasSize(1); } @Test @@ -162,7 +160,7 @@ public void canGetTextFlowsByStatusNotFuzzyNotTranslated() { .keepAll().excludeTranslated().excludeFuzzy().build(); List result = dao.getTextFlowByDocumentIdWithConstraints( documentId2, enUSLocale, notFuzzyOrTranslated, 0, 10); - assertThat(result, Matchers. empty()); + assertThat(result).isEmpty(); } @Ignore @@ -187,7 +185,7 @@ public void testGetTextFlowByDocumentIdWithConstraint() { FilterConstraints.builder().filterBy("mssg") .excludeTranslated().excludeFuzzy().build(), 0, 10); - assertThat(result, Matchers.hasSize(1)); + assertThat(result).hasSize(1); } @Test @@ -216,21 +214,21 @@ public void testGetTranslationsByMatchedContext() { new ProjectIterationDAO((Session) getEm().getDelegate()); HProjectIteration fromVersion = projectIterationDAO.getBySlug(projectSlug, fromVersionSlug); - Assertions.assertThat(fromVersion).isNotNull(); + assertThat(fromVersion).isNotNull(); HProjectIteration toVersion = projectIterationDAO.getBySlug(projectSlug, toVersionSlug); - Assertions.assertThat(toVersion).isNotNull(); + assertThat(toVersion).isNotNull(); List results = dao.getSourceByMatchedContext( fromVersion.getId(), toVersion.getId(), 0, 100); - Assertions.assertThat(results).isNotEmpty(); + assertThat(results).isNotEmpty(); for (HTextFlow[] result : results) { - Assertions.assertThat(result[0].getContentHash()) + assertThat(result[0].getContentHash()) .isEqualTo(result[1].getContentHash()); - Assertions.assertThat(result[0].getDocument().getDocId()) + assertThat(result[0].getDocument().getDocId()) .isEqualTo(result[1].getDocument().getDocId()); - Assertions.assertThat(result[0].getResId()) + assertThat(result[0].getResId()) .isEqualTo(result[1].getResId()); - Assertions.assertThat(result[0]).isNotEqualTo(result[1]); + assertThat(result[0]).isNotEqualTo(result[1]); } } } diff --git a/server/zanata-war/src/test/java/org/zanata/dao/TextFlowStreamingDAOTest.java b/server/zanata-war/src/test/java/org/zanata/dao/TextFlowStreamingDAOTest.java index 04c9d2e328..53ef9adcce 100644 --- a/server/zanata-war/src/test/java/org/zanata/dao/TextFlowStreamingDAOTest.java +++ b/server/zanata-war/src/test/java/org/zanata/dao/TextFlowStreamingDAOTest.java @@ -1,9 +1,6 @@ package org.zanata.dao; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.MatcherAssert.assertThat; import org.dbunit.operation.DatabaseOperation; -import org.hamcrest.Matchers; import org.hibernate.Session; import org.junit.Before; import org.junit.Test; @@ -14,6 +11,8 @@ import org.zanata.util.CloseableIterator; import com.google.common.collect.Iterators; +import static org.assertj.core.api.Assertions.assertThat; + public class TextFlowStreamingDAOTest extends ZanataDbunitJpaTest { private static final int TEXTFLOWS_IN_SAMPLE_PROJECT_10 = 5; @@ -49,8 +48,7 @@ public void setup() { public void findAllTextFlows() throws Exception { CloseableIterator iter = dao.findTextFlows(); try { - assertThat(Iterators.size(iter), - equalTo(TEXTFLOWS_IN_SAMPLE_PROJECT_10)); + assertThat(Iterators.size(iter)).isEqualTo(TEXTFLOWS_IN_SAMPLE_PROJECT_10); } finally { if (iter != null) { iter.close(); @@ -63,8 +61,8 @@ public void findTextFlowsForProject() throws Exception { HProject proj = projectDao.getBySlug("sample-project"); CloseableIterator iter = dao.findTextFlowsByProject(proj); try { - assertThat(Iterators.size(iter), - equalTo(TEXTFLOWS_IN_SAMPLE_PROJECT_10)); + assertThat(Iterators.size(iter)).isEqualTo( + TEXTFLOWS_IN_SAMPLE_PROJECT_10); } finally { if (iter != null) { iter.close(); @@ -77,7 +75,7 @@ public void findTextFlowsForEmptyProject() throws Exception { HProject proj = projectDao.getBySlug("retired-project"); CloseableIterator iter = dao.findTextFlowsByProject(proj); try { - assertThat(iter.hasNext(), Matchers.not(true)); + assertThat(iter.hasNext()).isFalse(); } finally { if (iter != null) { iter.close(); @@ -92,8 +90,7 @@ public void findTextFlowsForProjectIter() throws Exception { CloseableIterator iter = dao.findTextFlowsByProjectIteration(projIter); try { - assertThat(Iterators.size(iter), - equalTo(TEXTFLOWS_IN_SAMPLE_PROJECT_10)); + assertThat(Iterators.size(iter)).isEqualTo(TEXTFLOWS_IN_SAMPLE_PROJECT_10); } finally { if (iter != null) { iter.close(); @@ -108,7 +105,7 @@ public void findTextFlowsForEmptyProjectIteration() throws Exception { CloseableIterator iter = dao.findTextFlowsByProjectIteration(projIter); try { - assertThat(iter.hasNext(), Matchers.not(true)); + assertThat(iter.hasNext()).isFalse(); } finally { if (iter != null) { iter.close(); diff --git a/server/zanata-war/src/test/java/org/zanata/dao/TextFlowTargetReviewCommentsDAOJPATest.java b/server/zanata-war/src/test/java/org/zanata/dao/TextFlowTargetReviewCommentsDAOJPATest.java index 02fa751f1d..86ef8f891e 100644 --- a/server/zanata-war/src/test/java/org/zanata/dao/TextFlowTargetReviewCommentsDAOJPATest.java +++ b/server/zanata-war/src/test/java/org/zanata/dao/TextFlowTargetReviewCommentsDAOJPATest.java @@ -25,7 +25,6 @@ import java.util.List; import org.dbunit.operation.DatabaseOperation; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.zanata.ZanataDbunitJpaTest; @@ -35,7 +34,7 @@ import org.zanata.model.HTextFlowTargetReviewComment; import org.zanata.webtrans.shared.model.TransUnitId; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; /** * @author Patrick Huang userComments = target.getReviewComments(); - assertThat(userComments, Matchers.empty()); + assertThat(userComments).isEmpty(); target.addReviewComment("bad translation", person); getEm().persist(target); @@ -99,11 +98,10 @@ public void testTargetUserComment() { reviewCommentsDAO.getReviewComments(new TransUnitId(target .getTextFlow().getId()), target.getLocaleId()); - assertThat(result, Matchers.hasSize(1)); - assertThat(result.get(0).getCommenterName(), - Matchers.equalTo(person.getName())); - assertThat(result.get(0).getCreationDate(), - Matchers.lessThanOrEqualTo(new Date())); + assertThat(result).hasSize(1); + assertThat(result.get(0).getCommenterName()).isEqualTo(person.getName()); + assertThat(result.get(0).getCreationDate()) + .isBeforeOrEqualsTo(new Date()); } @Test @@ -126,7 +124,6 @@ public void testTargetUserCommentMadeOnPreviousTranslation() { reviewCommentsDAO.getReviewComments(new TransUnitId(target .getTextFlow().getId()), target.getLocaleId()); - assertThat(result.get(0).getTargetVersion(), - Matchers.equalTo(oldVersion)); + assertThat(result.get(0).getTargetVersion()).isEqualTo(oldVersion); } } diff --git a/server/zanata-war/src/test/java/org/zanata/dao/TransMemoryStreamingDAOTest.java b/server/zanata-war/src/test/java/org/zanata/dao/TransMemoryStreamingDAOTest.java index be202418d0..d8589ef9f9 100644 --- a/server/zanata-war/src/test/java/org/zanata/dao/TransMemoryStreamingDAOTest.java +++ b/server/zanata-war/src/test/java/org/zanata/dao/TransMemoryStreamingDAOTest.java @@ -1,7 +1,6 @@ package org.zanata.dao; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.model.tm.TransMemory.tm; import static org.zanata.model.tm.TransMemoryUnit.tu; import static org.zanata.model.tm.TransMemoryUnitVariant.tuv; @@ -42,7 +41,7 @@ public void findAllTextFlows() throws Exception { CloseableIterator iter = dao.findTransUnitsByTM(transMemory.get()); try { - assertThat(Iterators.size(iter), equalTo(4)); + assertThat(Iterators.size(iter)).isEqualTo(4); deleteTMData(); } finally { if (iter != null) { diff --git a/server/zanata-war/src/test/java/org/zanata/eventservice/SequentialConnectionIdGeneratorTest.java b/server/zanata-war/src/test/java/org/zanata/eventservice/SequentialConnectionIdGeneratorTest.java index de66b21144..eb9329cb0e 100644 --- a/server/zanata-war/src/test/java/org/zanata/eventservice/SequentialConnectionIdGeneratorTest.java +++ b/server/zanata-war/src/test/java/org/zanata/eventservice/SequentialConnectionIdGeneratorTest.java @@ -3,13 +3,12 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import static org.hamcrest.MatcherAssert.*; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.*; /** @@ -34,12 +33,12 @@ public void testGenerateConnectionId() throws Exception { when(request.getSession(true)).thenReturn(session); when(session.getId()).thenReturn("sessionId"); - assertThat(idGenerator.generateConnectionId(request), - Matchers.equalTo("sessionId-0")); - assertThat(idGenerator.generateConnectionId(request), - Matchers.equalTo("sessionId-1")); - assertThat(idGenerator.generateConnectionId(request), - Matchers.equalTo("sessionId-2")); + assertThat(idGenerator.generateConnectionId(request)) + .isEqualTo("sessionId-0"); + assertThat(idGenerator.generateConnectionId(request)) + .isEqualTo("sessionId-1"); + assertThat(idGenerator.generateConnectionId(request)) + .isEqualTo("sessionId-2"); } @Test @@ -48,6 +47,6 @@ public void testGetConnectionId() throws Exception { String connectionId = idGenerator.getConnectionId(request); - assertThat(connectionId, Matchers.equalTo("connectionId")); + assertThat(connectionId).isEqualTo("connectionId"); } } diff --git a/server/zanata-war/src/test/java/org/zanata/file/DocumentUploadTest.java b/server/zanata-war/src/test/java/org/zanata/file/DocumentUploadTest.java index 9cd77968f9..66644af225 100644 --- a/server/zanata-war/src/test/java/org/zanata/file/DocumentUploadTest.java +++ b/server/zanata-war/src/test/java/org/zanata/file/DocumentUploadTest.java @@ -1,8 +1,7 @@ package org.zanata.file; import static javax.ws.rs.core.Response.Status.fromStatusCode; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; import java.io.ByteArrayInputStream; @@ -89,16 +88,16 @@ protected ChunkUploadResponse responseEntity() { } protected void assertResponseHasStatus(Status errorStatus) { - assertThat(fromStatusCode(response.getStatus()), is(errorStatus)); + assertThat(fromStatusCode(response.getStatus())).isEqualTo(errorStatus); } protected void assertResponseHasErrorMessage(String errorMessage) { - assertThat(responseEntity().getErrorMessage(), is(errorMessage)); + assertThat(responseEntity().getErrorMessage()).isEqualTo(errorMessage); } protected void assertUploadTerminated() { - assertThat(responseEntity().getAcceptedChunks(), is(0)); - assertThat(responseEntity().isExpectingMore(), is(false)); + assertThat(responseEntity().getAcceptedChunks()).isEqualTo(0); + assertThat(responseEntity().isExpectingMore()).isFalse(); } /** diff --git a/server/zanata-war/src/test/java/org/zanata/file/DocumentUploadUtilTest.java b/server/zanata-war/src/test/java/org/zanata/file/DocumentUploadUtilTest.java index d4d96b7d2f..67aaa7c465 100644 --- a/server/zanata-war/src/test/java/org/zanata/file/DocumentUploadUtilTest.java +++ b/server/zanata-war/src/test/java/org/zanata/file/DocumentUploadUtilTest.java @@ -22,9 +22,7 @@ import static com.google.common.base.Charsets.UTF_8; import static javax.ws.rs.core.Response.Status.*; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.sameInstance; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -104,10 +102,10 @@ public void notValidIfNotLoggedIn() { util.failIfUploadNotValid(conf.id, conf.uploadForm); fail("Should throw exception if user is not logged in"); } catch (DocumentUploadException e) { - assertThat(e.getStatusCode(), is(UNAUTHORIZED)); - assertThat(e.getMessage(), - is("Valid combination of username and api-key for this " - + "server were not included in the request.")); + assertThat(e.getStatusCode()).isEqualTo(UNAUTHORIZED); + assertThat(e.getMessage()).isEqualTo( + "Valid combination of username and api-key for this " + + "server were not included in the request."); } } @@ -119,11 +117,9 @@ public void notValidIfNoFileContent() { util.failIfUploadNotValid(conf.id, conf.uploadForm); fail("Should throw exception if there is no file content"); } catch (DocumentUploadException e) { - assertThat(e.getStatusCode(), is(PRECONDITION_FAILED)); - assertThat( - e.getMessage(), - is("Required form parameter 'file' containing file content " - + "was not found.")); + assertThat(e.getStatusCode()).isEqualTo(PRECONDITION_FAILED); + assertThat(e.getMessage()).isEqualTo("Required form parameter 'file' containing file content " + + "was not found."); } } @@ -135,9 +131,9 @@ public void notValidIfNoFileType() { util.failIfUploadNotValid(conf.id, conf.uploadForm); fail("Should throw exception if file type is not set."); } catch (DocumentUploadException e) { - assertThat(e.getStatusCode(), is(PRECONDITION_FAILED)); - assertThat(e.getMessage(), - is("Required form parameter 'type' was not found.")); + assertThat(e.getStatusCode()).isEqualTo(PRECONDITION_FAILED); + assertThat(e.getMessage()) + .isEqualTo("Required form parameter 'type' was not found."); } } @@ -149,9 +145,9 @@ public void notValidIfNoContentHash() { util.failIfHashNotPresent(conf.uploadForm); fail("Should throw exception if hash is not set."); } catch (DocumentUploadException e) { - assertThat(e.getStatusCode(), is(PRECONDITION_FAILED)); - assertThat(e.getMessage(), - is("Required form parameter 'hash' was not found.")); + assertThat(e.getStatusCode()).isEqualTo(PRECONDITION_FAILED); + assertThat(e.getMessage()) + .isEqualTo("Required form parameter 'hash' was not found."); } } @@ -164,10 +160,9 @@ public void notValidIfVersionDoesNotExist() { util.failIfUploadNotValid(conf.id, conf.uploadForm); fail("Should throw exception if project-version does not exist."); } catch (DocumentUploadException e) { - assertThat(e.getStatusCode(), is(NOT_FOUND)); - assertThat(e.getMessage(), - is("The specified project-version \"myproject:myversion\" " - + "does not exist on this server.")); + assertThat(e.getStatusCode()).isEqualTo(NOT_FOUND); + assertThat(e.getMessage()).isEqualTo("The specified project-version \"myproject:myversion\" " + + "does not exist on this server."); } } @@ -189,11 +184,10 @@ private void notValidIfProjectStatusIs(EntityStatus nonActiveStatus) { util.failIfUploadNotValid(conf.id, conf.uploadForm); fail("Should throw exception if project is read only or obsolete."); } catch (DocumentUploadException e) { - assertThat(e.getStatusCode(), is(FORBIDDEN)); - assertThat( - e.getMessage(), - is("The project \"myproject\" is not active. Document upload " - + "is not allowed.")); + assertThat(e.getStatusCode()).isEqualTo(FORBIDDEN); + assertThat(e.getMessage()).isEqualTo( + "The project \"myproject\" is not active. Document upload " + + "is not allowed."); } } @@ -215,10 +209,10 @@ private void notValidIfVersionStatusIs(EntityStatus nonActiveStatus) { util.failIfUploadNotValid(conf.id, conf.uploadForm); fail("Should throw exception if version is read only or obsolete."); } catch (DocumentUploadException e) { - assertThat(e.getStatusCode(), is(FORBIDDEN)); - assertThat(e.getMessage(), - is("The project-version \"myproject:myversion\" is not " - + "active. Document upload is not allowed.")); + assertThat(e.getStatusCode()).isEqualTo(FORBIDDEN); + assertThat(e.getMessage()).isEqualTo( + "The project-version \"myproject:myversion\" is not " + + "active. Document upload is not allowed."); } } @@ -231,9 +225,9 @@ public void notValidIfFileTypeInvalid() { util.failIfUploadNotValid(conf.id, conf.uploadForm); fail("Should throw exception if file type is not valid."); } catch (DocumentUploadException e) { - assertThat(e.getStatusCode(), is(PRECONDITION_FAILED)); - assertThat(e.getMessage(), - is("Value 'invalid' is not a recognized document type.")); + assertThat(e.getStatusCode()).isEqualTo(PRECONDITION_FAILED); + assertThat(e.getMessage()).isEqualTo( + "Value 'invalid' is not a recognized document type."); } } @@ -246,11 +240,10 @@ public void subsequentPartNoUploadId() { util.failIfUploadNotValid(conf.id, conf.uploadForm); fail("Should throw exception if this is not the first part but no uploadId is supplied"); } catch (DocumentUploadException e) { - assertThat(e.getStatusCode(), is(PRECONDITION_FAILED)); - assertThat( - e.getMessage(), - is("Form parameter 'uploadId' must be provided when this is " - + "not the first part.")); + assertThat(e.getStatusCode()).isEqualTo(PRECONDITION_FAILED); + assertThat(e.getMessage()).isEqualTo( + "Form parameter 'uploadId' must be provided when this is " + + "not the first part."); } } @@ -266,9 +259,9 @@ public void subsequentPartUploadNotPresent() { try { util.failIfUploadNotValid(conf.id, conf.uploadForm); } catch (DocumentUploadException e) { - assertThat(e.getStatusCode(), is(PRECONDITION_FAILED)); - assertThat(e.getMessage(), - is("No incomplete uploads found for uploadId '5'.")); + assertThat(e.getStatusCode()).isEqualTo(PRECONDITION_FAILED); + assertThat(e.getMessage()) + .isEqualTo("No incomplete uploads found for uploadId '5'."); } } @@ -287,10 +280,9 @@ public void subsequentPartUploadMismatchedDocId() { try { util.failIfUploadNotValid(conf.id, conf.uploadForm); } catch (DocumentUploadException e) { - assertThat(e.getStatusCode(), is(PRECONDITION_FAILED)); - assertThat( - e.getMessage(), - is("Supplied uploadId '5' in request is not valid for document 'mismatched-id'.")); + assertThat(e.getStatusCode()).isEqualTo(PRECONDITION_FAILED); + assertThat(e.getMessage()).isEqualTo( + "Supplied uploadId '5' in request is not valid for document 'mismatched-id'."); } } @@ -300,9 +292,9 @@ public void returnFormStreamWhenFileIsAbsent() throws FileNotFoundException { new ByteArrayInputStream("test".getBytes()); conf = defaultUpload().fileStream(streamFromForm).build(); InputStream returnedStream = - getInputStream(Optional. absent(), conf.uploadForm); + getInputStream(Optional.absent(), conf.uploadForm); - assertThat(returnedStream, is(sameInstance(streamFromForm))); + assertThat(returnedStream).isSameAs(streamFromForm); } @Test @@ -319,8 +311,8 @@ public void returnFileStreamWhenFileIsPresent() throws IOException { InputStream returnedStream = getInputStream(presentFile, conf.uploadForm); - assertThat(IOUtils.toString(returnedStream, "utf-8"), - is("text in file")); + assertThat(IOUtils.toString(returnedStream, "utf-8")) + .isEqualTo("text in file"); } finally { if (f != null) { f.delete(); @@ -348,10 +340,10 @@ public void canCombineUploadPartsInOrder() throws SQLException, IOException { util.combineToTempFileAndDeleteUploadRecord(upload, uploadForm); - assertThat(returnedFile, is(sameInstance(persistedFile))); + assertThat(returnedFile).isSameAs(persistedFile); String persistedContents = IOUtils.toString(persistedInputStreamCaptor.getValue(), "utf-8"); - assertThat(persistedContents, is("abcdefghi")); + assertThat(persistedContents).isEqualTo("abcdefghi"); verify(session).delete(upload); } @@ -367,12 +359,11 @@ public void combineFailsOnHashMismatch() throws SQLException { try { util.combineToTempFileAndDeleteUploadRecord(upload, uploadForm); } catch (DocumentUploadException e) { - assertThat(e.getStatusCode(), is(CONFLICT)); - assertThat( - e.getMessage(), - is("MD5 hash \"incorrect hash\" sent with request does " + - "not match server-generated hash. Aborted upload " + - "operation.")); + assertThat(e.getStatusCode()).isEqualTo(CONFLICT); + assertThat(e.getMessage()).isEqualTo( + "MD5 hash \"incorrect hash\" sent with request does " + + "not match server-generated hash. Aborted upload " + + "operation."); } } @@ -386,7 +377,7 @@ public void combineSetsHashWhenNoHashProvided() throws SQLException { uploadForm.setFileStream(finalPartStream); util.combineToTempFileAndDeleteUploadRecord(upload, uploadForm); - assertThat(uploadForm.getHash(), is(HASH_OF_ABCDEFGHI)); + assertThat(uploadForm.getHash()).isEqualTo(HASH_OF_ABCDEFGHI); } private HDocumentUpload mockTwoPartUploadUsingHash(String hash) diff --git a/server/zanata-war/src/test/java/org/zanata/file/GlobalDocumentIdTest.java b/server/zanata-war/src/test/java/org/zanata/file/GlobalDocumentIdTest.java index 4b275fae65..2d034ec594 100644 --- a/server/zanata-war/src/test/java/org/zanata/file/GlobalDocumentIdTest.java +++ b/server/zanata-war/src/test/java/org/zanata/file/GlobalDocumentIdTest.java @@ -3,8 +3,7 @@ import org.junit.Before; import org.junit.Test; -import static org.hamcrest.MatcherAssert.*; -import static org.hamcrest.Matchers.*; +import static org.assertj.core.api.Assertions.assertThat; public class GlobalDocumentIdTest { @@ -25,34 +24,28 @@ private GlobalDocumentId newBasicInstance() { @Test public void getDocId() { - assertThat(id.getDocId(), is(DOCUMENT_ID)); + assertThat(id.getDocId()).isEqualTo(DOCUMENT_ID); } @Test public void getIterationSlug() { - assertThat(id.getVersionSlug(), is(VERSION_SLUG)); + assertThat(id.getVersionSlug()).isEqualTo(VERSION_SLUG); } @Test public void getProjectSlug() { - assertThat(id.getProjectSlug(), is(PROJECT_SLUG)); - } - - @Test - public void equalsIsReflexive() { - assertThat(id, equalTo(id)); + assertThat(id.getProjectSlug()).isEqualTo(PROJECT_SLUG); } @Test public void equalsIsSymmetric() { GlobalDocumentId sameId = newBasicInstance(); - assertThat(sameId, equalTo(id)); - assertThat(id, equalTo(sameId)); + assertThat(sameId).isEqualTo(id); } @Test public void sameHashForEqualObjects() { GlobalDocumentId sameId = newBasicInstance(); - assertThat(sameId.hashCode(), is(id.hashCode())); + assertThat(sameId.hashCode()).isEqualTo(id.hashCode()); } } diff --git a/server/zanata-war/src/test/java/org/zanata/file/SourceDocumentUploadTest.java b/server/zanata-war/src/test/java/org/zanata/file/SourceDocumentUploadTest.java index 9c81eefdc9..299dbddf46 100644 --- a/server/zanata-war/src/test/java/org/zanata/file/SourceDocumentUploadTest.java +++ b/server/zanata-war/src/test/java/org/zanata/file/SourceDocumentUploadTest.java @@ -21,9 +21,7 @@ package org.zanata.file; import static javax.ws.rs.core.Response.Status.*; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.nullValue; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doThrow; @@ -205,12 +203,12 @@ public void canUploadNewDocument() throws IOException { when(documentUploadUtil.isNewDocument(conf.id)).thenReturn(true); response = sourceUpload.tryUploadSourceFile(conf.id, conf.uploadForm); - assertThat(responseEntity().getSuccessMessage(), - is("Upload of new source document successful.")); + assertThat(responseEntity().getSuccessMessage()).isEqualTo( + "Upload of new source document successful."); assertResponseHasStatus(CREATED); - assertThat(responseEntity().getAcceptedChunks(), is(1)); - assertThat(responseEntity().isExpectingMore(), is(false)); - assertThat(responseEntity().getErrorMessage(), is(nullValue())); + assertThat(responseEntity().getAcceptedChunks()).isEqualTo(1); + assertThat(responseEntity().isExpectingMore()).isFalse(); + assertThat(responseEntity().getErrorMessage()).isNull(); } @Test @@ -222,11 +220,11 @@ public void canUploadExistingDocument() throws IOException { response = sourceUpload.tryUploadSourceFile(conf.id, conf.uploadForm); assertResponseHasStatus(OK); - assertThat(responseEntity().getAcceptedChunks(), is(1)); - assertThat(responseEntity().isExpectingMore(), is(false)); - assertThat(responseEntity().getSuccessMessage(), - is("Upload of new version of source document successful.")); - assertThat(responseEntity().getErrorMessage(), is(nullValue())); + assertThat(responseEntity().getAcceptedChunks()).isEqualTo(1); + assertThat(responseEntity().isExpectingMore()).isFalse(); + assertThat(responseEntity().getSuccessMessage()).isEqualTo( + "Upload of new version of source document successful."); + assertThat(responseEntity().getErrorMessage()).isNull(); } @Test @@ -235,7 +233,7 @@ public void usesGivenParameters() throws IOException { conf = defaultUpload().build(); mockRequiredServices(); sourceUpload.tryUploadSourceFile(conf.id, conf.uploadForm); - assertThat(paramCaptor.getValue().get(), is(conf.params)); + assertThat(paramCaptor.getValue().get()).isEqualTo(conf.params); } @Test @@ -244,7 +242,7 @@ public void fallsBackOnStoredParameters() throws IOException { conf = defaultUpload().params(null).build(); mockRequiredServices(); sourceUpload.tryUploadSourceFile(conf.id, conf.uploadForm); - assertThat(paramCaptor.getValue().get(), is(conf.storedParams)); + assertThat(paramCaptor.getValue().get()).isEqualTo(conf.storedParams); } @Test @@ -253,8 +251,8 @@ public void uploadParametersAreStored() throws IOException { conf = defaultUpload().build(); mockRequiredServices(); sourceUpload.tryUploadSourceFile(conf.id, conf.uploadForm); - assertThat(persistedRawDocument.getValue().getAdapterParameters(), - is(conf.params)); + assertThat(persistedRawDocument.getValue().getAdapterParameters()) + .isEqualTo(conf.params); } @Test @@ -263,7 +261,7 @@ public void storedParametersNotOverwrittenWithEmpty() throws IOException { conf = defaultUpload().params("").build(); mockRequiredServices(); sourceUpload.tryUploadSourceFile(conf.id, conf.uploadForm); - assertThat(persistedRawDocument.getValue().getAdapterParameters(), - is(conf.storedParams)); + assertThat(persistedRawDocument.getValue().getAdapterParameters()) + .isEqualTo(conf.storedParams); } } diff --git a/server/zanata-war/src/test/java/org/zanata/limits/LeakyBucketTest.java b/server/zanata-war/src/test/java/org/zanata/limits/LeakyBucketTest.java index a4dbecce7f..5ec7c854ce 100644 --- a/server/zanata-war/src/test/java/org/zanata/limits/LeakyBucketTest.java +++ b/server/zanata-war/src/test/java/org/zanata/limits/LeakyBucketTest.java @@ -8,15 +8,14 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import com.google.common.base.Function; -import com.google.common.base.Throwables; import com.google.common.collect.Lists; -import static org.hamcrest.MatcherAssert.assertThat; + +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; /** @@ -46,10 +45,10 @@ public void beforeMethod() { @Test public void willWaitUntilRefill() throws InterruptedException { - assertThat(bucket.tryAcquire(), Matchers.is(true)); - assertThat(bucket.tryAcquire(), Matchers.is(false)); + assertThat(bucket.tryAcquire()).isTrue(); + assertThat(bucket.tryAcquire()).isFalse(); when(timeTracker.timePassed()).thenReturn(timeOverRefillDuration); - assertThat(bucket.tryAcquire(), Matchers.is(true)); + assertThat(bucket.tryAcquire()).isTrue(); } @Test @@ -67,13 +66,12 @@ public Boolean call() throws Exception { ExecutorService executorService = Executors.newFixedThreadPool(threads); List> futures = executorService.invokeAll(callables); List result = getFutureResult(futures); - assertThat(result, Matchers.containsInAnyOrder(true, false, false)); + assertThat(result).contains(true, false, false); // here we simulate that we have waited enough time and try again when(timeTracker.timePassed()).thenReturn(timeOverRefillDuration, 0L, 0L); List> callAgain = executorService.invokeAll(callables); - assertThat(getFutureResult(callAgain), - Matchers.containsInAnyOrder(true, false, false)); + assertThat(getFutureResult(callAgain)).contains(true, false, false); } private static List diff --git a/server/zanata-war/src/test/java/org/zanata/model/CacheReliabilityTest.java b/server/zanata-war/src/test/java/org/zanata/model/CacheReliabilityTest.java index cee0c6441d..f50cc849ec 100644 --- a/server/zanata-war/src/test/java/org/zanata/model/CacheReliabilityTest.java +++ b/server/zanata-war/src/test/java/org/zanata/model/CacheReliabilityTest.java @@ -30,8 +30,7 @@ import org.junit.Test; import org.zanata.ZanataDbunitJpaTest; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; /** * @author Carlos Munoz projectTargets = project.getProjectIterations(); - assertThat("Project should have 3 targets", projectTargets.size(), - is(3)); + assertThat(projectTargets.size()).isEqualTo(3) + .as("Project should have 3 targets"); List iterationIds = Lists.transform(projectTargets, - new Function() { - @Override - public Long apply(HProjectIteration input) { - return input.getId(); - } - }); - assertThat(iterationIds, Matchers.containsInAnyOrder(1L, 2L, 900L)); + input -> input.getId()); + assertThat(iterationIds).contains(1L, 2L, 900L); } @Test @@ -108,11 +97,11 @@ public void checkPositionsNotNull() throws Exception { em.refresh(hdoc); List textFlows2 = hdoc.getTextFlows(); - assertThat(textFlows2.size(), is(2)); + assertThat(textFlows2.size()).isEqualTo(2); flow1 = textFlows2.get(0); - assertThat(flow1, notNullValue()); + assertThat(flow1).isNotNull(); flow2 = textFlows2.get(1); - assertThat(flow2, notNullValue()); + assertThat(flow2).isNotNull(); // TODO: we should automate this... hdoc.incrementRevision(); @@ -126,17 +115,17 @@ public void checkPositionsNotNull() throws Exception { em.refresh(hdoc); em.refresh(flow1); em.refresh(flow2); - assertThat(hdoc.getTextFlows().size(), is(1)); + assertThat(hdoc.getTextFlows().size()).isEqualTo(1); flow2 = hdoc.getTextFlows().get(0); - assertThat(flow2.getResId(), equalTo("textflow2")); + assertThat(flow2.getResId()).isEqualTo("textflow2"); flow1 = hdoc.getAllTextFlows().get("textflow1"); // assertThat(flow1.getPos(), nullValue()); - assertThat(flow1.isObsolete(), is(true)); - assertThat(flow1.getRevision(), is(2)); + assertThat(flow1.isObsolete()).isTrue(); + assertThat(flow1.getRevision()).isEqualTo(2); flow2 = hdoc.getAllTextFlows().get("textflow2"); // assertThat(flow1.getPos(), is(0)); - assertThat(flow2.isObsolete(), is(false)); + assertThat(flow2.isObsolete()).isFalse(); } // FIXME this test only works if resources-dev is on the classpath. @@ -180,8 +169,8 @@ public void ensureHistoryOnTextFlow() { em.createQuery( "from HTextFlowTargetHistory h where h.textFlowTarget =:target") .setParameter("target", target).getResultList(); - assertThat(hist, notNullValue()); - assertThat(hist.size(), not(0)); + assertThat(hist).isNotNull(); + assertThat(hist.size()).isNotEqualTo(0); } diff --git a/server/zanata-war/src/test/java/org/zanata/model/HDocumentHistoryJPATest.java b/server/zanata-war/src/test/java/org/zanata/model/HDocumentHistoryJPATest.java index 2a39486ad5..e15e81004b 100644 --- a/server/zanata-war/src/test/java/org/zanata/model/HDocumentHistoryJPATest.java +++ b/server/zanata-war/src/test/java/org/zanata/model/HDocumentHistoryJPATest.java @@ -1,10 +1,5 @@ package org.zanata.model; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; - import java.util.Date; import java.util.List; @@ -18,6 +13,8 @@ import org.zanata.common.LocaleId; import org.zanata.dao.LocaleDAO; +import static org.assertj.core.api.Assertions.assertThat; + public class HDocumentHistoryJPATest extends ZanataDbunitJpaTest { private LocaleDAO localeDAO; HLocale de_DE; @@ -61,17 +58,17 @@ public void ensureHistoryIsRecorded() { List historyElems = loadHistory(d); - assertThat(historyElems.size(), is(1)); + assertThat(historyElems.size()).isEqualTo(1); HDocumentHistory history = historyElems.get(0); - assertThat(history.getDocId(), is(d.getDocId())); - assertThat(history.getContentType(), is(ContentType.TextPlain)); - assertThat(history.getLastChanged().getTime(), - equalTo(lastChanged.getTime())); - assertThat(history.getLastModifiedBy(), nullValue()); - assertThat(history.getLocale().getLocaleId(), is(de_DE.getLocaleId())); - assertThat(history.getName(), is(d.getName())); - assertThat(history.getPath(), is(d.getPath())); - assertThat(history.getRevision(), is(d.getRevision() - 1)); + assertThat(history.getDocId()).isEqualTo(d.getDocId()); + assertThat(history.getContentType()).isEqualTo(ContentType.TextPlain); + assertThat(history.getLastChanged().getTime()) + .isEqualTo(lastChanged.getTime()); + assertThat(history.getLastModifiedBy()).isNull(); + assertThat(history.getLocale().getLocaleId()).isEqualTo(de_DE.getLocaleId()); + assertThat(history.getName()).isEqualTo(d.getName()); + assertThat(history.getPath()).isEqualTo(d.getPath()); + assertThat(history.getRevision()).isEqualTo(d.getRevision() - 1); d.incrementRevision(); d.setName("name2"); @@ -79,7 +76,7 @@ public void ensureHistoryIsRecorded() { session.flush(); historyElems = loadHistory(d); - assertThat(historyElems.size(), is(2)); + assertThat(historyElems.size()).isEqualTo(2); } diff --git a/server/zanata-war/src/test/java/org/zanata/model/HGlossaryEntryJPATest.java b/server/zanata-war/src/test/java/org/zanata/model/HGlossaryEntryJPATest.java index aeed47c90d..c097f26a31 100644 --- a/server/zanata-war/src/test/java/org/zanata/model/HGlossaryEntryJPATest.java +++ b/server/zanata-war/src/test/java/org/zanata/model/HGlossaryEntryJPATest.java @@ -33,8 +33,7 @@ import org.zanata.dao.GlossaryDAO; import org.zanata.util.GlossaryUtil; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; /** * @@ -70,7 +69,7 @@ public void testHashMap() { public void testTermsSize() { List entryList = glossaryDAO.getEntriesByLocale( LocaleId.EN_US, 0, 200, null, null, GlossaryUtil.GLOBAL_QUALIFIED_NAME); - assertThat(entryList.get(0).getGlossaryTerms().size(), is(3)); + assertThat(entryList.get(0).getGlossaryTerms().size()).isEqualTo(3); } @Test @@ -81,7 +80,7 @@ public void testDeleteGlossaries() { List entryList = glossaryDAO.getEntriesByLocale( LocaleId.EN_US, 0, 200, null, null, GlossaryUtil.GLOBAL_QUALIFIED_NAME); - assertThat(entryList.size(), is(0)); + assertThat(entryList.size()).isEqualTo(0); } @Override diff --git a/server/zanata-war/src/test/java/org/zanata/model/HTextFlowHistoryJPATest.java b/server/zanata-war/src/test/java/org/zanata/model/HTextFlowHistoryJPATest.java index 4a6bbdd662..387180ac59 100644 --- a/server/zanata-war/src/test/java/org/zanata/model/HTextFlowHistoryJPATest.java +++ b/server/zanata-war/src/test/java/org/zanata/model/HTextFlowHistoryJPATest.java @@ -1,8 +1,5 @@ package org.zanata.model; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; - import java.util.Arrays; import java.util.List; @@ -16,6 +13,8 @@ import org.zanata.common.LocaleId; import org.zanata.dao.LocaleDAO; +import static org.assertj.core.api.Assertions.assertThat; + public class HTextFlowHistoryJPATest extends ZanataDbunitJpaTest { private LocaleDAO localeDAO; HLocale en_US; @@ -53,8 +52,8 @@ public void ensureHistoryIsRecorded() { List historyElems = getHistory(tf); - assertThat("Incorrect History size on persist", historyElems.size(), - is(0)); + assertThat(historyElems.size()).isEqualTo(0) + .as("Incorrect History size on persist"); d.incrementRevision(); tf.setContents("hello world again"); @@ -63,10 +62,10 @@ public void ensureHistoryIsRecorded() { historyElems = getHistory(tf); - assertThat("Incorrect History size on first update", - historyElems.size(), is(1)); - assertThat(historyElems.get(0).getContents(), - is(Arrays.asList("hello world"))); + assertThat(historyElems.size()).isEqualTo(1) + .as("Incorrect History size on first update"); + assertThat(historyElems.get(0).getContents()) + .isEqualTo(Arrays.asList("hello world")); d.incrementRevision(); tf.setContents("hello world a third time"); @@ -75,10 +74,10 @@ public void ensureHistoryIsRecorded() { historyElems = getHistory(tf); - assertThat("Incorrect History size on second update", - historyElems.size(), is(2)); - assertThat(historyElems.get(1).getContents(), - is(Arrays.asList("hello world again"))); + assertThat(historyElems.size()).isEqualTo(2) + .as("Incorrect History size on second update"); + assertThat(historyElems.get(1).getContents()) + .isEqualTo(Arrays.asList("hello world again")); } @Test @@ -99,8 +98,8 @@ public void ensureHistoryIsRecordedPlural() { List historyElems = getHistory(tf); - assertThat("Incorrect History size on persist", historyElems.size(), - is(0)); + assertThat(historyElems.size()).isEqualTo(0) + .as("Incorrect History size on persist"); d.incrementRevision(); tf.setPlural(true); @@ -110,10 +109,10 @@ public void ensureHistoryIsRecordedPlural() { historyElems = getHistory(tf); - assertThat("Incorrect History size on first update", - historyElems.size(), is(1)); - assertThat(historyElems.get(0).getContents(), - is(Arrays.asList("hello world"))); + assertThat(historyElems.size()).isEqualTo(1) + .as("Incorrect History size on first update"); + assertThat(historyElems.get(0).getContents()) + .isEqualTo(Arrays.asList("hello world")); d.incrementRevision(); tf.setContents("hello world 4", "hello world 5", "hellow world 6"); @@ -122,10 +121,10 @@ public void ensureHistoryIsRecordedPlural() { historyElems = getHistory(tf); - assertThat("Incorrect History size on second update", - historyElems.size(), is(2)); - assertThat(historyElems.get(1).getContents(), - is(Arrays.asList("hello world 1", "hello world 2"))); + assertThat(historyElems.size()).isEqualTo(2) + .as("Incorrect History size on second update"); + assertThat(historyElems.get(1).getContents()) + .isEqualTo(Arrays.asList("hello world 1", "hello world 2")); } @SuppressWarnings("unchecked") diff --git a/server/zanata-war/src/test/java/org/zanata/model/HTextFlowJPATest.java b/server/zanata-war/src/test/java/org/zanata/model/HTextFlowJPATest.java index a4792a8e08..93c5e5e25f 100644 --- a/server/zanata-war/src/test/java/org/zanata/model/HTextFlowJPATest.java +++ b/server/zanata-war/src/test/java/org/zanata/model/HTextFlowJPATest.java @@ -20,10 +20,6 @@ */ package org.zanata.model; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.is; - import java.util.Arrays; import java.util.List; @@ -37,6 +33,8 @@ import org.zanata.dao.LocaleDAO; import org.zanata.dao.ProjectIterationDAO; +import static org.assertj.core.api.Assertions.assertThat; + public class HTextFlowJPATest extends ZanataDbunitJpaTest { private LocaleDAO localeDAO; @@ -93,12 +91,13 @@ public void textFlowWithSingleContent() { // reload the doc em.refresh(hdoc); - assertThat("Expected document to contain at least one text flow", hdoc - .getTextFlows().size(), greaterThan(0)); - assertThat("Expected Text flow to contain single content", hdoc - .getTextFlows().get(0).getContents().size(), is(1)); - assertThat("Expected deprecated method to still work", hdoc - .getTextFlows().get(0).getContents().get(0), is("hello world")); + assertThat(hdoc.getTextFlows().size()).isGreaterThan(0) + .as("Expected document to contain at least one text flow"); + assertThat(hdoc.getTextFlows().get(0).getContents().size()).isEqualTo(1) + .as("Expected Text flow to contain single content"); + assertThat(hdoc.getTextFlows().get(0).getContents().get(0)) + .isEqualTo("hello world") + .as("Expected deprecated method to still work"); } @Test @@ -125,15 +124,17 @@ public void textFlowWithPlurals() { // reload the doc em.refresh(hdoc); - assertThat("Expected document to contain at least one text flow", hdoc - .getTextFlows().size(), greaterThan(0)); - assertThat("Expected Text flow to contain 3 content strings", hdoc - .getTextFlows().get(0).getContents().size(), is(3)); - assertThat("Expected contents to be preserved", hdoc.getTextFlows() - .get(0).getContents(), is(Arrays.asList("hello world", - "hello worlds", "hellos worlds"))); - assertThat("Expected deprecated method to still work", hdoc - .getTextFlows().get(0).getContents().get(0), is("hello world")); + assertThat(hdoc.getTextFlows().size()).isGreaterThan(0) + .as("Expected document to contain at least one text flow"); + assertThat(hdoc.getTextFlows().get(0).getContents().size()).isEqualTo(3) + .as("Expected Text flow to contain 3 content strings"); + assertThat(hdoc.getTextFlows().get(0).getContents()) + .isEqualTo(Arrays.asList("hello world", + "hello worlds", "hellos worlds")) + .as("Expected contents to be preserved"); + assertThat(hdoc.getTextFlows().get(0).getContents().get(0)) + .isEqualTo("hello world") + .as("Expected deprecated method to still work"); } @Test @@ -156,16 +157,16 @@ public void textFlowWithPluralsAndSomeEmptyContents() { // reload the doc em.refresh(hdoc); - assertThat("Expected document to contain at least one text flow", hdoc - .getTextFlows().size(), greaterThan(0)); - assertThat("Expected Text flow to contain 4 content strings", hdoc - .getTextFlows().get(0).getContents().size(), is(4)); - assertThat("Expected contents to be preserved", hdoc.getTextFlows() - .get(0).getContents(), is(Arrays.asList("hello world 1", - "hello world 2", null, "hello world 4"))); - assertThat("Expected deprecated method to still work", hdoc - .getTextFlows().get(0).getContents().get(0), - is("hello world 1")); + assertThat(hdoc.getTextFlows().size()).isGreaterThan(0) + .as("Expected document to contain at least one text flow"); + assertThat(hdoc.getTextFlows().get(0).getContents().size()).isEqualTo(4) + .as("Expected Text flow to contain 4 content strings"); + assertThat(hdoc.getTextFlows().get(0).getContents()) + .isEqualTo(Arrays.asList("hello world 1", + "hello world 2", null, "hello world 4")) + .as("Expected contents to be preserved"); + assertThat(hdoc.getTextFlows().get(0).getContents().get(0)) + .isEqualTo("hello world 1"); } } diff --git a/server/zanata-war/src/test/java/org/zanata/model/HTextFlowTargetHistoryJPATest.java b/server/zanata-war/src/test/java/org/zanata/model/HTextFlowTargetHistoryJPATest.java index 9cfa2a7b35..6908e46f2a 100644 --- a/server/zanata-war/src/test/java/org/zanata/model/HTextFlowTargetHistoryJPATest.java +++ b/server/zanata-war/src/test/java/org/zanata/model/HTextFlowTargetHistoryJPATest.java @@ -14,8 +14,7 @@ import org.zanata.dao.LocaleDAO; import org.zanata.dao.TextFlowTargetHistoryDAO; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; public class HTextFlowTargetHistoryJPATest extends ZanataDbunitJpaTest { private LocaleDAO localeDAO; @@ -67,27 +66,27 @@ public void ensureHistoryIsRecorded() { session.flush(); List historyElems = getHistory(target); - assertThat("Incorrect History size on persist", historyElems.size(), - is(0)); + assertThat(historyElems.size()).isEqualTo(0) + .as("Incorrect History size on persist"); target.setContents("blah!"); session.flush(); historyElems = getHistory(target); - assertThat("Incorrect History size on first update", - historyElems.size(), is(1)); + assertThat(historyElems.size()).isEqualTo(1) + .as("Incorrect History size on first update"); target.setContents("hola mundo!"); session.flush(); historyElems = getHistory(target); - assertThat("Incorrect History size on second update", - historyElems.size(), is(2)); - assertThat(historyElems.size(), is(2)); + assertThat(historyElems.size()).isEqualTo(2) + .as("Incorrect History size on second update"); + assertThat(historyElems.size()).isEqualTo(2); HTextFlowTargetHistory hist = historyElems.get(0); - assertThat(hist.getContents(), is(Arrays.asList("helleu world"))); + assertThat(hist.getContents()).isEqualTo(Arrays.asList("helleu world")); } @Test @@ -110,17 +109,17 @@ public void ensureHistoryIsRecordedPlural() { session.flush(); List historyElems = getHistory(target); - assertThat(historyElems.size(), is(0)); + assertThat(historyElems.size()).isEqualTo(0); target.setContents("blah", "blah!"); session.flush(); historyElems = getHistory(target); - assertThat(historyElems.size(), is(1)); + assertThat(historyElems.size()).isEqualTo(1); HTextFlowTargetHistory hist = historyElems.get(0); - assertThat(hist.getContents(), - is(Arrays.asList("helleu world", "helleu worlds"))); + assertThat(hist.getContents()) + .isEqualTo(Arrays.asList("helleu world", "helleu worlds")); assert historyDAO.findContentInHistory(target, Arrays.asList("helleu world", "helleu worlds")); diff --git a/server/zanata-war/src/test/java/org/zanata/model/TransMemoryJPATest.java b/server/zanata-war/src/test/java/org/zanata/model/TransMemoryJPATest.java index d7a0c83dd1..18d0d60b1d 100644 --- a/server/zanata-war/src/test/java/org/zanata/model/TransMemoryJPATest.java +++ b/server/zanata-war/src/test/java/org/zanata/model/TransMemoryJPATest.java @@ -34,11 +34,7 @@ import org.zanata.model.tm.TransMemory; import org.zanata.model.tm.TMMetadataType; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.startsWith; +import static org.assertj.core.api.Assertions.assertThat; /** * @author Carlos Munoz results = queryTUVs().getResultList(); - assertThat(results.size(), greaterThan(0)); + assertThat(results.size()).isGreaterThan(0); } @Test @@ -204,7 +202,7 @@ public void saveTransUnitVariantWithFormatting() throws Exception { // Verify they were saved TransMemoryUnitVariant tuv = (TransMemoryUnitVariant) queryTUVs().getSingleResult(); - assertThat(tuv.getPlainTextSegment(), equalTo("Mensaje de Prueba")); + assertThat(tuv.getPlainTextSegment()).isEqualTo("Mensaje de Prueba"); } private Query queryTUVs() { diff --git a/server/zanata-war/src/test/java/org/zanata/rest/compat/AccountRawCompatibilityITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/compat/AccountRawCompatibilityITCase.java index bc6a331127..9de765e868 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/compat/AccountRawCompatibilityITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/compat/AccountRawCompatibilityITCase.java @@ -33,12 +33,10 @@ import org.zanata.rest.ResourceRequest; import org.zanata.apicompat.rest.MediaTypes; import org.zanata.apicompat.rest.dto.Account; -import org.zanata.rest.ResourceRequest; import java.io.IOException; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.provider.DBUnitProvider.DataSetOperation; import static org.zanata.util.RawRestTestUtils.assertJaxbUnmarshal; import static org.zanata.util.RawRestTestUtils.assertJsonUnmarshal; @@ -75,20 +73,20 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { // Ok - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, Account.class); Account account = jsonUnmarshal(entityString, Account.class); // Assert correct parsing of all properties - assertThat(account.getUsername(), is("demo")); - assertThat(account.getApiKey(), - is("23456789012345678901234567890123")); - assertThat(account.getEmail(), is("user1@localhost")); - assertThat(account.getName(), is("Sample User")); - assertThat(account.getPasswordHash(), - is("/9Se/pfHeUH8FJ4asBD6jQ==")); - assertThat(account.getRoles().size(), is(1)); + assertThat(account.getUsername()).isEqualTo("demo"); + assertThat(account.getApiKey()) + .isEqualTo("23456789012345678901234567890123"); + assertThat(account.getEmail()).isEqualTo("user1@localhost"); + assertThat(account.getName()).isEqualTo("Sample User"); + assertThat(account.getPasswordHash()) + .isEqualTo("/9Se/pfHeUH8FJ4asBD6jQ=="); + assertThat(account.getRoles().size()).isEqualTo(1); // assertThat(account.getLanguages().size(), is(1)); // Language // teams are not being returned } @@ -109,20 +107,20 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { // Ok - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, Account.class); Account account = jaxbUnmarshal(entityString, Account.class); // Assert correct parsing of all properties - assertThat(account.getUsername(), is("demo")); - assertThat(account.getApiKey(), - is("23456789012345678901234567890123")); - assertThat(account.getEmail(), is("user1@localhost")); - assertThat(account.getName(), is("Sample User")); - assertThat(account.getPasswordHash(), - is("/9Se/pfHeUH8FJ4asBD6jQ==")); - assertThat(account.getRoles().size(), is(1)); + assertThat(account.getUsername()).isEqualTo("demo"); + assertThat(account.getApiKey()) + .isEqualTo("23456789012345678901234567890123"); + assertThat(account.getEmail()).isEqualTo("user1@localhost"); + assertThat(account.getName()).isEqualTo("Sample User"); + assertThat(account.getPasswordHash()) + .isEqualTo("/9Se/pfHeUH8FJ4asBD6jQ=="); + assertThat(account.getRoles().size()).isEqualTo(1); // assertThat(account.getLanguages().size(), is(1)); // Language // teams are not being returned } @@ -142,8 +140,8 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) throws IOException { - assertThat(response.getStatus(), - is(Status.UNAUTHORIZED.getStatusCode())); + assertThat(response.getStatus()) + .isEqualTo(Status.UNAUTHORIZED.getStatusCode()); } }.run(); } @@ -165,7 +163,7 @@ public void putAccountJson() throws Exception { Response putResponse = accountClient.put(a); // Assert initial put - assertThat(putResponse.getStatus(), is(Status.CREATED.getStatusCode())); + assertThat(putResponse.getStatus()).isEqualTo(Status.CREATED.getStatusCode()); putResponse.close(); // Modified Account @@ -174,17 +172,17 @@ public void putAccountJson() throws Exception { putResponse.close(); // Assert modification - assertThat(putResponse.getStatus(), is(Status.OK.getStatusCode())); + assertThat(putResponse.getStatus()).isEqualTo(Status.OK.getStatusCode()); // Retrieve again String entityString = accountClient.get().readEntity(String.class); Account a2 = jsonUnmarshal(entityString, Account.class); - assertThat(a2.getUsername(), is(a.getUsername())); - assertThat(a2.getApiKey(), is(a.getApiKey())); - assertThat(a2.getEmail(), is(a.getEmail())); - assertThat(a2.getName(), is(a.getName())); - assertThat(a2.getPasswordHash(), is(a.getPasswordHash())); - assertThat(a2.getRoles().size(), is(0)); + assertThat(a2.getUsername()).isEqualTo(a.getUsername()); + assertThat(a2.getApiKey()).isEqualTo(a.getApiKey()); + assertThat(a2.getEmail()).isEqualTo(a.getEmail()); + assertThat(a2.getName()).isEqualTo(a.getName()); + assertThat(a2.getPasswordHash()).isEqualTo(a.getPasswordHash()); + assertThat(a2.getRoles().size()).isEqualTo(0); // assertThat(a2.getLanguages().size(), is(1)); // Language teams are not // being returned } @@ -206,24 +204,24 @@ public void putAccountXml() throws Exception { Response putResponse = accountClient.put(a); // Assert initial put - assertThat(putResponse.getStatus(), is(Status.CREATED.getStatusCode())); + assertThat(putResponse.getStatus()).isEqualTo(Status.CREATED.getStatusCode()); // Modified Account a.setName("New Account Name"); putResponse = accountClient.put(a); // Assert modification - assertThat(putResponse.getStatus(), is(Status.OK.getStatusCode())); + assertThat(putResponse.getStatus()).isEqualTo(Status.OK.getStatusCode()); // Retrieve again String entityString = accountClient.get().readEntity(String.class); Account a2 = jaxbUnmarshal(entityString, Account.class); - assertThat(a2.getUsername(), is(a.getUsername())); - assertThat(a2.getApiKey(), is(a.getApiKey())); - assertThat(a2.getEmail(), is(a.getEmail())); - assertThat(a2.getName(), is(a.getName())); - assertThat(a2.getPasswordHash(), is(a.getPasswordHash())); - assertThat(a2.getRoles().size(), is(0)); + assertThat(a2.getUsername()).isEqualTo(a.getUsername()); + assertThat(a2.getApiKey()).isEqualTo(a.getApiKey()); + assertThat(a2.getEmail()).isEqualTo(a.getEmail()); + assertThat(a2.getName()).isEqualTo(a.getName()); + assertThat(a2.getPasswordHash()).isEqualTo(a.getPasswordHash()); + assertThat(a2.getRoles().size()).isEqualTo(0); // assertThat(a2.getLanguages().size(), is(1)); // Language teams are not // being returned } @@ -243,7 +241,7 @@ public void putAccountXmlUnauthorized() throws Exception { Response putResponse = accountClient.put(a); // Assert initial put - assertThat(putResponse.getStatus(), is(Status.FORBIDDEN.getStatusCode())); + assertThat(putResponse.getStatus()).isEqualTo(Status.FORBIDDEN.getStatusCode()); putResponse.close(); } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/compat/ProjectIterationRawCompatibilityITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/compat/ProjectIterationRawCompatibilityITCase.java index 05442fcf6d..557b641eea 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/compat/ProjectIterationRawCompatibilityITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/compat/ProjectIterationRawCompatibilityITCase.java @@ -37,8 +37,7 @@ import java.io.IOException; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.provider.DBUnitProvider.DataSetOperation; import static org.zanata.util.RawRestTestUtils.*; @@ -77,13 +76,13 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { protected void onResponse(Response response) throws IOException { // 200 - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); + assertThat(response.getStatus()).isEqualTo(Status.OK.getStatusCode()); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, ProjectIteration.class); ProjectIteration it = jsonUnmarshal(entityString, ProjectIteration.class); - assertThat(it.getId(), is("1.0")); + assertThat(it.getId()).isEqualTo("1.0"); } }.run(); } @@ -104,13 +103,13 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { // 200 - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); + assertThat(response.getStatus()).isEqualTo(Status.OK.getStatusCode()); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, ProjectIteration.class); ProjectIteration it = jaxbUnmarshal(entityString, ProjectIteration.class); - assertThat(it.getId(), is("1.0")); + assertThat(it.getId()).isEqualTo("1.0"); } }.run(); @@ -143,8 +142,8 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { // 201 - assertThat(response.getStatus(), - is(Status.CREATED.getStatusCode())); + assertThat(response.getStatus()) + .isEqualTo(Status.CREATED.getStatusCode()); } }.run(); @@ -164,12 +163,12 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { // 200 - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); + assertThat(response.getStatus()).isEqualTo(Status.OK.getStatusCode()); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, ProjectIteration.class); ProjectIteration it = jsonUnmarshal(entityString, ProjectIteration.class); - assertThat(it.getId(), is("new-iteration")); + assertThat(it.getId()).isEqualTo("new-iteration"); } }.run(); @@ -202,8 +201,7 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { // 201 - assertThat(response.getStatus(), - is(Status.CREATED.getStatusCode())); + assertThat(response.getStatus()).isEqualTo(Status.CREATED.getStatusCode()); } }.run(); @@ -222,13 +220,13 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { // 200 - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); + assertThat(response.getStatus()).isEqualTo(Status.OK.getStatusCode()); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, ProjectIteration.class); ProjectIteration it = jaxbUnmarshal(entityString, ProjectIteration.class); - assertThat(it.getId(), is("new-iteration")); + assertThat(it.getId()).isEqualTo("new-iteration"); } }.run(); diff --git a/server/zanata-war/src/test/java/org/zanata/rest/compat/ProjectRawCompatibilityITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/compat/ProjectRawCompatibilityITCase.java index 09fd9523cb..be9cc616cd 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/compat/ProjectRawCompatibilityITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/compat/ProjectRawCompatibilityITCase.java @@ -43,9 +43,7 @@ import org.zanata.apicompat.rest.dto.Project; import org.zanata.rest.ResourceRequest; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.provider.DBUnitProvider.DataSetOperation; import static org.zanata.util.RawRestTestUtils.assertHeaderPresent; import static org.zanata.util.RawRestTestUtils.assertJaxbUnmarshal; @@ -95,7 +93,7 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { protected void onResponse(Response response) throws IOException { // Ok - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); assertHeaderPresent(response, HttpHeaders.ETAG); } }.run(); @@ -116,16 +114,16 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { // Ok - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, Project.class); Project project = jsonUnmarshal(entityString, Project.class); // Assert correct parsing of all properties - assertThat(project.getId(), is("sample-project")); - assertThat(project.getName(), is("Sample Project")); - assertThat(project.getDescription(), is("An example Project")); - assertThat(project.getIterations().size(), is(3)); + assertThat(project.getId()).isEqualTo("sample-project"); + assertThat(project.getName()).isEqualTo("Sample Project"); + assertThat(project.getDescription()).isEqualTo("An example Project"); + assertThat(project.getIterations().size()).isEqualTo(3); } }.run(); } @@ -144,7 +142,7 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { // Ok - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); List projects = jsonParse(response); Project sampleProject = null; @@ -156,10 +154,10 @@ protected void onResponse(Response response) { } // Assertions on individual project - assertThat(sampleProject, notNullValue()); - assertThat(sampleProject.getId(), is("sample-project")); - assertThat(sampleProject.getName(), is("Sample Project")); - assertThat(sampleProject.getLinks().size(), is(1)); + assertThat(sampleProject).isNotNull(); + assertThat(sampleProject.getId()).isEqualTo("sample-project"); + assertThat(sampleProject.getName()).isEqualTo("Sample Project"); + assertThat(sampleProject.getLinks().size()).isEqualTo(1); } }.run(); } @@ -180,7 +178,7 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { // Ok - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, Projects.class); Projects projects = jaxbUnmarshal(entityString, Projects.class); @@ -194,10 +192,10 @@ protected void onResponse(Response response) { } // Assertions on individual project - assertThat(sampleProject, notNullValue()); - assertThat(sampleProject.getId(), is("sample-project")); - assertThat(sampleProject.getName(), is("Sample Project")); - assertThat(sampleProject.getLinks().size(), is(1)); + assertThat(sampleProject).isNotNull(); + assertThat(sampleProject.getId()).isEqualTo("sample-project"); + assertThat(sampleProject.getName()).isEqualTo("Sample Project"); + assertThat(sampleProject.getLinks().size()).isEqualTo(1); } }.run(); } @@ -230,9 +228,9 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), - // 201 - is(Status.CREATED.getStatusCode())); + // 201 + assertThat(response.getStatus()) + .isEqualTo(Status.CREATED.getStatusCode()); } }.run(); } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/compat/StatisticsCompatibilityITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/compat/StatisticsCompatibilityITCase.java index 3b2720497d..8608105526 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/compat/StatisticsCompatibilityITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/compat/StatisticsCompatibilityITCase.java @@ -29,11 +29,7 @@ import org.zanata.apicompat.rest.service.StatisticsResource; import org.zanata.provider.DBUnitProvider; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; +import static org.assertj.core.api.Assertions.assertThat; /** * @author Carlos Munoz targets = getTransResourceFromResponse(getResponse).getTextFlowTargets(); for (TextFlowTarget target : targets) { - assertThat(target.getState(), is(ContentState.New)); + assertThat(target.getState()).isEqualTo(ContentState.New); } } } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/compat/TranslationsRawCompatibilityITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/compat/TranslationsRawCompatibilityITCase.java index 000c0ea977..d350fd9092 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/compat/TranslationsRawCompatibilityITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/compat/TranslationsRawCompatibilityITCase.java @@ -47,10 +47,7 @@ import org.zanata.apicompat.rest.dto.resource.TranslationsResource; import org.zanata.rest.ResourceRequest; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.greaterThanOrEqualTo; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.provider.DBUnitProvider.DataSetOperation; import static org.zanata.util.RawRestTestUtils.assertJsonUnmarshal; import static org.zanata.util.RawRestTestUtils.jsonMarshal; @@ -103,29 +100,28 @@ protected void onResponse(Response response) { assertJsonUnmarshal(entityString, Resource.class); Resource resource = jsonUnmarshal(entityString, Resource.class); - assertThat(resource.getName(), is("my/path/document-2.txt")); - assertThat(resource.getType(), is(ResourceType.FILE)); - assertThat(resource.getLang(), is(LocaleId.EN_US)); + assertThat(resource.getName()).isEqualTo("my/path/document-2.txt"); + assertThat(resource.getType()).isEqualTo(ResourceType.FILE); + assertThat(resource.getLang()).isEqualTo(LocaleId.EN_US); // Make sure all Text Flows are present - assertThat(resource.getTextFlows().size(), - greaterThanOrEqualTo(3)); + assertThat(resource.getTextFlows().size()).isGreaterThanOrEqualTo(3); // Evaluate individual text flows TextFlow txtFlow = resource.getTextFlows().get(0); - assertThat(txtFlow.getId(), is("tf2")); - assertThat(txtFlow.getRevision(), is(1)); - assertThat(txtFlow.getContents().get(0), is("mssgId1")); + assertThat(txtFlow.getId()).isEqualTo("tf2"); + assertThat(txtFlow.getRevision()).isEqualTo(1); + assertThat(txtFlow.getContents().get(0)).isEqualTo("mssgId1"); txtFlow = resource.getTextFlows().get(1); - assertThat(txtFlow.getId(), is("tf3")); - assertThat(txtFlow.getRevision(), is(1)); - assertThat(txtFlow.getContents().get(0), is("mssgId2")); + assertThat(txtFlow.getId()).isEqualTo("tf3"); + assertThat(txtFlow.getRevision()).isEqualTo(1); + assertThat(txtFlow.getContents().get(0)).isEqualTo("mssgId2"); txtFlow = resource.getTextFlows().get(2); - assertThat(txtFlow.getId(), is("tf4")); - assertThat(txtFlow.getRevision(), is(1)); - assertThat(txtFlow.getContents().get(0), is("mssgId3")); + assertThat(txtFlow.getId()).isEqualTo("tf4"); + assertThat(txtFlow.getRevision()).isEqualTo(1); + assertThat(txtFlow.getContents().get(0)).isEqualTo("mssgId3"); } }.run(); } @@ -165,8 +161,8 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { // 201 - assertThat(response.getStatus(), - is(Status.CREATED.getStatusCode())); + assertThat(response.getStatus()) + .isEqualTo(Status.CREATED.getStatusCode()); } }.run(); @@ -177,40 +173,38 @@ protected void onResponse(Response response) { PoHeader.ID + ";" + SimpleComment.ID)); // 200 - assertThat(resourceResponse.getStatus(), is(Status.OK.getStatusCode())); + assertThat(resourceResponse.getStatus()).isEqualTo(Status.OK.getStatusCode()); Resource createdResource = getResourceFromResponse(resourceResponse); - assertThat(createdResource.getName(), is(res.getName())); - assertThat(createdResource.getType(), is(res.getType())); - assertThat(createdResource.getContentType(), is(res.getContentType())); - assertThat(createdResource.getLang(), is(res.getLang())); + assertThat(createdResource.getName()).isEqualTo(res.getName()); + assertThat(createdResource.getType()).isEqualTo(res.getType()); + assertThat(createdResource.getContentType()).isEqualTo(res.getContentType()); + assertThat(createdResource.getLang()).isEqualTo(res.getLang()); // Created, so revision 1 - assertThat(createdResource.getRevision(), is(1)); + assertThat(createdResource.getRevision()).isEqualTo(1); // Extensions - assertThat(createdResource.getExtensions(true).size(), - greaterThanOrEqualTo(1)); + assertThat(createdResource.getExtensions(true).size()).isGreaterThanOrEqualTo(1); assertThat( createdResource.getExtensions(true).findByType(PoHeader.class) - .getComment(), is("This is a PO Header")); + .getComment()).isEqualTo("This is a PO Header"); // Text Flow - assertThat(createdResource.getTextFlows().size(), is(1)); + assertThat(createdResource.getTextFlows().size()).isEqualTo(1); TextFlow createdTf = createdResource.getTextFlows().get(0); - assertThat(createdTf.getContents(), is(tf1.getContents())); - assertThat(createdTf.getId(), is(tf1.getId())); - assertThat(createdTf.getLang(), is(tf1.getLang())); + assertThat(createdTf.getContents()).isEqualTo(tf1.getContents()); + assertThat(createdTf.getId()).isEqualTo(tf1.getId()); + assertThat(createdTf.getLang()).isEqualTo(tf1.getLang()); // Create, so revision 1 - assertThat(createdTf.getRevision(), is(1)); + assertThat(createdTf.getRevision()).isEqualTo(1); // Text Flow extensions - assertThat(createdTf.getExtensions(true).size(), is(1)); - assertThat( - createdTf.getExtensions(true) - .findOrAddByType(SimpleComment.class).getValue(), - is("This is one comment")); + assertThat(createdTf.getExtensions(true).size()).isEqualTo(1); + assertThat(createdTf.getExtensions(true) + .findOrAddByType(SimpleComment.class).getValue()) + .isEqualTo("This is one comment"); } @Test @@ -249,8 +243,8 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { // 201 - assertThat(response.getStatus(), - is(Status.CREATED.getStatusCode())); + assertThat(response.getStatus()) + .isEqualTo(Status.CREATED.getStatusCode()); } }.run(); @@ -261,36 +255,34 @@ protected void onResponse(Response response) { PoHeader.ID + ";" + SimpleComment.ID)); Resource createdResource = getResourceFromResponse(resourceResponse); - assertThat(createdResource.getName(), is(res.getName())); - assertThat(createdResource.getType(), is(res.getType())); - assertThat(createdResource.getContentType(), is(res.getContentType())); - assertThat(createdResource.getLang(), is(res.getLang())); + assertThat(createdResource.getName()).isEqualTo(res.getName()); + assertThat(createdResource.getType()).isEqualTo(res.getType()); + assertThat(createdResource.getContentType()).isEqualTo(res.getContentType()); + assertThat(createdResource.getLang()).isEqualTo(res.getLang()); // Created, so revision 1 - assertThat(createdResource.getRevision(), is(1)); + assertThat(createdResource.getRevision()).isEqualTo(1); // Extensions - assertThat(createdResource.getExtensions(true).size(), - greaterThanOrEqualTo(1)); + assertThat(createdResource.getExtensions(true).size()).isGreaterThanOrEqualTo(1); assertThat( createdResource.getExtensions(true).findByType(PoHeader.class) - .getComment(), is("This is a PO Header")); + .getComment()).isEqualTo("This is a PO Header"); // Text Flow - assertThat(createdResource.getTextFlows().size(), is(1)); + assertThat(createdResource.getTextFlows().size()).isEqualTo(1); TextFlow createdTf = createdResource.getTextFlows().get(0); - assertThat(createdTf.getContents(), is(tf1.getContents())); - assertThat(createdTf.getId(), is(tf1.getId())); - assertThat(createdTf.getLang(), is(tf1.getLang())); + assertThat(createdTf.getContents()).isEqualTo(tf1.getContents()); + assertThat(createdTf.getId()).isEqualTo(tf1.getId()); + assertThat(createdTf.getLang()).isEqualTo(tf1.getLang()); // Create, so revision 1 - assertThat(createdTf.getRevision(), is(1)); + assertThat(createdTf.getRevision()).isEqualTo(1); // Text Flow extensions - assertThat(createdTf.getExtensions(true).size(), is(1)); - assertThat( - createdTf.getExtensions(true) - .findOrAddByType(SimpleComment.class).getValue(), - is("This is one comment")); + assertThat(createdTf.getExtensions(true).size()).isEqualTo(1); + assertThat(createdTf.getExtensions(true) + .findOrAddByType(SimpleComment.class).getValue()) + .isEqualTo("This is one comment"); } @Test @@ -308,16 +300,16 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { // 200 - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); + assertThat(response.getStatus()).isEqualTo(Status.OK.getStatusCode()); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, ResourceMeta.class); ResourceMeta resMeta = jsonUnmarshal(entityString, ResourceMeta.class); - assertThat(resMeta.getName(), is("my/path/document-2.txt")); - assertThat(resMeta.getType(), is(ResourceType.FILE)); - assertThat(resMeta.getLang(), is(LocaleId.EN_US)); - assertThat(resMeta.getContentType(), is(ContentType.TextPlain)); + assertThat(resMeta.getName()).isEqualTo("my/path/document-2.txt"); + assertThat(resMeta.getType()).isEqualTo(ResourceType.FILE); + assertThat(resMeta.getLang()).isEqualTo(LocaleId.EN_US); + assertThat(resMeta.getContentType()).isEqualTo(ContentType.TextPlain); } }.run(); } @@ -354,8 +346,8 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { // 200 - assertThat(response.getStatus(), - is(Status.OK.getStatusCode())); + assertThat(response.getStatus()) + .isEqualTo(Status.OK.getStatusCode()); } }.run(); @@ -366,13 +358,13 @@ protected void onResponse(Response response) { ResourceMeta newResMeta = getResourceMetaFromResponse(getResponse); // 200 - assertThat(getResponse.getStatus(), is(Status.OK.getStatusCode())); - assertThat(newResMeta.getName(), is(resMeta.getName())); - assertThat(newResMeta.getContentType(), is(resMeta.getContentType())); - assertThat(newResMeta.getLang(), is(resMeta.getLang())); - assertThat(newResMeta.getType(), is(resMeta.getType())); + assertThat(getResponse.getStatus()).isEqualTo(Status.OK.getStatusCode()); + assertThat(newResMeta.getName()).isEqualTo(resMeta.getName()); + assertThat(newResMeta.getContentType()).isEqualTo(resMeta.getContentType()); + assertThat(newResMeta.getLang()).isEqualTo(resMeta.getLang()); + assertThat(newResMeta.getType()).isEqualTo(resMeta.getType()); // Updated so higher revision - assertThat(newResMeta.getRevision(), greaterThan(1)); + assertThat(newResMeta.getRevision()).isGreaterThan(1); } @Test @@ -391,53 +383,52 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { // 200 - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); + assertThat(response.getStatus()).isEqualTo(Status.OK.getStatusCode()); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, TranslationsResource.class); TranslationsResource transRes = jsonUnmarshal(entityString, TranslationsResource.class); - assertThat(transRes.getTextFlowTargets().size(), - greaterThanOrEqualTo(3)); + assertThat(transRes.getTextFlowTargets().size()).isGreaterThanOrEqualTo(3); // First Text Flow Target TextFlowTarget tft1 = transRes.getTextFlowTargets().get(0); - assertThat(tft1.getResId(), is("tf2")); - assertThat(tft1.getState(), is(ContentState.NeedReview)); - assertThat(tft1.getContents().get(0), is("mssgTrans1")); + assertThat(tft1.getResId()).isEqualTo("tf2"); + assertThat(tft1.getState()).isEqualTo(ContentState.NeedReview); + assertThat(tft1.getContents().get(0)).isEqualTo("mssgTrans1"); assertThat( tft1.getExtensions(true) - .findByType(SimpleComment.class).getValue(), - is("Text Flow Target Comment 1")); - assertThat(tft1.getTranslator().getName(), is("Sample User")); - assertThat(tft1.getTranslator().getEmail(), - is("user1@localhost")); + .findByType(SimpleComment.class).getValue()).isEqualTo("Text Flow Target Comment 1"); + assertThat(tft1.getTranslator().getName()).isEqualTo("Sample User"); + assertThat(tft1.getTranslator().getEmail()).isEqualTo("user1@localhost"); // Second Text Flow Target TextFlowTarget tft2 = transRes.getTextFlowTargets().get(1); - assertThat(tft2.getResId(), is("tf3")); - assertThat(tft2.getState(), is(ContentState.NeedReview)); - assertThat(tft2.getContents().get(0), is("mssgTrans2")); + assertThat(tft2.getResId()).isEqualTo("tf3"); + assertThat(tft2.getState()).isEqualTo(ContentState.NeedReview); + assertThat(tft2.getContents().get(0)).isEqualTo("mssgTrans2"); assertThat( - tft2.getExtensions(true) - .findByType(SimpleComment.class).getValue(), - is("Text Flow Target Comment 2")); - assertThat(tft2.getTranslator().getName(), is("Sample User")); - assertThat(tft2.getTranslator().getEmail(), - is("user1@localhost")); + tft2.getExtensions(true).findByType(SimpleComment.class) + .getValue()) + .isEqualTo("Text Flow Target Comment 2"); + assertThat(tft2.getTranslator().getName()) + .isEqualTo("Sample User"); + assertThat(tft2.getTranslator().getEmail()) + .isEqualTo("user1@localhost"); // First Text Flow Target TextFlowTarget tft3 = transRes.getTextFlowTargets().get(2); - assertThat(tft3.getResId(), is("tf4")); - assertThat(tft3.getState(), is(ContentState.NeedReview)); - assertThat(tft3.getContents().get(0), is("mssgTrans3")); + assertThat(tft3.getResId()).isEqualTo("tf4"); + assertThat(tft3.getState()).isEqualTo(ContentState.NeedReview); + assertThat(tft3.getContents().get(0)).isEqualTo("mssgTrans3"); assertThat( tft3.getExtensions(true) - .findByType(SimpleComment.class).getValue(), - is("Text Flow Target Comment 3")); - assertThat(tft3.getTranslator().getName(), is("Sample User")); - assertThat(tft3.getTranslator().getEmail(), - is("user1@localhost")); + .findByType(SimpleComment.class).getValue()) + .isEqualTo("Text Flow Target Comment 3"); + assertThat(tft3.getTranslator().getName()) + .isEqualTo("Sample User"); + assertThat(tft3.getTranslator().getEmail()) + .isEqualTo("user1@localhost"); } }.run(); } @@ -455,9 +446,8 @@ LocaleId.EN_US, new StringSet(SimpleComment.ID), false, final TranslationsResource transRes = getTransResourceFromResponse(response); // 200 - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); - assertThat(transRes.getTextFlowTargets().size(), - greaterThanOrEqualTo(3)); + assertThat(response.getStatus()).isEqualTo(Status.OK.getStatusCode()); + assertThat(transRes.getTextFlowTargets().size()).isGreaterThanOrEqualTo(3); // Alter the translations transRes.getTextFlowTargets().get(0).setContents("Translated 1"); @@ -497,7 +487,7 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { // 200 - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); + assertThat(response.getStatus()).isEqualTo(Status.OK.getStatusCode()); } }.run(); @@ -509,33 +499,32 @@ protected void onResponse(Response response) { TranslationsResource updatedTransRes = getTransResourceFromResponse(response); // 200 - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); - assertThat(updatedTransRes.getTextFlowTargets().size(), - greaterThanOrEqualTo(3)); + assertThat(response.getStatus()).isEqualTo(Status.OK.getStatusCode()); + assertThat(updatedTransRes.getTextFlowTargets().size()).isGreaterThanOrEqualTo(3); // First Text Flow Target TextFlowTarget tft1 = updatedTransRes.getTextFlowTargets().get(0); - assertThat(tft1.getResId(), is("tf2")); - assertThat(tft1.getState(), is(ContentState.Approved)); - assertThat(tft1.getContents().get(0), is("Translated 1")); + assertThat(tft1.getResId()).isEqualTo("tf2"); + assertThat(tft1.getState()).isEqualTo(ContentState.Approved); + assertThat(tft1.getContents().get(0)).isEqualTo("Translated 1"); assertThat(tft1.getExtensions(true).findByType(SimpleComment.class) - .getValue(), is("Translated Comment 1")); + .getValue()).isEqualTo("Translated Comment 1"); // Second Text Flow Target TextFlowTarget tft2 = updatedTransRes.getTextFlowTargets().get(1); - assertThat(tft2.getResId(), is("tf3")); - assertThat(tft2.getState(), is(ContentState.Approved)); - assertThat(tft2.getContents().get(0), is("Translated 2")); + assertThat(tft2.getResId()).isEqualTo("tf3"); + assertThat(tft2.getState()).isEqualTo(ContentState.Approved); + assertThat(tft2.getContents().get(0)).isEqualTo("Translated 2"); assertThat(tft2.getExtensions(true).findByType(SimpleComment.class) - .getValue(), is("Translated Comment 2")); + .getValue()).isEqualTo("Translated Comment 2"); // First Text Flow Target TextFlowTarget tft3 = updatedTransRes.getTextFlowTargets().get(2); - assertThat(tft3.getResId(), is("tf4")); - assertThat(tft3.getState(), is(ContentState.Approved)); - assertThat(tft3.getContents().get(0), is("Translated 3")); + assertThat(tft3.getResId()).isEqualTo("tf4"); + assertThat(tft3.getState()).isEqualTo(ContentState.Approved); + assertThat(tft3.getContents().get(0)).isEqualTo("Translated 3"); assertThat(tft3.getExtensions(true).findByType(SimpleComment.class) - .getValue(), is("Translated Comment 3")); + .getValue()).isEqualTo("Translated Comment 3"); } } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/FileServiceTest.java b/server/zanata-war/src/test/java/org/zanata/rest/service/FileServiceTest.java index 87e6bfb913..02dcfb45a3 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/FileServiceTest.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/FileServiceTest.java @@ -58,9 +58,7 @@ import javax.persistence.EntityManager; import javax.ws.rs.core.Response; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.sameInstance; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; @@ -133,7 +131,7 @@ public void sourceUploadParamsHandledCorrectly() { when(sourceUploader.tryUploadSourceFile(eq(id), formCaptor.capture())) .thenReturn(okResponse); fileService.uploadSourceFile(PROJ_SLUG, VER_SLUG, DOC_ID, form); - assertThat(formCaptor.getValue(), is(sameInstance(form))); + assertThat(formCaptor.getValue()).isSameAs(form); } @Test @@ -143,7 +141,7 @@ public void sourceUploadResponseReturnedDirectly() { okResponse); response = fileService.uploadSourceFile(PROJ_SLUG, VER_SLUG, DOC_ID, form); - assertThat(response, is(sameInstance(okResponse))); + assertThat(response).isSameAs(okResponse); } @Test @@ -155,7 +153,7 @@ public void translationUploadParamsHandledCorrectly() { .thenReturn(okResponse); fileService.uploadTranslationFile(PROJ_SLUG, VER_SLUG, LOCALE, DOC_ID, MERGE, form); - assertThat(formCaptor.getValue(), is(sameInstance(form))); + assertThat(formCaptor.getValue()).isSameAs(form); } @Test @@ -166,6 +164,6 @@ public void translationUploadResponseReturnedDirectly() { response = fileService.uploadTranslationFile(PROJ_SLUG, VER_SLUG, LOCALE, DOC_ID, MERGE, form); - assertThat(response, is(sameInstance(okResponse))); + assertThat(response).isSameAs(okResponse); } } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/ResourceUtilsParamTest.java b/server/zanata-war/src/test/java/org/zanata/rest/service/ResourceUtilsParamTest.java index 1cdf10b0e1..85de5ae053 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/ResourceUtilsParamTest.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/ResourceUtilsParamTest.java @@ -1,8 +1,5 @@ package org.zanata.rest.service; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; - import java.util.Arrays; import javax.enterprise.inject.Produces; @@ -23,6 +20,8 @@ import org.zanata.test.CdiUnitRunnerWithParameters; import org.zanata.test.ParamTestCdiExtension; +import static org.assertj.core.api.Assertions.assertThat; + @RunWith(Parameterized.class) @UseParametersRunnerFactory(CdiUnitRunnerWithParameters.Factory.class) @InRequestScope @@ -56,13 +55,13 @@ public static Iterable urlPatterns() { @Test public void decodeDocIds() { - assertThat("Decoding " + encoded, resourceUtils.decodeDocId(encoded), - is(decoded)); + assertThat(resourceUtils.decodeDocId(encoded)).isEqualTo(decoded) + .as("Decoding " + encoded); } @Test public void encodeDocIds() { - assertThat("Encoding " + decoded, resourceUtils.encodeDocId(decoded), - is(encoded)); + assertThat(resourceUtils.encodeDocId(decoded)).isEqualTo(encoded) + .as("Encoding " + decoded); } } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/ResourceUtilsTest.java b/server/zanata-war/src/test/java/org/zanata/rest/service/ResourceUtilsTest.java index 0c43740988..addbc839bd 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/ResourceUtilsTest.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/ResourceUtilsTest.java @@ -36,9 +36,7 @@ import org.zanata.rest.dto.resource.TextFlow; import org.zanata.test.CdiUnitRunner; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -75,13 +73,13 @@ public void initializeRequestScope() { @Test public void mergeNoTextFlows() { - List from = new ArrayList(); + List from = new ArrayList<>(); HDocument to = new HDocument(); boolean changed = resourceUtils.transferFromTextFlows(from, to, - new HashSet(), 1); + new HashSet<>(), 1); - assertThat(changed, is(false)); + assertThat(changed).isFalse(); } @Test @@ -97,7 +95,7 @@ public void mergeTextFlowWithOneFromChange() { resourceUtils.transferFromTextFlows(from, to, new HashSet(), 1); - assertThat(changed, is(true)); + assertThat(changed).isTrue(); } @Test @@ -155,25 +153,24 @@ public void mergeChangedTextFlow() { Map targets = to.getAllTextFlows().get("id").getTargets(); newTarg = targets.get(newLocId); - assertThat(newTarg.getState(), is(ContentState.New)); - assertThat(newTarg.getVersionNum(), is(newTargVersionBefore)); - assertThat(newTarg.getTextFlowRevision(), is(originalTFRevision)); + assertThat(newTarg.getState()).isEqualTo(ContentState.New); + assertThat(newTarg.getVersionNum()).isEqualTo(newTargVersionBefore); + assertThat(newTarg.getTextFlowRevision()).isEqualTo(originalTFRevision); fuzzyTarg = targets.get(fuzzyLocId); - assertThat(fuzzyTarg.getState(), is(ContentState.NeedReview)); - assertThat(fuzzyTarg.getVersionNum(), is(fuzzyTargVersionBefore)); - assertThat(fuzzyTarg.getTextFlowRevision(), is(originalTFRevision)); + assertThat(fuzzyTarg.getState()).isEqualTo(ContentState.NeedReview); + assertThat(fuzzyTarg.getVersionNum()).isEqualTo(fuzzyTargVersionBefore); + assertThat(fuzzyTarg.getTextFlowRevision()).isEqualTo(originalTFRevision); apprTarg = targets.get(apprLocId); - assertThat( - "approved targets should be set to fuzzy when source content changes", - apprTarg.getState(), is(ContentState.NeedReview)); - assertThat(apprTarg.getVersionNum(), is(apprTargVersionBefore + 1)); + assertThat(apprTarg.getState()).isEqualTo(ContentState.NeedReview) + .as("approved targets should be set to fuzzy when source content changes"); + assertThat(apprTarg.getVersionNum()).isEqualTo(apprTargVersionBefore + 1); // Note: TFTRevision should be updated when target content or state is // changed in editor, not here. - assertThat(apprTarg.getTextFlowRevision(), is(originalTFRevision)); + assertThat(apprTarg.getTextFlowRevision()).isEqualTo(originalTFRevision); - assertThat(changed, is(true)); + assertThat(changed).isTrue(); } @Test @@ -183,7 +180,7 @@ public void pushCommentInitialImport() { fromHeader.setComment(comment); HPoTargetHeader toHeader = new HPoTargetHeader(); resourceUtils.pushPoTargetComment(fromHeader, toHeader, MergeType.AUTO); - assertThat("", toHeader.getComment().getComment(), is(comment)); + assertThat(toHeader.getComment().getComment()).isEqualTo(comment); } @Test @@ -195,7 +192,7 @@ public void pushCommentSkip() { HPoTargetHeader toHeader = new HPoTargetHeader(); resourceUtils.pushPoTargetComment(fromHeader, toHeader, MergeType.IMPORT); - assertThat("", toHeader.getComment().getComment(), is(expectedComment)); + assertThat(toHeader.getComment().getComment()).isEqualTo(expectedComment); } @Test @@ -207,7 +204,7 @@ public void pushCommentMerge() { HPoTargetHeader toHeader = new HPoTargetHeader(); toHeader.setComment(new HSimpleComment("initial comment\nBob")); resourceUtils.pushPoTargetComment(fromHeader, toHeader, MergeType.AUTO); - assertThat("", toHeader.getComment().getComment(), is(expectedComment)); + assertThat(toHeader.getComment().getComment()).isEqualTo(expectedComment); } @Test @@ -220,7 +217,7 @@ public void pushCommentImport() { toHeader.setComment(new HSimpleComment("initial comment\nBob")); resourceUtils.pushPoTargetComment(fromHeader, toHeader, MergeType.IMPORT); - assertThat("", toHeader.getComment().getComment(), is(expectedComment)); + assertThat(toHeader.getComment().getComment()).isEqualTo(expectedComment); } @Test @@ -232,7 +229,7 @@ public void pullCommentEmpty() { List hTargets = Collections.emptyList(); resourceUtils.pullPoTargetComment(fromHeader, toHeader, hTargets); - assertThat("", toHeader.getComment(), is("")); + assertThat(toHeader.getComment()).isEqualTo(""); } @Test @@ -246,7 +243,7 @@ public void pullCommentInitial() { List hTargets = Collections.emptyList(); resourceUtils.pullPoTargetComment(fromHeader, toHeader, hTargets); - assertThat("", toHeader.getComment(), is(expectedComment)); + assertThat(toHeader.getComment()).isEqualTo(expectedComment); } @Test @@ -281,7 +278,7 @@ public void pullCommentWithCredits() { resourceUtils.pullPoTargetComment(fromHeader, toHeader, hTargets); - assertThat("", toHeader.getComment(), is(expectedComment)); + assertThat(toHeader.getComment()).isEqualTo(expectedComment); } @Test @@ -289,7 +286,7 @@ public void splitLinesSimple() { String s = "1\n2\n3"; List expected = Arrays.asList("1", "2", "3"); List lines = ResourceUtils.splitLines(s, null); - assertThat("", lines, is(expected)); + assertThat(lines).isEqualTo(expected); } @Test @@ -297,7 +294,7 @@ public void splitLinesEmpty() { String s = ""; List expected = Collections.emptyList(); List lines = ResourceUtils.splitLines(s, null); - assertThat("", lines, is(expected)); + assertThat(lines).isEqualTo(expected); } @Test @@ -305,7 +302,7 @@ public void splitLinesSkip() { String s = "1\n2 #zanata\n3"; List expected = Arrays.asList("1", "3"); List lines = ResourceUtils.splitLines(s, "#zanata"); - assertThat("", lines, is(expected)); + assertThat(lines).isEqualTo(expected); } @Test @@ -313,7 +310,7 @@ public void splitLinesSkipAll() { String s = "1 #zanata\n2 #zanata\n3 #zanata"; List expected = Collections.emptyList(); List lines = ResourceUtils.splitLines(s, "#zanata"); - assertThat("", lines, is(expected)); + assertThat(lines).isEqualTo(expected); } /** @@ -339,21 +336,21 @@ public void pluralFormsAlternateSeparators() { verify(mockLocaleDAO).findByLocaleId(LocaleId.ES); - assertThat(esPluralForm, notNullValue()); + assertThat(esPluralForm).isNotNull(); // Alternate forms that should match the "es" plurals // "es_ES" - assertThat(resourceUtils.getPluralForms(new LocaleId("es-ES")), - is(esPluralForm)); + assertThat(resourceUtils.getPluralForms(new LocaleId("es-ES"))) + .isEqualTo(esPluralForm); // "es.ES" - assertThat(resourceUtils.getPluralForms(new LocaleId("es.ES")), - is(esPluralForm)); + assertThat(resourceUtils.getPluralForms(new LocaleId("es.ES"))) + .isEqualTo(esPluralForm); // "es@ES" - assertThat(resourceUtils.getPluralForms(new LocaleId("es@ES")), - is(esPluralForm)); + assertThat(resourceUtils.getPluralForms(new LocaleId("es@ES"))) + .isEqualTo(esPluralForm); // "es.ES@Latin" - assertThat(resourceUtils.getPluralForms(new LocaleId("es.ES@Latin")), - is(esPluralForm)); + assertThat(resourceUtils.getPluralForms(new LocaleId("es.ES@Latin"))) + .isEqualTo(esPluralForm); } @Test @@ -370,7 +367,7 @@ public void pluralFormsTest() { //verify and assert verify(mockLocaleDAO).findByLocaleId(LocaleId.ES); - assertThat(pluralForms, is(testPluralForms)); + assertThat(pluralForms).isEqualTo(testPluralForms); } @Test @@ -385,31 +382,31 @@ public void pluralFormsTestUseDBEntryTest() { //verify and assert verify(mockLocaleDAO).findByLocaleId(LocaleId.ES); - assertThat(pluralForms, notNullValue()); + assertThat(pluralForms).isNotNull(); } @Test public void isValidPluralFormsTest() { String invalidPluralForms = "testPluralForms"; - assertThat(resourceUtils.isValidPluralForms(invalidPluralForms), is(false)); + assertThat(resourceUtils.isValidPluralForms(invalidPluralForms)).isFalse(); invalidPluralForms = "nplurals=notinteger"; - assertThat(resourceUtils.isValidPluralForms(invalidPluralForms), is(false)); + assertThat(resourceUtils.isValidPluralForms(invalidPluralForms)).isFalse(); invalidPluralForms = "nplurals=-1"; - assertThat(resourceUtils.isValidPluralForms(invalidPluralForms), is(false)); + assertThat(resourceUtils.isValidPluralForms(invalidPluralForms)).isFalse(); invalidPluralForms = "nplurals=" + ResourceUtils.MAX_TARGET_CONTENTS + 1; - assertThat(resourceUtils.isValidPluralForms(invalidPluralForms), is(false)); + assertThat(resourceUtils.isValidPluralForms(invalidPluralForms)).isFalse(); invalidPluralForms = "nplurals=0"; - assertThat(resourceUtils.isValidPluralForms(invalidPluralForms), is(false)); + assertThat(resourceUtils.isValidPluralForms(invalidPluralForms)).isFalse(); invalidPluralForms = "nplurals=1;plural=0"; - assertThat(resourceUtils.isValidPluralForms(invalidPluralForms), is(true)); + assertThat(resourceUtils.isValidPluralForms(invalidPluralForms)).isTrue(); invalidPluralForms = "nplurals=5; plural=10" + ResourceUtils.MAX_TARGET_CONTENTS; - assertThat(resourceUtils.isValidPluralForms(invalidPluralForms), is(true)); + assertThat(resourceUtils.isValidPluralForms(invalidPluralForms)).isTrue(); } } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/RestUtilsTest.java b/server/zanata-war/src/test/java/org/zanata/rest/service/RestUtilsTest.java index 2bd22e328a..a793efb509 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/RestUtilsTest.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/RestUtilsTest.java @@ -32,8 +32,7 @@ import org.zanata.rest.dto.resource.TranslationsResource; import org.zanata.test.CdiUnitRunner; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; @RunWith(CdiUnitRunner.class) public class RestUtilsTest extends ZanataTest { @@ -132,7 +131,7 @@ private void testRestUtilUnmarshall(T entity, MediaType.APPLICATION_XML_TYPE, new Headers<>()); log.info("got:" + DTOUtil.toXML(unmarshall)); - assertThat(DTOUtil.toXML(entity), is(testStr)); + assertThat(DTOUtil.toXML(entity)).isEqualTo(testStr); } finally { if (messageBody != null) { try { diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/TranslatorCreditTest.java b/server/zanata-war/src/test/java/org/zanata/rest/service/TranslatorCreditTest.java index 77a68512fd..4daf271dc3 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/TranslatorCreditTest.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/TranslatorCreditTest.java @@ -2,12 +2,11 @@ import org.junit.Test; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; - import java.util.Set; import java.util.TreeSet; +import static org.assertj.core.api.Assertions.assertThat; + public class TranslatorCreditTest { protected TranslatorCredit getAnne2011() { @@ -37,7 +36,7 @@ protected TranslatorCredit getBob2010() { @Test public void testToString() { TranslatorCredit cred = getAnne2011(); - assertThat(cred.toString(), is("Anne , 2011.")); + assertThat(cred.toString()).isEqualTo("Anne , 2011."); } @Test @@ -47,9 +46,9 @@ public void testSort() throws Exception { set.add(getAnne2011()); set.add(getAnne2012()); set.add(getBob2010()); - assertThat(set.toString(), is("[Bob , 2010., " + assertThat(set.toString()).isEqualTo("[Bob , 2010., " + "Anne , 2011., " - + "Anne , 2012.]")); + + "Anne , 2012.]"); } } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AccountRawRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AccountRawRestITCase.java index 45635f5474..a05c0dc352 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AccountRawRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AccountRawRestITCase.java @@ -35,8 +35,7 @@ import org.zanata.rest.ResourceRequest; import org.zanata.rest.dto.Account; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.provider.DBUnitProvider.DataSetOperation; import static org.zanata.util.RawRestTestUtils.assertJaxbUnmarshal; import static org.zanata.util.RawRestTestUtils.assertJsonUnmarshal; @@ -66,8 +65,7 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), - is(Status.NOT_FOUND.getStatusCode())); + assertThat(response.getStatus()).isEqualTo(Status.NOT_FOUND.getStatusCode()); } }.run(); } @@ -86,19 +84,17 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, Account.class); Account account = jaxbUnmarshal(entityString, Account.class); - assertThat(account.getUsername(), is("admin")); - assertThat(account.getPasswordHash(), - is("Eyox7xbNQ09MkIfRyH+rjg==")); - assertThat(account.getEmail(), is("root@localhost")); - assertThat(account.getApiKey(), - is("b6d7044e9ee3b2447c28fb7c50d86d98")); + assertThat(account.getUsername()).isEqualTo("admin"); + assertThat(account.getPasswordHash()).isEqualTo("Eyox7xbNQ09MkIfRyH+rjg=="); + assertThat(account.getEmail()).isEqualTo("root@localhost"); + assertThat(account.getApiKey()).isEqualTo("b6d7044e9ee3b2447c28fb7c50d86d98"); // 1 role - assertThat(account.getRoles().size(), is(1)); + assertThat(account.getRoles().size()).isEqualTo(1); } }.run(); } @@ -117,19 +113,17 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, Account.class); Account account = jsonUnmarshal(entityString, Account.class); - assertThat(account.getUsername(), is("admin")); - assertThat(account.getPasswordHash(), - is("Eyox7xbNQ09MkIfRyH+rjg==")); - assertThat(account.getEmail(), is("root@localhost")); - assertThat(account.getApiKey(), - is("b6d7044e9ee3b2447c28fb7c50d86d98")); + assertThat(account.getUsername()).isEqualTo("admin"); + assertThat(account.getPasswordHash()).isEqualTo("Eyox7xbNQ09MkIfRyH+rjg=="); + assertThat(account.getEmail()).isEqualTo("root@localhost"); + assertThat(account.getApiKey()).isEqualTo("b6d7044e9ee3b2447c28fb7c50d86d98"); // 1 role - assertThat(account.getRoles().size(), is(1)); + assertThat(account.getRoles().size()).isEqualTo(1); } }.run(); } @@ -159,8 +153,7 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), - is(Status.CREATED.getStatusCode())); + assertThat(response.getStatus()).isEqualTo(Status.CREATED.getStatusCode()); } }.run(); } @@ -191,8 +184,7 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), - is(Status.CREATED.getStatusCode())); + assertThat(response.getStatus()).isEqualTo(Status.CREATED.getStatusCode()); } }.run(); } @@ -221,8 +213,7 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), - is(Status.UNAUTHORIZED.getStatusCode())); + assertThat(response.getStatus()).isEqualTo(Status.UNAUTHORIZED.getStatusCode()); } }.run(); } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AnonymousUserRawRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AnonymousUserRawRestITCase.java index 9a37c2467b..4337f43d68 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AnonymousUserRawRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AnonymousUserRawRestITCase.java @@ -24,9 +24,7 @@ import java.util.HashMap; import java.util.Map; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.provider.DBUnitProvider.DataSetOperation; import static org.zanata.util.RawRestTestUtils.jaxbMarhsal; @@ -82,9 +80,8 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - - assertThat(response.getStatus(), - is(Status.UNAUTHORIZED.getStatusCode())); + assertThat(response.getStatus()) + .isEqualTo(Status.UNAUTHORIZED.getStatusCode()); } }.run(); } @@ -102,8 +99,8 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), - is(Status.OK.getStatusCode())); + assertThat(response.getStatus()) + .isEqualTo(Status.OK.getStatusCode()); } }.run(); } @@ -132,7 +129,7 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), greaterThan(200)); + assertThat(response.getStatus()).isGreaterThan(200); } }.run(); new ResourceRequest(getRestEndpointUrl("/projects"), "GET") { @@ -144,8 +141,8 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), - is(Status.UNAUTHORIZED.getStatusCode())); + assertThat(response.getStatus()) + .isEqualTo(Status.UNAUTHORIZED.getStatusCode()); } }.run(); } @@ -174,7 +171,7 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), greaterThan(200)); + assertThat(response.getStatus()).isGreaterThan(200); } }.run(); @@ -187,8 +184,8 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), - is(Status.OK.getStatusCode())); + assertThat(response.getStatus()) + .isEqualTo(Status.OK.getStatusCode()); } }.run(); } @@ -217,9 +214,8 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - - assertThat(response.getStatus(), - is(Status.UNAUTHORIZED.getStatusCode())); + assertThat(response.getStatus()) + .isEqualTo(Status.UNAUTHORIZED.getStatusCode()); } }.run(); } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AsyncProcessRawRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AsyncProcessRawRestITCase.java index d107651517..8a1712519e 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AsyncProcessRawRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AsyncProcessRawRestITCase.java @@ -20,8 +20,7 @@ */ package org.zanata.rest.service.raw; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.provider.DBUnitProvider.DataSetOperation; import javax.ws.rs.client.Invocation; @@ -56,7 +55,7 @@ public void notAdminCanNotGetAllProcessStatuses() throws Exception { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(403)); + assertThat(response.getStatus()).isEqualTo(403); } }.run(); } @@ -74,7 +73,7 @@ public void adminCanGetAllProcessStatuses() throws Exception { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); } }.run(); } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AsyncResourceRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AsyncResourceRestITCase.java index 7e13f4cfa0..2f6b1046c6 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AsyncResourceRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/AsyncResourceRestITCase.java @@ -3,10 +3,7 @@ import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicReference; import static com.jayway.awaitility.Awaitility.waitAtMost; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.util.RawRestTestUtils.assertJaxbUnmarshal; import static org.zanata.util.RawRestTestUtils.jaxbMarhsal; import static org.zanata.util.RawRestTestUtils.jaxbUnmarshal; @@ -99,13 +96,13 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, ProcessStatus.class); ProcessStatus status = jaxbUnmarshal(entityString, ProcessStatus.class); - assertThat(status.getUrl(), is(notNullValue())); + assertThat(status.getUrl()).isNotNull(); processId.set(status.getUrl()); } }.run(); @@ -127,7 +124,7 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); Resource get = jaxbUnmarshal(entityString, Resource.class); Resource base = resourceTestFactory.getTextFlowTest(); @@ -135,7 +132,7 @@ protected void onResponse(Response response) { ResourceTestUtil.clearRevs(get); log.debug("expect:" + base.toString()); log.debug("actual:" + get.toString()); - assertThat(get.toString(), is(base.toString())); + assertThat(get.toString()).isEqualTo(base.toString()); } }.run(); } @@ -169,13 +166,13 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, ProcessStatus.class); ProcessStatus status = jaxbUnmarshal(entityString, ProcessStatus.class); - assertThat(status.getUrl(), is(notNullValue())); + assertThat(status.getUrl()).isNotNull(); processId.set(status.getUrl()); } }.run(); @@ -197,7 +194,7 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); Resource get = jaxbUnmarshal(entityString, Resource.class); Resource base = resourceTestFactory.getTextFlowTest(); @@ -205,7 +202,7 @@ protected void onResponse(Response response) { ResourceTestUtil.clearRevs(get); log.debug("expect:" + base.toString()); log.debug("actual:" + get.toString()); - assertThat(get.toString(), is(base.toString())); + assertThat(get.toString()).isEqualTo(base.toString()); } }.run(); } @@ -241,12 +238,12 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, ProcessStatus.class); ProcessStatus status = jaxbUnmarshal(entityString, ProcessStatus.class); - assertThat(status.getUrl(), is(notNullValue())); + assertThat(status.getUrl()).isNotNull(); processId.set(status.getUrl()); } }.run(); @@ -286,12 +283,12 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, ProcessStatus.class); ProcessStatus status = jaxbUnmarshal(entityString, ProcessStatus.class); - assertThat(status.getUrl(), is(notNullValue())); + assertThat(status.getUrl()).isNotNull(); processId.set(status.getUrl()); } }.run(); @@ -316,13 +313,13 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, ProcessStatus.class); ProcessStatus status = jaxbUnmarshal(entityString, ProcessStatus.class); - assertThat(status.getStatusCode(), equalTo( - ProcessStatus.ProcessStatusCode.Finished)); + assertThat(status.getStatusCode()).isEqualTo( + ProcessStatus.ProcessStatusCode.Finished); } }.run(); return true; diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/FileRawRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/FileRawRestITCase.java index 26034674db..70afaf40cf 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/FileRawRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/FileRawRestITCase.java @@ -37,9 +37,7 @@ import org.zanata.RestTest; import org.zanata.rest.ResourceRequest; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.provider.DBUnitProvider.DataSetOperation; import static org.zanata.util.RawRestTestUtils.assertHeaderValue; @@ -77,7 +75,7 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { // Ok - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); assertHeaderValue(response, "Content-Disposition", "attachment; filename=\"document.txt.po\""); assertHeaderValue(response, HttpHeaders.CONTENT_TYPE, @@ -108,7 +106,7 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { // Ok - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); assertHeaderValue(response, "Content-Disposition", "attachment; filename=\"document-2.txt.po\""); assertHeaderValue(response, HttpHeaders.CONTENT_TYPE, @@ -133,20 +131,11 @@ private static void assertPoFileCorrect(String poFileContents) { if (message.isHeader()) { // assert that expected headers are present (with values if // needed) - assertThat(message.getMsgstr(), containsString("MIME-Version:")); - assertThat(message.getMsgstr(), containsString("Content-Type:")); - assertThat(message.getMsgstr(), - containsString("Content-Transfer-Encoding:")); - assertThat(message.getMsgstr(), - containsString("Last-Translator:")); - assertThat(message.getMsgstr(), - containsString("PO-Revision-Date:")); - assertThat(message.getMsgstr(), - containsString("Language-Team:")); - // Generator is Zanata - assertThat(message.getMsgstr(), - containsString("X-Generator: Zanata")); - assertThat(message.getMsgstr(), containsString("Plural-Forms:")); + assertThat(message.getMsgstr()) + .contains("MIME-Version:", "Content-Type:", + "Content-Transfer-Encoding:", + "Last-Translator:", "PO-Revision-Date:", + "X-Generator: Zanata", "Plural-Forms:"); } } } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectIterationRawRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectIterationRawRestITCase.java index 3c82e23fdd..0be399ea54 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectIterationRawRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectIterationRawRestITCase.java @@ -35,8 +35,7 @@ import org.zanata.rest.ResourceRequest; import org.zanata.rest.dto.ProjectIteration; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.provider.DBUnitProvider.DataSetOperation; import static org.zanata.util.RawRestTestUtils.assertHeaderPresent; import static org.zanata.util.RawRestTestUtils.assertJaxbUnmarshal; @@ -73,7 +72,7 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { // OK - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); assertHeaderPresent(response, HttpHeaders.ETAG); } }.run(); @@ -95,14 +94,14 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { // OK - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, ProjectIteration.class); ProjectIteration iteration = jaxbUnmarshal(entityString, ProjectIteration.class); - assertThat(iteration.getId(), is("1.0")); - assertThat(iteration.getStatus(), is(EntityStatus.ACTIVE)); + assertThat(iteration.getId()).isEqualTo("1.0"); + assertThat(iteration.getStatus()).isEqualTo(EntityStatus.ACTIVE); } }.run(); } @@ -123,13 +122,13 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { // OK - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, ProjectIteration.class); ProjectIteration iteration = jsonUnmarshal(entityString, ProjectIteration.class); - assertThat(iteration.getId(), is("1.0")); - assertThat(iteration.getStatus(), is(EntityStatus.ACTIVE)); + assertThat(iteration.getId()).isEqualTo("1.0"); + assertThat(iteration.getStatus()).isEqualTo(EntityStatus.ACTIVE); } }.run(); } @@ -150,8 +149,8 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { // Iteration not found because project is obsolete - assertThat(response.getStatus(), - is(Response.Status.NOT_FOUND.getStatusCode())); + assertThat(response.getStatus()) + .isEqualTo(Response.Status.NOT_FOUND.getStatusCode()); } }.run(); } @@ -172,8 +171,8 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { // 200 retired projects are readable - assertThat(response.getStatus(), - is(Response.Status.OK.getStatusCode())); + assertThat(response.getStatus()) + .isEqualTo(Response.Status.OK.getStatusCode()); } }.run(); } @@ -193,8 +192,8 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), - is(Response.Status.NOT_FOUND.getStatusCode())); + assertThat(response.getStatus()) + .isEqualTo(Response.Status.NOT_FOUND.getStatusCode()); } }.run(); } @@ -214,9 +213,9 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), + assertThat(response.getStatus()) // 404 - is(Response.Status.NOT_FOUND.getStatusCode())); + .isEqualTo(Response.Status.NOT_FOUND.getStatusCode()); } }.run(); } @@ -248,7 +247,7 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { // Created - assertThat(response.getStatus(), is(201)); + assertThat(response.getStatus()).isEqualTo(201); } }.run(); } @@ -280,7 +279,7 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(404)); + assertThat(response.getStatus()).isEqualTo(404); } }.run(); } @@ -311,7 +310,7 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); } }.run(); } @@ -343,7 +342,7 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { // Created - assertThat(response.getStatus(), is(201)); + assertThat(response.getStatus()).isEqualTo(201); } }.run(); } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectRawRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectRawRestITCase.java index aee042ee76..12c26b21d6 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectRawRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectRawRestITCase.java @@ -37,10 +37,7 @@ import org.zanata.rest.dto.Project; import org.zanata.rest.dto.ProjectIteration; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.provider.DBUnitProvider.DataSetOperation; import static org.zanata.util.RawRestTestUtils.assertHeaderPresent; import static org.zanata.util.RawRestTestUtils.assertJaxbUnmarshal; @@ -83,7 +80,7 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { // OK - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); assertHeaderPresent(response, HttpHeaders.ETAG); } }.run(); @@ -104,28 +101,28 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { // OK - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, Project.class); Project project = jaxbUnmarshal(entityString, Project.class); - assertThat(project.getId(), is("sample-project")); - assertThat(project.getDescription(), is("An example Project")); - assertThat(project.getStatus(), is(EntityStatus.ACTIVE)); - assertThat(project.getName(), is("Sample Project")); + assertThat(project.getId()).isEqualTo("sample-project"); + assertThat(project.getDescription()).isEqualTo("An example Project"); + assertThat(project.getStatus()).isEqualTo(EntityStatus.ACTIVE); + assertThat(project.getName()).isEqualTo("Sample Project"); // assertThat(project.getType(), // is(ProjectType.IterationProject)); - assertThat(project.getIterations().size(), is(3)); + assertThat(project.getIterations().size()).isEqualTo(3); // Iteration 1 ProjectIteration iteration = project.getIterations().get(0); - assertThat(iteration.getId(), is("1.0")); - assertThat(iteration.getStatus(), is(EntityStatus.ACTIVE)); + assertThat(iteration.getId()).isEqualTo("1.0"); + assertThat(iteration.getStatus()).isEqualTo(EntityStatus.ACTIVE); // Iteration 2 iteration = project.getIterations().get(1); - assertThat(iteration.getId(), is("1.1")); - assertThat(iteration.getStatus(), is(EntityStatus.ACTIVE)); + assertThat(iteration.getId()).isEqualTo("1.1"); + assertThat(iteration.getStatus()).isEqualTo(EntityStatus.ACTIVE); } }.run(); } @@ -144,7 +141,7 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(404)); + assertThat(response.getStatus()).isEqualTo(404); } }.run(); } @@ -164,7 +161,7 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { // Obsolete projects are not found - assertThat(response.getStatus(), is(404)); + assertThat(response.getStatus()).isEqualTo(404); } }.run(); } @@ -184,7 +181,7 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { // Retired projects can be read - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); } }.run(); } @@ -204,28 +201,28 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { // OK - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, Project.class); Project project = jsonUnmarshal(entityString, Project.class); - assertThat(project.getId(), is("sample-project")); - assertThat(project.getDescription(), is("An example Project")); - assertThat(project.getStatus(), is(EntityStatus.ACTIVE)); - assertThat(project.getName(), is("Sample Project")); + assertThat(project.getId()).isEqualTo("sample-project"); + assertThat(project.getDescription()).isEqualTo("An example Project"); + assertThat(project.getStatus()).isEqualTo(EntityStatus.ACTIVE); + assertThat(project.getName()).isEqualTo("Sample Project"); // assertThat(project.getType(), // is(ProjectType.IterationProject)); - assertThat(project.getIterations().size(), is(3)); + assertThat(project.getIterations().size()).isEqualTo(3); // Iteration 1 ProjectIteration iteration = project.getIterations().get(0); - assertThat(iteration.getId(), is("1.0")); - assertThat(iteration.getStatus(), is(EntityStatus.ACTIVE)); + assertThat(iteration.getId()).isEqualTo("1.0"); + assertThat(iteration.getStatus()).isEqualTo(EntityStatus.ACTIVE); // Iteration 2 iteration = project.getIterations().get(1); - assertThat(iteration.getId(), is("1.1")); - assertThat(iteration.getStatus(), is(EntityStatus.ACTIVE)); + assertThat(iteration.getId()).isEqualTo("1.1"); + assertThat(iteration.getStatus()).isEqualTo(EntityStatus.ACTIVE); } }.run(); } @@ -260,7 +257,7 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { // Created - assertThat(response.getStatus(), is(201)); + assertThat(response.getStatus()).isEqualTo(201); } }.run(); } @@ -293,7 +290,7 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(404)); + assertThat(response.getStatus()).isEqualTo(404); } }.run(); } @@ -328,8 +325,8 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is( - Response.Status.BAD_REQUEST.getStatusCode())); + assertThat(response.getStatus()).isEqualTo( + Response.Status.BAD_REQUEST.getStatusCode()); } }.run(); } @@ -364,8 +361,8 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is( - Response.Status.BAD_REQUEST.getStatusCode())); + assertThat(response.getStatus()).isEqualTo( + Response.Status.BAD_REQUEST.getStatusCode()); } }.run(); } @@ -400,7 +397,7 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { // Created - assertThat(response.getStatus(), is(201)); + assertThat(response.getStatus()).isEqualTo(201); } }.run(); } @@ -418,15 +415,12 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { // OK - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); - assertThat(entityString, - containsString("sample-project")); - assertThat(entityString, - containsString("retired-project")); - assertThat(entityString, - not(containsString("obsolete-project"))); + assertThat(entityString) + .contains("sample-project", "retired-project") + .doesNotContain("obsolete-project"); } }.run(); } @@ -445,15 +439,12 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { // OK - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); - assertThat(entityString, - containsString("sample-project")); - assertThat(entityString, - containsString("retired-project")); - assertThat(entityString, - not(containsString("obsolete-project"))); + assertThat(entityString) + .contains("sample-project", "retired-project") + .doesNotContain("obsolete-project"); } }.run(); } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectVersionRawRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectVersionRawRestITCase.java index 4d672cbcfe..1a9df3ee5b 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectVersionRawRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectVersionRawRestITCase.java @@ -16,8 +16,7 @@ import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.util.RawRestTestUtils.assertHeaderPresent; import static org.zanata.util.RawRestTestUtils.assertJaxbUnmarshal; import static org.zanata.util.RawRestTestUtils.assertJsonUnmarshal; @@ -63,7 +62,7 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { // OK - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); assertHeaderPresent(response, HttpHeaders.ETAG); } }.run(); @@ -84,14 +83,14 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { // OK - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, ProjectIteration.class); ProjectIteration iteration = jaxbUnmarshal(entityString, ProjectIteration.class); - assertThat(iteration.getId(), is("1.0")); - assertThat(iteration.getStatus(), is(EntityStatus.ACTIVE)); + assertThat(iteration.getId()).isEqualTo("1.0"); + assertThat(iteration.getStatus()).isEqualTo(EntityStatus.ACTIVE); } }.run(); } @@ -111,14 +110,14 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { // Ok - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, ProjectIteration.class); ProjectIteration iteration = jsonUnmarshal(entityString, ProjectIteration.class); - assertThat(iteration.getId(), is("1.0")); - assertThat(iteration.getStatus(), is(EntityStatus.ACTIVE)); + assertThat(iteration.getId()).isEqualTo("1.0"); + assertThat(iteration.getStatus()).isEqualTo(EntityStatus.ACTIVE); } }.run(); } @@ -139,8 +138,8 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { // Version not found because project is obsolete - assertThat(response.getStatus(), - is(Response.Status.NOT_FOUND.getStatusCode())); + assertThat(response.getStatus()) + .isEqualTo(Response.Status.NOT_FOUND.getStatusCode()); } }.run(); } @@ -160,8 +159,8 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { // 200 (Retired projects are readable) - assertThat(response.getStatus(), - is(Response.Status.OK.getStatusCode())); + assertThat(response.getStatus()) + .isEqualTo(Response.Status.OK.getStatusCode()); } }.run(); } @@ -180,8 +179,8 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), - is(Response.Status.NOT_FOUND.getStatusCode())); + assertThat(response.getStatus()) + .isEqualTo(Response.Status.NOT_FOUND.getStatusCode()); } }.run(); } @@ -200,9 +199,9 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), - // 404 - is(Response.Status.NOT_FOUND.getStatusCode())); + assertThat(response.getStatus()) + // 404 + .isEqualTo(Response.Status.NOT_FOUND.getStatusCode()); } }.run(); } @@ -233,7 +232,7 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { // Created - assertThat(response.getStatus(), is(201)); + assertThat(response.getStatus()).isEqualTo(201); } }.run(); } @@ -263,7 +262,7 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(404)); + assertThat(response.getStatus()).isEqualTo(404); } }.run(); } @@ -292,7 +291,7 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); } }.run(); } @@ -323,7 +322,7 @@ public void invoke(Invocation.Builder builder) { @Override protected void onResponse(Response response) { // Created - assertThat(response.getStatus(), is(201)); + assertThat(response.getStatus()).isEqualTo(201); } }.run(); } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectsRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectsRestITCase.java index df68baf176..dc1c0fe40a 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectsRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ProjectsRestITCase.java @@ -20,8 +20,7 @@ */ package org.zanata.rest.service.raw; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.util.RawRestTestUtils.jsonUnmarshal; import javax.ws.rs.client.Invocation; @@ -70,12 +69,12 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { // OK - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); Project[] projects = jsonUnmarshal(entityString, Project[].class); - Assertions.assertThat(projects.length).isGreaterThan(0); + assertThat(projects.length).isGreaterThan(0); for (Project project : projects) { - Assertions.assertThat(project.getStatus()).isNotEqualTo( + assertThat(project.getStatus()).isNotEqualTo( EntityStatus.OBSOLETE); } } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ResourceServiceRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ResourceServiceRestITCase.java index e6c4905631..509cd08339 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ResourceServiceRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/ResourceServiceRestITCase.java @@ -1,9 +1,5 @@ package org.zanata.rest.service.raw; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; - import java.util.List; import javax.ws.rs.core.Response; @@ -23,6 +19,8 @@ import com.google.common.collect.ImmutableList; +import static org.assertj.core.api.Assertions.assertThat; + public class ResourceServiceRestITCase extends SourceAndTranslationResourceRestBase { private final Logger log = LoggerFactory .getLogger(ResourceServiceRestITCase.class); @@ -60,7 +58,7 @@ public void testPutGetResourceWithExtensionDeprecated() { new StringSet("gettext;comment"))); ResourceTestUtil.clearRevs(sr); ResourceTestUtil.clearRevs(get); - assertThat(get, equalTo(sr)); + assertThat(get).isEqualTo(sr); } @Test @@ -75,7 +73,7 @@ public void testPutGetResourceWithExtension() { new StringSet("gettext;comment"))); ResourceTestUtil.clearRevs(sr); ResourceTestUtil.clearRevs(get); - assertThat(get, equalTo(sr)); + assertThat(get).isEqualTo(sr); } @Test @@ -92,7 +90,7 @@ public void testPutGetNoExtensionResourceDeprecated() { ResourceTestUtil.clearRevs(get); log.debug("expect:" + base.toString()); log.debug("actual:" + get.toString()); - assertThat(get.toString(), is(base.toString())); + assertThat(get.toString()).isEqualTo(base.toString()); } @Test @@ -109,7 +107,7 @@ public void testPutGetNoExtensionResource() { ResourceTestUtil.clearRevs(get); log.debug("expect:" + base.toString()); log.debug("actual:" + get.toString()); - assertThat(get.toString(), is(base.toString())); + assertThat(get.toString()).isEqualTo(base.toString()); } @Test @@ -125,7 +123,7 @@ public void testPutNoExtensionGetResource() { ResourceTestUtil.clearRevs(get); log.debug("expect:" + base.toString()); log.debug("actual:" + get.toString()); - assertThat(get.toString(), is(base.toString())); + assertThat(get.toString()).isEqualTo(base.toString()); } @Test @@ -138,7 +136,7 @@ public void testPutGetResourceDeprecated() { getSourceDocResource().getResource(sr.getName(), null)); ResourceTestUtil.clearRevs(base); ResourceTestUtil.clearRevs(get); - assertThat(get.toString(), is(base.toString())); + assertThat(get.toString()).isEqualTo(base.toString()); } @Test @@ -151,7 +149,7 @@ public void testPutGetResource() { getSourceDocResource().getResourceWithDocId(sr.getName(), null)); ResourceTestUtil.clearRevs(base); ResourceTestUtil.clearRevs(get); - assertThat(get.toString(), is(base.toString())); + assertThat(get.toString()).isEqualTo(base.toString()); } @Test @@ -163,7 +161,7 @@ public void testPostGetResource() { getSourceDocResource().getResourceWithDocId(sr.getName(), null)); ResourceTestUtil.clearRevs(base); ResourceTestUtil.clearRevs(get); - assertThat(get.toString(), is(base.toString())); + assertThat(get.toString()).isEqualTo(base.toString()); } @Test @@ -178,7 +176,7 @@ public void testPostGetResourceWithExtensionDeprecated() { ResourceTestUtil.clearRevs(get); log.debug("expect:" + sr.toString()); log.debug("actual:" + get.toString()); - assertThat(get.toString(), is(sr.toString())); + assertThat(get.toString()).isEqualTo(sr.toString()); } @Test @@ -192,7 +190,7 @@ public void testPostGetResourceWithExtension() { ResourceTestUtil.clearRevs(get); log.debug("expect:" + sr.toString()); log.debug("actual:" + get.toString()); - assertThat(get.toString(), is(sr.toString())); + assertThat(get.toString()).isEqualTo(sr.toString()); } @Test @@ -208,7 +206,7 @@ public void testPostGetNoExtensionResourceDeprecated() { ResourceTestUtil.clearRevs(get); log.debug("expect:" + base.toString()); log.debug("actual:" + get.toString()); - assertThat(get.toString(), is(base.toString())); + assertThat(get.toString()).isEqualTo(base.toString()); } @Test @@ -226,7 +224,7 @@ public void testPostNoExtensionGetResource() { log.debug("expect:" + expected); String got = RawRestTestUtils.jaxbMarhsal(get); log.debug("actual:" + got); - assertThat(got, is(expected)); + assertThat(got).isEqualTo(expected); } @Test @@ -241,7 +239,7 @@ public void testPostGetNoExtensionResource() { ResourceTestUtil.clearRevs(get); log.debug("expect:" + base.toString()); log.debug("actual:" + get.toString()); - assertThat(get.toString(), is(base.toString())); + assertThat(get.toString()).isEqualTo(base.toString()); } @Test @@ -263,7 +261,7 @@ public void testPutGetResourceMetaDeprecated() { ResourceMeta get = getResourceMetaFromResponse(resourceGetResponse); ResourceTestUtil.clearRevs(sr); ResourceTestUtil.clearRevs(get); - assertThat(sr, equalTo(get)); + assertThat(sr).isEqualTo(get); } @Test @@ -284,7 +282,7 @@ public void testPutGetResourceMeta() { ResourceMeta get = getResourceMetaFromResponse(resourceGetResponse); ResourceTestUtil.clearRevs(sr); ResourceTestUtil.clearRevs(get); - assertThat(sr, equalTo(get)); + assertThat(sr).isEqualTo(get); } @Test @@ -305,7 +303,7 @@ public void testPutNoExtensionGetResourceMeta() { ResourceMeta get = getResourceMetaFromResponse(resourceGetResponse); ResourceTestUtil.clearRevs(base); ResourceTestUtil.clearRevs(get); - assertThat(get, equalTo(base)); + assertThat(get).isEqualTo(base); } @Test @@ -325,7 +323,7 @@ public void testPutGetNoExtensionResourceMetaDeprecated() { ResourceMeta get = getResourceMetaFromResponse(resourceGetResponse); ResourceTestUtil.clearRevs(base); ResourceTestUtil.clearRevs(get); - assertThat(get, equalTo(base)); + assertThat(get).isEqualTo(base); } @Test @@ -346,7 +344,7 @@ public void testPutGetNoExtensionResourceMeta() { ResourceMeta get = getResourceMetaFromResponse(resourceGetResponse); ResourceTestUtil.clearRevs(base); ResourceTestUtil.clearRevs(get); - assertThat(get, equalTo(base)); + assertThat(get).isEqualTo(base); } @Test @@ -357,14 +355,14 @@ public void testDeleteResourceDeprecated() { getSourceDocResource().post(rs1, null, true); Response resourceGetResponse = getSourceDocResource().deleteResource(rs1.getName()); - assertThat(resourceGetResponse.getStatus(), - is(Status.OK.getStatusCode())); + assertThat(resourceGetResponse.getStatus()) + .isEqualTo(Status.OK.getStatusCode()); Resource rs2 = resourceTestFactory.getTextFlowTest(); Response resourceGetResponse2 = getSourceDocResource().deleteResource(rs2.getName()); - assertThat(resourceGetResponse2.getStatus(), - is(Status.NOT_FOUND.getStatusCode())); + assertThat(resourceGetResponse2.getStatus()) + .isEqualTo(Status.NOT_FOUND.getStatusCode()); } @Test @@ -374,14 +372,14 @@ public void testDeleteResource() { getSourceDocResource().post(rs1, null, true); Response resourceGetResponse = getSourceDocResource().deleteResourceWithDocId(rs1.getName()); - assertThat(resourceGetResponse.getStatus(), - is(Status.OK.getStatusCode())); + assertThat(resourceGetResponse.getStatus()) + .isEqualTo(Status.OK.getStatusCode()); Resource rs2 = resourceTestFactory.getTextFlowTest(); Response resourceGetResponse2 = getSourceDocResource().deleteResourceWithDocId(rs2.getName()); - assertThat(resourceGetResponse2.getStatus(), - is(Status.NOT_FOUND.getStatusCode())); + assertThat(resourceGetResponse2.getStatus()) + .isEqualTo(Status.NOT_FOUND.getStatusCode()); } @Test @@ -403,7 +401,7 @@ public void testPostGetResourceWithUnderscoreInFileNameWithExtensionDeprecated() log.debug("expect:" + expected); String got = RawRestTestUtils.jaxbMarhsal(get); log.debug("actual:" + got); - assertThat(got, is(expected)); + assertThat(got).isEqualTo(expected); } @Test @@ -424,6 +422,6 @@ public void testPostGetResourceWithUnderscoreInFileNameWithExtension() { log.debug("expect:" + expected); String got = RawRestTestUtils.jaxbMarhsal(get); log.debug("actual:" + got); - assertThat(got, is(expected)); + assertThat(got).isEqualTo(expected); } } diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/StatisticsRawRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/StatisticsRawRestITCase.java index 60e815d7cb..72dd372d30 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/StatisticsRawRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/StatisticsRawRestITCase.java @@ -20,8 +20,6 @@ */ package org.zanata.rest.service.raw; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; import java.util.Arrays; import javax.ws.rs.client.Invocation; import javax.ws.rs.core.HttpHeaders; @@ -37,6 +35,8 @@ import org.zanata.rest.ResourceRequest; import org.zanata.rest.dto.stats.ContainerTranslationStatistics; import org.zanata.rest.dto.stats.TranslationStatistics; + +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.provider.DBUnitProvider.DataSetOperation; import static org.zanata.util.RawRestTestUtils.assertJaxbUnmarshal; import static org.zanata.util.RawRestTestUtils.assertJsonUnmarshal; @@ -98,24 +98,24 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, ContainerTranslationStatistics.class); ContainerTranslationStatistics stats = jaxbUnmarshal(entityString, ContainerTranslationStatistics.class); - assertThat(stats.getId(), is("1.0")); - assertThat(stats.getRefs().size(), greaterThan(0)); - assertThat(stats.getDetailedStats(), nullValue()); - assertThat(stats.getStats().size(), greaterThan(0)); + assertThat(stats.getId()).isEqualTo("1.0"); + assertThat(stats.getRefs().size()).isGreaterThan(0); + assertThat(stats.getDetailedStats()).isNull(); + assertThat(stats.getStats().size()).isGreaterThan(0); for (TranslationStatistics transStat : stats.getStats()) { - assertThat(transStat.getUnit(), - is(TranslationStatistics.StatUnit.MESSAGE)); + assertThat(transStat.getUnit()) + .isEqualTo(TranslationStatistics.StatUnit.MESSAGE); assertThat( transStat.getUntranslated() + transStat.getDraft() - + transStat.getTranslatedAndApproved(), - equalTo(transStat.getTotal())); + + transStat.getTranslatedAndApproved()) + .isEqualTo(transStat.getTotal()); } } }.run(); @@ -143,31 +143,31 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, ContainerTranslationStatistics.class); ContainerTranslationStatistics stats = jaxbUnmarshal(entityString, ContainerTranslationStatistics.class); - assertThat(stats.getId(), is("1.0")); - assertThat(stats.getRefs().size(), greaterThan(0)); - assertThat(stats.getDetailedStats().size(), greaterThan(0)); - assertThat(stats.getStats().size(), greaterThan(0)); + assertThat(stats.getId()).isEqualTo("1.0"); + assertThat(stats.getRefs().size()).isGreaterThan(0); + assertThat(stats.getDetailedStats().size()).isGreaterThan(0); + assertThat(stats.getStats().size()).isGreaterThan(0); for (TranslationStatistics transStat : stats.getStats()) { assertThat( transStat.getDraft() + transStat.getApproved() - + transStat.getUntranslated(), - equalTo(transStat.getTotal())); + + transStat.getUntranslated()) + .isEqualTo(transStat.getTotal()); } String[] expectedLocales = new String[] { "en-US", "as", "es" }; for (TranslationStatistics transStat : stats.getStats()) { - assertThat(Arrays.asList(expectedLocales), - hasItem(transStat.getLocale())); + assertThat(Arrays.asList(expectedLocales)) + .contains(transStat.getLocale()); assertThat( transStat.getUntranslated() + transStat.getDraft() - + transStat.getTranslatedAndApproved(), - equalTo(transStat.getTotal())); + + transStat.getTranslatedAndApproved()) + .isEqualTo(transStat.getTotal()); } } }.run(); @@ -196,23 +196,23 @@ protected Invocation.Builder prepareRequest( @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, ContainerTranslationStatistics.class); ContainerTranslationStatistics stats = jaxbUnmarshal(entityString, ContainerTranslationStatistics.class); - assertThat(stats.getId(), is("my/path/document.txt")); - assertThat(stats.getRefs().size(), greaterThan(0)); - assertThat(stats.getDetailedStats(), nullValue()); - assertThat(stats.getStats().size(), greaterThan(0)); + assertThat(stats.getId()).isEqualTo("my/path/document.txt"); + assertThat(stats.getRefs().size()).isGreaterThan(0); + assertThat(stats.getDetailedStats()).isNull(); + assertThat(stats.getStats().size()).isGreaterThan(0); for (TranslationStatistics transStat : stats.getStats()) { - assertThat(transStat.getUnit(), - is(TranslationStatistics.StatUnit.MESSAGE)); + assertThat(transStat.getUnit()) + .isEqualTo(TranslationStatistics.StatUnit.MESSAGE); assertThat( transStat.getUntranslated() + transStat.getDraft() - + transStat.getTranslatedAndApproved(), - equalTo(transStat.getTotal())); + + transStat.getTranslatedAndApproved()) + .isEqualTo(transStat.getTotal()); } } }.run(); @@ -243,29 +243,29 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, ContainerTranslationStatistics.class); ContainerTranslationStatistics stats = jaxbUnmarshal(entityString, ContainerTranslationStatistics.class); - assertThat(stats.getId(), is("my/path/document.txt")); - assertThat(stats.getRefs().size(), greaterThan(0)); - assertThat(stats.getStats().size(), greaterThan(0)); + assertThat(stats.getId()).isEqualTo("my/path/document.txt"); + assertThat(stats.getRefs().size()).isGreaterThan(0); + assertThat(stats.getStats().size()).isGreaterThan(0); for (TranslationStatistics transStat : stats.getStats()) { assertThat( transStat.getUntranslated() + transStat.getDraft() - + transStat.getTranslatedAndApproved(), - equalTo(transStat.getTotal())); + + transStat.getTranslatedAndApproved()) + .isEqualTo(transStat.getTotal()); } String[] expectedLocales = new String[] { "en-US", "as", "es" }; for (TranslationStatistics transStat : stats.getStats()) { - assertThat(Arrays.asList(expectedLocales), - hasItem(transStat.getLocale())); + assertThat(Arrays.asList(expectedLocales)) + .contains(transStat.getLocale()); assertThat( transStat.getDraft() + transStat.getApproved() - + transStat.getUntranslated(), - equalTo(transStat.getTotal())); + + transStat.getUntranslated()) + .isEqualTo(transStat.getTotal()); } } }.run(); @@ -295,20 +295,20 @@ protected void onResponse(Response response) { String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, ContainerTranslationStatistics.class); - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); ContainerTranslationStatistics stats = jsonUnmarshal(entityString, ContainerTranslationStatistics.class); - assertThat(stats.getId(), is("1.0")); - assertThat(stats.getRefs().size(), greaterThan(0)); - assertThat(stats.getDetailedStats(), nullValue()); - assertThat(stats.getStats().size(), greaterThan(0)); + assertThat(stats.getId()).isEqualTo("1.0"); + assertThat(stats.getRefs().size()).isGreaterThan(0); + assertThat(stats.getDetailedStats()).isNull(); + assertThat(stats.getStats().size()).isGreaterThan(0); for (TranslationStatistics transStat : stats.getStats()) { - assertThat(transStat.getUnit(), - is(TranslationStatistics.StatUnit.MESSAGE)); + assertThat(transStat.getUnit()) + .isEqualTo(TranslationStatistics.StatUnit.MESSAGE); assertThat( transStat.getUntranslated() + transStat.getDraft() - + transStat.getTranslatedAndApproved(), - equalTo(transStat.getTotal())); + + transStat.getTranslatedAndApproved()) + .isEqualTo(transStat.getTotal()); } } }.run(); @@ -336,32 +336,32 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, ContainerTranslationStatistics.class); ContainerTranslationStatistics stats = jsonUnmarshal(entityString, ContainerTranslationStatistics.class); - assertThat(stats.getId(), is("1.0")); - assertThat(stats.getRefs().size(), greaterThan(0)); - assertThat(stats.getDetailedStats().size(), greaterThan(0)); - assertThat(stats.getStats().size(), greaterThan(0)); + assertThat(stats.getId()).isEqualTo("1.0"); + assertThat(stats.getRefs().size()).isGreaterThan(0); + assertThat(stats.getDetailedStats().size()).isGreaterThan(0); + assertThat(stats.getStats().size()).isGreaterThan(0); for (TranslationStatistics transStat : stats.getStats()) { assertThat( transStat.getDraft() + transStat.getApproved() - + transStat.getUntranslated(), - equalTo(transStat.getTotal())); + + transStat.getUntranslated()) + .isEqualTo(transStat.getTotal()); } String[] expectedLocales = new String[] { "en-US", "as", "es" }; for (TranslationStatistics transStat : stats.getStats()) { - assertThat(Arrays.asList(expectedLocales), - hasItem(transStat.getLocale())); + assertThat(Arrays.asList(expectedLocales)) + .contains(transStat.getLocale()); assertThat( transStat.getDraft() + transStat.getApproved() + transStat.getUntranslated() - + transStat.getTranslatedOnly(), - equalTo(transStat.getTotal())); + + transStat.getTranslatedOnly()) + .isEqualTo(transStat.getTotal()); } } }.run(); @@ -389,24 +389,24 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, ContainerTranslationStatistics.class); ContainerTranslationStatistics stats = jsonUnmarshal(entityString, ContainerTranslationStatistics.class); - assertThat(stats.getId(), is("my/path/document.txt")); - assertThat(stats.getRefs().size(), greaterThan(0)); - assertThat(stats.getDetailedStats(), nullValue()); - assertThat(stats.getStats().size(), greaterThan(0)); + assertThat(stats.getId()).isEqualTo("my/path/document.txt"); + assertThat(stats.getRefs().size()).isGreaterThan(0); + assertThat(stats.getDetailedStats()).isNull(); + assertThat(stats.getStats().size()).isGreaterThan(0); for (TranslationStatistics transStat : stats.getStats()) { - assertThat(transStat.getUnit(), - is(TranslationStatistics.StatUnit.MESSAGE)); + assertThat(transStat.getUnit()) + .isEqualTo(TranslationStatistics.StatUnit.MESSAGE); assertThat( transStat.getDraft() + transStat.getApproved() + transStat.getUntranslated() - + transStat.getTranslatedOnly(), - equalTo(transStat.getTotal())); + + transStat.getTranslatedOnly()) + .isEqualTo(transStat.getTotal()); } } }.run(); @@ -438,31 +438,31 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, ContainerTranslationStatistics.class); ContainerTranslationStatistics stats = jsonUnmarshal(entityString, ContainerTranslationStatistics.class); - assertThat(stats.getId(), is("my/path/document.txt")); - assertThat(stats.getRefs().size(), greaterThan(0)); - assertThat(stats.getStats().size(), greaterThan(0)); + assertThat(stats.getId()).isEqualTo("my/path/document.txt"); + assertThat(stats.getRefs().size()).isGreaterThan(0); + assertThat(stats.getStats().size()).isGreaterThan(0); for (TranslationStatistics transStat : stats.getStats()) { assertThat( transStat.getDraft() + transStat.getApproved() + transStat.getUntranslated() - + transStat.getTranslatedOnly(), - equalTo(transStat.getTotal())); + + transStat.getTranslatedOnly()) + .isEqualTo(transStat.getTotal()); } String[] expectedLocales = new String[] { "en-US", "as", "es" }; for (TranslationStatistics transStat : stats.getStats()) { - assertThat(Arrays.asList(expectedLocales), - hasItem(transStat.getLocale())); + assertThat(Arrays.asList(expectedLocales)) + .contains(transStat.getLocale()); assertThat( transStat.getDraft() + transStat.getApproved() + transStat.getUntranslated() - + transStat.getTranslatedOnly(), - equalTo(transStat.getTotal())); + + transStat.getTranslatedOnly()) + .isEqualTo(transStat.getTotal()); } } }.run(); diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/TranslationResourceRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/TranslationResourceRestITCase.java index 705bd11823..942d6cd4bb 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/TranslationResourceRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/TranslationResourceRestITCase.java @@ -1,8 +1,7 @@ package org.zanata.rest.service.raw; import static java.util.Arrays.asList; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.util.RawRestTestUtils.jaxbMarhsal; import static org.zanata.util.RawRestTestUtils.jsonUnmarshal; @@ -16,7 +15,6 @@ import javax.ws.rs.core.Response.Status; import org.fedorahosted.tennera.jgettext.HeaderFields; -import org.hamcrest.Matchers; import org.jboss.arquillian.container.test.api.RunAsClient; import org.junit.Test; import org.slf4j.Logger; @@ -70,7 +68,7 @@ public void createEmptyResource() { Response response = getSourceDocResource().post(sr, null, true); - assertThat(response.getStatus(), is(Status.CREATED.getStatusCode())); + assertThat(response.getStatus()).isEqualTo(Status.CREATED.getStatusCode()); doGetandAssertThatResourceListContainsNItems(1); } @@ -84,15 +82,15 @@ public void createResourceWithContentUsingPost() { Response postResponse = getSourceDocResource().post(sr, null, true); - assertThat(postResponse.getStatus(), is(Status.CREATED.getStatusCode())); + assertThat(postResponse.getStatus()).isEqualTo(Status.CREATED.getStatusCode()); postResponse = getSourceDocResource().post(sr, null, true); Response resourceGetResponse = getSourceDocResource().getResourceWithDocId("my.txt", null); - assertThat(resourceGetResponse.getStatus(), is(Status.OK.getStatusCode())); + assertThat(resourceGetResponse.getStatus()).isEqualTo(Status.OK.getStatusCode()); Resource gotSr = getResourceFromResponse(resourceGetResponse); - assertThat(gotSr.getTextFlows().size(), is(1)); - assertThat(gotSr.getTextFlows().get(0).getContents(), is(asList("tf1"))); + assertThat(gotSr.getTextFlows().size()).isEqualTo(1); + assertThat(gotSr.getTextFlows().get(0).getContents()).isEqualTo(asList("tf1")); } @@ -107,14 +105,14 @@ public void createResourceWithContentUsingPut() { Response response = getSourceDocResource() .putResourceWithDocId(sr, "my.txt", null, false); - assertThat(response.getStatus(), is(Status.CREATED.getStatusCode())); + assertThat(response.getStatus()).isEqualTo(Status.CREATED.getStatusCode()); Response resourceGetResponse = getSourceDocResource().getResourceWithDocId("my.txt", null); - assertThat(resourceGetResponse.getStatus(), is(Status.OK.getStatusCode())); + assertThat(resourceGetResponse.getStatus()).isEqualTo(Status.OK.getStatusCode()); Resource gotSr = getResourceFromResponse(resourceGetResponse); - assertThat(gotSr.getTextFlows().size(), is(1)); - assertThat(gotSr.getTextFlows().get(0).getContents(), is(asList("tf1"))); + assertThat(gotSr.getTextFlows().size()).isEqualTo(1); + assertThat(gotSr.getTextFlows().get(0).getContents()).isEqualTo(asList("tf1")); } @@ -140,16 +138,16 @@ public void createPoResourceWithPoHeader() { Response postResponse = getSourceDocResource().post(sr, null, true); // new StringSet(PoHeader.ID)); - assertThat(postResponse.getStatus(), is(Status.CREATED.getStatusCode())); + assertThat(postResponse.getStatus()).isEqualTo(Status.CREATED.getStatusCode()); doGetandAssertThatResourceListContainsNItems(1); Response resourceGetResponse = getSourceDocResource().getResourceWithDocId(docName, null); // , new StringSet(PoHeader.ID)); - assertThat(resourceGetResponse.getStatus(), is(Status.OK.getStatusCode())); + assertThat(resourceGetResponse.getStatus()).isEqualTo(Status.OK.getStatusCode()); Resource gotSr = getResourceFromResponse(resourceGetResponse); - assertThat(gotSr.getTextFlows().size(), is(1)); - assertThat(gotSr.getTextFlows().get(0).getContents(), is(asList("tf1"))); + assertThat(gotSr.getTextFlows().size()).isEqualTo(1); + assertThat(gotSr.getTextFlows().get(0).getContents()).isEqualTo(asList("tf1")); // @formatter:off /* @@ -184,17 +182,17 @@ public void publishTranslations() { .putTranslationsWithDocId(de_DE, entity, "my.txt", null, "auto"); - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); + assertThat(response.getStatus()).isEqualTo(Status.OK.getStatusCode()); Response getResponse = getTransResource() .getTranslationsWithDocId(de_DE, "my.txt", null, false, null); - assertThat(getResponse.getStatus(), is(Status.OK.getStatusCode())); + assertThat(getResponse.getStatus()).isEqualTo(Status.OK.getStatusCode()); TranslationsResource entity2 = getTranslationsResourceFromResponse(getResponse); - assertThat(entity2.getTextFlowTargets().size(), is(entity - .getTextFlowTargets().size())); + assertThat(entity2.getTextFlowTargets().size()).isEqualTo(entity + .getTextFlowTargets().size()); entity.getTextFlowTargets().clear(); // push an empty document @@ -202,13 +200,13 @@ public void publishTranslations() { getTransResource() .putTranslationsWithDocId(de_DE, entity, "my.txt", null, MergeType.IMPORT.toString()); - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); + assertThat(response.getStatus()).isEqualTo(Status.OK.getStatusCode()); getResponse = getTransResource() .getTranslationsWithDocId(de_DE, "my.txt", null, false, null); - assertThat(getResponse.getStatus(), is(Status.OK.getStatusCode())); + assertThat(getResponse.getStatus()).isEqualTo(Status.OK.getStatusCode()); } @Test @@ -217,7 +215,7 @@ public void getDocumentThatDoesntExist() { Response clientResponse = getSourceDocResource() .getResourceWithDocId("my,doc,does,not,exist.txt", null); - assertThat(clientResponse.getStatus(), is(Status.NOT_FOUND.getStatusCode())); + assertThat(clientResponse.getStatus()).isEqualTo(Status.NOT_FOUND.getStatusCode()); } @Test @@ -230,12 +228,12 @@ public void getDocument() throws Exception { Response response = getSourceDocResource().getResourceMetaWithDocId(docName, null); - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); + assertThat(response.getStatus()).isEqualTo(Status.OK.getStatusCode()); ResourceMeta doc = getResourceMetaFromResponse(response); - assertThat(doc.getName(), is(docName)); - assertThat(doc.getContentType(), is(ContentType.TextPlain)); - assertThat(doc.getLang(), is(LocaleId.EN_US)); - assertThat(doc.getRevision(), is(1)); + assertThat(doc.getName()).isEqualTo(docName); + assertThat(doc.getContentType()).isEqualTo(ContentType.TextPlain); + assertThat(doc.getLang()).isEqualTo(LocaleId.EN_US); + assertThat(doc.getRevision()).isEqualTo(1); /* * Link link = doc.getLinks().findLinkByRel(Relationships.SELF); @@ -264,10 +262,10 @@ public void getDocumentWithResources() throws Exception { { Response response = getSourceDocResource().getResourceWithDocId(docName, null); - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); + assertThat(response.getStatus()).isEqualTo(Status.OK.getStatusCode()); Resource doc = getResourceFromResponse(response); - assertThat(doc.getTextFlows().size(), is(1)); + assertThat(doc.getTextFlows().size()).isEqualTo(1); } Response response = @@ -275,20 +273,20 @@ public void getDocumentWithResources() throws Exception { .getTranslationsWithDocId(nbLocale, docName, null, false, null); - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); + assertThat(response.getStatus()).isEqualTo(Status.OK.getStatusCode()); TranslationsResource doc = getTranslationsResourceFromResponse(response); - assertThat("should have one textFlow", doc.getTextFlowTargets().size(), - is(1)); + assertThat(doc.getTextFlowTargets().size()).isEqualTo(1) + .as("should have one textFlow"); TextFlowTarget tft = doc.getTextFlowTargets().get(0); - assertThat(tft, notNullValue()); - assertThat("should have a textflow with this id", tft.getResId(), - is("tf1")); + assertThat(tft).isNotNull(); + assertThat(tft.getResId()).isEqualTo("tf1") + .as("should have a textflow with this id"); - assertThat("expected de target", tft, notNullValue()); - assertThat("expected translation for de", tft.getContents(), - is(asList("hei verden"))); + assertThat(tft).isNotNull().as("expected de target"); + assertThat(tft.getContents()).isEqualTo(asList("hei verden")) + .as("expected translation for de"); } @Test @@ -299,17 +297,18 @@ public void putNewDocument() { Response response = getSourceDocResource() .putResourceWithDocId(doc, docName, null, false); - assertThat(response.getStatus(), is(Status.CREATED.getStatusCode())); - assertThat(response.getMetadata().getFirst("Location").toString(), - endsWith(BASE_PATH + "?docId=" + UrlUtil.encodeString(docName))); + assertThat(response.getStatus()).isEqualTo(Status.CREATED.getStatusCode()); + assertThat(response.getMetadata().getFirst("Location").toString()) + .endsWith( + BASE_PATH + "?docId=" + UrlUtil.encodeString(docName)); Response documentResponse = getSourceDocResource().getResourceWithDocId(docName, null); - assertThat(documentResponse.getStatus(), is(Status.OK.getStatusCode())); + assertThat(documentResponse.getStatus()).isEqualTo(Status.OK.getStatusCode()); doc = getResourceFromResponse(documentResponse); - assertThat(doc.getRevision(), is(1)); + assertThat(doc.getRevision()).isEqualTo(1); /* * Link link = doc.getLinks().findLinkByRel(Relationships.SELF); @@ -338,9 +337,9 @@ public void putDocWithDuplicateTextFlowIds() throws Exception { Response response = getSourceDocResource() .putResourceWithDocId(doc, docName, null, false); - assertThat(response.getStatus(), is(Status.BAD_REQUEST.getStatusCode())); + assertThat(response.getStatus()).isEqualTo(Status.BAD_REQUEST.getStatusCode()); String message = response.readEntity(String.class); - assertThat(message, containsString("tf1")); + assertThat(message).contains("tf1"); } @Test @@ -369,25 +368,26 @@ public void putNewDocumentWithResources() throws Exception { Response response = getSourceDocResource() .putResourceWithDocId(doc, docName, null, false); - assertThat(response.getStatus(), is(Status.CREATED.getStatusCode())); - assertThat(response.getMetadata().getFirst("Location").toString(), - endsWith(BASE_PATH + "?docId=" + UrlUtil.encodeString(docName))); + assertThat(response.getStatus()).isEqualTo(Status.CREATED.getStatusCode()); + assertThat(response.getMetadata().getFirst("Location").toString()) + .endsWith(BASE_PATH + "?docId=" + UrlUtil.encodeString(docName)); Response documentResponse = getSourceDocResource().getResourceWithDocId(docName, null); - assertThat(documentResponse.getStatus(), is(Status.OK.getStatusCode())); + assertThat(documentResponse.getStatus()).isEqualTo(Status.OK.getStatusCode()); doc = getResourceFromResponse(documentResponse); - assertThat(doc.getRevision(), is(1)); + assertThat(doc.getRevision()).isEqualTo(1); - assertThat("Should have textFlows", doc.getTextFlows(), notNullValue()); - assertThat("Should have 2 textFlows", doc.getTextFlows().size(), is(2)); - assertThat("Should have tf1 textFlow", doc.getTextFlows().get(0) - .getId(), is("tf1")); - assertThat("Container1 should have tf3 textFlow", doc.getTextFlows() - .get(1).getId(), is(tf3.getId())); + assertThat(doc.getTextFlows()).isNotNull().as("Should have textFlows"); + assertThat(doc.getTextFlows().size()).isEqualTo(2) + .as("Should have 2 textFlows"); + assertThat(doc.getTextFlows().get(0).getId()).isEqualTo("tf1") + .as("Should have tf1 textFlow"); + assertThat(doc.getTextFlows().get(1).getId()).isEqualTo(tf3.getId()) + .as("Container1 should have tf3 textFlow"); textFlow = doc.getTextFlows().get(0); textFlow.setId("tf2"); @@ -396,20 +396,20 @@ public void putNewDocumentWithResources() throws Exception { null, false); // this WAS testing for status 205 - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); documentResponse = getSourceDocResource() .getResourceWithDocId(docName, null); - assertThat(documentResponse.getStatus(), is(Status.OK.getStatusCode())); + assertThat(documentResponse.getStatus()).isEqualTo(Status.OK.getStatusCode()); doc = getResourceFromResponse(documentResponse); - assertThat(doc.getRevision(), is(2)); + assertThat(doc.getRevision()).isEqualTo(2); - assertThat("Should have textFlows", doc.getTextFlows(), notNullValue()); - assertThat("Should have two textFlows", doc.getTextFlows().size(), - is(2)); - assertThat("should have same id", doc.getTextFlows().get(0).getId(), - is("tf2")); + assertThat(doc.getTextFlows()).isNotNull().as("Should have textFlows"); + assertThat(doc.getTextFlows().size()).isEqualTo(2) + .as("Should have two textFlows"); + assertThat(doc.getTextFlows().get(0).getId()).isEqualTo("tf2") + .as("should have same id"); } @Test @@ -639,7 +639,7 @@ public void generatedPoHeaders() throws Exception { "gettext"), true, null); TranslationsResource translations = getTranslationsResourceFromResponse(response); - assertThat(translations.getExtensions().size(), greaterThan(0)); + assertThat(translations.getExtensions().size()).isGreaterThan(0); // List of custom Zanata headers that should be present final String[] requiredHeaders = @@ -656,10 +656,8 @@ public void generatedPoHeaders() throws Exception { headerFound = true; } } - - assertThat("PO Target Header '" + reqHeader - + "' was not present when pulling translations.", - headerFound, is(true)); + assertThat(headerFound).isTrue().as("PO Target Header '" + reqHeader + + "' was not present when pulling translations."); } /** @@ -672,14 +670,12 @@ public void generatedPoHeaders() throws Exception { String value = entry.getValue().trim(); if (entry.getKey().equals(HeaderFields.KEY_LastTranslator)) { - assertThat(value, - containsString(ResourceUtils.COPIED_BY_ZANATA_NAME)); - assertThat(value, containsString( - ResourceUtils.COPIED_BY_ZANATA_NAME_EMAIL)); + assertThat(value).contains(ResourceUtils.COPIED_BY_ZANATA_NAME, + ResourceUtils.COPIED_BY_ZANATA_NAME_EMAIL); } if (entry.getKey().equals(HeaderFields.KEY_PoRevisionDate)) { - assertThat(value, not(isEmptyOrNullString())); + assertThat(value).isNotBlank(); } } } @@ -701,22 +697,22 @@ public void headersBeforeTranslating() throws Exception { TranslationsResource translations = getTranslationsResourceFromResponse(response); // Expecting no translations - assertThat(translations.getTextFlowTargets().size(), is(0)); + assertThat(translations.getTextFlowTargets().size()).isEqualTo(0); // Make sure the headers are populated PoTargetHeader header = translations.getExtensions(true).findByType( PoTargetHeader.class); - assertThat(header, notNullValue()); - assertThat(header.getEntries().size(), greaterThan(0)); + assertThat(header).isNotNull(); + assertThat(header.getEntries().size()).isGreaterThan(0); // Make sure the header values are empty since the system does not have // any information for them for (HeaderEntry entry : header.getEntries()) { if (entry.getKey().equals(HeaderFields.KEY_LastTranslator)) { - assertThat(entry.getValue().trim(), is("")); + assertThat(entry.getValue().trim()).isEqualTo(""); } else if (entry.getKey().equals(HeaderFields.KEY_PoRevisionDate)) { - assertThat(entry.getValue().trim(), is("")); + assertThat(entry.getValue().trim()).isEqualTo(""); } } } @@ -758,7 +754,7 @@ public void headersFromOriginalPush() throws Exception { Response putResponse = getTransResource().putTranslationsWithDocId(de_DE, entity, "my.txt", new StringSet("gettext"), "auto"); - assertThat(putResponse.getStatus(), is(Status.OK.getStatusCode())); + assertThat(putResponse.getStatus()).isEqualTo(Status.OK.getStatusCode()); // Get the translations with PO headers @@ -772,20 +768,18 @@ public void headersFromOriginalPush() throws Exception { PoTargetHeader header = translations.getExtensions(true).findByType( PoTargetHeader.class); - assertThat(header, notNullValue()); - assertThat(header.getEntries().size(), greaterThan(0)); + assertThat(header).isNotNull(); + assertThat(header.getEntries().size()).isGreaterThan(0); // Make sure the header values are the same as the ones pushed with the // document for (HeaderEntry entry : header.getEntries()) { String value = entry.getValue().trim(); if (entry.getKey().equals(HeaderFields.KEY_LastTranslator)) { - assertThat(value, - containsString(ResourceUtils.COPIED_BY_ZANATA_NAME)); - assertThat(value, containsString( - ResourceUtils.COPIED_BY_ZANATA_NAME_EMAIL)); + assertThat(value).contains(ResourceUtils.COPIED_BY_ZANATA_NAME, + ResourceUtils.COPIED_BY_ZANATA_NAME_EMAIL); } else if (entry.getKey().equals(HeaderFields.KEY_PoRevisionDate)) { - assertThat(value, is(dateFormat.format(poRevDate.getTime()))); + assertThat(value).isEqualTo(dateFormat.format(poRevDate.getTime())); } } } @@ -810,7 +804,7 @@ public void headersAfterTranslating() throws Exception { getTransResource() .putTranslationsWithDocId(de_DE, entity, "my.txt", null, "auto"); - assertThat(putResponse.getStatus(), is(Status.OK.getStatusCode())); + assertThat(putResponse.getStatus()).isEqualTo(Status.OK.getStatusCode()); // Get the translations with PO headers Response response = @@ -819,7 +813,7 @@ public void headersAfterTranslating() throws Exception { "gettext"), false, null); TranslationsResource translations = getTranslationsResourceFromResponse(response); - assertThat(translations.getTextFlowTargets().size(), greaterThan(0)); + assertThat(translations.getTextFlowTargets().size()).isGreaterThan(0); // Now translate and push them again for (TextFlowTarget tft : translations.getTextFlowTargets()) { @@ -831,8 +825,8 @@ public void headersAfterTranslating() throws Exception { getTransResource() .putTranslationsWithDocId(de_DE, translations, "my.txt", null, "auto"); - assertThat(putResponse.getStatus(), - is(Status.OK.getStatusCode())); + assertThat(putResponse.getStatus()) + .isEqualTo(Status.OK.getStatusCode()); // Fetch the translations again response = @@ -841,14 +835,14 @@ public void headersAfterTranslating() throws Exception { "gettext"), false, null); translations = getTranslationsResourceFromResponse(response); - assertThat(translations.getTextFlowTargets().size(), greaterThan(0)); + assertThat(translations.getTextFlowTargets().size()).isGreaterThan(0); // Make sure the headers are now populated PoTargetHeader header = translations.getExtensions(true).findByType( PoTargetHeader.class); - assertThat(header, notNullValue()); - assertThat(header.getEntries().size(), greaterThan(0)); + assertThat(header).isNotNull(); + assertThat(header.getEntries().size()).isGreaterThan(0); } @@ -875,11 +869,11 @@ private void expectResourceMetas(boolean checkRevs, Response response = getSourceDocResource().get(null); - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); List actualDocs = Lists.newArrayList(jsonUnmarshal( entityString, ResourceMeta[].class)); - assertThat(actualDocs, notNullValue()); + assertThat(actualDocs).isNotNull(); Map expectedDocs = new HashMap<>(); for (AbstractResourceMeta doc : docs) { @@ -893,9 +887,9 @@ private void expectResourceMetas(boolean checkRevs, log.debug("actual doc: " + doc.toString()); AbstractResourceMeta expectedDoc = expectedDocs.get(doc.getName()); if (checkRevs) - assertThat(doc.getRevision(), is(expectedDoc.getRevision())); + assertThat(doc.getRevision()).isEqualTo(expectedDoc.getRevision()); } - assertThat(actualDocsMap.keySet(), is(expectedDocs.keySet())); + assertThat(actualDocsMap.keySet()).isEqualTo(expectedDocs.keySet()); } private void expectResources(boolean checkRevs, Resource... docs) { @@ -903,7 +897,7 @@ private void expectResources(boolean checkRevs, Resource... docs) { Response response = getSourceDocResource().getResourceWithDocId(expectedDoc.getName(), extGettextComment); - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); Resource actualDoc = getResourceFromResponse(response); if (!checkRevs) { ResourceTestUtil.clearRevs(expectedDoc); @@ -911,7 +905,7 @@ private void expectResources(boolean checkRevs, Resource... docs) { } createExtensionSets(expectedDoc); createExtensionSets(actualDoc); - assertThat(actualDoc, Matchers.equalTo(expectedDoc)); + assertThat(actualDoc).isEqualTo(expectedDoc); } } @@ -927,7 +921,7 @@ private void dontExpectTarget(String id, LocaleId locale) { getTransResource() .getTranslationsWithDocId(locale, id, null, false, null); - assertThat(response.getStatus(), is(404)); + assertThat(response.getStatus()).isEqualTo(404); } private void expectTarget(boolean checkRevs, String id, LocaleId locale, @@ -936,7 +930,7 @@ private void expectTarget(boolean checkRevs, String id, LocaleId locale, getTransResource() .getTranslationsWithDocId(locale, id, extGettextComment, false, null); - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); TranslationsResource actualDoc = getTranslationsResourceFromResponse(response); actualDoc.getLinks(true).clear(); actualDoc.getExtensions(true); @@ -959,8 +953,7 @@ private void expectTarget(boolean checkRevs, String id, LocaleId locale, // Clear Po Headers since Zanata will generate custom ones ResourceTestUtil.clearPoTargetHeaders(actualDoc, expectedDoc); - assertThat(jaxbMarhsal(actualDoc), - Matchers.equalTo(jaxbMarhsal(expectedDoc))); + assertThat(jaxbMarhsal(actualDoc)).isEqualTo(jaxbMarhsal(expectedDoc)); } private Resource createSourceDoc(String name, boolean withTextFlow) { @@ -998,11 +991,11 @@ private Resource createSourceResource(String name) { private void doGetandAssertThatResourceListContainsNItems(int n) { Response resources = getSourceDocResource().get(null); - assertThat(resources.getStatus(), is(Status.OK.getStatusCode())); + assertThat(resources.getStatus()).isEqualTo(Status.OK.getStatusCode()); String entityString = resources.readEntity(String.class); ResourceMeta[] resourceMetas = jsonUnmarshal(entityString, ResourceMeta[].class); - assertThat(resourceMetas.length, is(n)); + assertThat(resourceMetas.length).isEqualTo(n); } private Resource newDoc(String id, TextFlow... textFlows) { @@ -1072,7 +1065,7 @@ private Resource putPo1() { Response response = getSourceDocResource() .putResourceWithDocId(doc, id, extGettextComment, false); - assertThat(response.getStatus(), isOneOf(200, 201)); + assertThat(response.getStatus()).isIn(200, 201); return doc; } @@ -1103,7 +1096,7 @@ private Resource putDoc1(boolean putTarget) { "slime mould comment")); Response response = getSourceDocResource() .putResourceWithDocId(doc, id, extComment, false); - assertThat(response.getStatus(), isOneOf(200, 201)); + assertThat(response.getStatus()).isIn(200, 201); if (putTarget) putTarget1(); @@ -1136,7 +1129,7 @@ private Resource putDoc1a(boolean putTarget) { Resource doc = newDoc(id, newTextFlow("HELLO", "Hello World", null)); Response response = getSourceDocResource() .putResourceWithDocId(doc, id, extComment, false); - assertThat(response.getStatus(), isOneOf(200, 201)); + assertThat(response.getStatus()).isIn(200, 201); if (putTarget) putTarget1a(); @@ -1174,14 +1167,14 @@ private void deleteDoc2() { protected void deleteDoc(String id) { Response response = getSourceDocResource().deleteResourceWithDocId(id); - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isIn(200); } private Resource postDoc2(boolean putTarget) { Resource doc = newDoc(DOC2_NAME, newTextFlow("HELLO", "Hello World", "hello comment")); Response response = getSourceDocResource().post(doc, extComment, true); - assertThat(response.getStatus(), is(201)); + assertThat(response.getStatus()).isIn(201); if (putTarget) putTarget2(); diff --git a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/VersionRawRestITCase.java b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/VersionRawRestITCase.java index 0ab97941d5..4e28c57610 100644 --- a/server/zanata-war/src/test/java/org/zanata/rest/service/raw/VersionRawRestITCase.java +++ b/server/zanata-war/src/test/java/org/zanata/rest/service/raw/VersionRawRestITCase.java @@ -20,8 +20,7 @@ */ package org.zanata.rest.service.raw; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.util.RawRestTestUtils.assertJaxbUnmarshal; import static org.zanata.util.RawRestTestUtils.assertJsonUnmarshal; @@ -65,7 +64,7 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { // OK - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJsonUnmarshal(entityString, VersionInfo.class); } @@ -85,7 +84,7 @@ protected Invocation.Builder prepareRequest(ResteasyWebTarget webTarget) { @Override protected void onResponse(Response response) { // OK - assertThat(response.getStatus(), is(200)); + assertThat(response.getStatus()).isEqualTo(200); String entityString = response.readEntity(String.class); assertJaxbUnmarshal(entityString, VersionInfo.class); } diff --git a/server/zanata-war/src/test/java/org/zanata/search/ContentCriterionTest.java b/server/zanata-war/src/test/java/org/zanata/search/ContentCriterionTest.java index 07bbb4bf79..446bbe0a79 100644 --- a/server/zanata-war/src/test/java/org/zanata/search/ContentCriterionTest.java +++ b/server/zanata-war/src/test/java/org/zanata/search/ContentCriterionTest.java @@ -1,9 +1,8 @@ package org.zanata.search; -import org.hamcrest.Matchers; import org.junit.Test; -import static org.hamcrest.MatcherAssert.*; +import static org.assertj.core.api.Assertions.assertThat; /** * @author Patrick Huang pahuang@redhat.com @@ -132,11 +132,11 @@ public void getAll() { FilterConstraints.builder().build(), documentId); String hql = constraintToQuery.toEntityQuery(); List textFlows = getResultList(hql, constraintToQuery); - assertThat(textFlows, Matchers.hasSize(10)); + assertThat(textFlows).hasSize(10); String navigationQuery = constraintToQuery.toModalNavigationQuery(); List navigationResult = getNavigationResult(navigationQuery, constraintToQuery); - assertThat(navigationResult, Matchers.hasSize(10)); + assertThat(navigationResult).hasSize(10); } @SuppressWarnings("unchecked") @@ -157,7 +157,7 @@ public void filterBySourceContent() { List result = getResultList(hql, constraintToQuery); List ids = transformToResIds(result); log.debug("result: {}", ids); - assertThat(ids, Matchers.contains("res3")); + assertThat(ids).contains("res3"); verifyModalNavigationQuery(constraintToQuery, result); } @@ -171,13 +171,13 @@ private void verifyModalNavigationQuery( private void verifyIdAndContentStateMatches(List one, List two) { - assertThat(one.size(), Matchers.equalTo(two.size())); + assertThat(one.size()).isEqualTo(two.size()); for (int i = 0; i < one.size(); i++) { HTextFlow textFlow1 = one.get(i); HTextFlow textFlow2 = two.get(i); - assertThat(textFlow1.getId(), Matchers.equalTo(textFlow2.getId())); - assertThat(getContentState(textFlow1, hLocale), - Matchers.equalTo(getContentState(textFlow2, hLocale))); + assertThat(textFlow1.getId()).isEqualTo(textFlow2.getId()); + assertThat(getContentState(textFlow1, hLocale)) + .isEqualTo(getContentState(textFlow2, hLocale)); } } @@ -200,7 +200,7 @@ public void filterByContentInSourceAndTarget() { List result = getResultList(hql, constraintToQuery); List ids = transformToResIds(result); log.debug("result: {}", ids); - assertThat(ids, Matchers.contains("res2")); + assertThat(ids).contains("res2"); verifyModalNavigationQuery(constraintToQuery, result); } @@ -215,7 +215,7 @@ public void filterByUntranslated() { List result = getResultList(hql, constraintToQuery); List ids = transformToResIds(result); log.debug("result: {}", ids); - assertThat(ids, Matchers.contains("res1", "res4", "res6", "res7")); + assertThat(ids).contains("res1", "res4", "res6", "res7"); verifyModalNavigationQuery(constraintToQuery, result); } @@ -229,7 +229,7 @@ public void filterByUntranslatedAndSourceContent() { List result = getResultList(hql, constraintToQuery); List ids = transformToResIds(result); log.debug("result: {}", ids); - assertThat(ids, Matchers.contains("res4")); + assertThat(ids).contains("res4"); verifyModalNavigationQuery(constraintToQuery, result); } @@ -243,7 +243,7 @@ public void filterByResId() { List result = getResultList(hql, constraintToQuery); List ids = transformToResIds(result); log.debug("result: {}", ids); - assertThat(ids, Matchers.contains("res2")); + assertThat(ids).contains("res2"); verifyModalNavigationQuery(constraintToQuery, result); } @@ -257,7 +257,7 @@ public void filterByMessageContext() { List result = getResultList(hql, constraintToQuery); List ids = transformToResIds(result); log.debug("result: {}", ids); - assertThat(ids, Matchers.contains("res6")); + assertThat(ids).contains("res6"); verifyModalNavigationQuery(constraintToQuery, result); } @@ -271,7 +271,7 @@ public void filterBySourceComment() { List result = getResultList(hql, constraintToQuery); List ids = transformToResIds(result); log.debug("result: {}", ids); - assertThat(ids, Matchers.contains("res7")); + assertThat(ids).contains("res7"); verifyModalNavigationQuery(constraintToQuery, result); } @@ -285,7 +285,7 @@ public void filterByTargetComment() { List result = getResultList(hql, constraintToQuery); List ids = transformToResIds(result); log.debug("result: {}", ids); - assertThat(ids, Matchers.contains("res5")); + assertThat(ids).contains("res5"); verifyModalNavigationQuery(constraintToQuery, result); } @@ -300,7 +300,7 @@ public void filterByTargetModifiedUser() { List result = getResultList(hql, constraintToQuery); List ids = transformToResIds(result); log.debug("result: {}", ids); - assertThat(ids, Matchers.contains("res9", "res10")); + assertThat(ids).contains("res9", "res10"); verifyModalNavigationQuery(constraintToQuery, result); } @@ -314,8 +314,7 @@ public void filterByTargetChangedDateAfter() { List result = getResultList(hql, constraintToQuery); List ids = transformToResIds(result); log.debug("result: {}", ids); - assertThat(ids, - Matchers.contains("res2", "res3", "res4", "res5", "res9")); + assertThat(ids).contains("res2", "res3", "res4", "res5", "res9"); verifyModalNavigationQuery(constraintToQuery, result); } @@ -329,7 +328,7 @@ public void filterByTargetChangedDateBefore() { List result = getResultList(hql, constraintToQuery); List ids = transformToResIds(result); log.debug("result: {}", ids); - assertThat(ids, Matchers.contains("res8", "res10")); + assertThat(ids).contains("res8", "res10"); verifyModalNavigationQuery(constraintToQuery, result); } @@ -344,7 +343,7 @@ public void filterByUntranslatedAndModifiedPerson() { List result = getResultList(hql, constraintToQuery); List ids = transformToResIds(result); log.debug("result: {}", ids); - assertThat(ids, Matchers.contains("res4")); + assertThat(ids).contains("res4"); verifyModalNavigationQuery(constraintToQuery, result); } @@ -360,7 +359,7 @@ public void filterByContentAndModifiedPersonAndState() { List result = getResultList(hql, constraintToQuery); List ids = transformToResIds(result); log.debug("result: {}", ids); - assertThat(ids, Matchers.contains("res4")); + assertThat(ids).contains("res4"); verifyModalNavigationQuery(constraintToQuery, result); } @@ -374,7 +373,7 @@ public void testEscapeCharacter() { List result = getResultList(hql, constraintToQuery); List ids = transformToResIds(result); log.debug("result: {}", ids); - assertThat(ids, Matchers.contains("res10")); + assertThat(ids).contains("res10"); verifyModalNavigationQuery(constraintToQuery, result); } diff --git a/server/zanata-war/src/test/java/org/zanata/search/FilterConstraintToQueryTest.java b/server/zanata-war/src/test/java/org/zanata/search/FilterConstraintToQueryTest.java index 3221061196..c0a517662f 100644 --- a/server/zanata-war/src/test/java/org/zanata/search/FilterConstraintToQueryTest.java +++ b/server/zanata-war/src/test/java/org/zanata/search/FilterConstraintToQueryTest.java @@ -1,12 +1,11 @@ package org.zanata.search; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import static org.zanata.search.FilterConstraintToQuery.Parameters.*; import java.util.List; -import org.hamcrest.Matchers; import org.hibernate.Query; import org.junit.Before; import org.junit.Test; @@ -52,7 +51,7 @@ public void testBuildSearchConditionWithNothingToSearch() { FilterConstraints.builder().keepAll().build(), documentId); String result = constraintToQuery.buildSearchCondition(); - assertThat(result, Matchers.nullValue()); + assertThat(result).isNull(); } @Test @@ -63,8 +62,8 @@ public void testBuildSearchConditionInSource() { .checkInSource(true).build(), documentId); constraintToQuery.setContentCriterion(contentCriterion); String result = constraintToQuery.buildSearchCondition(); - assertThat(result, Matchers.equalToIgnoringCase( - "(" + SOURCE_CONTENT_CASE_INSENSITIVE + ")")); + assertThat(result).isEqualToIgnoringCase( + "(" + SOURCE_CONTENT_CASE_INSENSITIVE + ")"); } @Test @@ -75,11 +74,10 @@ public void testBuildSearchConditionInTarget() { .checkInTarget(true).build(), documentId); constraintToQuery.setContentCriterion(contentCriterion); String result = constraintToQuery.buildSearchCondition(); - assertThat(result, - Matchers.equalToIgnoringCase( + assertThat(result).isEqualToIgnoringCase( "( EXISTS ( FROM HTextFlowTarget WHERE (" + TARGET_CONTENT_CASE_INSENSITIVE - + " and textFlow=tf and locale=:locale)))")); + + " and textFlow=tf and locale=:locale)))"); } @Test @@ -90,12 +88,11 @@ public void testBuildSearchConditionInBoth() { documentId); constraintToQuery.setContentCriterion(contentCriterion); String result = constraintToQuery.buildSearchCondition(); - assertThat(result, - Matchers.equalToIgnoringCase( + assertThat(result).isEqualToIgnoringCase( "(" + SOURCE_CONTENT_CASE_INSENSITIVE + " OR EXISTS ( FROM HTextFlowTarget WHERE (" + TARGET_CONTENT_CASE_INSENSITIVE - + " AND textFlow=tf and locale=:locale)))")); + + " AND textFlow=tf and locale=:locale)))"); } @Test @@ -106,7 +103,7 @@ public void testBuildStateConditionWithAllState() { documentId); constraintToQuery.setContentCriterion(contentCriterion); String result = constraintToQuery.buildSearchCondition(); - assertThat(result, Matchers.nullValue()); + assertThat(result).isNull(); } @Test @@ -115,8 +112,8 @@ public void testBuildStateConditionWithoutUntranslatedState() { FilterConstraintToQuery.filterInSingleDocument(FilterConstraints .builder().keepAll().excludeNew().build(), documentId); String result = constraintToQuery.buildStateCondition(); - assertThat(result, Matchers.equalToIgnoringCase( - " EXISTS ( FROM HTextFlowTarget WHERE ((textFlow=tf AND locale=:locale) AND state in (:ContentStateList)))")); + assertThat(result).isEqualToIgnoringCase( + " EXISTS ( FROM HTextFlowTarget WHERE ((textFlow=tf AND locale=:locale) AND state in (:ContentStateList)))"); } @Test @@ -125,8 +122,8 @@ public void testBuildStateConditionWithUntranslatedStateButNoSearch() { .filterInSingleDocument(FilterConstraints.builder().keepAll() .excludeTranslated().build(), documentId); String result = constraintToQuery.buildStateCondition(); - assertThat(result, Matchers.equalToIgnoringCase( - "( EXISTS ( FROM HTextFlowTarget WHERE ((textFlow=tf AND locale=:locale) AND state in (:ContentStateList))) OR :locale not in indices(tf.targets))")); + assertThat(result).isEqualToIgnoringCase( + "( EXISTS ( FROM HTextFlowTarget WHERE ((textFlow=tf AND locale=:locale) AND state in (:ContentStateList))) OR :locale not in indices(tf.targets))"); } @Test @@ -139,10 +136,8 @@ public void testBuildStateConditionWithUntranslatedStateAndSearch() { documentId); constraintToQuery.setContentCriterion(contentCriterion); String result = constraintToQuery.buildStateCondition(); - assertThat(result, - Matchers.equalToIgnoringCase( - "( EXISTS ( FROM HTextFlowTarget WHERE ((textFlow=tf and locale=:locale) AND state in (:ContentStateList))) OR (:locale not in indices(tf.targets) AND " - + SOURCE_CONTENT_CASE_INSENSITIVE + "))")); + assertThat(result).isEqualToIgnoringCase( + "( EXISTS ( FROM HTextFlowTarget WHERE ((textFlow=tf and locale=:locale) AND state in (:ContentStateList))) OR (:locale not in indices(tf.targets) AND " + SOURCE_CONTENT_CASE_INSENSITIVE + "))"); } @Test @@ -152,8 +147,8 @@ public void testToHQLWithNoCondition() { FilterConstraints.builder().keepAll().build(), documentId); String result = constraintToQuery.toEntityQuery(); - assertThat(result, Matchers.equalToIgnoringCase(QUERY_BEFORE_WHERE - + "WHERE (tf.obsolete=0 AND tf.document.id=:documentId) ORDER BY tf.pos")); + assertThat(result).isEqualToIgnoringCase(QUERY_BEFORE_WHERE + + "WHERE (tf.obsolete=0 AND tf.document.id=:documentId) ORDER BY tf.pos"); } @Test @@ -163,8 +158,8 @@ public void testToHQLWithNoConditionForMultipleDocuments() { FilterConstraints.builder().keepAll().build(), Lists.newArrayList(1L)); String result = constraintToQuery.toEntityQuery(); - assertThat(result, Matchers.equalToIgnoringCase(QUERY_BEFORE_WHERE - + "WHERE (tf.obsolete=0 AND tf.document.id in (:documentIdList)) ORDER BY tf.pos")); + assertThat(result).isEqualToIgnoringCase(QUERY_BEFORE_WHERE + + "WHERE (tf.obsolete=0 AND tf.document.id in (:documentIdList)) ORDER BY tf.pos"); } @Test @@ -190,8 +185,8 @@ public void testToHQLWithSearchAndStateCondition() { * ) OR ( :locale NOT IN indices(tf.targets) AND ( lower(tf.content0) * LIKE :searchString ) ) ) ) ORDER BY tf.pos */ - assertThat(result, Matchers.equalToIgnoringCase( - "SELECT distinct tf FROM HTextFlow tf LEFT JOIN tf.targets tfts WITH tfts.index=:locale WHERE (tf.obsolete=0 AND tf.document.id=:documentId AND ((lower(tf.content0) like :searchString) OR EXISTS ( FROM HTextFlowTarget WHERE ((lower(content0) like :searchString) AND textFlow=tf AND locale=:locale))) AND ( EXISTS ( FROM HTextFlowTarget WHERE ((textFlow=tf AND locale=:locale) AND state in (:ContentStateList))) OR (:locale not in indices(tf.targets) AND (lower(tf.content0) like :searchString)))) ORDER BY tf.pos")); + assertThat(result).isEqualToIgnoringCase( + "SELECT distinct tf FROM HTextFlow tf LEFT JOIN tf.targets tfts WITH tfts.index=:locale WHERE (tf.obsolete=0 AND tf.document.id=:documentId AND ((lower(tf.content0) like :searchString) OR EXISTS ( FROM HTextFlowTarget WHERE ((lower(content0) like :searchString) AND textFlow=tf AND locale=:locale))) AND ( EXISTS ( FROM HTextFlowTarget WHERE ((textFlow=tf AND locale=:locale) AND state in (:ContentStateList))) OR (:locale not in indices(tf.targets) AND (lower(tf.content0) like :searchString)))) ORDER BY tf.pos"); } @Test diff --git a/server/zanata-war/src/test/java/org/zanata/service/impl/ActivityServiceImplTest.java b/server/zanata-war/src/test/java/org/zanata/service/impl/ActivityServiceImplTest.java index 79b95dedfe..1ca0c07feb 100644 --- a/server/zanata-war/src/test/java/org/zanata/service/impl/ActivityServiceImplTest.java +++ b/server/zanata-war/src/test/java/org/zanata/service/impl/ActivityServiceImplTest.java @@ -20,17 +20,12 @@ */ package org.zanata.service.impl; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.nullValue; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; import java.util.Date; import java.util.List; -import com.google.common.base.Throwables; - import org.dbunit.operation.DatabaseOperation; import org.hibernate.Session; import org.jglue.cdiunit.AdditionalClasses; @@ -133,8 +128,8 @@ public void testNewReviewActivityInserted() throws Exception { activityService.findActivity(personId, EntityType.HProjectIteration, projectVersionId, ActivityType.REVIEWED_TRANSLATION, new Date()); - assertThat(activity, not(nullValue())); - assertThat(activity.getEventCount(), equalTo(1)); + assertThat(activity).isNotNull(); + assertThat(activity.getEventCount()).isEqualTo(1); } @Test @@ -149,7 +144,7 @@ public void testNewReviewActivityUpdated() throws Exception { List activities = activityService.findLatestActivitiesForContext(personId, projectVersionId, 0, 10); - assertThat(activities.size(), equalTo(1)); + assertThat(activities.size()).isEqualTo(1); TextFlowTargetStateEvent event2 = buildEvent(personId, versionId, documentId, null, @@ -161,13 +156,13 @@ public void testNewReviewActivityUpdated() throws Exception { activities = activityService.findLatestActivitiesForContext(personId, projectVersionId, 0, 10); - assertThat(activities.size(), equalTo(1)); + assertThat(activities.size()).isEqualTo(1); Activity activity = activityService.findActivity(personId, EntityType.HProjectIteration, projectVersionId, ActivityType.REVIEWED_TRANSLATION, new Date()); - assertThat(activity.getEventCount(), equalTo(2)); + assertThat(activity.getEventCount()).isEqualTo(2); } @Test @@ -184,7 +179,7 @@ public void testActivityInsertAndUpdate() throws Exception { activityService.findActivity(personId, EntityType.HProjectIteration, projectVersionId, ActivityType.UPDATE_TRANSLATION, new Date()); - assertThat(activity, not(nullValue())); + assertThat(activity).isNotNull(); Long id = activity.getId(); @@ -197,7 +192,7 @@ public void testActivityInsertAndUpdate() throws Exception { activityService.findActivity(personId, EntityType.HProjectIteration, projectVersionId, ActivityType.UPDATE_TRANSLATION, new Date()); - assertThat(activity.getId(), equalTo(id)); + assertThat(activity.getId()).isEqualTo(id); } @Test @@ -223,7 +218,7 @@ public void testActivityInsertMultipleTypeActivities() throws Exception { List activities = activityService.findLatestActivitiesForContext(personId, projectVersionId, 0, 5); - assertThat(activities.size(), equalTo(3)); + assertThat(activities.size()).isEqualTo(3); } @Test @@ -260,7 +255,7 @@ public void testGetAllPersonActivities() throws Exception { activityService.findLatestActivitiesForContext(personId, projectVersionId, 0, 10); - assertThat(activities.size(), equalTo(2)); + assertThat(activities.size()).isEqualTo(2); } private TextFlowTargetStateEvent buildEvent(Long personId, Long versionId, diff --git a/server/zanata-war/src/test/java/org/zanata/service/impl/CopyTransWorkTest.java b/server/zanata-war/src/test/java/org/zanata/service/impl/CopyTransWorkTest.java index 1ec988128f..eefb83631f 100644 --- a/server/zanata-war/src/test/java/org/zanata/service/impl/CopyTransWorkTest.java +++ b/server/zanata-war/src/test/java/org/zanata/service/impl/CopyTransWorkTest.java @@ -28,8 +28,7 @@ import java.util.List; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.common.ContentState.Approved; import static org.zanata.common.ContentState.NeedReview; import static org.zanata.common.ContentState.New; @@ -53,10 +52,10 @@ public void basicDetermineContentState() { for (ContentState state : validTranslatedStates) { assertThat(CopyTransWorkFactory.determineContentStateFromRuleList( Lists. newArrayList(), - true, state), is(state)); + true, state)).isEqualTo(state); assertThat(CopyTransWorkFactory.determineContentStateFromRuleList( Lists. newArrayList(), - false, state), is(Translated)); + false, state)).isEqualTo(Translated); } } @@ -68,19 +67,19 @@ public void contentStateWithIgnoreRule() { assertThat(CopyTransWorkFactory.determineContentStateFromRuleList( Lists.newArrayList(new MatchRulePair( Suppliers.ofInstance(true), IGNORE)), true, state - ), is(state)); + )).isEqualTo(state); assertThat(CopyTransWorkFactory.determineContentStateFromRuleList( Lists.newArrayList(new MatchRulePair( Suppliers.ofInstance(false), IGNORE)), true, state - ), is(state)); + )).isEqualTo(state); assertThat(CopyTransWorkFactory.determineContentStateFromRuleList( Lists.newArrayList(new MatchRulePair( Suppliers.ofInstance(true), IGNORE)), false, state - ), is(Translated)); + )).isEqualTo(Translated); assertThat(CopyTransWorkFactory.determineContentStateFromRuleList( Lists.newArrayList(new MatchRulePair( Suppliers.ofInstance(false), IGNORE)), false, state - ), is(Translated)); + )).isEqualTo(Translated); } } @@ -92,19 +91,19 @@ public void contentStateWithRejectRule() { assertThat(CopyTransWorkFactory.determineContentStateFromRuleList( Lists.newArrayList(new MatchRulePair( Suppliers.ofInstance(true), REJECT)), true, state - ), is(state)); + )).isEqualTo(state); assertThat(CopyTransWorkFactory.determineContentStateFromRuleList( Lists.newArrayList(new MatchRulePair( Suppliers.ofInstance(false), REJECT)), true, state - ), is(New)); + )).isEqualTo(New); assertThat(CopyTransWorkFactory.determineContentStateFromRuleList( Lists.newArrayList(new MatchRulePair( Suppliers.ofInstance(true), REJECT)), false, state - ), is(Translated)); + )).isEqualTo(Translated); assertThat(CopyTransWorkFactory.determineContentStateFromRuleList( Lists.newArrayList(new MatchRulePair( Suppliers.ofInstance(false), REJECT)), false, state - ), is(New)); + )).isEqualTo(New); } } @@ -117,31 +116,31 @@ public void contentStateWithDowngradeRule() { Lists.newArrayList(new MatchRulePair( Suppliers.ofInstance(true), DOWNGRADE_TO_FUZZY)), true, state - ), is(state)); + )).isEqualTo(state); assertThat(CopyTransWorkFactory.determineContentStateFromRuleList( Lists.newArrayList( new MatchRulePair( Suppliers.ofInstance(false), DOWNGRADE_TO_FUZZY)), true, state - ), - is(NeedReview)); + )) + .isEqualTo(NeedReview); assertThat(CopyTransWorkFactory.determineContentStateFromRuleList( Lists.newArrayList( new MatchRulePair( Suppliers.ofInstance(true), DOWNGRADE_TO_FUZZY)), false, state - ), - is(Translated)); + )) + .isEqualTo(Translated); assertThat(CopyTransWorkFactory.determineContentStateFromRuleList( Lists.newArrayList( new MatchRulePair( Suppliers.ofInstance(false), DOWNGRADE_TO_FUZZY)), false, state - ), - is(NeedReview)); + )) + .isEqualTo(NeedReview); } } @@ -157,20 +156,20 @@ public void failedRejectionRule() { REJECT) ), true, Translated - ), is(New)); + )).isEqualTo(New); assertThat(CopyTransWorkFactory.determineContentStateFromRuleList(Lists .newArrayList(new MatchRulePair(Suppliers.ofInstance(true), IGNORE), new MatchRulePair(Suppliers.ofInstance(false), - REJECT)), false, Translated), is(New)); + REJECT)), false, Translated)).isEqualTo(New); assertThat(CopyTransWorkFactory.determineContentStateFromRuleList(Lists .newArrayList(new MatchRulePair(Suppliers.ofInstance(false), REJECT), new MatchRulePair(Suppliers.ofInstance(false), - DOWNGRADE_TO_FUZZY)), true, Translated), is(New)); + DOWNGRADE_TO_FUZZY)), true, Translated)).isEqualTo(New); assertThat(CopyTransWorkFactory.determineContentStateFromRuleList(Lists .newArrayList(new MatchRulePair(Suppliers.ofInstance(false), REJECT), new MatchRulePair(Suppliers.ofInstance(true), - IGNORE)), false, Translated), is(New)); + IGNORE)), false, Translated)).isEqualTo(New); } @Test @@ -185,7 +184,7 @@ public void failedDowngradeRule() { REJECT) ), true, Translated - ), is(NeedReview)); + )).isEqualTo(NeedReview); assertThat(CopyTransWorkFactory.determineContentStateFromRuleList(Lists .newArrayList( new MatchRulePair(Suppliers.ofInstance(false), @@ -194,7 +193,7 @@ public void failedDowngradeRule() { REJECT) ), false, Translated - ), is(NeedReview)); + )).isEqualTo(NeedReview); assertThat(CopyTransWorkFactory.determineContentStateFromRuleList(Lists .newArrayList( new MatchRulePair(Suppliers.ofInstance(false), @@ -203,7 +202,7 @@ public void failedDowngradeRule() { IGNORE) ), true, Approved - ), is(NeedReview)); + )).isEqualTo(NeedReview); assertThat(CopyTransWorkFactory.determineContentStateFromRuleList(Lists .newArrayList( new MatchRulePair(Suppliers.ofInstance(false), @@ -212,7 +211,7 @@ public void failedDowngradeRule() { IGNORE) ), true, Approved - ), is(NeedReview)); + )).isEqualTo(NeedReview); } @Test @@ -221,16 +220,16 @@ public void determineContentStateFromRuleListBasics() { // and NO rules are evaluated assertThat(CopyTransWorkFactory.determineContentStateFromRuleList( Lists. newArrayList(), - true, Translated), is(Translated)); + true, Translated)).isEqualTo(Translated); assertThat(CopyTransWorkFactory.determineContentStateFromRuleList( Lists. newArrayList(), - false, Translated), is(Translated)); + false, Translated)).isEqualTo(Translated); assertThat(CopyTransWorkFactory.determineContentStateFromRuleList( Lists. newArrayList(), - true, Approved), is(Approved)); + true, Approved)).isEqualTo(Approved); assertThat(CopyTransWorkFactory.determineContentStateFromRuleList( Lists. newArrayList(), - false, Approved), is(Translated)); + false, Approved)).isEqualTo(Translated); } } diff --git a/server/zanata-war/src/test/java/org/zanata/service/impl/DocumentServiceImplTest.java b/server/zanata-war/src/test/java/org/zanata/service/impl/DocumentServiceImplTest.java index 77e1610c7e..2a723a8901 100644 --- a/server/zanata-war/src/test/java/org/zanata/service/impl/DocumentServiceImplTest.java +++ b/server/zanata-war/src/test/java/org/zanata/service/impl/DocumentServiceImplTest.java @@ -21,9 +21,7 @@ package org.zanata.service.impl; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @@ -166,11 +164,11 @@ public void documentMilestoneEventTranslatedTest() { eq(projectSlug), eq(versionSlug), eq(docIdString), eq(localeId), eq(message), eq(testUrl), captor.capture()); - assertThat(captor.getValue().size(), is(2)); - assertThat((captor.getValue().get(0)).getTypes(), - contains(WebhookType.DocumentMilestoneEvent)); - assertThat((captor.getValue().get(1)).getTypes(), - contains(WebhookType.DocumentMilestoneEvent)); + assertThat(captor.getValue().size()).isEqualTo(2); + assertThat((captor.getValue().get(0)).getTypes()) + .contains(WebhookType.DocumentMilestoneEvent); + assertThat((captor.getValue().get(1)).getTypes()) + .contains(WebhookType.DocumentMilestoneEvent); } @Test @@ -203,11 +201,11 @@ public void documentMilestoneEventApprovedTest() { eq(projectSlug), eq(versionSlug), eq(docIdString), eq(localeId), eq(message), eq(testUrl), captor.capture()); - assertThat(captor.getValue().size(), is(2)); - assertThat((captor.getValue().get(0)).getTypes(), - contains(WebhookType.DocumentMilestoneEvent)); - assertThat((captor.getValue().get(1)).getTypes(), - contains(WebhookType.DocumentMilestoneEvent)); + assertThat(captor.getValue().size()).isEqualTo(2); + assertThat((captor.getValue().get(0)).getTypes()) + .contains(WebhookType.DocumentMilestoneEvent); + assertThat((captor.getValue().get(1)).getTypes()) + .contains(WebhookType.DocumentMilestoneEvent); } @Test diff --git a/server/zanata-war/src/test/java/org/zanata/service/impl/GlossarySearchServiceImplTest.java b/server/zanata-war/src/test/java/org/zanata/service/impl/GlossarySearchServiceImplTest.java index ca14f29fd4..b3057b4907 100644 --- a/server/zanata-war/src/test/java/org/zanata/service/impl/GlossarySearchServiceImplTest.java +++ b/server/zanata-war/src/test/java/org/zanata/service/impl/GlossarySearchServiceImplTest.java @@ -1,8 +1,6 @@ package org.zanata.service.impl; import com.google.common.collect.Lists; -import net.customware.gwt.dispatch.shared.ActionException; -import org.hamcrest.Matchers; import org.jglue.cdiunit.InRequestScope; import org.junit.Test; import org.junit.runner.RunWith; @@ -10,7 +8,6 @@ import org.zanata.ZanataTest; import org.zanata.common.LocaleId; import org.zanata.dao.GlossaryDAO; -import org.zanata.exception.ZanataServiceException; import org.zanata.model.*; import org.zanata.rest.service.GlossaryService; import org.zanata.security.ZanataIdentity; @@ -18,9 +15,7 @@ import org.zanata.test.CdiUnitRunner; import org.zanata.util.UrlUtil; import org.zanata.webtrans.shared.model.GlossaryDetails; -import org.zanata.webtrans.shared.model.ProjectIterationId; import org.zanata.webtrans.shared.model.WorkspaceId; -import org.zanata.webtrans.shared.rpc.GetGlossaryDetailsAction; import javax.enterprise.inject.Any; import javax.enterprise.inject.Produces; @@ -28,8 +23,7 @@ import java.util.ArrayList; import java.util.Date; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Mockito.verify; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; @RunWith(CdiUnitRunner.class) @@ -90,8 +84,7 @@ public void testLookupDetails() throws Exception { // is tested in the GetGlossaryDetailsHandler test. // verify(identity).checkLoggedIn(); - assertThat(result, Matchers.hasSize(1)); - assertThat(result.get(0).getTarget(), - Matchers.equalTo("target term")); + assertThat(result).hasSize(1); + assertThat(result.get(0).getTarget()).isEqualTo("target term"); } } diff --git a/server/zanata-war/src/test/java/org/zanata/service/impl/LockManagerServiceImplTest.java b/server/zanata-war/src/test/java/org/zanata/service/impl/LockManagerServiceImplTest.java index 93c7240c97..b26d4a2893 100644 --- a/server/zanata-war/src/test/java/org/zanata/service/impl/LockManagerServiceImplTest.java +++ b/server/zanata-war/src/test/java/org/zanata/service/impl/LockManagerServiceImplTest.java @@ -21,7 +21,6 @@ package org.zanata.service.impl; import org.jglue.cdiunit.deltaspike.SupportDeltaspikeCore; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.zanata.ZanataTest; @@ -35,9 +34,7 @@ import javax.enterprise.inject.Produces; import javax.inject.Inject; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; /** * This service does not inject other components, so it can be tested without a @@ -69,12 +66,12 @@ public void simpleLock() { boolean lockAquired = lockManagerService.checkAndAttain(l1); - assertThat(lockAquired, is(true)); + assertThat(lockAquired).isTrue(); lockManagerService.release(l1); lockAquired = lockManagerService.checkAndAttain(l1); - assertThat(lockAquired, is(true)); + assertThat(lockAquired).isTrue(); lockManagerService.release(l1); } @@ -84,22 +81,22 @@ public void deniedLock() { Lock l1Eq = new Lock("prop1", "prop2", "prop3"); Lock l2 = new Lock("prop1", "prop2"); - assertThat(l1, equalTo(l1Eq)); + assertThat(l1).isEqualTo(l1Eq); boolean lockAquired = lockManagerService.checkAndAttain(l1); - assertThat(lockAquired, is(true)); + assertThat(lockAquired).isTrue(); // Same lock, should not aquire lockAquired = lockManagerService.checkAndAttain(l1Eq); - assertThat(lockAquired, is(false)); + assertThat(lockAquired).isFalse(); // different lock lockAquired = lockManagerService.checkAndAttain(l2); - assertThat(lockAquired, is(true)); + assertThat(lockAquired).isTrue(); lockManagerService.release(l1Eq); lockAquired = lockManagerService.checkAndAttain(l1Eq); - assertThat(lockAquired, is(true)); + assertThat(lockAquired).isTrue(); lockManagerService.release(l1Eq); lockManagerService.release(l2); diff --git a/server/zanata-war/src/test/java/org/zanata/service/impl/TextFlowSearchServiceImplTest.java b/server/zanata-war/src/test/java/org/zanata/service/impl/TextFlowSearchServiceImplTest.java index 20ce104712..d630c33bb3 100644 --- a/server/zanata-war/src/test/java/org/zanata/service/impl/TextFlowSearchServiceImplTest.java +++ b/server/zanata-war/src/test/java/org/zanata/service/impl/TextFlowSearchServiceImplTest.java @@ -3,7 +3,6 @@ import java.util.List; import org.dbunit.operation.DatabaseOperation; -import org.hamcrest.Matchers; import org.hibernate.Session; import org.hibernate.search.FullTextSession; import org.hibernate.search.jpa.FullTextEntityManager; @@ -28,7 +27,7 @@ import javax.enterprise.inject.Produces; import javax.inject.Inject; -import static org.hamcrest.MatcherAssert.*; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.*; /** @@ -90,6 +89,6 @@ public void testFindTextFlows() throws Exception { service.findTextFlows(workspaceId, FilterConstraints.builder() .filterBy("file").build()); - assertThat(result.size(), Matchers.equalTo(7)); + assertThat(result).hasSize(7); } } diff --git a/server/zanata-war/src/test/java/org/zanata/service/impl/TransMemoryMergeServiceImplTest.java b/server/zanata-war/src/test/java/org/zanata/service/impl/TransMemoryMergeServiceImplTest.java index 6a1b48d7d3..aaafeeeda1 100644 --- a/server/zanata-war/src/test/java/org/zanata/service/impl/TransMemoryMergeServiceImplTest.java +++ b/server/zanata-war/src/test/java/org/zanata/service/impl/TransMemoryMergeServiceImplTest.java @@ -22,7 +22,7 @@ package org.zanata.service.impl; import static com.google.common.collect.Lists.newArrayList; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; @@ -36,11 +36,9 @@ import java.util.List; import java.util.Optional; -import javax.enterprise.inject.Alternative; import javax.enterprise.inject.Produces; import javax.inject.Inject; -import org.hamcrest.Matchers; import org.jglue.cdiunit.InRequestScope; import org.junit.Before; import org.junit.Test; @@ -303,15 +301,16 @@ public void willTranslateIfMatches() throws ActionException { List updateRequest = updateRequestCaptor.getValue(); - assertThat(updateRequest, Matchers.hasSize(1)); + assertThat(updateRequest).hasSize(1); TransUnitUpdateRequest transUnitUpdateRequest = updateRequest.get(0); - assertThat(transUnitUpdateRequest.getNewContents(), - Matchers.equalTo(mostSimilarTM.getTargetContents())); - assertThat(transUnitUpdateRequest.getSourceType(), - Matchers.equalTo(TranslationSourceType.TM_MERGE.getAbbr())); + assertThat(transUnitUpdateRequest.getNewContents()) + .isEqualTo(mostSimilarTM.getTargetContents()); + assertThat(transUnitUpdateRequest.getSourceType()) + .isEqualTo(TranslationSourceType.TM_MERGE.getAbbr()); assertThat( - transUnitUpdateRequest.getTargetComment(), - Matchers.equalTo("auto translated by TM merge from project: project a, version: master, DocId: pot/msg.pot")); + transUnitUpdateRequest.getTargetComment()) + .isEqualTo( + "auto translated by TM merge from project: project a, version: master, DocId: pot/msg.pot"); } @Test @@ -443,20 +442,20 @@ public void canHandleMultipleTextFlows() throws ActionException { List updateRequest = updateRequestCaptor.getValue(); - assertThat(updateRequest, Matchers.hasSize(3)); - assertThat(updateRequest.get(0).getNewContents(), - Matchers.equalTo(tm100.get().getTargetContents())); - assertThat(updateRequest.get(1).getNewContents(), - Matchers.equalTo(tm90.get().getTargetContents())); - assertThat(updateRequest.get(2).getNewContents(), - Matchers.equalTo(tm80.get().getTargetContents())); - - assertThat(updateRequest.get(0).getSourceType(), - Matchers.equalTo(TranslationSourceType.TM_MERGE.getAbbr())); - assertThat(updateRequest.get(1).getSourceType(), - Matchers.equalTo(TranslationSourceType.TM_MERGE.getAbbr())); - assertThat(updateRequest.get(2).getSourceType(), - Matchers.equalTo(TranslationSourceType.TM_MERGE.getAbbr())); + assertThat(updateRequest).hasSize(3); + assertThat(updateRequest.get(0).getNewContents()) + .isEqualTo(tm100.get().getTargetContents()); + assertThat(updateRequest.get(1).getNewContents()) + .isEqualTo(tm90.get().getTargetContents()); + assertThat(updateRequest.get(2).getNewContents()) + .isEqualTo(tm80.get().getTargetContents()); + + assertThat(updateRequest.get(0).getSourceType()) + .isEqualTo(TranslationSourceType.TM_MERGE.getAbbr()); + assertThat(updateRequest.get(1).getSourceType()) + .isEqualTo(TranslationSourceType.TM_MERGE.getAbbr()); + assertThat(updateRequest.get(2).getSourceType()) + .isEqualTo(TranslationSourceType.TM_MERGE.getAbbr()); } @Test @@ -519,14 +518,14 @@ public void canAutoTranslateImportedTMResults() throws Exception { List updateRequest = updateRequestCaptor.getValue(); - assertThat(updateRequest, Matchers.hasSize(1)); + assertThat(updateRequest).hasSize(1); TransUnitUpdateRequest transUnitUpdateRequest = updateRequest.get(0); - assertThat(transUnitUpdateRequest.getNewContents(), - Matchers.equalTo(mostSimilarTM.getTargetContents())); + assertThat(transUnitUpdateRequest.getNewContents()) + .isEqualTo(mostSimilarTM.getTargetContents()); assertThat( - transUnitUpdateRequest.getTargetComment(), - Matchers.equalTo("auto translated by TM merge from translation memory: test-tm, unique id: uid10")); - assertThat(transUnitUpdateRequest.getSourceType(), - Matchers.equalTo(TranslationSourceType.TM_MERGE.getAbbr())); + transUnitUpdateRequest.getTargetComment()) + .isEqualTo("auto translated by TM merge from translation memory: test-tm, unique id: uid10"); + assertThat(transUnitUpdateRequest.getSourceType()) + .isEqualTo(TranslationSourceType.TM_MERGE.getAbbr()); } } diff --git a/server/zanata-war/src/test/java/org/zanata/service/impl/TranslationFileServiceImplTest.java b/server/zanata-war/src/test/java/org/zanata/service/impl/TranslationFileServiceImplTest.java index 1398907bd0..7692d1f855 100644 --- a/server/zanata-war/src/test/java/org/zanata/service/impl/TranslationFileServiceImplTest.java +++ b/server/zanata-war/src/test/java/org/zanata/service/impl/TranslationFileServiceImplTest.java @@ -20,9 +20,6 @@ */ package org.zanata.service.impl; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; - import org.hibernate.Session; import org.jglue.cdiunit.InRequestScope; import org.junit.Test; @@ -35,6 +32,8 @@ import javax.enterprise.inject.Produces; import javax.inject.Inject; +import static org.assertj.core.api.Assertions.assertThat; + @RunWith(CdiUnitRunner.class) public class TranslationFileServiceImplTest extends ZanataTest { @@ -46,7 +45,6 @@ public class TranslationFileServiceImplTest extends ZanataTest { @Test @InRequestScope public void hasPlainTextAdapter() { - assertThat(transFileService.hasAdapterFor(DocumentType.PLAIN_TEXT), - is(true)); + assertThat(transFileService.hasAdapterFor(DocumentType.PLAIN_TEXT)).isTrue(); } } diff --git a/server/zanata-war/src/test/java/org/zanata/service/impl/TranslationMergeServiceFactoryTest.java b/server/zanata-war/src/test/java/org/zanata/service/impl/TranslationMergeServiceFactoryTest.java index 89c3219004..42668f93d8 100644 --- a/server/zanata-war/src/test/java/org/zanata/service/impl/TranslationMergeServiceFactoryTest.java +++ b/server/zanata-war/src/test/java/org/zanata/service/impl/TranslationMergeServiceFactoryTest.java @@ -1,6 +1,5 @@ package org.zanata.service.impl; -import org.hamcrest.Matchers; import org.hibernate.Session; import org.jglue.cdiunit.InRequestScope; import org.junit.Test; @@ -15,7 +14,7 @@ import javax.enterprise.inject.Produces; import javax.inject.Inject; -import static org.hamcrest.MatcherAssert.*; +import static org.assertj.core.api.Assertions.assertThat; /** * @author Patrick Huang result = transService.translate(new LocaleId("de"), translationRequests); - assertThat(result.get(0).isTranslationSuccessful(), Matchers.is(false)); + assertThat(result.get(0).isTranslationSuccessful()).isFalse(); } @Test @@ -232,13 +230,13 @@ public void willCheckPermissionForReviewState() { verify(identity).checkPermission(eq("translation-review"), isA(HProject.class), isA(HLocale.class)); - assertThat(result.get(0).isTranslationSuccessful(), is(true)); - assertThat(result.get(0).getBaseVersionNum(), is(0)); - assertThat(result.get(0).getTranslatedTextFlowTarget().getVersionNum(), - is(1)); // moved up only one version - assertThat(result.get(0).getTranslatedTextFlowTarget().getState(), - is(ContentState.Approved)); - assertThat(result.get(0).getTranslatedTextFlowTarget().getSourceType(), - is(TranslationSourceType.MERGE_VERSION)); + assertThat(result.get(0).isTranslationSuccessful()).isTrue(); + assertThat(result.get(0).getBaseVersionNum()).isEqualTo(0); + assertThat(result.get(0).getTranslatedTextFlowTarget().getVersionNum()) + .isEqualTo(1); // moved up only one version + assertThat(result.get(0).getTranslatedTextFlowTarget().getState()) + .isEqualTo(ContentState.Approved); + assertThat(result.get(0).getTranslatedTextFlowTarget().getSourceType()) + .isEqualTo(TranslationSourceType.MERGE_VERSION); } } diff --git a/server/zanata-war/src/test/java/org/zanata/service/impl/TranslationStateCacheImplTest.java b/server/zanata-war/src/test/java/org/zanata/service/impl/TranslationStateCacheImplTest.java index 631c740f74..5ab6578ec0 100644 --- a/server/zanata-war/src/test/java/org/zanata/service/impl/TranslationStateCacheImplTest.java +++ b/server/zanata-war/src/test/java/org/zanata/service/impl/TranslationStateCacheImplTest.java @@ -47,8 +47,7 @@ import java.util.HashMap; import java.util.Map; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -97,8 +96,8 @@ public void testGetLastModifiedTextFlowTarget() throws Exception { // Then: verify(docStatusLoader).load(key); // only load the value once - assertThat(result1, equalTo(docStats)); - assertThat(result2, equalTo(docStats)); + assertThat(result1).isEqualTo(docStats); + assertThat(result2).isEqualTo(docStats); } @Test @@ -118,7 +117,7 @@ public void testTextFlowTargetHasError() throws Exception { // Then: verify(targetValidationLoader).load(targetId); // only load the value // once - assertThat(result, equalTo(null)); + assertThat(result).isNull(); } @Test @@ -139,6 +138,6 @@ public void testTextFlowTargetHasError2() throws Exception { // Then: verify(targetValidationLoader).load(targetId); // only load the value // once - assertThat(result, equalTo(true)); + assertThat(result).isTrue(); } } diff --git a/server/zanata-war/src/test/java/org/zanata/service/impl/TranslationUpdatedManagerTest.java b/server/zanata-war/src/test/java/org/zanata/service/impl/TranslationUpdatedManagerTest.java index f550373cee..601049ea49 100644 --- a/server/zanata-war/src/test/java/org/zanata/service/impl/TranslationUpdatedManagerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/service/impl/TranslationUpdatedManagerTest.java @@ -52,10 +52,7 @@ import com.google.common.collect.Lists; import com.google.common.collect.Sets; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.is; - +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -152,8 +149,8 @@ public void onDocStatUpdateTest() { verify(webhookService).processDocumentStats(eq(username), eq(projectSlug), eq(versionSlug), eq(strDocId), eq(localeId), eq(contentStates), captor.capture()); - assertThat(captor.getValue().size(), is(1)); - assertThat((captor.getValue().get(0)).getTypes(), - contains(WebhookType.DocumentStatsEvent)); + assertThat(captor.getValue().size()).isEqualTo(1); + assertThat((captor.getValue().get(0)).getTypes()) + .contains(WebhookType.DocumentStatsEvent); } } diff --git a/server/zanata-war/src/test/java/org/zanata/service/impl/UserAccountServiceImplTest.java b/server/zanata-war/src/test/java/org/zanata/service/impl/UserAccountServiceImplTest.java index b4a60f51c0..5a67003058 100644 --- a/server/zanata-war/src/test/java/org/zanata/service/impl/UserAccountServiceImplTest.java +++ b/server/zanata-war/src/test/java/org/zanata/service/impl/UserAccountServiceImplTest.java @@ -20,10 +20,7 @@ */ package org.zanata.service.impl; -import java.util.ArrayList; - import org.dbunit.operation.DatabaseOperation; -import org.hamcrest.Matchers; import org.hibernate.Session; import org.jglue.cdiunit.AdditionalClasses; import org.jglue.cdiunit.InRequestScope; @@ -33,7 +30,6 @@ import org.zanata.ZanataDbunitJpaTest; import org.zanata.model.HAccount; import org.zanata.model.HAccountResetPasswordKey; -import org.zanata.model.HAccountRole; import org.zanata.model.security.HCredentials; import org.zanata.model.security.HOpenIdCredentials; import org.zanata.model.validator.UniqueValidator; @@ -43,9 +39,7 @@ import javax.inject.Inject; import javax.persistence.EntityManager; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.hasProperty; -import static org.hamcrest.Matchers.not; +import static org.assertj.core.api.Assertions.assertThat; /** * @author Carlos Munoz (account.getRoles()), - not(Matchers. hasItem(hasProperty("name", - Matchers.is("admin"))))); + assertThat(account.getRoles()).extracting("name").doesNotContain("admin"); account = userAccountService.runRoleAssignmentRules(account, null, "zanata"); // Now it's admin - assertThat( - new ArrayList(account.getRoles()), - Matchers. hasItem(hasProperty("name", - Matchers.is("admin")))); + assertThat(account.getRoles()).extracting("name").contains("admin"); } @Test @@ -122,18 +111,13 @@ Matchers. hasItem(hasProperty("name", public void assignedFedoraRule() { // Non Fedora account HAccount account = createFedoraAccount(); - assertThat(new ArrayList(account.getRoles()), - not(Matchers. hasItem(hasProperty("name", - Matchers.is("Fedora"))))); + assertThat(account.getRoles()).extracting("name").doesNotContain("Fedora"); account = userAccountService.runRoleAssignmentRules(account, account .getCredentials().iterator().next(), "fedora"); // Now it's fedora - assertThat( - new ArrayList(account.getRoles()), - Matchers. hasItem(hasProperty("name", - Matchers.is("Fedora")))); + assertThat(account.getRoles()).extracting("name").contains("Fedora"); } @Test @@ -141,17 +125,13 @@ Matchers. hasItem(hasProperty("name", public void notAssignedFedoraRule() { // Non Fedora account HAccount account = em.find(HAccount.class, 3L); - assertThat(new ArrayList(account.getRoles()), - not(Matchers. hasItem(hasProperty("name", - Matchers.is("Fedora"))))); + assertThat(account.getRoles()).extracting("name").doesNotContain("Fedora"); account = userAccountService.runRoleAssignmentRules(account, null, "fedora"); // It's still not Fedora - assertThat(new ArrayList(account.getRoles()), - not(Matchers. hasItem(hasProperty("name", - Matchers.is("Fedora"))))); + assertThat(account.getRoles()).extracting("name").doesNotContain("Fedora"); } @Test @@ -159,14 +139,14 @@ public void notAssignedFedoraRule() { public void requestPasswordReset() { // account with no reset password key HAccount account = em.find(HAccount.class, 3L); - assertThat(account.getAccountResetPasswordKey(), Matchers.nullValue()); + assertThat(account.getAccountResetPasswordKey()).isNull(); HAccountResetPasswordKey resetPasswordKey = userAccountService .requestPasswordReset(account.getUsername(), account.getPerson().getEmail()); // Now it has reset password key - assertThat(account.getAccountResetPasswordKey(), - Matchers.notNullValue(HAccountResetPasswordKey.class)); + assertThat(account.getAccountResetPasswordKey()).isNotNull() + .isInstanceOf(HAccountResetPasswordKey.class); } } diff --git a/server/zanata-war/src/test/java/org/zanata/service/impl/VersionGroupServiceImplTest.java b/server/zanata-war/src/test/java/org/zanata/service/impl/VersionGroupServiceImplTest.java index cf3a693d01..23bc12b7ec 100644 --- a/server/zanata-war/src/test/java/org/zanata/service/impl/VersionGroupServiceImplTest.java +++ b/server/zanata-war/src/test/java/org/zanata/service/impl/VersionGroupServiceImplTest.java @@ -21,15 +21,11 @@ package org.zanata.service.impl; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; - import java.util.List; import java.util.Map; import java.util.Set; import org.dbunit.operation.DatabaseOperation; -import org.hamcrest.Matchers; import org.hibernate.Session; import org.hibernate.search.jpa.FullTextEntityManager; import org.infinispan.manager.CacheContainer; @@ -58,6 +54,8 @@ import javax.enterprise.inject.Produces; import javax.inject.Inject; +import static org.assertj.core.api.Assertions.assertThat; + /** * @author Alex Eng aeng@redhat.com */ @@ -120,7 +118,7 @@ public void getLocaleStatisticTest1() { localeId); // 3 versions in group1 - assertThat(result.size(), equalTo(3)); + assertThat(result).hasSize(3); } @Test @@ -133,7 +131,7 @@ public void getLocaleStatisticTest2() { localeId); // 2 versions in group1 - assertThat(result.size(), equalTo(2)); + assertThat(result).hasSize(2); } @Test @@ -141,7 +139,7 @@ public void getLocaleStatisticTest2() { public void getTotalMessageCountTest1() { int totalMessageCount = versionGroupServiceImpl.getTotalMessageCount(GROUP1_SLUG); - assertThat(totalMessageCount, equalTo(18)); + assertThat(totalMessageCount).isEqualTo(18); } @Test @@ -149,7 +147,7 @@ public void getTotalMessageCountTest1() { public void getTotalMessageCountTest2() { int totalMessageCount = versionGroupServiceImpl.getTotalMessageCount(GROUP2_SLUG); - assertThat(totalMessageCount, equalTo(0)); + assertThat(totalMessageCount).isEqualTo(0); } @Test @@ -157,7 +155,7 @@ public void getTotalMessageCountTest2() { public void getMaintainersBySlugTest() { List maintainers = versionGroupServiceImpl.getMaintainersBySlug(GROUP1_SLUG); - assertThat(maintainers.size(), equalTo(2)); + assertThat(maintainers.size()).isEqualTo(2); } @Test @@ -166,12 +164,12 @@ public void isVersionInGroupTest() { boolean result = versionGroupServiceImpl.isVersionInGroup(GROUP1_SLUG, new Long( 1)); - assertThat(result, equalTo(true)); + assertThat(result).isTrue(); result = versionGroupServiceImpl.isVersionInGroup(GROUP1_SLUG, new Long( 3)); - assertThat(result, equalTo(false)); + assertThat(result).isFalse(); } @Test @@ -179,11 +177,11 @@ public void isVersionInGroupTest() { public void getGroupActiveLocalesTest() { Set activeLocales = versionGroupServiceImpl.getGroupActiveLocales(GROUP1_SLUG); - assertThat(activeLocales.size(), equalTo(3)); + assertThat(activeLocales).hasSize(3); activeLocales = versionGroupServiceImpl.getGroupActiveLocales(GROUP3_SLUG); - assertThat(activeLocales.size(), equalTo(0)); + assertThat(activeLocales).hasSize(0); } @Test @@ -195,7 +193,7 @@ public void getMissingLocaleVersionMapTest() { int activateLocaleSize = versionGroupServiceImpl.getGroupActiveLocales(GROUP1_SLUG) .size(); - assertThat(map.size(), equalTo(activateLocaleSize)); + assertThat(map.size()).isEqualTo(activateLocaleSize); // See ProjectsData.dbunit.xml, HProjectIteration id="900" in group1 ProjectIterationDAO projectIterationDAO = @@ -203,7 +201,7 @@ public void getMissingLocaleVersionMapTest() { HProjectIteration version = projectIterationDAO.findById(new Long(900)); for (List versions : map.values()) { - assertThat("", versions, Matchers.contains(version)); + assertThat(versions).contains(version); } } } diff --git a/server/zanata-war/src/test/java/org/zanata/service/impl/VersionStateCacheImplTest.java b/server/zanata-war/src/test/java/org/zanata/service/impl/VersionStateCacheImplTest.java index 89356080ae..a517417fad 100644 --- a/server/zanata-war/src/test/java/org/zanata/service/impl/VersionStateCacheImplTest.java +++ b/server/zanata-war/src/test/java/org/zanata/service/impl/VersionStateCacheImplTest.java @@ -1,16 +1,13 @@ package org.zanata.service.impl; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import org.infinispan.manager.CacheContainer; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.zanata.cache.InfinispanTestCacheContainer; import org.zanata.common.LocaleId; import org.zanata.dao.LocaleDAO; @@ -60,6 +57,6 @@ public void getStatisticTest() throws Exception { // Then: verify(versionStatisticLoader).load(key); // only load the value once - assertThat(result, equalTo(wordStatistic)); + assertThat(result).isEqualTo(wordStatistic); } } diff --git a/server/zanata-war/src/test/java/org/zanata/test/LambdaMatcher.java b/server/zanata-war/src/test/java/org/zanata/test/LambdaMatcher.java deleted file mode 100644 index 6706397469..0000000000 --- a/server/zanata-war/src/test/java/org/zanata/test/LambdaMatcher.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.zanata.test; - -import org.hamcrest.BaseMatcher; -import org.hamcrest.Description; - -import java.util.Optional; -import java.util.function.Predicate; - -public class LambdaMatcher extends BaseMatcher { - private final Predicate matcher; - private final Optional description; - - public LambdaMatcher(Predicate matcher) { - this(matcher, null); - } - - public LambdaMatcher(Predicate matcher, String description) { - this.matcher = matcher; - this.description = Optional.ofNullable(description); - } - - @SuppressWarnings("unchecked") - @Override - public boolean matches(Object argument) { - return matcher.test((T) argument); - } - - @Override - public void describeTo(Description description) { - this.description.ifPresent(description::appendText); - } -} diff --git a/server/zanata-war/src/test/java/org/zanata/tmx/TMXParserTest.java b/server/zanata-war/src/test/java/org/zanata/tmx/TMXParserTest.java index 1e55bcf257..4b348414de 100644 --- a/server/zanata-war/src/test/java/org/zanata/tmx/TMXParserTest.java +++ b/server/zanata-war/src/test/java/org/zanata/tmx/TMXParserTest.java @@ -68,16 +68,7 @@ import java.util.Set; import java.util.TimeZone; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.hasEntry; -import static org.hamcrest.Matchers.hasKey; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.junit.Assert.assertTrue; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; /** @@ -193,24 +184,24 @@ public void parseTMX() throws Exception { // Make sure everything is stored properly tm = getEm().find(TransMemory.class, tm.getId()); - assertThat(tm.getTranslationUnits().size(), is(4)); + assertThat(tm.getTranslationUnits().size()).isEqualTo(4); // Dates were modified to match the TM header in the file Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); cal.setTime(tm.getCreationDate()); - assertThat(cal.get(Calendar.YEAR), is(2013)); - assertThat(cal.get(Calendar.MONTH), is(4)); - assertThat(cal.get(Calendar.DATE), is(9)); + assertThat(cal.get(Calendar.YEAR)).isEqualTo(2013); + assertThat(cal.get(Calendar.MONTH)).isEqualTo(4); + assertThat(cal.get(Calendar.DATE)).isEqualTo(9); - assertThat(tm.getSourceLanguage(), equalTo("en")); + assertThat(tm.getSourceLanguage()).isEqualTo("en"); // TM metadata - assertThat(tm.getMetadata().size(), greaterThan(0)); - assertThat(tm.getMetadata().get(TMMetadataType.TMX14), notNullValue()); + assertThat(tm.getMetadata().size()).isGreaterThan(0); + assertThat(tm.getMetadata().get(TMMetadataType.TMX14)).isNotNull(); // Translation Units for (TransMemoryUnit tu : tm.getTranslationUnits()) { - assertThat(tu.getTransUnitVariants().size(), greaterThan(0)); + assertThat(tu.getTransUnitVariants().size()).isGreaterThan(0); } Optional seg = tm.getTranslationUnits().stream() @@ -219,7 +210,7 @@ public void parseTMX() throws Exception { .map(map -> map.get("ja")) .map(TransMemoryUnitVariant::getPlainTextSegment) .findAny(); - assertThat(seg.orElseGet(null), containsString("を選択します")); + assertThat(seg.orElseGet(null)).contains("を選択します"); } @Test @@ -231,9 +222,9 @@ public void parseDubiousTMXDespiteUnderscoresInLocales() throws Exception { // Make sure everything is stored properly tm = getEm().find(TransMemory.class, tm.getId()); - assertThat(tm.getTranslationUnits().size(), is(1)); + assertThat(tm.getTranslationUnits().size()).isEqualTo(1); - assertThat(tm.getSourceLanguage(), equalTo("en-US")); + assertThat(tm.getSourceLanguage()).isEqualTo("en-US"); Set expectedLocales = Sets.newHashSet("en-US", "es", "es-ES", "fr", "fr-FR", "he", @@ -241,7 +232,7 @@ public void parseDubiousTMXDespiteUnderscoresInLocales() throws Exception { TransMemoryUnit tu = tm.getTranslationUnits().iterator().next(); HashSet actualLocales = Sets.newHashSet(tu.getTransUnitVariants().keySet()); - assertThat(actualLocales, equalTo(expectedLocales)); + assertThat(actualLocales).isEqualTo(expectedLocales); } @Test @@ -255,77 +246,73 @@ public void parseTMXWithMetadata() throws Exception { // Metadata at the header level Map tmAtts = TMXMetadataHelper.getAttributes(tm); - assertThat(tmAtts.size(), is(9)); - assertThat(tmAtts, hasEntry("segtype", "paragraph")); - assertThat(tmAtts, hasEntry("creationtoolversion", "unknown")); - assertThat(tmAtts, - hasEntry("creationtool", "Zanata TransMemoryExportTMXStrategy")); - assertThat(tmAtts, hasEntry("datatype", "unknown")); - assertThat(tmAtts, hasEntry("adminlang", "en")); - assertThat(tmAtts, hasEntry("o-tmf", "unknown")); - assertThat(tmAtts, hasEntry("srclang", "*all*")); - assertThat(tmAtts, hasKey("creationdate")); - assertThat(tmAtts, hasKey("changedate")); + assertThat(tmAtts.size()).isEqualTo(9); + assertThat(tmAtts).containsEntry("segtype", "paragraph") + .containsEntry("creationtoolversion", "unknown") + .containsEntry("creationtool", + "Zanata TransMemoryExportTMXStrategy") + .containsEntry("datatype", "unknown") + .containsEntry("adminlang", "en") + .containsEntry("o-tmf", "unknown") + .containsEntry("srclang", "*all*") + .containsKeys("creationdate", "changedate"); List tmChildren = TMXMetadataHelper.getChildren(tm); - assertThat(tmChildren.size(), is(2)); - assertThat(tmChildren.get(0).getLocalName(), is("prop")); - assertThat(tmChildren.get(0).getValue(), is("Header Prop value")); - assertThat(tmChildren.get(1).getLocalName(), is("note")); - assertThat(tmChildren.get(1).getValue(), is("Header Note value")); + assertThat(tmChildren.size()).isEqualTo(2); + assertThat(tmChildren.get(0).getLocalName()).isEqualTo("prop"); + assertThat(tmChildren.get(0).getValue()).isEqualTo("Header Prop value"); + assertThat(tmChildren.get(1).getLocalName()).isEqualTo("note"); + assertThat(tmChildren.get(1).getValue()).isEqualTo("Header Note value"); // Metadata at the TU level TransMemoryUnit tu0 = findInCollection(tm.getTranslationUnits(), "doc0:resId0"); Map tu0Atts = TMXMetadataHelper.getAttributes(tu0); - assertThat(tu0Atts.size(), is(4)); - assertThat(tu0Atts, hasEntry("tuid", "doc0:resId0")); - assertThat(tu0Atts, hasEntry("srclang", "en")); - assertThat(tu0Atts, hasKey("creationdate")); - assertThat(tu0Atts, hasKey("changedate")); + assertThat(tu0Atts.size()).isEqualTo(4); + assertThat(tu0Atts).containsEntry("tuid", "doc0:resId0") + .containsEntry("srclang", "en") + .containsKeys("creationdate", "changedate"); List tu0Children = TMXMetadataHelper.getChildren(tu0); - assertThat(tu0Children.size(), is(2)); - assertThat(tu0Children.get(0).getLocalName(), is("prop")); - assertThat(tu0Children.get(0).getValue(), is("Custom prop0 value")); - assertThat(tu0Children.get(1).getLocalName(), is("note")); - assertThat(tu0Children.get(1).getValue(), is("Custom note")); + assertThat(tu0Children.size()).isEqualTo(2); + assertThat(tu0Children.get(0).getLocalName()).isEqualTo("prop"); + assertThat(tu0Children.get(0).getValue()).isEqualTo("Custom prop0 value"); + assertThat(tu0Children.get(1).getLocalName()).isEqualTo("note"); + assertThat(tu0Children.get(1).getValue()).isEqualTo("Custom note"); TransMemoryUnit tu1 = findInCollection(tm.getTranslationUnits(), "doc0:resId1"); Map tu1Atts = TMXMetadataHelper.getAttributes(tu1); - assertThat(tu1Atts.size(), is(4)); - assertThat(tu1Atts, hasEntry("tuid", "doc0:resId1")); - assertThat(tu1Atts, hasEntry("srclang", "en")); - assertThat(tu1Atts, hasKey("creationdate")); - assertThat(tu1Atts, hasKey("changedate")); + assertThat(tu1Atts.size()).isEqualTo(4); + assertThat(tu1Atts).containsEntry("tuid", "doc0:resId1") + .containsEntry("srclang", "en") + .containsKeys("creationdate", "changedate"); List tu1Children = TMXMetadataHelper.getChildren(tu1); - assertThat(tu1Children.size(), is(4)); - assertThat(tu1Children.get(0).getLocalName(), is("prop")); - assertThat(tu1Children.get(0).getValue(), is("Custom prop0 value")); - assertThat(tu1Children.get(1).getLocalName(), is("prop")); - assertThat(tu1Children.get(1).getValue(), is("Custom prop1 value")); - assertThat(tu1Children.get(2).getLocalName(), is("note")); - assertThat(tu1Children.get(2).getValue(), is("Custom note0")); - assertThat(tu1Children.get(3).getLocalName(), is("note")); - assertThat(tu1Children.get(3).getValue(), is("Custom note1")); + assertThat(tu1Children.size()).isEqualTo(4); + assertThat(tu1Children.get(0).getLocalName()).isEqualTo("prop"); + assertThat(tu1Children.get(0).getValue()).isEqualTo("Custom prop0 value"); + assertThat(tu1Children.get(1).getLocalName()).isEqualTo("prop"); + assertThat(tu1Children.get(1).getValue()).isEqualTo("Custom prop1 value"); + assertThat(tu1Children.get(2).getLocalName()).isEqualTo("note"); + assertThat(tu1Children.get(2).getValue()).isEqualTo("Custom note0"); + assertThat(tu1Children.get(3).getLocalName()).isEqualTo("note"); + assertThat(tu1Children.get(3).getValue()).isEqualTo("Custom note1"); // Metadata at the TUV level TransMemoryUnitVariant tuv0 = tu0.getTransUnitVariants().get("en"); Map tuv0Atts = TMXMetadataHelper.getAttributes(tuv0); - assertThat(tuv0Atts.size(), is(3)); - assertThat(tuv0Atts, hasEntry("xml:lang", "en")); - assertThat(tuv0Atts, hasKey("creationdate")); - assertThat(tuv0Atts, hasKey("changedate")); + assertThat(tuv0Atts.size()).isEqualTo(3); + assertThat(tuv0Atts).containsEntry("xml:lang", "en") + .containsKeys("creationdate", "changedate"); List tuv0Children = TMXMetadataHelper.getChildren(tuv0); - assertThat(tuv0Children.size(), is(2)); - assertThat(tuv0Children.get(0).getLocalName(), is("prop")); - assertThat(tuv0Children.get(0).getValue(), - is("Custom prop0 value on tuv")); - assertThat(tuv0Children.get(1).getLocalName(), is("note")); - assertThat(tuv0Children.get(1).getValue(), is("Custom note on tuv")); + assertThat(tuv0Children.size()).isEqualTo(2); + assertThat(tuv0Children.get(0).getLocalName()).isEqualTo("prop"); + assertThat(tuv0Children.get(0).getValue()). + isEqualTo("Custom prop0 value on tuv"); + assertThat(tuv0Children.get(1).getLocalName()).isEqualTo("note"); + assertThat(tuv0Children.get(1).getValue()).isEqualTo("Custom note on tuv"); } @Test(expected = TMXParseException.class) @@ -350,13 +337,13 @@ public void mergeSameTM() throws Exception { // Make sure everything is stored properly tm = getEm().find(TransMemory.class, tm.getId()); - assertThat(tm.getTranslationUnits().size(), is(4)); + assertThat(tm.getTranslationUnits().size()).isEqualTo(4); // Second load (should yield the same result) populateTMFromFile(tm, "/tmx/default-valid-tm.tmx"); tm = getEm().find(TransMemory.class, tm.getId()); - assertThat(tm.getTranslationUnits().size(), is(4)); + assertThat(tm.getTranslationUnits().size()).isEqualTo(4); } @Test @@ -367,12 +354,12 @@ public void mergeComplementaryTM() throws Exception { // Make sure everything is stored properly tm = getEm().find(TransMemory.class, tm.getId()); - assertThat(tm.getTranslationUnits().size(), is(4)); + assertThat(tm.getTranslationUnits().size()).isEqualTo(4); // Second load (should add all new tuids) populateTMFromFile(tm, "/tmx/valid-tm-with-tuids.tmx"); tm = getEm().find(TransMemory.class, tm.getId()); - assertThat(tm.getTranslationUnits().size(), is(8)); + assertThat(tm.getTranslationUnits().size()).isEqualTo(8); } } diff --git a/server/zanata-war/src/test/java/org/zanata/util/FileUtilTest.java b/server/zanata-war/src/test/java/org/zanata/util/FileUtilTest.java index de83b0544a..6e1e37eafd 100644 --- a/server/zanata-war/src/test/java/org/zanata/util/FileUtilTest.java +++ b/server/zanata-war/src/test/java/org/zanata/util/FileUtilTest.java @@ -24,8 +24,7 @@ import org.junit.Test; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; /** * @author Alex Eng aeng@redhat.com @@ -34,14 +33,14 @@ public class FileUtilTest { @Test public void generateSimpleDocId() { - assertThat(FileUtil.generateDocId("foo", "bar.txt"), - is("foo/bar.txt")); + assertThat(FileUtil.generateDocId("foo", "bar.txt")) + .isEqualTo("foo/bar.txt"); } @Test public void generateSQLInjectionDocId() { String sqlInjectFilename = "file.txt;DROP ALL OBJECTS;other.txt"; - assertThat(FileUtil.generateDocId("", sqlInjectFilename), - is(sqlInjectFilename)); + assertThat(FileUtil.generateDocId("", sqlInjectFilename)) + .isEqualTo(sqlInjectFilename); } } diff --git a/server/zanata-war/src/test/java/org/zanata/util/QueryBuilderTest.java b/server/zanata-war/src/test/java/org/zanata/util/QueryBuilderTest.java index 478312abc8..4fbb877c3b 100644 --- a/server/zanata-war/src/test/java/org/zanata/util/QueryBuilderTest.java +++ b/server/zanata-war/src/test/java/org/zanata/util/QueryBuilderTest.java @@ -23,8 +23,7 @@ import org.hibernate.criterion.Restrictions; import org.junit.Test; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalToIgnoringCase; +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.util.QueryBuilder.and; import static org.zanata.util.QueryBuilder.or; @@ -39,9 +38,8 @@ public void simpleQueryTest() { QueryBuilder.select("col1, col2").from("DatabaseTable") .where("col1 = 2 and col2 = 1").toQueryString(); - assertThat( - query, - equalToIgnoringCase("select col1, col2 from DatabaseTable where col1 = 2 and col2 = 1")); + assertThat(query).isEqualToIgnoringCase( + "select col1, col2 from DatabaseTable where col1 = 2 and col2 = 1"); } @Test @@ -50,9 +48,8 @@ public void andQueryTest() { QueryBuilder.select("col1, col2").from("DatabaseTable") .where(and("col1 = 2", "col2 = 1")).toQueryString(); - assertThat( - query, - equalToIgnoringCase("select col1, col2 from DatabaseTable where (col1 = 2 and col2 = 1)")); + assertThat(query).isEqualToIgnoringCase( + "select col1, col2 from DatabaseTable where (col1 = 2 and col2 = 1)"); } @Test @@ -61,9 +58,8 @@ public void orQueryTest() { QueryBuilder.select("col1, col2").from("DatabaseTable") .where(or("col1 = 2", "col2 = 1")).toQueryString(); - assertThat( - query, - equalToIgnoringCase("select col1, col2 from DatabaseTable where (col1 = 2 or col2 = 1)")); + assertThat(query).isEqualToIgnoringCase( + "select col1, col2 from DatabaseTable where (col1 = 2 or col2 = 1)"); } @Test @@ -75,9 +71,8 @@ public void complexQueryTest() { .where(and("col1 = 2", or("or1", "or2", "or3"), and("and1", "and2"))).toQueryString(); - assertThat( - query, - equalToIgnoringCase("SELECT col1, col2 FROM DatabaseTable WHERE (col1 = 2 AND (or1 OR or2 OR or3) AND (and1 AND and2))")); + assertThat(query).isEqualToIgnoringCase( + "SELECT col1, col2 FROM DatabaseTable WHERE (col1 = 2 AND (or1 OR or2 OR or3) AND (and1 AND and2))"); } @Test @@ -89,9 +84,8 @@ public void emptyArgumentsQueryTest() { .where(and("col1 = 2", or(), and("and1", "and2"), and())) .toQueryString(); - assertThat( - query, - equalToIgnoringCase("SELECT col1, col2 FROM DatabaseTable WHERE (col1 = 2 AND (and1 AND and2))")); + assertThat(query).isEqualToIgnoringCase( + "SELECT col1, col2 FROM DatabaseTable WHERE (col1 = 2 AND (and1 AND and2))"); } @@ -107,9 +101,8 @@ public void complexQueryWithLeftJoinTest() { .where(and("col1 = 2", or("or1", "or2", "or3"), and("and1", "and2"))).toQueryString(); - assertThat( - query, - equalToIgnoringCase("SELECT col1, col2 FROM DatabaseTable LEFT JOIN Table2 WITH Table2.content=:content WHERE (col1 = 2 AND (or1 OR or2 OR or3) AND (and1 AND and2))")); + assertThat(query).isEqualToIgnoringCase( + "SELECT col1, col2 FROM DatabaseTable LEFT JOIN Table2 WITH Table2.content=:content WHERE (col1 = 2 AND (or1 OR or2 OR or3) AND (and1 AND and2))"); } @Test @@ -118,9 +111,8 @@ public void existsSubQueryTest() { QueryBuilder.exists().from("DatabaseTable") .where("col1 = 2 and col2 = 1").toQueryString(); - assertThat( - query, - equalToIgnoringCase(" exists ( from DatabaseTable where col1 = 2 and col2 = 1)")); + assertThat(query).isEqualToIgnoringCase( + " exists ( from DatabaseTable where col1 = 2 and col2 = 1)"); } @Test @@ -130,8 +122,7 @@ public void orderByQueryTest() { .where("col1 = 2 and col2 = 1").orderBy("col1") .toQueryString(); - assertThat( - query, - equalToIgnoringCase("select col1, col2 from DatabaseTable where col1 = 2 and col2 = 1 order by col1")); + assertThat(query).isEqualToIgnoringCase( + "select col1, col2 from DatabaseTable where col1 = 2 and col2 = 1 order by col1"); } } diff --git a/server/zanata-war/src/test/java/org/zanata/util/TransMemoryMergeStatusResolverTest.java b/server/zanata-war/src/test/java/org/zanata/util/TransMemoryMergeStatusResolverTest.java index 52aa5cb9d3..1c5c6419a8 100644 --- a/server/zanata-war/src/test/java/org/zanata/util/TransMemoryMergeStatusResolverTest.java +++ b/server/zanata-war/src/test/java/org/zanata/util/TransMemoryMergeStatusResolverTest.java @@ -38,10 +38,7 @@ import org.zanata.webtrans.shared.rpc.MergeRule; import org.zanata.webtrans.shared.rpc.MergeOptions; -import static org.hamcrest.MatcherAssert.*; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.nullValue; +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.webtrans.shared.model.TransMemoryResultItem.MatchType; /** @@ -131,7 +128,7 @@ public void notOneHundredMatchWillBeSetAsFuzzy() { resolver.decideStatus(action, textFlow, tmDetail, tmResultWithSimilarity(90), null); - assertThat(result, equalTo(ContentState.NeedReview)); + assertThat(result).isEqualTo(ContentState.NeedReview); } @Test @@ -140,8 +137,8 @@ public void differentResIdAndOptionIsFuzzy() { tmDetail(projectName, docId, "different res id", msgContext); action = mergeTMActionWhenResIdIsDifferent(MergeRule.FUZZY); assertThat(resolver.decideStatus(action, textFlow, tmDetail, - tmResultWithSimilarity(100), null), - equalTo(ContentState.NeedReview)); + tmResultWithSimilarity(100), null)) + .isEqualTo(ContentState.NeedReview); } @@ -151,8 +148,8 @@ public void differentDocIdAndOptionIsFuzzy() { tmDetail(projectName, "different doc id", resId, msgContext); action = mergeTMActionWhenDocIdIsDifferent(MergeRule.FUZZY); assertThat(resolver.decideStatus(action, textFlow, tmDetail, - tmResultWithSimilarity(100), null), - equalTo(ContentState.NeedReview)); + tmResultWithSimilarity(100), null)) + .isEqualTo(ContentState.NeedReview); } @@ -162,8 +159,8 @@ public void differentProjectNameAndOptionIsFuzzy() { tmDetail("different project name", docId, resId, msgContext); action = mergeTMActionWhenProjectNameIsDifferent(MergeRule.FUZZY); assertThat(resolver.decideStatus(action, textFlow, tmDetail, - tmResultWithSimilarity(100), null), - equalTo(ContentState.NeedReview)); + tmResultWithSimilarity(100), null)) + .isEqualTo(ContentState.NeedReview); } @@ -180,7 +177,7 @@ public void differentProjectNameAndOptionIsFuzzy() { oldTarget.setState(ContentState.NeedReview); assertThat(resolver.decideStatus(action, textFlow, tmDetail, - tmResultWithSimilarity(100), oldTarget), is(nullValue())); + tmResultWithSimilarity(100), oldTarget)).isNull(); } @Test @@ -188,8 +185,8 @@ public void fromImportedTmAndOptionIsFuzzy() { TransMemoryMergeRequest transMemoryMerge = mergeTMAction(importedMatch(MergeRule.FUZZY)); assertThat(resolver.decideStatus(transMemoryMerge, - tmResultWithSimilarityAndExternallyImported(100), null), - equalTo(ContentState.NeedReview)); + tmResultWithSimilarityAndExternallyImported(100), null)) + .isEqualTo(ContentState.NeedReview); } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/EventProcessorTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/EventProcessorTest.java index 43a949a70b..9fc5790255 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/EventProcessorTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/EventProcessorTest.java @@ -1,6 +1,5 @@ package org.zanata.webtrans.client; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -21,7 +20,8 @@ import de.novanic.eventservice.client.event.RemoteEventService; import de.novanic.eventservice.client.event.domain.Domain; import net.customware.gwt.presenter.client.EventBus; -import static org.hamcrest.MatcherAssert.assertThat; + +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -70,10 +70,9 @@ public void testStart() throws Exception { verify(remoteEventService).addListener(domainCaptor.capture(), eq(eventProcessor), callbackCaptor.capture()); - assertThat( - domainCaptor.getValue().getName(), - Matchers.equalTo(userWorkspaceContext.getWorkspaceContext() - .getWorkspaceId().toString())); + assertThat(domainCaptor.getValue().getName()) + .isEqualTo(userWorkspaceContext.getWorkspaceContext() + .getWorkspaceId().toString()); AsyncCallback callback = callbackCaptor.getValue(); when(configuration.getConnectionId()).thenReturn("connectionId"); diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/history/HistoryTokenTests.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/history/HistoryTokenTests.java index 2349b71308..81d63895ff 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/history/HistoryTokenTests.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/history/HistoryTokenTests.java @@ -1,12 +1,11 @@ package org.zanata.webtrans.client.history; -import static org.junit.Assert.*; - -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.zanata.webtrans.client.presenter.MainView; +import static org.assertj.core.api.Assertions.assertThat; + /** * Encapsulates a string token of key-value pairs for GWT history operations. * @@ -25,96 +24,90 @@ public void setup() { public void constructionSetsDefaults() { token = new HistoryToken(); - assertEquals("default view should be document list", - MainView.Documents, token.getView()); - assertEquals("default document path should be an empty string", "", - token.getDocumentPath()); - assertEquals("default document filter text should be an empty string", - "", token.getDocFilterText()); - assertFalse("default document filter exact match flag should be false", - token.getDocFilterExact()); - assertThat("default search text should be null", - token.getEditorTextSearch(), Matchers.nullValue()); - assertEquals( - "default project-wide search text should be an empty string", - "", token.getProjectSearchText()); - assertEquals( - "default project-wide search replacement text should be an empty string", - "", token.getProjectSearchReplacement()); - assertFalse( - "default project-wide search case sensitive flag should be false", - token.getProjectSearchCaseSensitive()); - assertThat(token.getTextFlowId(), Matchers.nullValue()); - assertThat(token.isFilterTranslated(), Matchers.equalTo(false)); - assertThat(token.isFilterUntranslated(), Matchers.equalTo(false)); - assertThat(token.isFilterFuzzy(), Matchers.equalTo(false)); - assertThat(token.isFilterApproved(), Matchers.equalTo(false)); - assertThat(token.isFilterRejected(), Matchers.equalTo(false)); - assertThat(token.isFilterHasError(), Matchers.equalTo(false)); + assertThat(MainView.Documents).isEqualTo(token.getView()) + .as("default view should be document list"); + assertThat(token.getDocumentPath()) + .as("default document path should be an empty string") + .isEqualTo(""); + assertThat(token.getDocFilterText()) + .as("default document filter text should be an empty string") + .isEqualTo(""); + assertThat(token.getDocFilterExact()).isFalse() + .as("default document filter exact match flag should be false"); + assertThat(token.getEditorTextSearch()) + .as("default search text should be null").isNull(); + assertThat(token.getProjectSearchText()) + .as("default project-wide search text should be an empty string") + .isEqualTo(""); + assertThat(token.getProjectSearchReplacement()) + .as("default project-wide search replacement text should be an empty string") + .isEqualTo(""); + assertThat(token.getProjectSearchCaseSensitive()).isFalse() + .as("default project-wide search case sensitive flag should be false"); + assertThat(token.getTextFlowId()).isNull(); + assertThat(token.isFilterTranslated()).isFalse(); + assertThat(token.isFilterUntranslated()).isFalse(); + assertThat(token.isFilterFuzzy()).isFalse(); + assertThat(token.isFilterApproved()).isFalse(); + assertThat(token.isFilterRejected()).isFalse(); + assertThat(token.isFilterHasError()).isFalse(); } @Test public void fromEmptyStringSetsDefaults() { token = HistoryToken.fromTokenString(""); - assertEquals("default view should be document list", - MainView.Documents, token.getView()); - assertEquals("default document path should be an empty string", "", - token.getDocumentPath()); - assertEquals("default document filter text should be an empty string", - "", token.getDocFilterText()); - assertFalse("default document filter exact match flag should be false", - token.getDocFilterExact()); - assertThat("default search text should be null", - token.getEditorTextSearch(), Matchers.nullValue()); - assertEquals( - "default project-wide search text should be an empty string", - "", token.getProjectSearchText()); - assertEquals( - "default project-wide search replacement text should be an empty string", - "", token.getProjectSearchReplacement()); - assertFalse( - "default project-wide search case sensitive flag should be false", - token.getProjectSearchCaseSensitive()); - assertThat(token.getTextFlowId(), Matchers.nullValue()); - assertThat(token.isFilterTranslated(), Matchers.equalTo(false)); - assertThat(token.isFilterUntranslated(), Matchers.equalTo(false)); - assertThat(token.isFilterFuzzy(), Matchers.equalTo(false)); - assertThat(token.isFilterApproved(), Matchers.equalTo(false)); - assertThat(token.isFilterRejected(), Matchers.equalTo(false)); - assertThat(token.isFilterHasError(), Matchers.equalTo(false)); + assertThat(token.getView()).isEqualTo(MainView.Documents) + .as("default view should be document list"); + assertThat(token.getDocumentPath()).isEqualTo("") + .as("default document path should be an empty string"); + assertThat(token.getDocFilterText()).isEqualTo("") + .as("default document filter text should be an empty string"); + assertThat(token.getDocFilterExact()).isFalse() + .as("default document filter exact match flag should be false"); + assertThat(token.getEditorTextSearch()).as("default search text should be null").isNull(); + assertThat(token.getProjectSearchText()).isEqualTo("").as( + "default project-wide search text should be an empty string"); + assertThat(token.getProjectSearchReplacement()).isEqualTo("") + .as("default project-wide search replacement text should be an empty string"); + assertThat(token.getProjectSearchCaseSensitive()).isFalse() + .as("default project-wide search case sensitive flag should be false"); + assertThat(token.getTextFlowId()).isNull(); + assertThat(token.isFilterTranslated()).isFalse(); + assertThat(token.isFilterUntranslated()).isFalse(); + assertThat(token.isFilterFuzzy()).isFalse(); + assertThat(token.isFilterApproved()).isFalse(); + assertThat(token.isFilterRejected()).isFalse(); + assertThat(token.isFilterHasError()).isFalse(); } @Test public void fromNullStringSetsDefaults() { token = HistoryToken.fromTokenString(null); - assertEquals("default view should be document list", - MainView.Documents, token.getView()); - assertEquals("default document path should be an empty string", "", - token.getDocumentPath()); - assertEquals("default document filter text should be an empty string", - "", token.getDocFilterText()); - assertFalse("default document filter exact match flag should be false", - token.getDocFilterExact()); - assertThat("default search text should be null", - token.getEditorTextSearch(), Matchers.nullValue()); - assertEquals( - "default project-wide search text should be an empty string", - "", token.getProjectSearchText()); - assertEquals( - "default project-wide search replacement text should be an empty string", - "", token.getProjectSearchReplacement()); - assertFalse( - "default project-wide search case sensitive flag should be false", - token.getProjectSearchCaseSensitive()); - assertThat(token.getTextFlowId(), Matchers.nullValue()); - assertThat(token.isFilterTranslated(), Matchers.equalTo(false)); - assertThat(token.isFilterUntranslated(), Matchers.equalTo(false)); - assertThat(token.isFilterFuzzy(), Matchers.equalTo(false)); - assertThat(token.isFilterApproved(), Matchers.equalTo(false)); - assertThat(token.isFilterRejected(), Matchers.equalTo(false)); - assertThat(token.isFilterHasError(), Matchers.equalTo(false)); + assertThat(token.getView()).isEqualTo(MainView.Documents) + .as("default view should be document list"); + assertThat(token.getDocumentPath()).isEqualTo("") + .as("default document path should be an empty string"); + assertThat(token.getDocFilterText()).isEqualTo("") + .as("default document filter text should be an empty string"); + assertThat(token.getDocFilterExact()).isFalse() + .as("default document filter exact match flag should be false"); + assertThat(token.getEditorTextSearch()) + .as("default search text should be null").isNull(); + assertThat(token.getProjectSearchText()).isEqualTo("") + .as("default project-wide search text should be an empty string"); + assertThat(token.getProjectSearchReplacement()).isEqualTo("") + .as("default project-wide search replacement text should be an empty string"); + assertThat(token.getProjectSearchCaseSensitive()).isFalse() + .as("default project-wide search case sensitive flag should be false"); + assertThat(token.getTextFlowId()).isNull(); + assertThat(token.isFilterTranslated()).isFalse(); + assertThat(token.isFilterUntranslated()).isFalse(); + assertThat(token.isFilterFuzzy()).isFalse(); + assertThat(token.isFilterApproved()).isFalse(); + assertThat(token.isFilterRejected()).isFalse(); + assertThat(token.isFilterHasError()).isFalse(); } @Test @@ -124,15 +117,14 @@ public void fromTokenStringSetsValues() { token = HistoryToken.fromTokenString(tokenString); - assertEquals("view should be set from token string", MainView.Editor, - token.getView()); - assertEquals("document path should be set from token string", - "some/document", token.getDocumentPath()); - assertEquals("document filter text should be set from token string", - "myfilter", token.getDocFilterText()); - assertTrue( - "document filter exact match flag should be set from token string", - token.getDocFilterExact()); + assertThat(token.getView()).isEqualTo(MainView.Editor) + .as("view should be set from token string"); + assertThat(token.getDocumentPath()).isEqualTo("some/document") + .as("document path should be set from token string"); + assertThat(token.getDocFilterText()).isEqualTo("myfilter") + .as("document filter text should be set from token string"); + assertThat(token.getDocFilterExact()).isTrue() + .as("document filter exact match flag should be set from token string"); } @Test @@ -142,17 +134,14 @@ public void fromTokenStringSetsSearchValues() { token = HistoryToken.fromTokenString(tokenString); - assertEquals("search text should be set from token string", - "searchtext", token.getEditorTextSearch()); - assertEquals( - "project-wide search text should be set from token string", - "projectsearchtext", token.getProjectSearchText()); - assertEquals( - "project-wide search replacement text should be set from token string", - "replacementtext", token.getProjectSearchReplacement()); - assertTrue( - "project-wide search case sensitivity should be set from token string", - token.getProjectSearchCaseSensitive()); + assertThat(token.getEditorTextSearch()).isEqualTo("searchtext") + .as("search text should be set from token string"); + assertThat(token.getProjectSearchText()).isEqualTo("projectsearchtext") + .as("project-wide search text should be set from token string"); + assertThat(token.getProjectSearchReplacement()).isEqualTo("replacementtext") + .as("project-wide search replacement text should be set from token string"); + assertThat(token.getProjectSearchCaseSensitive()).isTrue() + .as("project-wide search case sensitivity should be set from token string"); } @Test @@ -162,17 +151,14 @@ public void fromTokenStringParameterOrderIrrelevant() { token = HistoryToken.fromTokenString(differentOrderTokenString); - assertEquals("view should be set from any position in token string", - MainView.Editor, token.getView()); - assertEquals( - "document path should be set from any position in token string", - "some/document", token.getDocumentPath()); - assertEquals( - "document filter text should be set from any position in token string", - "myfilter", token.getDocFilterText()); - assertTrue( - "document filter exact match flag should be set from any position in token string", - token.getDocFilterExact()); + assertThat(token.getView()).isEqualTo(MainView.Editor) + .as("view should be set from any position in token string"); + assertThat(token.getDocumentPath()).isEqualTo("some/document") + .as("document path should be set from any position in token string"); + assertThat(token.getDocFilterText()).isEqualTo("myfilter") + .as("document filter text should be set from any position in token string"); + assertThat(token.getDocFilterExact()).isTrue() + .as("document filter exact match flag should be set from any position in token string"); } @Test @@ -182,18 +168,15 @@ public void fromTokenStringParameterOrderIrrelevant2() { token = HistoryToken.fromTokenString(differentOrderTokenString); - assertEquals( - "search text should be set from any position in token string", - "searchtext", token.getEditorTextSearch()); - assertEquals( - "project-wide search text should be set from any position in token string", - "projectsearchtext", token.getProjectSearchText()); - assertEquals( - "project-wide search replacement text should be set from any position in token string", - "replacementtext", token.getProjectSearchReplacement()); - assertTrue( - "project-wide search case sensitivity should be set from any position in token string", - token.getProjectSearchCaseSensitive()); + assertThat(token.getEditorTextSearch()).isEqualTo("searchtext") + .as("search text should be set from any position in token string"); + assertThat(token.getProjectSearchText()).isEqualTo("projectsearchtext") + .as("project-wide search text should be set from any position in token string"); + assertThat(token.getProjectSearchReplacement()) + .isEqualTo("replacementtext") + .as("project-wide search replacement text should be set from any position in token string"); + assertThat(token.getProjectSearchCaseSensitive()).isTrue().as( + "project-wide search case sensitivity should be set from any position in token string"); } @Test @@ -202,7 +185,7 @@ public void fromTokenStringHasTextFlowId() { token = HistoryToken.fromTokenString(tokenString); - assertThat(token.getTextFlowId(), Matchers.equalTo(1L)); + assertThat(token.getTextFlowId()).isEqualTo(1L); } @Test @@ -211,7 +194,7 @@ public void badTextFlowId() { token = HistoryToken.fromTokenString(tokenString); - assertThat(token.getTextFlowId(), Matchers.nullValue()); + assertThat(token.getTextFlowId()).isNull(); } @Test @@ -222,21 +205,22 @@ public void fromTokenStringUnknownTokenKeysIgnored() { token = HistoryToken.fromTokenString(unknownTokensString); // should be using defaults as there are no known keys - assertEquals("unknown keys should be ignored", MainView.Documents, - token.getView()); - assertEquals("unknown keys should be ignored", "", - token.getDocumentPath()); - assertEquals("unknown keys should be ignored", "", - token.getDocFilterText()); - assertFalse("unknown keys should be ignored", token.getDocFilterExact()); - assertThat("unknown keys should be ignored", - token.getEditorTextSearch(), Matchers.nullValue()); - assertEquals("unknown keys should be ignored", "", - token.getProjectSearchText()); - assertEquals("unknown keys should be ignored", "", - token.getProjectSearchReplacement()); - assertFalse("unknown keys should be ignored", - token.getProjectSearchCaseSensitive()); + assertThat(token.getView()).isEqualTo(MainView.Documents) + .as("unknown keys should be ignored"); + assertThat(token.getDocumentPath()).isEqualTo("") + .as("unknown keys should be ignored"); + assertThat(token.getDocFilterText()).isEqualTo("") + .as("unknown keys should be ignored"); + assertThat(token.getDocFilterExact()).isFalse() + .as("unknown keys should be ignored"); + assertThat(token.getEditorTextSearch()) + .as("unknown keys should be ignored").isNull(); + assertThat(token.getProjectSearchText()).isEqualTo("") + .as("unknown keys should be ignored"); + assertThat(token.getProjectSearchReplacement()).isEqualTo("") + .as("unknown keys should be ignored"); + assertThat(token.getProjectSearchCaseSensitive()).isFalse() + .as("unknown keys should be ignored"); } @Test @@ -244,14 +228,14 @@ public void getSetView() { token = new HistoryToken(); token.setView(MainView.Editor); - assertEquals(MainView.Editor, token.getView()); + assertThat(token.getView()).isEqualTo(MainView.Editor); token.setView(MainView.Documents); - assertEquals(MainView.Documents, token.getView()); + assertThat(token.getView()).isEqualTo(MainView.Documents); token.setView(MainView.Editor); token.setView(null); - assertEquals("view should reset to default if set to null value", - MainView.Documents, token.getView()); + assertThat(token.getView()).isEqualTo(MainView.Documents) + .as("view should reset to default if set to null value"); } @Test @@ -259,123 +243,115 @@ public void getSetDocPath() { token = new HistoryToken(); token.setDocumentPath("new/document/path"); - assertEquals(token.getDocumentPath(), "new/document/path"); + assertThat(token.getDocumentPath()).isEqualTo("new/document/path"); token.setDocumentPath(null); - assertEquals( - "document path should be set to empty string if null is given", - "", token.getDocumentPath()); + assertThat(token.getDocumentPath()).isEqualTo("") + .as("document path should be set to empty string if null is given"); token.setDocumentPath("random/path"); token.setDocumentPath(""); - assertEquals("document path can be set to empty string", "", - token.getDocumentPath()); + assertThat(token.getDocumentPath()).isEqualTo("") + .as("document path can be set to empty string"); } @Test public void getSetFilterText() { token = new HistoryToken(); token.setDocFilterText("filter/text, more/filter/text, foo"); - assertEquals("filter/text, more/filter/text, foo", - token.getDocFilterText()); + assertThat(token.getDocFilterText()).isEqualTo("filter/text, more/filter/text, foo"); token.setDocFilterText(null); - assertEquals( - "filter text should be returned as empty string after setting to null", - "", token.getDocFilterText()); + assertThat(token.getDocFilterText()).isEqualTo("").as( + "filter text should be returned as empty string after setting to null"); token.setDocFilterText("some filter text"); token.setDocFilterText(""); - assertEquals("filter text can be set to empty string", "", - token.getDocFilterText()); + assertThat(token.getDocFilterText()).isEqualTo("").as("filter text can be set to empty string"); } @Test public void getSetFilterFlag() { token = new HistoryToken(); token.setDocFilterExact(true); - assertTrue(token.getDocFilterExact()); + assertThat(token.getDocFilterExact()).isTrue(); token.setDocFilterExact(false); - assertFalse(token.getDocFilterExact()); + assertThat(token.getDocFilterExact()).isFalse(); } @Test public void getSetSearchText() { token = new HistoryToken(); token.setEditorTextSearch("some search text"); - assertEquals("some search text", token.getEditorTextSearch()); + assertThat(token.getEditorTextSearch()).isEqualTo("some search text"); token.setEditorTextSearch(null); - assertThat( - "search text should be returned null after setting to null", - token.getEditorTextSearch(), Matchers.nullValue()); + assertThat(token.getEditorTextSearch()) + .as("search text should be returned null after setting to null") + .isNull(); token.setEditorTextSearch("text to be discarded"); token.setEditorTextSearch(""); - assertThat("empty search text is treated as null", - token.getEditorTextSearch(), Matchers.nullValue()); + assertThat(token.getEditorTextSearch()) + .as("empty search text is treated as null").isNull(); } @Test public void getSetProjectSearchText() { token = new HistoryToken(); token.setProjectSearchText("some project search text"); - assertEquals("some project search text", token.getProjectSearchText()); + assertThat(token.getProjectSearchText()).isEqualTo("some project search text"); token.setProjectSearchText(null); - assertEquals( - "project search text should be returned as empty string after setting to null", - "", token.getProjectSearchText()); + assertThat(token.getProjectSearchText()).isEqualTo("").as( + "project search text should be returned as empty string after setting to null"); token.setProjectSearchText("text to be discarded"); token.setProjectSearchText(""); - assertEquals("project search text can be set to empty string", "", - token.getProjectSearchText()); + assertThat(token.getProjectSearchText()).isEqualTo("") + .as("project search text can be set to empty string"); } @Test public void getSetProjectSearchReplacement() { token = new HistoryToken(); token.setProjectSearchReplacement("some project search replacement text"); - assertEquals("some project search replacement text", - token.getProjectSearchReplacement()); + assertThat(token.getProjectSearchReplacement()).isEqualTo("some project search replacement text"); token.setProjectSearchReplacement(null); - assertEquals( - "project search replacement text should be returned as empty string after setting to null", - "", token.getProjectSearchReplacement()); + assertThat(token.getProjectSearchReplacement()) + .as("project search replacement text should be returned as empty string after setting to null") + .isEqualTo(""); token.setProjectSearchReplacement("text to be discarded"); token.setProjectSearchReplacement(""); - assertEquals( - "project search replacement text can be set to empty string", - "", token.getProjectSearchReplacement()); + assertThat(token.getProjectSearchReplacement()) + .as("project search replacement text can be set to empty string") + .isEqualTo(""); } @Test public void getSetProjectSearchCaseSensitive() { token = new HistoryToken(); token.setProjectSearchCaseSensitive(true); - assertTrue(token.getProjectSearchCaseSensitive()); + assertThat(token.getProjectSearchCaseSensitive()).isTrue(); token.setProjectSearchCaseSensitive(false); - assertFalse(token.getProjectSearchCaseSensitive()); + assertThat(token.getProjectSearchCaseSensitive()).isFalse(); } @Test public void encodesColon() { token = new HistoryToken(); token.setProjectSearchText("test:test"); - assertEquals( - "Colons should be replaced with \"!c\" in the token string", - "projectsearch:test!ctest", token.toTokenString()); + assertThat(token.toTokenString()).isEqualTo("projectsearch:test!ctest") + .as("Colons should be replaced with \"!c\" in the token string"); } @Test public void encodesSemicolon() { token = new HistoryToken(); token.setProjectSearchText("test;test"); - assertEquals( - "Semicolons should be replaced with \"!s\" in the token string", - "projectsearch:test!stest", token.toTokenString()); + assertThat(token.toTokenString()).isEqualTo("projectsearch:test!stest") + .as("Semicolons should be replaced with \"!s\" in the token string"); } @Test @@ -384,8 +360,8 @@ public void toTokenStringHasNoDefaults() { String tokenString = token.toTokenString(); - assertEquals("output token string should not contain default values", - 0, tokenString.length()); + assertThat(tokenString.length()).isEqualTo(0) + .as("output token string should not contain default values"); } @Test @@ -402,15 +378,17 @@ public void toTokenStringHasCustomValues() { String newTokenString = token.toTokenString(); - assertTrue(newTokenString.contains("filter:myfilter")); - assertTrue(newTokenString.contains("doc:some/document")); - assertTrue(newTokenString.contains("view:doc")); - assertTrue(newTokenString.contains("filtertype:exact")); - assertTrue(newTokenString.contains("search:searchtext")); - assertTrue(newTokenString.contains("projectsearch:projectsearchtext")); - assertTrue(newTokenString - .contains("projectsearchreplace:replacementtext")); - assertTrue(newTokenString.contains("projectsearchcase:sensitive")); + assertThat(newTokenString.contains("filter:myfilter")).isTrue(); + assertThat(newTokenString.contains("doc:some/document")).isTrue(); + assertThat(newTokenString.contains("view:doc")).isTrue(); + assertThat(newTokenString.contains("filtertype:exact")).isTrue(); + assertThat(newTokenString.contains("search:searchtext")).isTrue(); + assertThat(newTokenString.contains("projectsearch:projectsearchtext")) + .isTrue(); + assertThat(newTokenString + .contains("projectsearchreplace:replacementtext")).isTrue(); + assertThat(newTokenString.contains("projectsearchcase:sensitive")) + .isTrue(); } @Test @@ -430,30 +408,23 @@ public void tokenStringRoundTrip() { token = null; token = HistoryToken.fromTokenString(tokenString); - assertEquals( - "view should survive a round-trip to and from token string", - MainView.Editor, token.getView()); - assertEquals( - "document path should survive a round-trip to and from token string", - "some/document", token.getDocumentPath()); - assertEquals( - "document filter text should survive a round-trip to and from token string", - "myfilter", token.getDocFilterText()); - assertTrue( - "document filter exact match flag should survive a round-trip to and from token string", - token.getDocFilterExact()); - assertEquals( - "search text should survive a round-trip to and from token string", - "searchtext", token.getEditorTextSearch()); - assertEquals( - "project-wide search text should survive a round-trip to and from token string", - "projectsearchtext", token.getProjectSearchText()); - assertEquals( - "project-wide search replacement text should survive a round-trip to and from token string", - "replacementtext", token.getProjectSearchReplacement()); - assertTrue( - "project-wide search case sensitivity should survive a round-trip to and from token string", - token.getProjectSearchCaseSensitive()); + assertThat(token.getView()).isEqualTo(MainView.Editor) + .as("view should survive a round-trip to and from token string"); + assertThat(token.getDocumentPath()).isEqualTo("some/document") + .as("document path should survive a round-trip to and from token string"); + assertThat(token.getDocFilterText()).isEqualTo("myfilter") + .as("document filter text should survive a round-trip to and from token string"); + assertThat(token.getDocFilterExact()).isTrue() + .as("document filter exact match flag should survive a round-trip to and from token string"); + assertThat(token.getEditorTextSearch()).isEqualTo("searchtext") + .as("search text should survive a round-trip to and from token string"); + assertThat(token.getProjectSearchText()).isEqualTo("projectsearchtext") + .as("project-wide search text should survive a round-trip to and from token string"); + assertThat(token.getProjectSearchReplacement()) + .isEqualTo("replacementtext") + .as("project-wide search replacement text should survive a round-trip to and from token string"); + assertThat(token.getProjectSearchCaseSensitive()).isTrue().as( + "project-wide search case sensitivity should survive a round-trip to and from token string"); } @Test @@ -470,21 +441,20 @@ public void tokenStringRoundTripWithEncodedCharacters() { token = null; token = HistoryToken.fromTokenString(tokenString); - assertEquals( - "encodable characters in document path should survive a round-trip to and from token string", - "some:document;with!encodedchars", token.getDocumentPath()); - assertEquals( - "encodable characters in document filter text should survive a round-trip to and from token string", - "my!fil:ter;", token.getDocFilterText()); - assertEquals( - "encodable characters in search text should survive a round-trip to and from token string", - ":search!text;", token.getEditorTextSearch()); - assertEquals( - "encodable characters in project-wide search text should survive a round-trip to and from token string", - "project:search;text!", token.getProjectSearchText()); - assertEquals( - "encodable characters in project-wide search replacement text should survive a round-trip to and from token string", - "re!place;ment:text", token.getProjectSearchReplacement()); + assertThat(token.getDocumentPath()) + .isEqualTo("some:document;with!encodedchars") + .as("encodable characters in document path should survive a round-trip to and from token string"); + + assertThat(token.getDocFilterText()).isEqualTo("my!fil:ter;") + .as("encodable characters in document filter text should survive a round-trip to and from token string"); + assertThat(token.getEditorTextSearch()).isEqualTo(":search!text;") + .as("encodable characters in search text should survive a round-trip to and from token string"); + assertThat(token.getProjectSearchText()) + .isEqualTo("project:search;text!") + .as("encodable characters in project-wide search text should survive a round-trip to and from token string"); + assertThat(token.getProjectSearchReplacement()) + .isEqualTo("re!place;ment:text") + .as("encodable characters in project-wide search replacement text should survive a round-trip to and from token string"); } @Test @@ -494,9 +464,7 @@ public void tokenStringHasFilterOption() { token.setFilterTranslated(true); String tokenString = token.toTokenString(); - - assertThat(tokenString, Matchers.containsString("fuzzy:show")); - assertThat(tokenString, Matchers.containsString("translated:show")); + assertThat(tokenString).contains("fuzzy:show", "translated:show"); } @Test @@ -511,7 +479,7 @@ public void tokenStringHasAllFilterOption() { String tokenString = token.toTokenString(); - assertThat(tokenString, Matchers.equalTo("")); + assertThat(tokenString).isEqualTo(""); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/AppPresenterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/AppPresenterTest.java index 9f7cfb4202..d3f92bc8b5 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/AppPresenterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/AppPresenterTest.java @@ -1,7 +1,6 @@ package org.zanata.webtrans.client.presenter; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.*; @@ -15,7 +14,6 @@ import net.customware.gwt.presenter.client.EventBus; import net.customware.gwt.presenter.client.PresenterRevealedEvent; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -177,26 +175,24 @@ public void testKeyShortcutsKeys() { // testing keys KeyShortcut docListKey = shortcuts.get(0); - assertThat(docListKey.getAllKeys(), - Matchers.contains(new Keys(Keys.ALT_KEY, 'L'))); - assertThat(docListKey.getDescription(), Matchers.equalTo("doc list")); - assertThat(docListKey.getContext(), - Matchers.equalTo(ShortcutContext.Application)); + assertThat(docListKey.getAllKeys()) + .contains(new Keys(Keys.ALT_KEY, 'L')); + assertThat(docListKey.getDescription()).isEqualTo("doc list"); + assertThat(docListKey.getContext()) + .isEqualTo(ShortcutContext.Application); KeyShortcut editorKey = shortcuts.get(1); - assertThat(editorKey.getAllKeys(), - Matchers.contains(new Keys(Keys.ALT_KEY, 'O'))); - assertThat(editorKey.getDescription(), Matchers.equalTo("editor")); - assertThat(editorKey.getContext(), - Matchers.equalTo(ShortcutContext.Application)); + assertThat(editorKey.getAllKeys()) + .contains(new Keys(Keys.ALT_KEY, 'O')); + assertThat(editorKey.getDescription()).isEqualTo("editor"); + assertThat(editorKey.getContext()) + .isEqualTo(ShortcutContext.Application); KeyShortcut searchKey = shortcuts.get(2); - assertThat(searchKey.getAllKeys(), - Matchers.contains(new Keys(Keys.ALT_KEY, 'P'))); - assertThat(searchKey.getDescription(), - Matchers.equalTo("project wide search")); - assertThat(searchKey.getContext(), - Matchers.equalTo(ShortcutContext.Application)); + assertThat(searchKey.getAllKeys()) + .contains(new Keys(Keys.ALT_KEY, 'P')); + assertThat(searchKey.getDescription()).isEqualTo("project wide search"); + assertThat(searchKey.getContext()).isEqualTo(ShortcutContext.Application); } @Test @@ -220,7 +216,7 @@ public void testKeyShortcutHandlers() { HistoryToken docToken = new HistoryToken(); when(history.getHistoryToken()).thenReturn(docToken); docListKey.getHandler().onKeyShortcut(null); - assertThat(docToken.getView(), Matchers.is(MainView.Documents)); + assertThat(docToken.getView()).isEqualTo(MainView.Documents); verify(history).newItem(docToken.toTokenString()); // editor key handler on selected doc is null @@ -235,14 +231,14 @@ public void testKeyShortcutHandlers() { presenter.setStatesForTest(null, null, MainView.Documents, selectedDocument); editorKey.getHandler().onKeyShortcut(null); - assertThat(editorToken.getView(), Matchers.is(MainView.Editor)); + assertThat(editorToken.getView()).isEqualTo(MainView.Editor); verify(history).newItem(editorToken.toTokenString()); // search key handler HistoryToken searchToken = new HistoryToken(); when(history.getHistoryToken()).thenReturn(searchToken); searchKey.getHandler().onKeyShortcut(null); - assertThat(searchToken.getView(), Matchers.is(MainView.Search)); + assertThat(searchToken.getView()).isEqualTo(MainView.Search); verify(history).newItem(searchToken.toTokenString()); } @@ -267,7 +263,7 @@ public void onWorkspaceContextUpdateToReadOnly() { verify(eventBus).fireEvent(eventCaptor.capture()); NotificationEvent event = eventCaptor.getValue(); - assertThat(event.getMessage(), Matchers.equalTo("readonly workspace")); + assertThat(event.getMessage()).isEqualTo("readonly workspace"); verify(display).setReadOnlyVisible(userWorkspace.hasReadOnlyAccess()); } @@ -283,7 +279,7 @@ public void onWorkspaceContextUpdateToEditable() { verify(eventBus).fireEvent(eventCaptor.capture()); NotificationEvent event = eventCaptor.getValue(); - assertThat(event.getMessage(), Matchers.equalTo("editable workspace")); + assertThat(event.getMessage()).isEqualTo("editable workspace"); verify(display).setReadOnlyVisible(userWorkspace.hasReadOnlyAccess()); } @@ -303,8 +299,7 @@ public void canSwitchToEditorView() { verify(display).showInMainView(MainView.Editor); verify(display).setStats(statsCaptor.capture(), eq(true)); - assertThat(statsCaptor.getValue(), - Matchers.sameInstance(selectedDocumentStats)); + assertThat(statsCaptor.getValue()).isSameAs(selectedDocumentStats); } @Test @@ -327,16 +322,14 @@ public void canSwitchToSearchView() { verify(display).showInMainView(MainView.Search); verify(display).setStats(statsCaptor.capture(), eq(true)); - assertThat(statsCaptor.getValue(), Matchers.sameInstance(projectStats)); + assertThat(statsCaptor.getValue()).isSameAs(projectStats); } @Test public void canSwitchToDocumentView() { // Given: current selected document is null - assertThat(presenter.getSelectedDocIdOrNull(), - Matchers.is(Matchers.nullValue())); - assertThat(presenter.getSelectedDocumentInfoOrNull(), - Matchers.is(Matchers.nullValue())); + assertThat(presenter.getSelectedDocIdOrNull()).isNull(); + assertThat(presenter.getSelectedDocumentInfoOrNull()).isNull(); when(messages.documentListTitle()).thenReturn("Documents"); presenter.setStatesForTest(projectStats, selectedDocumentStats, null, null); @@ -352,7 +345,7 @@ public void canSwitchToDocumentView() { verify(display).showInMainView(MainView.Documents); verify(display).setStats(statsCaptor.capture(), eq(true)); - assertThat(statsCaptor.getValue(), Matchers.sameInstance(projectStats)); + assertThat(statsCaptor.getValue()).isSameAs(projectStats); } @Test @@ -379,8 +372,7 @@ public void canSelectDocumentInEditorView() { // current view is editor presenter.showView(MainView.Editor); verify(display).setStats(statsCaptor.capture(), eq(true)); - assertThat(statsCaptor.getValue(), - Matchers.sameInstance(selectedDocumentStats)); + assertThat(statsCaptor.getValue()).isSameAs(selectedDocumentStats); // When: presenter.selectDocument(docId); @@ -388,9 +380,8 @@ public void canSelectDocumentInEditorView() { // Then: display.setDocumentLabel("pot/", "a.po"); verify(display, atLeastOnce()).setStats(selectedDocumentStats, true); - assertThat(selectedDocumentStats.getStats(), - Matchers.equalTo(newSelectedStats.getStats())); - assertThat(presenter.getSelectedDocIdOrNull(), Matchers.is(docId)); + assertThat(selectedDocumentStats.getStats()).isEqualTo(newSelectedStats.getStats()); + assertThat(presenter.getSelectedDocIdOrNull()).isEqualTo(docId); } @Test @@ -423,15 +414,13 @@ public void canSelectDocumentNotInEditorView() { verify(display).enableTab(MainView.Editor, true); verifyNoMoreInteractions(display); - assertThat(presenter.getSelectedDocIdOrNull(), Matchers.is(docId)); - assertThat(presenter.getSelectedDocumentInfoOrNull(), - Matchers.is(documentInfo)); + assertThat(presenter.getSelectedDocIdOrNull()).isEqualTo(docId); + assertThat(presenter.getSelectedDocumentInfoOrNull()).isEqualTo(documentInfo); } @Test public void onDocumentStatsUpdateWillDoNothingIfNoSelectedDocument() { - assertThat(presenter.getSelectedDocumentInfoOrNull(), - Matchers.is(Matchers.nullValue())); + assertThat(presenter.getSelectedDocumentInfoOrNull()).isNull(); presenter.onDocumentStatsUpdated(new DocumentStatsUpdatedEvent( new DocumentId(1L, ""), new ContainerTranslationStatistics())); @@ -483,8 +472,7 @@ selectedDocumentStats, new AuditInfo(new Date(), newStats)); // Then: - assertThat(selectedDocumentStats.getStats(), - Matchers.equalTo(newStats.getStats())); + assertThat(selectedDocumentStats.getStats()).isEqualTo(newStats.getStats()); verify(display, atLeastOnce()).setStats(selectedDocumentStats, true); } @@ -581,8 +569,8 @@ public void onProjectStatsUpdated() { RefreshProjectStatsEvent event = new RefreshProjectStatsEvent(buildSampleDocumentArray()); presenter.onProjectStatsUpdated(event); - assertThat("project stats should contain stats in the event", - projectStats.getStats().size(), is(2)); + assertThat(projectStats.getStats().size()).isEqualTo(2) + .as("project stats should contain stats in the event"); verify(display, times(2)).setStats(projectStats, true); } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/ChangeReferenceLangPresenterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/ChangeReferenceLangPresenterTest.java index 592a270d45..237f25f98e 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/ChangeReferenceLangPresenterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/ChangeReferenceLangPresenterTest.java @@ -1,13 +1,11 @@ package org.zanata.webtrans.client.presenter; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; - import net.customware.gwt.presenter.client.EventBus; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; @@ -60,8 +58,8 @@ public void onSourceLangListBoxOptionChangedWithValidLocale() { presenter.onSourceLangListBoxOptionChanged(new Locale( new IdForLocale(1L, LocaleId.EN_US), "en-US")); - assertThat(configHolder.getState().getSelectedReferenceForSourceLang(), - Matchers.equalTo("en-US")); + assertThat(configHolder.getState().getSelectedReferenceForSourceLang()) + .isEqualTo("en-US"); verify(eventBus).fireEvent(UserConfigChangeEvent.EDITOR_CONFIG_CHANGE_EVENT); } @@ -72,8 +70,8 @@ public void onSourceLangListBoxOptionChangedWithNotChosenLocale() { presenter.onSourceLangListBoxOptionChanged(Locale.notChosenLocale); - assertThat(configHolder.getState().getSelectedReferenceForSourceLang(), - Matchers.equalTo(UserConfigHolder.DEFAULT_SELECTED_REFERENCE)); + assertThat(configHolder.getState().getSelectedReferenceForSourceLang()) + .isEqualTo(UserConfigHolder.DEFAULT_SELECTED_REFERENCE); verify(eventBus).fireEvent(UserConfigChangeEvent.EDITOR_CONFIG_CHANGE_EVENT); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/ComparingPairTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/ComparingPairTest.java index 24801c5709..d22bf3bcf5 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/ComparingPairTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/ComparingPairTest.java @@ -23,7 +23,6 @@ import java.util.Date; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.zanata.common.ContentState; @@ -31,7 +30,7 @@ import com.google.common.collect.Lists; -import static org.hamcrest.MatcherAssert.*; +import static org.assertj.core.api.Assertions.assertThat; /** * @author Patrick Huang eventCaptor = ArgumentCaptor.forClass(UserConfigChangeEvent.class); verify(eventBus).fireEvent(eventCaptor.capture()); - assertThat(eventCaptor.getValue().getView(), - Matchers.equalTo(MainView.Documents)); + assertThat(eventCaptor.getValue().getView()) + .isEqualTo(MainView.Documents); } @Test @@ -211,10 +209,9 @@ public void onLoadSavedOption() { AsyncCallback callback = callbackCaptor.getValue(); callback.onSuccess(result); - assertThat(configHolder.getState().getDocumentListPageSize(), - Matchers.equalTo(100)); - assertThat(configHolder.getState().isShowError(), - Matchers.equalTo(true)); + assertThat(configHolder.getState().getDocumentListPageSize()) + .isEqualTo(100); + assertThat(configHolder.getState().isShowError()).isTrue(); verify(eventBus).fireEvent(isA(UserConfigChangeEvent.class)); diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/DocumentListPresenterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/DocumentListPresenterTest.java index 2eeb466783..e0c9445fbe 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/DocumentListPresenterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/DocumentListPresenterTest.java @@ -1,11 +1,6 @@ package org.zanata.webtrans.client.presenter; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.hasItems; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.isIn; -import static org.hamcrest.Matchers.notNullValue; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; @@ -170,24 +165,21 @@ public void loadDocsIntoDataProvider() { documentListPresenter.setDocuments(buildSampleDocumentArray()); // right amount of docs - assertThat( - "the data provider should have the same sized document list returned from the server", - documentListPresenter.getFilteredNodes().size(), is(3)); + assertThat(documentListPresenter.getFilteredNodes()).hasSize(3) + .as("the data provider should have the same sized document list returned from the server"); ArrayList expectedDocs = buildSampleDocumentArray(); ArrayList actualDocInfos = new ArrayList(); for (DocumentNode node : documentListPresenter.getFilteredNodes()) { - assertThat( - "the data provider should have only documents that were returned from the server", - node.getDocInfo(), isIn(expectedDocs)); + assertThat(node.getDocInfo()).isIn(expectedDocs) + .as("the data provider should have only documents that were returned from the server"); actualDocInfos.add(node.getDocInfo()); } - assertThat( - "the data provider should have all documents returned from the server", - actualDocInfos, - hasItems(expectedDocs.get(0), expectedDocs.get(1), - expectedDocs.get(2))); + assertThat(actualDocInfos) + .contains(expectedDocs.get(0), expectedDocs.get(1), + expectedDocs.get(2)) + .as("the data provider should have all documents returned from the server"); } @Test @@ -231,51 +223,43 @@ public void generatesDocumentStatsOnTuUpdate() { TestFixture.extractFromEvents(capturedEventBusEvent.getAllValues(), DocumentStatsUpdatedEvent.class); - assertThat( - "a document stats event should be fired when a TU update event occurs, not found", - docStatsEvent, notNullValue()); + assertThat(docStatsEvent).isNotNull() + .as("a document stats event should be fired when a TU update event occurs, not found"); // document stats - assertThat( - "document id in document stats event shoudl match updated TU document id", - docStatsEvent.getDocId(), equalTo(new DocumentId(2222L, ""))); + assertThat(docStatsEvent.getDocId()) + .isEqualTo(new DocumentId(2222L, "")) + .as("document id in document stats event shoudl match updated TU document id"); // check actual counts (approved/fuzzy/untranslated) // default TUs: 1/2/3 // approving 1 fuzzy, expect 2/1/3 - assertThat( - "document Approved TU count should increase by 1 when a TU is updated from NeedsReview to Approved", - docStatsEvent.getNewStats() - .getStats(LocaleId.ES.toString(), StatUnit.MESSAGE) - .getApproved(), is(new Long(2))); - assertThat( - "document NeedsReview TU count should decrease by 1 when a TU is updated from NeedsReview to Approved", - docStatsEvent.getNewStats() - .getStats(LocaleId.ES.toString(), StatUnit.MESSAGE) - .getDraft(), is(new Long(1))); - assertThat( - "document Untranslated TU count should remain the same when a TU is updated from NeedsReview to Approved", - docStatsEvent.getNewStats() - .getStats(LocaleId.ES.toString(), StatUnit.MESSAGE) - .getUntranslated(), is(new Long(3))); + assertThat(docStatsEvent.getNewStats() + .getStats(LocaleId.ES.toString(), StatUnit.MESSAGE) + .getApproved()).isEqualTo(new Long(2)) + .as("document Approved TU count should increase by 1 when a TU is updated from NeedsReview to Approved"); + assertThat(docStatsEvent.getNewStats() + .getStats(LocaleId.ES.toString(), StatUnit.MESSAGE).getDraft()) + .isEqualTo(new Long(1)); + assertThat(docStatsEvent.getNewStats() + .getStats(LocaleId.ES.toString(), StatUnit.MESSAGE) + .getUntranslated()).isEqualTo(new Long(3)) + .as("document Untranslated TU count should remain the same when a TU is updated from NeedsReview to Approved"); // default words: 4/5/6 // approving 3 fuzzy so expect 7/2/6 - assertThat( - "document Approved words should increase when TU changes to Approved", - docStatsEvent.getNewStats() - .getStats(LocaleId.ES.toString(), StatUnit.WORD) - .getApproved(), is(new Long(7))); - assertThat( - "document NeedsReview words should decrease when a TU changes from NeedsReview", - docStatsEvent.getNewStats() - .getStats(LocaleId.ES.toString(), StatUnit.WORD) - .getDraft(), is(new Long(2))); - assertThat( - "document Untranslated words should not change when TU changes between NeedsReview and Approved", - docStatsEvent.getNewStats() - .getStats(LocaleId.ES.toString(), StatUnit.WORD) - .getDraft(), is(new Long(2))); + assertThat(docStatsEvent.getNewStats() + .getStats(LocaleId.ES.toString(), StatUnit.WORD).getApproved()) + .isEqualTo(new Long(7)) + .as("document Approved words should increase when TU changes to Approved"); + assertThat(docStatsEvent.getNewStats() + .getStats(LocaleId.ES.toString(), StatUnit.WORD).getDraft()) + .isEqualTo(new Long(2)) + .as("document NeedsReview words should decrease when a TU changes from NeedsReview"); + assertThat(docStatsEvent.getNewStats() + .getStats(LocaleId.ES.toString(), StatUnit.WORD).getDraft()) + .isEqualTo(new Long(2)) + .as("document Untranslated words should not change when TU changes between NeedsReview and Approved"); } @Test @@ -292,12 +276,11 @@ public void filterTextUpdateGeneratesHistoryToken() { HistoryToken capturedHistoryToken = HistoryToken.fromTokenString(capturedHistoryTokenString .getValue()); - assertThat( - "generated history token filter text should match the filter textbox", - capturedHistoryToken.getDocFilterText(), is(filterText)); - assertThat( - "generated history token filter exact flag should match the exact match checkbox", - capturedHistoryToken.getDocFilterExact(), is(false)); + assertThat(capturedHistoryToken.getDocFilterText()) + .isEqualTo(filterText) + .as("generated history token filter text should match the filter textbox"); + assertThat(capturedHistoryToken.getDocFilterExact()).isFalse() + .as("generated history token filter exact flag should match the exact match checkbox"); } @Test @@ -311,10 +294,9 @@ public void checkExactSearchCheckboxGeneratesHistoryToken() { HistoryToken exactSearchToken = new HistoryToken(); exactSearchToken.setDocFilterExact(true); - assertThat( - "checking the 'exact search' checkbox should be reflected in a new history token", - capturedHistoryTokenString.getValue(), - is(exactSearchToken.toTokenString())); + assertThat(capturedHistoryTokenString.getValue()) + .isEqualTo(exactSearchToken.toTokenString()) + .as("checking the 'exact search' checkbox should be reflected in a new history token"); } @Test @@ -333,10 +315,9 @@ public void uncheckExactSearchCheckboxGeneratesHistoryToken() { HistoryToken inexactSearchToken = new HistoryToken(); inexactSearchToken.setDocFilterExact(false); - assertThat( - "unchecking the 'exact search' checkbox should be reflected in a new history token", - capturedHistoryTokenString.getValue(), - is(inexactSearchToken.toTokenString())); + assertThat(capturedHistoryTokenString.getValue()) + .isEqualTo(inexactSearchToken.toTokenString()) + .as("unchecking the 'exact search' checkbox should be reflected in a new history token"); } // TODO tests for check and uncheck case sensitive check @@ -363,11 +344,10 @@ public void documentSelectUpdatesHistoryToken() { verify(mockUserWorkspaceContext).setSelectedDoc(docInfo); HistoryToken newToken = capturedHistoryToken.getValue(); - assertThat("path of selected document should be set in history token", - newToken.getDocumentPath(), is("second/path/doc122")); - assertThat( - "view in history token should change to individual document view when a new document is selected", - newToken.getView(), is(MainView.Editor)); + assertThat(newToken.getDocumentPath()).isEqualTo("second/path/doc122") + .as("path of selected document should be set in history token"); + assertThat(newToken.getView()).isEqualTo(MainView.Editor) + .as("view in history token should change to individual document view when a new document is selected"); } @Test @@ -391,17 +371,14 @@ public void exactSearchMatchesExactOnly() { expectedDocs.remove(0); // first doc does not match the filter ArrayList actualDocInfos = new ArrayList(); for (DocumentNode node : documentListPresenter.getFilteredNodes()) { - assertThat( - "the data provider should have only documents that exactly match the current filter", - node.getDocInfo(), isIn(expectedDocs)); + assertThat(node.getDocInfo()).isIn(expectedDocs) + .as("the data provider should have only documents that exactly match the current filter"); actualDocInfos.add(node.getDocInfo()); } - assertThat( - "the data provider should have all documents that exactly match the filter", - actualDocInfos, hasItems(expectedDocs.get(0))); - assertThat( - "the data provider list should contain exactly the number of documents matching the filter", - documentListPresenter.getFilteredNodes().size(), is(1)); + assertThat(actualDocInfos).contains(expectedDocs.get(0)) + .as("the data provider should have all documents that exactly match the filter"); + assertThat(documentListPresenter.getFilteredNodes()).hasSize(1) + .as("the data provider list should contain exactly the number of documents matching the filter"); } // TODO test case sensitivity option @@ -425,21 +402,18 @@ public void commaSeparatedFilter() { ArrayList expectedDocs = buildSampleDocumentArray(); expectedDocs.remove(1); // second doc does not match any of the filter - // strings + // strings ArrayList actualDocInfos = new ArrayList(); for (DocumentNode node : documentListPresenter.getFilteredNodes()) { - assertThat( - "the data provider should have only documents that match the current filter", - node.getDocInfo(), isIn(expectedDocs)); + assertThat(node.getDocInfo()).isIn(expectedDocs) + .as("the data provider should have only documents that match the current filter"); actualDocInfos.add(node.getDocInfo()); } - assertThat( - "the data provider should have all documents that match the filter", - actualDocInfos, - hasItems(expectedDocs.get(0), expectedDocs.get(1))); - assertThat( - "the data provider list should contain exactly the number of documents matching the filter", - documentListPresenter.getFilteredNodes().size(), is(2)); + assertThat(actualDocInfos) + .contains(expectedDocs.get(0), expectedDocs.get(1)) + .as("the data provider should have all documents that match the filter"); + assertThat(documentListPresenter.getFilteredNodes()).hasSize(2) + .as("the data provider list should contain exactly the number of documents matching the filter"); } // TODO test case sensitive check updated from history @@ -456,11 +430,11 @@ public void getDocumentId() { DocumentId docId = documentListPresenter .getDocumentId("does/not/match/exact/filter"); - assertThat(docId.getId(), is(3333L)); + assertThat(docId.getId()).isEqualTo(3333L); // second document from buildSampleDocumentArray() docId = documentListPresenter.getDocumentId("match/exact/filter"); - assertThat(docId.getId(), is(2222L)); + assertThat(docId.getId()).isEqualTo(2222L); } @Test @@ -471,19 +445,19 @@ public void getDocumentInfo() { DocumentId doc1 = new DocumentId(1111L, "no/filter/matches"); DocumentInfo docInfo = documentListPresenter.getDocumentInfo(doc1); - assertThat(docInfo, is(equalTo(new DocumentInfo(doc1, "doc111", + assertThat(docInfo).isEqualTo(new DocumentInfo(doc1, "doc111", "first/path/", LocaleId.EN_US, new ContainerTranslationStatistics(), new AuditInfo(new Date(), "Translator"), new HashMap(), - new AuditInfo(new Date(), "last translator"))))); + new AuditInfo(new Date(), "last translator"))); DocumentId doc2 = new DocumentId(3333L, "does/not/match/exact/filter"); docInfo = documentListPresenter.getDocumentInfo(doc2); - assertThat(docInfo, is(equalTo(new DocumentInfo(doc2, "doc123", + assertThat(docInfo).isEqualTo(new DocumentInfo(doc2, "doc123", "third/path/", LocaleId.EN_US, new ContainerTranslationStatistics(), new AuditInfo(new Date(), "Translator"), new HashMap(), - new AuditInfo(new Date(), "last translator"))))); + new AuditInfo(new Date(), "last translator"))); } @Test diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/EditorKeyShortcutsTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/EditorKeyShortcutsTest.java index f646cbdbf7..ac446527cc 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/EditorKeyShortcutsTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/EditorKeyShortcutsTest.java @@ -1,6 +1,6 @@ package org.zanata.webtrans.client.presenter; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.spy; @@ -12,7 +12,6 @@ import net.customware.gwt.presenter.client.EventBus; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -121,7 +120,7 @@ public void testCopyTMKeyHandler() { copy3TM.getHandler().onKeyShortcut(null); verify(eventBus).fireEvent(eventCaptor.capture()); - assertThat(eventCaptor.getValue().getIndex(), Matchers.is(3)); + assertThat(eventCaptor.getValue().getIndex()).isEqualTo(3); } @Test @@ -185,8 +184,8 @@ public void testNextStateKeyHandler() { verify(targetContentsPresenter).savePendingChangesIfApplicable(); verify(eventBus).fireEvent(eventCaptor.capture()); - assertThat(eventCaptor.getValue().getRowType(), - Matchers.equalTo(NavTransUnitEvent.NavigationType.NextState)); + assertThat(eventCaptor.getValue().getRowType()) + .isEqualTo(NavTransUnitEvent.NavigationType.NextState); } @Test @@ -202,8 +201,8 @@ public void testPreviousStateKeyHandler() { verify(targetContentsPresenter).savePendingChangesIfApplicable(); verify(eventBus).fireEvent(eventCaptor.capture()); - assertThat(eventCaptor.getValue().getRowType(), - Matchers.equalTo(NavTransUnitEvent.NavigationType.PrevState)); + assertThat(eventCaptor.getValue().getRowType()) + .isEqualTo(NavTransUnitEvent.NavigationType.PrevState); } @Test @@ -360,27 +359,26 @@ public void testOnUserConfigChangedNavOption() throws Exception { KeyShortcut nextState = allKeys.get(2); KeyShortcut prevState = allKeys.get(3); - assertThat(nextState.getDescription(), Matchers.equalTo("next fuzzy")); - assertThat(prevState.getDescription(), Matchers.equalTo("prev fuzzy")); + assertThat(nextState.getDescription()).isEqualTo("next fuzzy"); + assertThat(prevState.getDescription()).isEqualTo("prev fuzzy"); } private static void assertKeys(KeyShortcut shortcut, String description, boolean isStopPropagation, boolean isPreventDefault, Keys... keys) { - assertThat(shortcut.getAllKeys(), Matchers.containsInAnyOrder(keys)); - assertThat(shortcut.getContext(), - Matchers.equalTo(ShortcutContext.Edit)); - assertThat(shortcut.getDescription(), Matchers.equalTo(description)); - assertThat(shortcut.getKeyEvent(), - Matchers.equalTo(KeyShortcut.KeyEvent.KEY_DOWN)); - assertThat(shortcut.isStopPropagation(), - Matchers.equalTo(isStopPropagation)); - assertThat(shortcut.isPreventDefault(), - Matchers.equalTo(isPreventDefault)); + assertThat(shortcut.getAllKeys()).contains(keys); + assertThat(shortcut.getContext()) + .isEqualTo(ShortcutContext.Edit); + assertThat(shortcut.getDescription()).isEqualTo(description); + assertThat(shortcut.getKeyEvent()) + .isEqualTo(KeyShortcut.KeyEvent.KEY_DOWN); + assertThat(shortcut.isStopPropagation()) + .isEqualTo(isStopPropagation); + assertThat(shortcut.isPreventDefault()) + .isEqualTo(isPreventDefault); } private static void assertAttentionKeys(KeyShortcut shortcut, Keys... keys) { - assertThat(shortcut.getAllAttentionKeys(), - Matchers.containsInAnyOrder(keys)); + assertThat(shortcut.getAllAttentionKeys()).contains(keys); } @Test diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/EditorOptionsPresenterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/EditorOptionsPresenterTest.java index 3c890ad2ee..fa58e61594 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/EditorOptionsPresenterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/EditorOptionsPresenterTest.java @@ -1,6 +1,6 @@ package org.zanata.webtrans.client.presenter; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -10,7 +10,6 @@ import net.customware.gwt.presenter.client.EventBus; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -128,8 +127,7 @@ public void canSetReadOnlyOnWorkspaceUpdate() { // Then: verify(userWorkspaceContext).setProjectActive(false); - assertThat(configHolder.getState().isDisplayButtons(), - Matchers.is(false)); + assertThat(configHolder.getState().isDisplayButtons()).isFalse(); verify(display).setOptionsState(configHolder.getState()); verify(eventBus).fireEvent( UserConfigChangeEvent.EDITOR_CONFIG_CHANGE_EVENT); @@ -179,12 +177,12 @@ public String getNewIterationSlug() { public void onPageSizeClick() { presenter.onPageSizeClick(99); - assertThat(configHolder.getState().getEditorPageSize(), - Matchers.equalTo(99)); + assertThat(configHolder.getState().getEditorPageSize()) + .isEqualTo(99); ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(EditorPageSizeChangeEvent.class); verify(eventBus).fireEvent(eventCaptor.capture()); - assertThat(eventCaptor.getValue().getPageSize(), Matchers.equalTo(99)); + assertThat(eventCaptor.getValue().getPageSize()).isEqualTo(99); } @Test @@ -193,8 +191,7 @@ public void onEnterSaveApprovedOptionChange() { presenter.onEnterSaveOptionChanged(true); - assertThat(configHolder.getState().isEnterSavesApproved(), - Matchers.is(true)); + assertThat(configHolder.getState().isEnterSavesApproved()).isTrue(); verify(eventBus).fireEvent( UserConfigChangeEvent.EDITOR_CONFIG_CHANGE_EVENT); } @@ -205,8 +202,7 @@ public void onEditorButtonsOptionChange() { presenter.onEditorButtonsOptionChanged(true); - assertThat(configHolder.getState().isDisplayButtons(), - Matchers.is(true)); + assertThat(configHolder.getState().isDisplayButtons()).isTrue(); verify(eventBus).fireEvent( UserConfigChangeEvent.EDITOR_CONFIG_CHANGE_EVENT); } @@ -217,8 +213,8 @@ public void onNavOptionChange() { presenter.onSelectionChange("", NavOption.FUZZY); - assertThat(configHolder.getState().getNavOption(), - Matchers.equalTo(NavOption.FUZZY)); + assertThat(configHolder.getState().getNavOption()) + .isEqualTo(NavOption.FUZZY); verify(eventBus).fireEvent( UserConfigChangeEvent.EDITOR_CONFIG_CHANGE_EVENT); } @@ -229,8 +225,7 @@ public void onShowSaveApprovedWarningChanged() { presenter.onShowSaveApprovedWarningChanged(false); - assertThat(configHolder.getState().isShowSaveApprovedWarning(), - Matchers.equalTo(false)); + assertThat(configHolder.getState().isShowSaveApprovedWarning()).isFalse(); verify(eventBus).fireEvent( UserConfigChangeEvent.EDITOR_CONFIG_CHANGE_EVENT); } @@ -241,8 +236,8 @@ public void onTMDisplayModeChanged() { presenter.onTransMemoryDisplayModeChanged(DiffMode.NORMAL); - assertThat(configHolder.getState().getTransMemoryDisplayMode(), - Matchers.equalTo(DiffMode.NORMAL)); + assertThat(configHolder.getState().getTransMemoryDisplayMode()) + .isEqualTo(DiffMode.NORMAL); verify(eventBus).fireEvent( UserConfigChangeEvent.EDITOR_CONFIG_CHANGE_EVENT); } @@ -253,8 +248,7 @@ public void onCodeMirrorOptionChanged() { presenter.onUseCodeMirrorOptionChanged(true, false); - assertThat(configHolder.getState().isUseCodeMirrorEditor(), - Matchers.equalTo(true)); + assertThat(configHolder.getState().isUseCodeMirrorEditor()).isTrue(); verify(eventBus).fireEvent(RefreshPageEvent.REDRAW_PAGE_EVENT); } @@ -307,10 +301,9 @@ public void onLoadSavedOption() { // when(translatedChk.getValue()).thenReturn(true); // when(untranslatedChk.getValue()).thenReturn(false); callback.onSuccess(result); - assertThat(configHolder.getState().getEditorPageSize(), - Matchers.equalTo(10)); - assertThat(configHolder.getState().getNavOption(), - Matchers.equalTo(NavOption.FUZZY)); + assertThat(configHolder.getState().getEditorPageSize()).isEqualTo(10); + assertThat(configHolder.getState().getNavOption()) + .isEqualTo(NavOption.FUZZY); verify(eventBus).fireEvent( UserConfigChangeEvent.EDITOR_CONFIG_CHANGE_EVENT); diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/ForceReviewCommentPresenterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/ForceReviewCommentPresenterTest.java index 11aefff2b3..bb4b3a8b88 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/ForceReviewCommentPresenterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/ForceReviewCommentPresenterTest.java @@ -21,7 +21,6 @@ package org.zanata.webtrans.client.presenter; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.Answers; @@ -44,7 +43,8 @@ import com.google.gwt.user.client.rpc.AsyncCallback; import net.customware.gwt.presenter.client.EventBus; -import static org.hamcrest.MatcherAssert.assertThat; + +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -86,8 +86,8 @@ public void setUp() throws Exception { verify(keyShortcutPresenter).register(shortcutCapture.capture()); KeyShortcut keyShortcut = shortcutCapture.getValue(); - assertThat(keyShortcut.getContext(), - Matchers.equalTo(ShortcutContext.RejectConfirmationPopup)); + assertThat(keyShortcut.getContext()) + .isEqualTo(ShortcutContext.RejectConfirmationPopup); } @Test @@ -111,8 +111,8 @@ public void testAddComment() throws Exception { verify(dispatcher).execute(actionCaptor.capture(), resultCaptor.capture()); - assertThat(actionCaptor.getValue().getContent(), - Matchers.equalTo("i hate this")); + assertThat(actionCaptor.getValue().getContent()) + .isEqualTo("i hate this"); AsyncCallback callback = resultCaptor.getValue(); diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/GlossaryDetailsPresenterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/GlossaryDetailsPresenterTest.java index 309836f8cf..700ca76f25 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/GlossaryDetailsPresenterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/GlossaryDetailsPresenterTest.java @@ -21,7 +21,7 @@ package org.zanata.webtrans.client.presenter; -import static org.hamcrest.MatcherAssert.*; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; @@ -29,7 +29,6 @@ import static org.mockito.Mockito.when; import net.customware.gwt.presenter.client.EventBus; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.Answers; @@ -123,8 +122,8 @@ public void show() { verify(mockDispatcher).execute(getGlossaryDetailsCaptor.capture(), getGlossarycallbackCaptor.capture()); - assertThat(getGlossaryDetailsCaptor.getValue().getSourceIdList(), - Matchers.equalTo(item.getSourceIdList())); + assertThat(getGlossaryDetailsCaptor.getValue().getSourceIdList()) + .isEqualTo(item.getSourceIdList()); AsyncCallback callback = getGlossarycallbackCaptor.getValue(); diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/GlossaryPresenterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/GlossaryPresenterTest.java index bc7e49276c..2d823d29e1 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/GlossaryPresenterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/GlossaryPresenterTest.java @@ -20,7 +20,7 @@ */ package org.zanata.webtrans.client.presenter; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.spy; @@ -33,7 +33,6 @@ import net.customware.gwt.presenter.client.EventBus; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -147,7 +146,7 @@ public void onFocus() { ShortcutContext.Navigation, !isFocused); verify(keyShortcutPresenter).setContextActive(ShortcutContext.Edit, !isFocused); - assertThat(presenter.isFocused(), Matchers.is(isFocused)); + assertThat(presenter.isFocused()).isEqualTo(isFocused); } @Test @@ -213,10 +212,9 @@ public void fireSearchEvent() { verify(dispatcher).execute(getGlossaryCaptor.capture(), callbackCaptor.capture()); GetGlossary action = getGlossaryCaptor.getValue(); - assertThat(action.getQuery(), Matchers.equalTo("query")); - assertThat(action.getSearchType(), Matchers.equalTo(SearchType.FUZZY)); - assertThat(action.getSrcLocaleId(), - Matchers.equalTo(docInfo.getSourceLocale())); + assertThat(action.getQuery()).isEqualTo("query"); + assertThat(action.getSearchType()).isEqualTo(SearchType.FUZZY); + assertThat(action.getSrcLocaleId()).isEqualTo(docInfo.getSourceLocale()); } @Test @@ -249,10 +247,9 @@ public void fireSearchEvent() { verify(dispatcher).execute(getGlossaryCaptor.capture(), callbackCaptor.capture()); GetGlossary action = getGlossaryCaptor.getValue(); - assertThat(action.getQuery(), Matchers.equalTo("query1")); - assertThat(action.getSearchType(), Matchers.equalTo(SearchType.FUZZY)); - assertThat(action.getSrcLocaleId(), - Matchers.equalTo(docInfo.getSourceLocale())); + assertThat(action.getQuery()).isEqualTo("query1"); + assertThat(action.getSearchType()).isEqualTo(SearchType.FUZZY); + assertThat(action.getSrcLocaleId()).isEqualTo(docInfo.getSourceLocale()); } @Test @@ -381,7 +378,7 @@ public void createGlossaryRequestForTransUnit() { verify(dispatcher).execute(getGlossaryCaptor.capture(), callbackCaptor.capture()); GetGlossary action = getGlossaryCaptor.getValue(); - assertThat(action.getQuery(), Matchers.equalTo("source1 source2 ")); + assertThat(action.getQuery()).isEqualTo("source1 source2 "); } @Test @@ -396,13 +393,10 @@ public void onKeyShortcut() { verify(keyShortcutPresenter).register(keyShortcutCaptor.capture()); KeyShortcut keyShortcut = keyShortcutCaptor.getValue(); - assertThat(keyShortcut.getAllKeys(), - Matchers.containsInAnyOrder(new Keys(Keys.NO_MODIFIER, - KeyCodes.KEY_ENTER))); - assertThat(keyShortcut.getContext(), - Matchers.equalTo(ShortcutContext.Glossary)); - assertThat(keyShortcut.getDescription(), - Matchers.equalTo("search glossary")); + assertThat(keyShortcut.getAllKeys()).contains(new Keys(Keys.NO_MODIFIER, + KeyCodes.KEY_ENTER)); + assertThat(keyShortcut.getContext()).isEqualTo(ShortcutContext.Glossary); + assertThat(keyShortcut.getDescription()).isEqualTo("search glossary"); keyShortcut.getHandler().onKeyShortcut(null); verify(spyPresenter).fireSearchEvent(); diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/KeyShortcutPresenterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/KeyShortcutPresenterTest.java index 838f699909..0d197f3113 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/KeyShortcutPresenterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/KeyShortcutPresenterTest.java @@ -20,8 +20,7 @@ */ package org.zanata.webtrans.client.presenter; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -59,7 +58,6 @@ /** * @author David Mason, damason@redhat.com - * */ public class KeyShortcutPresenterTest { static final String TEST_MESSAGE_CLOSE_SHORTCUT_VIEW = @@ -134,37 +132,38 @@ public void displaysRegisteredShortcutsInOrder() { keyShortcutPresenter.showShortcuts(); // Shortcut list should contain Alt+Y and Esc shortcuts - assertThat("KeyShortcutPresenter should register 2 global shortcuts", - shortcutList.size(), is(3)); + assertThat(shortcutList.size()).isEqualTo(3) + .as("KeyShortcutPresenter should register 2 global shortcuts"); // esc should be first as it has no modifiers Set firstShortcutKeys = shortcutList.get(0).getAllKeys(); String firstShortcut = "first shortcut should be Esc with no modifiers"; - assertThat(firstShortcut, firstShortcutKeys.size(), is(1)); + assertThat(firstShortcutKeys.size()).isEqualTo(1).as(firstShortcut); Keys firstShortcutFirstKeys = firstShortcutKeys.iterator().next(); - assertThat(firstShortcut, firstShortcutFirstKeys.getModifiers(), is(0)); - assertThat(firstShortcut, firstShortcutFirstKeys.getKeyCode(), - is(KeyCodes.KEY_ESCAPE)); + assertThat(firstShortcutFirstKeys.getModifiers()).isEqualTo(0) + .as(firstShortcut); + assertThat(firstShortcutFirstKeys.getKeyCode()) + .isEqualTo(KeyCodes.KEY_ESCAPE).as(firstShortcut); // Alt+X should be next Set secondShortcutKeys = shortcutList.get(1).getAllKeys(); String secondShortcut = "second shortcut should be Alt+X"; - assertThat(secondShortcut, secondShortcutKeys.size(), is(1)); + assertThat(secondShortcutKeys.size()).isEqualTo(1).as(secondShortcut); Keys secondShortcutFirstKeys = secondShortcutKeys.iterator().next(); - assertThat(secondShortcut, secondShortcutFirstKeys.getModifiers(), - is(Keys.ALT_KEY)); - assertThat(secondShortcut, secondShortcutFirstKeys.getKeyCode(), - is((int) 'X')); + assertThat(secondShortcutFirstKeys.getModifiers()) + .isEqualTo(Keys.ALT_KEY).as(secondShortcut); + assertThat(secondShortcutFirstKeys.getKeyCode()).isEqualTo((int) 'X') + .as(secondShortcut); // Alt+Y should be last Set thirdShortcutKeys = shortcutList.get(2).getAllKeys(); String thirdShortcut = "third shortcut should be Alt+Y"; - assertThat(thirdShortcut, thirdShortcutKeys.size(), is(1)); + assertThat(thirdShortcutKeys.size()).isEqualTo(1).as(thirdShortcut); Keys thirdShortcutFirstKeys = thirdShortcutKeys.iterator().next(); - assertThat(thirdShortcut, thirdShortcutFirstKeys.getModifiers(), - is(Keys.ALT_KEY)); - assertThat(thirdShortcut, thirdShortcutFirstKeys.getKeyCode(), - is((int) 'Y')); + assertThat(thirdShortcutFirstKeys.getModifiers()) + .isEqualTo(Keys.ALT_KEY).as(thirdShortcut); + assertThat(thirdShortcutFirstKeys.getKeyCode()).isEqualTo((int) 'Y') + .as(thirdShortcut); } @Test @@ -199,9 +198,9 @@ public void testAttentionModeTimesOut() { verify(mockTimer).schedule(5000); capturedTimedAction.getValue().run(); verify(mockEventBus, times(2)).fireEvent(eventBusCapture.capture()); - assertThat(eventBusCapture.getAllValues().get(0).isActive(), is(true)); - assertThat(eventBusCapture.getAllValues().get(1).isActive(), is(false)); - assertThat(eventBusCapture.getAllValues().size(), is(2)); + assertThat(eventBusCapture.getAllValues().get(0).isActive()).isTrue(); + assertThat(eventBusCapture.getAllValues().get(1).isActive()).isFalse(); + assertThat(eventBusCapture.getAllValues().size()).isEqualTo(2); } private NativePreviewEvent buildNativeKeyDownEvent(Keys keys) { diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/OptionsPresenterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/OptionsPresenterTest.java index 904ce4f02d..256a7974d8 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/OptionsPresenterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/OptionsPresenterTest.java @@ -1,16 +1,13 @@ package org.zanata.webtrans.client.presenter; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import net.customware.gwt.presenter.client.EventBus; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.zanata.webtrans.client.events.UserConfigChangeEvent; @@ -36,9 +33,6 @@ public class OptionsPresenterTest { private UserConfigHolder configHolder = new UserConfigHolder(); - @Captor - private ArgumentCaptor eventCaptor; - @Before public void beforeMethod() { MockitoAnnotations.initMocks(this); @@ -109,8 +103,7 @@ public void onShowErrorsOptionChanged() { presenter.onBind(); presenter.onShowErrorsOptionChanged(true); - assertThat(configHolder.getState().isShowError(), - Matchers.equalTo(true)); + assertThat(configHolder.getState().isShowError()).isTrue(); } @Test @@ -118,8 +111,8 @@ public void onDisplayThemeChanged() { presenter.onBind(); presenter.onThemesChanged(ThemesOption.THEMES_COMPACT.name()); - assertThat(configHolder.getState().getDisplayTheme(), - Matchers.equalTo(ThemesOption.THEMES_COMPACT)); + assertThat(configHolder.getState().getDisplayTheme()) + .isEqualTo(ThemesOption.THEMES_COMPACT); } @Test diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/PathDocumentFilterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/PathDocumentFilterTest.java index 95fc1e550a..8b869c8dc2 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/PathDocumentFilterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/PathDocumentFilterTest.java @@ -1,11 +1,8 @@ package org.zanata.webtrans.client.presenter; -import static org.hamcrest.MatcherAssert.assertThat; - import java.util.Date; import java.util.HashMap; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.zanata.common.LocaleId; @@ -14,6 +11,8 @@ import org.zanata.webtrans.shared.model.DocumentId; import org.zanata.webtrans.shared.model.DocumentInfo; +import static org.assertj.core.api.Assertions.assertThat; + /** * @author Patrick Huang pahuang@redhat.com @@ -39,46 +38,42 @@ public void testAcceptWithCaseInsensitiveAndNotExactMatch() throws Exception { filter.setPattern("a,b b, c , , d"); - assertThat(filter.accept(docInfo("a", "/pot/")), Matchers.equalTo(true)); - assertThat(filter.accept(docInfo("b b", "/pot/")), - Matchers.equalTo(true)); - assertThat(filter.accept(docInfo("c", "/pot/")), Matchers.equalTo(true)); - assertThat(filter.accept(docInfo("C", "/pot/")), Matchers.equalTo(true)); - assertThat(filter.accept(docInfo("d", "/pot/")), Matchers.equalTo(true)); - assertThat(filter.accept(docInfo("b", "/pot/")), - Matchers.equalTo(false)); + assertThat(filter.accept(docInfo("a", "/pot/"))).isTrue(); + assertThat(filter.accept(docInfo("b b", "/pot/"))).isTrue(); + assertThat(filter.accept(docInfo("c", "/pot/"))).isTrue(); + assertThat(filter.accept(docInfo("C", "/pot/"))).isTrue(); + assertThat(filter.accept(docInfo("d", "/pot/"))).isTrue(); + assertThat(filter.accept(docInfo("b", "/pot/"))).isFalse(); } @Test public void testAcceptWithCaseSensitiveAndNotExactMatch() throws Exception { filter.setPattern("a").setCaseSensitive(true); - assertThat(filter.accept(docInfo("a", "/pot/")), Matchers.equalTo(true)); - assertThat(filter.accept(docInfo("A", "/pot/")), - Matchers.equalTo(false)); + assertThat(filter.accept(docInfo("a", "/pot/"))).isTrue(); + assertThat(filter.accept(docInfo("A", "/pot/"))).isFalse(); } @Test public void testSetFullText() throws Exception { filter.setPattern("/pot/a").setFullText(true); - assertThat(filter.accept(docInfo("a", "/pot/")), Matchers.equalTo(true)); - assertThat(filter.accept(docInfo("a", "")), Matchers.equalTo(false)); + assertThat(filter.accept(docInfo("a", "/pot/"))).isTrue(); + assertThat(filter.accept(docInfo("a", ""))).isFalse(); } @Test public void alwaysAcceptIfNoPattern() { - assertThat(filter.accept(docInfo("a", "/pot/")), Matchers.equalTo(true)); + assertThat(filter.accept(docInfo("a", "/pot/"))).isTrue(); } @Test public void testSetPatternAgainWillClearPreviousPattern() throws Exception { filter.setPattern("a"); - assertThat(filter.accept(docInfo("a", "/pot/")), Matchers.equalTo(true)); + assertThat(filter.accept(docInfo("a", "/pot/"))).isTrue(); filter.setPattern("b"); - assertThat(filter.accept(docInfo("b", "/pot/")), Matchers.equalTo(true)); - assertThat(filter.accept(docInfo("a", "/pot/")), - Matchers.equalTo(false)); + assertThat(filter.accept(docInfo("b", "/pot/"))).isTrue(); + assertThat(filter.accept(docInfo("a", "/pot/"))).isFalse(); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/SearchResultsPresenterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/SearchResultsPresenterTest.java index 9c5ec047aa..37464603af 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/SearchResultsPresenterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/SearchResultsPresenterTest.java @@ -20,11 +20,9 @@ */ package org.zanata.webtrans.client.presenter; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -324,19 +322,18 @@ public void searchButtonClickUpdatesHistory() { verify(mockHistory).newItem(capturedHistoryToken.capture()); HistoryToken newToken = capturedHistoryToken.getValue(); - assertThat( - "new history token should be updated with current search phrase in search text box", - newToken.getProjectSearchText(), is(TEST_SEARCH_PHRASE)); - assertThat( - "new history token project search case sensitivity should match checkbox value", - newToken.getProjectSearchCaseSensitive(), - is(caseSensitiveFalseValue)); - assertThat( - "new history token should reflect search in target when selected search field is target", - newToken.isProjectSearchInTarget(), is(true)); - assertThat( - "new history token should reflect not to search in source when selected search field is target", - newToken.isProjectSearchInSource(), is(false)); + assertThat(newToken.getProjectSearchText()) + .isEqualTo(TEST_SEARCH_PHRASE) + .as("new history token should be updated with current search phrase in search text box"); + assertThat(newToken.getProjectSearchCaseSensitive()) + .isEqualTo(caseSensitiveFalseValue) + .as("new history token project search case sensitivity should match checkbox value"); + assertThat(newToken.isProjectSearchInTarget()) + .isTrue() + .as("new history token should reflect search in target when selected search field is target"); + assertThat(newToken.isProjectSearchInSource()) + .isFalse() + .as("new history token should reflect not to search in source when selected search field is target"); } @Test @@ -355,10 +352,9 @@ public void searchWithCaseSensitive() { verify(mockHistory).newItem(capturedHistoryToken.capture()); HistoryToken newToken = capturedHistoryToken.getValue(); - assertThat( - "new history token project search case sensitivity should match checkbox value", - newToken.getProjectSearchCaseSensitive(), - is(caseSensitiveTrueValue)); + assertThat(newToken.getProjectSearchCaseSensitive()). + isEqualTo(caseSensitiveTrueValue) + .as("new history token project search case sensitivity should match checkbox value"); } @Test @@ -374,12 +370,10 @@ public void searchInSource() { verify(mockHistory).newItem(capturedHistoryToken.capture()); HistoryToken newToken = capturedHistoryToken.getValue(); - assertThat( - "new history token should reflect search in source when selected search field is source", - newToken.isProjectSearchInSource(), is(true)); - assertThat( - "new history token should reflect not to search in target when selected search field is source", - newToken.isProjectSearchInTarget(), is(false)); + assertThat(newToken.isProjectSearchInSource()).isTrue() + .as("new history token should reflect search in source when selected search field is source"); + assertThat(newToken.isProjectSearchInTarget()).isFalse() + .as("new history token should reflect not to search in target when selected search field is source"); } @Test @@ -396,12 +390,10 @@ public void searchInSourceAndTarget() { verify(mockHistory).newItem(capturedHistoryToken.capture()); HistoryToken newToken = capturedHistoryToken.getValue(); - assertThat( - "new history token should reflect search in source when selected search field is both", - newToken.isProjectSearchInSource(), is(true)); - assertThat( - "new history token should reflect search in target when selected search field is both", - newToken.isProjectSearchInTarget(), is(true)); + assertThat(newToken.isProjectSearchInSource()).isTrue() + .as("new history token should reflect search in source when selected search field is both"); + assertThat(newToken.isProjectSearchInTarget()).isTrue() + .as("new history token should reflect search in target when selected search field is both"); } @Test @@ -420,9 +412,8 @@ public void replacementValueChanged() { verify(mockHistory).newItem(capturedHistoryToken.capture()); HistoryToken newToken = capturedHistoryToken.getValue(); - assertThat( - "new history token should be updated with current replacement phrase", - newToken.getProjectSearchReplacement(), is(TEST_REPLACE_PHRASE)); + assertThat(newToken.getProjectSearchReplacement()).isEqualTo(TEST_REPLACE_PHRASE) + .as("new history token should be updated with current replacement phrase"); } @Ignore @@ -454,8 +445,8 @@ public void firesSearchFromHistoryOneResult() { searchResultsPresenter.bind(); simulateSearch(); - assertThat("text flows for document should be added to data provider", - dataProviderDoc1List.size(), is(1)); + assertThat(dataProviderDoc1List.size()).isEqualTo(1) + .as("text flows for document should be added to data provider"); } // TODO use 4 results in 2 documents diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/SideMenuPresenterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/SideMenuPresenterTest.java index 495dff5ecd..e5ef9c7f86 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/SideMenuPresenterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/SideMenuPresenterTest.java @@ -1,11 +1,10 @@ package org.zanata.webtrans.client.presenter; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.*; import net.customware.gwt.presenter.client.EventBus; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -19,7 +18,6 @@ import org.zanata.webtrans.client.events.PublishWorkspaceChatEvent; import org.zanata.webtrans.client.events.ShowSideMenuEvent; import org.zanata.webtrans.client.events.WorkspaceContextUpdateEvent; -import org.zanata.webtrans.client.resources.WebTransMessages; import org.zanata.webtrans.client.rpc.CachingDispatchAsync; import org.zanata.webtrans.client.service.UserSessionService; import org.zanata.webtrans.client.view.SideMenuDisplay; @@ -199,7 +197,7 @@ public void testOnEditorOptionsClickNotExpanded() throws Exception { // Then: verify(display).setSelectedTab(SideMenuDisplay.OPTION_VIEW); verify(eventBus).fireEvent(eventCaptor.capture()); - assertThat(eventCaptor.getValue().isShowing(), Matchers.equalTo(true)); + assertThat(eventCaptor.getValue().isShowing()).isTrue(); verifyNoMoreInteractions(display); } @@ -239,7 +237,7 @@ public void testOnEditorOptionsClickNotExpanded() throws Exception { // Then: verify(display).getCurrentTab(); verify(eventBus, times(2)).fireEvent(eventCaptor.capture()); - assertThat(eventCaptor.getValue().isShowing(), Matchers.equalTo(false)); + assertThat(eventCaptor.getValue().isShowing()).isFalse(); verifyNoMoreInteractions(display); } @@ -254,7 +252,7 @@ public void testOnNotificationClick() throws Exception { // Then: verify(display).setSelectedTab(SideMenuDisplay.NOTIFICATION_VIEW); verify(eventBus).fireEvent(eventCaptor.capture()); - assertThat(eventCaptor.getValue().isShowing(), Matchers.equalTo(true)); + assertThat(eventCaptor.getValue().isShowing()).isTrue(); verifyNoMoreInteractions(display); } @@ -270,7 +268,7 @@ public void testOnValidationOptionsClick() throws Exception { // Then: verify(display).setSelectedTab(SideMenuDisplay.VALIDATION_OPTION_VIEW); verify(eventBus).fireEvent(eventCaptor.capture()); - assertThat(eventCaptor.getValue().isShowing(), Matchers.equalTo(true)); + assertThat(eventCaptor.getValue().isShowing()).isTrue(); verifyNoMoreInteractions(display); } @@ -286,7 +284,7 @@ public void testOnChatClick() throws Exception { // Then: verify(display).setSelectedTab(SideMenuDisplay.WORKSPACEUSER_VIEW); verify(eventBus).fireEvent(eventCaptor.capture()); - assertThat(eventCaptor.getValue().isShowing(), Matchers.equalTo(true)); + assertThat(eventCaptor.getValue().isShowing()).isTrue(); verifyNoMoreInteractions(display); } @@ -311,7 +309,7 @@ public void showNotificationIfExpanded() { // Given: expanded and current tab is editor options presenter.expendSideMenu(true); verify(eventBus).fireEvent(eventCaptor.capture()); - assertThat(eventCaptor.getValue().isShowing(), Matchers.is(true)); + assertThat(eventCaptor.getValue().isShowing()).isTrue(); when(display.getCurrentTab()).thenReturn(SideMenuDisplay.OPTION_VIEW); // When: diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/SourceContentsPresenterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/SourceContentsPresenterTest.java index 080df95ae4..b505c9d550 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/SourceContentsPresenterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/SourceContentsPresenterTest.java @@ -5,7 +5,6 @@ import com.google.gwtmockito.GwtMock; import com.google.gwtmockito.GwtMockito; -import org.hamcrest.Matchers; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -30,7 +29,8 @@ import com.google.gwt.event.shared.GwtEvent; import net.customware.gwt.presenter.client.EventBus; -import static org.hamcrest.MatcherAssert.*; + +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.*; import org.zanata.webtrans.client.rpc.CachingDispatchAsync; @@ -96,8 +96,7 @@ public void testShowData() throws Exception { verify(display2).setValue(transUnits.get(1)); verify(display2).setSourceSelectionHandler(presenter); - assertThat(presenter.getDisplays(), - Matchers.contains(display1, display2)); + assertThat(presenter.getDisplays()).contains(display1, display2); } @Test @@ -119,8 +118,8 @@ public void testSetSelectedSource() throws Exception { // Then: verify(hasSelectableSource1).clickSelf(); - assertThat(presenter.getCurrentTransUnitIdOrNull(), - Matchers.equalTo(selectedId)); + assertThat(presenter.getCurrentTransUnitIdOrNull()) + .isEqualTo(selectedId); } @Test @@ -151,14 +150,14 @@ public void testOnClick() throws Exception { @Test public void testGetSelectedSource() throws Exception { String noSelectedSource = presenter.getSelectedSource(); - assertThat(noSelectedSource, Matchers.nullValue()); + assertThat(noSelectedSource).isNull(); when(clickEvent.getSource()).thenReturn(hasSelectableSource1); when(hasSelectableSource1.getSource()).thenReturn("source content"); presenter.onClick(clickEvent); String selectedSource = presenter.getSelectedSource(); - assertThat(selectedSource, Matchers.equalTo("source content")); + assertThat(selectedSource).isEqualTo("source content"); } @Test @@ -180,8 +179,8 @@ public void testOnClickOnDifferentRow() throws Exception { // When: select source with id 1 presenter.setSelectedSource(previousSelectedId); - assertThat(presenter.getCurrentTransUnitIdOrNull(), - Matchers.equalTo(previousSelectedId)); + assertThat(presenter.getCurrentTransUnitIdOrNull()) + .isEqualTo(previousSelectedId); // after select source with id 1 click on source panel in display2 when(clickEvent.getSource()).thenReturn(hasSelectableSource2); @@ -196,8 +195,7 @@ public void testOnClickOnDifferentRow() throws Exception { TestFixture.extractFromEvents( gwtEventArgumentCaptor.getAllValues(), TableRowSelectedEvent.class); - assertThat(tableRowSelectedEvent.getSelectedId(), - Matchers.equalTo(selectedId)); + assertThat(tableRowSelectedEvent.getSelectedId()).isEqualTo(selectedId); // on display2 selected it should select the second source panel presenter.setSelectedSource(selectedId); @@ -222,7 +220,7 @@ public void testHighlightSearch() throws Exception { public void withNoPriorSelectionGetCurrentTransUnitIdIsNull() throws Exception { TransUnitId transUnitId = presenter.getCurrentTransUnitIdOrNull(); - assertThat(transUnitId, Matchers.nullValue()); + assertThat(transUnitId).isNull(); } @Test diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TargetContentsPresenterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TargetContentsPresenterTest.java index 9210bec898..0af9eb43b1 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TargetContentsPresenterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TargetContentsPresenterTest.java @@ -28,8 +28,6 @@ import com.google.gwt.event.shared.GwtEvent; import com.google.inject.Provider; import net.customware.gwt.presenter.client.EventBus; -import org.hamcrest.MatcherAssert; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -56,7 +54,6 @@ import org.zanata.webtrans.client.resources.TableEditorMessages; import org.zanata.webtrans.client.resources.ValidationMessages; import org.zanata.webtrans.client.service.UserOptionsService; -import org.zanata.webtrans.client.ui.HasUpdateValidationMessage; import org.zanata.webtrans.client.ui.SaveAsApprovedConfirmationDisplay; import org.zanata.webtrans.client.ui.ToggleEditor; import org.zanata.webtrans.client.ui.UndoLink; @@ -74,8 +71,7 @@ import java.util.List; import java.util.Map; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.atLeast; @@ -188,12 +184,11 @@ public void canValidate() { RunValidationEvent event = TestFixture.extractFromEvents(eventCaptor.getAllValues(), RunValidationEvent.class); - assertThat(event.getSourceContent(), equalTo("source")); - assertThat(event.getTarget(), equalTo("target")); - assertThat(event.isFireNotification(), equalTo(false)); - assertThat(event.getWidgetList(), - Matchers. containsInAnyOrder( - editor, display)); + assertThat(event.getSourceContent()).isEqualTo("source"); + assertThat(event.getTarget()).isEqualTo("target"); + assertThat(event.isFireNotification()).isFalse(); + assertThat(event.getWidgetList()) + .containsExactlyInAnyOrder(editor, display); } @Test @@ -215,9 +210,9 @@ public void canSaveAsFuzzy() { TestFixture.extractFromEvents(eventCaptor.getAllValues(), TransUnitSaveEvent.class); - assertThat(event.getTransUnitId(), equalTo(selectedTU.getId())); - assertThat(event.getTargets(), Matchers.equalTo(NEW_TARGETS)); - assertThat(event.getStatus(), equalTo(ContentState.NeedReview)); + assertThat(event.getTransUnitId()).isEqualTo(selectedTU.getId()); + assertThat(event.getTargets()).isEqualTo(NEW_TARGETS); + assertThat(event.getStatus()).isEqualTo(ContentState.NeedReview); } @Test @@ -244,7 +239,7 @@ public void canGetNewTargets() { List result = presenter.getNewTargets(); - MatcherAssert.assertThat(result, Matchers.sameInstance(NEW_TARGETS)); + assertThat(result).isSameAs(NEW_TARGETS); } @Test @@ -282,7 +277,7 @@ public void onRequestValidationWillFireRunValidationEvent() { RunValidationEvent event = TestFixture.extractFromEvents(eventCaptor.getAllValues(), RunValidationEvent.class); - MatcherAssert.assertThat(event.getTarget(), Matchers.equalTo("target")); + assertThat(event.getTarget()).isEqualTo("target"); } @Test @@ -329,14 +324,12 @@ public void testOnInsertString() { NotificationEvent notificationEvent = TestFixture.extractFromEvents(eventCaptor.getAllValues(), NotificationEvent.class); - MatcherAssert.assertThat(notificationEvent.getMessage(), - Matchers.equalTo("copied")); + assertThat(notificationEvent.getMessage()).isEqualTo("copied"); RunValidationEvent runValidationEvent = TestFixture.extractFromEvents(eventCaptor.getAllValues(), RunValidationEvent.class); - assertThat(runValidationEvent.getSourceContent(), - equalTo("source content")); + assertThat(runValidationEvent.getSourceContent()).isEqualTo("source content"); } @Test @@ -355,8 +348,7 @@ public void testOnTransMemoryCopy() { NotificationEvent notificationEvent = TestFixture.extractFromEvents(eventCaptor.getAllValues(), NotificationEvent.class); - MatcherAssert.assertThat(notificationEvent.getMessage(), - Matchers.equalTo("copied")); + assertThat(notificationEvent.getMessage()).isEqualTo("copied"); } @Test @@ -421,15 +413,15 @@ public void willSaveAndMoveToNextRow() { TransUnitSaveEvent saveEvent = TestFixture.extractFromEvents(eventCaptor.getAllValues(), TransUnitSaveEvent.class); - assertThat(saveEvent.getTransUnitId(), equalTo(selectedTU.getId())); - assertThat(saveEvent.getTargets(), Matchers.equalTo(NEW_TARGETS)); - assertThat(saveEvent.getStatus(), equalTo(ContentState.Translated)); + assertThat(saveEvent.getTransUnitId()).isEqualTo(selectedTU.getId()); + assertThat(saveEvent.getTargets()).isEqualTo(NEW_TARGETS); + assertThat(saveEvent.getStatus()).isEqualTo(ContentState.Translated); NavTransUnitEvent navEvent = TestFixture.extractFromEvents(eventCaptor.getAllValues(), NavTransUnitEvent.class); - assertThat(navEvent.getRowType(), - equalTo(NavTransUnitEvent.NavigationType.NextEntry)); + assertThat(navEvent.getRowType()) + .isEqualTo(NavTransUnitEvent.NavigationType.NextEntry); } @Test @@ -486,7 +478,7 @@ public void canGetCurrentTransUnitId() { presenter.setStatesForTesting(selectedTU.getId(), 0, display); TransUnitId result = presenter.getCurrentTransUnitIdOrNull(); - assertThat(result, Matchers.sameInstance(selectedTU.getId())); + assertThat(result).isSameAs(selectedTU.getId()); } @Test @@ -495,13 +487,12 @@ public void testIsReadOnly() { boolean readOnly = presenter.isReadOnly(); - assertThat(readOnly, Matchers.is(true)); + assertThat(readOnly).isTrue(); } @Test public void canGetConfigState() { - assertThat(presenter.getConfigState(), - Matchers.equalTo(configHolder.getState())); + assertThat(presenter.getConfigState()).isEqualTo(configHolder.getState()); } @Test @@ -511,7 +502,7 @@ public void testIsDisplayButtons() { boolean displayButtons = presenter.isDisplayButtons(); - assertThat(displayButtons, Matchers.is(false)); + assertThat(displayButtons).isFalse(); } @Test @@ -526,8 +517,7 @@ public void testOnFocus() { TableRowSelectedEvent tableRowSelectedEvent = TestFixture.extractFromEvents(eventCaptor.getAllValues(), TableRowSelectedEvent.class); - assertThat(tableRowSelectedEvent.getSelectedId(), - Matchers.equalTo(selectedTU.getId())); + assertThat(tableRowSelectedEvent.getSelectedId()).isEqualTo(selectedTU.getId()); } @Test @@ -575,7 +565,7 @@ public void testConcealDisplay() { public void canGetDisplays() { List displays = presenter.getDisplays(); - assertThat(displays, Matchers.contains(display, display, display)); + assertThat(displays).contains(display, display, display); } @Test @@ -910,7 +900,7 @@ public void rejectTranslationWillForceComment() { CommentBeforeSaveEvent commentBeforeSaveEvent = extractFromEvents(eventCaptor.getAllValues(), CommentBeforeSaveEvent.class); - assertThat(commentBeforeSaveEvent.getSaveEvent().getStatus(), - Matchers.equalTo(ContentState.Rejected)); + assertThat(commentBeforeSaveEvent.getSaveEvent().getStatus()) + .isEqualTo(ContentState.Rejected); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransFilterPresenterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransFilterPresenterTest.java index c65772849e..2c1eab0ec9 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransFilterPresenterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransFilterPresenterTest.java @@ -1,11 +1,10 @@ package org.zanata.webtrans.client.presenter; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import net.customware.gwt.presenter.client.EventBus; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; @@ -71,7 +70,7 @@ public void testSearchTerm() throws Exception { presenter.searchTerm("blah"); - assertThat(historyToken.getEditorTextSearch(), Matchers.equalTo("blah")); + assertThat(historyToken.getEditorTextSearch()).isEqualTo("blah"); verify(history).newItem(historyToken); } @@ -102,18 +101,18 @@ public void willSetOptionsBackOnFilterViewCancelEvent() { verify(display).setApprovedFilter(event.isFilterApproved()); verify(display).setRejectedFilter(event.isFilterRejected()); - assertThat(historyToken.isFilterUntranslated(), - Matchers.equalTo(event.isFilterUntranslated())); - assertThat(historyToken.isFilterTranslated(), - Matchers.equalTo(event.isFilterTranslated())); - assertThat(historyToken.isFilterFuzzy(), - Matchers.equalTo(event.isFilterFuzzy())); - assertThat(historyToken.isFilterApproved(), - Matchers.equalTo(event.isFilterApproved())); - assertThat(historyToken.isFilterRejected(), - Matchers.equalTo(event.isFilterRejected())); - assertThat(historyToken.isFilterHasError(), - Matchers.equalTo(event.isFilterHasError())); + assertThat(historyToken.isFilterUntranslated()) + .isEqualTo(event.isFilterUntranslated()); + assertThat(historyToken.isFilterTranslated()) + .isEqualTo(event.isFilterTranslated()); + assertThat(historyToken.isFilterFuzzy()) + .isEqualTo(event.isFilterFuzzy()); + assertThat(historyToken.isFilterApproved()) + .isEqualTo(event.isFilterApproved()); + assertThat(historyToken.isFilterRejected()) + .isEqualTo(event.isFilterRejected()); + assertThat(historyToken.isFilterHasError()) + .isEqualTo(event.isFilterHasError()); } @Test @@ -156,19 +155,19 @@ public void onUserConfigChange() { configHolder.getState().isFilterByHasError()); assertThat( - historyToken.isFilterTranslated(), - Matchers.equalTo(configHolder.getState().isFilterByTranslated())); - assertThat(historyToken.isFilterFuzzy(), - Matchers.equalTo(configHolder.getState().isFilterByFuzzy())); - assertThat(historyToken.isFilterUntranslated(), - Matchers.equalTo(configHolder.getState() - .isFilterByUntranslated())); - assertThat(historyToken.isFilterApproved(), - Matchers.equalTo(configHolder.getState().isFilterByApproved())); - assertThat(historyToken.isFilterRejected(), - Matchers.equalTo(configHolder.getState().isFilterByRejected())); - assertThat(historyToken.isFilterHasError(), - Matchers.equalTo(configHolder.getState().isFilterByHasError())); + historyToken.isFilterTranslated()) + .isEqualTo(configHolder.getState().isFilterByTranslated()); + assertThat(historyToken.isFilterFuzzy()) + .isEqualTo(configHolder.getState().isFilterByFuzzy()); + assertThat(historyToken.isFilterUntranslated()) + .isEqualTo(configHolder.getState() + .isFilterByUntranslated()); + assertThat(historyToken.isFilterApproved()) + .isEqualTo(configHolder.getState().isFilterByApproved()); + assertThat(historyToken.isFilterRejected()) + .isEqualTo(configHolder.getState().isFilterByRejected()); + assertThat(historyToken.isFilterHasError()) + .isEqualTo(configHolder.getState().isFilterByHasError()); } @Test @@ -180,24 +179,18 @@ public void onMessageFilterOptionChanged() { false); UserConfigHolder configHolder = userOptionsService.getConfigHolder(); - assertThat(configHolder.getState().isFilterByTranslated(), - Matchers.equalTo(true)); - assertThat(configHolder.getState().isFilterByFuzzy(), - Matchers.equalTo(false)); - assertThat(configHolder.getState().isFilterByUntranslated(), - Matchers.equalTo(true)); - assertThat(configHolder.getState().isFilterByApproved(), - Matchers.equalTo(true)); - assertThat(configHolder.getState().isFilterByRejected(), - Matchers.equalTo(false)); - assertThat(configHolder.getState().isFilterByHasError(), - Matchers.equalTo(false)); - assertThat(historyToken.isFilterTranslated(), Matchers.equalTo(true)); - assertThat(historyToken.isFilterFuzzy(), Matchers.equalTo(false)); - assertThat(historyToken.isFilterUntranslated(), Matchers.equalTo(true)); - assertThat(historyToken.isFilterApproved(), Matchers.equalTo(true)); - assertThat(historyToken.isFilterRejected(), Matchers.equalTo(false)); - assertThat(historyToken.isFilterHasError(), Matchers.equalTo(false)); + assertThat(configHolder.getState().isFilterByTranslated()).isTrue(); + assertThat(configHolder.getState().isFilterByFuzzy()).isFalse(); + assertThat(configHolder.getState().isFilterByUntranslated()).isTrue(); + assertThat(configHolder.getState().isFilterByApproved()).isTrue(); + assertThat(configHolder.getState().isFilterByRejected()).isFalse(); + assertThat(configHolder.getState().isFilterByHasError()).isFalse(); + assertThat(historyToken.isFilterTranslated()).isTrue(); + assertThat(historyToken.isFilterFuzzy()).isFalse(); + assertThat(historyToken.isFilterUntranslated()).isTrue(); + assertThat(historyToken.isFilterApproved()).isTrue(); + assertThat(historyToken.isFilterRejected()).isFalse(); + assertThat(historyToken.isFilterHasError()).isFalse(); verify(history).newItem(historyToken); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransMemoryDetailsPresenterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransMemoryDetailsPresenterTest.java index 19e3fca6d0..5e23f54786 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransMemoryDetailsPresenterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransMemoryDetailsPresenterTest.java @@ -3,7 +3,6 @@ import java.util.ArrayList; import java.util.Date; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -24,7 +23,8 @@ import com.google.common.collect.Lists; import net.customware.gwt.presenter.client.EventBus; -import static org.hamcrest.MatcherAssert.*; + +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -68,8 +68,8 @@ public void testShow() throws Exception { verify(dispatcher).execute(actionCaptor.capture(), resultCaptor.capture()); - assertThat(actionCaptor.getValue().getTransUnitIdList(), - Matchers.equalTo(sourceIds)); + assertThat(actionCaptor.getValue().getTransUnitIdList()) + .isEqualTo(sourceIds); AbstractAsyncCallback callback = resultCaptor.getValue(); diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransMemoryPresenterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransMemoryPresenterTest.java index e634db8928..4ee9d1655f 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransMemoryPresenterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransMemoryPresenterTest.java @@ -1,7 +1,6 @@ package org.zanata.webtrans.client.presenter; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.greaterThan; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.*; import static org.zanata.webtrans.shared.model.TransMemoryResultItem.MatchType; @@ -13,7 +12,6 @@ import net.customware.gwt.presenter.client.EventBus; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -301,11 +299,10 @@ public void canFireSearchEvent() { callbackCaptor.capture()); // verify action GetTranslationMemory action = getTMActionCaptor.getValue(); - assertThat(action.getSearchType(), Matchers.equalTo(SearchType.FUZZY)); - assertThat(action.getLocaleId(), Matchers.equalTo(targetLocale)); - assertThat(action.getSourceLocaleId(), Matchers.equalTo(sourceLocale)); - assertThat(action.getQuery().getQueries(), - Matchers.contains("search query")); + assertThat(action.getSearchType()).isEqualTo(SearchType.FUZZY); + assertThat(action.getLocaleId()).isEqualTo(targetLocale); + assertThat(action.getSourceLocaleId()).isEqualTo(sourceLocale); + assertThat(action.getQuery().getQueries()).contains("search query"); } @Test @@ -447,8 +444,8 @@ public void testOnTransMemoryCopy() { presenter.onTransMemoryCopy(new TransMemoryShortcutCopyEvent(0)); verify(eventBus).fireEvent(copyTMEventCaptor.capture()); - assertThat(copyTMEventCaptor.getValue().getTargetResult(), - Matchers.equalTo(targetContents)); + assertThat(copyTMEventCaptor.getValue().getTargetResult()) + .isEqualTo(targetContents); } @Test @@ -462,7 +459,7 @@ public void onClearContent() { verify(tMTextBox).setText(""); verify(display).clearTableContent(); - assertThat(currentResult, Matchers. empty()); + assertThat(currentResult).isEmpty(); } @Test @@ -517,9 +514,9 @@ public void ignoreIfNotEditorConfigOptionChange() { */ @Test public void matchTypeEnumOrder() throws Exception { - assertThat(MatchType.ApprovedInternal, - greaterThan(MatchType.TranslatedInternal)); - assertThat(MatchType.TranslatedInternal, - greaterThan(MatchType.Imported)); + assertThat(MatchType.ApprovedInternal) + .isGreaterThan(MatchType.TranslatedInternal); + assertThat(MatchType.TranslatedInternal) + .isGreaterThan(MatchType.Imported); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransUnitNavigationPresenterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransUnitNavigationPresenterTest.java index 2f318a8a18..393a24ee02 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransUnitNavigationPresenterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransUnitNavigationPresenterTest.java @@ -1,6 +1,6 @@ package org.zanata.webtrans.client.presenter; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; import static org.zanata.webtrans.client.events.NavTransUnitEvent.NavigationType.FirstEntry; import static org.zanata.webtrans.client.events.NavTransUnitEvent.NavigationType.LastEntry; @@ -8,7 +8,6 @@ import static org.zanata.webtrans.client.events.NavTransUnitEvent.NavigationType.PrevState; import net.customware.gwt.presenter.client.EventBus; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -70,8 +69,7 @@ public void onGoToFirstEntry() { verify(targetContentsPresenter).savePendingChangesIfApplicable(); verify(eventBus).fireEvent(eventCaptor.capture()); - assertThat(eventCaptor.getValue().getRowType(), - Matchers.equalTo(FirstEntry)); + assertThat(eventCaptor.getValue().getRowType()).isEqualTo(FirstEntry); } @Test @@ -80,8 +78,7 @@ public void onGoToLastEntry() { verify(targetContentsPresenter).savePendingChangesIfApplicable(); verify(eventBus).fireEvent(eventCaptor.capture()); - assertThat(eventCaptor.getValue().getRowType(), - Matchers.equalTo(LastEntry)); + assertThat(eventCaptor.getValue().getRowType()).isEqualTo(LastEntry); } @Test @@ -90,8 +87,7 @@ public void onGoToPreviousState() { verify(targetContentsPresenter).savePendingChangesIfApplicable(); verify(eventBus).fireEvent(eventCaptor.capture()); - assertThat(eventCaptor.getValue().getRowType(), - Matchers.equalTo(PrevState)); + assertThat(eventCaptor.getValue().getRowType()).isEqualTo(PrevState); } @Test @@ -100,7 +96,6 @@ public void onGoToNextState() { verify(targetContentsPresenter).savePendingChangesIfApplicable(); verify(eventBus).fireEvent(eventCaptor.capture()); - assertThat(eventCaptor.getValue().getRowType(), - Matchers.equalTo(NextState)); + assertThat(eventCaptor.getValue().getRowType()).isEqualTo(NextState); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransUnitReplaceInfoTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransUnitReplaceInfoTest.java index 3428f406d6..76d3a81e45 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransUnitReplaceInfoTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransUnitReplaceInfoTest.java @@ -2,7 +2,6 @@ import java.util.Comparator; -import org.hamcrest.Matchers; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -11,7 +10,7 @@ import org.zanata.webtrans.shared.model.TransUnitUpdateInfo; import org.zanata.webtrans.shared.model.TransUnitUpdatePreview; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; /** * @author Patrick Huang sameComparator = TransUnitReplaceInfo.getRowComparator(); - assertThat(comparator, Matchers.sameInstance(sameComparator)); + assertThat(comparator).isSameAs(sameComparator); } @Test @@ -44,17 +43,17 @@ public void rowComparatorComparesOnRowIndex() { Comparator comparator = TransUnitReplaceInfo.getRowComparator(); - assertThat(comparator.compare(null, null), Matchers.equalTo(0)); - assertThat(comparator.compare(null, newReplaceInfo(1)), - Matchers.equalTo(-1)); - assertThat(comparator.compare(newReplaceInfo(1), null), - Matchers.equalTo(1)); - assertThat(comparator.compare(newReplaceInfo(1), newReplaceInfo(1)), - Matchers.equalTo(0)); - assertThat(comparator.compare(newReplaceInfo(1), newReplaceInfo(2)), - Matchers.equalTo(-1)); - assertThat(comparator.compare(newReplaceInfo(2), newReplaceInfo(1)), - Matchers.equalTo(1)); + assertThat(comparator.compare(null, null)).isEqualTo(0); + assertThat(comparator.compare(null, newReplaceInfo(1))) + .isEqualTo(-1); + assertThat(comparator.compare(newReplaceInfo(1), null)) + .isEqualTo(1); + assertThat(comparator.compare(newReplaceInfo(1), newReplaceInfo(1))) + .isEqualTo(0); + assertThat(comparator.compare(newReplaceInfo(1), newReplaceInfo(2))) + .isEqualTo(-1); + assertThat(comparator.compare(newReplaceInfo(2), newReplaceInfo(1))) + .isEqualTo(1); } @Test @@ -65,14 +64,12 @@ public void testSetterAndGetter() { new TransUnitReplaceInfo(CONTAINING_DOC_ID, transUnit); // init state - assertThat(info.getDocId(), Matchers.equalTo(CONTAINING_DOC_ID)); - assertThat(info.getPreview(), Matchers.nullValue()); - assertThat(info.getPreviewState(), - Matchers.equalTo(PreviewState.NotFetched)); - assertThat(info.getReplaceInfo(), Matchers.nullValue()); - assertThat(info.getReplaceState(), - Matchers.equalTo(ReplacementState.NotReplaced)); - assertThat(info.getTransUnit(), Matchers.sameInstance(transUnit)); + assertThat(info.getDocId()).isEqualTo(CONTAINING_DOC_ID); + assertThat(info.getPreview()).isNull(); + assertThat(info.getPreviewState()).isEqualTo(PreviewState.NotFetched); + assertThat(info.getReplaceInfo()).isNull(); + assertThat(info.getReplaceState()).isEqualTo(ReplacementState.NotReplaced); + assertThat(info.getTransUnit()).isSameAs(transUnit); // update state info.setPreview(updatePreview); @@ -82,11 +79,10 @@ public void testSetterAndGetter() { TransUnit newTU = TestFixture.makeTransUnit(2); info.setTransUnit(newTU); - assertThat(info.getPreview(), Matchers.sameInstance(updatePreview)); - assertThat(info.getPreviewState(), Matchers.equalTo(PreviewState.Show)); - assertThat(info.getReplaceInfo(), Matchers.sameInstance(updateInfo)); - assertThat(info.getReplaceState(), - Matchers.equalTo(ReplacementState.Replaced)); - assertThat(info.getTransUnit(), Matchers.sameInstance(newTU)); + assertThat(info.getPreview()).isSameAs(updatePreview); + assertThat(info.getPreviewState()).isEqualTo(PreviewState.Show); + assertThat(info.getReplaceInfo()).isSameAs(updateInfo); + assertThat(info.getReplaceState()).isSameAs(ReplacementState.Replaced); + assertThat(info.getTransUnit()).isSameAs(newTU); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransUnitsTablePresenterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransUnitsTablePresenterTest.java index 2fce0f982a..5a57be76a7 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransUnitsTablePresenterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TransUnitsTablePresenterTest.java @@ -1,6 +1,6 @@ package org.zanata.webtrans.client.presenter; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @@ -17,7 +17,6 @@ import net.customware.gwt.presenter.client.EventBus; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -224,8 +223,7 @@ public void onCancelFilter() { ArgumentCaptor filterViewEventCaptor = ArgumentCaptor.forClass(FilterViewEvent.class); verify(eventBus).fireEvent(filterViewEventCaptor.capture()); - assertThat(filterViewEventCaptor.getValue().isCancelFilter(), - Matchers.equalTo(true)); + assertThat(filterViewEventCaptor.getValue().isCancelFilter()).isTrue(); verify(display).hideFilterConfirmation(); } @@ -331,8 +329,8 @@ public void willRefreshRowFromCurrentUserNotAsEditorSave() { ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(NotificationEvent.class); verify(eventBus).fireEvent(eventCaptor.capture()); - assertThat(eventCaptor.getValue().getMessage(), - Matchers.equalTo("concurrent edit detected")); + assertThat(eventCaptor.getValue().getMessage()) + .isEqualTo("concurrent edit detected"); verify(targetContentsPresenter).currentEditorContentHasChanged(); verify(targetContentsPresenter).updateRow(updatedTransUnit); verifyNoMoreInteractions(targetContentsPresenter); @@ -363,8 +361,8 @@ public void willDetectSaveDoneByAnotherUserAndCurrentUserHasUnsavedChange() { ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(NotificationEvent.class); verify(eventBus).fireEvent(eventCaptor.capture()); - assertThat(eventCaptor.getValue().getMessage(), - Matchers.equalTo("concurrent edit detected")); + assertThat(eventCaptor.getValue().getMessage()) + .isEqualTo("concurrent edit detected"); ArgumentCaptor transHistoryCaptor = ArgumentCaptor.forClass(TransHistoryItem.class); @@ -377,10 +375,10 @@ public void willDetectSaveDoneByAnotherUserAndCurrentUserHasUnsavedChange() { transHistoryCaptor.capture(), eq(Collections. emptyList()), eq(Collections. emptyList())); - assertThat(transHistoryCaptor.getValue().getVersionNum(), - Matchers.equalTo(updatedTransUnit.getVerNum().toString())); - assertThat(transHistoryCaptor.getValue().getContents(), - Matchers.equalTo(updatedTransUnit.getTargets())); + assertThat(transHistoryCaptor.getValue().getVersionNum()) + .isEqualTo(updatedTransUnit.getVerNum().toString()); + assertThat(transHistoryCaptor.getValue().getContents()) + .isEqualTo(updatedTransUnit.getTargets()); inOrder.verify(targetContentsPresenter).updateRow(updatedTransUnit); } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TranslationHistoryPresenterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TranslationHistoryPresenterTest.java index 48cde2dd0b..782d99d620 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TranslationHistoryPresenterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TranslationHistoryPresenterTest.java @@ -3,7 +3,6 @@ import java.util.Date; import java.util.List; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.Answers; @@ -38,7 +37,8 @@ import com.google.gwt.user.client.rpc.AsyncCallback; import net.customware.gwt.presenter.client.EventBus; -import static org.hamcrest.MatcherAssert.assertThat; + +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; @@ -111,8 +111,8 @@ public void willNotifyErrorAndHideTranslationHistoryOnFailure() { verify(display).setTitle("translation history"); verify(display).resetView(); verify(display).center(); - assertThat(actionCaptor.getValue().getTransUnitId(), - Matchers.equalTo(transUnitId)); + assertThat(actionCaptor.getValue().getTransUnitId()) + .isEqualTo(transUnitId); // And on failure AsyncCallback result = @@ -169,7 +169,7 @@ public void willShowTranslationHistoryWithUnsavedValueOnSuccess() { resultCaptor.getValue(); result.onSuccess(createTranslationHistory(latest, historyItem)); verify(display).setData(listArgumentCaptor.capture()); - assertThat(listArgumentCaptor.getValue(), Matchers.hasSize(3)); + assertThat(listArgumentCaptor.getValue()).hasSize(3); } private static GetTranslationHistoryResult createTranslationHistory( @@ -189,8 +189,8 @@ public void canCopyIntoEditor() { ArgumentCaptor.forClass(CopyDataToEditorEvent.class); verify(eventBus).fireEvent(eventCaptor.capture()); - assertThat(eventCaptor.getValue().getTargetResult(), - Matchers.equalTo(contents)); + assertThat(eventCaptor.getValue().getTargetResult()) + .isEqualTo(contents); } @Test @@ -201,8 +201,8 @@ public void testAddComment() throws Exception { verify(dispatcher).execute(addReviewCommentActionArgumentCaptor.capture(), addReviewCommentResultCaptor.capture()); - assertThat(addReviewCommentActionArgumentCaptor.getValue().getContent(), - Matchers.equalTo("some comment")); + assertThat(addReviewCommentActionArgumentCaptor.getValue().getContent()) + .isEqualTo("some comment"); AsyncCallback callback = addReviewCommentResultCaptor.getValue(); @@ -236,8 +236,7 @@ public void canDisplayEntriesInOrder() { verify(display).setData(listArgumentCaptor.capture()); List result = listArgumentCaptor.getValue(); - assertThat(result, - Matchers. contains(comment, latest, item)); + assertThat(result).contains(comment, latest, item); } @Test @@ -268,8 +267,8 @@ public void testKeyShortcutForAddComment() { when(display.getComment()).thenReturn("blah"); KeyShortcut keyShortcut = keyShortcutCapture.getValue(); - assertThat(keyShortcut.getAllKeys().iterator().next(), - Matchers.equalTo(new Keys(Keys.CTRL_KEY, KeyCodes.KEY_ENTER))); + assertThat(keyShortcut.getAllKeys().iterator().next()) + .isEqualTo(new Keys(Keys.CTRL_KEY, KeyCodes.KEY_ENTER)); keyShortcut.getHandler().onKeyShortcut(mock(KeyShortcutEvent.class)); verify(display).getComment(); diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TranslationPresenterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TranslationPresenterTest.java index 46ffb75adb..31e637ba87 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TranslationPresenterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TranslationPresenterTest.java @@ -1,6 +1,6 @@ package org.zanata.webtrans.client.presenter; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doNothing; @@ -15,7 +15,6 @@ import net.customware.gwt.presenter.client.EventBus; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -129,31 +128,25 @@ public void testKeyShortcuts() { // test keys KeyShortcut prevKey = shortcuts.get(0); - assertThat(prevKey.getAllKeys(), Matchers.equalTo(Keys.setOf(new Keys( - Keys.ALT_KEY, KeyCodes.KEY_UP), new Keys(Keys.ALT_KEY, 'J')))); - assertThat(prevKey.getDescription(), Matchers.equalTo("previous row")); - assertThat(prevKey.getContext(), - Matchers.equalTo(ShortcutContext.Navigation)); - assertThat(prevKey.getKeyEvent(), - Matchers.equalTo(KeyShortcut.KeyEvent.KEY_DOWN)); + assertThat(prevKey.getAllKeys()).isEqualTo(Keys.setOf(new Keys( + Keys.ALT_KEY, KeyCodes.KEY_UP), new Keys(Keys.ALT_KEY, 'J'))); + assertThat(prevKey.getDescription()).isEqualTo("previous row"); + assertThat(prevKey.getContext()).isEqualTo(ShortcutContext.Navigation); + assertThat(prevKey.getKeyEvent()).isEqualTo(KeyShortcut.KeyEvent.KEY_DOWN); KeyShortcut nextKey = shortcuts.get(1); - assertThat(nextKey.getAllKeys(), Matchers.equalTo(Keys.setOf(new Keys( - Keys.ALT_KEY, KeyCodes.KEY_DOWN), new Keys(Keys.ALT_KEY, 'K')))); - assertThat(nextKey.getDescription(), Matchers.equalTo("next row")); - assertThat(nextKey.getContext(), - Matchers.equalTo(ShortcutContext.Navigation)); - assertThat(nextKey.getKeyEvent(), - Matchers.equalTo(KeyShortcut.KeyEvent.KEY_DOWN)); + assertThat(nextKey.getAllKeys()).isEqualTo(Keys.setOf(new Keys( + Keys.ALT_KEY, KeyCodes.KEY_DOWN), new Keys(Keys.ALT_KEY, 'K'))); + assertThat(nextKey.getDescription()).isEqualTo("next row"); + assertThat(nextKey.getContext()).isEqualTo(ShortcutContext.Navigation); + assertThat(nextKey.getKeyEvent()).isEqualTo(KeyShortcut.KeyEvent.KEY_DOWN); KeyShortcut enterKey = shortcuts.get(2); - assertThat(enterKey.getAllKeys(), Matchers.contains(new Keys( - Keys.NO_MODIFIER, KeyCodes.KEY_ENTER))); - assertThat(enterKey.getDescription(), Matchers.equalTo("open editor")); - assertThat(enterKey.getContext(), - Matchers.equalTo(ShortcutContext.Navigation)); - assertThat(enterKey.getKeyEvent(), - Matchers.equalTo(KeyShortcut.KeyEvent.KEY_UP)); + assertThat(enterKey.getAllKeys()).contains(new Keys( + Keys.NO_MODIFIER, KeyCodes.KEY_ENTER)); + assertThat(enterKey.getDescription()).isEqualTo("open editor"); + assertThat(enterKey.getContext()).isEqualTo(ShortcutContext.Navigation); + assertThat(enterKey.getKeyEvent()).isEqualTo(KeyShortcut.KeyEvent.KEY_UP); // test key handlers prevKey.getHandler().onKeyShortcut(null); @@ -236,7 +229,7 @@ public void onWorkspaceContextUpdate() { when(event.isProjectActive()).thenReturn(false); presenter.onWorkspaceContextUpdated(event); - assertThat(userWorkspaceContext.hasReadOnlyAccess(), Matchers.is(true)); + assertThat(userWorkspaceContext.hasReadOnlyAccess()).isTrue(); verify(transMemoryPresenter).unbind(); verify(glossaryPresenter).unbind(); } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/UserConfigHolderTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/UserConfigHolderTest.java index 68a9a7a99b..8a2266a2b1 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/UserConfigHolderTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/UserConfigHolderTest.java @@ -20,18 +20,18 @@ */ package org.zanata.webtrans.client.presenter; -import static org.hamcrest.MatcherAssert.assertThat; import java.lang.reflect.InvocationTargetException; import java.util.Map; import java.util.Random; import org.apache.commons.beanutils.BeanUtils; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.zanata.webtrans.shared.rpc.NavOption; +import static org.assertj.core.api.Assertions.assertThat; + public class UserConfigHolderTest { private UserConfigHolder configHolder; @@ -46,11 +46,10 @@ public void testDefaultValues() throws Exception { Map propertiesMap = getPropertiesMap(); - assertThat(propertiesMap, - Matchers.hasEntry("enterSavesApproved", "false")); - assertThat(propertiesMap, Matchers.hasEntry("displayButtons", "true")); - assertThat(propertiesMap, Matchers.hasEntry("editorPageSize", "25")); - assertThat(propertiesMap, Matchers.hasEntry("showError", "false")); + assertThat(propertiesMap).containsEntry("enterSavesApproved", "false"); + assertThat(propertiesMap).containsEntry("displayButtons", "true"); + assertThat(propertiesMap).containsEntry("editorPageSize", "25"); + assertThat(propertiesMap).containsEntry("showError", "false"); } @SuppressWarnings("unchecked") @@ -69,26 +68,24 @@ public void randomSetterAndGetter() throws Exception { configHolder.setDisplayButtons(value); configHolder.setShowError(value); - assertThat(configHolder.getState().isEnterSavesApproved(), - Matchers.equalTo(value)); - assertThat(configHolder.getState().isDisplayButtons(), - Matchers.equalTo(value)); - assertThat(configHolder.getState().isShowError(), - Matchers.equalTo(value)); + assertThat(configHolder.getState().isEnterSavesApproved()) + .isEqualTo(value); + assertThat(configHolder.getState().isDisplayButtons()).isEqualTo(value); + assertThat(configHolder.getState().isShowError()).isEqualTo(value); } @Test public void canGetPredicateBasedOnNavOption() { configHolder.setNavOption(NavOption.FUZZY_UNTRANSLATED); - assertThat(configHolder.getContentStatePredicate(), - Matchers.is(UserConfigHolder.INCOMPLETE_PREDICATE)); + assertThat(configHolder.getContentStatePredicate()) + .isEqualTo(UserConfigHolder.INCOMPLETE_PREDICATE); configHolder.setNavOption(NavOption.FUZZY); - assertThat(configHolder.getContentStatePredicate(), - Matchers.is(UserConfigHolder.DRAFT_PREDICATE)); + assertThat(configHolder.getContentStatePredicate()) + .isEqualTo(UserConfigHolder.DRAFT_PREDICATE); configHolder.setNavOption(NavOption.UNTRANSLATED); - assertThat(configHolder.getContentStatePredicate(), - Matchers.is(UserConfigHolder.NEW_PREDICATE)); + assertThat(configHolder.getContentStatePredicate()) + .isEqualTo(UserConfigHolder.NEW_PREDICATE); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/WorkspaceUsersPresenterTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/WorkspaceUsersPresenterTest.java index 64f4b479bf..8a043f387d 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/WorkspaceUsersPresenterTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/WorkspaceUsersPresenterTest.java @@ -1,7 +1,5 @@ package org.zanata.webtrans.client.presenter; -import com.google.gwt.user.client.rpc.AsyncCallback; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -22,14 +20,13 @@ import org.zanata.webtrans.client.view.WorkspaceUsersDisplay; import org.zanata.webtrans.shared.auth.Identity; import org.zanata.webtrans.shared.model.Person; -import org.zanata.webtrans.shared.model.UserPanelSessionItem; import org.zanata.webtrans.shared.rpc.HasWorkspaceChatData; -import org.zanata.webtrans.shared.rpc.NoOpResult; import org.zanata.webtrans.shared.rpc.PublishWorkspaceChatAction; import com.google.gwt.event.dom.client.KeyCodes; import net.customware.gwt.presenter.client.EventBus; -import static org.hamcrest.MatcherAssert.assertThat; + +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.spy; @@ -98,14 +95,12 @@ public void testKeyShortcut() { // key is 'enter', context is Chat, description is publish chat KeyShortcut keyShortcut = keyShortcutCaptor.getValue(); - assertThat(keyShortcut.getAllKeys(), Matchers.hasSize(1)); + assertThat(keyShortcut.getAllKeys()).hasSize(1); Keys keys = keyShortcut.getAllKeys().iterator().next(); - assertThat(keys.getModifiers(), Matchers.equalTo(Keys.NO_MODIFIER)); - assertThat(keys.getKeyCode(), Matchers.equalTo(KeyCodes.KEY_ENTER)); - assertThat(keyShortcut.getDescription(), - Matchers.equalTo("publish chat")); - assertThat(keyShortcut.getContext(), - Matchers.equalTo(ShortcutContext.Chat)); + assertThat(keys.getModifiers()).isEqualTo(Keys.NO_MODIFIER); + assertThat(keys.getKeyCode()).isEqualTo(KeyCodes.KEY_ENTER); + assertThat(keyShortcut.getDescription()).isEqualTo("publish chat"); + assertThat(keyShortcut.getContext()).isEqualTo(ShortcutContext.Chat); // key handler when(identity.getPerson()).thenReturn(person); @@ -132,11 +127,10 @@ public void onSendButtonClicked() { verify(dispatcher).execute(actionCaptor.capture(), isA(NoOpAsyncCallback.class)); PublishWorkspaceChatAction chatAction = actionCaptor.getValue(); - assertThat(chatAction.getPerson(), - Matchers.equalTo(person.getId().toString())); - assertThat(chatAction.getMsg(), Matchers.equalTo("hello")); - assertThat(chatAction.getMessageType(), - Matchers.equalTo(HasWorkspaceChatData.MESSAGE_TYPE.USER_MSG)); + assertThat(chatAction.getPerson()).isEqualTo(person.getId().toString()); + assertThat(chatAction.getMsg()).isEqualTo("hello"); + assertThat(chatAction.getMessageType()) + .isEqualTo(HasWorkspaceChatData.MESSAGE_TYPE.USER_MSG); verify(display).setChatInputText(""); } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/DistinctColorListImplTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/DistinctColorListImplTest.java index d7f9438f4f..f1bfadda68 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/DistinctColorListImplTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/DistinctColorListImplTest.java @@ -1,13 +1,11 @@ package org.zanata.webtrans.client.service; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; -import org.zanata.webtrans.client.service.DistinctColorListImpl; import org.zanata.webtrans.shared.auth.EditorClientId; import com.google.common.collect.Lists; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; /** * @author Patrick Huang getPageDataModelAsIds() { @@ -252,8 +249,8 @@ public void canGoToLastPageWithNotPerfectDivide() { verifyDispatcherAndCallOnSuccess(); service.gotoPage(1); verifyDispatcherAndCallOnSuccess(); - assertThat(getPageDataModelAsIds(), contains(4, 5)); - assertThat(navigationStateHolder.getCurrentPage(), is(1)); + assertThat(getPageDataModelAsIds()).contains(4, 5); + assertThat(navigationStateHolder.getCurrentPage()).isEqualTo(1); service.gotoPage(1); verifyNoMoreInteractions(dispatcher); } @@ -264,12 +261,12 @@ public void canGoToLastPageWithPerfectDivide() { verifyDispatcherAndCallOnSuccess(); service.gotoPage(1); verifyDispatcherAndCallOnSuccess(); - assertThat(getPageDataModelAsIds(), contains(3, 4, 5)); - assertThat(navigationStateHolder.getCurrentPage(), is(1)); + assertThat(getPageDataModelAsIds()).contains(3, 4, 5); + assertThat(navigationStateHolder.getCurrentPage()).isEqualTo(1); service.gotoPage(1); verifyNoMoreInteractions(dispatcher); - assertThat(getPageDataModelAsIds(), contains(3, 4, 5)); - assertThat(navigationStateHolder.getCurrentPage(), is(1)); + assertThat(getPageDataModelAsIds()).contains(3, 4, 5); + assertThat(navigationStateHolder.getCurrentPage()).isEqualTo(1); } @Test @@ -278,12 +275,12 @@ public void canHavePageCountGreaterThanActualSize() { verifyDispatcherAndCallOnSuccess(); service.gotoPage(100); verifyDispatcherAndCallOnSuccess(); - assertThat(getPageDataModelAsIds(), contains(0, 1, 2, 3, 4, 5)); - assertThat(navigationStateHolder.getCurrentPage(), is(0)); + assertThat(getPageDataModelAsIds()).contains(0, 1, 2, 3, 4, 5); + assertThat(navigationStateHolder.getCurrentPage()).isEqualTo(0); service.gotoPage(0); verifyDispatcherAndCallOnSuccess(); - assertThat(getPageDataModelAsIds(), contains(0, 1, 2, 3, 4, 5)); - assertThat(navigationStateHolder.getCurrentPage(), is(0)); + assertThat(getPageDataModelAsIds()).contains(0, 1, 2, 3, 4, 5); + assertThat(navigationStateHolder.getCurrentPage()).isEqualTo(0); } @Test @@ -292,17 +289,17 @@ public void canGoToNextPage() { verifyDispatcherAndCallOnSuccess(); service.gotoPage(1); verifyDispatcherAndCallOnSuccess(); - assertThat(getPageDataModelAsIds(), contains(2, 3)); - assertThat(navigationStateHolder.getCurrentPage(), is(1)); + assertThat(getPageDataModelAsIds()).contains(2, 3); + assertThat(navigationStateHolder.getCurrentPage()).isEqualTo(1); service.gotoPage(2); verifyDispatcherAndCallOnSuccess(); - assertThat(getPageDataModelAsIds(), contains(4, 5)); - assertThat(navigationStateHolder.getCurrentPage(), is(2)); + assertThat(getPageDataModelAsIds()).contains(4, 5); + assertThat(navigationStateHolder.getCurrentPage()).isEqualTo(2); // can't go any further service.gotoPage(2); verifyNoMoreInteractions(dispatcher); - assertThat(getPageDataModelAsIds(), contains(4, 5)); - assertThat(navigationStateHolder.getCurrentPage(), is(2)); + assertThat(getPageDataModelAsIds()).contains(4, 5); + assertThat(navigationStateHolder.getCurrentPage()).isEqualTo(2); } @Test @@ -312,24 +309,24 @@ public void canGoToPreviousPage() { // should be on first page already service.gotoPage(0); verifyNoMoreInteractions(dispatcher); - assertThat(getPageDataModelAsIds(), contains(0, 1)); - assertThat(navigationStateHolder.getCurrentPage(), is(0)); + assertThat(getPageDataModelAsIds()).contains(0, 1); + assertThat(navigationStateHolder.getCurrentPage()).isEqualTo(0); service.gotoPage(2); verifyDispatcherAndCallOnSuccess(); - assertThat(getPageDataModelAsIds(), contains(4, 5)); - assertThat(navigationStateHolder.getCurrentPage(), is(2)); + assertThat(getPageDataModelAsIds()).contains(4, 5); + assertThat(navigationStateHolder.getCurrentPage()).isEqualTo(2); service.gotoPage(1); verifyDispatcherAndCallOnSuccess(); - assertThat(getPageDataModelAsIds(), contains(2, 3)); - assertThat(navigationStateHolder.getCurrentPage(), is(1)); + assertThat(getPageDataModelAsIds()).contains(2, 3); + assertThat(navigationStateHolder.getCurrentPage()).isEqualTo(1); service.gotoPage(0); verifyDispatcherAndCallOnSuccess(); - assertThat(getPageDataModelAsIds(), contains(0, 1)); - assertThat(navigationStateHolder.getCurrentPage(), is(0)); + assertThat(getPageDataModelAsIds()).contains(0, 1); + assertThat(navigationStateHolder.getCurrentPage()).isEqualTo(0); // can't go any further service.gotoPage(0); verifyNoMoreInteractions(dispatcher); - assertThat(navigationStateHolder.getCurrentPage(), is(0)); + assertThat(navigationStateHolder.getCurrentPage()).isEqualTo(0); } @Test @@ -338,18 +335,18 @@ public void canGoToPage() { verifyDispatcherAndCallOnSuccess(); service.gotoPage(1); verifyDispatcherAndCallOnSuccess(); - assertThat(getPageDataModelAsIds(), contains(3, 4, 5)); - assertThat(navigationStateHolder.getCurrentPage(), is(1)); + assertThat(getPageDataModelAsIds()).contains(3, 4, 5); + assertThat(navigationStateHolder.getCurrentPage()).isEqualTo(1); // page out of bound service.gotoPage(7); verifyDispatcherAndCallOnSuccess(); - assertThat(getPageDataModelAsIds(), contains(3, 4, 5)); - assertThat(navigationStateHolder.getCurrentPage(), is(1)); + assertThat(getPageDataModelAsIds()).contains(3, 4, 5); + assertThat(navigationStateHolder.getCurrentPage()).isEqualTo(1); // page is negative service.gotoPage(-1); verifyDispatcherAndCallOnSuccess(); - assertThat(getPageDataModelAsIds(), contains(0, 1, 2)); - assertThat(navigationStateHolder.getCurrentPage(), is(0)); + assertThat(getPageDataModelAsIds()).contains(0, 1, 2); + assertThat(navigationStateHolder.getCurrentPage()).isEqualTo(0); } @Test @@ -366,13 +363,12 @@ public void onRPCSuccess() { TestFixture.extractFromEvents(eventCaptor.getAllValues(), TableRowSelectedEvent.class); TransUnitId firstItem = new TransUnitId(TEXT_FLOWS.get(0).getId()); - assertThat(tableRowSelectedEvent.getSelectedId(), - Matchers.equalTo(firstItem)); + assertThat(tableRowSelectedEvent.getSelectedId()).isEqualTo(firstItem); // behaviour on GetTransUnitNavigation success PageCountChangeEvent pageCountChangeEvent = TestFixture.extractFromEvents(eventCaptor.getAllValues(), PageCountChangeEvent.class); - assertThat(pageCountChangeEvent.getPageCount(), Matchers.is(2)); + assertThat(pageCountChangeEvent.getPageCount()).isEqualTo(2); inOrder.verify(eventBus).fireEvent(LoadingEvent.FINISH_EVENT); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/NavigationServiceUnitTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/NavigationServiceUnitTest.java index 9479b7c680..0cca0d9575 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/NavigationServiceUnitTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/NavigationServiceUnitTest.java @@ -1,6 +1,6 @@ package org.zanata.webtrans.client.service; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.*; import java.util.List; @@ -8,7 +8,6 @@ import net.customware.gwt.presenter.client.EventBus; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -133,8 +132,8 @@ public void onNavigationEventOnSamePage() { TableRowSelectedEvent tableRowSelectedEvent = TestFixture.extractFromEvents(eventCaptor.getAllValues(), TableRowSelectedEvent.class); - assertThat(tableRowSelectedEvent.getSelectedId(), - Matchers.equalTo(data.get(0).getId())); + assertThat(tableRowSelectedEvent.getSelectedId()) + .isEqualTo(data.get(0).getId()); } @Test @@ -147,10 +146,10 @@ public void onNavigationEventOnDifferentPage() { verify(dispatcher, times(2)).execute(actionCaptor.capture(), resultCaptor.capture()); GetTransUnitList action = actionCaptor.getValue(); - assertThat(action.getOffset(), Matchers.equalTo(3)); - assertThat(action.getCount(), Matchers.equalTo(EDITOR_PAGE_SIZE)); - assertThat(action.getTargetTransUnitId(), - Matchers.equalTo(data.get(data.size() - 1).getId())); + assertThat(action.getOffset()).isEqualTo(3); + assertThat(action.getCount()).isEqualTo(EDITOR_PAGE_SIZE); + assertThat(action.getTargetTransUnitId()) + .isEqualTo(data.get(data.size() - 1).getId()); } @Test @@ -164,8 +163,8 @@ public void onNextEntry() { TableRowSelectedEvent tableRowSelectedEvent = TestFixture.extractFromEvents(eventCaptor.getAllValues(), TableRowSelectedEvent.class); - assertThat(tableRowSelectedEvent.getSelectedId(), - Matchers.equalTo(data.get(1).getId())); + assertThat(tableRowSelectedEvent.getSelectedId()) + .isEqualTo(data.get(1).getId()); } @Test @@ -178,8 +177,8 @@ public void onPreviousEntry() { TableRowSelectedEvent tableRowSelectedEvent = TestFixture.extractFromEvents(eventCaptor.getAllValues(), TableRowSelectedEvent.class); - assertThat(tableRowSelectedEvent.getSelectedId(), - Matchers.equalTo(data.get(1).getId())); + assertThat(tableRowSelectedEvent.getSelectedId()) + .isEqualTo(data.get(1).getId()); } @Test @@ -193,8 +192,8 @@ public void onNextState() { TableRowSelectedEvent tableRowSelectedEvent = TestFixture.extractFromEvents(eventCaptor.getAllValues(), TableRowSelectedEvent.class); - assertThat(tableRowSelectedEvent.getSelectedId(), - Matchers.equalTo(data.get(2).getId())); + assertThat(tableRowSelectedEvent.getSelectedId()) + .isEqualTo(data.get(2).getId()); } @Test @@ -208,8 +207,8 @@ public void onPreviousState() { TableRowSelectedEvent tableRowSelectedEvent = TestFixture.extractFromEvents(eventCaptor.getAllValues(), TableRowSelectedEvent.class); - assertThat(tableRowSelectedEvent.getSelectedId(), - Matchers.equalTo(data.get(2).getId())); + assertThat(tableRowSelectedEvent.getSelectedId()) + .isEqualTo(data.get(2).getId()); } @Test @@ -260,9 +259,8 @@ public void testOnTransUnitUpdatedNotInCurrentPage() throws Exception { // Then: verifyZeroInteractions(pageDataChangeListener); - assertThat(data.get(data.size() - 1).getSourceComment(), - Matchers.not(Matchers.equalTo(updatedTU.getSourceComment()))); - + assertThat(data.get(data.size() - 1).getSourceComment()) + .isNotEqualTo(updatedTU.getSourceComment()); } @Test @@ -287,14 +285,14 @@ public void testOnTransUnitUpdatedNotInCurrentDocument() throws Exception { public void testUpdateDataModel() throws Exception { service.init(initContext); service.selectByRowIndex(0); - assertThat(service.getSelectedOrNull().getStatus(), - Matchers.equalTo(ContentState.Approved)); + assertThat(service.getSelectedOrNull().getStatus()) + .isEqualTo(ContentState.Approved); service.updateDataModel(TestFixture.makeTransUnit(service .getSelectedOrNull().getId().getId(), ContentState.NeedReview)); - assertThat(service.getSelectedOrNull().getStatus(), - Matchers.equalTo(ContentState.NeedReview)); + assertThat(service.getSelectedOrNull().getStatus()) + .isEqualTo(ContentState.NeedReview); } @Test @@ -306,8 +304,7 @@ public void testOnDocumentSelected() throws Exception { verify(dispatcher).execute(actionCaptor.capture(), resultCaptor.capture()); GetTransUnitList getTransUnitList = actionCaptor.getValue(); - assertThat(getTransUnitList.getDocumentId(), - Matchers.equalTo(documentId)); + assertThat(getTransUnitList.getDocumentId()).isEqualTo(documentId); } @Test @@ -319,7 +316,7 @@ public void testOnPageSizeChange() throws Exception { verify(dispatcher, times(2)).execute(actionCaptor.capture(), resultCaptor.capture()); GetTransUnitList getTransUnitList = actionCaptor.getValue(); - assertThat(getTransUnitList.getCount(), Matchers.equalTo(5)); + assertThat(getTransUnitList.getCount()).isEqualTo(5); } @@ -328,45 +325,44 @@ public void testSelectByRowIndex() throws Exception { service.init(initContext); service.selectByRowIndex(1); - assertThat(service.getCurrentRowIndexOnPage(), Matchers.equalTo(1)); - assertThat(service.getSelectedOrNull(), Matchers.equalTo(data.get(1))); + assertThat(service.getCurrentRowIndexOnPage()).isEqualTo(1); + assertThat(service.getSelectedOrNull()).isEqualTo(data.get(1)); } @Test public void testFindRowIndexById() throws Exception { - assertThat(service.findRowIndexById(new TransUnitId(2)), - Matchers.equalTo(1)); + assertThat(service.findRowIndexById(new TransUnitId(2))) + .isEqualTo(1); // not in current page - assertThat(service.findRowIndexById(new TransUnitId(99)), - Matchers.equalTo(NavigationService.UNDEFINED)); + assertThat(service.findRowIndexById(new TransUnitId(99))) + .isEqualTo(NavigationService.UNDEFINED); } @Test public void testGetSelectedOrNull() throws Exception { service.init(initContext); - assertThat(service.getSelectedOrNull(), Matchers.nullValue()); + assertThat(service.getSelectedOrNull()).isNull(); service.selectByRowIndex(1); - assertThat(service.getSelectedOrNull(), Matchers.equalTo(data.get(1))); + assertThat(service.getSelectedOrNull()).isEqualTo(data.get(1)); } @Test public void testGetCurrentPageValues() throws Exception { - assertThat(service.getCurrentPageValues(), - Matchers.equalTo(data.subList(0, EDITOR_PAGE_SIZE))); + assertThat(service.getCurrentPageValues()) + .isEqualTo(data.subList(0, EDITOR_PAGE_SIZE)); } @Test public void testGetByIdOrNull() throws Exception { - assertThat(service.getByIdOrNull(new TransUnitId(2)), - Matchers.equalTo(data.get(1))); + assertThat(service.getByIdOrNull(new TransUnitId(2))) + .isEqualTo(data.get(1)); // not in current page - assertThat(service.getByIdOrNull(new TransUnitId(99)), - Matchers.nullValue()); + assertThat(service.getByIdOrNull(new TransUnitId(99))).isNull(); } @Test @@ -380,7 +376,7 @@ public void onBookmarkedTextFlowOnSamePage() { TableRowSelectedEvent event = TestFixture.extractFromEvents(eventCaptor.getAllValues(), TableRowSelectedEvent.class); - assertThat(event.getSelectedId(), Matchers.equalTo(targetId)); + assertThat(event.getSelectedId()).isEqualTo(targetId); verifyZeroInteractions(dispatcher); } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/SaveEventQueueTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/SaveEventQueueTest.java index ef9d74e360..0e52157485 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/SaveEventQueueTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/SaveEventQueueTest.java @@ -1,14 +1,14 @@ package org.zanata.webtrans.client.service; import java.util.List; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.zanata.common.ContentState; import org.zanata.webtrans.client.events.TransUnitSaveEvent; import org.zanata.webtrans.shared.model.TransUnitId; import com.google.common.collect.Lists; -import static org.hamcrest.MatcherAssert.*; + +import static org.assertj.core.api.Assertions.assertThat; /** * @author Patrick Huang @@ -40,13 +40,11 @@ private void printQueue() { private static void assertEventEquals(TransUnitSaveEvent one, TransUnitSaveEvent other) { - assertThat(one.getStatus(), Matchers.equalTo(other.getStatus())); - assertThat(one.getTargets(), Matchers.equalTo(other.getTargets())); - assertThat(one.getOldContents(), - Matchers.equalTo(other.getOldContents())); - assertThat(one.getTransUnitId(), - Matchers.equalTo(other.getTransUnitId())); - assertThat(one.getVerNum(), Matchers.equalTo(other.getVerNum())); + assertThat(one.getStatus()).isEqualTo(other.getStatus()); + assertThat(one.getTargets()).isEqualTo(other.getTargets()); + assertThat(one.getOldContents()).isEqualTo(other.getOldContents()); + assertThat(one.getTransUnitId()).isEqualTo(other.getTransUnitId()); + assertThat(one.getVerNum()).isEqualTo(other.getVerNum()); } private static TransUnitSaveEvent fromQueueAsEvent( @@ -58,39 +56,39 @@ private static TransUnitSaveEvent fromQueueAsEvent( public void testPush() throws Exception { TransUnitSaveEvent firstEvent = saveEvent(1, 0, "new", "old"); queue.push(firstEvent); - assertThat(queue.getEventQueue(), Matchers.hasSize(1)); + assertThat(queue.getEventQueue()).hasSize(1); // pushing another event with same id and version should replace the old // pending one TransUnitSaveEvent anotherEvent = saveEvent(1, 0, "newer", "new"); queue.push(anotherEvent); - assertThat(queue.getEventQueue(), Matchers.hasSize(1)); + assertThat(queue.getEventQueue()).hasSize(1); assertEventEquals(fromQueueAsEvent(queue.getEventQueue(), 0), anotherEvent); - assertThat(queue.hasPending(), Matchers.is(true)); + assertThat(queue.hasPending()).isTrue(); // pushing another event but doesn't match previous one. It will get // discarded TransUnitSaveEvent invalidEvent = saveEvent(1, 0, "blah", "content don\'t match previous"); queue.push(invalidEvent); - assertThat(queue.getEventQueue(), Matchers.hasSize(1)); + assertThat(queue.getEventQueue()).hasSize(1); assertEventEquals(fromQueueAsEvent(queue.getEventQueue(), 0), anotherEvent); - assertThat(queue.hasPending(), Matchers.is(true)); + assertThat(queue.hasPending()).isTrue(); // pushing another event with different id will not conflict with other // pending one TransUnitSaveEvent differentId = saveEvent(2, 1, "different id", "hi"); queue.push(differentId); - assertThat(queue.getEventQueue(), Matchers.hasSize(2)); + assertThat(queue.getEventQueue()).hasSize(2); assertEventEquals(fromQueueAsEvent(queue.getEventQueue(), 0), anotherEvent); assertEventEquals(fromQueueAsEvent(queue.getEventQueue(), 1), differentId); - assertThat(queue.hasPending(), Matchers.is(true)); + assertThat(queue.hasPending()).isTrue(); // pushing an event with equal state as the saving event. It will be // discarded queue.getNextPendingForSaving(anotherEvent.getTransUnitId()); queue.push(anotherEvent); - assertThat(queue.getEventQueue(), Matchers.hasSize(2)); + assertThat(queue.getEventQueue()).hasSize(2); assertEventEquals(fromQueueAsEvent(queue.getEventQueue(), 0), anotherEvent); assertEventEquals(fromQueueAsEvent(queue.getEventQueue(), 1), @@ -104,15 +102,13 @@ public void testGetNextPendingForSaving() throws Exception { TransUnitSaveEvent next = queue.getNextPendingForSaving(firstEvent.getTransUnitId()); assertEventEquals(firstEvent, next); - assertThat(queue.getEventQueue().get(0).isSaving(), Matchers.is(true)); - assertThat(queue.isSaving(firstEvent.getTransUnitId()), - Matchers.is(true)); + assertThat(queue.getEventQueue().get(0).isSaving()).isTrue(); + assertThat(queue.isSaving(firstEvent.getTransUnitId())).isTrue(); // pushing another event won't replace saving event TransUnitSaveEvent anotherSave = saveEvent(1, 0, "newer", "new"); queue.push(anotherSave); - assertThat(queue.getEventQueue(), Matchers.hasSize(2)); - assertThat(queue.isSaving(anotherSave.getTransUnitId()), - Matchers.is(true)); + assertThat(queue.getEventQueue()).hasSize(2); + assertThat(queue.isSaving(anotherSave.getTransUnitId())).isTrue(); } @Test @@ -125,20 +121,20 @@ public void testRemoveSaved() throws Exception { queue.push(pendingBeforeSave); // after save success we remove saved event queue.removeSaved(goToSave, 1); - assertThat(queue.getEventQueue(), Matchers.hasSize(1)); + assertThat(queue.getEventQueue()).hasSize(1); TransUnitSaveEvent pendingEventAfterSave = queue.getEventQueue().get(0).toEvent(); - assertThat(pendingEventAfterSave.getStatus(), - Matchers.equalTo(pendingBeforeSave.getStatus())); - assertThat(pendingEventAfterSave.getTargets(), - Matchers.equalTo(pendingBeforeSave.getTargets())); - assertThat(pendingEventAfterSave.getOldContents(), - Matchers.equalTo(pendingBeforeSave.getOldContents())); - assertThat(pendingEventAfterSave.getTransUnitId(), - Matchers.equalTo(pendingBeforeSave.getTransUnitId())); + assertThat(pendingEventAfterSave.getStatus()) + .isEqualTo(pendingBeforeSave.getStatus()); + assertThat(pendingEventAfterSave.getTargets()) + .isEqualTo(pendingBeforeSave.getTargets()); + assertThat(pendingEventAfterSave.getOldContents()) + .isEqualTo(pendingBeforeSave.getOldContents()); + assertThat(pendingEventAfterSave.getTransUnitId()) + .isEqualTo(pendingBeforeSave.getTransUnitId()); // version should be changed - assertThat(pendingEventAfterSave.getVerNum(), Matchers.equalTo(1)); - assertThat(queue.hasPending(), Matchers.is(true)); + assertThat(pendingEventAfterSave.getVerNum()).isEqualTo(1); + assertThat(queue.hasPending()).isTrue(); } @Test @@ -146,8 +142,7 @@ public void testRemoveAllPending() throws Exception { TransUnitSaveEvent saveEvent = saveEvent(1, 0, "new", "old"); queue.push(saveEvent); queue.removeAllPending(saveEvent.getTransUnitId()); - assertThat(queue.getEventQueue(), - Matchers. empty()); - assertThat(queue.hasPending(), Matchers.is(false)); + assertThat(queue.getEventQueue()).isEmpty(); + assertThat(queue.hasPending()).isFalse(); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/SinglePageDataModelImplTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/SinglePageDataModelImplTest.java index d6885dc6fe..963b5d7fed 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/SinglePageDataModelImplTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/SinglePageDataModelImplTest.java @@ -2,7 +2,6 @@ import java.util.List; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.zanata.common.ContentState; @@ -12,7 +11,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; -import static org.hamcrest.MatcherAssert.*; +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.webtrans.client.service.NavigationService.UNDEFINED; /** @@ -36,17 +35,17 @@ public void setUp() throws Exception { @Test public void canSetDataAndResetCurrentRowToUnselected() { - assertThat(model.getData(), Matchers.is(Matchers. empty())); + assertThat(model.getData()).isEmpty(); model.setData(data); - assertThat(model.getCurrentRow(), Matchers.equalTo(UNDEFINED)); - assertThat(model.getData(), Matchers.is(data)); + assertThat(model.getCurrentRow()).isEqualTo(UNDEFINED); + assertThat(model.getData()).isEqualTo(data); model.setSelected(1); - assertThat(model.getCurrentRow(), Matchers.equalTo(1)); + assertThat(model.getCurrentRow()).isEqualTo(1); model.setData(data); - assertThat(model.getCurrentRow(), Matchers.equalTo(UNDEFINED)); + assertThat(model.getCurrentRow()).isEqualTo(UNDEFINED); } @Test @@ -54,10 +53,10 @@ public void canGetByIdOrNull() { model.setData(data); TransUnit found = model.getByIdOrNull(new TransUnitId(2)); - assertThat(found, Matchers.equalTo(data.get(1))); + assertThat(found).isEqualTo(data.get(1)); TransUnit notFound = model.getByIdOrNull(new TransUnitId(99)); - assertThat(notFound, Matchers.is(Matchers.nullValue())); + assertThat(notFound).isNull(); } @Test @@ -65,10 +64,10 @@ public void canFindIndexById() { model.setData(data); int index = model.findIndexById(new TransUnitId(3)); - assertThat(index, Matchers.is(2)); + assertThat(index).isEqualTo(2); int notFoundIndex = model.findIndexById(new TransUnitId(99)); - assertThat(notFoundIndex, Matchers.is(UNDEFINED)); + assertThat(notFoundIndex).isEqualTo(UNDEFINED); } @Test @@ -77,9 +76,8 @@ public void canSetSelectedByIndex() { model.setSelected(2); - assertThat(model.getCurrentRow(), Matchers.is(2)); - assertThat(model.getSelectedOrNull(), - Matchers.sameInstance(data.get(2))); + assertThat(model.getCurrentRow()).isEqualTo(2); + assertThat(model.getSelectedOrNull()).isSameAs(data.get(2)); } @Test @@ -89,7 +87,7 @@ public void selectedIsNullIfIndexIsOutOfRange() { model.setSelected(-1); TransUnit result = model.getSelectedOrNull(); - assertThat(result, Matchers.is(Matchers.nullValue())); + assertThat(result).isNull(); } @Test @@ -100,15 +98,14 @@ public void willUpdateModelIfInCurrentPage() { List oldData = ImmutableList.copyOf(data); model.setData(data); - assertThat(model.getByIdOrNull(updatedTUId), - Matchers.not(Matchers.sameInstance(updatedTransUnit))); + assertThat(model.getByIdOrNull(updatedTUId)) + .isNotSameAs(updatedTransUnit); boolean updated = model.updateIfInCurrentPage(updatedTransUnit); - assertThat(updated, Matchers.is(true)); - assertThat(model.getData(), Matchers.not(Matchers.equalTo(oldData))); - assertThat(model.getByIdOrNull(updatedTUId), - Matchers.sameInstance(updatedTransUnit)); + assertThat(updated).isTrue(); + assertThat(model.getData()).isNotEqualTo(oldData); + assertThat(model.getByIdOrNull(updatedTUId)).isSameAs(updatedTransUnit); } @Test @@ -119,12 +116,11 @@ public void willNotUpdateModelIfNotInCurrentPage() { List oldData = ImmutableList.copyOf(data); model.setData(data); - assertThat(model.getByIdOrNull(updatedTUId), - Matchers.not(Matchers.sameInstance(updatedTransUnit))); + assertThat(model.getByIdOrNull(updatedTUId)).isNotSameAs(updatedTransUnit); boolean updated = model.updateIfInCurrentPage(updatedTransUnit); - assertThat(updated, Matchers.is(false)); - assertThat(model.getData(), Matchers.equalTo(oldData)); + assertThat(updated).isFalse(); + assertThat(model.getData()).isEqualTo(oldData); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/TransUnitSaveServiceTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/TransUnitSaveServiceTest.java index ecd0766fdd..a411f86b06 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/TransUnitSaveServiceTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/TransUnitSaveServiceTest.java @@ -1,9 +1,6 @@ package org.zanata.webtrans.client.service; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -12,7 +9,6 @@ import net.customware.gwt.presenter.client.EventBus; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -28,7 +24,6 @@ import org.zanata.webtrans.client.resources.TableEditorMessages; import org.zanata.webtrans.client.rpc.CachingDispatchAsync; import org.zanata.webtrans.client.ui.GoToRowLink; -import org.zanata.webtrans.client.ui.InlineLink; import org.zanata.webtrans.client.ui.UndoLink; import org.zanata.webtrans.client.view.TargetContentsDisplay; import org.zanata.webtrans.shared.model.DocumentId; @@ -131,16 +126,16 @@ public void willSaveIfSomethingHasChanged() { resultCaptor.capture()); UpdateTransUnit updateTransUnit = actionCaptor.getValue(); - assertThat(updateTransUnit.getUpdateRequests(), hasSize(1)); - assertThat(updateTransUnit.getUpdateType(), - equalTo(TransUnitUpdated.UpdateType.WebEditorSave)); + assertThat(updateTransUnit.getUpdateRequests()).hasSize(1); + assertThat(updateTransUnit.getUpdateType()) + .isEqualTo(TransUnitUpdated.UpdateType.WebEditorSave); TransUnitUpdateRequest request = updateTransUnit.getUpdateRequests().get(0); - assertThat(request.getTransUnitId(), equalTo(TRANS_UNIT_ID)); - assertThat(request.getNewContents(), Matchers.contains("new content")); - assertThat(request.getBaseTranslationVersion(), equalTo(VER_NUM)); - assertThat(request.getNewContentState(), equalTo(ContentState.Approved)); + assertThat(request.getTransUnitId()).isEqualTo(TRANS_UNIT_ID); + assertThat(request.getNewContents()).contains("new content"); + assertThat(request.getBaseTranslationVersion()).isEqualTo(VER_NUM); + assertThat(request.getNewContentState()).isEqualTo(ContentState.Approved); } @Test @@ -162,18 +157,18 @@ public void willSaveToQueueIfItsSavingSameRow() { resultCaptor.capture()); UpdateTransUnit updateTransUnit = actionCaptor.getValue(); - assertThat(updateTransUnit.getUpdateRequests(), hasSize(1)); - assertThat(updateTransUnit.getUpdateType(), - equalTo(TransUnitUpdated.UpdateType.WebEditorSave)); + assertThat(updateTransUnit.getUpdateRequests()).hasSize(1); + assertThat(updateTransUnit.getUpdateType()) + .isEqualTo(TransUnitUpdated.UpdateType.WebEditorSave); TransUnitUpdateRequest request = updateTransUnit.getUpdateRequests().get(0); - assertThat(request.getTransUnitId(), equalTo(TRANS_UNIT_ID)); - assertThat(request.getNewContents(), Matchers.contains("new content")); - assertThat(request.getBaseTranslationVersion(), equalTo(VER_NUM)); - assertThat(request.getNewContentState(), equalTo(ContentState.Approved)); + assertThat(request.getTransUnitId()).isEqualTo(TRANS_UNIT_ID); + assertThat(request.getNewContents()).contains("new content"); + assertThat(request.getBaseTranslationVersion()).isEqualTo(VER_NUM); + assertThat(request.getNewContentState()).isEqualTo(ContentState.Approved); - assertThat(queue.hasPending(), Matchers.is(true)); + assertThat(queue.hasPending()).isTrue(); } @Test @@ -191,8 +186,8 @@ public void onRPCSuccessAndSaveReturnSuccess() { // Then: verify(dispatcher).execute(actionCaptor.capture(), resultCaptor.capture()); - assertThat(actionCaptor.getValue().getUpdateType(), - equalTo(TransUnitUpdated.UpdateType.WebEditorSave)); + assertThat(actionCaptor.getValue().getUpdateType()) + .isEqualTo(TransUnitUpdated.UpdateType.WebEditorSave); // on save success // Given: result comes back with saving successful @@ -218,8 +213,8 @@ public void onRPCSuccessAndSaveReturnSuccess() { ArgumentCaptor.forClass(NotificationEvent.class); verify(eventBus).fireEvent(notificationEventCaptor.capture()); NotificationEvent event = notificationEventCaptor.getValue(); - assertThat(event.getSeverity(), is(NotificationEvent.Severity.Info)); - assertThat(event.getMessage(), equalTo("saved row 1, id 1")); + assertThat(event.getSeverity()).isEqualTo(NotificationEvent.Severity.Info); + assertThat(event.getMessage()).isEqualTo("saved row 1, id 1"); verify(undoLink).prepareUndoFor(result); verify(targetContentsPresenter).addUndoLink(rowIndex, undoLink); verify(navigationService).updateDataModel(updatedTU); @@ -267,10 +262,10 @@ public void onRPCSuccessAndThereIsPendingSave() { resultCaptor.capture()); // Then: we have 3 action here just because we verify dispatcher twice - assertThat(actionCaptor.getAllValues(), Matchers.hasSize(3)); + assertThat(actionCaptor.getAllValues()).hasSize(3); UpdateTransUnit secondRequest = actionCaptor.getAllValues().get(2); - assertThat(secondRequest.getUpdateRequests().get(0).getNewContents(), - Matchers.contains("newer content")); + assertThat(secondRequest.getUpdateRequests().get(0).getNewContents()) + .contains("newer content"); } @Test @@ -313,10 +308,9 @@ public void onPRCSuccessButSaveUnsuccessfulInResult() { TargetContentsDisplay.EditingState.UNSAVED); verify(eventBus).fireEvent(notificationEventCaptor.capture()); NotificationEvent event = notificationEventCaptor.getValue(); - assertThat(event.getSeverity(), is(NotificationEvent.Severity.Error)); - assertThat(event.getMessage(), equalTo("update failed")); - assertThat(event.getInlineLink(), - Matchers. sameInstance(goToLink)); + assertThat(event.getSeverity()).isEqualTo(NotificationEvent.Severity.Error); + assertThat(event.getMessage()).isEqualTo("update failed"); + assertThat(event.getInlineLink()).isSameAs(goToLink); } @Test @@ -351,10 +345,9 @@ public void onPRCFailure() { TargetContentsDisplay.EditingState.UNSAVED); verify(eventBus).fireEvent(notificationEventCaptor.capture()); NotificationEvent event = notificationEventCaptor.getValue(); - assertThat(event.getSeverity(), is(NotificationEvent.Severity.Error)); - assertThat(event.getMessage(), equalTo("update failed")); - assertThat(event.getInlineLink(), - Matchers. sameInstance(goToLink)); + assertThat(event.getSeverity()).isEqualTo(NotificationEvent.Severity.Error); + assertThat(event.getMessage()).isEqualTo("update failed"); + assertThat(event.getInlineLink()).isSameAs(goToLink); } private static UpdateTransUnitResult diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/TranslatorInteractionServiceTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/TranslatorInteractionServiceTest.java index aad09ba78d..97aa626c9a 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/TranslatorInteractionServiceTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/TranslatorInteractionServiceTest.java @@ -1,6 +1,5 @@ package org.zanata.webtrans.client.service; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -18,7 +17,7 @@ import org.zanata.webtrans.shared.model.TransUnit; import org.zanata.webtrans.shared.rpc.TransUnitEditAction; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; /** @@ -47,8 +46,7 @@ public void canGetEditorClientId() { EditorClientId currentEditorClientId = service.getCurrentEditorClientId(); - assertThat(currentEditorClientId, - Matchers.equalTo(identity.getEditorClientId())); + assertThat(currentEditorClientId).isEqualTo(identity.getEditorClientId()); } @Test @@ -60,10 +58,9 @@ public void canCallServerOnSelection() { verify(dispatcher).execute(actionCaptor.capture(), Mockito.isA(NoOpAsyncCallback.class)); TransUnitEditAction action = actionCaptor.getValue(); - assertThat(action.getPerson(), - Matchers.sameInstance(identity.getPerson())); - assertThat(action.getSelectedTransUnitId(), - Matchers.sameInstance(selectedTransUnit.getId())); + assertThat(action.getPerson()).isSameAs(identity.getPerson()); + assertThat(action.getSelectedTransUnitId()) + .isSameAs(selectedTransUnit.getId()); } @Test @@ -77,8 +74,8 @@ public void onPersonExit() { verify(dispatcher).execute(actionCaptor.capture(), Mockito.isA(NoOpAsyncCallback.class)); TransUnitEditAction action = actionCaptor.getValue(); - assertThat(action.getPerson(), Matchers.sameInstance(person)); - assertThat(action.getSelectedTransUnitId(), - Matchers.sameInstance(selectedTransUnit.getId())); + assertThat(action.getPerson()).isSameAs(person); + assertThat(action.getSelectedTransUnitId()) + .isSameAs(selectedTransUnit.getId()); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/UserOptionsServiceTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/UserOptionsServiceTest.java index 67ecedf52c..4075fb6a99 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/UserOptionsServiceTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/UserOptionsServiceTest.java @@ -20,7 +20,7 @@ */ package org.zanata.webtrans.client.service; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -31,7 +31,6 @@ import net.customware.gwt.presenter.client.EventBus; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -107,10 +106,10 @@ public void persistOptionChange() { Boolean.parseBoolean(action.getConfigurationMap().get( DisplayButtons)); - assertThat(docListSize, Matchers.equalTo(1000)); - assertThat(editorSize, Matchers.equalTo(2000)); - assertThat(displayButton, Matchers.equalTo(false)); - assertThat(showError, Matchers.equalTo(true)); + assertThat(docListSize).isEqualTo(1000); + assertThat(editorSize).isEqualTo(2000); + assertThat(displayButton).isFalse(); + assertThat(showError).isTrue(); AsyncCallback callback = callbackCaptor.getValue(); callback.onSuccess(new SaveOptionsResult()); @@ -121,55 +120,50 @@ public void persistOptionChange() { @Test public void getCommonOptions() { Map map = service.getCommonOptions(); - assertThat(map.size(), Matchers.equalTo(2)); - assertThat(map.containsKey(ShowErrors), - Matchers.equalTo(true)); - assertThat(map.containsKey(Themes), Matchers.equalTo(true)); + assertThat(map.size()).isEqualTo(2); + assertThat(map.containsKey(ShowErrors)).isTrue(); + assertThat(map.containsKey(Themes)).isTrue(); } @Test public void getDocumentListOptions() { Map map = service.getDocumentListOptions(); - assertThat(map.size(), Matchers.equalTo(3)); - assertThat(map.containsKey(ShowErrors), - Matchers.equalTo(true)); - assertThat(map.containsKey(Themes), Matchers.equalTo(true)); - assertThat(map.containsKey(DocumentListPageSize), - Matchers.equalTo(true)); + assertThat(map).hasSize(3); + assertThat(map).containsKey(ShowErrors); + assertThat(map).containsKey(Themes); + assertThat(map).containsKey(DocumentListPageSize); } @Test public void getEditorOptions() { Map map = service.getEditorOptions(); - assertThat(map.keySet(), Matchers.containsInAnyOrder(ShowErrors, + assertThat(map.keySet()).contains(ShowErrors, Themes, DisplayButtons, EnterSavesApproved, EditorPageSize, TranslatedMessageFilter, UseCodeMirrorEditor, TransMemoryDisplayMode, FuzzyMessageFilter, UntranslatedMessageFilter, ApprovedMessageFilter, RejectedMessageFilter, Navigation, ShowSaveApprovedWarning, - SelectedReferenceLang, DisplayTransMemory, DisplayGlossary)); + SelectedReferenceLang, DisplayTransMemory, DisplayGlossary); } @Test public void loadCommonOptions() { service.loadCommonOptions(); - - assertThat(configHolder.getState().isShowError(), - Matchers.equalTo(UserConfigHolder.DEFAULT_SHOW_ERROR)); + assertThat(configHolder.getState().isShowError()) + .isEqualTo(UserConfigHolder.DEFAULT_SHOW_ERROR); } @Test public void loadDocumentListDefaultOptions() { service.getConfigHolder().setShowError(true); service.getConfigHolder().setDocumentListPageSize(2000); - service.loadDocumentListDefaultOptions(); - assertThat(configHolder.getState().isShowError(), - Matchers.equalTo(UserConfigHolder.DEFAULT_SHOW_ERROR)); - assertThat(configHolder.getState().getDocumentListPageSize(), - Matchers.equalTo(UserConfigHolder.DEFAULT_DOC_LIST_PAGE_SIZE)); + assertThat(configHolder.getState().isShowError()) + .isEqualTo(UserConfigHolder.DEFAULT_SHOW_ERROR); + assertThat(configHolder.getState().getDocumentListPageSize()) + .isEqualTo(UserConfigHolder.DEFAULT_DOC_LIST_PAGE_SIZE); } @@ -181,39 +175,38 @@ public void loadEditorDefaultOptions() { service.loadEditorDefaultOptions(); - assertThat(configHolder.getState().isShowError(), - Matchers.equalTo(UserConfigHolder.DEFAULT_SHOW_ERROR)); - assertThat(configHolder.getState().isDisplayButtons(), - Matchers.equalTo(UserConfigHolder.DEFAULT_DISPLAY_BUTTONS)); - assertThat(configHolder.getState().isEnterSavesApproved(), - Matchers.equalTo(UserConfigHolder.DEFAULT_ENTER_SAVES_APPROVED)); - assertThat(configHolder.getState().isFilterByFuzzy(), - Matchers.equalTo(UserConfigHolder.DEFAULT_FILTER)); - assertThat(configHolder.getState().isFilterByTranslated(), - Matchers.equalTo(UserConfigHolder.DEFAULT_FILTER)); - assertThat(configHolder.getState().isFilterByUntranslated(), - Matchers.equalTo(UserConfigHolder.DEFAULT_FILTER)); - assertThat(configHolder.getState().isFilterByApproved(), - Matchers.equalTo(UserConfigHolder.DEFAULT_FILTER)); - assertThat(configHolder.getState().isFilterByRejected(), - Matchers.equalTo(UserConfigHolder.DEFAULT_FILTER)); - assertThat(configHolder.getState().getNavOption(), - Matchers.equalTo(NavOption.FUZZY_UNTRANSLATED)); - assertThat(configHolder.getState().getEditorPageSize(), - Matchers.equalTo(UserConfigHolder.DEFAULT_EDITOR_PAGE_SIZE)); - assertThat( - configHolder.getState().isShowSaveApprovedWarning(), - Matchers.equalTo(UserConfigHolder.DEFAULT_SHOW_SAVE_APPROVED_WARNING)); - assertThat(configHolder.getState().isUseCodeMirrorEditor(), - Matchers.equalTo(UserConfigHolder.DEFAULT_USE_CODE_MIRROR)); - assertThat(configHolder.getState().getTransMemoryDisplayMode(), - Matchers.equalTo(UserConfigHolder.DEFAULT_TM_DISPLAY_MODE)); - assertThat(configHolder.getState().getSelectedReferenceForSourceLang(), - Matchers.equalTo(UserConfigHolder.DEFAULT_SELECTED_REFERENCE)); + assertThat(configHolder.getState().isShowError()) + .isEqualTo(UserConfigHolder.DEFAULT_SHOW_ERROR); + assertThat(configHolder.getState().isDisplayButtons()) + .isEqualTo(UserConfigHolder.DEFAULT_DISPLAY_BUTTONS); + assertThat(configHolder.getState().isEnterSavesApproved()) + .isEqualTo(UserConfigHolder.DEFAULT_ENTER_SAVES_APPROVED); + assertThat(configHolder.getState().isFilterByFuzzy()) + .isEqualTo(UserConfigHolder.DEFAULT_FILTER); + assertThat(configHolder.getState().isFilterByTranslated()) + .isEqualTo(UserConfigHolder.DEFAULT_FILTER); + assertThat(configHolder.getState().isFilterByUntranslated()) + .isEqualTo(UserConfigHolder.DEFAULT_FILTER); + assertThat(configHolder.getState().isFilterByApproved()) + .isEqualTo(UserConfigHolder.DEFAULT_FILTER); + assertThat(configHolder.getState().isFilterByRejected()) + .isEqualTo(UserConfigHolder.DEFAULT_FILTER); + assertThat(configHolder.getState().getNavOption()) + .isEqualTo(NavOption.FUZZY_UNTRANSLATED); + assertThat(configHolder.getState().getEditorPageSize()) + .isEqualTo(UserConfigHolder.DEFAULT_EDITOR_PAGE_SIZE); + assertThat(configHolder.getState().isShowSaveApprovedWarning()) + .isEqualTo(UserConfigHolder.DEFAULT_SHOW_SAVE_APPROVED_WARNING); + assertThat(configHolder.getState().isUseCodeMirrorEditor()) + .isEqualTo(UserConfigHolder.DEFAULT_USE_CODE_MIRROR); + assertThat(configHolder.getState().getTransMemoryDisplayMode()) + .isEqualTo(UserConfigHolder.DEFAULT_TM_DISPLAY_MODE); + assertThat(configHolder.getState().getSelectedReferenceForSourceLang()) + .isEqualTo(UserConfigHolder.DEFAULT_SELECTED_REFERENCE); } @Test public void getConfigHolder() { - assertThat(service.getConfigHolder(), Matchers.equalTo(configHolder)); + assertThat(service.getConfigHolder()).isEqualTo(configHolder); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/UserSessionServiceTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/UserSessionServiceTest.java index 130c0d3c68..832bb13d89 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/UserSessionServiceTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/UserSessionServiceTest.java @@ -1,6 +1,5 @@ package org.zanata.webtrans.client.service; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; @@ -18,7 +17,8 @@ import org.zanata.webtrans.shared.rpc.HasTransUnitEditData; import net.customware.gwt.presenter.client.EventBus; -import static org.hamcrest.MatcherAssert.assertThat; + +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -73,9 +73,9 @@ public void onTransUnitEditEvent() { // Then: assertThat(service.getUserSessionMap().get(editorClientId) - .getSelectedId(), Matchers.sameInstance(transUnit.getId())); + .getSelectedId()).isSameAs(transUnit.getId()); assertThat(service.getUserSessionMap().get(editorClientId) - .getSelectedId(), Matchers.sameInstance(transUnit.getId())); + .getSelectedId()).isSameAs(transUnit.getId()); } @Test @@ -90,12 +90,12 @@ public void onEnterWorkspace() { service.onEnterWorkspace(event); - assertThat(service.getUserSessionMap(), Matchers.hasKey(editorClientId)); + assertThat(service.getUserSessionMap()).containsKey(editorClientId); UserPanelSessionItem userPanel = service.getUserSessionMap().get(editorClientId); - assertThat(userPanel.getPanel(), Matchers.sameInstance(panel)); + assertThat(userPanel.getPanel()).isSameAs(panel); verify(panel).setColor("red"); - assertThat(userPanel.getSelectedId(), Matchers.nullValue()); + assertThat(userPanel.getSelectedId()).isNull(); } @Test @@ -117,7 +117,7 @@ public void onExitWorkspace() { person.getId().toString()); verify(translatorInteractionService).personExit(person, selectedTransUnit.getId()); - assertThat(service.getUserSessionMap().size(), Matchers.is(0)); + assertThat(service.getUserSessionMap().size()).isEqualTo(0); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/ValidationServiceTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/ValidationServiceTest.java index 6d7ece6ad0..8d919f730e 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/ValidationServiceTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/client/service/ValidationServiceTest.java @@ -1,6 +1,6 @@ package org.zanata.webtrans.client.service; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; import java.io.IOException; @@ -12,7 +12,6 @@ import net.customware.gwt.presenter.client.EventBus; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; @@ -80,8 +79,7 @@ public void canUpdateValidatorStatus() { ValidationAction validationAction = service.getValidationMap().get(VAL_KEY); - assertThat(validationAction.getRules().isEnabled(), - Matchers.equalTo(false)); + assertThat(validationAction.getRules().isEnabled()).isFalse(); verify(eventBus).fireEvent(RequestValidationEvent.EVENT); } @@ -91,7 +89,7 @@ public void canGetValidationList() { new ArrayList(service.getValidationMap() .values()); - assertThat(validationList.size(), Matchers.equalTo(7)); + assertThat(validationList.size()).isEqualTo(7); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/server/TranslationWorkspaceImplTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/server/TranslationWorkspaceImplTest.java index 8665518e39..463855bf93 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/server/TranslationWorkspaceImplTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/server/TranslationWorkspaceImplTest.java @@ -23,7 +23,6 @@ import java.util.Map; import java.util.concurrent.ConcurrentMap; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.zanata.common.LocaleId; @@ -39,8 +38,7 @@ import com.google.common.collect.MapMaker; -import static org.hamcrest.MatcherAssert.*; -import static org.hamcrest.Matchers.*; +import static org.assertj.core.api.Assertions.assertThat; public class TranslationWorkspaceImplTest { private TranslationWorkspaceImpl translationWorkspace; @@ -66,8 +64,7 @@ public void canGetWorkspaceContext() { WorkspaceContext workspaceContext = translationWorkspace.getWorkspaceContext(); - assertThat(workspaceContext.getWorkspaceId(), - Matchers.equalTo(workspaceId)); + assertThat(workspaceContext.getWorkspaceId()).isEqualTo(workspaceId); } @Test @@ -80,10 +77,9 @@ public void canGetUsers() { Map users = translationWorkspace.getUsers(); - assertThat(users, Matchers.hasKey(editorClientId)); + assertThat(users).containsKey(editorClientId); PersonSessionDetails personSessionDetails = users.get(editorClientId); - assertThat(personSessionDetails.getPerson().getId(), - Matchers.equalTo(personId)); + assertThat(personSessionDetails.getPerson().getId()).isEqualTo(personId); } @Test @@ -92,12 +88,11 @@ public void canRemoveClient() { PersonId personId = new PersonId("personId"); translationWorkspace.addEditorClient("sessionId", editorClientId, personId); - assertThat(translationWorkspace.getUsers(), - Matchers.hasKey(editorClientId)); + assertThat(translationWorkspace.getUsers()).containsKey(editorClientId); translationWorkspace.removeEditorClient(editorClientId); - assertThat(translationWorkspace.getUsers().size(), Matchers.is(0)); + assertThat(translationWorkspace.getUsers().size()).isEqualTo(0); } @Test @@ -111,19 +106,14 @@ public void canRemoveClientsWithSameSessionId() { personId); translationWorkspace.addEditorClient(httpSessionId, editorClientId2, personId); - assertThat(translationWorkspace.getUsers().keySet(), - Matchers.containsInAnyOrder(editorClientId1, editorClientId2)); + assertThat(translationWorkspace.getUsers().keySet()) + .contains(editorClientId1, editorClientId2); // When: translationWorkspace.removeEditorClients(httpSessionId); // Then: - assertThat( - translationWorkspace.getUsers().entrySet(), - is(Matchers - .> empty())); - // requires hamcrest 1.3.1: - // assertThat(translationWorkspace.getUsers(), is(anEmptyMap())); + assertThat(translationWorkspace.getUsers().entrySet()).isEmpty(); } @Test @@ -138,10 +128,10 @@ public void canUpdateUserSelection() { PersonSessionDetails personSessionDetails = translationWorkspace.getUsers().get(editorClientId); - assertThat(personSessionDetails.getSelectedTransUnitId(), - Matchers.equalTo(selectedTransUnit.getId())); - assertThat(translationWorkspace.getUserSelection(editorClientId), - Matchers.equalTo(selectedTransUnit.getId())); + assertThat(personSessionDetails.getSelectedTransUnitId()) + .isEqualTo(selectedTransUnit.getId()); + assertThat(translationWorkspace.getUserSelection(editorClientId)) + .isEqualTo(selectedTransUnit.getId()); } @Test diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/server/TranslationWorkspaceManagerImplTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/server/TranslationWorkspaceManagerImplTest.java index 29ca97d29d..97da9cea18 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/server/TranslationWorkspaceManagerImplTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/server/TranslationWorkspaceManagerImplTest.java @@ -2,7 +2,7 @@ import com.google.common.base.Optional; import com.google.common.collect.Lists; -import org.hamcrest.Matchers; +import org.assertj.core.matcher.AssertionMatcher; import org.jglue.cdiunit.ProducerConfig; import org.junit.Test; import org.junit.runner.RunWith; @@ -22,7 +22,6 @@ import org.zanata.service.LocaleService; import org.zanata.service.ValidationService; import org.zanata.test.CdiUnitRunner; -import org.zanata.test.LambdaMatcher; import org.zanata.webtrans.shared.NoSuchWorkspaceException; import org.zanata.webtrans.shared.auth.EditorClientId; import org.zanata.webtrans.shared.model.ProjectIterationId; @@ -42,7 +41,7 @@ import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; @@ -196,10 +195,9 @@ public void testRegisterNewWorkspace() throws Exception { manager.getOrRegisterWorkspace(workspaceId); WorkspaceContext context = workspace.getWorkspaceContext(); - assertThat(context.getWorkspaceId(), Matchers.equalTo(workspaceId)); - assertThat(context.getLocaleName(), Matchers.equalTo("German")); - assertThat(context.getWorkspaceName(), - Matchers.equalTo("project (master)")); + assertThat(context.getWorkspaceId()).isEqualTo(workspaceId); + assertThat(context.getLocaleName()).isEqualTo("German"); + assertThat(context.getWorkspaceName()).isEqualTo("project (master)"); } @Test @@ -221,7 +219,7 @@ public void testGetRegisteredNewWorkspace() throws Exception { // call again with same workspace id will return same instance TranslationWorkspace anotherWorkspace = manager.getOrRegisterWorkspace(workspaceId); - assertThat(anotherWorkspace, Matchers.sameInstance(workspace)); + assertThat(anotherWorkspace).isSameAs(workspace); } @Test @@ -267,15 +265,14 @@ public void testExitWorkspace() throws Exception { verify(mockWorkspace, times(2)).publish(eventCaptor.capture()); ExitWorkspace exitWorkspace1 = eventCaptor.getAllValues().get(0); - assertThat(exitWorkspace1.getEditorClientId(), - Matchers.equalTo(editorClientIds.get(0))); - assertThat(exitWorkspace1.getPerson().getName(), - Matchers.equalTo("patrick")); + assertThat(exitWorkspace1.getEditorClientId()) + .isEqualTo(editorClientIds.get(0)); + assertThat(exitWorkspace1.getPerson().getName()).isEqualTo("patrick"); verify(mockWorkspace).publish(exitWorkspace1); ExitWorkspace exitWorkspace2 = eventCaptor.getAllValues().get(1); - assertThat(exitWorkspace2.getEditorClientId(), - Matchers.equalTo(editorClientIds.get(1))); + assertThat(exitWorkspace2.getEditorClientId()) + .isEqualTo(editorClientIds.get(1)); verify(mockWorkspace).publish(exitWorkspace2); verify(gravatarServiceImpl, times(2)).getUserImageUrl(16, "admin@example.com"); @@ -351,15 +348,25 @@ public void testProjectUpdate() throws Exception { private static WorkspaceContextUpdate matchEvent(String oldProjectSlug, String newProjectSlug) { - return argThat(new LambdaMatcher<>(wcu -> - wcu.getOldProjectSlug().equals(oldProjectSlug) && - wcu.getNewProjectSlug().equals(newProjectSlug))); + return argThat(new AssertionMatcher() { + @Override + public void assertion(WorkspaceContextUpdate actual) + throws AssertionError { + assertThat(actual.getOldProjectSlug()).isEqualTo(oldProjectSlug); + assertThat(actual.getNewProjectSlug()).isEqualTo(newProjectSlug); + } + }); } private static WorkspaceId matchIteration(String iterationSlug) { - return argThat(new LambdaMatcher<>( - workspaceId -> workspaceId.getProjectIterationId() - .getIterationSlug().equals(iterationSlug))); + return argThat(new AssertionMatcher() { + @Override + public void assertion(WorkspaceId actual) + throws AssertionError { + assertThat(actual.getProjectIterationId().getIterationSlug()) + .isEqualTo(iterationSlug); + } + }); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/ActivateWorkspaceHandlerTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/ActivateWorkspaceHandlerTest.java index c311e74811..56eb3b879b 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/ActivateWorkspaceHandlerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/ActivateWorkspaceHandlerTest.java @@ -1,6 +1,6 @@ package org.zanata.webtrans.server.rpc; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; @@ -16,7 +16,6 @@ import net.customware.gwt.dispatch.server.ExecutionContext; import org.apache.deltaspike.core.api.common.DeltaSpike; -import org.hamcrest.Matchers; import org.jglue.cdiunit.InRequestScope; import org.jglue.cdiunit.deltaspike.SupportDeltaspikeCore; import org.junit.Before; @@ -192,32 +191,30 @@ public void testExecute() throws Exception { verify(translationWorkspace).addEditorClient(eq(HTTP_SESSION_ID), editorClientIdCaptor.capture(), eq(person.getId())); EditorClientId editorClientId = editorClientIdCaptor.getValue(); - assertThat(editorClientId.getHttpSessionId(), - Matchers.equalTo(HTTP_SESSION_ID)); + assertThat(editorClientId.getHttpSessionId()).isEqualTo(HTTP_SESSION_ID); verify(translationWorkspace).publish( enterWorkspaceEventCaptor.capture()); EnterWorkspace enterWorkspace = enterWorkspaceEventCaptor.getValue(); - assertThat(enterWorkspace.getPerson(), Matchers.equalTo(person)); - assertThat(enterWorkspace.getEditorClientId(), - Matchers.equalTo(editorClientId)); + assertThat(enterWorkspace.getPerson()).isEqualTo(person); + assertThat(enterWorkspace.getEditorClientId()) + .isEqualTo(editorClientId); Identity userIdentity = result.getIdentity(); - assertThat(userIdentity.getPerson(), Matchers.equalTo(person)); - assertThat(userIdentity.getEditorClientId(), - Matchers.equalTo(editorClientId)); + assertThat(userIdentity.getPerson()).isEqualTo(person); + assertThat(userIdentity.getEditorClientId()).isEqualTo(editorClientId); UserWorkspaceContext userWorkspaceContext = result.getUserWorkspaceContext(); assertThat(userWorkspaceContext.getWorkspaceRestrictions() - .isHasGlossaryUpdateAccess(), Matchers.equalTo(true)); + .isHasGlossaryUpdateAccess()).isTrue(); assertThat(userWorkspaceContext.getWorkspaceRestrictions() - .isProjectActive(), Matchers.equalTo(true)); + .isProjectActive()).isTrue(); assertThat(userWorkspaceContext.getWorkspaceRestrictions() - .isHasEditTranslationAccess(), Matchers.equalTo(true)); + .isHasEditTranslationAccess()).isTrue(); - assertThat(result.getStoredUserConfiguration(), - Matchers.sameInstance(optionsResult.getConfiguration())); + assertThat(result.getStoredUserConfiguration()) + .isSameAs(optionsResult.getConfiguration()); } @Test diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/AddReviewCommentHandlerTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/AddReviewCommentHandlerTest.java index 3d67473cc6..09205a4bf1 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/AddReviewCommentHandlerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/AddReviewCommentHandlerTest.java @@ -23,7 +23,6 @@ import org.jglue.cdiunit.InRequestScope; import org.zanata.ZanataTest; -import org.hamcrest.Matchers; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Answers; @@ -58,7 +57,7 @@ import javax.enterprise.inject.Produces; import javax.inject.Inject; -import static org.hamcrest.MatcherAssert.*; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.when; @@ -158,8 +157,8 @@ public void testExecute() throws Exception { inOrder.verify(textFlowTargetReviewCommentsDAO).flush(); inOrder.verify(workspace).publish(isA(AddReviewComment.class)); - assertThat(result.getComment().getId(), - Matchers.equalTo(new ReviewCommentId(1L))); + assertThat(result.getComment().getId()) + .isEqualTo(new ReviewCommentId(1L)); } @Test(expected = ActionException.class) diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetDocumentListHandlerTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetDocumentListHandlerTest.java index 9b5e842fe0..695fefcc5f 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetDocumentListHandlerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetDocumentListHandlerTest.java @@ -1,13 +1,12 @@ package org.zanata.webtrans.server.rpc; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.Arrays; import java.util.List; -import org.hamcrest.Matchers; import org.jglue.cdiunit.InRequestScope; import org.junit.Test; import org.junit.runner.RunWith; @@ -70,12 +69,11 @@ public void testExecute() throws Exception { GetDocumentListResult result = handler.execute(action, null); verify(identity).checkLoggedIn(); - assertThat(result.getDocuments(), Matchers.hasSize(1)); + assertThat(result.getDocuments()).hasSize(1); DocumentInfo documentInfo = result.getDocuments().get(0); - assertThat(documentInfo.getId(), - Matchers.equalTo(new DocumentId(new Long(1), ""))); - assertThat(documentInfo.getPath(), Matchers.equalTo("/dot/")); - assertThat(documentInfo.getName(), Matchers.equalTo("a.po")); + assertThat(documentInfo.getId()).isEqualTo(new DocumentId(new Long(1), "")); + assertThat(documentInfo.getPath()).isEqualTo("/dot/"); + assertThat(documentInfo.getName()).isEqualTo("a.po"); } @Test @@ -91,7 +89,7 @@ public void testExecuteWithFilter() throws Exception { GetDocumentListResult result = handler.execute(action, null); - assertThat(result.getDocuments(), Matchers.hasSize(1)); + assertThat(result.getDocuments()).hasSize(1); } private HDocument hDocument(long id) { diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetGlossaryDetailsHandlerTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetGlossaryDetailsHandlerTest.java index ce2ff4c33a..b65e3faba9 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetGlossaryDetailsHandlerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetGlossaryDetailsHandlerTest.java @@ -3,15 +3,12 @@ import java.util.ArrayList; import java.util.Date; -import org.hamcrest.Matchers; import org.jglue.cdiunit.InRequestScope; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.zanata.ZanataTest; import org.zanata.common.LocaleId; -import org.zanata.dao.GlossaryDAO; -import org.zanata.exception.ZanataServiceException; import org.zanata.model.Glossary; import org.zanata.model.HGlossaryEntry; import org.zanata.model.HGlossaryTerm; @@ -20,23 +17,18 @@ import org.zanata.rest.service.GlossaryService; import org.zanata.security.ZanataIdentity; import org.zanata.service.GlossarySearchService; -import org.zanata.service.LocaleService; import org.zanata.test.CdiUnitRunner; -import org.zanata.util.UrlUtil; import org.zanata.webtrans.shared.model.GlossaryDetails; -import org.zanata.webtrans.shared.model.ProjectIterationId; import org.zanata.webtrans.shared.model.WorkspaceId; import org.zanata.webtrans.shared.rpc.GetGlossaryDetailsAction; import org.zanata.webtrans.shared.rpc.GetGlossaryDetailsResult; import com.google.common.collect.Lists; -import net.customware.gwt.dispatch.shared.ActionException; - import javax.enterprise.inject.Any; import javax.enterprise.inject.Produces; import javax.inject.Inject; -import static org.hamcrest.MatcherAssert.*; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -95,7 +87,7 @@ public void testExecute() throws Exception { GetGlossaryDetailsResult result = handler.execute(action, null); verify(identity).checkLoggedIn(); - assertThat(result.getGlossaryDetails(), Matchers.is(details)); + assertThat(result.getGlossaryDetails()).isEqualTo(details); } @Test diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetGlossaryHandlerJpaTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetGlossaryHandlerJpaTest.java index c72b264217..120567a58e 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetGlossaryHandlerJpaTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetGlossaryHandlerJpaTest.java @@ -3,11 +3,9 @@ import java.util.ArrayList; import java.util.List; import org.dbunit.operation.DatabaseOperation; -import org.hamcrest.Matchers; import org.hibernate.Session; import org.hibernate.search.jpa.FullTextEntityManager; import org.jglue.cdiunit.InRequestScope; -import org.jglue.cdiunit.ProducesAlternative; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -21,7 +19,6 @@ import org.zanata.model.HLocale; import org.zanata.rest.service.ProjectService; import org.zanata.security.ZanataIdentity; -import org.zanata.service.GlossarySearchService; import org.zanata.service.LocaleService; import org.zanata.service.impl.GlossarySearchServiceImpl; import org.zanata.test.CdiUnitRunner; @@ -30,15 +27,12 @@ import org.zanata.webtrans.shared.model.GlossaryResultItem; import org.zanata.webtrans.shared.model.ProjectIterationId; import org.zanata.webtrans.shared.rpc.GetGlossary; -import org.zanata.webtrans.shared.rpc.GetGlossaryResult; import org.zanata.webtrans.shared.rpc.HasSearchType; import com.google.common.collect.Lists; -import javax.enterprise.inject.Any; -import javax.enterprise.inject.Default; import javax.enterprise.inject.Produces; -import javax.inject.Inject; import javax.persistence.EntityManager; -import static org.hamcrest.MatcherAssert.*; + +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; @@ -138,14 +132,10 @@ public void canGetGlossary() throws Exception { log.info("************** {} second", duration); // Then: - assertThat(result, Matchers.hasSize(2)); - assertThat(result.get(0).getSource(), - Matchers.equalTo("Planet Fedora")); - assertThat(result.get(0).getTarget(), - Matchers.equalTo("Fedora 博客聚集")); - assertThat(result.get(1).getSource(), - Matchers.equalTo("Fedora Artwork")); - assertThat(result.get(1).getTarget(), - Matchers.equalTo("Fedora 美工")); + assertThat(result).hasSize(2); + assertThat(result.get(0).getSource()).isEqualTo("Planet Fedora"); + assertThat(result.get(0).getTarget()).isEqualTo("Fedora 博客聚集"); + assertThat(result.get(1).getSource()).isEqualTo("Fedora Artwork"); + assertThat(result.get(1).getTarget()).isEqualTo("Fedora 美工"); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetProjectTransUnitListsHandlerTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetProjectTransUnitListsHandlerTest.java index 1ab0193f07..234c6c4c0b 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetProjectTransUnitListsHandlerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetProjectTransUnitListsHandlerTest.java @@ -1,7 +1,6 @@ package org.zanata.webtrans.server.rpc; import java.util.List; -import org.hamcrest.Matchers; import org.jglue.cdiunit.InRequestScope; import org.junit.Before; import org.junit.Test; @@ -31,7 +30,8 @@ import javax.enterprise.inject.Any; import javax.enterprise.inject.Produces; import javax.inject.Inject; -import static org.hamcrest.MatcherAssert.*; + +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; @@ -127,7 +127,7 @@ public void emptySearchTermWillReturnEmpty() throws Exception { action.setWorkspaceId(workspaceId); GetProjectTransUnitListsResult result = handler.execute(action, null); verify(identity).checkLoggedIn(); - assertThat(result.getDocumentIds(), Matchers. emptyIterable()); + assertThat(result.getDocumentIds()).isEmpty(); verifyZeroInteractions(textFlowSearchServiceImpl); } @@ -144,12 +144,12 @@ public void searchWithNoLeadingAndTrailingWhiteSpace() throws Exception { GetProjectTransUnitListsResult result = handler.execute(action, null); verify(identity).checkLoggedIn(); FilterConstraints constraints = constraintCaptor.getValue(); - assertThat(constraints.isSearchInSource(), Matchers.equalTo(true)); - assertThat(constraints.isSearchInTarget(), Matchers.equalTo(true)); - assertThat(constraints.isCaseSensitive(), Matchers.equalTo(true)); - assertThat(result.getDocumentIds(), Matchers.contains(DOC_ID)); - assertThat(TestFixture.asIds(result.getUnits(DOC_ID)), - Matchers.contains(1, 2, 3, 4)); + assertThat(constraints.isSearchInSource()).isTrue(); + assertThat(constraints.isSearchInTarget()).isTrue(); + assertThat(constraints.isCaseSensitive()).isTrue(); + assertThat(result.getDocumentIds()).contains(DOC_ID); + assertThat(TestFixture.asIds(result.getUnits(DOC_ID))) + .contains(1, 2, 3, 4); } @Test @@ -165,12 +165,11 @@ public void searchWithLeadingWhiteSpace() throws Exception { GetProjectTransUnitListsResult result = handler.execute(action, null); verify(identity).checkLoggedIn(); FilterConstraints constraints = constraintCaptor.getValue(); - assertThat(constraints.isSearchInSource(), Matchers.equalTo(true)); - assertThat(constraints.isSearchInTarget(), Matchers.equalTo(true)); - assertThat(constraints.isCaseSensitive(), Matchers.equalTo(true)); - assertThat(result.getDocumentIds(), Matchers.contains(DOC_ID)); - assertThat(TestFixture.asIds(result.getUnits(DOC_ID)), - Matchers.contains(2, 3)); + assertThat(constraints.isSearchInSource()).isTrue(); + assertThat(constraints.isSearchInTarget()).isTrue(); + assertThat(constraints.isCaseSensitive()).isTrue(); + assertThat(result.getDocumentIds()).contains(DOC_ID); + assertThat(TestFixture.asIds(result.getUnits(DOC_ID))).contains(2, 3); } @Test @@ -186,12 +185,11 @@ public void searchWithTrailingWhiteSpace() throws Exception { GetProjectTransUnitListsResult result = handler.execute(action, null); verify(identity).checkLoggedIn(); FilterConstraints constraints = constraintCaptor.getValue(); - assertThat(constraints.isSearchInSource(), Matchers.equalTo(true)); - assertThat(constraints.isSearchInTarget(), Matchers.equalTo(false)); - assertThat(constraints.isCaseSensitive(), Matchers.equalTo(false)); - assertThat(result.getDocumentIds(), Matchers.contains(DOC_ID)); - assertThat(TestFixture.asIds(result.getUnits(DOC_ID)), - Matchers.contains(1, 3)); + assertThat(constraints.isSearchInSource()).isTrue(); + assertThat(constraints.isSearchInTarget()).isFalse(); + assertThat(constraints.isCaseSensitive()).isFalse(); + assertThat(result.getDocumentIds()).contains(DOC_ID); + assertThat(TestFixture.asIds(result.getUnits(DOC_ID))).contains(1, 3); } @Test diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTargetForLocaleHandlerTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTargetForLocaleHandlerTest.java index 8f96a542c3..2fbde606d1 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTargetForLocaleHandlerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTargetForLocaleHandlerTest.java @@ -1,10 +1,9 @@ package org.zanata.webtrans.server.rpc; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import org.dbunit.operation.DatabaseOperation; -import org.hamcrest.Matchers; import org.jglue.cdiunit.InRequestScope; import org.junit.Before; import org.junit.Test; @@ -77,8 +76,8 @@ public void testExecute() throws Exception { .thenReturn(getEm().find(HTextFlowTarget.class, 61L)); GetTargetForLocaleResult result = handler.execute(action, null); verify(identity).checkLoggedIn(); - assertThat(result.getTarget().getContent(), Matchers.equalTo( - getEm().find(HTextFlowTarget.class, 61L).getContents().get(0))); + assertThat(result.getTarget().getContent()).isEqualTo( + getEm().find(HTextFlowTarget.class, 61L).getContents().get(0)); } @Test @@ -88,7 +87,7 @@ public void testExecuteWhenTargetLangDoesNotExsist() throws Exception { jaHLocale.getLocaleId())).thenReturn(null); GetTargetForLocaleResult result = handler.execute(action, null); verify(identity).checkLoggedIn(); - assertThat(result.getTarget(), Matchers.equalTo(null)); + assertThat(result.getTarget()).isNull(); } @Test diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTransMemoryDetailsHandlerTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTransMemoryDetailsHandlerTest.java index c303773ebc..1c427a14c2 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTransMemoryDetailsHandlerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTransMemoryDetailsHandlerTest.java @@ -2,7 +2,6 @@ import java.util.Date; -import org.hamcrest.Matchers; import org.hibernate.search.jpa.FullTextEntityManager; import org.jglue.cdiunit.AdditionalClasses; import org.jglue.cdiunit.InRequestScope; @@ -40,7 +39,7 @@ import javax.enterprise.inject.Produces; import javax.inject.Inject; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -126,7 +125,7 @@ public void testExecute() throws Exception { TransMemoryDetailsList result = handler.execute(action, null); verify(identity).checkLoggedIn(); - assertThat(result.getItems(), Matchers.hasSize(2)); + assertThat(result.getItems()).hasSize(2); } @Test(expected = ActionException.class) diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTransMemoryHandlerTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTransMemoryHandlerTest.java index 60f091d407..7c5b79f5b9 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTransMemoryHandlerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTransMemoryHandlerTest.java @@ -3,7 +3,6 @@ import java.util.List; import org.apache.lucene.queryparser.classic.QueryParser; -import org.hamcrest.Matchers; import org.jglue.cdiunit.InRequestScope; import org.junit.Test; import org.junit.runner.RunWith; @@ -24,8 +23,7 @@ import javax.enterprise.inject.Produces; import javax.inject.Inject; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -66,7 +64,7 @@ public void testExecute() throws Exception { // Then: verify(identity).checkLoggedIn(); - assertThat(result.getMemories(), Matchers.hasSize(0)); + assertThat(result.getMemories()).hasSize(0); } @Test @@ -79,11 +77,13 @@ public void testRollback() throws Exception { // http://lucene.apache.org/java/2_4_1/queryparsersyntax.html#Escaping%20Special%20Characters @Test public void testLuceneQuery() { - assertThat(QueryParser.escape("plaintext"), is("plaintext")); + assertThat(QueryParser.escape("plaintext")).isEqualTo("plaintext"); assertThat( QueryParser.escape("lucene special characters + - && || ! ( ) " - + "{ } [ ] ^ \" ~ * ? : \\ plus % _"), - is("lucene special characters \\+ \\- \\&\\& \\|\\| \\! \\( \\) " - + "\\{ \\} \\[ \\] \\^ \\\" \\~ \\* \\? \\: \\\\ plus % _")); + + "{ } [ ] ^ \" ~ * ? : \\ plus % _")) + .isEqualTo( + "lucene special characters \\+ \\- \\&\\& \\|\\| \\! \\( \\) " + + + "\\{ \\} \\[ \\] \\^ \\\" \\~ \\* \\? \\: \\\\ plus % _"); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTransUnitListHandlerTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTransUnitListHandlerTest.java index 5a15e96111..a5f0335fd2 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTransUnitListHandlerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTransUnitListHandlerTest.java @@ -1,6 +1,6 @@ package org.zanata.webtrans.server.rpc; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -9,7 +9,6 @@ import java.util.Map; import com.google.common.cache.CacheLoader; import org.dbunit.operation.DatabaseOperation; -import org.hamcrest.Matchers; import org.hibernate.Session; import org.hibernate.search.FullTextSession; import org.hibernate.search.jpa.FullTextEntityManager; @@ -152,10 +151,10 @@ public void testExecuteToGetAll() throws Exception { log.info("********** duration :{} second", (System.nanoTime() - startTime) / 1.0E9); log.info("result: {}", result); - assertThat(result.getDocumentId(), Matchers.equalTo(document.getId())); - assertThat(result.getGotoRow(), Matchers.equalTo(0)); - assertThat(TestFixture.asIds(result.getUnits()), - Matchers.contains(1, 2, 3, 4, 5)); + assertThat(result.getDocumentId()).isEqualTo(document.getId()); + assertThat(result.getGotoRow()).isEqualTo(0); + assertThat(TestFixture.asIds(result.getUnits())) + .contains(1, 2, 3, 4, 5); } @Test @@ -167,10 +166,10 @@ public void testExecuteWithStatusFilterOnly() throws Exception { prepareActionAndMockLocaleService(action); GetTransUnitListResult result = handler.execute(action, null); log.info("result: {}", result); - assertThat(result.getDocumentId(), Matchers.equalTo(document.getId())); - assertThat(result.getGotoRow(), Matchers.equalTo(0)); - assertThat(TestFixture.asIds(result.getUnits()), - Matchers.contains(3, 5, 6, 7, 8)); + assertThat(result.getDocumentId()).isEqualTo(document.getId()); + assertThat(result.getGotoRow()).isEqualTo(0); + assertThat(TestFixture.asIds(result.getUnits())) + .contains(3, 5, 6, 7, 8); } @Test @@ -182,10 +181,10 @@ public void testExecuteWithHasErrorFilterOnly() throws Exception { prepareActionAndMockLocaleService(action); GetTransUnitListResult result = handler.execute(action, null); log.info("result: {}", result); - assertThat(result.getDocumentId(), Matchers.equalTo(document.getId())); - assertThat(result.getGotoRow(), Matchers.equalTo(0)); - assertThat(TestFixture.asIds(result.getUnits()), - Matchers.contains(1, 2, 3, 4, 5)); + assertThat(result.getDocumentId()).isEqualTo(document.getId()); + assertThat(result.getGotoRow()).isEqualTo(0); + assertThat(TestFixture.asIds(result.getUnits())) + .contains(1, 2, 3, 4, 5); } @Test @@ -202,10 +201,10 @@ public void testExecuteWithSearchOnly() throws Exception { GetTransUnitListResult result = handler.execute(action, null); // Then: log.info("result: {}", result); - assertThat(result.getDocumentId(), Matchers.equalTo(document.getId())); - assertThat(result.getGotoRow(), Matchers.equalTo(0)); - assertThat(TestFixture.asIds(result.getUnits()), - Matchers.contains(2, 3, 4, 5, 6, 8)); + assertThat(result.getDocumentId()).isEqualTo(document.getId()); + assertThat(result.getGotoRow()).isEqualTo(0); + assertThat(TestFixture.asIds(result.getUnits())) + .contains(2, 3, 4, 5, 6, 8); } @Test @@ -221,10 +220,10 @@ public void testExecuteWithSearchAndStatusFilter() throws Exception { GetTransUnitListResult result = handler.execute(action, null); // Then: log.info("result: {}", result); - assertThat(result.getDocumentId(), Matchers.equalTo(document.getId())); - assertThat(result.getGotoRow(), Matchers.equalTo(0)); - assertThat(TestFixture.asIds(result.getUnits()), - Matchers.contains(3, 5, 6, 8)); + assertThat(result.getDocumentId()).isEqualTo(document.getId()); + assertThat(result.getGotoRow()).isEqualTo(0); + assertThat(TestFixture.asIds(result.getUnits())) + .contains(3, 5, 6, 8); } @Test @@ -239,10 +238,10 @@ public void testExecuteWithSearchAndStatusFilter2() throws Exception { GetTransUnitListResult result = handler.execute(action, null); // Then: log.info("result: {}", result); - assertThat(result.getDocumentId(), Matchers.equalTo(document.getId())); - assertThat(result.getGotoRow(), Matchers.equalTo(0)); - assertThat(TestFixture.asIds(result.getUnits()), - Matchers.contains(3, 5, 6, 8)); + assertThat(result.getDocumentId()).isEqualTo(document.getId()); + assertThat(result.getGotoRow()).isEqualTo(0); + assertThat(TestFixture.asIds(result.getUnits())) + .contains(3, 5, 6, 8); } @Test @@ -258,7 +257,7 @@ public void testExecuteWithPageSize() throws Exception { prepareActionAndMockLocaleService(action); // When: GetTransUnitListResult result = handler.execute(action, null); - assertThat(result.getTargetPageIndex(), Matchers.equalTo(3)); + assertThat(result.getTargetPageIndex()).isEqualTo(3); } /** @@ -293,6 +292,6 @@ public void testExecuteWithPageSizeNeedReload() throws Exception { .thenReturn(navigationResult); when(navigationResult.getIdIndexList()).thenReturn(idIndexList); GetTransUnitListResult result = handler.execute(action, null); - assertThat(result.getTargetPageIndex(), Matchers.equalTo(2)); + assertThat(result.getTargetPageIndex()).isEqualTo(2); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTranslationHistoryHandlerTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTranslationHistoryHandlerTest.java index 672b997256..03df7f2a98 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTranslationHistoryHandlerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTranslationHistoryHandlerTest.java @@ -10,7 +10,6 @@ import javax.inject.Inject; import javax.validation.constraints.NotNull; -import org.hamcrest.Matchers; import org.jglue.cdiunit.InRequestScope; import org.junit.Before; import org.junit.Test; @@ -37,7 +36,6 @@ import org.zanata.test.CdiUnitRunner; import org.zanata.webtrans.shared.model.ProjectIterationId; import org.zanata.webtrans.shared.model.ReviewComment; -import org.zanata.webtrans.shared.model.TransHistoryItem; import org.zanata.webtrans.shared.model.TransUnitId; import org.zanata.webtrans.shared.model.WorkspaceId; import org.zanata.webtrans.shared.rpc.GetTranslationHistoryAction; @@ -48,7 +46,8 @@ import net.customware.gwt.dispatch.server.ExecutionContext; import net.customware.gwt.dispatch.shared.ActionException; -import static org.hamcrest.MatcherAssert.assertThat; + +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -117,17 +116,15 @@ public void canGetEmptyHistoryForTextFlowWithNoTranslation() HTextFlow hTextFlow = createHTextFlow(); when(textFlowDAO.findById(transUnitId.getId(), false)).thenReturn( hTextFlow); - assertThat(hTextFlow.getTargets().values(), - Matchers. emptyIterable()); + assertThat(hTextFlow.getTargets().values()).isEmpty(); // When: GetTranslationHistoryResult result = handler.execute(action, executionContext); // Then: - assertThat(result.getHistoryItems(), - Matchers. empty()); - assertThat(result.getLatest(), Matchers.nullValue()); + assertThat(result.getHistoryItems()).isEmpty(); + assertThat(result.getLatest()).isNull(); } @Test @@ -165,13 +162,12 @@ public void canGetHistoryAndCurrentTranslation() throws ActionException { handler.execute(action, executionContext); // Then: - assertThat(result.getHistoryItems(), Matchers.hasSize(2)); - assertThat(result.getLatest().getVersionNum(), - Matchers.equalTo(currentTranslation.getVersionNum().toString())); - assertThat(result.getLatest().getContents(), - Matchers.equalTo(currentTranslation.getContents())); - assertThat(result.getLatest().getModifiedBy(), - Matchers.equalTo("admin")); + assertThat(result.getHistoryItems()).hasSize(2); + assertThat(result.getLatest().getVersionNum()) + .isEqualTo(currentTranslation.getVersionNum().toString()); + assertThat(result.getLatest().getContents()) + .isEqualTo(currentTranslation.getContents()); + assertThat(result.getLatest().getModifiedBy()).isEqualTo("admin"); } @Test @@ -203,13 +199,12 @@ public void canGetCurrentTranslationWithoutLastModifiedBy() handler.execute(action, executionContext); // Then: - assertThat(result.getHistoryItems(), - Matchers. emptyIterable()); - assertThat(result.getLatest().getVersionNum(), - Matchers.equalTo(currentTranslation.getVersionNum().toString())); - assertThat(result.getLatest().getContents(), - Matchers.equalTo(currentTranslation.getContents())); - assertThat(result.getLatest().getModifiedBy(), Matchers.equalTo("")); + assertThat(result.getHistoryItems()).isEmpty(); + assertThat(result.getLatest().getVersionNum()) + .isEqualTo(currentTranslation.getVersionNum().toString()); + assertThat(result.getLatest().getContents()) + .isEqualTo(currentTranslation.getContents()); + assertThat(result.getLatest().getModifiedBy()).isEqualTo(""); } @Test @@ -240,13 +235,12 @@ public void canStripObsoleteTargetContentBasedOnCurrentNPlural() handler.execute(action, executionContext); // Then: the contents we get back is consistent against number of plural - assertThat(result.getHistoryItems(), - Matchers. emptyIterable()); - assertThat(result.getLatest().getVersionNum(), - Matchers.equalTo(currentTranslation.getVersionNum().toString())); - assertThat(result.getLatest().getContents(), - Matchers.contains(currentTranslation.getContents().get(0))); - assertThat(result.getLatest().getModifiedBy(), Matchers.equalTo("")); + assertThat(result.getHistoryItems()).isEmpty(); + assertThat(result.getLatest().getVersionNum()) + .isEqualTo(currentTranslation.getVersionNum().toString()); + assertThat(result.getLatest().getContents()) + .contains(currentTranslation.getContents().get(0)); + assertThat(result.getLatest().getModifiedBy()).isEqualTo(""); } private static HTextFlow createHTextFlow() { @@ -296,10 +290,9 @@ public void canGetReviewComments() { List result = handler.getReviewComments(action); - assertThat(result, Matchers.hasSize(2)); - assertThat(result.get(0).getComment(), Matchers.equalTo("a comment")); - assertThat(result.get(1).getComment(), - Matchers.equalTo("another comment")); + assertThat(result).hasSize(2); + assertThat(result.get(0).getComment()).isEqualTo("a comment"); + assertThat(result.get(1).getComment()).isEqualTo("another comment"); } private static HTextFlowTargetReviewComment makeCommentEntity( diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTranslatorListHandlerTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTranslatorListHandlerTest.java index a16d04d335..83d9edd061 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTranslatorListHandlerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/GetTranslatorListHandlerTest.java @@ -2,7 +2,6 @@ import java.util.Map; -import org.hamcrest.Matchers; import org.jglue.cdiunit.InRequestScope; import org.junit.Before; import org.junit.Test; @@ -31,7 +30,7 @@ import javax.enterprise.inject.Produces; import javax.inject.Inject; -import static org.hamcrest.MatcherAssert.*; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -80,14 +79,14 @@ public void testExecute() throws Exception { GetTranslatorListResult result = handler.execute(action, null); verify(identity).checkLoggedIn(); - assertThat(result.getSize(), Matchers.equalTo(1)); + assertThat(result.getSize()).isEqualTo(1); Map translatorList = result.getTranslatorList(); - assertThat(translatorList, Matchers.hasKey(editorClientId)); + assertThat(translatorList).containsKey(editorClientId); assertThat(translatorList.get(editorClientId).getPerson() - .getAvatarUrl(), Matchers.equalTo("gravatarUrl")); - assertThat(translatorList.get(editorClientId).getPerson().getName(), - Matchers.equalTo("pahuang")); + .getAvatarUrl()).isEqualTo("gravatarUrl"); + assertThat(translatorList.get(editorClientId).getPerson().getName()) + .isEqualTo("pahuang"); } private static HAccount createHAccount(String email, String name) { diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/LoadOptionsHandlerTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/LoadOptionsHandlerTest.java index 37eb4f89c8..dcfa56ac5f 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/LoadOptionsHandlerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/LoadOptionsHandlerTest.java @@ -1,12 +1,9 @@ package org.zanata.webtrans.server.rpc; -import static org.hamcrest.MatcherAssert.assertThat; - import java.util.HashMap; import java.util.List; import org.dbunit.operation.DatabaseOperation; -import org.hamcrest.Matchers; import org.hibernate.Session; import org.jglue.cdiunit.InRequestScope; import org.junit.Test; @@ -28,6 +25,8 @@ import javax.inject.Inject; import javax.persistence.EntityManager; +import static org.assertj.core.api.Assertions.assertThat; + /** * @author Patrick Huang pahuang@redhat.com @@ -108,12 +107,9 @@ public void testExecuteWithOptionsInDatabase() throws Exception { LoadOptionsResult result = handler.execute(new LoadOptionsAction(null), null); - assertThat(result.getConfiguration().isShowError(), - Matchers.equalTo(true)); - assertThat(result.getConfiguration().getNavOption(), - Matchers.equalTo(NavOption.FUZZY_UNTRANSLATED)); - assertThat(result.getConfiguration().isDisplayButtons(), - Matchers.equalTo(true)); + assertThat(result.getConfiguration().isShowError()).isTrue(); + assertThat(result.getConfiguration().getNavOption()).isEqualTo(NavOption.FUZZY_UNTRANSLATED); + assertThat(result.getConfiguration().isDisplayButtons()).isTrue(); } @Test @@ -126,18 +122,15 @@ public void testExecuteWithNoOptionsInDatabase() throws Exception { List options = getEm().createQuery("from HAccountOption", HAccountOption.class) .getResultList(); - assertThat(options, Matchers. empty()); + assertThat(options).isEmpty(); LoadOptionsResult result = handler.execute(new LoadOptionsAction(null), null); // then: we get back default values - assertThat(result.getConfiguration().isShowError(), - Matchers.equalTo(false)); - assertThat(result.getConfiguration().getNavOption(), - Matchers.equalTo(NavOption.FUZZY_UNTRANSLATED)); - assertThat(result.getConfiguration().getEditorPageSize(), - Matchers.equalTo(25)); + assertThat(result.getConfiguration().isShowError()).isFalse(); + assertThat(result.getConfiguration().getNavOption()).isEqualTo(NavOption.FUZZY_UNTRANSLATED); + assertThat(result.getConfiguration().getEditorPageSize()).isEqualTo(25); } @Test diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/PreviewReplaceTextHandlerTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/PreviewReplaceTextHandlerTest.java index b7d729340c..3b71e2ec56 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/PreviewReplaceTextHandlerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/PreviewReplaceTextHandlerTest.java @@ -1,6 +1,5 @@ package org.zanata.webtrans.server.rpc; -import org.hamcrest.Matchers; import org.jglue.cdiunit.InRequestScope; import org.junit.Test; import org.junit.runner.RunWith; @@ -22,7 +21,7 @@ import javax.enterprise.inject.Produces; import javax.inject.Inject; -import static org.hamcrest.MatcherAssert.*; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; /** @@ -48,12 +47,12 @@ public void testExecute() throws Exception { PreviewReplaceTextResult result = handler.execute(action, null); verify(identity).checkLoggedIn(); - assertThat(result.getPreviews(), Matchers.hasSize(1)); + assertThat(result.getPreviews()).hasSize(1); TransUnitUpdatePreview preview = result.getPreviews().get(0); - assertThat(preview.getId(), Matchers.equalTo(transUnit.getId())); - assertThat(preview.getState(), - Matchers.equalTo(ContentState.NeedReview)); - assertThat(preview.getContents(), Matchers.contains("replace")); + assertThat(preview.getId()).isEqualTo(transUnit.getId()); + assertThat(preview.getState()) + .isEqualTo(ContentState.NeedReview); + assertThat(preview.getContents()).contains("replace"); } @Test(expected = ActionException.class) diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/PublishWorkspaceChatHandlerTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/PublishWorkspaceChatHandlerTest.java index 49671763d9..87acee3d79 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/PublishWorkspaceChatHandlerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/PublishWorkspaceChatHandlerTest.java @@ -1,6 +1,5 @@ package org.zanata.webtrans.server.rpc; -import org.hamcrest.Matchers; import org.jglue.cdiunit.InRequestScope; import org.junit.Test; import org.junit.runner.RunWith; @@ -22,7 +21,7 @@ import javax.enterprise.inject.Produces; import javax.inject.Inject; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -59,10 +58,10 @@ public void testExecute() throws Exception { verify(identity).checkLoggedIn(); verify(translationWorkspace).publish(eventCaptor.capture()); PublishWorkspaceChat chat = eventCaptor.getValue(); - assertThat(chat.getPersonId(), Matchers.equalTo("admin")); - assertThat(chat.getMsg(), Matchers.equalTo("hi")); - assertThat(chat.getMessageType(), - Matchers.equalTo(HasWorkspaceChatData.MESSAGE_TYPE.USER_MSG)); + assertThat(chat.getPersonId()).isEqualTo("admin"); + assertThat(chat.getMsg()).isEqualTo("hi"); + assertThat(chat.getMessageType()) + .isEqualTo(HasWorkspaceChatData.MESSAGE_TYPE.USER_MSG); } @Test diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/RemoteLoggingHandlerTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/RemoteLoggingHandlerTest.java index df7c6aad96..fc085fa945 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/RemoteLoggingHandlerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/RemoteLoggingHandlerTest.java @@ -1,6 +1,5 @@ package org.zanata.webtrans.server.rpc; -import org.hamcrest.Matchers; import org.jglue.cdiunit.InRequestScope; import org.junit.Before; import org.junit.Test; @@ -17,7 +16,7 @@ import javax.enterprise.inject.Produces; import javax.inject.Inject; -import static org.hamcrest.MatcherAssert.*; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -57,7 +56,7 @@ public void testExecuteWithoutLoggedIn() throws Exception { NoOpResult result = handler.execute(new RemoteLoggingAction("blah"), null); - assertThat(result, Matchers.notNullValue()); + assertThat(result).isNotNull(); } @Test diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/ReplaceTextHandlerTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/ReplaceTextHandlerTest.java index 6a05a074f6..52a4c77064 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/ReplaceTextHandlerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/ReplaceTextHandlerTest.java @@ -22,8 +22,6 @@ import java.util.List; -import org.hamcrest.MatcherAssert; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -37,6 +35,8 @@ import net.customware.gwt.dispatch.server.ExecutionContext; import net.customware.gwt.dispatch.shared.ActionException; + +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; @@ -78,8 +78,8 @@ public void canReplaceTextCaseInsensitively() throws ActionException { verify(mockUpdateTransUnitHandler).execute(captor.capture(), eq(context)); List expectedList = Lists.newArrayList("123", "123", "123"); - MatcherAssert.assertThat(captor.getValue().getUpdateRequests().get(0) - .getNewContents(), Matchers.equalTo(expectedList)); + assertThat(captor.getValue().getUpdateRequests().get(0) + .getNewContents()).isEqualTo(expectedList); } @Test @@ -96,8 +96,8 @@ public void canReplaceTextCaseSensitively() throws ActionException { verify(mockUpdateTransUnitHandler).execute(captor.capture(), eq(context)); List expectedList = Lists.newArrayList("123", "AbC", "ABC"); - MatcherAssert.assertThat(captor.getValue().getUpdateRequests().get(0) - .getNewContents(), Matchers.equalTo(expectedList)); + assertThat(captor.getValue().getUpdateRequests().get(0) + .getNewContents()).isEqualTo(expectedList); } @Test(expected = ActionException.class) diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/RevertTransUnitUpdatesHandlerTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/RevertTransUnitUpdatesHandlerTest.java index 153f0d25d8..5f0d0469a2 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/RevertTransUnitUpdatesHandlerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/RevertTransUnitUpdatesHandlerTest.java @@ -1,13 +1,12 @@ package org.zanata.webtrans.server.rpc; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import java.util.List; -import org.hamcrest.Matchers; import org.jglue.cdiunit.AdditionalClasses; import org.jglue.cdiunit.InRequestScope; import org.jglue.cdiunit.deltaspike.SupportDeltaspikeCore; @@ -88,9 +87,9 @@ public void testExecute() throws Exception { UpdateTransUnitResult result = handler.execute(action, null); - assertThat(result.getUpdateInfoList(), Matchers.hasSize(1)); - assertThat(result.getUpdateInfoList().get(0).getPreviousState(), - Matchers.equalTo(ContentState.NeedReview)); + assertThat(result.getUpdateInfoList()).hasSize(1); + assertThat(result.getUpdateInfoList().get(0).getPreviousState()) + .isEqualTo(ContentState.NeedReview); } private static TranslationService.TranslationResult mockTranslationResult( diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/SaveOptionsHandlerTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/SaveOptionsHandlerTest.java index a6f01484f8..2c899404c1 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/SaveOptionsHandlerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/SaveOptionsHandlerTest.java @@ -1,11 +1,9 @@ package org.zanata.webtrans.server.rpc; -import static org.hamcrest.MatcherAssert.assertThat; import java.util.HashMap; import java.util.List; import java.util.Map; import org.dbunit.operation.DatabaseOperation; -import org.hamcrest.Matchers; import org.hibernate.Session; import org.jglue.cdiunit.InRequestScope; import org.junit.runner.RunWith; @@ -23,6 +21,8 @@ import javax.inject.Inject; import javax.persistence.EntityManager; +import static org.assertj.core.api.Assertions.assertThat; + /** * @author Patrick Huang * pahuang@redhat.com @@ -73,23 +73,21 @@ public void testExecute() throws Exception { configMap.put(UserOptions.EnterSavesApproved, Boolean.toString(true)); SaveOptionsAction action = new SaveOptionsAction(configMap); SaveOptionsResult result = handler.execute(action, null); - assertThat(result.isSuccess(), Matchers.equalTo(true)); + assertThat(result.isSuccess()).isTrue(); List accountOptions = getEm().createQuery("from HAccountOption", HAccountOption.class) .getResultList(); - assertThat(accountOptions, Matchers.hasSize(configMap.size())); + assertThat(accountOptions).hasSize(configMap.size()); Map editorOptions = getAuthenticatedAcount(getEm()).getEditorOptions(); - assertThat(editorOptions.values(), - Matchers.containsInAnyOrder(accountOptions.toArray())); + assertThat(editorOptions.values()).containsAll(accountOptions); handler.execute(action, null); // save again should override previous // value accountOptions = getEm().createQuery("from HAccountOption", HAccountOption.class) .getResultList(); - assertThat(accountOptions, Matchers.hasSize(configMap.size())); - assertThat(editorOptions.values(), - Matchers.containsInAnyOrder(accountOptions.toArray())); + assertThat(accountOptions).hasSize(configMap.size()); + assertThat(editorOptions.values()).containsAll(accountOptions); } @Test diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/TransUnitEditHandlerTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/TransUnitEditHandlerTest.java index 6c56dc489e..2912ecc4f4 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/TransUnitEditHandlerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/server/rpc/TransUnitEditHandlerTest.java @@ -1,6 +1,5 @@ package org.zanata.webtrans.server.rpc; -import org.hamcrest.Matchers; import org.jglue.cdiunit.InRequestScope; import org.junit.Test; import org.junit.runner.RunWith; @@ -24,7 +23,7 @@ import javax.enterprise.inject.Produces; import javax.inject.Inject; -import static org.hamcrest.MatcherAssert.*; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -66,11 +65,10 @@ public void testExecute() throws Exception { selectedTransUnit.getId()); verify(translationWorkspace).publish(eventCaptor.capture()); TransUnitEdit transUnitEdit = eventCaptor.getValue(); - assertThat(transUnitEdit.getEditorClientId(), - Matchers.sameInstance(editorClientId)); - assertThat(transUnitEdit.getPerson(), Matchers.sameInstance(person)); - assertThat(transUnitEdit.getSelectedTransUnitId(), - Matchers.sameInstance(selectedTransUnit.getId())); + assertThat(transUnitEdit.getEditorClientId()).isSameAs(editorClientId); + assertThat(transUnitEdit.getPerson()).isSameAs(person); + assertThat(transUnitEdit.getSelectedTransUnitId()) + .isSameAs(selectedTransUnit.getId()); } @Test diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/shared/util/StringNotEmptyPredicateTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/shared/util/StringNotEmptyPredicateTest.java index cc9e419a11..37ac8f8094 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/shared/util/StringNotEmptyPredicateTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/shared/util/StringNotEmptyPredicateTest.java @@ -1,9 +1,8 @@ package org.zanata.webtrans.shared.util; -import org.hamcrest.Matchers; import org.junit.Test; -import static org.hamcrest.MatcherAssert.*; +import static org.assertj.core.api.Assertions.assertThat; import static org.zanata.webtrans.shared.util.StringNotEmptyPredicate.INSTANCE; /** @@ -13,9 +12,9 @@ public class StringNotEmptyPredicateTest { @Test public void testApply() throws Exception { - assertThat(INSTANCE.apply(""), Matchers.equalTo(false)); - assertThat(INSTANCE.apply(null), Matchers.equalTo(false)); - assertThat(INSTANCE.apply(" "), Matchers.equalTo(true)); - assertThat(INSTANCE.apply("a"), Matchers.equalTo(true)); + assertThat(INSTANCE.apply("")).isFalse(); + assertThat(INSTANCE.apply(null)).isFalse(); + assertThat(INSTANCE.apply(" ")).isTrue(); + assertThat(INSTANCE.apply("a")).isTrue(); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/HtmlXmlTagValidationTests.java b/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/HtmlXmlTagValidationTests.java index 022eeba309..be48c4da52 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/HtmlXmlTagValidationTests.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/HtmlXmlTagValidationTests.java @@ -20,10 +20,6 @@ */ package org.zanata.webtrans.shared.validation; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.hasItem; -import static org.hamcrest.Matchers.is; - import java.io.IOException; import java.util.Arrays; import java.util.List; @@ -36,6 +32,8 @@ import org.zanata.webtrans.shared.model.ValidationId; import org.zanata.webtrans.shared.validation.action.HtmlXmlTagValidation; +import static org.assertj.core.api.Assertions.assertThat; + /** * * @author Alex Eng aeng@redhat.com @@ -59,7 +57,7 @@ public void init() throws IOException { @Test public void idIsSet() { - assertThat(htmlXmlTagValidation.getId(), is(ValidationId.HTML_XML)); + assertThat(htmlXmlTagValidation.getId()).isEqualTo(ValidationId.HTML_XML); } @Test @@ -70,7 +68,7 @@ public void matchingHtmlNoError() { "HTML TAG Test
    column 1 row 1column 2 row 1
    "; List errorList = htmlXmlTagValidation.validate(source, target); - assertThat(errorList.size(), is(0)); + assertThat(errorList.size()).isEqualTo(0); } @Test @@ -79,7 +77,7 @@ public void matchingXmlNoError() { String target = "nombre"; List errorList = htmlXmlTagValidation.validate(source, target); - assertThat(errorList.size(), is(0)); + assertThat(errorList.size()).isEqualTo(0); } @Test @@ -88,9 +86,8 @@ public void addedTagError() { String target = "1"; List errorList = htmlXmlTagValidation.validate(source, target); - assertThat(errorList, - hasItem(messages.tagsAdded(Arrays.asList("")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.tagsAdded(Arrays.asList(""))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -100,9 +97,9 @@ public void addedTagsError() { "1"; List errorList = htmlXmlTagValidation.validate(source, target); - assertThat(errorList, hasItem(messages.tagsAdded(Arrays.asList("", - "", "")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.tagsAdded(Arrays.asList("", + "", ""))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -113,9 +110,8 @@ public void missingTagError() { "HTML TAG Test
    column 1 row 1column 2 row 1
    "; List errorList = htmlXmlTagValidation.validate(source, target); - assertThat(errorList, - hasItem(messages.tagsMissing(Arrays.asList("")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.tagsMissing(Arrays.asList(""))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -126,9 +122,9 @@ public void missingTagsError() { "HTML TAG Test
    column 1 row 1
    "; List errorList = htmlXmlTagValidation.validate(source, target); - assertThat(errorList, hasItem(messages.tagsMissing(Arrays.asList( - "", "

    ", "")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.tagsMissing(Arrays.asList( + "", "

    ", ""))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -137,11 +133,9 @@ public void orderOnlyValidatedWithSameTags() { String target = ""; List errorList = htmlXmlTagValidation.validate(source, target); - assertThat(errorList, - hasItem(messages.tagsMissing(Arrays.asList("")))); - assertThat(errorList, - hasItem(messages.tagsAdded(Arrays.asList("")))); - assertThat(errorList.size(), is(2)); + assertThat(errorList).contains(messages.tagsMissing(Arrays.asList(""))); + assertThat(errorList).contains(messages.tagsAdded(Arrays.asList(""))); + assertThat(errorList.size()).isEqualTo(2); } @Test @@ -150,9 +144,8 @@ public void lastTagMovedToFirstError() { String target = ""; List errorList = htmlXmlTagValidation.validate(source, target); - assertThat(errorList, - hasItem(messages.tagsWrongOrder(Arrays.asList("")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.tagsWrongOrder(Arrays.asList(""))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -161,9 +154,8 @@ public void firstTagMovedToLastError() { String target = ""; List errorList = htmlXmlTagValidation.validate(source, target); - assertThat(errorList, - hasItem(messages.tagsWrongOrder(Arrays.asList("")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.tagsWrongOrder(Arrays.asList(""))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -172,9 +164,8 @@ public void tagMovedToMiddleError() { String target = ""; List errorList = htmlXmlTagValidation.validate(source, target); - assertThat(errorList, - hasItem(messages.tagsWrongOrder(Arrays.asList("")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.tagsWrongOrder(Arrays.asList(""))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -183,9 +174,9 @@ public void reversedTagsError() { String target = ""; List errorList = htmlXmlTagValidation.validate(source, target); - assertThat(errorList, hasItem(messages.tagsWrongOrder(Arrays.asList( - "", "", "", "", "")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.tagsWrongOrder(Arrays.asList( + "", "", "", "", ""))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -194,9 +185,9 @@ public void reportFirstTagsOutOfOrder() { String target = ""; List errorList = htmlXmlTagValidation.validate(source, target); - assertThat(errorList, hasItem(messages.tagsWrongOrder(Arrays.asList( - "", "", "")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.tagsWrongOrder(Arrays.asList( + "", "", ""))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -205,9 +196,9 @@ public void reportLeastTagsOutOfOrder() { String target = ""; List errorList = htmlXmlTagValidation.validate(source, target); - assertThat(errorList, hasItem(messages.tagsWrongOrder(Arrays.asList( - "", "", "")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.tagsWrongOrder(Arrays.asList( + "", "", ""))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -216,8 +207,8 @@ public void swapSomeTagsError() { String target = ""; List errorList = htmlXmlTagValidation.validate(source, target); - assertThat(errorList, hasItem(messages.tagsWrongOrder(Arrays.asList( - "", "")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.tagsWrongOrder(Arrays.asList( + "", ""))); + assertThat(errorList.size()).isEqualTo(1); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/JavaVariablesValidationTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/JavaVariablesValidationTest.java index 8a87b0523f..0c1ad5ba38 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/JavaVariablesValidationTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/JavaVariablesValidationTest.java @@ -20,11 +20,6 @@ */ package org.zanata.webtrans.shared.validation; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.hasItem; -import static org.hamcrest.Matchers.hasItems; -import static org.hamcrest.Matchers.is; - import java.io.IOException; import java.util.Arrays; import java.util.List; @@ -37,10 +32,10 @@ import org.zanata.webtrans.shared.model.ValidationId; import org.zanata.webtrans.shared.validation.action.JavaVariablesValidation; +import static org.assertj.core.api.Assertions.assertThat; + /** - * * @author David Mason, damason@redhat.com - * **/ public class JavaVariablesValidationTest { private JavaVariablesValidation javaVariablesValidation; @@ -60,8 +55,8 @@ public void init() throws IOException { @Test public void idIsSet() { - assertThat(javaVariablesValidation.getId(), - is(ValidationId.JAVA_VARIABLES)); + assertThat(javaVariablesValidation.getId()) + .isEqualTo(ValidationId.JAVA_VARIABLES); } @Test @@ -71,7 +66,7 @@ public void noErrorForMatchingVars() { List errorList = javaVariablesValidation.validate(source, target); - assertThat(errorList.size(), is(0)); + assertThat(errorList.size()).isEqualTo(0); } @Test @@ -81,9 +76,9 @@ public void missingVarInTarget() { List errorList = javaVariablesValidation.validate(source, target); - assertThat(errorList, - hasItem(messages.varsMissing(Arrays.asList("{0}")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList) + .contains(messages.varsMissing(Arrays.asList("{0}"))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -93,9 +88,9 @@ public void missingVarsThroughoutTarget() { List errorList = javaVariablesValidation.validate(source, target); - assertThat(errorList, hasItem(messages.varsMissing(Arrays.asList("{0}", - "{1}", "{2}")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.varsMissing(Arrays.asList("{0}", + "{1}", "{2}"))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -105,8 +100,9 @@ public void addedVarInTarget() { List errorList = javaVariablesValidation.validate(source, target); - assertThat(errorList, hasItem(messages.varsAdded(Arrays.asList("{0}")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList) + .contains(messages.varsAdded(Arrays.asList("{0}"))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -116,9 +112,9 @@ public void addedVarsThroughoutTarget() { List errorList = javaVariablesValidation.validate(source, target); - assertThat(errorList, - hasItem(messages.varsAdded(Arrays.asList("{0}", "{1}", "{2}")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains( + messages.varsAdded(Arrays.asList("{0}", "{1}", "{2}"))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -128,11 +124,9 @@ public void bothAddedAndMissingVars() { List errorList = javaVariablesValidation.validate(source, target); - assertThat( - errorList, - hasItems(messages.varsAdded(Arrays.asList("{2}")), - messages.varsMissing(Arrays.asList("{0}")))); - assertThat(errorList.size(), is(2)); + assertThat(errorList).contains(messages.varsAdded(Arrays.asList("{2}")), + messages.varsMissing(Arrays.asList("{0}"))); + assertThat(errorList.size()).isEqualTo(2); } @Test @@ -144,9 +138,9 @@ public void disturbanceInTheForce() { List errorList = javaVariablesValidation.validate(source, target); - assertThat(errorList, hasItem(messages.varsMissing(Arrays.asList("{0}", - "{1}", "{2}")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.varsMissing(Arrays.asList("{0}", + "{1}", "{2}"))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -156,9 +150,9 @@ public void diskContainsFiles() { List errorList = javaVariablesValidation.validate(source, target); - assertThat(errorList, - hasItem(messages.varsMissing(Arrays.asList("{0}", "{1}")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList) + .contains(messages.varsMissing(Arrays.asList("{0}", "{1}"))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -168,7 +162,7 @@ public void doesNotDetectEscapedVariables() { List errorList = javaVariablesValidation.validate(source, target); - assertThat(errorList.size(), is(0)); + assertThat(errorList.size()).isEqualTo(0); } @Test @@ -178,7 +172,7 @@ public void doesNotDetectQuotedVariables() { List errorList = javaVariablesValidation.validate(source, target); - assertThat(errorList.size(), is(0)); + assertThat(errorList.size()).isEqualTo(0); } @Test @@ -188,7 +182,7 @@ public void doesNotDetectVariablesInQuotedText() { List errorList = javaVariablesValidation.validate(source, target); - assertThat(errorList.size(), is(0)); + assertThat(errorList.size()).isEqualTo(0); } @Test @@ -199,9 +193,9 @@ public void ignoresEscapedQuotes() { List errorList = javaVariablesValidation.validate(source, target); - assertThat(errorList, - hasItem(messages.varsMissing(Arrays.asList("{0}")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList) + .contains(messages.varsMissing(Arrays.asList("{0}"))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -212,7 +206,7 @@ public void advancedQuoting() { List errorList = javaVariablesValidation.validate(source, target); - assertThat(errorList.size(), is(0)); + assertThat(errorList.size()).isEqualTo(0); } @Test @@ -224,7 +218,7 @@ public void translatedChoicesStillMatch() { List errorList = javaVariablesValidation.validate(source, target); - assertThat(errorList.size(), is(0)); + assertThat(errorList.size()).isEqualTo(0); } @Test @@ -235,9 +229,8 @@ public void choiceFormatAndRecursion() { List errorList = javaVariablesValidation.validate(source, target); - assertThat(errorList, - hasItem(messages.varsMissing(Arrays.asList("{0}")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.varsMissing(Arrays.asList("{0}"))); + assertThat(errorList.size()).isEqualTo(1); } // TODO tests for format type diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/NewlineLeadTrailValidationTests.java b/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/NewlineLeadTrailValidationTests.java index 0ee747bea2..7bcddd2a81 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/NewlineLeadTrailValidationTests.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/NewlineLeadTrailValidationTests.java @@ -20,11 +20,6 @@ */ package org.zanata.webtrans.shared.validation; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.hasItem; -import static org.hamcrest.Matchers.hasItems; -import static org.hamcrest.Matchers.is; - import java.io.IOException; import java.util.List; @@ -35,6 +30,8 @@ import org.zanata.webtrans.shared.model.ValidationId; import org.zanata.webtrans.shared.validation.action.NewlineLeadTrailValidation; +import static org.assertj.core.api.Assertions.assertThat; + /** * * @author Alex Eng aeng@redhat.com @@ -56,8 +53,7 @@ public void init() throws IOException { @Test public void idIsSet() { - assertThat(newlineLeadTrailValidation.getId(), - is(ValidationId.NEW_LINE)); + assertThat(newlineLeadTrailValidation.getId()).isEqualTo(ValidationId.NEW_LINE); } @Test @@ -67,7 +63,7 @@ public void noNewlinesBothMatch() { List errorList = newlineLeadTrailValidation.validate(source, target); - assertThat(errorList.size(), is(0)); + assertThat(errorList.size()).isEqualTo(0); } @Test @@ -77,7 +73,7 @@ public void bothNewlinesBothMatch() { List errorList = newlineLeadTrailValidation.validate(source, target); - assertThat(errorList.size(), is(0)); + assertThat(errorList.size()).isEqualTo(0); } @Test @@ -87,10 +83,8 @@ public void missingLeadingNewline() { List errorList = newlineLeadTrailValidation.validate(source, target); - assertThat( - errorList, - hasItems(messages.leadingNewlineMissing())); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.leadingNewlineMissing()); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -100,10 +94,8 @@ public void addedLeadingNewline() { List errorList = newlineLeadTrailValidation.validate(source, target); - assertThat( - errorList, - hasItems(messages.leadingNewlineAdded())); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.leadingNewlineAdded()); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -113,10 +105,8 @@ public void missingTrailingNewline() { List errorList = newlineLeadTrailValidation.validate(source, target); - assertThat( - errorList, - hasItems(messages.trailingNewlineMissing())); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.trailingNewlineMissing()); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -126,10 +116,8 @@ public void addedTrailingNewline() { List errorList = newlineLeadTrailValidation.validate(source, target); - assertThat( - errorList, - hasItems(messages.trailingNewlineAdded())); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.trailingNewlineAdded()); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -139,11 +127,9 @@ public void addedBothNewlines() { List errorList = newlineLeadTrailValidation.validate(source, target); - assertThat( - errorList, - hasItems(messages.leadingNewlineAdded(), - messages.trailingNewlineAdded())); - assertThat(errorList.size(), is(2)); + assertThat(errorList).contains(messages.leadingNewlineAdded(), + messages.trailingNewlineAdded()); + assertThat(errorList.size()).isEqualTo(2); } @Test @@ -153,11 +139,9 @@ public void missingBothNewlines() { List errorList = newlineLeadTrailValidation.validate(source, target); - assertThat( - errorList, - hasItems(messages.leadingNewlineMissing(), - messages.trailingNewlineMissing())); - assertThat(errorList.size(), is(2)); + assertThat(errorList).contains(messages.leadingNewlineMissing(), + messages.trailingNewlineMissing()); + assertThat(errorList.size()).isEqualTo(2); } @Test @@ -167,11 +151,9 @@ public void addedAndMissing1() { List errorList = newlineLeadTrailValidation.validate(source, target); - assertThat( - errorList, - hasItems(messages.leadingNewlineMissing(), - messages.trailingNewlineAdded())); - assertThat(errorList.size(), is(2)); + assertThat(errorList).contains(messages.leadingNewlineMissing(), + messages.trailingNewlineAdded()); + assertThat(errorList.size()).isEqualTo(2); } @Test @@ -181,10 +163,8 @@ public void addedAndMissing2() { List errorList = newlineLeadTrailValidation.validate(source, target); - assertThat( - errorList, - hasItems(messages.leadingNewlineAdded(), - messages.trailingNewlineMissing())); - assertThat(errorList.size(), is(2)); + assertThat(errorList).contains(messages.leadingNewlineAdded(), + messages.trailingNewlineMissing()); + assertThat(errorList.size()).isEqualTo(2); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/PrintfVariablesValidationTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/PrintfVariablesValidationTest.java index aaec6d684e..4ccc79b781 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/PrintfVariablesValidationTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/PrintfVariablesValidationTest.java @@ -20,11 +20,6 @@ */ package org.zanata.webtrans.shared.validation; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.is; - import java.io.IOException; import java.util.Arrays; import java.util.List; @@ -37,6 +32,8 @@ import org.zanata.webtrans.shared.model.ValidationId; import org.zanata.webtrans.shared.validation.action.PrintfVariablesValidation; +import static org.assertj.core.api.Assertions.assertThat; + /** * * @author Alex Eng aeng@redhat.com @@ -61,8 +58,8 @@ public void init() throws IOException { @Test public void idIsSet() { - assertThat(printfVariablesValidation.getId(), - is(ValidationId.PRINTF_VARIABLES)); + assertThat(printfVariablesValidation.getId()) + .isEqualTo(ValidationId.PRINTF_VARIABLES); } @Test @@ -72,7 +69,7 @@ public void noErrorForMatchingVars() { List errorList = printfVariablesValidation.validate(source, target); - assertThat(errorList.size(), is(0)); + assertThat(errorList.size()).isEqualTo(0); } @Test @@ -82,9 +79,9 @@ public void missingVarInTarget() { List errorList = printfVariablesValidation.validate(source, target); - assertThat(errorList, - contains(messages.varsMissing(Arrays.asList("%1v")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList) + .contains(messages.varsMissing(Arrays.asList("%1v"))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -94,9 +91,9 @@ public void missingVarsThroughoutTarget() { List errorList = printfVariablesValidation.validate(source, target); - assertThat(errorList, - contains(messages.varsMissing(Arrays.asList("%a", "%b", "%c")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList) + .contains(messages.varsMissing(Arrays.asList("%a", "%b", "%c"))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -107,9 +104,9 @@ public void addedVarInTarget() { List errorList = printfVariablesValidation.validate(source, target); - assertThat(errorList, - contains(messages.varsAdded(Arrays.asList("%2$#x")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList) + .contains(messages.varsAdded(Arrays.asList("%2$#x"))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -120,9 +117,9 @@ public void addedVarsThroughoutTarget() { List errorList = printfVariablesValidation.validate(source, target); - assertThat(errorList, contains(messages.varsAdded(Arrays.asList( - "%1$-0lls", "%2$-0hs", "%3$-0ls")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.varsAdded(Arrays.asList( + "%1$-0lls", "%2$-0hs", "%3$-0ls"))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -132,11 +129,9 @@ public void bothAddedAndMissingVars() { List errorList = printfVariablesValidation.validate(source, target); - assertThat( - errorList, - containsInAnyOrder(messages.varsAdded(Arrays.asList("%z")), - messages.varsMissing(Arrays.asList("%x")))); - assertThat(errorList.size(), is(2)); + assertThat(errorList).contains(messages.varsAdded(Arrays.asList("%z")), + messages.varsMissing(Arrays.asList("%x"))); + assertThat(errorList.size()).isEqualTo(2); } @@ -147,8 +142,8 @@ public void substringVariablesDontMatch() { List errorList = printfVariablesValidation.validate(source, target); - assertThat(errorList, contains(messages.varsAdded(Arrays.asList("%l")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.varsAdded(Arrays.asList("%l"))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -158,9 +153,8 @@ public void superstringVariablesDontMatch() { List errorList = printfVariablesValidation.validate(source, target); - assertThat(errorList, - contains(messages.varsMissing(Arrays.asList("%l")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.varsMissing(Arrays.asList("%l"))); + assertThat(errorList.size()).isEqualTo(1); } @Test @@ -170,11 +164,10 @@ public void superstringVariablesDontMatch2() { List errorList = printfVariablesValidation.validate(source, target); - assertThat( - errorList, - contains(messages.varsMissing(Arrays.asList("%z")), - messages.varsAdded(Arrays.asList("%zz")))); - assertThat(errorList.size(), is(2)); + assertThat(errorList) + .contains(messages.varsMissing(Arrays.asList("%z")), + messages.varsAdded(Arrays.asList("%zz"))); + assertThat(errorList.size()).isEqualTo(2); } @Test @@ -185,8 +178,8 @@ public void checkWithRealWorldExamples() { List errorList = printfVariablesValidation.validate(source, target); - assertThat(errorList, contains(messages.varsMissing(Arrays.asList("%s", - "%d", "%-25s", "%r")))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.varsMissing(Arrays.asList("%s", + "%d", "%-25s", "%r"))); + assertThat(errorList.size()).isEqualTo(1); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/PrintfXSIExtensionValidationTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/PrintfXSIExtensionValidationTest.java index 51fe0b9eb7..ab152d3f59 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/PrintfXSIExtensionValidationTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/PrintfXSIExtensionValidationTest.java @@ -1,10 +1,5 @@ package org.zanata.webtrans.shared.validation; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.hasItem; -import static org.hamcrest.Matchers.is; - import java.io.IOException; import java.util.Arrays; import java.util.List; @@ -17,6 +12,8 @@ import org.zanata.webtrans.shared.model.ValidationId; import org.zanata.webtrans.shared.validation.action.PrintfXSIExtensionValidation; +import static org.assertj.core.api.Assertions.assertThat; + /** * @author Patrick Huang pahuang@redhat.com @@ -40,8 +37,8 @@ public void init() throws IOException { @Test public void idAndDescriptionAreSet() { - assertThat(printfVariablesValidation.getId(), - is(ValidationId.PRINTF_XSI_EXTENSION)); + assertThat(printfVariablesValidation.getId()) + .isEqualTo(ValidationId.PRINTF_XSI_EXTENSION); } @Test @@ -51,7 +48,7 @@ public void validPositionalVariables() { List errorList = printfVariablesValidation.validate(source, target); - assertThat(errorList.size(), is(0)); + assertThat(errorList.size()).isEqualTo(0); } @Test @@ -61,14 +58,12 @@ public void mixPositionalVariablesWithNotPositional() { List errorList = printfVariablesValidation.validate(source, target); - assertThat(errorList.size(), is(3)); + assertThat(errorList.size()).isEqualTo(3); - assertThat( - errorList, - containsInAnyOrder( - messages.varsMissing(Arrays.asList("%3$lu")), - messages.varsAdded(Arrays.asList("%lu")), - messages.mixVarFormats())); + assertThat(errorList).contains( + messages.varsMissing(Arrays.asList("%3$lu")), + messages.varsAdded(Arrays.asList("%lu")), + messages.mixVarFormats()); } @Test @@ -78,13 +73,12 @@ public void positionalVariableOutOfRange() { List errorList = printfVariablesValidation.validate(source, target); - assertThat(errorList.size(), is(3)); + assertThat(errorList.size()).isEqualTo(3); - assertThat( - errorList, - containsInAnyOrder(messages.varPositionOutOfRange("%99$lu"), - messages.varsMissing(Arrays.asList("%1$s", "%3$lu")), - messages.varsAdded(Arrays.asList("%3$s", "%99$lu")))); + assertThat(errorList).contains( + messages.varPositionOutOfRange("%99$lu"), + messages.varsMissing(Arrays.asList("%1$s", "%3$lu")), + messages.varsAdded(Arrays.asList("%3$s", "%99$lu"))); } @Test @@ -95,13 +89,12 @@ public void positionalVariablesHaveSamePosition() { List errorList = printfVariablesValidation.validate(source, target); - assertThat(errorList.size(), is(3)); - assertThat( - errorList, - containsInAnyOrder(messages.varsMissing(Arrays.asList("%1$s")), - messages.varsAdded(Arrays.asList("%3$s")), messages - .varPositionDuplicated(Arrays.asList("%3$s", - "%3$lu")))); + assertThat(errorList.size()).isEqualTo(3); + assertThat(errorList).contains( + messages.varsMissing(Arrays.asList("%1$s")), + messages.varsAdded(Arrays.asList("%3$s")), messages + .varPositionDuplicated(Arrays.asList("%3$s", + "%3$lu"))); } @Test @@ -110,14 +103,11 @@ public void invalidPositionalVariablesBringItAll() { String target = "%2$d %2$s %9$lu %z"; List errorList = printfVariablesValidation.validate(source, target); - - assertThat(errorList, hasItem(messages.varPositionOutOfRange("%9$lu"))); - assertThat(errorList, hasItem(messages.mixVarFormats())); - assertThat(errorList, hasItem(messages.varPositionDuplicated(Arrays - .asList("%2$d", "%2$s")))); - assertThat(errorList, - hasItem(messages.varsMissing(Arrays.asList("%1$s", "%3$lu")))); - assertThat(errorList, hasItem(messages.varsAdded(Arrays.asList("%2$s", - "%9$lu", "%z")))); + assertThat(errorList).contains( + messages.varPositionOutOfRange("%9$lu"), + messages.mixVarFormats(), + messages.varPositionDuplicated(Arrays.asList("%2$d", "%2$s")), + messages.varsMissing(Arrays.asList("%1$s", "%3$lu")), + messages.varsAdded(Arrays.asList("%2$s", "%9$lu", "%z"))); } } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/TabValidationTest.java b/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/TabValidationTest.java index bd1ab5fcbe..dafe5aa82e 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/TabValidationTest.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/TabValidationTest.java @@ -20,10 +20,6 @@ */ package org.zanata.webtrans.shared.validation; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.hasItem; -import static org.hamcrest.Matchers.is; - import java.io.IOException; import java.util.Collections; import java.util.List; @@ -35,6 +31,8 @@ import org.zanata.webtrans.shared.model.ValidationId; import org.zanata.webtrans.shared.validation.action.TabValidation; +import static org.assertj.core.api.Assertions.assertThat; + public class TabValidationTest { private ValidationMessages messages; private TabValidation validation; @@ -50,7 +48,7 @@ public void init() throws IOException { @Test public void idIsSet() { - assertThat(validation.getId(), is(ValidationId.TAB)); + assertThat(validation.getId()).isEqualTo(ValidationId.TAB); } @Test @@ -59,7 +57,7 @@ public void noTabsInEither() { String target = "Target without tab"; List errorList = validation.validate(source, target); - assertThat(errorList, is(noErrors)); + assertThat(errorList).isEqualTo(noErrors); } @Test @@ -68,7 +66,7 @@ public void tabsInBoth() { String target = "Target with\ttab"; List errorList = validation.validate(source, target); - assertThat(errorList, is(noErrors)); + assertThat(errorList).isEqualTo(noErrors); } @Test @@ -77,8 +75,8 @@ public void noTabsInTarget() { String target = "Target without tab"; List errorList = validation.validate(source, target); - assertThat(errorList, hasItem(messages.targetHasFewerTabs(1, 0))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.targetHasFewerTabs(1, 0)); + assertThat(errorList.size()).isEqualTo(1); } @@ -88,8 +86,8 @@ public void noTabsInSource() { String target = "Target with\textra tab"; List errorList = validation.validate(source, target); - assertThat(errorList, hasItem(messages.targetHasMoreTabs(0, 1))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.targetHasMoreTabs(0, 1)); + assertThat(errorList.size()).isEqualTo(1); } @@ -99,8 +97,8 @@ public void fewerTabsInTarget() { String target = "Target with one\ttab"; List errorList = validation.validate(source, target); - assertThat(errorList, hasItem(messages.targetHasFewerTabs(2, 1))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.targetHasFewerTabs(2, 1)); + assertThat(errorList.size()).isEqualTo(1); } @@ -110,8 +108,8 @@ public void moreTabsInTarget() { String target = "Target with two\t\t tabs"; List errorList = validation.validate(source, target); - assertThat(errorList, hasItem(messages.targetHasMoreTabs(1, 2))); - assertThat(errorList.size(), is(1)); + assertThat(errorList).contains(messages.targetHasMoreTabs(1, 2)); + assertThat(errorList.size()).isEqualTo(1); } diff --git a/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/XMLEntityValidationTests.java b/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/XMLEntityValidationTests.java index 7dfac27816..1d25e8de7e 100644 --- a/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/XMLEntityValidationTests.java +++ b/server/zanata-war/src/test/java/org/zanata/webtrans/shared/validation/XMLEntityValidationTests.java @@ -20,13 +20,9 @@ */ package org.zanata.webtrans.shared.validation; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; - import java.io.IOException; import java.util.List; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.MockitoAnnotations; @@ -35,6 +31,8 @@ import org.zanata.webtrans.shared.model.ValidationId; import org.zanata.webtrans.shared.validation.action.XmlEntityValidation; +import static org.assertj.core.api.Assertions.assertThat; + /** * * @author Alex Eng aeng@redhat.com @@ -58,8 +56,7 @@ public void beforeMethod() throws IOException { @Test public void idIsSet() { - assertThat(xmlEntityValidation.getId(), - Matchers.equalTo(ValidationId.XML_ENTITY)); + assertThat(xmlEntityValidation.getId()).isEqualTo(ValidationId.XML_ENTITY); } @Test @@ -68,7 +65,7 @@ public void testNoEntity() { String target = "Target string without xml entity"; List errorList = xmlEntityValidation.validate(source, target); - assertThat(errorList.size(), Matchers.equalTo(0)); + assertThat(errorList.size()).isEqualTo(0); } @Test @@ -77,7 +74,7 @@ public void testWithCompleteEntity() { String target = "Target string: &mash; bla bla &test;"; List errorList = xmlEntityValidation.validate(source, target); - assertThat(errorList.size(), Matchers.equalTo(0)); + assertThat(errorList.size()).isEqualTo(0); } @Test @@ -86,11 +83,9 @@ public void testWithIncompleteEntityCharRef() { String target = "Target string: &mash bla bla &test"; List errorList = xmlEntityValidation.validate(source, target); - assertThat(errorList.size(), Matchers.equalTo(2)); - assertThat( - errorList, - contains(messages.invalidXMLEntity("&mash"), - messages.invalidXMLEntity("&test"))); + assertThat(errorList.size()).isEqualTo(2); + assertThat(errorList).contains(messages.invalidXMLEntity("&mash"), + messages.invalidXMLEntity("&test")); } @Test @@ -99,11 +94,9 @@ public void testWithIncompleteEntityDecimalRef() { String target = "Target string: Ӓ bla bla &#BC;"; List errorList = xmlEntityValidation.validate(source, target); - assertThat(errorList.size(), Matchers.equalTo(2)); - assertThat( - errorList, - contains(messages.invalidXMLEntity("Ӓ"), - messages.invalidXMLEntity("&#BC;"))); + assertThat(errorList.size()).isEqualTo(2); + assertThat(errorList).contains(messages.invalidXMLEntity("Ӓ"), + messages.invalidXMLEntity("&#BC;")); } @Test @@ -112,11 +105,9 @@ public void testWithIncompleteEntityHexadecimalRef() { String target = "Target string: ሴ bla bla Z"; List errorList = xmlEntityValidation.validate(source, target); - assertThat(errorList.size(), Matchers.equalTo(2)); - assertThat( - errorList, - contains(messages.invalidXMLEntity("ሴ"), - messages.invalidXMLEntity(" Z"))); + assertThat(errorList.size()).isEqualTo(2); + assertThat(errorList).contains(messages.invalidXMLEntity("ሴ"), + messages.invalidXMLEntity(" Z")); } } diff --git a/server/zanata-war/src/test/java/org/zanata/xml/StreamSerializerTest.java b/server/zanata-war/src/test/java/org/zanata/xml/StreamSerializerTest.java index 81e3fa14df..3f06e24971 100644 --- a/server/zanata-war/src/test/java/org/zanata/xml/StreamSerializerTest.java +++ b/server/zanata-war/src/test/java/org/zanata/xml/StreamSerializerTest.java @@ -1,9 +1,5 @@ package org.zanata.xml; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.startsWith; - import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -14,7 +10,8 @@ import nu.xom.Element; import org.junit.Test; -import org.zanata.xml.StreamSerializer; + +import static org.assertj.core.api.Assertions.assertThat; public class StreamSerializerTest { @@ -41,12 +38,12 @@ public void sanityTest() throws IOException { serializer.flush(); String output = out.toString(); - assertThat(output, - startsWith("")); + assertThat(output) + .startsWith(""); String expected = "" + "" + "" + ""; - assertThat(output, containsString(expected)); + assertThat(output).contains(expected); } }