Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

Commit

Permalink
add standard REST endpoints for original and processed uploaded docum…
Browse files Browse the repository at this point in the history
…ents
  • Loading branch information
davidmason committed Aug 17, 2012
1 parent 620af8a commit f66b13f
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 18 deletions.
Expand Up @@ -290,6 +290,16 @@ public void setLocaleId(String localeId)
this.localeId = localeId;
}

public boolean hasOriginal(String docPath, String docName)
{
return translationFileServiceImpl.hasPersistedDocument(projectSlug, iterationSlug, docPath, docName);
}

public String extensionOf(String docName)
{
return "." + translationFileServiceImpl.extractExtension(docName);
}

public String getDocumentNameFilter()
{
return documentNameFilter;
Expand Down
75 changes: 61 additions & 14 deletions zanata-war/src/main/java/org/zanata/rest/service/FileService.java
Expand Up @@ -65,7 +65,11 @@
@Consumes( { MediaType.APPLICATION_OCTET_STREAM })
public class FileService implements FileResource
{

public static final String RAW_DOWNLOAD_TEMPLATE = "/raw/{projectSlug}/{iterationSlug}";

private static final String SUBSTITUTE_APPROVED_AND_FUZZY = "half-baked";
private static final String SUBSTITUTE_APPROVED = "baked";

@In
private DocumentDAO documentDAO;

Expand All @@ -81,6 +85,30 @@ public class FileService implements FileResource
@In
private ResourceUtils resourceUtils;

@GET
@Path(RAW_DOWNLOAD_TEMPLATE)
// /file/raw/{projectSlug}/{iterationSlug}?docId={docId}
public Response downloadRawFile( @PathParam("projectSlug") String projectSlug,
@PathParam("iterationSlug") String iterationSlug,
@QueryParam("docId") String docId)
{
final Response response;
HDocument document = this.documentDAO.getByProjectIterationAndDocId(projectSlug, iterationSlug, docId);

if( document != null && translationFileServiceImpl.hasPersistedDocument(projectSlug, iterationSlug, document.getPath(), document.getName()))
{
InputStream fileContents = translationFileServiceImpl.streamDocument(projectSlug, iterationSlug, document.getPath(), document.getName());
StreamingOutput output = new InputStreamStreamingOutput(fileContents);
response = Response.ok()
.header("Content-Disposition", "attachment; filename=\"" + document.getName() + "\"")
.entity(output).build();
}
else
{
response = Response.status(Status.NOT_FOUND).build();
}
return response;
}

/**
* Downloads a single translation file.
Expand All @@ -106,7 +134,7 @@ public Response downloadTranslationFile( @PathParam("projectSlug") String projec
@PathParam("fileType") String fileExtension,
@QueryParam("docId") String docId )
{
final Response response;
final Response response;
HDocument document = this.documentDAO.getByProjectIterationAndDocId(projectSlug, iterationSlug, docId);

if( document == null )
Expand All @@ -118,7 +146,7 @@ else if ("po".equals(fileExtension))
final Set<String> extensions = new HashSet<String>();
extensions.add("gettext");
extensions.add("comment");

// Perform translation of Hibernate DTOs to JAXB DTOs
TranslationsResource transRes =
(TranslationsResource) this.translatedDocResourceService.getTranslations(docId, new LocaleId(locale), extensions, true).getEntity();
Expand All @@ -129,38 +157,35 @@ else if ("po".equals(fileExtension))
.header("Content-Disposition", "attachment; filename=\"" + document.getName() + ".po\"")
.entity(output).build();
}

// TODO decide whether to have one URL for original format, or use fileExtension for all
else if (translationFileServiceImpl.hasAdapterFor(fileExtension) &&
translationFileServiceImpl.hasPersistedDocument(projectSlug, iterationSlug, document.getPath(), document.getName()))
else if ( (SUBSTITUTE_APPROVED.equals(fileExtension) || SUBSTITUTE_APPROVED_AND_FUZZY.equals(fileExtension))
&& translationFileServiceImpl.hasPersistedDocument(projectSlug, iterationSlug, document.getPath(), document.getName()))
{
final Set<String> extensions = Collections.<String>emptySet();
TranslationsResource transRes =
(TranslationsResource) this.translatedDocResourceService.getTranslations(docId, new LocaleId(locale), extensions, true).getEntity();
// Filter translations to only provide approved translations.
// "Preview" downloads should include fuzzy as well.
// New list is used as transRes list appears not to be a modifiable implementation.
// Filter to only provide translated targets. "Preview" downloads include fuzzy.
// Using new list is used as transRes list appears not to be a modifiable implementation.
List<TextFlowTarget> translations = new ArrayList<TextFlowTarget>();
boolean useFuzzy = SUBSTITUTE_APPROVED_AND_FUZZY.equals(fileExtension);
for (TextFlowTarget target : transRes.getTextFlowTargets())
{
if (target.getState() == ContentState.Approved)
if (target.getState() == ContentState.Approved || (useFuzzy && target.getState() == ContentState.NeedReview))
{
translations.add(target);
}
}

InputStream fileContents = translationFileServiceImpl.streamDocument(projectSlug, iterationSlug, document.getPath(), document.getName());
StreamingOutput output = new FormatAdapterStreamingOutput(fileContents, translations, locale, translationFileServiceImpl.getAdapterFor(fileExtension));
StreamingOutput output = new FormatAdapterStreamingOutput(fileContents, translations, locale, translationFileServiceImpl.getAdapterFor(docId));
response = Response.ok()
.header("Content-Disposition", "attachment; filename=\"" + document.getName() + "\"")
.entity(output).build();
}
else
{
// TODO check if this media type is appropriate
response = Response.status(Status.UNSUPPORTED_MEDIA_TYPE).build();
}

return response;
}

Expand Down Expand Up @@ -239,6 +264,28 @@ public void write(OutputStream output) throws IOException, WebApplicationExcepti
}
}

private class InputStreamStreamingOutput implements StreamingOutput
{
private InputStream input;

public InputStreamStreamingOutput(InputStream input)
{
this.input = input;
}

@Override
public void write(OutputStream output) throws IOException, WebApplicationException
{
byte[] buffer = new byte[4096]; // To hold file contents
int bytesRead; // How many bytes in buffer

while ((bytesRead = input.read(buffer)) != -1)
{
output.write(buffer, 0, bytesRead);
}
}
}

private class FormatAdapterStreamingOutput implements StreamingOutput
{
private List<TextFlowTarget> translations;
Expand Down
Expand Up @@ -74,5 +74,12 @@ public interface TranslationFileService
*/
InputStream streamDocument(String projectSlug, String iterationSlug, String docPath, String docName);

/**
*
* @param fileNameOrExtension
* @return the extension for a given filename, or the extension that was passed in
*/
String extractExtension(String fileNameOrExtension);


}
Expand Up @@ -180,7 +180,8 @@ public FileFormatAdapter getAdapterFor(String fileNameOrExtension)
}
}

