{"action":"created","comment":{"url":"https://api.github.com/repos/kite-sdk/kite/pulls/comments/60118053","id":60118053,"diff_hunk":"@@ -0,0 +1,215 @@\n+\n+/*\n+ * Copyright 2013 Cloudera Inc.\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 org.kitesdk.morphline.stdlib;\n+\n+import java.security.MessageDigest;\n+import java.security.NoSuchAlgorithmException;\n+import java.util.Collection;\n+import java.util.Collections;\n+import java.util.ListIterator;\n+\n+import org.kitesdk.morphline.api.Command;\n+import org.kitesdk.morphline.api.CommandBuilder;\n+import org.kitesdk.morphline.api.MorphlineContext;\n+import org.kitesdk.morphline.api.Record;\n+import org.kitesdk.morphline.base.AbstractCommand;\n+import org.kitesdk.morphline.shaded.org.apache.commons.codec.binary.binary.StringUtils;\n+\n+import com.typesafe.config.Config;\n+\n+/**\n+ * Command that creates a hash digest of a field so-as to deterministically\n+ * provide a unique key\n+ */\n+\n+public class HashDigestBuilder implements CommandBuilder {\n+\n+  @Override\n+  public Collection<String> getNames() {\n+    return Collections.singletonList(\"hashDigest\");\n+  }\n+\n+  @Override\n+  public Command build(Config config, Command parent, Command child,\n+      MorphlineContext context) {\n+    return new HashDigest(this, config, parent, child, context);\n+  }\n+\n+  ///////////////////////////////////////////////////////////////////////////////\n+  // Nested classes:\n+  ///////////////////////////////////////////////////////////////////////////////\n+  private static final class HashDigest extends AbstractCommand {\n+\n+    private final String inputFieldName;\n+    private final String outputFieldName;\n+    private final String hashType;\n+    private final boolean preserveExisting;\n+\n+    private static final String INPUT_FIELD = \"inputField\";\n+    private static final String OUTPUT_FIELD = \"outputField\";\n+    private static final String HASH_TYPE = \"hashType\";\n+    private static final String PRESERVE_EXISTING_NAME = \"preserveExisting\";\n+    private static final boolean PRESERVE_EXISTING_DEFAULT = true;\n+\n+    public HashDigest(CommandBuilder builder, Config config, Command parent,\n+        Command child, MorphlineContext context) {\n+      super(builder, config, parent, child, context);\n+\n+      this.inputFieldName = getConfigs().getString(config, INPUT_FIELD);\n+      this.outputFieldName = getConfigs().getString(config, OUTPUT_FIELD);\n+      this.hashType = getConfigs().getString(config, HASH_TYPE);\n+      this.preserveExisting = getConfigs().getBoolean(config,\n+          PRESERVE_EXISTING_NAME, PRESERVE_EXISTING_DEFAULT);\n+\n+      validateArguments();\n+\n+      if (LOG.isTraceEnabled()) {\n+        LOG.trace(\"inputField: {}\", inputFieldName);\n+        LOG.trace(\"outputField: {}\", outputFieldName);\n+        LOG.trace(\"hashType: {}\", hashType);\n+        LOG.trace(\"preserveExisting: {}\", preserveExisting );\n+      }\n+    }\n+\n+    @Override\n+    protected boolean doProcess(Record record) {\n+\n+      if (!preserveExisting) {\n+        record.removeAll(outputFieldName);\n+      }\n+\n+      ListIterator iter = record.get(inputFieldName).listIterator();\n+      \n+      while (iter.hasNext()) {\n+        record.put(outputFieldName, doHash(iter.next().toString()));\n+      }\n+\n+      // pass record to next command in chain:\n+      return super.doProcess(record);\n+\n+    }\n+\n+    private String doHash(String inputString) {\n+      MessageDigest digest = DigestUtils.getDigest(hashType);\n+\n+      byte[] inputBytes = StringUtils.getBytesUtf8(inputString);\n+\n+      return Hex.encodeHexString(digest.digest(inputBytes));\n+    }\n+\n+    @Override\n+    protected void doNotify(Record notification) {","path":"kite-morphlines/kite-morphlines-core/src/main/java/org/kitesdk/morphline/stdlib/HashDigestBuilder.java","position":115,"original_position":115,"commit_id":"33fdfbdaaa67c5d30e8992adfadcd402b5b0964a","original_commit_id":"33fdfbdaaa67c5d30e8992adfadcd402b5b0964a","user":{"login":"whoschek","id":919871,"avatar_url":"https://avatars.githubusercontent.com/u/919871?v=3","gravatar_id":"","url":"https://api.github.com/users/whoschek","html_url":"https://github.com/whoschek","followers_url":"https://api.github.com/users/whoschek/followers","following_url":"https://api.github.com/users/whoschek/following{/other_user}","gists_url":"https://api.github.com/users/whoschek/gists{/gist_id}","starred_url":"https://api.github.com/users/whoschek/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/whoschek/subscriptions","organizations_url":"https://api.github.com/users/whoschek/orgs","repos_url":"https://api.github.com/users/whoschek/repos","events_url":"https://api.github.com/users/whoschek/events{/privacy}","received_events_url":"https://api.github.com/users/whoschek/received_events","type":"User","site_admin":false},"body":"now doNotify() nomore does anything and the method can be removed, which improves readability.","created_at":"2016-04-18T19:19:39Z","updated_at":"2016-04-18T19:19:39Z","html_url":"https://github.com/kite-sdk/kite/pull/443#discussion_r60118053","pull_request_url":"https://api.github.com/repos/kite-sdk/kite/pulls/443","_links":{"self":{"href":"https://api.github.com/repos/kite-sdk/kite/pulls/comments/60118053"},"html":{"href":"https://github.com/kite-sdk/kite/pull/443#discussion_r60118053"},"pull_request":{"href":"https://api.github.com/repos/kite-sdk/kite/pulls/443"}}},"pull_request":{"url":"https://api.github.com/repos/kite-sdk/kite/pulls/443","id":66653921,"html_url":"https://github.com/kite-sdk/kite/pull/443","diff_url":"https://github.com/kite-sdk/kite/pull/443.diff","patch_url":"https://github.com/kite-sdk/kite/pull/443.patch","issue_url":"https://api.github.com/repos/kite-sdk/kite/issues/443","number":443,"state":"open","locked":false,"title":"Morphlines hashDigest command","user":{"login":"tmgstevens","id":5276180,"avatar_url":"https://avatars.githubusercontent.com/u/5276180?v=3","gravatar_id":"","url":"https://api.github.com/users/tmgstevens","html_url":"https://github.com/tmgstevens","followers_url":"https://api.github.com/users/tmgstevens/followers","following_url":"https://api.github.com/users/tmgstevens/following{/other_user}","gists_url":"https://api.github.com/users/tmgstevens/gists{/gist_id}","starred_url":"https://api.github.com/users/tmgstevens/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tmgstevens/subscriptions","organizations_url":"https://api.github.com/users/tmgstevens/orgs","repos_url":"https://api.github.com/users/tmgstevens/repos","events_url":"https://api.github.com/users/tmgstevens/events{/privacy}","received_events_url":"https://api.github.com/users/tmgstevens/received_events","type":"User","site_admin":false},"body":"Initial commit for hashCommand implementation and tests","created_at":"2016-04-15T14:43:36Z","updated_at":"2016-04-18T19:19:39Z","closed_at":null,"merged_at":null,"merge_commit_sha":"237bb96db3199de9d8463381c93583691d2b47ca","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/kite-sdk/kite/pulls/443/commits","review_comments_url":"https://api.github.com/repos/kite-sdk/kite/pulls/443/comments","review_comment_url":"https://api.github.com/repos/kite-sdk/kite/pulls/comments{/number}","comments_url":"https://api.github.com/repos/kite-sdk/kite/issues/443/comments","statuses_url":"https://api.github.com/repos/kite-sdk/kite/statuses/33fdfbdaaa67c5d30e8992adfadcd402b5b0964a","head":{"label":"tmgstevens:KITE-1122","ref":"KITE-1122","sha":"33fdfbdaaa67c5d30e8992adfadcd402b5b0964a","user":{"login":"tmgstevens","id":5276180,"avatar_url":"https://avatars.githubusercontent.com/u/5276180?v=3","gravatar_id":"","url":"https://api.github.com/users/tmgstevens","html_url":"https://github.com/tmgstevens","followers_url":"https://api.github.com/users/tmgstevens/followers","following_url":"https://api.github.com/users/tmgstevens/following{/other_user}","gists_url":"https://api.github.com/users/tmgstevens/gists{/gist_id}","starred_url":"https://api.github.com/users/tmgstevens/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tmgstevens/subscriptions","organizations_url":"https://api.github.com/users/tmgstevens/orgs","repos_url":"https://api.github.com/users/tmgstevens/repos","events_url":"https://api.github.com/users/tmgstevens/events{/privacy}","received_events_url":"https://api.github.com/users/tmgstevens/received_events","type":"User","site_admin":false},"repo":{"id":55432330,"name":"kite","full_name":"tmgstevens/kite","owner":{"login":"tmgstevens","id":5276180,"avatar_url":"https://avatars.githubusercontent.com/u/5276180?v=3","gravatar_id":"","url":"https://api.github.com/users/tmgstevens","html_url":"https://github.com/tmgstevens","followers_url":"https://api.github.com/users/tmgstevens/followers","following_url":"https://api.github.com/users/tmgstevens/following{/other_user}","gists_url":"https://api.github.com/users/tmgstevens/gists{/gist_id}","starred_url":"https://api.github.com/users/tmgstevens/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tmgstevens/subscriptions","organizations_url":"https://api.github.com/users/tmgstevens/orgs","repos_url":"https://api.github.com/users/tmgstevens/repos","events_url":"https://api.github.com/users/tmgstevens/events{/privacy}","received_events_url":"https://api.github.com/users/tmgstevens/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/tmgstevens/kite","description":"Kite SDK","fork":true,"url":"https://api.github.com/repos/tmgstevens/kite","forks_url":"https://api.github.com/repos/tmgstevens/kite/forks","keys_url":"https://api.github.com/repos/tmgstevens/kite/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tmgstevens/kite/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tmgstevens/kite/teams","hooks_url":"https://api.github.com/repos/tmgstevens/kite/hooks","issue_events_url":"https://api.github.com/repos/tmgstevens/kite/issues/events{/number}","events_url":"https://api.github.com/repos/tmgstevens/kite/events","assignees_url":"https://api.github.com/repos/tmgstevens/kite/assignees{/user}","branches_url":"https://api.github.com/repos/tmgstevens/kite/branches{/branch}","tags_url":"https://api.github.com/repos/tmgstevens/kite/tags","blobs_url":"https://api.github.com/repos/tmgstevens/kite/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tmgstevens/kite/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tmgstevens/kite/git/refs{/sha}","trees_url":"https://api.github.com/repos/tmgstevens/kite/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tmgstevens/kite/statuses/{sha}","languages_url":"https://api.github.com/repos/tmgstevens/kite/languages","stargazers_url":"https://api.github.com/repos/tmgstevens/kite/stargazers","contributors_url":"https://api.github.com/repos/tmgstevens/kite/contributors","subscribers_url":"https://api.github.com/repos/tmgstevens/kite/subscribers","subscription_url":"https://api.github.com/repos/tmgstevens/kite/subscription","commits_url":"https://api.github.com/repos/tmgstevens/kite/commits{/sha}","git_commits_url":"https://api.github.com/repos/tmgstevens/kite/git/commits{/sha}","comments_url":"https://api.github.com/repos/tmgstevens/kite/comments{/number}","issue_comment_url":"https://api.github.com/repos/tmgstevens/kite/issues/comments{/number}","contents_url":"https://api.github.com/repos/tmgstevens/kite/contents/{+path}","compare_url":"https://api.github.com/repos/tmgstevens/kite/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tmgstevens/kite/merges","archive_url":"https://api.github.com/repos/tmgstevens/kite/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tmgstevens/kite/downloads","issues_url":"https://api.github.com/repos/tmgstevens/kite/issues{/number}","pulls_url":"https://api.github.com/repos/tmgstevens/kite/pulls{/number}","milestones_url":"https://api.github.com/repos/tmgstevens/kite/milestones{/number}","notifications_url":"https://api.github.com/repos/tmgstevens/kite/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tmgstevens/kite/labels{/name}","releases_url":"https://api.github.com/repos/tmgstevens/kite/releases{/id}","deployments_url":"https://api.github.com/repos/tmgstevens/kite/deployments","created_at":"2016-04-04T17:48:37Z","updated_at":"2016-04-04T17:48:42Z","pushed_at":"2016-04-15T19:32:29Z","git_url":"git://github.com/tmgstevens/kite.git","ssh_url":"git@github.com:tmgstevens/kite.git","clone_url":"https://github.com/tmgstevens/kite.git","svn_url":"https://github.com/tmgstevens/kite","homepage":"http://kitesdk.org/docs/current/","size":48299,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":true,"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":"kite-sdk:master","ref":"master","sha":"6e2f5100c0ea3c6a3c1a94c113aeeedf8d9deb95","user":{"login":"kite-sdk","id":5732728,"avatar_url":"https://avatars.githubusercontent.com/u/5732728?v=3","gravatar_id":"","url":"https://api.github.com/users/kite-sdk","html_url":"https://github.com/kite-sdk","followers_url":"https://api.github.com/users/kite-sdk/followers","following_url":"https://api.github.com/users/kite-sdk/following{/other_user}","gists_url":"https://api.github.com/users/kite-sdk/gists{/gist_id}","starred_url":"https://api.github.com/users/kite-sdk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kite-sdk/subscriptions","organizations_url":"https://api.github.com/users/kite-sdk/orgs","repos_url":"https://api.github.com/users/kite-sdk/repos","events_url":"https://api.github.com/users/kite-sdk/events{/privacy}","received_events_url":"https://api.github.com/users/kite-sdk/received_events","type":"Organization","site_admin":false},"repo":{"id":14829187,"name":"kite","full_name":"kite-sdk/kite","owner":{"login":"kite-sdk","id":5732728,"avatar_url":"https://avatars.githubusercontent.com/u/5732728?v=3","gravatar_id":"","url":"https://api.github.com/users/kite-sdk","html_url":"https://github.com/kite-sdk","followers_url":"https://api.github.com/users/kite-sdk/followers","following_url":"https://api.github.com/users/kite-sdk/following{/other_user}","gists_url":"https://api.github.com/users/kite-sdk/gists{/gist_id}","starred_url":"https://api.github.com/users/kite-sdk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kite-sdk/subscriptions","organizations_url":"https://api.github.com/users/kite-sdk/orgs","repos_url":"https://api.github.com/users/kite-sdk/repos","events_url":"https://api.github.com/users/kite-sdk/events{/privacy}","received_events_url":"https://api.github.com/users/kite-sdk/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/kite-sdk/kite","description":"Kite SDK","fork":false,"url":"https://api.github.com/repos/kite-sdk/kite","forks_url":"https://api.github.com/repos/kite-sdk/kite/forks","keys_url":"https://api.github.com/repos/kite-sdk/kite/keys{/key_id}","collaborators_url":"https://api.github.com/repos/kite-sdk/kite/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/kite-sdk/kite/teams","hooks_url":"https://api.github.com/repos/kite-sdk/kite/hooks","issue_events_url":"https://api.github.com/repos/kite-sdk/kite/issues/events{/number}","events_url":"https://api.github.com/repos/kite-sdk/kite/events","assignees_url":"https://api.github.com/repos/kite-sdk/kite/assignees{/user}","branches_url":"https://api.github.com/repos/kite-sdk/kite/branches{/branch}","tags_url":"https://api.github.com/repos/kite-sdk/kite/tags","blobs_url":"https://api.github.com/repos/kite-sdk/kite/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/kite-sdk/kite/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/kite-sdk/kite/git/refs{/sha}","trees_url":"https://api.github.com/repos/kite-sdk/kite/git/trees{/sha}","statuses_url":"https://api.github.com/repos/kite-sdk/kite/statuses/{sha}","languages_url":"https://api.github.com/repos/kite-sdk/kite/languages","stargazers_url":"https://api.github.com/repos/kite-sdk/kite/stargazers","contributors_url":"https://api.github.com/repos/kite-sdk/kite/contributors","subscribers_url":"https://api.github.com/repos/kite-sdk/kite/subscribers","subscription_url":"https://api.github.com/repos/kite-sdk/kite/subscription","commits_url":"https://api.github.com/repos/kite-sdk/kite/commits{/sha}","git_commits_url":"https://api.github.com/repos/kite-sdk/kite/git/commits{/sha}","comments_url":"https://api.github.com/repos/kite-sdk/kite/comments{/number}","issue_comment_url":"https://api.github.com/repos/kite-sdk/kite/issues/comments{/number}","contents_url":"https://api.github.com/repos/kite-sdk/kite/contents/{+path}","compare_url":"https://api.github.com/repos/kite-sdk/kite/compare/{base}...{head}","merges_url":"https://api.github.com/repos/kite-sdk/kite/merges","archive_url":"https://api.github.com/repos/kite-sdk/kite/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/kite-sdk/kite/downloads","issues_url":"https://api.github.com/repos/kite-sdk/kite/issues{/number}","pulls_url":"https://api.github.com/repos/kite-sdk/kite/pulls{/number}","milestones_url":"https://api.github.com/repos/kite-sdk/kite/milestones{/number}","notifications_url":"https://api.github.com/repos/kite-sdk/kite/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/kite-sdk/kite/labels{/name}","releases_url":"https://api.github.com/repos/kite-sdk/kite/releases{/id}","deployments_url":"https://api.github.com/repos/kite-sdk/kite/deployments","created_at":"2013-11-30T22:06:02Z","updated_at":"2016-04-18T15:02:01Z","pushed_at":"2016-04-18T19:01:51Z","git_url":"git://github.com/kite-sdk/kite.git","ssh_url":"git@github.com:kite-sdk/kite.git","clone_url":"https://github.com/kite-sdk/kite.git","svn_url":"https://github.com/kite-sdk/kite","homepage":"http://kitesdk.org/docs/current/","size":63183,"stargazers_count":207,"watchers_count":207,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":161,"mirror_url":null,"open_issues_count":28,"forks":161,"open_issues":28,"watchers":207,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/kite-sdk/kite/pulls/443"},"html":{"href":"https://github.com/kite-sdk/kite/pull/443"},"issue":{"href":"https://api.github.com/repos/kite-sdk/kite/issues/443"},"comments":{"href":"https://api.github.com/repos/kite-sdk/kite/issues/443/comments"},"review_comments":{"href":"https://api.github.com/repos/kite-sdk/kite/pulls/443/comments"},"review_comment":{"href":"https://api.github.com/repos/kite-sdk/kite/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/kite-sdk/kite/pulls/443/commits"},"statuses":{"href":"https://api.github.com/repos/kite-sdk/kite/statuses/33fdfbdaaa67c5d30e8992adfadcd402b5b0964a"}}}}