{"action":"created","comment":{"url":"https://api.github.com/repos/dimagi/commcare-odk/pulls/comments/35469280","id":35469280,"diff_hunk":"@@ -0,0 +1,239 @@\n+package org.commcare.android.tasks;\n+\n+import android.os.AsyncTask;\n+import android.os.Bundle;\n+\n+import java.io.File;\n+import java.io.IOException;\n+\n+import org.commcare.android.util.TemplatePrinterUtils;\n+\n+\n+/**\n+ * Asynchronous task for populating an html document with data.\n+ *\n+ * @author Richard Lu\n+ * @author amstone\n+ */\n+public class TemplatePrinterTask extends AsyncTask<Void, Void, Boolean> {\n+\n+    /**\n+     * If an error occurs, stores which type the error was, to be passed back to\n+     * TemplatePrinterActivity through the PopulateListener's onError method\n+     */\n+    private int errorType;\n+\n+    /**\n+     * The 2 types of errors that can be encountered in this task\n+     */\n+    public static final int IO_ERROR = 0;\n+    private static final int VALIDATION_ERROR = 1;\n+\n+    /**\n+     * The template file for this print action\n+     */\n+    private final File inputFile;\n+\n+    /**\n+     * The path where the populated template should be saved to\n+     */\n+    private final String outputPath;\n+\n+    /**\n+     * The mapping from keywords to case property values to be used in populating the template\n+     */\n+    private final Bundle values;\n+\n+    private final PopulateListener listener;\n+\n+\n+    public TemplatePrinterTask(File input, String outputPath, Bundle values,\n+                               PopulateListener listener) {\n+        this.inputFile = input;\n+        this.outputPath = outputPath;\n+        this.values = values;\n+        this.listener = listener;\n+    }\n+\n+    /**\n+     * Attempts to perform population of the template file, and throws the appropriate exception\n+     * if encountering an error.\n+     */\n+    @Override\n+    protected Boolean doInBackground(Void... params) {\n+        try {\n+            populateHtml(inputFile, values);\n+            return true;\n+        } catch (IOException e) {\n+            errorType = IO_ERROR;\n+            return false;\n+        } catch (RuntimeException e) {\n+            errorType = VALIDATION_ERROR;\n+            return false;\n+        }\n+    }\n+\n+    /**\n+     * Receives the return value from doInBackground and proceeds accordingly\n+     */\n+    @Override\n+    protected void onPostExecute(Boolean success) {\n+        if (success) {\n+            listener.onFinished();\n+        } else {\n+            listener.onError(errorType);\n+        }\n+    }\n+\n+    /**\n+     * Populates an html print template based on the given set of key-value pairings\n+     * and save the newly-populated template to a temp location\n+     *\n+     * @param input the html print template\n+     * @param values the mapping of keywords to case property values\n+     * @throws IOException\n+     */\n+    private void populateHtml(File input, Bundle values) throws IOException {\n+        // Read from input file\n+        // throws IOException\n+        String fileText = TemplatePrinterUtils.docToString(input);\n+\n+        // Check if <body></body> section of html string is properly formed\n+        // throws RuntimeException\n+        int startBodyIndex = fileText.indexOf(\"<body\");\n+        String beforeBodySection = fileText.substring(0, startBodyIndex);\n+        String bodySection = fileText.substring(startBodyIndex);\n+        validateStringOrThrowException(bodySection);\n+\n+        // Swap out place-holder keywords for case property values within <body></body> section\n+        bodySection = replace(bodySection, values);\n+\n+        // Write the new HTML to the desired  temp file location\n+        // throws IO Exception\n+        TemplatePrinterUtils.writeStringToFile(beforeBodySection + bodySection, outputPath);","path":"app/src/org/commcare/android/tasks/TemplatePrinterTask.java","position":113,"original_position":113,"commit_id":"bcb936511d74d72be48d0c0788c090a382252265","original_commit_id":"bcb936511d74d72be48d0c0788c090a382252265","user":{"login":"amstone326","id":3723143,"avatar_url":"https://avatars.githubusercontent.com/u/3723143?v=3","gravatar_id":"","url":"https://api.github.com/users/amstone326","html_url":"https://github.com/amstone326","followers_url":"https://api.github.com/users/amstone326/followers","following_url":"https://api.github.com/users/amstone326/following{/other_user}","gists_url":"https://api.github.com/users/amstone326/gists{/gist_id}","starred_url":"https://api.github.com/users/amstone326/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/amstone326/subscriptions","organizations_url":"https://api.github.com/users/amstone326/orgs","repos_url":"https://api.github.com/users/amstone326/repos","events_url":"https://api.github.com/users/amstone326/events{/privacy}","received_events_url":"https://api.github.com/users/amstone326/received_events","type":"User","site_admin":false},"body":"Not sure what you're asking, can you clarify?","created_at":"2015-07-24T21:50:37Z","updated_at":"2015-07-24T21:50:37Z","html_url":"https://github.com/dimagi/commcare-odk/pull/126#discussion_r35469280","pull_request_url":"https://api.github.com/repos/dimagi/commcare-odk/pulls/126","_links":{"self":{"href":"https://api.github.com/repos/dimagi/commcare-odk/pulls/comments/35469280"},"html":{"href":"https://github.com/dimagi/commcare-odk/pull/126#discussion_r35469280"},"pull_request":{"href":"https://api.github.com/repos/dimagi/commcare-odk/pulls/126"}}},"pull_request":{"url":"https://api.github.com/repos/dimagi/commcare-odk/pulls/126","id":28202087,"html_url":"https://github.com/dimagi/commcare-odk/pull/126","diff_url":"https://github.com/dimagi/commcare-odk/pull/126.diff","patch_url":"https://github.com/dimagi/commcare-odk/pull/126.patch","issue_url":"https://api.github.com/repos/dimagi/commcare-odk/issues/126","number":126,"state":"open","locked":false,"title":"Printer integration","user":{"login":"lu16j","id":4657561,"avatar_url":"https://avatars.githubusercontent.com/u/4657561?v=3","gravatar_id":"","url":"https://api.github.com/users/lu16j","html_url":"https://github.com/lu16j","followers_url":"https://api.github.com/users/lu16j/followers","following_url":"https://api.github.com/users/lu16j/following{/other_user}","gists_url":"https://api.github.com/users/lu16j/gists{/gist_id}","starred_url":"https://api.github.com/users/lu16j/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lu16j/subscriptions","organizations_url":"https://api.github.com/users/lu16j/orgs","repos_url":"https://api.github.com/users/lu16j/repos","events_url":"https://api.github.com/users/lu16j/events{/privacy}","received_events_url":"https://api.github.com/users/lu16j/received_events","type":"User","site_admin":false},"body":"DO NOT MERGE until corresponding HQ feature is implemented (ticket submitted by Clayton).\r\n\r\nTODOs when HQ feature is implemented:\r\n- Remove TEMPLATE_FILE_HACK_EXT and all dependencies on it from TemplatePrinterActivity.\r\n- Update TEMPLATE_FILE_PATH if the template document file will always be in the same location. If not, write a function to determine where the template file is.\r\n\r\nOther nice-to-dos:\r\n- Make this a question type rather than a callout.\r\n\r\n------\r\n\r\nAdds an internal callout activity (used in the same way as an app callout) which loads a .docx/.odt file template, populates it with CommCare data, and sends it off to an external document reader for printing/saving to PDF.\r\n\r\nTemplate files formatting:\r\n- Text occurrences of \"{{ attr_key }}\" will be replaced with the corresponding attr_value included in the activity's extras.\r\n- The formatting of attr_key will be preserved (i.e. if it was bold and italicized, the data it will be replaced by will also be bold and italicized).\r\n\r\nExternal app dependencies:\r\n- Required: one of\r\n - Quickoffice or equivalent for .docx templates (recommended; better editors, better viewers)\r\n - OpenDocument Reader or equivalent for .odt templates\r\n- Optional:\r\n - File Explorer or equivalent file manager capable of file selection. If template file is not bundled with application, file manager will be launched to manually select a template file.","created_at":"2015-01-28T15:29:54Z","updated_at":"2015-07-24T21:50:37Z","closed_at":null,"merged_at":null,"merge_commit_sha":"8fb5d6ce5f4512c8b1a7d43f8c42cc6567a05c75","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/dimagi/commcare-odk/pulls/126/commits","review_comments_url":"https://api.github.com/repos/dimagi/commcare-odk/pulls/126/comments","review_comment_url":"https://api.github.com/repos/dimagi/commcare-odk/pulls/comments{/number}","comments_url":"https://api.github.com/repos/dimagi/commcare-odk/issues/126/comments","statuses_url":"https://api.github.com/repos/dimagi/commcare-odk/statuses/bcb936511d74d72be48d0c0788c090a382252265","head":{"label":"dimagi:printer-integration","ref":"printer-integration","sha":"bcb936511d74d72be48d0c0788c090a382252265","user":{"login":"dimagi","id":94514,"avatar_url":"https://avatars.githubusercontent.com/u/94514?v=3","gravatar_id":"","url":"https://api.github.com/users/dimagi","html_url":"https://github.com/dimagi","followers_url":"https://api.github.com/users/dimagi/followers","following_url":"https://api.github.com/users/dimagi/following{/other_user}","gists_url":"https://api.github.com/users/dimagi/gists{/gist_id}","starred_url":"https://api.github.com/users/dimagi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dimagi/subscriptions","organizations_url":"https://api.github.com/users/dimagi/orgs","repos_url":"https://api.github.com/users/dimagi/repos","events_url":"https://api.github.com/users/dimagi/events{/privacy}","received_events_url":"https://api.github.com/users/dimagi/received_events","type":"Organization","site_admin":false},"repo":{"id":20939877,"name":"commcare-odk","full_name":"dimagi/commcare-odk","owner":{"login":"dimagi","id":94514,"avatar_url":"https://avatars.githubusercontent.com/u/94514?v=3","gravatar_id":"","url":"https://api.github.com/users/dimagi","html_url":"https://github.com/dimagi","followers_url":"https://api.github.com/users/dimagi/followers","following_url":"https://api.github.com/users/dimagi/following{/other_user}","gists_url":"https://api.github.com/users/dimagi/gists{/gist_id}","starred_url":"https://api.github.com/users/dimagi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dimagi/subscriptions","organizations_url":"https://api.github.com/users/dimagi/orgs","repos_url":"https://api.github.com/users/dimagi/repos","events_url":"https://api.github.com/users/dimagi/events{/privacy}","received_events_url":"https://api.github.com/users/dimagi/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/dimagi/commcare-odk","description":"","fork":false,"url":"https://api.github.com/repos/dimagi/commcare-odk","forks_url":"https://api.github.com/repos/dimagi/commcare-odk/forks","keys_url":"https://api.github.com/repos/dimagi/commcare-odk/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dimagi/commcare-odk/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dimagi/commcare-odk/teams","hooks_url":"https://api.github.com/repos/dimagi/commcare-odk/hooks","issue_events_url":"https://api.github.com/repos/dimagi/commcare-odk/issues/events{/number}","events_url":"https://api.github.com/repos/dimagi/commcare-odk/events","assignees_url":"https://api.github.com/repos/dimagi/commcare-odk/assignees{/user}","branches_url":"https://api.github.com/repos/dimagi/commcare-odk/branches{/branch}","tags_url":"https://api.github.com/repos/dimagi/commcare-odk/tags","blobs_url":"https://api.github.com/repos/dimagi/commcare-odk/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dimagi/commcare-odk/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dimagi/commcare-odk/git/refs{/sha}","trees_url":"https://api.github.com/repos/dimagi/commcare-odk/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dimagi/commcare-odk/statuses/{sha}","languages_url":"https://api.github.com/repos/dimagi/commcare-odk/languages","stargazers_url":"https://api.github.com/repos/dimagi/commcare-odk/stargazers","contributors_url":"https://api.github.com/repos/dimagi/commcare-odk/contributors","subscribers_url":"https://api.github.com/repos/dimagi/commcare-odk/subscribers","subscription_url":"https://api.github.com/repos/dimagi/commcare-odk/subscription","commits_url":"https://api.github.com/repos/dimagi/commcare-odk/commits{/sha}","git_commits_url":"https://api.github.com/repos/dimagi/commcare-odk/git/commits{/sha}","comments_url":"https://api.github.com/repos/dimagi/commcare-odk/comments{/number}","issue_comment_url":"https://api.github.com/repos/dimagi/commcare-odk/issues/comments{/number}","contents_url":"https://api.github.com/repos/dimagi/commcare-odk/contents/{+path}","compare_url":"https://api.github.com/repos/dimagi/commcare-odk/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dimagi/commcare-odk/merges","archive_url":"https://api.github.com/repos/dimagi/commcare-odk/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dimagi/commcare-odk/downloads","issues_url":"https://api.github.com/repos/dimagi/commcare-odk/issues{/number}","pulls_url":"https://api.github.com/repos/dimagi/commcare-odk/pulls{/number}","milestones_url":"https://api.github.com/repos/dimagi/commcare-odk/milestones{/number}","notifications_url":"https://api.github.com/repos/dimagi/commcare-odk/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dimagi/commcare-odk/labels{/name}","releases_url":"https://api.github.com/repos/dimagi/commcare-odk/releases{/id}","created_at":"2014-06-17T21:17:26Z","updated_at":"2015-05-06T16:04:54Z","pushed_at":"2015-07-24T21:42:25Z","git_url":"git://github.com/dimagi/commcare-odk.git","ssh_url":"git@github.com:dimagi/commcare-odk.git","clone_url":"https://github.com/dimagi/commcare-odk.git","svn_url":"https://github.com/dimagi/commcare-odk","homepage":null,"size":60667,"stargazers_count":3,"watchers_count":3,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":17,"forks":5,"open_issues":17,"watchers":3,"default_branch":"master"}},"base":{"label":"dimagi:master","ref":"master","sha":"4952365606c0b70c57cf5859133307a99e3317f7","user":{"login":"dimagi","id":94514,"avatar_url":"https://avatars.githubusercontent.com/u/94514?v=3","gravatar_id":"","url":"https://api.github.com/users/dimagi","html_url":"https://github.com/dimagi","followers_url":"https://api.github.com/users/dimagi/followers","following_url":"https://api.github.com/users/dimagi/following{/other_user}","gists_url":"https://api.github.com/users/dimagi/gists{/gist_id}","starred_url":"https://api.github.com/users/dimagi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dimagi/subscriptions","organizations_url":"https://api.github.com/users/dimagi/orgs","repos_url":"https://api.github.com/users/dimagi/repos","events_url":"https://api.github.com/users/dimagi/events{/privacy}","received_events_url":"https://api.github.com/users/dimagi/received_events","type":"Organization","site_admin":false},"repo":{"id":20939877,"name":"commcare-odk","full_name":"dimagi/commcare-odk","owner":{"login":"dimagi","id":94514,"avatar_url":"https://avatars.githubusercontent.com/u/94514?v=3","gravatar_id":"","url":"https://api.github.com/users/dimagi","html_url":"https://github.com/dimagi","followers_url":"https://api.github.com/users/dimagi/followers","following_url":"https://api.github.com/users/dimagi/following{/other_user}","gists_url":"https://api.github.com/users/dimagi/gists{/gist_id}","starred_url":"https://api.github.com/users/dimagi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dimagi/subscriptions","organizations_url":"https://api.github.com/users/dimagi/orgs","repos_url":"https://api.github.com/users/dimagi/repos","events_url":"https://api.github.com/users/dimagi/events{/privacy}","received_events_url":"https://api.github.com/users/dimagi/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/dimagi/commcare-odk","description":"","fork":false,"url":"https://api.github.com/repos/dimagi/commcare-odk","forks_url":"https://api.github.com/repos/dimagi/commcare-odk/forks","keys_url":"https://api.github.com/repos/dimagi/commcare-odk/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dimagi/commcare-odk/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dimagi/commcare-odk/teams","hooks_url":"https://api.github.com/repos/dimagi/commcare-odk/hooks","issue_events_url":"https://api.github.com/repos/dimagi/commcare-odk/issues/events{/number}","events_url":"https://api.github.com/repos/dimagi/commcare-odk/events","assignees_url":"https://api.github.com/repos/dimagi/commcare-odk/assignees{/user}","branches_url":"https://api.github.com/repos/dimagi/commcare-odk/branches{/branch}","tags_url":"https://api.github.com/repos/dimagi/commcare-odk/tags","blobs_url":"https://api.github.com/repos/dimagi/commcare-odk/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dimagi/commcare-odk/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dimagi/commcare-odk/git/refs{/sha}","trees_url":"https://api.github.com/repos/dimagi/commcare-odk/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dimagi/commcare-odk/statuses/{sha}","languages_url":"https://api.github.com/repos/dimagi/commcare-odk/languages","stargazers_url":"https://api.github.com/repos/dimagi/commcare-odk/stargazers","contributors_url":"https://api.github.com/repos/dimagi/commcare-odk/contributors","subscribers_url":"https://api.github.com/repos/dimagi/commcare-odk/subscribers","subscription_url":"https://api.github.com/repos/dimagi/commcare-odk/subscription","commits_url":"https://api.github.com/repos/dimagi/commcare-odk/commits{/sha}","git_commits_url":"https://api.github.com/repos/dimagi/commcare-odk/git/commits{/sha}","comments_url":"https://api.github.com/repos/dimagi/commcare-odk/comments{/number}","issue_comment_url":"https://api.github.com/repos/dimagi/commcare-odk/issues/comments{/number}","contents_url":"https://api.github.com/repos/dimagi/commcare-odk/contents/{+path}","compare_url":"https://api.github.com/repos/dimagi/commcare-odk/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dimagi/commcare-odk/merges","archive_url":"https://api.github.com/repos/dimagi/commcare-odk/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dimagi/commcare-odk/downloads","issues_url":"https://api.github.com/repos/dimagi/commcare-odk/issues{/number}","pulls_url":"https://api.github.com/repos/dimagi/commcare-odk/pulls{/number}","milestones_url":"https://api.github.com/repos/dimagi/commcare-odk/milestones{/number}","notifications_url":"https://api.github.com/repos/dimagi/commcare-odk/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dimagi/commcare-odk/labels{/name}","releases_url":"https://api.github.com/repos/dimagi/commcare-odk/releases{/id}","created_at":"2014-06-17T21:17:26Z","updated_at":"2015-05-06T16:04:54Z","pushed_at":"2015-07-24T21:42:25Z","git_url":"git://github.com/dimagi/commcare-odk.git","ssh_url":"git@github.com:dimagi/commcare-odk.git","clone_url":"https://github.com/dimagi/commcare-odk.git","svn_url":"https://github.com/dimagi/commcare-odk","homepage":null,"size":60667,"stargazers_count":3,"watchers_count":3,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":17,"forks":5,"open_issues":17,"watchers":3,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/dimagi/commcare-odk/pulls/126"},"html":{"href":"https://github.com/dimagi/commcare-odk/pull/126"},"issue":{"href":"https://api.github.com/repos/dimagi/commcare-odk/issues/126"},"comments":{"href":"https://api.github.com/repos/dimagi/commcare-odk/issues/126/comments"},"review_comments":{"href":"https://api.github.com/repos/dimagi/commcare-odk/pulls/126/comments"},"review_comment":{"href":"https://api.github.com/repos/dimagi/commcare-odk/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/dimagi/commcare-odk/pulls/126/commits"},"statuses":{"href":"https://api.github.com/repos/dimagi/commcare-odk/statuses/bcb936511d74d72be48d0c0788c090a382252265"}}}}