/** * Merges chunks found in a target translation Project that do not exist in the source translation * to a sibling chunk so that no data is lost. * * @param library * @param targetTranslation target translation to merge * @return */ public static boolean migrateChunkChanges( final Library library, final TargetTranslation targetTranslation) { try { Logger.i( TargetTranslationMigrator.class.getName(), "Migrating chunks in target translation " + targetTranslation.getProjectId()); final SourceTranslation sourceTranslation = library.getDefaultSourceTranslation(targetTranslation.getProjectId(), "en"); if (sourceTranslation == null) { Logger.w( TargetTranslationMigrator.class.getName(), "Could not find a source translation for the target translation " + targetTranslation.getId()); return false; } if (targetTranslation.getPath().exists()) { boolean migrationSuccess = true; // perform the chunk migration on each chapter of the target translation for (ChapterTranslation chapterTranslation : targetTranslation.getChapterTranslations()) { Chapter chapter = library.getChapter(sourceTranslation, chapterTranslation.getId()); if (chapter != null) { boolean success = mergeInvalidChunksInChapter(library, sourceTranslation, targetTranslation, chapter); migrationSuccess = migrationSuccess && success; } } return migrationSuccess; } } catch (Exception e) { Logger.e( TargetTranslationMigrator.class.getName(), "Failed to merge the chunks in the target translation " + targetTranslation.getProjectId()); } return false; }
/** * Detects the format of the file and imports it * * @param file */ public void importTranslation(final File file) { try { if (file.exists() && file.isFile()) { String[] name = file.getName().split("\\."); if (name[name.length - 1].toLowerCase().equals(Project.PROJECT_EXTENSION)) { // import translationStudio project final ProgressDialog dialog = new ProgressDialog(this); dialog.setMessage(getResources().getString(R.string.import_project)); dialog.setCancelable(false); dialog.setCanceledOnTouchOutside(false); dialog.show(); final Handler handle = new Handler(Looper.getMainLooper()); new ThreadableUI(this) { @Override public void onStop() {} @Override public void run() { ProjectImport[] importRequests = Sharing.prepareArchiveImport(file); if (importRequests.length > 0) { boolean importWarnings = false; for (ProjectImport s : importRequests) { if (!s.isApproved()) { importWarnings = true; } } if (importWarnings) { // review the import status in a dialog FragmentTransaction ft = getFragmentManager().beginTransaction(); Fragment prev = getFragmentManager().findFragmentByTag("dialog"); if (prev != null) { ft.remove(prev); } ft.addToBackStack(null); app().closeToastMessage(); ProjectTranslationImportApprovalDialog newFragment = new ProjectTranslationImportApprovalDialog(); newFragment.setImportRequests(importRequests); newFragment.setOnClickListener( new ProjectTranslationImportApprovalDialog.OnClickListener() { @Override public void onOk(ProjectImport[] requests) { handle.post( new Runnable() { @Override public void run() { dialog.setMessage(getResources().getString(R.string.loading)); dialog.show(); } }); for (ProjectImport r : requests) { Sharing.importProject(r); } Sharing.cleanImport(requests); AppContext.context().showToastMessage(R.string.success); handle.post( new Runnable() { @Override public void run() { dialog.dismiss(); } }); } @Override public void onCancel(ProjectImport[] requests) {} }); newFragment.show(ft, "dialog"); } else { // TODO: we should update the status with the results of the import and let the // user see an overview of the import process. for (ProjectImport r : importRequests) { Sharing.importProject(r); } Sharing.cleanImport(importRequests); app().showToastMessage(R.string.success); } } else { Sharing.cleanImport(importRequests); app().showToastMessage(R.string.translation_import_failed); } } @Override public void onPostExecute() { dialog.dismiss(); } }.start(); } else if (name[name.length - 1].toLowerCase().equals("zip")) { // import DokuWiki files final ProgressDialog dialog = new ProgressDialog(SharingActivity.this); dialog.setMessage(getResources().getString(R.string.import_project)); dialog.setCanceledOnTouchOutside(false); dialog.setCancelable(false); dialog.show(); new ThreadableUI(this) { @Override public void onStop() {} @Override public void run() { if (Sharing.importDokuWikiArchive(file)) { app().showToastMessage(R.string.success); } else { app().showToastMessage(R.string.translation_import_failed); } } @Override public void onPostExecute() { dialog.dismiss(); } }.start(); } else if (name[name.length - 1].toLowerCase().equals("txt")) { // import legacy 1.x DokuWiki files final ProgressDialog dialog = new ProgressDialog(SharingActivity.this); dialog.setMessage(getResources().getString(R.string.import_project)); dialog.setCanceledOnTouchOutside(false); dialog.setCancelable(false); dialog.show(); new ThreadableUI(this) { @Override public void onStop() {} @Override public void run() { if (Sharing.importDokuWiki(file)) { app().showToastMessage(R.string.success); } else { app().showToastMessage(R.string.translation_import_failed); } } @Override public void onPostExecute() { dialog.dismiss(); } }.start(); } } else { app().showToastMessage(R.string.missing_file); } } catch (Exception e) { Logger.e(this.getClass().getName(), "Failed to read file", e); } }
/** Performs the backup if nessesary */ private void runBackup() { boolean backupPerformed = false; Translator translator = AppContext.getTranslator(); TargetTranslation[] targetTranslations = translator.getTargetTranslations(); for (TargetTranslation t : targetTranslations) { // commit pending changes try { t.commit(); } catch (Exception e) { Logger.e(this.getClass().getName(), "Failed to commit changes before backing up", e); continue; } // run backup if there are translations if (t.numTranslated() > 0) { // retreive commit hash String tag; try { tag = t.getCommitHash(); } catch (Exception e) { Logger.w(this.getClass().getName(), "Failed to read commit hash", e); continue; } // check if backup is required if (tag != null) { File primaryBackupDir = new File(AppContext.getPublicDirectory(), "backups/" + t.getId() + "/"); File primaryBackupFile = new File(primaryBackupDir, tag + "." + Translator.ARCHIVE_EXTENSION); File downloadBackupDir = new File(AppContext.getPublicDownloadsDirectory(), "backups/" + t.getId() + "/"); File downloadBackupFile = new File(downloadBackupDir, tag + "." + Translator.ARCHIVE_EXTENSION); // e.g. ../../backups/uw-obs-de/[commit hash].tstudio if (!downloadBackupFile.exists()) { // peform backup File archive = new File( AppContext.getPublicDownloadsDirectory(), t.getId() + ".temp." + Translator.ARCHIVE_EXTENSION); try { translator.exportArchive(t, archive); } catch (Exception e) { Logger.e( this.getClass().getName(), "Failed to export the target translation " + t.getId(), e); continue; } if (archive.exists() && archive.isFile()) { // move into backup FileUtils.deleteQuietly(downloadBackupDir); FileUtils.deleteQuietly(primaryBackupDir); downloadBackupDir.mkdirs(); primaryBackupDir.mkdirs(); try { // backup to downloads directory FileUtils.copyFile(archive, downloadBackupFile); // backup to a slightly less public area (used for auto restore) FileUtils.copyFile(archive, primaryBackupFile); backupPerformed = true; } catch (IOException e) { Logger.e( this.getClass().getName(), "Failed to copy the backup archive for target translation: " + t.getId(), e); } archive.delete(); } else { Logger.w( this.getClass().getName(), "Failed to export the target translation: " + t.getId()); } } } else { Logger.w(this.getClass().getName(), "Could not find the commit hash"); } } } if (backupPerformed) { onBackupComplete(); } }