private String extractExtension(String fileNameOrExtension)
@Override
public String extractExtension(String fileNameOrExtension)
{
if (fileNameOrExtension == null || fileNameOrExtension.length() == 0 || fileNameOrExtension.endsWith("."))
{
Expand Down
5 changes: 2 additions & 3 deletions zanata-war/src/main/webapp/iteration/files.xhtml
Expand Up @@ -98,10 +98,9 @@
<f:param name="docId" value="#{doc.docId}"/>
<h:outputText value="#{messages['jsf.iteration.files.dotpo']}"/>
</s:link>
<s:link styleClass="table_link" view="/rest/file/translation/#{projectIterationFilesAction.projectSlug}/#{projectIterationFilesAction.iterationSlug}/#{projectIterationFilesAction.localeId}/txt">
<s:link rendered="#{projectIterationFilesAction.hasOriginal(doc.path, doc.name)}" styleClass="table_link" view="/rest/file/translation/#{projectIterationFilesAction.projectSlug}/#{projectIterationFilesAction.iterationSlug}/#{projectIterationFilesAction.localeId}/baked">
<f:param name="docId" value="#{doc.docId}"/>
<!-- TODO replace with original format link, only if available -->
<h:outputText value=".txt"/>
<h:outputText value="#{projectIterationFilesAction.extensionOf(doc.name)}"/>
</s:link>
</rich:column>
<rich:column rendered="#{projectIterationFilesAction.fileUploadAllowed}">
Expand Down

0 comments on commit f66b13f

Please sign in to comment.