{"action":"created","comment":{"url":"https://api.github.com/repos/codice/ddf/pulls/comments/87449887","pull_request_review_id":8063269,"id":87449887,"diff_hunk":"@@ -124,28 +135,113 @@ public static Result transform(Node nodeXml, TransformerProperties transformerPr\n      */\n     public static String getRootNamespace(String xml) {\n \n-        String rootNamespace = null;\n-\n         if (xml == null) {\n             return null;\n         }\n \n-        initializeXMLInputFactory();\n+        return processElements(xml, (result, xmlStreamReader) -> {\n+            result.set(xmlStreamReader.getNamespaceURI());\n+            return false;\n+        });\n+    }\n+\n+    /**\n+     * Iterate through the elements of an XML document.\n+     * <p>\n+     * It uses a lambda function and an instance of the the internal class Holder. The holder\n+     * stores the return value. The lambda function has a change to process every element\n+     * in the document. To store a result, call set() on the holder object.\n+     * <p>\n+     * If the lambda function returns false, processing continues to the next element.\n+     * <p>\n+     * When the last element in the document is processed, the value in the holder object\n+     * is returned.\n+     * <p>\n+     * If the function encounters a processing exception, the value of the holder object is\n+     * set to null, processing stops, and the value returned to the caller is null.\n+     * <p>\n+     * If the lambda function return true, processing terminate processing, During processing Set the value in the ProcessingResult to be the return value of this method.\n+     * To stop processing, set the value \"done\" in ProcessingResult to true.\n+     * For an example, see the getRootNamespace() method.\n+     * <p>\n+     * //     * @param xml                    The XML to process\n+     * //     * @param result                 Instance of ProcessingResult\n+     * //     * @param processElementFunction Function that accepts an instance of XMLStreamReader\n+     * //     *                               and holder. The function must retrun a boolean.\n+     * //     * @param <T>                    The type of the holders value\n+     * //     * @return The value stored in the result holder object\n+     */\n+\n+    private static void transformation(Source sourceXml, TransformerProperties transformProperties,\n+            Result result) {\n+        ClassLoader tccl = Thread.currentThread()\n+                .getContextClassLoader();\n+        Thread.currentThread()\n+                .setContextClassLoader(XMLUtils.class.getClassLoader());\n+        try {\n+            TransformerFactory transFactory = TransformerFactory.newInstance();\n+            Transformer transformer = transFactory.newTransformer();\n+\n+            for (Entry<String, String> entry : transformProperties.getOutputProperties()) {\n+                transformer.setOutputProperty(entry.getKey(), entry.getValue());\n+            }\n+            if (transformProperties.getErrorListener() != null) {\n+                transformer.setErrorListener(transformProperties.getErrorListener());\n+            }\n+            transformer.transform(sourceXml, result);\n+        } catch (TransformerException e) {\n+            LOGGER.debug(\"Unable to transform XML.\", e);\n+        } finally {\n+            Thread.currentThread()\n+                    .setContextClassLoader(tccl);\n+        }\n+    }\n+\n+    /**\n+     * Iterate through the elements of an XML document.\n+     * <p>\n+     * It uses a lambda function and an instance of the the internal class ResultHolder. The result\n+     * stores the return value. The lambda function has a change to process every element\n+     * in the document. To store a result, call set() on the result object.\n+     * <p>\n+     * If the lambda function returns false, processing continues to the next element.\n+     * <p>\n+     * When the last element in the document is processed, the value in the holder object\n+     * is returned.\n+     * <p>\n+     * If the function encounters a processing exception and the value returned to the caller is null.\n+     * <p>\n+     * If the lambda function return true, processing terminate processing, During processing Set the value in the ProcessingResult to be the return value of this method.\n+     * To stop processing, set the value \"done\" in ProcessingResult to true.\n+     * For an example, see the getRootNamespace() method.\n+     *\n+     * @param xml                    The XML to process\n+     * @param processElementFunction Function that accepts an instance of XMLStreamReader and result holder. The function must return a boolean.\n+     * @return <T>  The result of the processing\n+     */\n \n+    public static <T> T processElements(String xml,\n+            BiFunction<ResultHolder<T>, XMLStreamReader, Boolean> processElementFunction) {\n+\n+        initializeXMLInputFactory();\n         XMLStreamReader xmlStreamReader = null;\n+        ResultHolder<T> result = new ResultHolder<>();\n+        boolean keepProcessing;\n \n         try (StringReader strReader = new StringReader(xml)) {\n             xmlStreamReader = xmlInputFactory.createXMLStreamReader(strReader);\n-\n             while (xmlStreamReader.hasNext()) {\n                 int event = xmlStreamReader.next();\n                 if (event == XMLStreamConstants.START_ELEMENT) {\n-                    rootNamespace = xmlStreamReader.getNamespaceURI();\n-                    return rootNamespace;\n+                    keepProcessing = processElementFunction.apply(result, xmlStreamReader);\n+                    if (!keepProcessing) {","path":"platform/util/platform-util/src/main/java/org/codice/ddf/platform/util/XMLUtils.java","position":147,"original_position":147,"commit_id":"4c045a98aa8c1a771b390f6c5c2d50083d8e4f18","original_commit_id":"4c045a98aa8c1a771b390f6c5c2d50083d8e4f18","user":{"login":"ahoffer","id":133284,"avatar_url":"https://avatars.githubusercontent.com/u/133284?v=3","gravatar_id":"","url":"https://api.github.com/users/ahoffer","html_url":"https://github.com/ahoffer","followers_url":"https://api.github.com/users/ahoffer/followers","following_url":"https://api.github.com/users/ahoffer/following{/other_user}","gists_url":"https://api.github.com/users/ahoffer/gists{/gist_id}","starred_url":"https://api.github.com/users/ahoffer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ahoffer/subscriptions","organizations_url":"https://api.github.com/users/ahoffer/orgs","repos_url":"https://api.github.com/users/ahoffer/repos","events_url":"https://api.github.com/users/ahoffer/events{/privacy}","received_events_url":"https://api.github.com/users/ahoffer/received_events","type":"User","site_admin":false},"body":"Good call.","created_at":"2016-11-10T17:57:57Z","updated_at":"2016-11-10T17:57:57Z","html_url":"https://github.com/codice/ddf/pull/1402#discussion_r87449887","pull_request_url":"https://api.github.com/repos/codice/ddf/pulls/1402","_links":{"self":{"href":"https://api.github.com/repos/codice/ddf/pulls/comments/87449887"},"html":{"href":"https://github.com/codice/ddf/pull/1402#discussion_r87449887"},"pull_request":{"href":"https://api.github.com/repos/codice/ddf/pulls/1402"}}},"pull_request":{"url":"https://api.github.com/repos/codice/ddf/pulls/1402","id":92440622,"html_url":"https://github.com/codice/ddf/pull/1402","diff_url":"https://github.com/codice/ddf/pull/1402.diff","patch_url":"https://github.com/codice/ddf/pull/1402.patch","issue_url":"https://api.github.com/repos/codice/ddf/issues/1402","number":1402,"state":"open","locked":false,"title":"DDF-2578 Add API to XMLUtils class","user":{"login":"ahoffer","id":133284,"avatar_url":"https://avatars.githubusercontent.com/u/133284?v=3","gravatar_id":"","url":"https://api.github.com/users/ahoffer","html_url":"https://github.com/ahoffer","followers_url":"https://api.github.com/users/ahoffer/followers","following_url":"https://api.github.com/users/ahoffer/following{/other_user}","gists_url":"https://api.github.com/users/ahoffer/gists{/gist_id}","starred_url":"https://api.github.com/users/ahoffer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ahoffer/subscriptions","organizations_url":"https://api.github.com/users/ahoffer/orgs","repos_url":"https://api.github.com/users/ahoffer/repos","events_url":"https://api.github.com/users/ahoffer/events{/privacy}","received_events_url":"https://api.github.com/users/ahoffer/received_events","type":"User","site_admin":false},"body":"#### What does this PR do?\r\nThere is a lot of boilerplate code setting up an XML parser, writing a loop to catch events, and handling checked errors. This PR adds a public method that accepts a function and an instance of a new inner class. Developers who create new modules that require XML parsing can make use of this method.\r\n#### Who is reviewing it (please choose AT LEAST two reviewers that need to approve the PR before it can get merged)?\r\n@brendan-hofmann @tbatie @mweser @AzGoalie \r\n\r\n#### Choose 2 committers to review/merge the PR \r\n@coyotesqrl\r\n@pklinef\r\n#### How should this be tested? (List steps with links to updated documentation)\r\nThere are unit tests for the changes in XMLUtilsTest class\r\n#### Any background context you want to provide?\r\n#### What are the relevant tickets?\r\n[](https://codice.atlassian.net/browse/)\r\n#### Screenshots (if appropriate)\r\n#### Checklist:\r\n- [N/A ] Documentation Updated\r\n- [ N/A] Change Log Updated\r\n- [ Yes] Update / Add Unit Tests\r\n- [ N/A] Update / Add Integration Tests\r\n","created_at":"2016-11-05T03:22:05Z","updated_at":"2016-11-10T17:57:57Z","closed_at":null,"merged_at":null,"merge_commit_sha":"0c6bfdac65fdd0b72d27d1b744f9a5339a04697b","assignee":{"login":"pklinef","id":700518,"avatar_url":"https://avatars.githubusercontent.com/u/700518?v=3","gravatar_id":"","url":"https://api.github.com/users/pklinef","html_url":"https://github.com/pklinef","followers_url":"https://api.github.com/users/pklinef/followers","following_url":"https://api.github.com/users/pklinef/following{/other_user}","gists_url":"https://api.github.com/users/pklinef/gists{/gist_id}","starred_url":"https://api.github.com/users/pklinef/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pklinef/subscriptions","organizations_url":"https://api.github.com/users/pklinef/orgs","repos_url":"https://api.github.com/users/pklinef/repos","events_url":"https://api.github.com/users/pklinef/events{/privacy}","received_events_url":"https://api.github.com/users/pklinef/received_events","type":"User","site_admin":false},"assignees":[{"login":"pklinef","id":700518,"avatar_url":"https://avatars.githubusercontent.com/u/700518?v=3","gravatar_id":"","url":"https://api.github.com/users/pklinef","html_url":"https://github.com/pklinef","followers_url":"https://api.github.com/users/pklinef/followers","following_url":"https://api.github.com/users/pklinef/following{/other_user}","gists_url":"https://api.github.com/users/pklinef/gists{/gist_id}","starred_url":"https://api.github.com/users/pklinef/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pklinef/subscriptions","organizations_url":"https://api.github.com/users/pklinef/orgs","repos_url":"https://api.github.com/users/pklinef/repos","events_url":"https://api.github.com/users/pklinef/events{/privacy}","received_events_url":"https://api.github.com/users/pklinef/received_events","type":"User","site_admin":false},{"login":"coyotesqrl","id":1469860,"avatar_url":"https://avatars.githubusercontent.com/u/1469860?v=3","gravatar_id":"","url":"https://api.github.com/users/coyotesqrl","html_url":"https://github.com/coyotesqrl","followers_url":"https://api.github.com/users/coyotesqrl/followers","following_url":"https://api.github.com/users/coyotesqrl/following{/other_user}","gists_url":"https://api.github.com/users/coyotesqrl/gists{/gist_id}","starred_url":"https://api.github.com/users/coyotesqrl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coyotesqrl/subscriptions","organizations_url":"https://api.github.com/users/coyotesqrl/orgs","repos_url":"https://api.github.com/users/coyotesqrl/repos","events_url":"https://api.github.com/users/coyotesqrl/events{/privacy}","received_events_url":"https://api.github.com/users/coyotesqrl/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/codice/ddf/pulls/1402/commits","review_comments_url":"https://api.github.com/repos/codice/ddf/pulls/1402/comments","review_comment_url":"https://api.github.com/repos/codice/ddf/pulls/comments{/number}","comments_url":"https://api.github.com/repos/codice/ddf/issues/1402/comments","statuses_url":"https://api.github.com/repos/codice/ddf/statuses/4c045a98aa8c1a771b390f6c5c2d50083d8e4f18","head":{"label":"ahoffer:DDF-2578","ref":"DDF-2578","sha":"4c045a98aa8c1a771b390f6c5c2d50083d8e4f18","user":{"login":"ahoffer","id":133284,"avatar_url":"https://avatars.githubusercontent.com/u/133284?v=3","gravatar_id":"","url":"https://api.github.com/users/ahoffer","html_url":"https://github.com/ahoffer","followers_url":"https://api.github.com/users/ahoffer/followers","following_url":"https://api.github.com/users/ahoffer/following{/other_user}","gists_url":"https://api.github.com/users/ahoffer/gists{/gist_id}","starred_url":"https://api.github.com/users/ahoffer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ahoffer/subscriptions","organizations_url":"https://api.github.com/users/ahoffer/orgs","repos_url":"https://api.github.com/users/ahoffer/repos","events_url":"https://api.github.com/users/ahoffer/events{/privacy}","received_events_url":"https://api.github.com/users/ahoffer/received_events","type":"User","site_admin":false},"repo":{"id":42614877,"name":"ddf","full_name":"ahoffer/ddf","owner":{"login":"ahoffer","id":133284,"avatar_url":"https://avatars.githubusercontent.com/u/133284?v=3","gravatar_id":"","url":"https://api.github.com/users/ahoffer","html_url":"https://github.com/ahoffer","followers_url":"https://api.github.com/users/ahoffer/followers","following_url":"https://api.github.com/users/ahoffer/following{/other_user}","gists_url":"https://api.github.com/users/ahoffer/gists{/gist_id}","starred_url":"https://api.github.com/users/ahoffer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ahoffer/subscriptions","organizations_url":"https://api.github.com/users/ahoffer/orgs","repos_url":"https://api.github.com/users/ahoffer/repos","events_url":"https://api.github.com/users/ahoffer/events{/privacy}","received_events_url":"https://api.github.com/users/ahoffer/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ahoffer/ddf","description":"The Distributed Data Framework - Distribution, SDK, and Test","fork":true,"url":"https://api.github.com/repos/ahoffer/ddf","forks_url":"https://api.github.com/repos/ahoffer/ddf/forks","keys_url":"https://api.github.com/repos/ahoffer/ddf/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ahoffer/ddf/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ahoffer/ddf/teams","hooks_url":"https://api.github.com/repos/ahoffer/ddf/hooks","issue_events_url":"https://api.github.com/repos/ahoffer/ddf/issues/events{/number}","events_url":"https://api.github.com/repos/ahoffer/ddf/events","assignees_url":"https://api.github.com/repos/ahoffer/ddf/assignees{/user}","branches_url":"https://api.github.com/repos/ahoffer/ddf/branches{/branch}","tags_url":"https://api.github.com/repos/ahoffer/ddf/tags","blobs_url":"https://api.github.com/repos/ahoffer/ddf/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ahoffer/ddf/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ahoffer/ddf/git/refs{/sha}","trees_url":"https://api.github.com/repos/ahoffer/ddf/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ahoffer/ddf/statuses/{sha}","languages_url":"https://api.github.com/repos/ahoffer/ddf/languages","stargazers_url":"https://api.github.com/repos/ahoffer/ddf/stargazers","contributors_url":"https://api.github.com/repos/ahoffer/ddf/contributors","subscribers_url":"https://api.github.com/repos/ahoffer/ddf/subscribers","subscription_url":"https://api.github.com/repos/ahoffer/ddf/subscription","commits_url":"https://api.github.com/repos/ahoffer/ddf/commits{/sha}","git_commits_url":"https://api.github.com/repos/ahoffer/ddf/git/commits{/sha}","comments_url":"https://api.github.com/repos/ahoffer/ddf/comments{/number}","issue_comment_url":"https://api.github.com/repos/ahoffer/ddf/issues/comments{/number}","contents_url":"https://api.github.com/repos/ahoffer/ddf/contents/{+path}","compare_url":"https://api.github.com/repos/ahoffer/ddf/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ahoffer/ddf/merges","archive_url":"https://api.github.com/repos/ahoffer/ddf/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ahoffer/ddf/downloads","issues_url":"https://api.github.com/repos/ahoffer/ddf/issues{/number}","pulls_url":"https://api.github.com/repos/ahoffer/ddf/pulls{/number}","milestones_url":"https://api.github.com/repos/ahoffer/ddf/milestones{/number}","notifications_url":"https://api.github.com/repos/ahoffer/ddf/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ahoffer/ddf/labels{/name}","releases_url":"https://api.github.com/repos/ahoffer/ddf/releases{/id}","deployments_url":"https://api.github.com/repos/ahoffer/ddf/deployments","created_at":"2015-09-16T21:39:29Z","updated_at":"2016-01-12T21:13:31Z","pushed_at":"2016-11-10T17:13:30Z","git_url":"git://github.com/ahoffer/ddf.git","ssh_url":"git@github.com:ahoffer/ddf.git","clone_url":"https://github.com/ahoffer/ddf.git","svn_url":"https://github.com/ahoffer/ddf","homepage":"","size":146153,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"codice:master","ref":"master","sha":"64d6ce2667c74bf743c27641160182954e2ca414","user":{"login":"codice","id":2386734,"avatar_url":"https://avatars.githubusercontent.com/u/2386734?v=3","gravatar_id":"","url":"https://api.github.com/users/codice","html_url":"https://github.com/codice","followers_url":"https://api.github.com/users/codice/followers","following_url":"https://api.github.com/users/codice/following{/other_user}","gists_url":"https://api.github.com/users/codice/gists{/gist_id}","starred_url":"https://api.github.com/users/codice/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/codice/subscriptions","organizations_url":"https://api.github.com/users/codice/orgs","repos_url":"https://api.github.com/users/codice/repos","events_url":"https://api.github.com/users/codice/events{/privacy}","received_events_url":"https://api.github.com/users/codice/received_events","type":"Organization","site_admin":false},"repo":{"id":15173563,"name":"ddf","full_name":"codice/ddf","owner":{"login":"codice","id":2386734,"avatar_url":"https://avatars.githubusercontent.com/u/2386734?v=3","gravatar_id":"","url":"https://api.github.com/users/codice","html_url":"https://github.com/codice","followers_url":"https://api.github.com/users/codice/followers","following_url":"https://api.github.com/users/codice/following{/other_user}","gists_url":"https://api.github.com/users/codice/gists{/gist_id}","starred_url":"https://api.github.com/users/codice/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/codice/subscriptions","organizations_url":"https://api.github.com/users/codice/orgs","repos_url":"https://api.github.com/users/codice/repos","events_url":"https://api.github.com/users/codice/events{/privacy}","received_events_url":"https://api.github.com/users/codice/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/codice/ddf","description":"Distributed Data Framework - an open source, modular integration framework.","fork":false,"url":"https://api.github.com/repos/codice/ddf","forks_url":"https://api.github.com/repos/codice/ddf/forks","keys_url":"https://api.github.com/repos/codice/ddf/keys{/key_id}","collaborators_url":"https://api.github.com/repos/codice/ddf/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/codice/ddf/teams","hooks_url":"https://api.github.com/repos/codice/ddf/hooks","issue_events_url":"https://api.github.com/repos/codice/ddf/issues/events{/number}","events_url":"https://api.github.com/repos/codice/ddf/events","assignees_url":"https://api.github.com/repos/codice/ddf/assignees{/user}","branches_url":"https://api.github.com/repos/codice/ddf/branches{/branch}","tags_url":"https://api.github.com/repos/codice/ddf/tags","blobs_url":"https://api.github.com/repos/codice/ddf/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/codice/ddf/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/codice/ddf/git/refs{/sha}","trees_url":"https://api.github.com/repos/codice/ddf/git/trees{/sha}","statuses_url":"https://api.github.com/repos/codice/ddf/statuses/{sha}","languages_url":"https://api.github.com/repos/codice/ddf/languages","stargazers_url":"https://api.github.com/repos/codice/ddf/stargazers","contributors_url":"https://api.github.com/repos/codice/ddf/contributors","subscribers_url":"https://api.github.com/repos/codice/ddf/subscribers","subscription_url":"https://api.github.com/repos/codice/ddf/subscription","commits_url":"https://api.github.com/repos/codice/ddf/commits{/sha}","git_commits_url":"https://api.github.com/repos/codice/ddf/git/commits{/sha}","comments_url":"https://api.github.com/repos/codice/ddf/comments{/number}","issue_comment_url":"https://api.github.com/repos/codice/ddf/issues/comments{/number}","contents_url":"https://api.github.com/repos/codice/ddf/contents/{+path}","compare_url":"https://api.github.com/repos/codice/ddf/compare/{base}...{head}","merges_url":"https://api.github.com/repos/codice/ddf/merges","archive_url":"https://api.github.com/repos/codice/ddf/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/codice/ddf/downloads","issues_url":"https://api.github.com/repos/codice/ddf/issues{/number}","pulls_url":"https://api.github.com/repos/codice/ddf/pulls{/number}","milestones_url":"https://api.github.com/repos/codice/ddf/milestones{/number}","notifications_url":"https://api.github.com/repos/codice/ddf/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/codice/ddf/labels{/name}","releases_url":"https://api.github.com/repos/codice/ddf/releases{/id}","deployments_url":"https://api.github.com/repos/codice/ddf/deployments","created_at":"2013-12-13T20:38:28Z","updated_at":"2016-11-08T16:53:10Z","pushed_at":"2016-11-10T17:13:30Z","git_url":"git://github.com/codice/ddf.git","ssh_url":"git@github.com:codice/ddf.git","clone_url":"https://github.com/codice/ddf.git","svn_url":"https://github.com/codice/ddf","homepage":"http://ddf.codice.org","size":295412,"stargazers_count":49,"watchers_count":49,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":96,"mirror_url":null,"open_issues_count":31,"forks":96,"open_issues":31,"watchers":49,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/codice/ddf/pulls/1402"},"html":{"href":"https://github.com/codice/ddf/pull/1402"},"issue":{"href":"https://api.github.com/repos/codice/ddf/issues/1402"},"comments":{"href":"https://api.github.com/repos/codice/ddf/issues/1402/comments"},"review_comments":{"href":"https://api.github.com/repos/codice/ddf/pulls/1402/comments"},"review_comment":{"href":"https://api.github.com/repos/codice/ddf/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/codice/ddf/pulls/1402/commits"},"statuses":{"href":"https://api.github.com/repos/codice/ddf/statuses/4c045a98aa8c1a771b390f6c5c2d50083d8e4f18"}}}}
{"actor":{"display_login":"ahoffer"}}