TMService { @Transactional public String exportAssetAsXLIFF(Long assetId, String bcp47Tag) { logger.debug("Export data for asset id: {} and locale: {}", assetId, bcp47Tag); logger.trace("Create XLIFFWriter"); XLIFFWriter xliffWriter = new XLIFFWriter(); logger.trace("Prepare FilterEventsWriterStep to use an XLIFFWriter with outputstream (allows only one doc to be processed)"); FilterEventsWriterStep filterEventsWriterStep = new FilterEventsWriterStep(xliffWriter); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); filterEventsWriterStep.setOutputStream(byteArrayOutputStream); filterEventsWriterStep.setOutputEncoding(StandardCharsets.UTF_8.toString()); logger.trace("Prepare the Okapi pipeline"); IPipelineDriver driver = new PipelineDriver(); driver.addStep(new RawDocumentToFilterEventsStep(new TMExportFilter(assetId))); driver.addStep(filterEventsWriterStep); logger.trace("Add single document with fake output URI to be processed with an outputStream"); Locale locale = localeService.findByBcp47Tag(bcp47Tag); RawDocument rawDocument = new RawDocument(RawDocument.EMPTY, LocaleId.ENGLISH, LocaleId.fromBCP47(locale.getBcp47Tag())); driver.addBatchItem(rawDocument, RawDocument.getFakeOutputURIForStream(), null); logger.debug("Start processing batch"); driver.processBatch(); logger.trace("Get the output result from the stream"); return StreamUtil.getUTF8OutputStreamAsString(byteArrayOutputStream); }  TMTextUnit addTMTextUnit(Long tmId, Long assetId, String name, String content, String comment); TMTextUnit addTMTextUnit(
            TM tm,
            Asset asset,
            String name,
            String content,
            String comment,
            DateTime createdDate,
            PluralForm pluralForm,
            String pluralFormOther); TMTextUnit addTMTextUnit(
            TM tm,
            Asset asset,
            String name,
            String content,
            String comment,
            User createdByUser,
            DateTime createdDate,
            PluralForm pluralForm,
            String pluralFormOther); TMTextUnitVariant addCurrentTMTextUnitVariant(Long tmTextUnitId, Long localeId, String content); TMTextUnitVariant addCurrentTMTextUnitVariant(Long tmTextUnitId, Long localeId, String content, TMTextUnitVariant.Status status, boolean includedInLocalizedFile); TMTextUnitVariant addCurrentTMTextUnitVariant(Long tmTextUnitId, Long localeId, String content, TMTextUnitVariant.Status status, boolean includedInLocalizedFile, DateTime createdDate); TMTextUnitCurrentVariant addTMTextUnitCurrentVariant(Long tmTextUnitId, Long localeId, String content, String comment); TMTextUnitCurrentVariant addTMTextUnitCurrentVariant(Long tmTextUnitId, Long localeId, String content, String comment, TMTextUnitVariant.Status status); TMTextUnitCurrentVariant addTMTextUnitCurrentVariant(
            Long tmTextUnitId,
            Long localeId,
            String content,
            String comment,
            TMTextUnitVariant.Status status,
            boolean includedInLocalizedFile); TMTextUnitCurrentVariant addTMTextUnitCurrentVariant(
            Long tmTextUnitId,
            Long localeId,
            String content,
            String comment,
            TMTextUnitVariant.Status status,
            boolean includedInLocalizedFile,
            DateTime createdDate); AddTMTextUnitCurrentVariantResult addTMTextUnitCurrentVariantWithResult(
            Long tmTextUnitId,
            Long localeId,
            String content,
            String comment,
            TMTextUnitVariant.Status status,
            boolean includedInLocalizedFile,
            DateTime createdDate); AddTMTextUnitCurrentVariantResult addTMTextUnitCurrentVariantWithResult(
            TMTextUnitCurrentVariant tmTextUnitCurrentVariant,
            Long tmId,
            Long tmTextUnitId,
            Long localeId,
            String content,
            String comment,
            TMTextUnitVariant.Status status,
            boolean includedInLocalizedFile,
            DateTime createdDate,
            User createdBy); boolean isUpdateNeededForTmTextUnitVariant(
            TMTextUnitVariant.Status currentStatus,
            String currentContentMd5,
            boolean currentIncludedInLocalizedFile,
            String currentComment,
            TMTextUnitVariant.Status newStatus,
            String newContentMd5,
            boolean newIncludedInLocalizedFile,
            String newComment); TMTextUnitVariant addTMTextUnitVariant(
            Long tmTextUnitId,
            Long localeId,
            String content,
            String comment,
            TMTextUnitVariant.Status status,
            boolean includedInLocalizedFile,
            DateTime createdDate); TMTextUnitVariant addTMTextUnitVariant(
            Long tmTextUnitId,
            Long localeId,
            String content,
            String comment,
            TMTextUnitVariant.Status status,
            boolean includedInLocalizedFile,
            DateTime createdDate,
            User createdBy); UpdateTMWithXLIFFResult updateTMWithTranslationKitXLIFF(
            String xliffContent,
            TMTextUnitVariant.Status importStatus,
            String dropImporterUsernameOverride); UpdateTMWithXLIFFResult updateTMWithXLIFFById(
            String xliffContent,
            TMTextUnitVariant.Status importStatus); UpdateTMWithXLIFFResult updateTMWithXLIFFByMd5(
            String xliffContent,
            TMTextUnitVariant.Status importStatus,
            Repository repository); @Transactional String exportAssetAsXLIFF(Long assetId, String bcp47Tag); String generateLocalized(
            Asset asset,
            String content,
            RepositoryLocale repositoryLocale,
            String outputBcp47tag,
            FilterConfigIdOverride filterConfigIdOverride,
            List<String> filterOptions,
            Status status,
            InheritanceMode inheritanceMode); String generatePseudoLocalized(
            Asset asset,
            String content,
            FilterConfigIdOverride filterConfigIdOverride); PollableFuture<Void> importLocalizedAssetAsync(
            Long assetId,
            String content,
            Long localeId,
            StatusForEqualTarget statusForEqualtarget,
            FilterConfigIdOverride filterConfigIdOverride,
            List<String> filterOptions); void importLocalizedAsset(
            Long assetId,
            String content,
            Long localeId,
            StatusForEqualTarget statusForEqualtarget,
            FilterConfigIdOverride filterConfigIdOverride,
            List<String> filterOptions); @Pollable(async = true, message = "Export asset as xliff") PollableFuture<String> exportAssetAsXLIFFAsync(
            Long tmXliffId,
            Long assetId,
            String bcp47Tag,
            @InjectCurrentTask PollableTask currentTask); TMXliff createTMXliff(Long assetId, String bcp47Tag, String content, PollableTask pollableTask);  }
