Commit f1cf8d1b authored by Alexander Basov's avatar Alexander Basov Committed by Matija Obreza

Moved Transifex code to TransifexServiceImpl

Added TransifexClientTest to see behavior of their API
parent 9a0714d4
......@@ -64,6 +64,7 @@
<oval.version>1.81</oval.version>
<jackson.version>2.2.1</jackson.version>
<jaxb-api.version>2.1</jaxb-api.version>
<!--Container -->
<jetty.version>9.1.2.v20140210</jetty.version>
......@@ -302,11 +303,17 @@
<version>${oval.version}</version>
</dependency>
<!--<dependency> -->
<!--<groupId>com.fasterxml.jackson.core</groupId> -->
<!--<artifactId>jackson-databind</artifactId> -->
<!--<version>${jackson.version}</version> -->
<!--</dependency> -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxb-api.version}</version>
<scope>runtime</scope>
</dependency>
<!--Jetty -->
......@@ -508,7 +515,20 @@
<artifactId>urlrewritefilter</artifactId>
<version>4.0.4</version>
</dependency>
</dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
<!--dom4j-->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
</dependencies>
<build>
<plugins>
......
......@@ -16,20 +16,12 @@
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;
@Entity
@Table(name = "article")
public class Article extends AuditedModel {
......@@ -61,6 +53,8 @@ public class Article extends AuditedModel {
@Column(length = 100000)
private String body;
private boolean transifexed = true;
@Temporal(TemporalType.TIMESTAMP)
private Calendar postDate;
......@@ -119,4 +113,12 @@ public class Article extends AuditedModel {
public void setLang(String lang) {
this.lang = lang;
}
public boolean isTransifexed() {
return transifexed;
}
public void setTransifexed(boolean transifexed) {
this.transifexed = transifexed;
}
}
package org.genesys2.server.servlet.controller.transifex;
import org.apache.commons.codec.binary.Base64;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.io.HTMLWriter;
import org.dom4j.io.OutputFormat;
import org.genesys2.server.model.impl.Article;
import org.genesys2.server.service.ContentService;
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.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
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.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
@Controller
@RequestMapping(value = "/transifex")
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.min.translated}")
private String minTranslatedValue;
@Value("${transifex.base.api.url}")
private String baseApiURL;
private RestTemplate template;
private HttpHeaders headers;
@RequestMapping(value = "/deleteContent/{slug}")
public String deleteResource(@PathVariable String slug, Model model) {
//make authentication for Transifex
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");
}
}
model.addAttribute("title", article.getTitle());
model.addAttribute("article", article);
return "/content/article-edit";
}
@RequestMapping(value = "/hooks", 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 translated){
System.out.println(projectSlug+" done \n");
}
@RequestMapping(value = "/translate/{slug}/{lang}", method = RequestMethod.GET)
public String translateArticles(@PathVariable String lang, @PathVariable String slug, Model model) throws DocumentException {
//make authentication for Transifex
basicAuthentication();
//Extract article from database we need
Article article = contentService.getGlobalArticle(slug, getLocale());
StringBuilder url = new StringBuilder();
url.append("project/");
url.append(projectSlug);
url.append("/resource/");
url.append("article-");
url.append(slug);
url.append("/translation/");
url.append(lang);
url.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];
article.setTitle(title);
article.setBody(body);
contentService.updateArticle(article.getId(), article.getSlug(), article.getTitle(), article.getBody());
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, DocumentException {
//We want to sent .xhtml file to transifex, for this we use dom4j
//Make the authentication for Transifex
basicAuthentication();
//Extract article from database we need
Article article = contentService.getGlobalArticle(slug, getLocale(), false);
//Create temporary file articleSlug.xhtml
String filePath = "/home/alexander/Downloads/"+article.getSlug()+".xhtml";
File xhtmlFile = new File(filePath);
xhtmlFile.createNewFile();
//Create dom4j document witch will be containing xhtml content
Document xhtmlDocument;
//Define xhtml output format for HTMLWriter
OutputFormat outputFormat = OutputFormat.createPrettyPrint();
outputFormat.setXHTML(true);
HTMLWriter writer = new HTMLWriter(new FileWriter(xhtmlFile), outputFormat);
if (!resourceExists(article)) {
//We will request like MULTIPART_FORM_DATA
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
//This is template our xhtml
String content = "<html xmlns=\"http://www.w3.org/1999/xhtml\"> \n" +
" <head> \n" +
"<meta http-equiv=\"CONTENT-TYPE\" content=\"text/html; charset=utf­8\"/> \n" +
"<title>"+article.getTitle()+"</title> \n" +
" </head> \n" +
" <body>"+article.getBody()+"</body> \n" +
"</html>";
//Parse String content and write it into articleSlug.xhtml file
xhtmlDocument = DocumentHelper.parseText(content);
writer.write(xhtmlDocument);
writer.flush();
//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");
Resource resource = new FileSystemResource(filePath);
map.add("content", resource);
//Create our request entity
HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(map, headers);
model.addAttribute("title", article.getTitle());
model.addAttribute("article", article);
StringBuilder url = new StringBuilder();
url.append("project/");
url.append(projectSlug);
url.append("/resources/");
try {
//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");
}
//After all operations, temporary .xhtml file is deleted
xhtmlFile.delete();
}
return "/content/article-edit";
}
//Transifex requires Basic HTTP authentication!
//This method make authentication for Transifex
public void basicAuthentication() {
template = new RestTemplate();
headers = new HttpHeaders();
String trasifexCreds = trasifexUserName + ":" + transifexPassord;
byte[] transifexCredsBytes = trasifexCreds.getBytes();
byte[] base64CredsBytes = Base64.encodeBase64(transifexCredsBytes);
String base64Creds = new String(base64CredsBytes);
headers.add("Authorization", "Basic " + base64Creds);
}
//This method verify if article already exists in Transifex
public boolean resourceExists(Article resource) {
//make authentication for Transifex
basicAuthentication();
StringBuilder url = new StringBuilder();
url.append("project/");
url.append(projectSlug);
url.append("/resource/");
url.append("article-");
url.append(resource.getSlug());
ResponseEntity<String> response;
HttpEntity<String> request = new HttpEntity<>(headers);
try {
response = template.exchange(baseApiURL + url, HttpMethod.GET, request, String.class);
} catch (HttpClientErrorException e) {
return false;
}
return response.getStatusCode().value() == 200;
}
}
......@@ -125,3 +125,9 @@ cache.tileserver.eviction-policy=LRU
# Connection to Elasticsearch
elasticsearch.url=http://localhost:9200/
transifex.project=genesys-dev
transifex.username=Alexandr19011990
transifex.password=Alexandr19011990
transifex.min.translated=80
transifex.base.api.url =https://www.transifex.com/api/2/
<!DOCTYPE html>
<%@include file="/WEB-INF/jsp/init.jsp"%>
<%@include file="/WEB-INF/jsp/init.jsp" %>
<html>
<head>
<title>${title}</title>
<title>${title}</title>
</head>
<body>
<h1>
<spring:message code="article.edit-article" />
</h1>
<form role="form" class="" action="<c:url value="/content/save-article" />" method="post">
<c:if test="${article.id ne null}">
<input type="hidden" name="id" value="${article.id}" />
</c:if>
<div class="form-group">
<label for="article-slug" class="control-label"><spring:message code="article.slug" /></label>
<div class="controls">
<input type="text" id="article-slug" name="slug" value="<c:out value="${article.slug}" />" class="span9 form-control required" />
</div>
</div>
<div class="form-group">
<label for="article-title" class="control-label"><spring:message code="article.title" /></label>
<div class="controls">
<input type="text" id="article-title" name="title" value="<c:out value="${article.title}" />" class="span9 form-control required" />
</div>
</div>
<div class="form-group">
<label for="article-body" class="control-label"><spring:message code="article.body" /></label>
<div class="controls">
<textarea id="article-body" name="body" class="span9 required form-control html-editor"><c:out value="${article.body}" escapeXml="false" /></textarea>
</div>
</div>
<input type="submit" value="<spring:message code="save"/>" class="btn btn-primary" />
<a href="<c:url value="${article.id ne null ? '/content/'.concat(article.slug) : '/' }" />" class="btn btn-default">Cancel</a>
<!-- CSRF protection -->
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form>
<content tag="javascript">
<script type="text/javascript" src="/html/js/tinymce/tinymce.min.js"></script>
<script type="text/javascript">
jQuery(document).ready(function() {
if (window.location.hash=='#raw') {
} else {
tinyMCE.init({
selector : ".html-editor",
menubar : false,
statusbar : false,
height : 200,
plugins: "link autolink code",
directionality : document.dir,
<h1>
<spring:message code="article.edit-article"/>
</h1>
<div class="form-group">
<div> ${responseFromTransifex}</div>
<a href="<c:url value="/transifex/postContent/${article.slug}"/>" class="btn btn-default">Post to Transifex</a>
</div>
<div class="form-group">
<div> ${result}</div>
<a href="<c:url value="/transifex/deleteContent/${article.slug}"/>" class="btn btn-default">Delete from
Transifex</a>
</div>
<div class="form-group">
<div class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><c:out value="Transifex's translate" /> <b class="caret"></b></a>
<ul class="dropdown-menu" role="menu">
<li><a href="${pageContext.request.contextPath}/transifex/translate/${article.slug}/${"en"}">English</a></li>
<li><a href="${pageContext.request.contextPath}/transifex/translate/${article.slug}/${"es"}">Spanish</a></li>
<li><a href="${pageContext.request.contextPath}/transifex/translate/${article.slug}/${"ar"}">Arabic</a></li>
<li><a href="${pageContext.request.contextPath}/transifex/translate/${article.slug}/${"zh"}">Chinese</a></li>
<li><a href="${pageContext.request.contextPath}/transifex/translate/${article.slug}/${"fr"}">French</a></li>
<li><a href="${pageContext.request.contextPath}/transifex/translate/${article.slug}/${"de"}">German</a></li>
<li><a href="${pageContext.request.contextPath}/transifex/translate/${article.slug}/${"fa"}">Persian</a></li>
<li><a href="${pageContext.request.contextPath}/transifex/translate/${article.slug}/${"ru"}">Russian</a></li>
</ul>
</div>
</div>
<form role="form" class="" action="<c:url value="/content/save-article" />" method="post">
<c:if test="${article.id ne null}">
<input type="hidden" name="id" value="${article.id}"/>
</c:if>
<div class="form-group">
<label for="article-slug" class="control-label"><spring:message code="article.slug"/></label>
<div class="controls">
<input type="text" id="article-slug" name="slug" value="<c:out value="${article.slug}" />"
class="span9 form-control required"/>
</div>
</div>
<div class="form-group">
<label for="article-title" class="control-label"><spring:message code="article.title"/></label>
<div class="controls">
<input type="text" id="article-title" name="title" value="<c:out value="${article.title}" />"
class="span9 form-control required"/>
</div>
</div>
<div class="form-group">
<label for="article-body" class="control-label"><spring:message code="article.body"/></label>
<div class="controls">
<textarea id="article-body" name="body" class="span9 required form-control html-editor"><c:out
value="${article.body}" escapeXml="false"/></textarea>
</div>
</div>
<input type="submit" value="<spring:message code="save"/>" class="btn btn-primary"/>
<a href="<c:url value="${article.id ne null ? '/content/'.concat(article.slug) : '/' }" />" class="btn btn-default">Cancel</a>
<!-- CSRF protection -->
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form>
<content tag="javascript">
<script type="text/javascript" src="/html/js/tinymce/tinymce.min.js"></script>
<script type="text/javascript">
jQuery(document).ready(function () {
if (window.location.hash == '#raw') {
} else {
tinyMCE.init({
selector: ".html-editor",
menubar: false,
statusbar: false,
height: 200,
plugins: "link autolink code",
directionality: document.dir,
convert_urls: false
});
}
});
</script>
});
}
});
</script>
</content>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment