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

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