Commit bae81f7b authored by Matija Obreza's avatar Matija Obreza
Browse files

Removed TransifexTranslation model, service and repository

parent f295095d
......@@ -16,13 +16,20 @@
package org.genesys2.server.model.impl;
import java.util.Calendar;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.genesys2.server.model.AuditedModel;
import org.hibernate.annotations.Type;
import javax.persistence.*;
import java.util.Calendar;
import java.util.List;
@Entity
@Table(name = "article")
public class Article extends AuditedModel {
......@@ -54,9 +61,6 @@ public class Article extends AuditedModel {
@Column(length = 100000)
private String body;
@OneToMany(mappedBy = "article",fetch = FetchType.LAZY, cascade = CascadeType.REMOVE, orphanRemoval = true)
private List<TransifexTranslation> transifexTranslations;
@Temporal(TemporalType.TIMESTAMP)
private Calendar postDate;
......@@ -115,13 +119,4 @@ public class Article extends AuditedModel {
public void setLang(String lang) {
this.lang = lang;
}
public List<TransifexTranslation> getTranslations() {
return transifexTranslations;
}
public void setTranslations(List<TransifexTranslation> translations) {
this.transifexTranslations = translations;
}
}
package org.genesys2.server.model.impl;
import org.genesys2.server.model.BusinessModel;
import javax.persistence.*;
@Entity
@Table(name = "transifextranslation")
public class TransifexTranslation extends BusinessModel{
private static final long serialVersionUID = 1L;
@Column
private String translatedLang;
@Column
private boolean transifexed;
@ManyToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name = "article_id", nullable = false)
private Article article;
public String getTranslatedLang() {
return translatedLang;
}
public void setTranslatedLang(String translatedLang) {
this.translatedLang = translatedLang;
}
public boolean isTransifexed() {
return transifexed;
}
public void setTransifexed(boolean transifexed) {
this.transifexed = transifexed;
}
public Article getArticle() {
return article;
}
public void setArticle(Article article) {
this.article = article;
}
}
package org.genesys2.server.persistence.domain;
import org.genesys2.server.model.impl.TransifexTranslation;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface TransifextranslationRepository extends JpaRepository<TransifexTranslation, Long>{
@Query("select tt from TransifexTranslation tt join tt.article a where a.id = :articleId")
List<TransifexTranslation> findByArticleId(@Param("articleId")Long articleId);
}
package org.genesys2.server.service;
import org.genesys2.server.model.impl.TransifexTranslation;
import java.util.List;
public interface TransifexTranslationService {
TransifexTranslation getTransifexTranslation(Long id);
void save(String articleName, TransifexTranslation transifexTranslations);
void deleteTransifexTranslation(Long id);
List<TransifexTranslation> findAll();
List<TransifexTranslation> findAllByArticleId(Long articleId);
}
......@@ -70,6 +70,7 @@ public class ContentServiceImpl implements ContentService {
@Override
public Locale getDefaultLocale() {
// TODO FIXME We should use a configurable default locale for content service
return Locale.getDefault();
}
......
package org.genesys2.server.service.impl;
import org.genesys2.server.model.impl.Article;
import org.genesys2.server.model.impl.ClassPK;
import org.genesys2.server.model.impl.TransifexTranslation;
import org.genesys2.server.persistence.domain.ArticleRepository;
import org.genesys2.server.persistence.domain.ClassPKRepository;
import org.genesys2.server.persistence.domain.TransifextranslationRepository;
import org.genesys2.server.service.TransifexTranslationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@Transactional
public class TransifexTranslationServiceImpl implements TransifexTranslationService {
@Autowired
private TransifextranslationRepository transifextranslationRepository;
@Autowired
private ArticleRepository articleRepository;
@Autowired
private ClassPKRepository classPKRepository;
@Override
public TransifexTranslation getTransifexTranslation(Long id) {
return transifextranslationRepository.getOne(id);
}
@Override
public void save(String articleName, TransifexTranslation transifexTranslations) {
ClassPK articleClassPk = classPKRepository.findByClassName(Article.class.getName());
Article article = articleRepository.findByClassPkAndTargetIdAndSlugAndLang(articleClassPk,
null, articleName, LocaleContextHolder.getLocale().getLanguage());
if (article != null) {
transifexTranslations.setArticle(article);
transifextranslationRepository.save(transifexTranslations);
}
}
@Override
public void deleteTransifexTranslation(Long id) {
transifextranslationRepository.delete(id);
}
@Override
public List<TransifexTranslation> findAll() {
return transifextranslationRepository.findAll();
}
@Override
public List<TransifexTranslation> findAllByArticleId(Long articleId) {
return transifextranslationRepository.findByArticleId(articleId);
}
}
package org.genesys2.server.servlet.controller.transifex;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Locale;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.genesys2.server.model.impl.Article;
import org.genesys2.server.model.impl.TransifexTranslation;
import org.genesys2.server.service.ContentService;
import org.genesys2.server.service.TransifexTranslationService;
import org.genesys2.server.servlet.controller.BaseController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.*;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.LinkedMultiValueMap;
......@@ -20,216 +29,249 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import java.io.*;
@Controller
@RequestMapping(value = "/transifex")
public class TransifexAPIController extends BaseController{
@Autowired
private ContentService contentService;
@Autowired
private TransifexTranslationService translationService;
@Value("${transifex.project}")
private String projectSlug;
@Value("${transifex.username}")
private String trasifexUserName;
@Value("${transifex.password}")
private String transifexPassord;
@Value("${transifex.base.api.url}")
private String baseApiURL;
@Value("${transifex.content.template}")
private String contentTemplate;
@Value("${transifex.min.translated}")
private int transifexMinTranslated;
private RestTemplate template = new RestTemplate();
@RequestMapping(value = "/deleteContent/{slug}")
public String deleteResource(@PathVariable String slug, Model model) {
//make authentication for Transifex
HttpHeaders headers = basicAuthentication();
Article article = contentService.getGlobalArticle(slug, getLocale());
if (resourceExists(article)) {
StringBuilder url = new StringBuilder();
url.append("project/");
url.append(projectSlug);
url.append("/resource/");
url.append("article-");
url.append(article.getSlug());
HttpEntity<String> request = new HttpEntity<>(headers);
ResponseEntity<String> response = template.exchange(baseApiURL + url, HttpMethod.DELETE, request, String.class);
if(response.getStatusCode().value() == 204){
model.addAttribute("result", "deleted ok");
}
}else{
model.addAttribute("result", "not exists");
}
model.addAttribute("title", article.getTitle());
model.addAttribute("article", article);
return "/content/article-edit";
}
/**
* Use "magic" SHA1 hash value just for some security purposes
*
* Note: the very same value should be in Transifex preferences
*
* @see classpath:spring/spring-security.xml
*/
@RequestMapping(value = "/hooks/40874cca86ca396169a5f4e6ebf6e4bf7199c4e7", method = RequestMethod.POST)
public void webHookHandle(@RequestParam(value = "project") String projectSlug,
@RequestParam(value = "resource") String resource,
@RequestParam(value = "language") String language,
@RequestParam(value = "translated") int translatedPercentage, Model model){
//TODO may be revisit this
//currently we do this due to nature of Transifex hook
String articleName = resource.split("-")[1];
if(translatedPercentage == transifexMinTranslated){
TransifexTranslation translation = new TransifexTranslation();
translation.setTransifexed(true);
translation.setTranslatedLang(language);
translationService.save(articleName, translation);
}
}
@RequestMapping(value = "/translate/{slug}/{lang}", method = RequestMethod.GET)
public String translateArticles(@PathVariable String lang, @PathVariable String slug, Model model) {
//make authentication for Transifex
HttpHeaders headers = basicAuthentication();
//Extract article from database we need
Article article = contentService.getGlobalArticle(slug, getLocale());
StringBuilder url = new StringBuilder()
.append("project/")
.append(projectSlug)
.append("/resource/")
.append("article-")
.append(slug)
.append("/translation/")
.append(lang)
.append("/?file");
HttpEntity<String> request = new HttpEntity<>(headers);
ResponseEntity<String> response = template.exchange(baseApiURL + url, HttpMethod.GET, request, String.class);
String title = response.getBody().split("<title>")[1].split("</title>")[0];
String body = response.getBody().split("<body>")[1].split("</body>")[0];
contentService.updateArticle(article.getId(), article.getSlug(), title, body);
model.addAttribute("title", article.getTitle());
model.addAttribute("article", article);
return "/content/article-edit";
}
@RequestMapping(value = "/postContent/{slug}")
public String postResourceToTransifex(@PathVariable String slug, Model model) throws IOException {
//Make the authentication for Transifex
HttpHeaders headers = basicAuthentication();
//Extract article from database we need
Article article = contentService.getGlobalArticle(slug, getLocale(), false);
if (!resourceExists(article)) {
//We will request like MULTIPART_FORM_DATA
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
//This is template our xhtml
String content = String.format(contentTemplate, article.getTitle(), article.getBody());
//Create Multi
// value map with all necessary information for request
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add("slug", "article-"+slug);
map.add("name", article.getTitle());
map.add("i18n_type", "XHTML");
File tempFile = File.createTempFile(slug, ".xhtml");
public class TransifexAPIController extends BaseController {
@Autowired
private ContentService contentService;
@Value("${transifex.project}")
private String projectSlug;
@Value("${transifex.username}")
private String trasifexUserName;
@Value("${transifex.password}")
private String transifexPassord;
@Value("${transifex.base.api.url}")
private String baseApiURL;
@Value("${transifex.content.template}")
private String contentTemplate;
@Value("${transifex.min.translated}")
private int transifexMinTranslated;
private RestTemplate template = new RestTemplate();
@RequestMapping(value = "/deleteContent/{slug}")
public String deleteResource(@PathVariable String slug, Model model) {
// make authentication for Transifex
HttpHeaders headers = basicAuthentication();
Article article = contentService.getGlobalArticle(slug, getLocale());
if (resourceExists(article)) {
StringBuilder url = new StringBuilder();
url.append("project/");
url.append(projectSlug);
url.append("/resource/");
url.append("article-");
url.append(article.getSlug());
HttpEntity<String> request = new HttpEntity<>(headers);
ResponseEntity<String> response = template.exchange(baseApiURL + url, HttpMethod.DELETE, request, String.class);
if (response.getStatusCode().value() == 204) {
model.addAttribute("result", "deleted ok");
}
} else {
model.addAttribute("result", "not exists");
}
model.addAttribute("title", article.getTitle());
model.addAttribute("article", article);
return "/content/article-edit";
}
/**
* Use "magic" SHA1 hash value just for some security purposes
*
* Note: the very same value should be in Transifex preferences
*
* @see classpath:spring/spring-security.xml
*/
// FIXME make "magic" configurable
@RequestMapping(value = "/hook/40874cca86ca396169a5f4e6ebf6e4bf7199c4e7", method = RequestMethod.POST)
public @ResponseBody
String webHookHandle(@RequestParam(value = "project") String projectSlug, @RequestParam(value = "resource") String resource,
@RequestParam(value = "language") String language, @RequestParam(value = "translated") Integer translatedPercentage, Model model) {
// FIXME remove once confirmed to work
_logger.warn("project=" + projectSlug + " resource=" + resource + " lang=" + language + " translated=" + translatedPercentage);
// TODO may be revisit this
// currently we do this due to nature of Transifex hook
if (!resource.startsWith("article-")) {
_logger.warn("Ignoring Transifex'd hook for " + resource);
return "Ignored";
}
String slug = resource.split("-")[1];
_logger.warn("Transifex'd article slug=" + slug);
if (translatedPercentage != null && translatedPercentage.intValue() >= transifexMinTranslated) {
// fetch updated resource from Transifex
updateArticle(slug, language);
return "Thanks!";
} else {
return "Not sufficiently translated";
}
}
/**
* Get translated contents from Transifex and update the local Article.
*
* @param lang
* @param slug
* @param model
* @return
*/
@RequestMapping(value = "/translate/{slug}/{lang}", method = RequestMethod.GET)
public String translateArticles(@PathVariable String lang, @PathVariable String slug, Model model) {
Article article = updateArticle(slug, lang);
model.addAttribute("title", article.getTitle());
model.addAttribute("article", article);
return "/content/article-edit";
}
private Article updateArticle(String slug, String lang) {
_logger.info("Fetching updated translation for article " + slug + " lang=" + lang);
// make authentication for Transifex
HttpHeaders headers = basicAuthentication();
StringBuilder url = new StringBuilder().append("project/").append(projectSlug).append("/resource/").append("article-").append(slug)
.append("/translation/").append(lang).append("/?file");
HttpEntity<String> request = new HttpEntity<>(headers);
ResponseEntity<String> response = template.exchange(baseApiURL + url, HttpMethod.GET, request, String.class);
// TODO FIXME Check response status. Proceed only on HTTP OK response.
_logger.info("Response code=" + response.getStatusCode());
String title = response.getBody().split("<title>")[1].split("</title>")[0];
String body = response.getBody().split("<body>")[1].split("</body>")[0];
Locale locale = new Locale(lang);
// Extract article from database we need (correct locale + do not use
// default (EN) language)
Article article = contentService.getGlobalArticle(slug, locale, false);
if (article == null) {
// No article for selected locale
article = contentService.createGlobalArticle(slug, locale, title, body);
} else {
// Update article for locale
article = contentService.updateArticle(article.getId(), article.getSlug(), title, body);
}
_logger.info("Updated translation for article " + slug + " lang=" + lang);
return article;
}
@RequestMapping(value = "/postContent/{slug:.+}")
public String postResourceToTransifex(@PathVariable String slug, Model model) throws IOException {
_logger.info("Posting to transifex slug=" + slug);
// Make the authentication for Transifex
HttpHeaders headers = basicAuthentication();
// Extract article from database we need
Article article = contentService.getGlobalArticle(slug, contentService.getDefaultLocale(), false);
if (!resourceExists(article)) {
// We will request like MULTIPART_FORM_DATA
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
// This is template our xhtml
String content = String.format(contentTemplate, article.getTitle(), article.getBody());
// Create Multi value map with all necessary information for request
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add("slug", "article-" + slug);
map.add("name", article.getTitle());
map.add("i18n_type", "XHTML");
File tempFile = File.createTempFile(slug, ".xhtml");
//default FileWriter support default encoding only
try (BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile))){
IOUtils.write(content, writer);
System.err.println(content);
IOUtils.write(content, writer);
writer.flush();
Resource resource = new FileSystemResource(tempFile);
map.add("content", resource);
//Create our request entity
HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(map, headers);
StringBuilder url = new StringBuilder();
url.append("project/");
url.append(projectSlug);
url.append("/resources/");
//Send our post request(with .xhtml file) to Transifex
template.postForLocation(baseApiURL + url, request);
model.addAttribute("responseFromTransifex", "Resource added");
} catch (HttpClientErrorException e) {
model.addAttribute("responseFromTransifex", "fail");
}
}else{