@Test public void testExportAssetAsXLIFF() throws RepositoryNameAlreadyUsedException { createTestData(); String targetLocaleBcp47Tag = "fr-FR"; logger.debug("Export empty TM for source (en)"); String exportAssetAsXLIFF = tmService.exportAssetAsXLIFF(assetId, "en"); assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<xliff version=\"1.2\" xmlns=\"urn:oasis:names:tc:xliff:document:1.2\" xmlns:okp=\"okapi-framework:xliff-extensions\">\n" + "<file original=\"test-asset-path.xliff\" source-language=\"en\" target-language=\"en\" datatype=\"x-undefined\" okp:inputEncoding=\"UTF-8\">\n" + "<body>\n" + "</body>\n" + "</file>\n" + "</xliff>\n", exportAssetAsXLIFF); logger.debug("Export empty TM for locale"); exportAssetAsXLIFF = tmService.exportAssetAsXLIFF(assetId, targetLocaleBcp47Tag); assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<xliff version=\"1.2\" xmlns=\"urn:oasis:names:tc:xliff:document:1.2\" xmlns:okp=\"okapi-framework:xliff-extensions\">\n" + "<file original=\"test-asset-path.xliff\" source-language=\"en\" target-language=\"fr-FR\" datatype=\"x-undefined\" okp:inputEncoding=\"UTF-8\">\n" + "<body>\n" + "</body>\n" + "</file>\n" + "</xliff>\n", exportAssetAsXLIFF); logger.debug("Add translations"); TMTextUnit tmTextUnit1 = tmService.addTMTextUnit(tmId, assetId, "application_name", "Application Name", "This text is shown in the start screen of the application. Keep it short."); TMTextUnit tmTextUnit2 = tmService.addTMTextUnit(tmId, assetId, "home", "Home", "This is the text displayed in the link that takes the user to the home page."); Locale targetLocale = localeService.findByBcp47Tag(targetLocaleBcp47Tag); tmService.addCurrentTMTextUnitVariant(tmTextUnit1.getId(), targetLocale.getId(), "Nom de l'application"); tmService.addCurrentTMTextUnitVariant(tmTextUnit2.getId(), targetLocale.getId(), "Page d'accueil"); logger.debug("Export TM for source (en) with 2 translation"); exportAssetAsXLIFF = tmService.exportAssetAsXLIFF(assetId, "en"); exportAssetAsXLIFF = removeIdsAndDatesFromJson(exportAssetAsXLIFF); logger.debug(exportAssetAsXLIFF); assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<xliff version=\"1.2\" xmlns=\"urn:oasis:names:tc:xliff:document:1.2\" xmlns:okp=\"okapi-framework:xliff-extensions\">\n" + "<file original=\"test-asset-path.xliff\" source-language=\"en\" target-language=\"en\" datatype=\"x-undefined\" okp:inputEncoding=\"UTF-8\">\n" + "<body>\n" + "<trans-unit id=\"\" resname=\"application_name\" xml:space=\"preserve\">\n" + "<source xml:lang=\"en\">Application Name</source>\n" + "<target xml:lang=\"en\">Application Name</target>\n" + "<note>{\"sourceComment\":\"This text is shown in the start screen of the application. Keep it short.\",\"targetComment\":\"This text is shown in the start screen of the application. Keep it short.\",\"includedInLocalizedFile\":true,\"status\":\"APPROVED\",\"variantComments\":[],\"pluralForm\":null,\"pluralFormOther\":null}</note>\n" + "</trans-unit>\n" + "<trans-unit id=\"\" resname=\"home\" xml:space=\"preserve\">\n" + "<source xml:lang=\"en\">Home</source>\n" + "<target xml:lang=\"en\">Home</target>\n" + "<note>{\"sourceComment\":\"This is the text displayed in the link that takes the user to the home page.\",\"targetComment\":\"This is the text displayed in the link that takes the user to the home page.\",\"includedInLocalizedFile\":true,\"status\":\"APPROVED\",\"variantComments\":[],\"pluralForm\":null,\"pluralFormOther\":null}</note>\n" + "</trans-unit>\n" + "</body>\n" + "</file>\n" + "</xliff>\n", exportAssetAsXLIFF); logger.debug("Export TM for locale with 2 translation"); exportAssetAsXLIFF = tmService.exportAssetAsXLIFF(assetId, targetLocaleBcp47Tag); exportAssetAsXLIFF = removeIdsAndDatesFromJson(exportAssetAsXLIFF); logger.debug(exportAssetAsXLIFF); assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<xliff version=\"1.2\" xmlns=\"urn:oasis:names:tc:xliff:document:1.2\" xmlns:okp=\"okapi-framework:xliff-extensions\">\n" + "<file original=\"test-asset-path.xliff\" source-language=\"en\" target-language=\"fr-FR\" datatype=\"x-undefined\" okp:inputEncoding=\"UTF-8\">\n" + "<body>\n" + "<trans-unit id=\"\" resname=\"application_name\" xml:space=\"preserve\">\n" + "<source xml:lang=\"en\">Application Name</source>\n" + "<target xml:lang=\"fr-FR\">Nom de l'application</target>\n" + "<note>{\"sourceComment\":\"This text is shown in the start screen of the application. Keep it short.\",\"targetComment\":null,\"includedInLocalizedFile\":true,\"status\":\"APPROVED\",\"variantComments\":[],\"pluralForm\":null,\"pluralFormOther\":null}</note>\n" + "</trans-unit>\n" + "<trans-unit id=\"\" resname=\"home\" xml:space=\"preserve\">\n" + "<source xml:lang=\"en\">Home</source>\n" + "<target xml:lang=\"fr-FR\">Page d'accueil</target>\n" + "<note>{\"sourceComment\":\"This is the text displayed in the link that takes the user to the home page.\",\"targetComment\":null,\"includedInLocalizedFile\":true,\"status\":\"APPROVED\",\"variantComments\":[],\"pluralForm\":null,\"pluralFormOther\":null}</note>\n" + "</trans-unit>\n" + "</body>\n" + "</file>\n" + "</xliff>\n", exportAssetAsXLIFF); logger.debug("Export TM with a string that needs review"); tmService.addTMTextUnitCurrentVariant(tmTextUnit2.getId(), targetLocale.getId(), "Page d'accueil", "this string need to be reviewed because...", TMTextUnitVariant.Status.REVIEW_NEEDED, true); exportAssetAsXLIFF = tmService.exportAssetAsXLIFF(assetId, targetLocaleBcp47Tag); exportAssetAsXLIFF = removeIdsAndDatesFromJson(exportAssetAsXLIFF); logger.debug(exportAssetAsXLIFF); assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<xliff version=\"1.2\" xmlns=\"urn:oasis:names:tc:xliff:document:1.2\" xmlns:okp=\"okapi-framework:xliff-extensions\">\n" + "<file original=\"test-asset-path.xliff\" source-language=\"en\" target-language=\"fr-FR\" datatype=\"x-undefined\" okp:inputEncoding=\"UTF-8\">\n" + "<body>\n" + "<trans-unit id=\"\" resname=\"application_name\" xml:space=\"preserve\">\n" + "<source xml:lang=\"en\">Application Name</source>\n" + "<target xml:lang=\"fr-FR\">Nom de l'application</target>\n" + "<note>{\"sourceComment\":\"This text is shown in the start screen of the application. Keep it short.\",\"targetComment\":null,\"includedInLocalizedFile\":true,\"status\":\"APPROVED\",\"variantComments\":[],\"pluralForm\":null,\"pluralFormOther\":null}</note>\n" + "</trans-unit>\n" + "<trans-unit id=\"\" resname=\"home\" xml:space=\"preserve\">\n" + "<source xml:lang=\"en\">Home</source>\n" + "<target xml:lang=\"fr-FR\">Page d'accueil</target>\n" + "<note>{\"sourceComment\":\"This is the text displayed in the link that takes the user to the home page.\",\"targetComment\":\"this string need to be reviewed because...\",\"includedInLocalizedFile\":true,\"status\":\"REVIEW_NEEDED\",\"variantComments\":[],\"pluralForm\":null,\"pluralFormOther\":null}</note>\n" + "</trans-unit>\n" + "</body>\n" + "</file>\n" + "</xliff>\n", exportAssetAsXLIFF); logger.debug("Export TM with a string that has comments"); TMTextUnitCurrentVariant currentVariant = tmService.addTMTextUnitCurrentVariant(tmTextUnit2.getId(), targetLocale.getId(), "Page d'accueil", "this string has some comments", TMTextUnitVariant.Status.REVIEW_NEEDED, false); tmTextUnitVariantCommentService.addComment( currentVariant.getTmTextUnitVariant().getId(), TMTextUnitVariantComment.Type.LEVERAGING, TMTextUnitVariantComment.Severity.INFO, "Leveraging" ); tmTextUnitVariantCommentService.addComment( currentVariant.getTmTextUnitVariant().getId(), TMTextUnitVariantComment.Type.INTEGRITY_CHECK, TMTextUnitVariantComment.Severity.ERROR, "Failed Integrity Check" ); exportAssetAsXLIFF = tmService.exportAssetAsXLIFF(assetId, targetLocaleBcp47Tag); exportAssetAsXLIFF = removeIdsAndDatesFromJson(exportAssetAsXLIFF); logger.debug(exportAssetAsXLIFF); assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<xliff version=\"1.2\" xmlns=\"urn:oasis:names:tc:xliff:document:1.2\" xmlns:okp=\"okapi-framework:xliff-extensions\">\n" + "<file original=\"test-asset-path.xliff\" source-language=\"en\" target-language=\"fr-FR\" datatype=\"x-undefined\" okp:inputEncoding=\"UTF-8\">\n" + "<body>\n" + "<trans-unit id=\"\" resname=\"application_name\" xml:space=\"preserve\">\n" + "<source xml:lang=\"en\">Application Name</source>\n" + "<target xml:lang=\"fr-FR\">Nom de l'application</target>\n" + "<note>{\"sourceComment\":\"This text is shown in the start screen of the application. Keep it short.\",\"targetComment\":null,\"includedInLocalizedFile\":true,\"status\":\"APPROVED\",\"variantComments\":[],\"pluralForm\":null,\"pluralFormOther\":null}</note>\n" + "</trans-unit>\n" + "<trans-unit id=\"\" resname=\"home\" xml:space=\"preserve\">\n" + "<source xml:lang=\"en\">Home</source>\n" + "<target xml:lang=\"fr-FR\">Page d'accueil</target>\n" + "<note>{\"sourceComment\":\"This is the text displayed in the link that takes the user to the home page.\",\"targetComment\":\"this string has some comments\",\"includedInLocalizedFile\":false,\"status\":\"REVIEW_NEEDED\",\"variantComments\":[{\"severity\":\"INFO\",\"type\":\"LEVERAGING\",\"content\":\"Leveraging\",\"createdByUser\":{\"username\":\"admin\",\"enabled\":true,\"surname\":null,\"givenName\":null,\"commonName\":null,\"partiallyCreated\":false,\"authorities\":[{\"authority\":\"ROLE_ADMIN\"}]}},{\"severity\":\"ERROR\",\"type\":\"INTEGRITY_CHECK\",\"content\":\"Failed Integrity Check\",\"createdByUser\":{\"username\":\"admin\",\"enabled\":true,\"surname\":null,\"givenName\":null,\"commonName\":null,\"partiallyCreated\":false,\"authorities\":[{\"authority\":\"ROLE_ADMIN\"}]}}],\"pluralForm\":null,\"pluralFormOther\":null}</note>\n" + "</trans-unit>\n" + "</body>\n" + "</file>\n" + "</xliff>\n", exportAssetAsXLIFF); }