{"action":"created","comment":{"url":"https://api.github.com/repos/diffplug/spotless/pulls/comments/105094023","pull_request_review_id":25956328,"id":105094023,"diff_hunk":"@@ -0,0 +1,303 @@\n+/*\n+ * Copyright 2016 DiffPlug\n+ *\n+ * Licensed under the Apache License, Version 2.0 (the \"License\");\n+ * you may not use this file except in compliance with the License.\n+ * You may obtain a copy of the License at\n+ *\n+ *     http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+ */\n+package com.diffplug.spotless;\n+\n+import java.io.File;\n+import java.io.FileInputStream;\n+import java.io.IOException;\n+import java.io.InputStream;\n+import java.util.Arrays;\n+import java.util.LinkedList;\n+import java.util.List;\n+import java.util.Map;\n+import java.util.Properties;\n+import java.util.Set;\n+import java.util.logging.Logger;\n+import java.util.stream.Collectors;\n+\n+import javax.annotation.Nullable;\n+import javax.xml.parsers.DocumentBuilder;\n+import javax.xml.parsers.DocumentBuilderFactory;\n+import javax.xml.parsers.ParserConfigurationException;\n+\n+import org.w3c.dom.NamedNodeMap;\n+import org.w3c.dom.Node;\n+import org.w3c.dom.NodeList;\n+import org.xml.sax.SAXException;\n+\n+/** Utility manages settings of formatter configured by properties. */\n+public class FormatterProperties {\n+\n+\tprivate static final Logger LOG = Logger.getLogger(FormatterProperties.class.getName());\n+\n+\tprivate final Properties properties;\n+\n+\t/**\n+\t * Per default the property list is empty and the formatters default\n+\t * settings are used.\n+\t */\n+\tpublic FormatterProperties() {\n+\t\tproperties = new Properties();\n+\t}\n+\n+\t/**\n+\t * Import settings from a sequence of files (file import is the given order)\n+\t *\n+\t * @param settingsFiles\n+\t *            Sequence of files\n+\t * @throws IllegalArgumentException\n+\t *            In case the import of a file fails\n+\t */\n+\tpublic void add(final Iterable<File> settingsFiles) throws IllegalArgumentException {\n+\t\tsettingsFiles.forEach(file -> add(file));\n+\t}\n+\n+\t/**\n+\t * Import settings from given file. New settings (with the same ID/key)\n+\t * override existing once.\n+\t *\n+\t * @param settingsFile\n+\t *            File\n+\t * @throws IllegalArgumentException\n+\t *            In case the import of the file fails\n+\t */\n+\tpublic void add(final File settingsFile) throws IllegalArgumentException {\n+\t\tif (!(settingsFile.isFile() || settingsFile.canRead())) {\n+\t\t\tString msg = String.format(\"Settings file '%s' does not exist or can not be read.\", settingsFile);\n+\t\t\tthrow new IllegalArgumentException(msg);\n+\t\t}\n+\t\ttry {\n+\t\t\tProperties newSettings = FileParser.parse(settingsFile);\n+\t\t\tproperties.putAll(newSettings);\n+\t\t} catch (IOException | IllegalArgumentException | NullPointerException exception) {\n+\t\t\tStringBuffer message = new StringBuffer(\n+\t\t\t\t\tString.format(\"Failed to add properties from '%s' to formatter settings.\", settingsFile));\n+\t\t\tString detailedMessage = exception.getMessage();\n+\t\t\tif (null != detailedMessage) {\n+\t\t\t\tmessage.append(String.format(\" %s\", detailedMessage));\n+\t\t\t}","path":"lib/src/main/java/com/diffplug/spotless/FormatterProperties.java","position":91,"original_position":91,"commit_id":"048cdbacd297124b3002bc5d27aea9bec0e2b415","original_commit_id":"048cdbacd297124b3002bc5d27aea9bec0e2b415","user":{"login":"fvgh","id":10271755,"avatar_url":"https://avatars3.githubusercontent.com/u/10271755?v=3","gravatar_id":"","url":"https://api.github.com/users/fvgh","html_url":"https://github.com/fvgh","followers_url":"https://api.github.com/users/fvgh/followers","following_url":"https://api.github.com/users/fvgh/following{/other_user}","gists_url":"https://api.github.com/users/fvgh/gists{/gist_id}","starred_url":"https://api.github.com/users/fvgh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fvgh/subscriptions","organizations_url":"https://api.github.com/users/fvgh/orgs","repos_url":"https://api.github.com/users/fvgh/repos","events_url":"https://api.github.com/users/fvgh/events{/privacy}","received_events_url":"https://api.github.com/users/fvgh/received_events","type":"User","site_admin":false},"body":":thumbsup:","created_at":"2017-03-09T06:23:32Z","updated_at":"2017-03-09T06:23:32Z","html_url":"https://github.com/diffplug/spotless/pull/84#discussion_r105094023","pull_request_url":"https://api.github.com/repos/diffplug/spotless/pulls/84","_links":{"self":{"href":"https://api.github.com/repos/diffplug/spotless/pulls/comments/105094023"},"html":{"href":"https://github.com/diffplug/spotless/pull/84#discussion_r105094023"},"pull_request":{"href":"https://api.github.com/repos/diffplug/spotless/pulls/84"}}},"pull_request":{"url":"https://api.github.com/repos/diffplug/spotless/pulls/84","id":109796750,"html_url":"https://github.com/diffplug/spotless/pull/84","diff_url":"https://github.com/diffplug/spotless/pull/84.diff","patch_url":"https://github.com/diffplug/spotless/pull/84.patch","issue_url":"https://api.github.com/repos/diffplug/spotless/issues/84","number":84,"state":"open","locked":false,"title":"Feature/common property support","user":{"login":"fvgh","id":10271755,"avatar_url":"https://avatars3.githubusercontent.com/u/10271755?v=3","gravatar_id":"","url":"https://api.github.com/users/fvgh","html_url":"https://github.com/fvgh","followers_url":"https://api.github.com/users/fvgh/followers","following_url":"https://api.github.com/users/fvgh/following{/other_user}","gists_url":"https://api.github.com/users/fvgh/gists{/gist_id}","starred_url":"https://api.github.com/users/fvgh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fvgh/subscriptions","organizations_url":"https://api.github.com/users/fvgh/orgs","repos_url":"https://api.github.com/users/fvgh/repos","events_url":"https://api.github.com/users/fvgh/events{/privacy}","received_events_url":"https://api.github.com/users/fvgh/received_events","type":"User","site_admin":false},"body":"Feature provides unified handling of property files, meaning the reading of property files is decoupled from the formatter steps which are configured by properties. \r\nAll property based formatter steps allow configuration by multiple property files. The following formats are currently supported:\r\n\r\n- Java properties (*.xml, *.properties) \r\n- Eclipse profiles (*.xml)\r\n- Eclipse preferences (*.pref)\r\n\r\nThe feature is backward compatible and requires no reconfiguration. Hence the corresponding configuration method (e.g. `propertiesFile`) remains unchanged and allows the configuration of multiple files.\r\nAll corresponding formatter steps also allow to specify no property files at all. In this case default configuration will by applied.\r\n\r\nGradle favors configuration injection over inheritance. Configuration injection is  possible by allowing the reuse of property files for multiple formatter steps, but also by allowing properties to overwrite each other. Hence the `FileSignature` needs to be sensitive to file order.\r\n\r\nThe implemented Gradle interface does not follow the Gradle DSL naming convention which clearly distinguish methods accepting a single or multiple arguments (e.g. `file`/`files`). Be aware that in some cases (e.g. `eclipseFormatFile`), the `spotless` methods as such instantiate and not only configures the formatter step. So the current implementation tries to follow the `spotless` rule to keep the normal configuration (a single property file) simple. It is even not desired to stress in the documentation the point that all property based formatter steps can be equally configured. Instead error messages should guide the user, not only mentioning if the configuration is not accepted, but list the allowed options.\r\n\r\nA use-case of this feature will be the Groovy-Eclipse Formatter, which basically uses the JDT configuration but also provides the configuration of a few Groovy specific parameters. Hence this feature assures that an existing JDT profile can be reused and the Groovy specific parameters can be added in a dedicated configuration file. Furthermore it allows to override some of the JDT configuration for the Java code embedded within Groovy files.","created_at":"2017-03-08T22:15:21Z","updated_at":"2017-03-09T06:23:32Z","closed_at":null,"merged_at":null,"merge_commit_sha":"9e347f20babeb3330be3b14d51f57ce12a8f72ea","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/diffplug/spotless/pulls/84/commits","review_comments_url":"https://api.github.com/repos/diffplug/spotless/pulls/84/comments","review_comment_url":"https://api.github.com/repos/diffplug/spotless/pulls/comments{/number}","comments_url":"https://api.github.com/repos/diffplug/spotless/issues/84/comments","statuses_url":"https://api.github.com/repos/diffplug/spotless/statuses/048cdbacd297124b3002bc5d27aea9bec0e2b415","head":{"label":"fvgh:feature/common_property_support","ref":"feature/common_property_support","sha":"048cdbacd297124b3002bc5d27aea9bec0e2b415","user":{"login":"fvgh","id":10271755,"avatar_url":"https://avatars3.githubusercontent.com/u/10271755?v=3","gravatar_id":"","url":"https://api.github.com/users/fvgh","html_url":"https://github.com/fvgh","followers_url":"https://api.github.com/users/fvgh/followers","following_url":"https://api.github.com/users/fvgh/following{/other_user}","gists_url":"https://api.github.com/users/fvgh/gists{/gist_id}","starred_url":"https://api.github.com/users/fvgh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fvgh/subscriptions","organizations_url":"https://api.github.com/users/fvgh/orgs","repos_url":"https://api.github.com/users/fvgh/repos","events_url":"https://api.github.com/users/fvgh/events{/privacy}","received_events_url":"https://api.github.com/users/fvgh/received_events","type":"User","site_admin":false},"repo":{"id":81749395,"name":"spotless","full_name":"fvgh/spotless","owner":{"login":"fvgh","id":10271755,"avatar_url":"https://avatars3.githubusercontent.com/u/10271755?v=3","gravatar_id":"","url":"https://api.github.com/users/fvgh","html_url":"https://github.com/fvgh","followers_url":"https://api.github.com/users/fvgh/followers","following_url":"https://api.github.com/users/fvgh/following{/other_user}","gists_url":"https://api.github.com/users/fvgh/gists{/gist_id}","starred_url":"https://api.github.com/users/fvgh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fvgh/subscriptions","organizations_url":"https://api.github.com/users/fvgh/orgs","repos_url":"https://api.github.com/users/fvgh/repos","events_url":"https://api.github.com/users/fvgh/events{/privacy}","received_events_url":"https://api.github.com/users/fvgh/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/fvgh/spotless","description":"Keep your code spotless with Gradle","fork":true,"url":"https://api.github.com/repos/fvgh/spotless","forks_url":"https://api.github.com/repos/fvgh/spotless/forks","keys_url":"https://api.github.com/repos/fvgh/spotless/keys{/key_id}","collaborators_url":"https://api.github.com/repos/fvgh/spotless/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/fvgh/spotless/teams","hooks_url":"https://api.github.com/repos/fvgh/spotless/hooks","issue_events_url":"https://api.github.com/repos/fvgh/spotless/issues/events{/number}","events_url":"https://api.github.com/repos/fvgh/spotless/events","assignees_url":"https://api.github.com/repos/fvgh/spotless/assignees{/user}","branches_url":"https://api.github.com/repos/fvgh/spotless/branches{/branch}","tags_url":"https://api.github.com/repos/fvgh/spotless/tags","blobs_url":"https://api.github.com/repos/fvgh/spotless/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/fvgh/spotless/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/fvgh/spotless/git/refs{/sha}","trees_url":"https://api.github.com/repos/fvgh/spotless/git/trees{/sha}","statuses_url":"https://api.github.com/repos/fvgh/spotless/statuses/{sha}","languages_url":"https://api.github.com/repos/fvgh/spotless/languages","stargazers_url":"https://api.github.com/repos/fvgh/spotless/stargazers","contributors_url":"https://api.github.com/repos/fvgh/spotless/contributors","subscribers_url":"https://api.github.com/repos/fvgh/spotless/subscribers","subscription_url":"https://api.github.com/repos/fvgh/spotless/subscription","commits_url":"https://api.github.com/repos/fvgh/spotless/commits{/sha}","git_commits_url":"https://api.github.com/repos/fvgh/spotless/git/commits{/sha}","comments_url":"https://api.github.com/repos/fvgh/spotless/comments{/number}","issue_comment_url":"https://api.github.com/repos/fvgh/spotless/issues/comments{/number}","contents_url":"https://api.github.com/repos/fvgh/spotless/contents/{+path}","compare_url":"https://api.github.com/repos/fvgh/spotless/compare/{base}...{head}","merges_url":"https://api.github.com/repos/fvgh/spotless/merges","archive_url":"https://api.github.com/repos/fvgh/spotless/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/fvgh/spotless/downloads","issues_url":"https://api.github.com/repos/fvgh/spotless/issues{/number}","pulls_url":"https://api.github.com/repos/fvgh/spotless/pulls{/number}","milestones_url":"https://api.github.com/repos/fvgh/spotless/milestones{/number}","notifications_url":"https://api.github.com/repos/fvgh/spotless/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/fvgh/spotless/labels{/name}","releases_url":"https://api.github.com/repos/fvgh/spotless/releases{/id}","deployments_url":"https://api.github.com/repos/fvgh/spotless/deployments","created_at":"2017-02-12T19:04:30Z","updated_at":"2017-02-12T19:04:32Z","pushed_at":"2017-03-08T21:10:06Z","git_url":"git://github.com/fvgh/spotless.git","ssh_url":"git@github.com:fvgh/spotless.git","clone_url":"https://github.com/fvgh/spotless.git","svn_url":"https://github.com/fvgh/spotless","homepage":"","size":2852,"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":"diffplug:master","ref":"master","sha":"f26f305dca4f3b3ed4e2448b172d41719d11063c","user":{"login":"diffplug","id":6572898,"avatar_url":"https://avatars1.githubusercontent.com/u/6572898?v=3","gravatar_id":"","url":"https://api.github.com/users/diffplug","html_url":"https://github.com/diffplug","followers_url":"https://api.github.com/users/diffplug/followers","following_url":"https://api.github.com/users/diffplug/following{/other_user}","gists_url":"https://api.github.com/users/diffplug/gists{/gist_id}","starred_url":"https://api.github.com/users/diffplug/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/diffplug/subscriptions","organizations_url":"https://api.github.com/users/diffplug/orgs","repos_url":"https://api.github.com/users/diffplug/repos","events_url":"https://api.github.com/users/diffplug/events{/privacy}","received_events_url":"https://api.github.com/users/diffplug/received_events","type":"Organization","site_admin":false},"repo":{"id":34685800,"name":"spotless","full_name":"diffplug/spotless","owner":{"login":"diffplug","id":6572898,"avatar_url":"https://avatars1.githubusercontent.com/u/6572898?v=3","gravatar_id":"","url":"https://api.github.com/users/diffplug","html_url":"https://github.com/diffplug","followers_url":"https://api.github.com/users/diffplug/followers","following_url":"https://api.github.com/users/diffplug/following{/other_user}","gists_url":"https://api.github.com/users/diffplug/gists{/gist_id}","starred_url":"https://api.github.com/users/diffplug/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/diffplug/subscriptions","organizations_url":"https://api.github.com/users/diffplug/orgs","repos_url":"https://api.github.com/users/diffplug/repos","events_url":"https://api.github.com/users/diffplug/events{/privacy}","received_events_url":"https://api.github.com/users/diffplug/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/diffplug/spotless","description":"Keep your code spotless with Gradle","fork":false,"url":"https://api.github.com/repos/diffplug/spotless","forks_url":"https://api.github.com/repos/diffplug/spotless/forks","keys_url":"https://api.github.com/repos/diffplug/spotless/keys{/key_id}","collaborators_url":"https://api.github.com/repos/diffplug/spotless/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/diffplug/spotless/teams","hooks_url":"https://api.github.com/repos/diffplug/spotless/hooks","issue_events_url":"https://api.github.com/repos/diffplug/spotless/issues/events{/number}","events_url":"https://api.github.com/repos/diffplug/spotless/events","assignees_url":"https://api.github.com/repos/diffplug/spotless/assignees{/user}","branches_url":"https://api.github.com/repos/diffplug/spotless/branches{/branch}","tags_url":"https://api.github.com/repos/diffplug/spotless/tags","blobs_url":"https://api.github.com/repos/diffplug/spotless/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/diffplug/spotless/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/diffplug/spotless/git/refs{/sha}","trees_url":"https://api.github.com/repos/diffplug/spotless/git/trees{/sha}","statuses_url":"https://api.github.com/repos/diffplug/spotless/statuses/{sha}","languages_url":"https://api.github.com/repos/diffplug/spotless/languages","stargazers_url":"https://api.github.com/repos/diffplug/spotless/stargazers","contributors_url":"https://api.github.com/repos/diffplug/spotless/contributors","subscribers_url":"https://api.github.com/repos/diffplug/spotless/subscribers","subscription_url":"https://api.github.com/repos/diffplug/spotless/subscription","commits_url":"https://api.github.com/repos/diffplug/spotless/commits{/sha}","git_commits_url":"https://api.github.com/repos/diffplug/spotless/git/commits{/sha}","comments_url":"https://api.github.com/repos/diffplug/spotless/comments{/number}","issue_comment_url":"https://api.github.com/repos/diffplug/spotless/issues/comments{/number}","contents_url":"https://api.github.com/repos/diffplug/spotless/contents/{+path}","compare_url":"https://api.github.com/repos/diffplug/spotless/compare/{base}...{head}","merges_url":"https://api.github.com/repos/diffplug/spotless/merges","archive_url":"https://api.github.com/repos/diffplug/spotless/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/diffplug/spotless/downloads","issues_url":"https://api.github.com/repos/diffplug/spotless/issues{/number}","pulls_url":"https://api.github.com/repos/diffplug/spotless/pulls{/number}","milestones_url":"https://api.github.com/repos/diffplug/spotless/milestones{/number}","notifications_url":"https://api.github.com/repos/diffplug/spotless/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/diffplug/spotless/labels{/name}","releases_url":"https://api.github.com/repos/diffplug/spotless/releases{/id}","deployments_url":"https://api.github.com/repos/diffplug/spotless/deployments","created_at":"2015-04-27T19:10:58Z","updated_at":"2017-03-06T06:17:11Z","pushed_at":"2017-03-08T22:15:22Z","git_url":"git://github.com/diffplug/spotless.git","ssh_url":"git@github.com:diffplug/spotless.git","clone_url":"https://github.com/diffplug/spotless.git","svn_url":"https://github.com/diffplug/spotless","homepage":"","size":3060,"stargazers_count":101,"watchers_count":101,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":17,"mirror_url":null,"open_issues_count":10,"forks":17,"open_issues":10,"watchers":101,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/diffplug/spotless/pulls/84"},"html":{"href":"https://github.com/diffplug/spotless/pull/84"},"issue":{"href":"https://api.github.com/repos/diffplug/spotless/issues/84"},"comments":{"href":"https://api.github.com/repos/diffplug/spotless/issues/84/comments"},"review_comments":{"href":"https://api.github.com/repos/diffplug/spotless/pulls/84/comments"},"review_comment":{"href":"https://api.github.com/repos/diffplug/spotless/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/diffplug/spotless/pulls/84/commits"},"statuses":{"href":"https://api.github.com/repos/diffplug/spotless/statuses/048cdbacd297124b3002bc5d27aea9bec0e2b415"}}}}
{"actor":{"display_login":"fvgh"}}