From 5c2956a641f6287df3f670c64f31379b22f6440a Mon Sep 17 00:00:00 2001 From: Helmi Akermi <70575401+hakermi@users.noreply.github.com> Date: Fri, 25 Aug 2023 11:18:10 +0100 Subject: [PATCH] feat: Add multilangue backend services - EXO-65935 - Meeds-io/MIPs#70 (#711) Add multilangue backend services --- .../exoplatform/wiki/jpa/EntityConverter.java | 24 ++++++ .../exoplatform/wiki/jpa/JPADataStorage.java | 69 +++++++++++++++- .../wiki/jpa/dao/DraftPageDAO.java | 32 +++++++- .../wiki/jpa/dao/PageVersionDAO.java | 39 ++++++++++ .../wiki/jpa/entity/DraftPageEntity.java | 17 +++- .../wiki/jpa/entity/PageVersionEntity.java | 17 +++- .../java/org/exoplatform/wiki/model/Page.java | 2 + .../exoplatform/wiki/model/PageHistory.java | 2 + .../exoplatform/wiki/service/DataStorage.java | 46 +++++++++++ .../exoplatform/wiki/service/NoteService.java | 54 ++++++++++++- .../wiki/service/impl/NoteServiceImpl.java | 78 ++++++++++++++++--- .../wiki/service/rest/NotesRestService.java | 62 +++++++++++---- .../db/changelog/wiki.db.changelog-1.0.0.xml | 8 ++ .../wiki/service/TestNoteService.java | 73 +++++++++++++++++ .../service/rest/NotesRestServiceTest.java | 39 +++++++--- 15 files changed, 513 insertions(+), 49 deletions(-) diff --git a/notes-service/src/main/java/org/exoplatform/wiki/jpa/EntityConverter.java b/notes-service/src/main/java/org/exoplatform/wiki/jpa/EntityConverter.java index f5d4da9af4..5c2fc6da39 100644 --- a/notes-service/src/main/java/org/exoplatform/wiki/jpa/EntityConverter.java +++ b/notes-service/src/main/java/org/exoplatform/wiki/jpa/EntityConverter.java @@ -24,8 +24,12 @@ import org.exoplatform.commons.file.model.FileInfo; import org.exoplatform.commons.file.model.FileItem; import org.exoplatform.commons.file.services.FileService; +import org.exoplatform.commons.utils.CommonsUtils; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; +import org.exoplatform.social.core.identity.model.Identity; +import org.exoplatform.social.core.identity.provider.OrganizationIdentityProvider; +import org.exoplatform.social.core.manager.IdentityManager; import org.exoplatform.wiki.WikiException; import org.exoplatform.wiki.jpa.dao.PageDAO; import org.exoplatform.wiki.jpa.dao.WikiDAO; @@ -374,6 +378,7 @@ public static DraftPage convertDraftPageEntityToDraftPage(DraftPageEntity draftP draftPage.setAuthor(draftPageEntity.getAuthor()); draftPage.setOwner(draftPageEntity.getAuthor()); draftPage.setContent(draftPageEntity.getContent()); + draftPage.setLang(draftPageEntity.getLang()); draftPage.setSyntax(draftPageEntity.getSyntax()); draftPage.setCreatedDate(draftPageEntity.getCreatedDate()); draftPage.setUpdatedDate(draftPageEntity.getUpdatedDate()); @@ -415,6 +420,7 @@ public static DraftPageEntity convertDraftPageToDraftPageEntity(DraftPage draftP draftPageEntity.setTitle(draftPage.getTitle()); draftPageEntity.setAuthor(draftPage.getAuthor()); draftPageEntity.setContent(draftPage.getContent()); + draftPageEntity.setLang(draftPage.getLang()); draftPageEntity.setSyntax(draftPage.getSyntax()); draftPageEntity.setCreatedDate(draftPage.getCreatedDate()); draftPageEntity.setUpdatedDate(draftPage.getUpdatedDate()); @@ -441,6 +447,7 @@ public static PageVersion convertPageVersionEntityToPageVersion(PageVersionEntit pageVersion.setContent(pageVersionEntity.getContent()); pageVersion.setCreatedDate(pageVersionEntity.getCreatedDate()); pageVersion.setUpdatedDate(pageVersionEntity.getUpdatedDate()); + pageVersion.setLang(pageVersionEntity.getLang()); } return pageVersion; } @@ -455,6 +462,7 @@ public static PageHistory convertPageVersionEntityToPageHistory(PageVersionEntit pageHistory.setContent(pageVersionEntity.getContent()); pageHistory.setCreatedDate(pageVersionEntity.getCreatedDate()); pageHistory.setUpdatedDate(pageVersionEntity.getUpdatedDate()); + pageHistory.setLang(pageVersionEntity.getLang()); } return pageHistory; } @@ -470,4 +478,20 @@ public static PermissionEntry convertPermissionEntityToPermissionEntry(Permissio return permissionEntry; } + public static List toPageHistoryVersions(List pageVersionEntities) { + IdentityManager identityManager = CommonsUtils.getService(IdentityManager.class); + + return pageVersionEntities.stream().map(EntityConverter::convertPageVersionEntityToPageHistory) + .peek(pageHistory -> { + Identity identity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, + pageHistory.getAuthor()); + if (identity != null && identity.getProfile() != null + && identity.getProfile().getFullName() != null) { + pageHistory.setAuthorFullName(identity.getProfile().getFullName()); + }}).toList(); + } + + public static List toDraftPages(List draftPageEntities) { + return draftPageEntities.stream().map(EntityConverter::convertDraftPageEntityToDraftPage).toList(); + } } diff --git a/notes-service/src/main/java/org/exoplatform/wiki/jpa/JPADataStorage.java b/notes-service/src/main/java/org/exoplatform/wiki/jpa/JPADataStorage.java index f6232c253e..146bcdee49 100644 --- a/notes-service/src/main/java/org/exoplatform/wiki/jpa/JPADataStorage.java +++ b/notes-service/src/main/java/org/exoplatform/wiki/jpa/JPADataStorage.java @@ -20,7 +20,6 @@ package org.exoplatform.wiki.jpa; import org.apache.commons.lang.StringUtils; -import org.exoplatform.commons.api.persistence.DataInitializer; import org.exoplatform.commons.api.persistence.ExoTransactional; import org.exoplatform.commons.file.services.FileService; import org.exoplatform.commons.utils.ObjectPageList; @@ -1120,10 +1119,10 @@ public void addPageVersion(Page page , String userName) throws WikiException { pageVersionEntity.setVersionNumber(versionNumber); pageVersionEntity.setName(pageEntity.getName()); pageVersionEntity.setTitle(pageEntity.getTitle()); - if(StringUtils.isNotEmpty(userName)){ + if (StringUtils.isNotEmpty(userName)) { pageVersionEntity.setAuthor(userName); - } else{ - pageVersionEntity.setAuthor(pageEntity.getAuthor()); + } else { + pageVersionEntity.setAuthor(pageEntity.getAuthor()); } pageVersionEntity.setContent(pageEntity.getContent()); pageVersionEntity.setSyntax(pageEntity.getSyntax()); @@ -1132,6 +1131,7 @@ public void addPageVersion(Page page , String userName) throws WikiException { Date now = Calendar.getInstance().getTime(); pageVersionEntity.setCreatedDate(now); pageVersionEntity.setUpdatedDate(now); + pageVersionEntity.setLang(page.getLang()); // attachment must be saved here because of Hibernate bug HHH-6776 pageVersionDAO.create(pageVersionEntity); @@ -1444,4 +1444,65 @@ private String getDownloadURL(String wikiType, String wikiOwner, String pageName return sb.toString(); } + + + /** + * {@inheritDoc} + */ + @Override + public List getPageHistoryVersionsByPageIdAndLang(Long pageId, String lang) { + if (pageId == null) { + throw new IllegalArgumentException("pageId argument is null"); + } + return EntityConverter.toPageHistoryVersions(pageVersionDAO.findPageVersionsByPageIdAndLang(pageId, lang)); + } + + /** + * {@inheritDoc} + */ + @Override + public DraftPage getLatestDraftPageByUserAndTargetPageAndLang(Long targetPageId, String username, String lang) { + if (username == null) { + throw new IllegalArgumentException("username argument is null"); + } + if (targetPageId == null) { + throw new IllegalArgumentException("targetPageId argument is null"); + } + return EntityConverter.convertDraftPageEntityToDraftPage(draftPageDAO.findLatestDraftPageByUserAndTargetPageAndLang(targetPageId, + username, + lang)); + } + + /** + * {@inheritDoc} + */ + @Override + public PageVersion getPublishedVersionByPageIdAndLang(Long pageId, String lang) { + if (pageId == null) { + throw new IllegalArgumentException("targetPageId argument is null"); + } + return convertPageVersionEntityToPageVersion(pageVersionDAO.findLatestVersionByPageIdAndLang(pageId, lang)); + } + + /** + * {@inheritDoc} + */ + @Override + public List getPageAvailableTranslationLanguages(Long pageId) { + if (pageId == null) { + throw new IllegalArgumentException("pageId argument is null"); + } + return pageVersionDAO.findPageAvailableTranslationLanguages(pageId); + } + + /** + * {@inheritDoc} + */ + @Override + public DraftPage getDraftPageByIdAndLang(Long draftNoteId, String lang) { + if (draftNoteId == null) { + throw new IllegalArgumentException("draftNoteId argument is null"); + } + return EntityConverter.convertDraftPageEntityToDraftPage(draftPageDAO.findDraftNoteByIdAndLang(draftNoteId, lang)); + } } diff --git a/notes-service/src/main/java/org/exoplatform/wiki/jpa/dao/DraftPageDAO.java b/notes-service/src/main/java/org/exoplatform/wiki/jpa/dao/DraftPageDAO.java index 32f7faddfa..dbe81ad756 100644 --- a/notes-service/src/main/java/org/exoplatform/wiki/jpa/dao/DraftPageDAO.java +++ b/notes-service/src/main/java/org/exoplatform/wiki/jpa/dao/DraftPageDAO.java @@ -17,12 +17,9 @@ package org.exoplatform.wiki.jpa.dao; import org.exoplatform.commons.api.persistence.ExoTransactional; -import org.exoplatform.commons.persistence.impl.GenericDAOJPAImpl; import org.exoplatform.wiki.jpa.entity.DraftPageEntity; -import javax.persistence.EntityTransaction; import javax.persistence.NoResultException; -import javax.persistence.Query; import javax.persistence.TypedQuery; import java.util.List; @@ -103,4 +100,33 @@ public DraftPageEntity findLatestDraftPageByUserAndTargetPage(Long targetPageId, return null; } } + + public DraftPageEntity findLatestDraftPageByUserAndTargetPageAndLang(Long targetPageId, String username, String lang) { + TypedQuery query = + getEntityManager().createNamedQuery("wikiDraftPage.findLatestDraftPageByUserAndTargetPageAndLang", + DraftPageEntity.class) + .setParameter("username", username) + .setParameter("targetPageId", targetPageId) + .setParameter("lang", lang); + query.setMaxResults(1); + try { + return query.getSingleResult(); + } catch (NoResultException e) { + return null; + } + } + + public DraftPageEntity findDraftNoteByIdAndLang(Long draftNoteId, String lang) { + TypedQuery query = getEntityManager() + .createNamedQuery("wikiDraftPage.findDraftByIdAndLang", + DraftPageEntity.class) + .setParameter("id", draftNoteId) + .setParameter("lang", lang); + + try { + return query.getSingleResult(); + } catch (NoResultException e) { + return null; + } + } } diff --git a/notes-service/src/main/java/org/exoplatform/wiki/jpa/dao/PageVersionDAO.java b/notes-service/src/main/java/org/exoplatform/wiki/jpa/dao/PageVersionDAO.java index e1397c6274..0677e66bfb 100644 --- a/notes-service/src/main/java/org/exoplatform/wiki/jpa/dao/PageVersionDAO.java +++ b/notes-service/src/main/java/org/exoplatform/wiki/jpa/dao/PageVersionDAO.java @@ -23,6 +23,7 @@ import javax.persistence.NoResultException; import javax.persistence.Query; import javax.persistence.TypedQuery; +import java.util.Collections; import java.util.List; public class PageVersionDAO extends WikiBaseDAO { @@ -62,4 +63,42 @@ public Long countPagesVersionsBySyntax(String syntax) { .setParameter("syntax", syntax) .getSingleResult(); } + + public List findPageVersionsByPageIdAndLang(Long pageId, String lang) { + TypedQuery query = getEntityManager() + .createNamedQuery("wikiPageVersion.getPageVersionsByPageIdAndLang", + PageVersionEntity.class) + .setParameter("pageId", pageId) + .setParameter("lang", lang); + try { + return query.getResultList(); + } catch (NoResultException e) { + return Collections.emptyList(); + } + } + + public PageVersionEntity findLatestVersionByPageIdAndLang(Long pageId, String lang) { + TypedQuery query = getEntityManager() + .createNamedQuery("wikiPageVersion.getLatestPageVersionsByPageIdAndLang", + PageVersionEntity.class) + .setParameter("pageId", pageId) + .setParameter("lang", lang); + query.setMaxResults(1); + try { + return query.getSingleResult(); + } catch (NoResultException e) { + return null; + } + } + + public List findPageAvailableTranslationLanguages(Long pageId) { + Query query = getEntityManager().createNamedQuery("wikiPageVersion.getPageAvailableTranslationLanguages") + .setParameter("pageId", pageId); + try { + return query.getResultList(); + } catch (NoResultException e) { + return Collections.emptyList(); + } + } + } diff --git a/notes-service/src/main/java/org/exoplatform/wiki/jpa/entity/DraftPageEntity.java b/notes-service/src/main/java/org/exoplatform/wiki/jpa/entity/DraftPageEntity.java index e308b1cb34..5c9a9215c9 100644 --- a/notes-service/src/main/java/org/exoplatform/wiki/jpa/entity/DraftPageEntity.java +++ b/notes-service/src/main/java/org/exoplatform/wiki/jpa/entity/DraftPageEntity.java @@ -35,8 +35,10 @@ @NamedQuery(name = "wikiDraftPage.findDraftPageByUserAndName", query = "SELECT d FROM WikiDraftPageEntity d WHERE d.author = :username AND d.name = :draftPageName ORDER BY d.updatedDate DESC"), @NamedQuery(name = "wikiDraftPage.findLatestDraftPageByUserAndTargetPage", query = "SELECT d FROM WikiDraftPageEntity d WHERE d.author = :username AND d.targetPage.id = :targetPageId ORDER BY d.updatedDate DESC"), @NamedQuery(name = "wikiDraftPage.findDraftPageByUserAndTargetPage", query = "SELECT d FROM WikiDraftPageEntity d WHERE d.author = :username AND d.targetPage.id = :targetPageId"), - @NamedQuery(name = "wikiDraftPage.findDraftPagesByUserAndParentPage", query = "SELECT d FROM WikiDraftPageEntity d WHERE d.author = :username AND d.parentPage.id = :parentPageId") -}) + @NamedQuery(name = "wikiDraftPage.findDraftPagesByUserAndParentPage", query = "SELECT d FROM WikiDraftPageEntity d WHERE d.author = :username AND d.parentPage.id = :parentPageId"), + @NamedQuery(name = "wikiDraftPage.findLatestDraftPageByUserAndTargetPageAndLang", query = "SELECT d FROM WikiDraftPageEntity d WHERE d.author = :username AND d.targetPage.id = :targetPageId AND " + + "((:lang IS NULL AND d.lang IS NULL) OR (:lang IS NOT NULL AND d.lang = :lang)) ORDER BY d.updatedDate DESC"), + @NamedQuery(name = "wikiDraftPage.findDraftByIdAndLang", query = "SELECT d FROM WikiDraftPageEntity d WHERE d.id = :id AND ((:lang IS NULL AND d.lang IS NULL) OR (:lang IS NOT NULL AND d.lang = :lang))") }) public class DraftPageEntity extends BasePageEntity { @Id @@ -62,6 +64,9 @@ public class DraftPageEntity extends BasePageEntity { @OneToMany(cascade = CascadeType.ALL, mappedBy = "draftPage") private List attachments; + @Column(name = "LANG") + private String lang; + public PageEntity getTargetPage() { return targetPage; } @@ -109,4 +114,12 @@ public List getAttachments() { public void setAttachments(List attachments) { this.attachments = attachments; } + + public String getLang() { + return lang; + } + + public void setLang(String lang) { + this.lang = lang; + } } diff --git a/notes-service/src/main/java/org/exoplatform/wiki/jpa/entity/PageVersionEntity.java b/notes-service/src/main/java/org/exoplatform/wiki/jpa/entity/PageVersionEntity.java index 6605bfe03c..50a221c326 100644 --- a/notes-service/src/main/java/org/exoplatform/wiki/jpa/entity/PageVersionEntity.java +++ b/notes-service/src/main/java/org/exoplatform/wiki/jpa/entity/PageVersionEntity.java @@ -36,7 +36,11 @@ @NamedQuery(name = "wikiPageVersion.getLastversionNumberOfPage", query = "SELECT max(p.versionNumber) FROM WikiPageVersionEntity p WHERE p.page.id = :pageId"), @NamedQuery(name = "wikiPageVersion.getPageversionByPageIdAndVersion", query = "SELECT p FROM WikiPageVersionEntity p WHERE p.page.id = :pageId AND p.versionNumber = :versionNumber"), @NamedQuery(name = "wikiPageVersion.getAllPagesVersionsBySyntax", query = "SELECT p FROM WikiPageVersionEntity p WHERE p.syntax = :syntax OR p.syntax IS NULL ORDER BY p.updatedDate DESC"), - @NamedQuery(name = "wikiPageVersion.countAllPagesVersionsBySyntax", query = "SELECT COUNT(p) FROM WikiPageVersionEntity p WHERE p.syntax = :syntax OR p.syntax IS NULL") + @NamedQuery(name = "wikiPageVersion.countAllPagesVersionsBySyntax", query = "SELECT COUNT(p) FROM WikiPageVersionEntity p WHERE p.syntax = :syntax OR p.syntax IS NULL"), + @NamedQuery(name = "wikiPageVersion.getPageVersionsByPageIdAndLang", query = "SELECT p FROM WikiPageVersionEntity p WHERE p.page.id = :pageId AND ((:lang IS NULL AND p.lang IS NULL) OR (:lang IS NOT NULL AND p.lang = :lang))"), + @NamedQuery(name = "wikiPageVersion.getLatestPageVersionsByPageIdAndLang", query = "SELECT p FROM WikiPageVersionEntity p WHERE p.page.id = :pageId AND ((:lang IS NULL AND p.lang IS NULL) OR (:lang IS NOT NULL AND p.lang = :lang)) ORDER BY p.versionNumber DESC"), + @NamedQuery(name = "wikiPageVersion.getPageAvailableTranslationLanguages", query = "SELECT DISTINCT p.lang FROM WikiPageVersionEntity p WHERE p.page.id = :pageId AND p.lang IS NOT NULL") + }) public class PageVersionEntity extends BasePageEntity { @Id @@ -58,6 +62,9 @@ public class PageVersionEntity extends BasePageEntity { @Column(name = "MINOR_EDIT") private boolean minorEdit; + @Column(name = "LANG") + private String lang; + public long getId() { return id; } @@ -93,4 +100,12 @@ public boolean isMinorEdit() { public void setMinorEdit(boolean minorEdit) { this.minorEdit = minorEdit; } + + public String getLang() { + return lang; + } + + public void setLang(String lang) { + this.lang = lang; + } } diff --git a/notes-service/src/main/java/org/exoplatform/wiki/model/Page.java b/notes-service/src/main/java/org/exoplatform/wiki/model/Page.java index 8ff7101a9d..16d60123bd 100644 --- a/notes-service/src/main/java/org/exoplatform/wiki/model/Page.java +++ b/notes-service/src/main/java/org/exoplatform/wiki/model/Page.java @@ -99,6 +99,8 @@ public class Page { private Map> metadatas; + private String lang; + public Page(String name) { this.name = name; } diff --git a/notes-service/src/main/java/org/exoplatform/wiki/model/PageHistory.java b/notes-service/src/main/java/org/exoplatform/wiki/model/PageHistory.java index 71bde7e557..790361b66f 100644 --- a/notes-service/src/main/java/org/exoplatform/wiki/model/PageHistory.java +++ b/notes-service/src/main/java/org/exoplatform/wiki/model/PageHistory.java @@ -38,4 +38,6 @@ public class PageHistory { private Date updatedDate; private String content; + + private String lang; } diff --git a/notes-service/src/main/java/org/exoplatform/wiki/service/DataStorage.java b/notes-service/src/main/java/org/exoplatform/wiki/service/DataStorage.java index 44cbc24ddc..0b49dbdb24 100644 --- a/notes-service/src/main/java/org/exoplatform/wiki/service/DataStorage.java +++ b/notes-service/src/main/java/org/exoplatform/wiki/service/DataStorage.java @@ -207,4 +207,50 @@ public default List getAttachmentsOfPage(Page page, boolean loadCont * @return the List pf pages of the wiki */ public List getPagesOfWiki(String wikiType, String wikiOwner); + + /** + * Retrieves list of page versions by page id and lang + * + * @param pageId page id + * @param lang content language + * @return {@link List} of {@link PageHistory} + */ + List getPageHistoryVersionsByPageIdAndLang(Long pageId, String lang); + + /** + * Retrieves latest draft of a specific page by target page id and content language + * and owner username + * + * @param targetPageId target page id + * @param username owner username + * @param lang content language + * @return {@link DraftPage} + */ + DraftPage getLatestDraftPageByUserAndTargetPageAndLang(Long targetPageId, String username, String lang); + + /** + * Retrieves the published note page version by its id and content language + * @param pageId page id + * @param lang content language + * @return {@link PageVersion} + */ + PageVersion getPublishedVersionByPageIdAndLang(Long pageId, String lang); + + /** + * Retrieves list of available translations languages of a page + * + * @param pageId page id + * @return {@link List} of {@link String} + */ + List getPageAvailableTranslationLanguages(Long pageId); + + /** + * Retrieves a draft note by its id and content language + * + * @param draftNoteId draft note id + * @param lang content language + * @return {@link DraftPage} + */ + DraftPage getDraftPageByIdAndLang(Long draftNoteId, String lang); + } diff --git a/notes-service/src/main/java/org/exoplatform/wiki/service/NoteService.java b/notes-service/src/main/java/org/exoplatform/wiki/service/NoteService.java index 694574254c..27cb8e1098 100644 --- a/notes-service/src/main/java/org/exoplatform/wiki/service/NoteService.java +++ b/notes-service/src/main/java/org/exoplatform/wiki/service/NoteService.java @@ -147,12 +147,22 @@ Page getNoteOfNoteBookByName(String noteType, * Gets a draft note based on its unique id. * * @param id Unique id of the draft note. - * @param userId + * @param userId user id * @return The note. * @throws WikiException if an error occured */ DraftPage getDraftNoteById(String id, String userId) throws WikiException, IllegalAccessException; + /** + * Retrieves a draft note by its id and content language + * + * @param draftNoteId draft note id + * @param userId user id + * @param lang content language + * @return {@link DraftPage} + */ + DraftPage getDraftNoteByIdAndLang(Long draftNoteId, String userId, String lang) throws WikiException, IllegalAccessException; + /** * Returns latest draft of given page. * @@ -234,6 +244,16 @@ Page getNoteOfNoteBookByName(String noteType, */ List getVersionsHistoryOfNote(Page note, String userName) throws WikiException; + /** + * Retrieves the history version of given note by language + * + * @param note the target note id + * @param userName user name + * @param lang content language + * @return {@link List} of {@link PageHistory} + */ + List getVersionsHistoryOfNoteByLang(Page note, String userName, String lang) throws WikiException; + /** * Creates a version of a note. This method only tag the current note data as a * new version, it does not update the note data @@ -444,4 +464,36 @@ void importNotes(List files, Page parent, String conflict, Identity user * @throws WikiException if an error occured */ boolean hasPermissionOnPage(Page page, PermissionType permissionType, Identity user) throws WikiException; + + /** + * Retrieves note page by its id and content lang + * + * @param pageId page id + * @param userIdentity user identity id + * @param source source + * @param lang content language + * @return {@link Page} + * @throws WikiException + * @throws IllegalAccessException + */ + Page getNoteByIdAndLang(Long pageId, Identity userIdentity, String source, String lang) throws WikiException, IllegalAccessException; + + /** + * Retrieves list of available translations languages of a page + * + * @param pageId page id + * @return {@link List} of {@link String} + */ + List getPageAvailableTranslationLanguages(Long pageId); + + /** + * Retrieves latest draft of a specific page by target page id and content language + * and owner username + * + * @param targetPageId target page id + * @param username owner username + * @param lang content language + * @return {@link DraftPage} + */ + DraftPage getLatestDraftPageByUserAndTargetPageAndLang(Long targetPageId, String username, String lang); } diff --git a/notes-service/src/main/java/org/exoplatform/wiki/service/impl/NoteServiceImpl.java b/notes-service/src/main/java/org/exoplatform/wiki/service/impl/NoteServiceImpl.java index 09bede2906..a241170eed 100644 --- a/notes-service/src/main/java/org/exoplatform/wiki/service/impl/NoteServiceImpl.java +++ b/notes-service/src/main/java/org/exoplatform/wiki/service/impl/NoteServiceImpl.java @@ -41,6 +41,7 @@ import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; +import org.exoplatform.wiki.model.*; import org.gatein.api.EntityNotFoundException; import com.fasterxml.jackson.core.type.TypeReference; @@ -65,13 +66,6 @@ import org.exoplatform.social.metadata.model.MetadataItem; import org.exoplatform.social.metadata.model.MetadataObject; import org.exoplatform.wiki.WikiException; -import org.exoplatform.wiki.model.DraftPage; -import org.exoplatform.wiki.model.ImportList; -import org.exoplatform.wiki.model.NoteToExport; -import org.exoplatform.wiki.model.Page; -import org.exoplatform.wiki.model.PageHistory; -import org.exoplatform.wiki.model.PermissionType; -import org.exoplatform.wiki.model.Wiki; import org.exoplatform.wiki.rendering.cache.AttachmentCountData; import org.exoplatform.wiki.rendering.cache.MarkupData; import org.exoplatform.wiki.rendering.cache.MarkupKey; @@ -206,6 +200,7 @@ public Page createNote(Wiki noteBook, String parentNoteName, Page note, Identity createdPage.setToBePublished(note.isToBePublished()); createdPage.setAppName(note.getAppName()); createdPage.setUrl(Utils.getPageUrl(createdPage)); + createdPage.setLang(note.getLang()); invalidateCache(parentPage); invalidateCache(note); @@ -487,7 +482,12 @@ public DraftPage getDraftNoteById(String id, String userId) throws WikiException return null; } DraftPage draftPage = dataStorage.getDraftPageById(id); + computeDraftProps(draftPage, userId); + return draftPage; + } + + private void computeDraftProps(DraftPage draftPage, String userId) throws WikiException, IllegalAccessException { if (draftPage != null) { Space space = spaceService.getSpaceByGroupId(draftPage.getWikiOwner()); if (!canViewNotes(userId, space, draftPage)) { @@ -497,10 +497,17 @@ public DraftPage getDraftNoteById(String id, String userId) throws WikiException draftPage.setCanManage(canManageNotes(userId, space, draftPage)); draftPage.setCanImport(canImportNotes(userId, space, draftPage)); String authorFullName = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, draftPage.getAuthor()) - .getProfile() - .getFullName(); + .getProfile() + .getFullName(); draftPage.setAuthorFullName(authorFullName); } + } + + @Override + public DraftPage getDraftNoteByIdAndLang(Long draftNoteId, String userId, String lang) throws WikiException, IllegalAccessException { + DraftPage draftPage = dataStorage.getDraftPageByIdAndLang(draftNoteId, lang); + computeDraftProps(draftPage, userId); + return draftPage; } @@ -550,7 +557,7 @@ public Page getNoteById(String id, Identity userIdentity, String source) throws page.setCanImport(canImportNotes(userIdentity.getUserId(), space, page)); Map> metadata = retrieveMetadataItems(id, userIdentity.getUserId()); page.setMetadatas(metadata); - if (StringUtils.isNotEmpty(source)) { + if (StringUtils.isNotBlank(source)) { if (source.equals("tree")) { postOpenByTree(page.getWikiType(), page.getWikiOwner(), page.getName(), page); } @@ -745,6 +752,7 @@ public DraftPage updateDraftForExistPage(DraftPage draftNoteToUpdate, newDraftPage.setTargetPageId(draftNoteToUpdate.getTargetPageId()); newDraftPage.setParentPageId(draftNoteToUpdate.getParentPageId()); newDraftPage.setContent(draftNoteToUpdate.getContent()); + newDraftPage.setLang(draftNoteToUpdate.getLang()); newDraftPage.setSyntax(draftNoteToUpdate.getSyntax()); newDraftPage.setCreatedDate(new Date(clientTime)); newDraftPage.setUpdatedDate(new Date(clientTime)); @@ -778,6 +786,7 @@ public DraftPage updateDraftForNewPage(DraftPage draftNoteToUpdate, long clientT newDraftPage.setParentPageId(draftNoteToUpdate.getParentPageId()); newDraftPage.setTargetPageRevision("1"); newDraftPage.setContent(draftNoteToUpdate.getContent()); + newDraftPage.setLang(draftNoteToUpdate.getLang()); newDraftPage.setSyntax(draftNoteToUpdate.getSyntax()); newDraftPage.setCreatedDate(new Date(clientTime)); newDraftPage.setUpdatedDate(new Date(clientTime)); @@ -803,6 +812,7 @@ public DraftPage createDraftForExistPage(DraftPage draftPage, newDraftPage.setTargetPageId(targetPage.getId()); newDraftPage.setParentPageId(draftPage.getParentPageId()); newDraftPage.setContent(draftPage.getContent()); + newDraftPage.setLang(draftPage.getLang()); newDraftPage.setSyntax(draftPage.getSyntax()); newDraftPage.setCreatedDate(new Date(clientTime)); newDraftPage.setUpdatedDate(new Date(clientTime)); @@ -817,7 +827,7 @@ public DraftPage createDraftForExistPage(DraftPage draftPage, newDraftPage.setTargetPageRevision(revision); } - newDraftPage = dataStorage.createDraftPageForUser(newDraftPage, Utils.getCurrentUser()); + newDraftPage = dataStorage.createDraftPageForUser(newDraftPage, username); return newDraftPage; } @@ -835,6 +845,7 @@ public DraftPage createDraftForNewPage(DraftPage draftPage, long clientTime) thr newDraftPage.setTargetPageRevision("1"); newDraftPage.setParentPageId(draftPage.getParentPageId()); newDraftPage.setContent(draftPage.getContent()); + newDraftPage.setLang(draftPage.getLang()); newDraftPage.setSyntax(draftPage.getSyntax()); newDraftPage.setCreatedDate(new Date(clientTime)); newDraftPage.setUpdatedDate(new Date(clientTime)); @@ -1427,4 +1438,49 @@ private Map> retrieveMetadataItems(String noteId, Str }); return metadata; } + + /** + * {@inheritDoc} + */ + @Override + public Page getNoteByIdAndLang(Long pageId, Identity userIdentity, String source, String lang) throws WikiException, + IllegalAccessException { + Page page = getNoteById(String.valueOf(pageId), userIdentity, source); + PageVersion publishedVersion = dataStorage.getPublishedVersionByPageIdAndLang(pageId, lang); + if (page != null && publishedVersion != null) { + page.setTitle(publishedVersion.getTitle()); + page.setContent(publishedVersion.getContent()); + page.setLang(publishedVersion.getLang()); + } + return page; + } + + /** + * {@inheritDoc} + */ + @Override + public List getPageAvailableTranslationLanguages(Long pageId) { + return dataStorage.getPageAvailableTranslationLanguages(pageId); + } + + /** + * {@inheritDoc} + */ + @Override + public List getVersionsHistoryOfNoteByLang(Page note, String userName, String lang) throws WikiException { + List pageHistories = dataStorage.getPageHistoryVersionsByPageIdAndLang(Long.valueOf(note.getId()), lang); + if (lang == null && pageHistories.isEmpty()) { + dataStorage.addPageVersion(note, userName); + pageHistories = dataStorage.getPageHistoryVersionsByPageIdAndLang(Long.valueOf(note.getId()), null); + } + return pageHistories; + } + + /** + * {@inheritDoc} + */ + @Override + public DraftPage getLatestDraftPageByUserAndTargetPageAndLang(Long targetPageId, String username, String lang) { + return dataStorage.getLatestDraftPageByUserAndTargetPageAndLang(targetPageId, username, lang); + } } diff --git a/notes-service/src/main/java/org/exoplatform/wiki/service/rest/NotesRestService.java b/notes-service/src/main/java/org/exoplatform/wiki/service/rest/NotesRestService.java index 2bfe7726b6..5f11d79046 100644 --- a/notes-service/src/main/java/org/exoplatform/wiki/service/rest/NotesRestService.java +++ b/notes-service/src/main/java/org/exoplatform/wiki/service/rest/NotesRestService.java @@ -38,8 +38,8 @@ import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang3.StringUtils; import org.exoplatform.social.rest.api.EntityBuilder; -import org.exoplatform.social.rest.api.RestUtils; import org.exoplatform.social.rest.entity.IdentityEntity; +import org.exoplatform.social.rest.api.RestUtils; import org.exoplatform.wiki.model.Attachment; import org.exoplatform.wiki.service.search.SearchResult; import org.exoplatform.wiki.service.search.SearchResultType; @@ -47,7 +47,6 @@ import org.exoplatform.wiki.service.search.WikiSearchData; import org.json.JSONObject; import org.gatein.api.EntityNotFoundException; -import org.json.JSONObject; import org.exoplatform.common.http.HTTPStatus; import org.exoplatform.commons.utils.HTMLSanitizer; import org.exoplatform.services.log.ExoLogger; @@ -208,12 +207,13 @@ public Response getNoteById(@Parameter(description = "Note id", required = true) @Parameter(description = "withChildren") @QueryParam("withChildren") boolean withChildren, - @Parameter(description = "source", required = false) - @QueryParam("source") - String source) { + @Parameter(description = "source") + @QueryParam("source") String source, + @Parameter(description = "note content language") + @QueryParam("lang") String lang) { try { Identity identity = ConversationState.getCurrent().getIdentity(); - Page note = noteService.getNoteById(noteId, identity, source); + Page note = noteService.getNoteByIdAndLang(Long.valueOf(noteId), identity, source, lang); if (note == null || note.isDeleted()) { return Response.status(Response.Status.NOT_FOUND).build(); } @@ -242,6 +242,31 @@ public Response getNoteById(@Parameter(description = "Note id", required = true) } } + @GET + @Path("/note/langs/{noteId}") + @Produces(MediaType.APPLICATION_JSON) + @RolesAllowed("users") + @Operation(summary = "Get available translation languages by page id", + method = "GET", + description = "This get gets the available translation languages by page id.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Request fulfilled"), + @ApiResponse(responseCode = "400", description = "Invalid query input"), + @ApiResponse(responseCode = "500", description = "Server internal error") }) + public Response getPageAvailableTranslationLanguages(@Parameter(description = "Note id", required = true) + @PathParam("noteId") Long noteId) { + if (noteId == null) { + return Response.status(Response.Status.BAD_REQUEST).entity("New document title is mandatory").build(); + } + try { + List languages = noteService.getPageAvailableTranslationLanguages(noteId); + return Response.ok(languages).type(MediaType.APPLICATION_JSON_TYPE).build(); + } catch (Exception e) { + log.error("Error while getting available translation languages of the page with id : {}", noteId, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } + } + @GET @Path("/draftNote/{noteId}") @Produces(MediaType.APPLICATION_JSON) @@ -252,12 +277,13 @@ public Response getNoteById(@Parameter(description = "Note id", required = true) @ApiResponse(responseCode = "403", description = "Unauthorized operation"), @ApiResponse(responseCode = "404", description = "Resource not found") }) public Response getDraftNoteById(@Parameter(description = "Note id", required = true) - @PathParam("noteId") - String noteId) { + @PathParam("noteId") Long noteId, + @Parameter(description = "draft content language") + @QueryParam("lang") String lang) { try { Identity identity = ConversationState.getCurrent().getIdentity(); String currentUserId = identity.getUserId(); - DraftPage draftNote = noteService.getDraftNoteById(noteId, currentUserId); + DraftPage draftNote = noteService.getDraftNoteByIdAndLang(noteId, currentUserId, lang); if (draftNote == null) { return Response.status(Response.Status.BAD_REQUEST).build(); } @@ -289,8 +315,9 @@ public Response getDraftNoteById(@Parameter(description = "Note id", required = @ApiResponse(responseCode = "403", description = "Unauthorized operation"), @ApiResponse(responseCode = "404", description = "Resource not found") }) public Response getLatestDraftOfPage(@Parameter(description = "Note id", required = true) - @PathParam("noteId") - String noteId) { + @PathParam("noteId") String noteId, + @Parameter(description = "draft content language") + @QueryParam("lang") String lang) { try { Identity identity = ConversationState.getCurrent().getIdentity(); String currentUserId = identity.getUserId(); @@ -298,8 +325,9 @@ public Response getLatestDraftOfPage(@Parameter(description = "Note id", require if (targetPage == null) { return Response.status(Response.Status.BAD_REQUEST).build(); } - DraftPage draftNote = noteService.getLatestDraftOfPage(targetPage, currentUserId); - + DraftPage draftNote = noteService.getLatestDraftPageByUserAndTargetPageAndLang(Long.valueOf(targetPage.getId()), + currentUserId, + lang); return Response.ok(draftNote != null ? draftNote : JSONObject.NULL).build(); } catch (Exception e) { log.error("Can't get draft note {}", noteId, e); @@ -317,15 +345,17 @@ public Response getLatestDraftOfPage(@Parameter(description = "Note id", require @ApiResponse(responseCode = "403", description = "Unauthorized operation"), @ApiResponse(responseCode = "404", description = "Resource not found") }) public Response getNoteVersions(@Parameter(description = "Note id", required = true) - @PathParam("noteId") - String noteId) { + @PathParam("noteId") String noteId, + @Parameter(description = "versions content language") + @QueryParam("lang") String lang) { try { Identity identity = ConversationState.getCurrent().getIdentity(); Page note = noteService.getNoteById(noteId, identity); if (note == null) { return Response.status(Response.Status.NOT_FOUND).build(); } - return Response.ok(noteService.getVersionsHistoryOfNote(note, identity.getUserId())).build(); + return Response.ok(noteService.getVersionsHistoryOfNoteByLang(note, identity.getUserId(), lang)) + .build(); } catch (IllegalAccessException e) { log.error("User does not have view permissions on the note {}", noteId, e); return Response.status(Response.Status.UNAUTHORIZED).build(); diff --git a/notes-service/src/main/resources/db/changelog/wiki.db.changelog-1.0.0.xml b/notes-service/src/main/resources/db/changelog/wiki.db.changelog-1.0.0.xml index 7ee7324c4d..9d5293cf71 100644 --- a/notes-service/src/main/resources/db/changelog/wiki.db.changelog-1.0.0.xml +++ b/notes-service/src/main/resources/db/changelog/wiki.db.changelog-1.0.0.xml @@ -720,4 +720,12 @@ + + + + + + + + \ No newline at end of file diff --git a/notes-service/src/test/java/org/exoplatform/wiki/service/TestNoteService.java b/notes-service/src/test/java/org/exoplatform/wiki/service/TestNoteService.java index 8bf0b2536b..f3a3aad673 100644 --- a/notes-service/src/test/java/org/exoplatform/wiki/service/TestNoteService.java +++ b/notes-service/src/test/java/org/exoplatform/wiki/service/TestNoteService.java @@ -29,6 +29,7 @@ import org.exoplatform.wiki.jpa.BaseTest; import org.exoplatform.wiki.model.*; import org.junit.Assert; +import org.junit.Test; import java.io.File; import java.io.IOException; @@ -313,6 +314,78 @@ public void testGEtNoteById() throws WikiException, IllegalAccessException { assertTrue(deletedNote.isDeleted()); } + public void testGetNoteByIdAndLang() throws WikiException, IllegalAccessException { + Identity root = new Identity("root"); + Wiki portalWiki = getOrCreateWiki(wService, PortalConfig.PORTAL_TYPE, "testPortal"); + Page note1 = noteService.createNote(portalWiki, "Home", new Page("testPage", "testPage"), root) ; + note1.setLang("en"); + noteService.createVersionOfNote(note1, "root"); + + assertNotNull(noteService.getNoteOfNoteBookByName(PortalConfig.PORTAL_TYPE, "testPortal", "testPage")) ; + + Page note = noteService.getNoteByIdAndLang(Long.valueOf(note1.getId()),root,"", "en"); + + assertNotNull(note); + assertEquals(note.getName(),note1.getName()); + + assertFalse(note.isDeleted()); + + noteService.deleteNote(note.getWikiType(), note.getWikiOwner(), note.getName()); + Page deletedNote = noteService.getNoteById(note1.getId(),root,""); + + assertNotNull(deletedNote); + assertTrue(deletedNote.isDeleted()); + } + + public void testGetPageAvailableTranslationLanguages() throws WikiException, IllegalAccessException { + Identity root = new Identity("root"); + Wiki portalWiki = getOrCreateWiki(wService, PortalConfig.PORTAL_TYPE, "testPortal"); + Page note = noteService.createNote(portalWiki, "Home", new Page("testLang", "testLang"), root) ; + note.setLang("ar"); + noteService.createVersionOfNote(note, "root"); + noteService.createVersionOfNote(note, "root"); + note.setLang("en"); + noteService.createVersionOfNote(note, "root"); + note.setLang("fr"); + noteService.createVersionOfNote(note, "root"); + + List langs = noteService.getPageAvailableTranslationLanguages(Long.valueOf(note.getId())); + + assertNotNull(langs); + assertEquals(3, langs.size()); + } + + public void testGetVersionsHistoryOfNoteByLang() throws WikiException, IllegalAccessException { + Identity root = new Identity("root"); + Wiki portalWiki = getOrCreateWiki(wService, PortalConfig.PORTAL_TYPE, "testPortal"); + Page note = noteService.createNote(portalWiki, "Home", new Page("testVersionHistory", "testVersionHistory"), root) ; + List pageHistories = noteService.getVersionsHistoryOfNoteByLang(note, "root", null); + assertEquals(1, pageHistories.size()); + assertNull(pageHistories.get(0).getLang()); + note.setLang("ar"); + noteService.createVersionOfNote(note, "root"); + pageHistories = noteService.getVersionsHistoryOfNoteByLang(note, "root", "ar"); + assertEquals(1, pageHistories.size()); + assertNotNull(pageHistories.get(0).getLang()); + assertEquals("ar", pageHistories.get(0).getLang()); + pageHistories = noteService.getVersionsHistoryOfNoteByLang(note, "root", "en"); + assertEquals(0, pageHistories.size()); + } + + public void testGetLatestDraftPageByUserAndTargetPageAndLang() throws WikiException, IllegalAccessException { + Identity root = new Identity("root"); + Wiki portalWiki = getOrCreateWiki(wService, PortalConfig.PORTAL_TYPE, "testPortal"); + Page note = noteService.createNote(portalWiki, "Home", new Page("testLatestDraft", "testLatestDraft"), root) ; + DraftPage draftPage = new DraftPage(); + draftPage.setTitle("test draft"); + draftPage.setContent(note.getContent()); + draftPage.setName("test draft"); + draftPage.setTargetPageId(note.getId()); + noteService.createDraftForExistPage(draftPage, note, null, new Date().getTime(), "root"); + DraftPage latestDraft = noteService.getLatestDraftPageByUserAndTargetPageAndLang(Long.valueOf(note.getId()), "root", null); + assertNotNull(latestDraft); + } + public void testGetNoteOfNoteBookByName() throws WikiException, IllegalAccessException { Identity root = new Identity("root"); Wiki portalWiki = getOrCreateWiki(wService, PortalConfig.PORTAL_TYPE, "testPortal"); diff --git a/notes-service/src/test/java/org/exoplatform/wiki/service/rest/NotesRestServiceTest.java b/notes-service/src/test/java/org/exoplatform/wiki/service/rest/NotesRestServiceTest.java index d0a7a9b84c..b5fb464d7d 100644 --- a/notes-service/src/test/java/org/exoplatform/wiki/service/rest/NotesRestServiceTest.java +++ b/notes-service/src/test/java/org/exoplatform/wiki/service/rest/NotesRestServiceTest.java @@ -155,19 +155,19 @@ public void getNoteById() throws WikiException, IllegalAccessException { List breadcrumb = new ArrayList<>(); breadcrumb.add(new BreadcrumbData("1", "test", "note", "user")); page.setDeleted(true); - when(noteService.getNoteById("1", identity, "source")).thenReturn(null); - Response response = notesRestService.getNoteById("1", "note", "user", true, "source"); + when(noteService.getNoteByIdAndLang(1L, identity, "source", null)).thenReturn(null); + Response response = notesRestService.getNoteById("1", "note", "user", true, "source", "en"); assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus()); - when(noteService.getNoteById("1", identity, "source")).thenReturn(page); - Response response1 = notesRestService.getNoteById("1", "note", "user", true, "source"); + when(noteService.getNoteByIdAndLang(1L, identity, "source", "en")).thenReturn(page); + Response response1 = notesRestService.getNoteById("1", "note", "user", true, "source", "en"); assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response1.getStatus()); page.setDeleted(false); page.setWikiType("type"); - Response response2 = notesRestService.getNoteById("1", "note", "user", true, "source"); + Response response2 = notesRestService.getNoteById("1", "note", "user", true, "source", "en"); assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response2.getStatus()); page.setWikiType("note"); page.setWikiOwner("owner"); - Response response3 = notesRestService.getNoteById("1", "note", "user", true, "source"); + Response response3 = notesRestService.getNoteById("1", "note", "user", true, "source", "en"); assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response3.getStatus()); page.setWikiOwner("user"); @@ -177,15 +177,15 @@ public void getNoteById() throws WikiException, IllegalAccessException { when(noteService.getBreadCrumb("note", "user", "1", false)).thenReturn(breadcrumb); when(noteService.updateNote(page)).thenReturn(page); - Response response4 = notesRestService.getNoteById("1", "note", "user", true, "source"); + Response response4 = notesRestService.getNoteById("1", "note", "user", true, "source", "en"); assertEquals(Response.Status.OK.getStatusCode(), response4.getStatus()); - doThrow(new IllegalAccessException("Fake Exception")).when(noteService).getNoteById("1", identity, "source"); - Response response5 = notesRestService.getNoteById("1", "note", "user", true, "source"); + doThrow(new IllegalAccessException("Fake Exception")).when(noteService).getNoteByIdAndLang(1L, identity, "source", "en"); + Response response5 = notesRestService.getNoteById("1", "note", "user", true, "source", "en"); assertEquals(Response.Status.UNAUTHORIZED.getStatusCode(), response5.getStatus()); - doThrow(new IllegalStateException("Fake Exception")).when(noteService).getNoteById("1", identity, "source"); - Response response6 = notesRestService.getNoteById("1", "note", "user", true, "source"); + doThrow(new IllegalStateException("Fake Exception")).when(noteService).getNoteByIdAndLang(1L, identity, "source", "en"); + Response response6 = notesRestService.getNoteById("1", "note", "user", true, "source", "en"); assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), response6.getStatus()); } @@ -314,4 +314,21 @@ public void getFullTreeData() throws Exception { Response response2 = notesRestService.getFullTreeData("path", true); assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), response2.getStatus()); } + + @Test + public void testGetPageAvailableTranslationLanguages() { + List langs = new ArrayList<>(); + langs.add("ar"); + langs.add("en"); + Response response = notesRestService.getPageAvailableTranslationLanguages(null); + assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus()); + when(noteService.getPageAvailableTranslationLanguages(1L)).thenReturn(langs); + response = notesRestService.getPageAvailableTranslationLanguages(1L); + assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + + doThrow(new RuntimeException()).when(noteService).getPageAvailableTranslationLanguages(2L); + response = notesRestService.getPageAvailableTranslationLanguages(2L); + assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus()); + + } }